Question

I'm trying to get ARGB components from CGBitmapContext with the following codes:


-(id) initWithImage: (UIImage*) image   //create BitmapContext with UIImage and use 'pixelData' as the pointer
{

        CGContextRef    context = NULL;
        CGColorSpaceRef colorSpace;
        int             bitmapByteCount;
        int             bitmapBytesPerRow;

        bitmapBytesPerRow   = (image.size.width * 4);                       
        bitmapByteCount     = (bitmapBytesPerRow * image.size.height);

        colorSpace = CGColorSpaceCreateDeviceRGB();                         
        pixelData = malloc( bitmapByteCount );      //unsigned char* pixelData is defined in head file
        context = CGBitmapContextCreate (pixelData,                         
                        image.size.width,
                        image.size.height,
                        8,    // bits per component
                        bitmapBytesPerRow,
                        colorSpace,
                        kCGImageAlphaPremultipliedFirst
                        );
        CGColorSpaceRelease( colorSpace );                                  

        CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
        pixelData = CGBitmapContextGetData(context);
        return self;
}


-(float) alphaAtX:(int)x y:(int)y   //get alpha component using the pointer 'pixelData' 
{
    return pixelData[(y *width + x) *4 + 3];    //+0 for red, +1 for green, +2 for blue, +3 for alpha
}

-(void)viewDidLoad { [super viewDidLoad]; UIImage *img = [UIImage imageNamed:@"MacDrive.png"]; //load image

[self initWithImage:img];   //create BitmapContext with UIImage
float alpha = [self alphaAtX:20 y:20];  //store alpha component

}

When I try to store red/green/blue, they turn out to be always 240. And alpha is always 255.

So I think maybe something is wrong with the pointer. It could not return the correct ARGB data I want. Any ideas about what's wrong with the code?

Was it helpful?

Solution

First of all, you're leaking memory, the pixelData memory never gets freed.

For your usage, it's better to let the CGContext calls manage the memory. Simply pass NULL i.s.o. pixelData, and as long as you keep the reference count up on your context, the CGBitmapContextGetData(context) will remain valid.

You're using alpha as if it was the last entry (RGBA, not ARGB), use it as such in the creation of your context, or adapt the alphaAtX code. I'm not sure if you want premultiplied, if it's just to check alpha values, you don't.

All in all something like:

[...]
CGContextRelease(context);
context = CGBitmapContextCreate (NULL,                                                     
                                    image.size.width,
                                    image.size.height,
                                    8,    // bits per component
                                    bitmapBytesPerRow,
                                    colorSpace,
                                    kCGImageAlphaLast
                                    );
CGColorSpaceRelease( colorSpace );                                                                      

CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
pixelData = CGBitmapContextGetData(context);
[...]

with context being a member variable, initialized to NULL, will already be a step in the right direction.

OTHER TIPS

First, I would check to see if the context returned from your CGBitmapContextCreate call is valid (that is, make sure context != NULL). I'd also check to make sure your originally loaded image is valid (so, make sure img != nil).

If your context is nil, it may be because your image size is unreasonable, or else your pixel data format is unavailable. Try using kCGImageAlphaPremultipliedLast instead?

Second, you don't need to use CGBitmapContextGetData - you can just use the pixelData pointer you passed in in the first place. You should also CGContextRelease your context before leaving your initWithImage: function to avoid a leak.

I also note that you're using kCGImageAlphaPremultipliedFirst. This means that the alpha component is first, not last, in your image, so you want an offset of 0 for the alpha component in your alphaAtX:y: function.

Does any of that help?

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