Question

I have a series of PNG images that use indices into a palette for color (PNG color type 3). In some cases, I need to make a copy of an image where some of the entries in the palette are modified. In this way we recolor a source PNG over and over.

In Java, this is handled by getting the RGB values from an IndexedColorModel, modifying the values and creating a new IndexedColorModel, and creating a new BufferedImage with the source image's raster data and the new color model.

In Actionscript, I had to read in the PNG bytes as a bare ByteArray, find the palette chunk, modify the values, then have the runtime load up the image from the ByteArray.

I'm now looking to implement the same system for iOS via MonoTouch (which I'm new to), but I've hit a wall. I believe the Actionscript approach would work here as well, but it would be nice to avoid working at such a low level this time, and it looks like I can get close.

If I'm starting from a UIImage, I can get the color space with UIImage.CGImage.ColorSpace. I can verify that it's an indexed color model with colorSpace.Model. What I'm not sure about is how I get the actual array of palette bytes.

And then on the other side, how do I create a new image with the new palette? CGImage.WithColorSpace looks like it would do what I want... maybe? And then I have to be able to create a color space with my new palette: On the surface, CGColorSpace.CreateIndexed looks like what I want, but I'm unclear on how the baseSpace parameter is used. I want to create a CGColorSpace with a totally new color palette that I provide, and then use the original image's indices with the new palette. Maybe I'm misunderstanding exactly what CGColorSpace is used for.

Was it helpful?

Solution

In Actionscript, I had to read in the PNG bytes as a bare ByteArray, find the palette chunk, modify the values, then have the runtime load up the image from the ByteArray.

That's a bit brute but it would work. However I'm pretty sure CoreGraphics has everything you need to avoid this.

If I'm starting from a UIImage

Since you'll be using CoreGraphics (CG) anyway you can start with a CGImage. Sample code (objc) here: iPhone SDK: accessing indexed color PNG images

What I'm not sure about is how I get the actual array of palette bytes.

CGColorSpaceGetColorTable looks like the perfect candidate. However it looks like it's missing from MonoTouch bindings (I'll check that) but it would be easy (it's a p/invoke) to bind manually and use in your application.

but I'm unclear on how the baseSpace parameter is used

CGColorSpace.CreateIndexed can accept a null parameter for baseSpace but you might be better copying the same, base, GCColorSpace from the original PNG image.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top