【问题标题】:Golang image/gif EncodeAll have many black dotsGolang image/gif EncodeAll 有很多黑点
【发布时间】:2022-10-25 14:15:52
【问题描述】:

我有许多 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:

有数:

我的PNG信息:

文件类型:PNG
文件类型扩展名: png
MIME 类型:图像/png
位深:8
颜色类型:带 Alpha 的 RGB
压缩:放气/充气
过滤器:自适应
隔行扫描:非隔行扫描
SRGB 渲染:感知
Exif 字节顺序:大端(摩托罗拉,MM)
色彩空间:sRGB

带黑点的 gif:

使用 palgen.Generate(img, 256):

【问题讨论】:

    标签: image go gif


    【解决方案1】:

    GIF 使用 256 色调色板,而 PNG 通常是 RGBA,每个颜色通道(和 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)
    

    给我source.png中的源PNG,为我生成一个合适的GIF(gif.gif)而没有抖动的完整示例:

    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:

    【讨论】:

    • 我用你的方法又试了一次,但是GIF边缘还是有一些黑点
    • 我将结果添加到问题描述中
    • 您仍然不提供原始的png。您没有提供您使用的完整工作代码。你展示了另一个明显组合的图像,你没有展示它是如何创建的代码。正如我通过剪切顶部图像使用您的组合 png 演示的那样,它对于 Go 1.19 和单个示例图像足够好。当您没有提供足够的信息时,您希望人们如何帮助您?
    • 对不起,我只是认为这是一个不依赖于我的原始绘图的一般问题。现在我附上我的原始 png。再次帮助我,谢谢
    【解决方案2】:

    利用
    draw.Draw(Paletted,img.Bounds(),img,image.ZP, draw.Src)

    代替
    draw.FloydSteinberg.Draw(Paletted, img.Bounds(), img, image.Point{})

    【讨论】:

      猜你喜欢
      • 2017-07-01
      • 2019-03-23
      • 2012-12-12
      • 2015-01-23
      • 2018-01-12
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多