Skip to content

Commit

Permalink
encode and decode gifs
Browse files Browse the repository at this point in the history
  • Loading branch information
Nota30 committed Feb 10, 2024
1 parent 8296841 commit 9ad56ca
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
90 changes: 90 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package gifenc

import (
"fmt"
"image"
"image/draw"
"image/gif"
"image/png"
"io"
"os"
)

func (config Config) Decode(path string) error {
// Open the GIF
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("error while opening file: %s", err)
}

split(file, config.Width, config.Height, config.Output)

return nil
}

// Split the GIF into images
func split(file io.Reader, width int, height int, output Output) (err error) {
defer func() {
if recv := recover(); recv != nil {
err = fmt.Errorf("error while decoding file: %s", recv)
}
}()

gif, err := gif.DecodeAll(file)
if err != nil {
return fmt.Errorf("error while decoding file: %s", err)
}

x, y := getArea(gif)
if width == 0 {
width = x
}
if height == 0 {
height = y
}

dst := image.NewRGBA(image.Rect(0, 0, width, height))
draw.Draw(dst, dst.Bounds(), gif.Image[0], image.Point{}, draw.Src)

for i, img := range gif.Image {
draw.Draw(dst, dst.Bounds(), img, image.Point{}, draw.Over)

file, err := os.Create(fmt.Sprintf("%s%s%d%s", output.Path, output.Name, i, ".png"))
if err != nil {
return fmt.Errorf("error while creating image: %s", err)
}

err = png.Encode(file, dst)
if err != nil {
return fmt.Errorf("error while creating image: %s", err)
}

file.Close()
}

return nil
}

func getArea(gif *gif.GIF) (x, y int) {
var xLow int
var xHigh int
var yLow int
var yHigh int

for _, img := range gif.Image {
if img.Rect.Min.X < xLow {
xLow = img.Rect.Min.X
}
if img.Rect.Min.Y < yLow {
yLow = img.Rect.Min.Y
}
if img.Rect.Max.X > xHigh {
xHigh = img.Rect.Max.X
}
if img.Rect.Max.Y > yHigh {
yHigh = img.Rect.Max.Y
}
}

return xHigh - xLow, yHigh - yLow
}
62 changes: 62 additions & 0 deletions encode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package gifenc

import (
"fmt"
"image"
"image/color/palette"
"image/draw"
"image/gif"
"image/png"
"os"
)

func (config Config) Encode(path string) error {
files, err := os.ReadDir(path)
if err != nil {
return fmt.Errorf("error while opening dir: %s", err)
}

var allFiles []string
for _, file := range files {
fmt.Print(file.Name())
allFiles = append(allFiles, file.Name())
}

animated := gif.GIF{
LoopCount: len(allFiles),
}

for _, file := range allFiles {
reader, err := os.Open(path + file)
if err != nil {
return fmt.Errorf("error while opening file: %s", err)
}
defer reader.Close()

img, err := png.Decode(reader)
if err != nil {
return fmt.Errorf("error while decoding image: %s", err)
}
bounds := img.Bounds()
drawer := draw.FloydSteinberg

paletted := image.NewPaletted(bounds, palette.Plan9)

drawer.Draw(paletted, img.Bounds(), img, image.Point{})
animated.Image = append(animated.Image, paletted)
animated.Delay = append(animated.Delay, config.Delay)
}

file, err := os.Create(config.Output.Name)
if err != nil {
return fmt.Errorf("error while creating file: %s", err)
}
defer file.Close()

encodeErr := gif.EncodeAll(file, &animated)
if encodeErr != nil {
return fmt.Errorf("error while creating file: %s", err)
}

return nil
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/Nota30/gifenc

go 1.21.6
13 changes: 13 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gifenc

type Output struct {
Name string `default:"img"`
Path string
}

type Config struct {
Output Output
Delay int // encode delay
Width int // decode width
Height int // decode height
}

0 comments on commit 9ad56ca

Please sign in to comment.