Programming, Software

Bit Depth Problems with RMagick / ImageMagick

I just spent the entire afternoon debugging a problem I couldn’t find elsewhere, so I’m documenting it in the off chance someone else runs into the evil thing.

I’m composing some images on the fly using ImageMagick via RMagic. It grabs one file, floods the image with a given color, and layers another on top of it. Locally, it works great, and gives me “body parts” like this one:

Unfortunately, when I push the code to Heroku, it starts going through a goth phase and filling everything in with BLACK LIKE SOUL:
I spent a very, very long time trying to suss this one out, checking out everything from opacity to gem versions. Finally, I checked the ImageMagick version (Magick::Magick_version).
Local: “ImageMagick 6.6.7-1 2011-02-08 Q8 http://www.imagemagick.org”
Heroku: “ImageMagick 6.6.0-4 2010-06-01 Q16 http://www.imagemagick.org”

Ok, so Heroku’s is a bit older. But that’s not the critical issue. The bigger problem is the Q16, which is reporting the quantum depth. I don’t understand nearly enough about image processing to talk about what that really means. But long story short, it means my images had different default bit depths and it was causing everything to blow up. Or something.

I was able to fix it by changing how I instantiated the Pixel for the fill. Before, I was using

fill_image.colorize(1,1,1,Magick::Pixel.new(r,g,b))

where r, g, and b are integers between 0 and 255.

Conveniently, RMagick has added a from_color method to Pixel, which lets you define a pixel based on a color name. I passed in a hex value, and everything magic(k)ally works normally again:

color = '#ababab'
fill_color = Magick::Pixel.from_color(color.upcase)
fill_image = fill_image.colorize(1,1,1,fill_color)

I wish I understood a few more of the particulars about what is really going on here. But for the time being I need to move on to finishing this up. Any insight is welcome in the comments.

2 thoughts on “Bit Depth Problems with RMagick / ImageMagick”

  1. BAM! You nailed it, buddy. Thanks for writing this up – first hit on Google.

    My problem was actually going the opposite direction. I was reading pixel values looking for a specific value. For example, if you’re looking 0xFF when you have an 8-bit quantum, everything is fine. Deploy somewhere like Heroku where you have a 16-bit quantum, and max-intensity pixels come back as 0xFFFF instead of 0xFF.

    So for anyone else out there: If you’re checking a pixel channel value for 0xFF, don’t. Instead, check for Magick::QuantumRange.

    If you want to test other pixel values between 0 and Magick::QuantumRange, I suggest using Magick::Pixel#to_color to do the opposite of Magick::Pixel#from_color mentioned above, specifying the quantum and format you want the color returned in.

Leave a Reply

Your email address will not be published. Required fields are marked *