HOME

Creating transparent animated GIFs with Go and gg (golang)

anmited gif created with Go and gg

The image/gif package of Go's standard library makes it quite easy to create animated GIF images. All you need to do is create your individual frames as an array of *image.Paletted and use gif.EncodeAll() to encode them into an animated GIF.

Once you get to the point where you need to do something more advanced than importing existing images or drawing basic shapes, you might find yourself using additional packages like the awesome gg which I highly recommend.

Here things start to get interesting because gif.EncodeAll() expects paletted images as its input, whereas gg will create RGBA images by default.
The obvious way to solve this problem would be to create your frames with gg, export them as PNG images and use gif.Decode() to read your newly created PNG files and decode them to paletted GIF images that you can re-encode into an animated GIF.
While this works just fine, it is not really a good solution since there is a lot of encoding and decoding overhead and it would lead to the creation of lots of PNG images on disk that we are not really interested in.

What we are going to do instead is this: we are going create our frames with gg as before, create a new pletted image in memory, and draw the RGBA image we created with gg onto the new image using image/draw effectively converting it from RGBA to paletted:

	dc.DrawCircle(x, y, 20)
	dc.SetRGBA(0, 0, 0, 1)
	dc.Fill()

	img := dc.Image()
	bounds := img.Bounds()

	dst := image.NewPaletted(bounds, palette.WebSafe)
	draw.Draw(dst, bounds, img, bounds.Min, draw.Src)

Now we can just append our new paletted image to our array of individual frames and encode them into an animated GIF:

	images = append(images, dst)
	delays = append(delays, 10)

	f, _ := os.OpenFile("rgb.gif", os.O_WRONLY|os.O_CREATE, 0600)
	defer f.Close()
	gif.EncodeAll(f, &gif.GIF{
		Image: images,
		Delay: delays,
	})

We're not quite done yet, since we want our final animated GIF to have a transparent background.
When converting from RGBA using a default palette like palette.WebSafe we lose the alpha channel (i.e. transparency) of our gg image.

To solve this problem we create our own palette that includes a transparent color:

	var myPalette color.Palette = color.Palette{
		image.Transparent,
		image.Black,
		image.White,
		color.RGBA{0xEE, 0xEE, 0xEE, 255},
		color.RGBA{0xCC, 0xCC, 0xCC, 255},
		color.RGBA{0x99, 0x99, 0x99, 255},
		color.RGBA{0x66, 0x66, 0x66, 255},
		color.RGBA{0x33, 0x33, 0x33, 255},
	}

And use this palette when creating our paletted image:

	dst := image.NewPaletted(bounds, palette.WebSafe)

Now we have all the pieces in place to create gorgeous animated GIF images with transparency effects.

A full example that was used to create the animation at the top of this page can be found here:
animation.go