Problems drawing on frames of an animated gif

511 views
Skip to first unread message

kale...@googlemail.com

unread,
Jan 21, 2017, 10:54:46 AM1/21/17
to golang-nuts
Hi,

I'm trying to draw some text on an animated gif and I'm having a few problems.

I have a source gif (attached as fire.gif) which I can decode fine and pass the frames to the drawing lib.
The problem occurs when I'm trying to replace the original frames with ones I've modified. I always seem to get the same result (see attached out.gif).
The text seems to be drawn fine but the other frames which contain the animation seem to be missing.

Here's the code:

package main

import (
 
"image"
 
"image/draw"
 
"image/gif"
 
"log"
 
"os"


 
"github.com/fogleman/gg"
)

func main
() {

   
in, err := os.Open("/home/gary/Desktop/fire.gif")
   
if err != nil {
        log
.Fatalln(err)
   
}
    defer
in.Close()

    decoded
, err := gif.DecodeAll(in)
   
if err != nil {
        log
.Fatalln(err)
   
}

   
for x := 0; x < len(decoded.Image); x++ {
        frame
:= decoded.Image[x]
        ctx
:= gg.NewContextForImage(frame)
        ctx
.SetHexColor("#FFF")
        ctx
.DrawStringWrapped("Lorem ipsum dolor sit amet", 10, 10, 0, 0, 500, 1.4, gg.AlignLeft)

        palImg
:= image.NewPaletted(frame.Bounds(), frame.Palette)
        draw
.FloydSteinberg.Draw(palImg, frame.Bounds(), ctx.Image(), image.ZP)

        decoded
.Image[x] = palImg
   
}

   
out, err := os.Create("/home/gary/Desktop/out.gif")
   
if err != nil {
        log
.Fatalln(err)
   
}
    defer
out.Close()

    err
= gif.EncodeAll(out, decoded)
   
if err != nil {
        log
.Fatalln(err)
   
}
}


Any ideas how to compile the changed frame to give me the correct output?
fire.gif
out.gif

andrey mirtchovski

unread,
Jan 21, 2017, 11:57:15 AM1/21/17
to kale...@googlemail.com, golang-nuts
I see only a single frame in your source file. I ran your program on
another gif and got the expected result:

http://i.imgur.com/HOnlU1q.gif
http://i.imgur.com/GnSUHQ1.gif
> --
> 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.

kale...@googlemail.com

unread,
Jan 21, 2017, 6:28:28 PM1/21/17
to golang-nuts, kale...@googlemail.com
I think the upload has ruined the frames. I'll try another gif tomorrow.

andrey mirtchovski

unread,
Jan 21, 2017, 9:47:13 PM1/21/17
to kale...@googlemail.com, golang-nuts
just as a warning, you may get unexpected results if you're working
with "compressed" gifs. i.e., file where the next frame is only the
difference between this one and the previous one. there are also
interlaced gifs, etc. i suggest you use "gifsicle" (available on
linux) to expand the gif first and then try with that if the original
doesn't work as well as you'd hoped. not sure if go's gif package
supports all optimizations.

https://www.lcdf.org/gifsicle/

On Sat, Jan 21, 2017 at 4:28 PM, kalekold via golang-nuts

kale...@googlemail.com

unread,
Jan 22, 2017, 2:03:46 PM1/22/17
to golang-nuts, kale...@googlemail.com
Hmm.. the source gif I'm using must be compressed. Doesn't Go handle compressed gifs in the same way? When you say 'I may get unexpected results' is that because the current gif package doesn't support compression?

Nigel Tao

unread,
Feb 4, 2017, 8:25:21 PM2/4/17
to kale...@googlemail.com, golang-nuts
On Mon, Jan 23, 2017 at 6:03 AM, kalekold via golang-nuts
<golan...@googlegroups.com> wrote:
> Hmm.. the source gif I'm using must be compressed. Doesn't Go handle
> compressed gifs in the same way? When you say 'I may get unexpected results'
> is that because the current gif package doesn't support compression?

A GIF image is a sequence of frames. Some frames are complete
pictures, some frames contain only those pixels that changed from the
previous frame. (If you're familiar with video formats like MPEG, you
might recognize these concepts as I-frames and P-frames).

The second type of frame, delta frames or P-frames, often encode much
smaller since they're often mostly transparent, and so are sometimes
called "compressed" GIFs. Both sorts of frames also use LZW
compression, but that's probably not what we're discussing here.

The Go image/gif package supports complete and delta frames. As per
the GIF spec (http://www.w3.org/Graphics/GIF/spec-gif89a.txt), the
package calls this the disposal method. Support means that decoding a
GIF image will give you the per-frame disposal methods, and passing a
slice of per-frame disposal methods to Encode will produce a well
formatted GIF.

However, the package does not apply the deltas to previous frames for
you. If you want to load an animated GIFs and replace some frames, it
is up to the user of the image/gif package (i.e. you) to apply the
deltas when decoding, or re-calculate the deltas when encoding. Or you
can set decoded.Disposal[i] to gif.DisposalNone to change the frame
from a P-frame to an I-frame, but that might lead to a larger GIF
file.

gary.wi...@victoriaplumb.com

unread,
Feb 6, 2017, 12:18:40 PM2/6/17
to golang-nuts, kale...@googlemail.com
Thanks!
Reply all
Reply to author
Forward
0 new messages