[Cuis-dev] Animated GIFs

Eric Gade eric.gade at gmail.com
Mon Nov 22 16:02:20 PST 2021

Hi all,

A couple of years ago I refactored Pharo's GIF parsing to be able to deal
with animated GIFs (among other things). I've made good headway on a Cuis
port recently and wanted to share / get feedback.

You can find the working copy here:

For a sort of detailed description of the work, here is the original Pharo
PR: https://github.com/pharo-project/pharo/pull/1666. Note that the
examples there are not all relevant to Cuis, since some of the
ImageReadWriter messages are different in Cuis.

You'll notice that there are two animated image morph classes in this
package: AnimatedImageMorph and AnimatedImageCompMorph. The crux is this:
GIF image frames are only partial bitmap data. Each frame describes how it
should be blended (or not) with the next frame, and at what offset. In my
original Pharo implementation, the class AnimatedImageMorph does this
compositing on the fly each time it proceeds to the next frame. That allows
one to write back the frames as a GIF file that will be (almost) identical
to the original. However, it really makes things complicated (see below)
and bugs out on some GIFs.

So for this port, I decided to rename that version of the class to
AnimatedImageCompMorph and instead present a much simpler class called
AnimatedImageMorph which simply takes a sequence of Forms and updates them
according to the stepTime. This works much better. But in order for it to
be possible, I had to also create the GIFFrameCompiler utility class that
can composite the GIF frame data into full, individual Forms for each
frame. You can see this in action in the class side helper methods of

The complication with "live-compositing" the GIF frames in
AnimatedImageCompMorph stems from the fact that one cannot -- at least I
couldn't find a way -- make a canvas on an existing Form and then "paint
over" some rectangle with transparent pixels, and have those pixels become
transparent. Instead what happens is nothing -- the original pixels retain
their value. In some ways that's what one would expect of course. In our
case it's a pain, because one of the composite rules for GIF frames is
"restore background color" and sometimes that color is transparent. Thus
the GIFFrameCompiler approach.

Here is a useful snippet of code that should work for all of us:
Feature require: 'WebClient'.
r _ WebClient httpDo: [ :client |
client httpGet: '
image _ AnimatedImageMorph gifFromBinaryStream: r content asByteArray
image runningWorld color: (image forms first colorAt: 0 at 0).
morphPosition: 10 at 10;

If I have not formatted this package correctly, please let me know. This is
my first "real" Cuis package. Additionally, is there some pattern for
including test packages? I'm asking because I don't see any test packages
in the image or even when I require other features.

Let me know if you have any questions or comments. Thanks!

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20211122/98686b27/attachment.htm>

More information about the Cuis-dev mailing list