Tuesday, February 16, 2010
Top left: The original image. Top right: The image quantized to 4 bits of color information per channel. Lower left: 3 bits of color per channel. Lower right: 2 bits per channel.
It turns out to be surprisingly quick and easy to quantize the colors in an image to a smaller number of bits per channel than the standard 8 bits for red, 8 bits for green, and 8 bits for blue. All you have to do is loop over the pixels and AND them against the appropriate mask value. A mask value of 0xFFF0F0F0 discards the lower 4 bits' worth of color information from each channel, essentially leaving 4 bits, each, for red, green, and blue. A mask value of 0xFFE0E0E0 keeps just the top 3 bits in each channel, while a mask of 0xFFC0C0C0 retains just 2 bits of color per channel.
The getRGB() method of BufferedImage fetches the pixels from your image as a giant one-dimensional array. The corresponding setImage() method replaces the pixels. The updatePanel() method of Panel (defined in ImageMunger.java) causes the JComponent to refresh.
As you might expect, quantizing the color info makes the image easier to compress. The original image, in PNG form, occupies 185 Kbytes on disk. The 4-bit-per-channel version occupies just 61K; the 3-bit version, 38K; and the 2-bit version, a little over 23K.