commit f6b1c99058e40a8ac9d1604a81b5a8514b7752c7 Author: IllusionMan1212 Date: Wed Mar 1 23:45:10 2023 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f6f4e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +wasm_exec.js +gif-encoder.wasm diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2cbc5b3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "go.buildTags": "js,wasm", + + // other + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features", + }, + "git.branchPrefix": "feat/", + "git.branchProtection": [ "master" ], + "git.branchProtectionPrompt": "alwaysPrompt", +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d3883b3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gif-encoder + +go 1.19 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/main.go b/main.go new file mode 100644 index 0000000..28e2e02 --- /dev/null +++ b/main.go @@ -0,0 +1,76 @@ +//go:build js && wasm +// +build js,wasm + +package main + +import ( + "bytes" + "fmt" + "image" + "image/color/palette" + "image/draw" + "image/gif" + "image/png" + "log" + "syscall/js" +) + +func encodeGif(this js.Value, args []js.Value) interface{} { + inImages := args[0] + delays := args[1] + disposals := args[2] + + outImages := make([]*image.Paletted, 0) + delay := make([]int, 0) + disposal := make([]byte, 0) + + // Plan9 palette doesn't include transparent colors + // so we use WebSafe and add transparent color + myPalette := append(palette.WebSafe, image.Transparent) + opts := gif.Options{ + NumColors: 256, + Drawer: draw.FloydSteinberg, + } + + fmt.Println(inImages.Length()) + for i := 0; i < inImages.Length(); i++ { + imgBytes := make([]byte, inImages.Index(i).Length()) + js.CopyBytesToGo(imgBytes, inImages.Index(i)) + + reader := bytes.NewReader(imgBytes) + img, err := png.Decode(reader) + if err != nil { + log.Fatal(err) + } + + b := img.Bounds() + pimg := image.NewPaletted(b, myPalette) + opts.Drawer.Draw(pimg, b, img, image.ZP) + + outImages = append(outImages, pimg) + delay = append(delay, delays.Index(i).Int()) + disposal = append(disposal, byte(disposals.Index(i).Int())) + } + + outGif := &gif.GIF{ + Image: outImages, + Delay: delay, + LoopCount: 0, + Disposal: disposal, + BackgroundIndex: 0, + } + + outBytes := new(bytes.Buffer) + err := gif.EncodeAll(outBytes, outGif) + if err != nil { + log.Fatal(err) + } + + return js.CopyBytesToJS(args[3], outBytes.Bytes()) +} + +func main() { + done := make(chan struct{}, 0) + js.Global().Set("encodeGif", js.FuncOf(encodeGif)) + <-done +} diff --git a/new/new.go b/new/new.go new file mode 100644 index 0000000..af047ea --- /dev/null +++ b/new/new.go @@ -0,0 +1,82 @@ +package main + +import ( + "image" + "image/color/palette" + "image/draw" + "image/gif" + "image/png" + "io/ioutil" + "log" + "os" + "path/filepath" +) + +func main() { + if len(os.Args) < 2 { + log.Fatal("No directory or file provided.") + } + + path := os.Args[1] + + if path == "" { + log.Fatal("No directory or file provided.") + } + + files, err := ioutil.ReadDir(path) + if err != nil { + log.Fatal(err) + } + + images := make([]*image.Paletted, 0) + delay := make([]int, 0) + disposal := make([]byte, 0) + + for _, fileInfo := range files { + if fileInfo.IsDir() { + continue + } + + file, err := os.OpenFile(filepath.Join(path, fileInfo.Name()), os.O_RDWR, os.ModeExclusive) + if err != nil { + log.Fatal("Failed to open file") + } + defer file.Close() + + img, err := png.Decode(file) + if err != nil { + log.Fatal(err) + } + + opts := gif.Options{ + NumColors: 256, + Drawer: draw.FloydSteinberg, + } + b := img.Bounds() + myPalette := append(palette.WebSafe, image.Transparent) + pimg := image.NewPaletted(b, myPalette) + opts.Drawer.Draw(pimg, b, img, image.ZP) + + images = append(images, pimg) + delay = append(delay, 10) + disposal = append(disposal, 2) + } + + outGif := &gif.GIF{ + Image: images, + Delay: delay, + LoopCount: 0, + Disposal: disposal, + BackgroundIndex: 40, + } + + out, err := os.Create("out.gif") + if err != nil { + log.Fatal(err) + } + defer out.Close() + err = gif.EncodeAll(out, outGif) + if err != nil { + log.Fatal(err) + } +}