convert png boards to gif
This commit is contained in:
parent
22f03b8f48
commit
588398a4df
7 changed files with 98 additions and 0 deletions
1
go.mod
generated
1
go.mod
generated
|
|
@ -9,6 +9,7 @@ require (
|
||||||
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7
|
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7
|
||||||
github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85
|
github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85
|
||||||
github.com/dsoprea/go-png-image-structure/v2 v2.0.0-20210512210324-29b889a6093d
|
github.com/dsoprea/go-png-image-structure/v2 v2.0.0-20210512210324-29b889a6093d
|
||||||
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||||
github.com/jung-kurt/gofpdf v1.16.2
|
github.com/jung-kurt/gofpdf v1.16.2
|
||||||
|
|
|
||||||
2
go.sum
generated
2
go.sum
generated
|
|
@ -60,6 +60,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
||||||
|
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
|
|
||||||
BIN
lib/xgif/test_input1.png
Normal file
BIN
lib/xgif/test_input1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 271 KiB |
BIN
lib/xgif/test_input2.png
Normal file
BIN
lib/xgif/test_input2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 340 KiB |
BIN
lib/xgif/test_output.gif
Normal file
BIN
lib/xgif/test_output.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
56
lib/xgif/xgif.go
Normal file
56
lib/xgif/xgif.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package xgif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/gif"
|
||||||
|
"image/png"
|
||||||
|
|
||||||
|
"github.com/ericpauley/go-quantize/quantize"
|
||||||
|
)
|
||||||
|
|
||||||
|
const INFINITE_LOOP = 0
|
||||||
|
|
||||||
|
func AnimatePNGs(pngs [][]byte, gifWidth, gifHeight int, animIntervalMs int) ([]byte, error) {
|
||||||
|
interval := animIntervalMs / 10 // gif animation interval is in 100ths of a second
|
||||||
|
anim := &gif.GIF{
|
||||||
|
LoopCount: INFINITE_LOOP,
|
||||||
|
Config: image.Config{
|
||||||
|
Width: gifWidth,
|
||||||
|
Height: gifHeight,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pngBytes := range pngs {
|
||||||
|
pngImage, err := png.Decode(bytes.NewBuffer(pngBytes))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
err = gif.Encode(buf, pngImage, &gif.Options{
|
||||||
|
NumColors: 256, // GIFs can have up to 256 colors
|
||||||
|
Quantizer: quantize.MedianCutQuantizer{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gifImg, err := gif.Decode(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
palettedImg, ok := gifImg.(*image.Paletted)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("decoded git image could not be cast as *image.Paletted")
|
||||||
|
}
|
||||||
|
anim.Image = append(anim.Image, palettedImg)
|
||||||
|
anim.Delay = append(anim.Delay, interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
err := gif.EncodeAll(buf, anim)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
39
lib/xgif/xgif_test.go
Normal file
39
lib/xgif/xgif_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
package xgif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"image/png"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"oss.terrastruct.com/util-go/go2"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed test_input1.png
|
||||||
|
var test_input1 []byte
|
||||||
|
|
||||||
|
//go:embed test_input2.png
|
||||||
|
var test_input2 []byte
|
||||||
|
|
||||||
|
//go:embed test_output.gif
|
||||||
|
var test_output []byte
|
||||||
|
|
||||||
|
func TestPngToGif(t *testing.T) {
|
||||||
|
board1, err := png.Decode(bytes.NewBuffer(test_input1))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
gifWidth := board1.Bounds().Dx()
|
||||||
|
gifHeight := board1.Bounds().Dy()
|
||||||
|
|
||||||
|
board2, err := png.Decode(bytes.NewBuffer(test_input2))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
gifWidth = go2.Max(board2.Bounds().Dx(), gifWidth)
|
||||||
|
gifHeight = go2.Max(board2.Bounds().Dy(), gifHeight)
|
||||||
|
|
||||||
|
boards := [][]byte{test_input1, test_input2}
|
||||||
|
interval := 1_000
|
||||||
|
gifBytes, err := AnimatePNGs(boards, gifWidth, gifHeight, interval)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, test_output, gifBytes)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue