Yanking the Thread

Have you ever pulled on a loose thread on a sweater, only to produce a gaping hole that needs fixing? Well, I almost did that over the weekend with my Imaging code. Here’s what happened…

In order to work on imaging code, you need to see the images that you load, store and/or manipulate. This particular library was initially developed on a Linux laptop and used the X11 GUI to display the images. My code is now on my web server w/o any kind of GUI. So, in order to see the result of my bit gymnastics I need to dump the image into a graphics file, which can then be read by my web browser. As GIF, JPEG and PNG files all use compression of some form or other, I decided to write BMP image files. Initial tests worked extremely well. I was able to load in a BMP file, output a different BMP files and see no image loss. So far, so good.

The problem occurred when I decided to open up a PNM file and dump the BMP file. I noticed, then, that the colors were off, even though the image was recognizable. That’s when it hit me. BMP files store their colors in BGR (Blue, Green, Red) order instead of RGB order. So the blue and red data was getting swapped.

This minor detail had a huge effect on my design. I currently enforce RGB data order. In order to handle BMP Files, this left me with two options:

  • Swap the pixel ordering on both input and output from/to BMP files
  • Support BGR pixel ordering

Both options have issues of their own. Option #1 would introduce a performance penalty on BMP file I/O. Option #2 would require me to take another look at how pixels and pixel buffers are organized throughout my Imaging library. Not being one to shun the difficult path, I chose option #2 and discovered that my pixel and colorspace handling code design had several flaws, the worst being ease of use. While the algorithms were accurate, the implementation and organization was not well done.

Without going into details, I need to rethink my design before touching the code. I want to support 8-bit, 16-bit and floating point color component values w/o having to write and maintain three parallel layers of pixel manipulation code to support the different component types. I also don’t want to use C++ templates. I may write a Ruby script that will take C++ code template files and generate the pixel manipulation code, but I’m not sure if that’s the proper approach.

Anyway, I need to rethink some of my earlier design decisions before pressing forward.

Comments are closed.