Outreachy Blog 2

Table of contents

Image Credits: Julia Set Example by Michael Dales
Everybody Struggles
Contributing to opensource projects comes with a lot of new learnings. There is always something new that you stumble upon which you would have otherwise not even come across. May it be through someone else’s code, their contributions or their way of doing things.
Often new comers look at these experienced contributors and get overwhelmed by their code. I definitely had this experience when working with a library called ocaml-gif.
Claudius uses ocaml-gif for capturing images and now animations. The library was originally authored by Jan Dudek and then reworked by my mentor Michael Dales to update it to modern OCaml and rework the APIs to be more palette based.
A short Intro to ocaml-gif
ocaml-gif is an OCaml library that supports reading and writing of GIF files. It consists of the below modules:
giF.ml
: It handles the high-level structure of a GIF file, including frames and the overall file encoding. This module acts as the main entry point for constructing and writing GIFs.colorTable.ml
: This module defines a color table as an array of RGB color tuples used in GIF images. It provides utility functions to create, access, modify and convert color tables.image.ml
: This module defines the structure of individual GIF frames, including pixel data and per-frame metadata like delay. It is used to build and describe each frame before it's written to the final GIF output.lzw.ml
: This module implements the LZW (Lempel-Ziv-Welch) compression algorithm required for GIF image data. It compresses indexed pixel arrays into byte streams for the GIF file format.
Together, these modules work in unison to construct and write valid GIFs.image.ml
defines frame data, colorTable.ml
builds the color table, lzw.ml
compresses the pixels, and gif.ml
ties everything into a complete GIF file.
My previous experience working with ocaml-gif
I had previously worked with ocaml-gif for the screenshot feature during the contributions phase for Outreachy, so I had a little familiarity with the library.
Now I am using the same library to add another feature to Claudius to capture animated GIFs. But this time I needed to understand it even more deeper as I had figured out there is no other easier way to make use of ocaml-gif for animated GIF rather than modifying it for our use-case.
So ocaml-gif already had a function from_image
. It was originally designed to create a single frame GIF or a static image. It used to take one Image.t
at a time. This had all the image dimensions, offsets, pixel data and optional metadata. It then generated a global color table and compressed the image using the LZW compression. And then the image was written as a valid .gif
file containing just that frame.
This function was ideal for static images, but it lacked the support for per-frame delays and multiple frames needed for animation.
Modifications to ocaml-gif for the animation feature
Addition of
from_images
To support animated GIFs in Claudius, I added a new function called from_images
to the giF.ml
module as a natural generalization to the previously present from_image
. It works like the existing from_image
, but instead of handling a single frame, it takes a list of Image.t
. It then validates if all the frames have same dimensions. This is necessary as it ensures that all the frames can be displayed uniformly within the same screen area of the GIF. It also ensures that all palettes have less than 256 colors as ocaml-gif supports upto 256 colors.
Refactoring the commonalities
Now from_image in itself did a lot of things. It extracted the palette, computed the color table and LZW code sizes, built a stream descriptor, handling of image control values and construction of image block, Now these were a lot of things for just a single function to handle. The similar functionalities were also needed in the newly added from_images. So, there was a scope for refactoring here.
So, I split the function into 2 smaller helper function to handle seperate concerns. compute_color_table
handled the functionalty for computing color table size, LZW code size, and building the color table whilst block_of_image
handles the logic for image block creation. These two functions were then used in both from_image and from_images.
Simplification of
from_image
Now since from_images
was a generalization to capture multiple images which accepted a list of Image.t
, we used the same function to simplify the structure for from_image
to just one line! So, now we pass a list of one image to from_image
and delegate the entire construction process to the already generalized from_images
function.
Unit testing for
from_images
I added a unit test test_write_animation_8_bpp
for from_images
to validate the behavior of animated GIF generation. The test makes sure that all the frames are correctly encoded and have the same dimensions. It also makes sure that the order for the frames is preserved. This is done by checking the first pixel in each frame to contain the expected value, which changes with the frame index.
A little final touch to the documentation
We are preparing to get ocaml-gif into opam. And since I had taken a good amount of time to understand and work with the library, addition of documention for it was a nice little contribution!
So, that was about my journey until now! Thanks for reading and see you in the next blog!
Subscribe to my newsletter
Read articles from Shreya Pawaskar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Shreya Pawaskar
Shreya Pawaskar
Outrechy intern'25 at @claudiusFX for @ocaml || Opensource Contributor || BTech AI&DS Graduate