我有很多 png 图像,想将它们编码为 gif 动画。
这些png图像没有任何黑点,但是gif结果有很多点。
g := new(gif.GIF)
frames := len(images)
g.Image = make([]*image.Paletted, frames)
g.Delay = make([]int, frames)
eg := errgroup.Group{}
var cl color.Palette = palette.Plan9
for k, img := range images {
img := img
k := k
eg.Go(func() error {
Paletted := image.NewPaletted(img.Bounds(), cl)
draw.FloydSteinberg.Draw(Paletted, img.Bounds(), img, image.Point{})
g.Image[k] = Paletted
g.Delay[k] = deply
return nil
})
}
if err := eg.Wait(); err != nil {
return nil, err
}
var buf bytes.Buffer
err := gif.EncodeAll(&buf, g)
我的png信息:
File Type : PNG
File Type Extension : png
MIME Type : image/png
Bit Depth : 8
Color Type : RGB with Alpha
Compression : Deflate/Inflate
Filter : Adaptive
Interlace : Noninterlaced
SRGB Rendering : Perceptual
Exif Byte Order : Big-endian (Motorola, MM)
Color Space : sRGB
使用 palgen.Generate(img, 256):
最佳答案
GIF 使用 256 色调色板,而 PNG 通常是 RGBA,每个颜色 channel (和 alpha)至少有 8 位。在您不完整的示例代码中,您使用预定义的 palette.Plan9
调色板。至少选择原始 PNG 中最主要的颜色显示它是 RGB 颜色 #f08740
。但是 Plan9
调色板中没有匹配的颜色,因此 FloydSteinberg
将不得不使用 Plan9
调色板中“最接近”的颜色进行抖动。这显然效果不佳。
您需要使用经过调整的调色板来完全避免抖动或至少将其最小化。由于您给出了一个非最小和不完整的示例,我不得不自己滚动一个最小的示例,该示例根据给定的唯一 PNG 源为 GIF 创建自定义调色板(请上传单独的图像下次不要把所有东西都放在一张图片里,这样真的很不方便。)
快速谷歌搜索显示 Go 模块 github.com/xyproto/palgen
确实根据输入图像和指定数量的颜色创建自定义 color.Palette
;这个模块似乎得到了积极的维护,我立即成功地使用了它:
img, _, err := image.Decode(f)
pal, err := palgen.Generate(img, 256)
为我生成合适的 GIF (gif.gif
) 而无需抖动的完整示例,给定 source.png
中的源 PNG:
package main
import (
"image"
"image/draw"
"image/gif"
_ "image/png"
"os"
"github.com/xyproto/palgen"
)
func main() {
g := new(gif.GIF)
g.Image = make([]*image.Paletted, 1)
g.Delay = make([]int, 1)
f, err := os.Open("source.png")
if err != nil {
panic(err)
}
defer f.Close()
img, _, err := image.Decode(f)
pal, err := palgen.Generate(img, 256)
Paletted := image.NewPaletted(img.Bounds(), pal)
draw.FloydSteinberg.Draw(Paletted, img.Bounds(), img, image.Point{})
g.Image[0] = Paletted
g.Delay[0] = 100
out, err := os.Create("gif.gif")
if err != nil {
panic(err)
}
defer out.Close()
err = gif.EncodeAll(out, g)
if err != nil {
panic(err)
}
}
源图source.png
:
最终 GIF gif.gif
:
关于image - Golang image/gif EncodeAll有很多黑点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73987493/