views:

267

answers:

1

I have a large 8-bit PNG image. I am using Java to slice the image into smaller 32x32 images. I use Java's ImageIO to load the PNG into a BufferedImage and then call it's getSubimage(x, y, 32, 32). I then use ImageIO to write each tile out as a PNG.

The problem is that the resulting image has the same IndexColorModel as the original image. For example, one 32x32 tile has only 8 total colors but it includes a color model with all 100-odd colors from the original image.

I would like to remove unused colors from the 32x32 tile's IndexColorModel before I write out the PNG. There is no sense including color data for colors not used in the image and I'd like the images to be as small as possible.

Is there a built-in mechanism to do this or can someone point me to an (easy) way to modify/reduce the ColorModel?

Thanks!

+1  A: 

Take a look at ColorConvertOp in java.awt.image.

Basically, you create a new IndexColorModel of the desired depth. If you really want the smallest, you can walk through the Raster and count the colors. Otherwise, just choose 4 or 5 bits per pixel. Then create a BufferedImage with TYPE_BYTE_BINARY and the IndexColorMap. Finally, use the ColorConvertOp's filter() method to copy the original data to the new BufferedImage.

Devon_C_Miller
Devon, thanks - this got me moving in the right direction except that after creating an `IndexColorModel` with the exact number of colors, the saved PNG still appears to have 256-colors in it's color table. Either Photoshop is displaying an incorrect color table or the palette has the correct 8 colors and then fills the remaining spaces up to 256 with shades of gray. Any ideas?
Thaliant
Hmm, it works for me, so it could be PS is reporting incorrectly. If you're on windows, check the file properties, "Summary" tab, "Advanced". It should show a "Bit Depth" of 4.
Devon_C_Miller
I might have the Bit Depth wrong when I am creating the IndexedColorModel. It may be in an invalid state which is producing the strangeness in the color table. I'll check it out and report back here.
Thaliant
After a bit of experimenting, it looks like 2-color and 8-color work correctly, but 4-color gives me 32-bits/pixel. So, if you have an image with less than 8 colors, pad it out to 8
Devon_C_Miller
It looks like I've been chasing a Photoshop "bug." Saving the same image out of Photoshop and loading it back in using a custom palette shows the same custom colors and grayscale-padded color table. Java's ImageIO-encoded PNG is substantially smaller (nearly 40% smaller) than Photoshops but displays properly in browsers and Flash. Padding was not required in the end - with less than 8 or more than 8 colors, the image in Photoshop still has the grayscale palette (at no extra cost) which actually may be a feature of the PNG format rather than a bug in Photoshop. Thanks for all your help!
Thaliant
P.S. I'd vote your answer up but I can't because I don't have enough reputation apparently. Thanks anyway!
Thaliant