In this post, we discuss GIF file format and the launch of GIFImages.jl to work with GIF files in Julia.
Introduction
Graphics Interchange Format (GIF) is a bitmap image format and is very widely used due to widespread support and portability between applications and operating systems.
Important: GIF format supports up to 1 byte per pixel for each image, allowing a single image to reference its palette of up to 256 different colors chosen from the 24-bit RGB color space.
GIFs also support animations and allow a separate palette of up to 256 colors for each frame. Palette limitations make it unsuitable for images with a huge number of unique colors. GIF images are compressed using the Lempel–Ziv–Welch (LZW) lossless data compression technique to reduce the file size without degrading the visual quality.
Let's take the example of Chelsea to understand GIFs.
GIFImages.jl provides support for methods to decode(read) and encode(write to gif from single/multiple image array) to GIF files.
julia> using GIFImages
julia> filepath = "chelsea-disappears.gif"
julia> imgs = gif_decode(filepath)
300×451×7 Array{RGB{N0f8},3} with eltype RGB{N0f8}:
[:, :, 1] =
RGB{N0f8}(0.635,0.494,0.404) RGB{N0f8}(0.635,0.494,0.404) … RGB{N0f8}(0.176,0.102,0.051)
RGB{N0f8}(0.663,0.525,0.447) RGB{N0f8}(0.663,0.525,0.447) RGB{N0f8}(0.2,0.122,0.067)
⋮ ⋱ ⋮
RGB{N0f8}(0.549,0.392,0.275) RGB{N0f8}(0.506,0.341,0.212) RGB{N0f8}(0.635,0.494,0.404)
[:, :, 2] =
:
:
The size of the returned image is (300,451,7) which represents the height, width, and number of images respectively. GIF images are RGB palette based and 256 different colors can be chosen from the 24-bit RGB color space. Now, let's how we made this GIF with gif_encode
julia> using GIFImages, TestImages
julia> chel = testimage("chelsea")
julia> gif_arr = ones(RGB{N0f8}, (size(chel)[1], size(chel)[2], 7)) #gif image array
julia> map(x->gif_arr[:,:,x]=chel, [1,2,3,4,5,7])
julia> map(x->gif_arr[:,1:x*100,x+1] .= RGB{N0f8}.(1.0,1.0,1.0) , 1:4) # covering more and area with white color in subsequent images.
julia> gif_encode("chelsea-disppears.gif", gif_arr)
And now take another tiny gif_image of size(2,2,6) to understand the file structure:
That tiny black dot is 4(2x2) pixels of your computer screen!! Now let's see GIF image file structure and understand with help of our new GIF:
How gif under lens looks like:
GIF under lens! | Appearance |
---|---|
Now, let's see how data is organized in our small gif!!
Data is highlighted to differentiate different sections in the gif file.
-
Header block
: First 6 bytes(Yellow) -
Logical Screen Descriptor
: Next 7 bytes -
Global Color Table
: Next 6 bytes(Purple)
Now for each image, starts with 0x2C:
-
Image Descriptor
: 9 bytes(Purple) -
Image Compressed data
afterwards(Mint Green)
In end, file ends with 0x3B
The Why
One might ask why use GIFImages instead of already existing ImageMagick method which is provided by FileIO load, save.
Why then?
- Decoding process time taken is much faster(x15 times), encoding process time taken is comparable(work in progress).
- GIFImages allows support for using local colormaps for decoding GIF which has made a big difference in decoding, I have noticed less erroneous decoding with support for using both local and global color palettes.
- Encoding method provides a way to limit number of colors to a certain number which ImageMagick approach doesn't.
Note!!!!
GIFImages.jl is now available for the community's use in Julia's General Registry and can be simply installed using:
# Enter ']' from the REPL to enter Pkg mode.
pkg> add GIFImages
Future Work
- Work on support for the application extension block which allows to create animations in the gif file and allow looping.
- Add GIFImages support to ImageIO which JuliaImages wants to use to deprecate the old ImageMagick backend with faster IO support.
- Improve upon the color quantization methods that were written to support the encoding process of GIFs, mainly memory allocations are concerning.
- In the distant future, consider and if needed provide in-house support for GIFs by writing GIF support in Julia itself, rather than relying on LibGif
Acknowledgments
Thank you @johnnychen94 for being constant support as a mentor and a friend over the years!!
Top comments (2)
Wonderful work