Correct way to turn an image.Image into a *image.Paletted, for making gifs

1,526 views
Skip to first unread message

Brian Picciano

unread,
Dec 4, 2015, 2:33:58 AM12/4/15
to golang-nuts
Hi there! I'm currently attempting to make a gif out of a series of image.Image instances (each the same dimensions). I see that to build the gif.GIF struct I need to somehow turn my image.Images into *image.Paletted, but after browsing the various image apis I still don't see an obvious way to do that. Currently I'm using gif.Encode to encode a single frame into a buffer, then gif.DecodeAll to decode it back out into its own gif.GIF, and then append that to my actual gif. This is super ugly and feels very wrong, and it also seems to break transparency. Any help would be appreciated, thanks!

Caleb Spare

unread,
Dec 4, 2015, 3:19:35 AM12/4/15
to Brian Picciano, golang-nuts
I'm not sure about the transparency thing.

In order to transform your image.Images into *image.Paletted, you can
do what the gif encoder does. The code is very short:

https://github.com/golang/go/blob/master/src/image/gif/writer.go#L358-L366

(Basically, check if it's already an *image.Palleted; if not, use a
quantizer to re-render it as a paletted image.)

-Caleb
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Brian Picciano

unread,
Dec 4, 2015, 3:35:56 AM12/4/15
to golang-nuts, mediocr...@gmail.com
Ah, good call. So I've replaced the encode/decode nonsense with that and things still work. Except transparency still isn't working :(

Here is the function in question, the ctx simply holds onto a bunch of the values, like the final gif.GIF being created and such:

func (c *ctx) addFrame(img image.Image) error {
        opts
:= gif.Options{
               
NumColors: 256,
               
Drawer:    draw.FloydSteinberg,
       
}
        b
:= img.Bounds()
 
       
// More or less taken from the image/gif package
        pimg
:= image.NewPaletted(b, palette.Plan9[:opts.NumColors])
       
if opts.Quantizer != nil {
                pimg
.Palette = opts.Quantizer.Quantize(make(color.Palette, 0, opts.NumColors), img)
       
}
        opts
.Drawer.Draw(pimg, b, img, image.ZP)
 
        spf
:= 1 / float64(c.fps)
 

        c
.g.Image = append(c.g.Image, pimg)
        c
.g.Delay = append(c.g.Delay, int(spf*100))
       
return nil
}


Nigel Tao

unread,
Dec 4, 2015, 4:31:33 AM12/4/15
to Brian Picciano, golang-nuts
On Fri, Dec 4, 2015 at 7:35 PM, Brian Picciano <mediocr...@gmail.com> wrote:
> Except transparency still isn't working :(
>
> pimg := image.NewPaletted(b, palette.Plan9[:opts.NumColors])

None of the colors in the Plan 9 palette are transparent. If you want
pimg, your resultant image, to have transparent pixels, use a
different palette.

shubhams...@gmail.com

unread,
Jun 20, 2019, 12:56:33 PM6/20/19
to golang-nuts
Just use 
myPalette := append(palette.WebSafe, image.Transparent)

You can't add transparent color to plan9 palette since it's already full. Better to use WebSafe!
Reply all
Reply to author
Forward
0 new messages