I have transferred my C++ image library to C. Fortunately that wasn’t too hard, and I’ve been able to make many improvements along the way.
After the porting to C it’s cleaner, way more modular, I love it.
- supported image formats:
- bitmap (.BMP)
- GIF (some cases not handled like interlaced data)
- supported pixel formats
- indexed images 1 to 8 bits per pixel (color palette of 2 to 256 colors)
- grayscale images 1 bit, 2bit, 4 bit, 8 bit
- RGB 16 bit
- grayscale-alpha 16 bit (8 each)
- RGB 24 bit
- RGBA 32 bit
- Color conversion, 144 named color constants
- load / save images from and to all supported formats
- conversion from one format to the other
- set / get individual pixels
- downscale, mirror or flip image
- create animated GIFs
- color quantization (median-cut algorithm) – to reduce colors of image
- Floyd-Steinberg dithering
- Perlin noise
- Value noise
- a few noise effects
I updated the code documentation on the project’s GitHub page
For JPEG and PNG I downloaded the source code and integrated it to a separate build process I have for the few dependencies the project has (basically these two plus Zlib, and Glew for OpenGL). I’m using static library versions.
For BMP and GIF formats, I implemented them (almost completely) following the specs, with help from mostly Wikipedia for BMP, and for GIF there are this very helpful spec here and this absolutely awesome site by Matthew Flickinger, it’s great, probably saved me lots of time, especially with understanding LZW encoding / decoding.
For color quantization and dithering, in the C++ I was using code from a cool project I found on Github, it was very well done but I didn’t fully understand how it worked when I added it, and I don’t like to do that anymore. So I ditched that code and started from scratch, used Wikipedia and had help understanding the logic thanks to this page too.
I had to implement generic sorting algorithms in core library, for color quantization.
Turns out quicksort was absolutely atrocious for what I needed to do (too many items to sort), so I also added mergesort and it “fixed” it (meaning now speed is actually not too bad). I’ve had tremendous help with the algorithms on GeeksForGeeks.
I’m very interested in implementing IntroSort and see if that improves on mergesort for pixel sorting.
I have a few things to tidy up, like correctly extracting all frames from an animated GIF handling the transparency based on the disposal method, or writing pixel diffing functions when adding animated frames to a GIF file, to reduce output file size.
I might make a small executable to do with image work, conversion, dithering etc. Like a crappy version of ImageMagick command line.
But all this can wait, next I’m very excited to move on to porting my C++ OpenGL wrapper library to C, which mostly was already working like a C API so hopefully that shouldn’t take too long.
Animated GIF with “palettized” image and dithering, from 2 to 256 colors, compared to the reference image
The reference image transformed to grayscale, 4 bit depth, with and without Floyd-Steinberg dithering
Another animated gif of my 3d “planet” noise (using Perlin noise)