GIF App Development – How to Develop GIF Encoding
Learn how to develop GIF encoding in your app and discover libraries that can help you in this process.
In this article, we’ll briefly list libraries that can help you with GIF file encoding which is an important part of GIF-maker app development process. Note that projects are constantly evolving, some get deprecated, other new ones appear.
Why GIF encoding is so complex?
It may seem that making the GIF file out of a sequence of images is just like making a video file, only the format differs. Well, nothing could be further from the truth! Keep in mind that GIF format has been developed in 1987, over 30 years ago and at the beginning, it even didn’t support animations. That’s why it has some limitations that make encoding a little bit harder.
The most significant issue is that a single GIF frame may contain up to 256 colors (including the transparent one if used). The snapshot visible at the given moment of time may consist of multiple frames. That’s because a frame may have a smaller size than the whole canvas. Additionally, a frame may contain transparent pixels. If we want to encode a frame that has more than 256 colors, we have to transform it somehow. There are a few ways to deal with that issue, some of them may be also combined.
One of them is dithering. Roughly speaking, it simulates intermediate colors by mixing more distinct ones. You can see an example in the picture below. Note that an image consists of only completely black and completely white pixels. However, dithering introduces the illusion of greyscale.
If all the frames can be stored (either in memory or in a format like a video file), we can first go through all of them, check which colors are used and how frequently (create histograms), and build an optimal palette(s). There are a few ways to create such histograms. For example, FFmpeg’s palettegen filter supports 3 different statistic modes.
Each GIF frame may have its own palette (if it does not then a global palette is used). With separate palettes, we can have more colors in the whole file. However, multiple palettes consume additional storage space and time to decode. Depending on the animation length, canvas size, and usage it may or may not be meaningful. You can read more about that in the article about high-quality GIF encoding.
Note that GIF format supports only transparency (alpha bit – pixels can be fully transparent or fully opaque), not translucency (alpha channel – fine-grained transparency level). That means if your source contains translucent pixels they will appear as either transparent or opaque in the output GIF file. Look at the following images:
Each frame can have its own delay. It is the time for which a frame is displayed. Delay is measured in centiseconds (1 unit = 0.01s). 100 FPS sounds great. However, due to the fact that GIF decoding is generally slow comparing to video (which is often hardware accelerated) the limits were introduced. The lowest values (shortest delays) are artificially increased to higher values. What is more the value after increasing is usually not the minimum one but something even higher!
For example in the environment of writing this article the effectively minimal delay is 0.02s. Everything smaller is increased to 0.01s. See animations below:
See also Animated GIF Minimum Frame Delay Browser Compatibility Study (which is also a source of the images above) for more examples in different browsers. You may be interested in the web archive copy since images on the original website are dead. Choosing the minimum value wasn’t an easy task.
Devices running Android (mostly smartphones and tablets), usually have less performant hardware than PCs used at the same time, so the optimizations have significant meaning here. This means that GIF encoding in Android apps is usually done natively (using C/C++ and JNI, not to be confused with native – non-hybrid, non-Flutter apps).
Fortunately, you don’t always need to go to so low level of abstraction when you develop GIF encoding in your app. One of the most popular libraries for image/video encoding is FFmpeg. Android developer-friendly version is not provided officially. However, some wrappers do exist. At the time of writing one of the most popular is Mobile FFmpeg. Something like this will be probably all you need when you just want to produce GIF out of some input source.
If you want to manipulate on some more GIF-specific properties like disposal methods on individual frames or modify GIF file metadata you may be interested in gifsicle. Unfortunately, it has neither official Android bindings nor a well-known unofficial port. You need to compile it from the source.
GIF encoding is not an easy process. Due to the fact that GIF was not designed for modern animations, we need to resort to very sophisticated techniques to achieve satisfactory results. Fortunately, we don’t need to write everything from scratch. This topic is popular enough so there are ready libraries that can be used at least low-level parts of the app. Read also an article GIF app development – Challenges and Tips, and check out GIPHY Cam – the app for creating and sharing GIFs that we’ve developed.