mirror of
https://github.com/IllusionMan1212/gif-cropper-wasm.git
synced 2026-10-24 02:12:39 +00:00
fix: finish the cropper
This commit is contained in:
@@ -7,66 +7,73 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/color/palette"
|
|
||||||
"image/draw"
|
|
||||||
"image/gif"
|
"image/gif"
|
||||||
"image/png"
|
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
if intersection.Empty() {
|
||||||
|
return &image.Paletted{
|
||||||
|
Palette: p.Palette,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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{} {
|
func encodeGif(this js.Value, args []js.Value) interface{} {
|
||||||
inImages := args[0]
|
rawGifBytes := args[0]
|
||||||
delays := args[1]
|
x := args[1].Int()
|
||||||
disposals := args[2]
|
y := args[2].Int()
|
||||||
|
w := args[3].Int()
|
||||||
|
h := args[4].Int()
|
||||||
|
|
||||||
outImages := make([]*image.Paletted, 0)
|
gifBytes := make([]byte, rawGifBytes.Length())
|
||||||
delay := make([]int, 0)
|
js.CopyBytesToGo(gifBytes, rawGifBytes)
|
||||||
disposal := make([]byte, 0)
|
gifIn, err := gif.DecodeAll(bytes.NewReader(gifBytes))
|
||||||
|
|
||||||
// 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 {
|
if err != nil {
|
||||||
log.Fatal(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b := img.Bounds()
|
for i := 0; i < len(gifIn.Image); i++ {
|
||||||
pimg := image.NewPaletted(b, myPalette)
|
frame := gifIn.Image[i]
|
||||||
opts.Drawer.Draw(pimg, b, img, image.ZP)
|
selection := image.Rect(x, y, x+w, y+h)
|
||||||
|
gifIn.Image[i] = Crop(frame, selection)
|
||||||
outImages = append(outImages, pimg)
|
|
||||||
delay = append(delay, delays.Index(i).Int())
|
|
||||||
disposal = append(disposal, byte(disposals.Index(i).Int()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outGif := &gif.GIF{
|
outGif := gif.GIF{
|
||||||
Image: outImages,
|
Image: gifIn.Image,
|
||||||
Delay: delay,
|
Delay: gifIn.Delay,
|
||||||
LoopCount: 0,
|
LoopCount: gifIn.LoopCount,
|
||||||
Disposal: disposal,
|
Disposal: gifIn.Disposal,
|
||||||
BackgroundIndex: 0,
|
BackgroundIndex: gifIn.BackgroundIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
outBytes := new(bytes.Buffer)
|
outBytes := new(bytes.Buffer)
|
||||||
err := gif.EncodeAll(outBytes, outGif)
|
err = gif.EncodeAll(outBytes, &outGif)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return js.CopyBytesToJS(args[3], outBytes.Bytes())
|
return js.CopyBytesToJS(args[5], outBytes.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
-82
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user