image - Golang image/gif EncodeAll有很多黑点

标签 image go gif

我有很多 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: origin png

与数: enter image description here

我的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

带黑点的gif: gif with black dots

使用 palgen.Generate(img, 256):

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:

source.png

最终 GIF gif.gif:

gif.gif

关于image - Golang image/gif EncodeAll有很多黑点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73987493/

相关文章:

file - 无法覆盖文件内容

python - 在 matplotlib 中绘制最后 100 个点

haskell - 如何使用任一字符串 (IO())

html - 如何在 HTML img 标签中屏蔽图像?

linux - 如何创建和部署自定义的嵌入式 Linux 镜像

c# - USB显微镜的自动对焦算法

go - 在 Golang 中使用 virt-install 安装虚拟机

图像色彩饱和度

arrays - Unmarshal 只给我嵌套在 JSON 响应中的数组的第一个元素

javascript - 在 p5js 中将 Canvas 导出为 GIF/PNG