Initializing a pixel array from a CGBitmapContext

Discussion in 'iOS Programming' started by KnightWRX, Jul 23, 2011.

  1. KnightWRX macrumors Pentium


    Jan 28, 2009
    Quebec, Canada

    Ran into an issue with PNGs having transparent backgrounds and applying them into a pixel array using a CGBitmapContext. This was the "faulty" code :

    -(id) initWithCGImage: (CGImageRef) image
    	NSInteger bytes;
    	self = [super init];
    	CGColorSpaceRef colorSpace;
    	width = CGImageGetWidth(image);
    	height = CGImageGetHeight(image);
    	bytesPerChannel = 4; 
    	colorSpace = CGColorSpaceCreateDeviceRGB();
    	bytes = width * height * sizeof(BRUnifiedPixelRGBA);
    	imagePixels = malloc(bytes);
    	//[self resetToSolidColor: 0x00000000];
    	CGContextRef context = CGBitmapContextCreate(imagePixels, 
    						   width * bytesPerChannel,
    			             		 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    	   		   CGRectMake(0.0f, 0.0f, width, height),
    	return self;
    This ended up giving artifacts (from previously used and discarded memory regions in all probability) that basically looked like this :


    (Please save the laughter and comments about my graphical skills for yourselves. Consider it an honor to have seen a very, very early screenshot).

    Now, my question, short of resetting the entire pixel buffer memory after allocation (either with memcpy() or with a for loop, which [-(void) resetToSolidColor basically is), is there some parameters I can pass to CGBitmapContextCreate to tell it to not do alpha blending and just squash whatever is there ?

    Reading through CGImageAlphaInfo, I'm not quite sure I understand the Premultiplied vs well... not premultiplied bit. Is that what I'm looking for or really is there just no way to do this short of resetting memory myself ?

    (BTW, yes, I realise the BytesPerChannel variable is very poorly named. There is only 1 byte per channel, 4 channels per pixel... whatever, call it lazyness on my part, this code was written a very long time ago and I'm just now using it with transparent PNGs).
  2. chown33 macrumors 604

    Aug 9, 2009
    Call calloc() instead of malloc() and the memory will be returned zeroed. See the man page for calloc.

    Otherwise you'll have to zero it yourself. Assuming zeroing is the desired state for the pixel format.
  3. KnightWRX thread starter macrumors Pentium


    Jan 28, 2009
    Quebec, Canada
    Yes 0 is fine since this is a transparent png the alpha channel needs to be set to 0 or otherwise it would mess up when I merge 2 images.

    Hum... calloc has a bit of a different calling convention than malloc, dunno if I want to mess with that. The resetToSolidColor function is actually quite useful in initializing flat color surfaces, which I use a lot. I think I'll just keep that and make the 0x0 value a constant like my other color constants and clean up the code a bit.

    But can someone still explain what the Alpha premultiplied vs not pre-multiplied means ? The documentation isn't quite clear there.
  4. chown33 macrumors 604

    Aug 9, 2009
    It's simple C. You'll have to read the man page, but it's not hard.

    No harm in that.

    Did google stop working?

    If I start typing "premult", the first suggestion is "premultiplied alpha".
    If I choose that, the first result is a Wikipedia article:

    If I find "premult" on the page, an explanation and example moves into view.
  5. firewood macrumors 604

    Jul 29, 2003
    Silicon Valley
    non-premultiplied means your 8-bit RGB values are full scaled to go from 0 to 255

    premultiplied means your 8-bit RGB values are scaled to go from 0 to Alpha,
    where Alpha can be less than 255.
  6. KnightWRX thread starter macrumors Pentium


    Jan 28, 2009
    Quebec, Canada
    I'm sure it's not, but allocating a sized object and then a count of those means I need to sit down and read it, when basically, I already wrote the "zeroing" code which also serves another purpose on top of it.

    Sorry, I was stuck on Apple's documentation and didn't think this was a broader concept concerning Alpha blending. The wikipedia page was quite clear and it has nothing to do with what I wanted. I really guess calloc() or malloc() plus a full buffer initalization is the only way to not screw up the transparent background when copying the PNG using a CGBitmapContext. Anyway, the code works great now.
  7. PhoneyDeveloper macrumors 68040


    Sep 2, 2008
    If you want to fill your context with a color then you should fill your context with a color.

    CGContextSetFillColorWithColor(context, backgroundColor);
    CGContextFillRect(context, bounds);
  8. KnightWRX thread starter macrumors Pentium


    Jan 28, 2009
    Quebec, Canada
    That actually wouldn't work at all in my case. I'll leave you to think on why not. ;) Hint: It would result in the same broken behavior with artifacts.

Share This Page