How can I get pure alpha channel information from a PNG image on iPhone OS?

I created the following context (simplified):

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate (bitmapData, pixWide, pixHeigh, 8, // bits per component bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst); 

Now when I try to extract data for the first pixel in my PNG using Alphatransparency, it has very strange alpha values. I have a simple PNG, square. On each edge, I cut off 10x10 pixels and made them completely transparent. Alpha should not be something like 153.

KCGImageAlphaOnly is declared in cGImage.h. Doc says:

kCGImageAlphaOnly No data color, only alpha channel.

Good, so it's really good, because I only need Alpha data, and nothing more. But that raises some question marks in my head. If I use a fully equipped PNG with a bunch of colors + alpha: will this constant check that my PNG is converted to match this color space? Or do I need to provide a PNG that matches the specified color space?

Edit: I tried using kCGImageAlphaOnly, but I get this error:

 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 bits/pixel; 0-component colorspace; kCGImageAlphaOnly; 55 bytes/row. 

What could be the problem? I indicated this before:

 size_t pixelsWide = CGImageGetWidth(inImage); size_t pixelsHigh = CGImageGetHeight(inImage); bitmapBytesPerRow = (pixelsWide * 1); // not * 4, because I just want alpha bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); 

Edit: I read this a minute ago:

PNGs added to Xcode are optimized "pngcrush" during compilation. It does some bytes (from RGBA to BRGA) and pre-multiply alpha.

I assume that this pre-multiplication of alpha creates problems.

Edit: alpha channel remains intact after pngcrunch has performed byte exchange in PNG. I don't care about colors, just alpha, I think that pre-multiplication should not be too big a problem.

My PNG was a 24-bit PNG bevor. I added them to Xcode.

+4
source share
2 answers

You cannot do this:

 bitmapBytesPerRow = (pixelsWide * 1); // not * 4, because I just want alpha 

The function you call will always return all image data. The kCGImageAlphaOnly used to tell you that an image contains only an alpha channel, no color information.

You need to use pixelsWide * 4 for bytesPerRow. Also note that the bitmapData argument for CGBitmapContextCreate () is used to explicitly allocate storage space, and not to draw it.

It is possible that you want to do this (untested code, just typed from memory):

 CGImageRef image = GetMyImageFromWhereverItIs(); CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); CGContextRef ctx = CGBitmapContextCreate( NULL, CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetBytesPerRow(image), space, kCGBitmapByteOrderDefault | kCGImageAlphaLast ); CGColorSpaceRelease( space ); // now draw the image into the context CGRect rect = CGRectMake( 0, 0, CGImageGetWidth(image), CGImageGetHeight(image) ); CGContextDrawImage( ctx, rect, image ); UInt32 * pixels = CGBitmapContextGetData( ctx ); // now we can iterate through the data & read the alpha values int i, count = CGBitmapContextGetBytesPerRow(ctx) * CGBitmapContextGetHeight(ctx); for ( i = 0; i < count; i++ ) { UInt8 alpha = pixels[i] & 0x000000ff; // do with the alpha what you will } 
+5
source

Are you sure you are only looking for alpha values?

If you expect all alpha components to come first, then all red components, etc .: This flat layout, and I don't think Quartz supports it natively - it only supports all components together in each pixel ( ARGBARGBARGBARGB… not AAAA…RRRR…GGGG…BBBB… ). So, if you simply lay right in the data that treats each byte as alpha, then your problem: you look at the red, green and blue components and consider them as alpha.

As for premultiplication, which does not affect the alpha channel, this affects the color channels. Formula for arranging a raster (placing one raster image over another):

 dst.r = src.r * src.a + dst.r * (1.0 - src.a); dst.g = src.g * src.a + dst.g * (1.0 - src.a); dst.b = src.b * src.a + dst.b * (1.0 - src.a); 

Finalization cuts out the first expression for multiplication:

 dst.r = src.r′ + dst.r * (1.0 - src.a); dst.g = src.g′ + dst.g * (1.0 - src.a); dst.b = src.b′ + dst.b * (1.0 - src.a); 

This works because the original color components are already multiplied by the alpha component, hence the name "premultiplied". Now there is no need to multiply them, because it already has results.

This is an optimization and, apparently, important for the iPhone (all these multiplication operations add up when you make a million or two of them). But this does not affect the layout of the components: alternating remain alternating, whether the RGB components will be pre-multiplied or not.

+4
source

All Articles