From a756c1e6e20004a669f1ad8756c7f1bd21e2f896 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Fri, 3 Mar 2023 05:57:35 +0200 Subject: [PATCH] fix: finish the cropper --- main.go | 95 +++++++++++++++++++++++++++++------------------------- new/new.go | 82 ---------------------------------------------- 2 files changed, 51 insertions(+), 126 deletions(-) delete mode 100644 new/new.go diff --git a/main.go b/main.go index 28e2e02..04efa19 100644 --- a/main.go +++ b/main.go @@ -7,66 +7,73 @@ import ( "bytes" "fmt" "image" - "image/color/palette" - "image/draw" "image/gif" - "image/png" "log" + "math" "syscall/js" ) -func encodeGif(this js.Value, args []js.Value) interface{} { - inImages := args[0] - delays := args[1] - disposals := args[2] +// taken from stdlib's image/image.go (SubImage) and modified to account for +// gif frame positions +func Crop(p *image.Paletted, selection image.Rectangle) *image.Paletted { + intersection := p.Rect.Intersect(selection) - 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) + if intersection.Empty() { + return &image.Paletted{ + Palette: p.Palette, } - - 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, + i := p.PixOffset(intersection.Min.X, intersection.Min.Y) + xMin := int(math.Round(float64(intersection.Min.X) - (float64(selection.Min.X)))) + yMin := int(math.Round(float64(intersection.Min.Y) - (float64(selection.Min.Y)))) + xMax := xMin + (intersection.Dx()) + yMax := yMin + (intersection.Dy()) + bounds := image.Rect(xMin, yMin, xMax, yMax) + + return &image.Paletted{ + Pix: p.Pix[i:], + Stride: p.Stride, + Rect: bounds, + Palette: p.Palette, + } +} + +func encodeGif(this js.Value, args []js.Value) interface{} { + rawGifBytes := args[0] + x := args[1].Int() + y := args[2].Int() + w := args[3].Int() + h := args[4].Int() + + gifBytes := make([]byte, rawGifBytes.Length()) + js.CopyBytesToGo(gifBytes, rawGifBytes) + gifIn, err := gif.DecodeAll(bytes.NewReader(gifBytes)) + if err != nil { + fmt.Println(err) + } + + for i := 0; i < len(gifIn.Image); i++ { + frame := gifIn.Image[i] + selection := image.Rect(x, y, x+w, y+h) + gifIn.Image[i] = Crop(frame, selection) + } + + outGif := gif.GIF{ + Image: gifIn.Image, + Delay: gifIn.Delay, + LoopCount: gifIn.LoopCount, + Disposal: gifIn.Disposal, + BackgroundIndex: gifIn.BackgroundIndex, } outBytes := new(bytes.Buffer) - err := gif.EncodeAll(outBytes, outGif) + err = gif.EncodeAll(outBytes, &outGif) if err != nil { log.Fatal(err) } - return js.CopyBytesToJS(args[3], outBytes.Bytes()) + return js.CopyBytesToJS(args[5], outBytes.Bytes()) } func main() { diff --git a/new/new.go b/new/new.go deleted file mode 100644 index af047ea..0000000 --- a/new/new.go +++ /dev/null @@ -1,82 +0,0 @@ -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) - } -}