简体   繁体   中英

Get pixel RGB wrong by CGBitmapContextCreate

I came into a strange problem. I'm using CGBitmapContextCreate to get the raw pixel data from an image, and then modify the pixel color at specified location. However, I found out when I get the RGBA of a pixel that alpha equals to 1, everything goes fine, but if the alpha is less than 1, the RGB is wrong, it's a darker color. Could anyone tell me why, it drives me crazy...

Here is my code, and you can get the test picture here

图片

#define Mask8(x) ( (x) & 0xFF )
#define R(x) ( Mask8(x) )
#define G(x) ( Mask8(x >> 8 ) )
#define B(x) ( Mask8(x >> 16) )
#define A(x) ( Mask8(x >> 24) )
#define RGBAMake(r, g, b, a) ( Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24 )

- (void)getPixelRGBA
{
    UIImage *image = [UIImage imageNamed:@"testpicture.png"];
    NSUInteger bytesPerRow = 4*image.size.width;
    UInt32 *pixels = (UInt32 *)calloc(image.size.width*image.size.height, sizeof(UInt32));

    CGContextRef context = CGBitmapContextCreate(pixels, image.size.width, image.size.height, 8, bytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);

    // pixel with alpha < 1, color gets dark
    int offset1 = 75 * (int)image.size.width + 75;
    UInt32 *pixelValue1 = pixels + offset1;
    UInt32 pixelColor1 = *pixelValue1;
    UInt32 r1 = R(pixelColor1);
    UInt32 g1 = G(pixelColor1);
    UInt32 b1 = B(pixelColor1);
    CGFloat a1 = A(pixelColor1)/255.0f;

    // pixel with alpha == 1, color is right
    int offset2 = 75 * (int)image.size.width + 80;
    UInt32 *pixelValue2 = pixels + offset2;
    UInt32 pixelColor2 = *pixelValue2;
    UInt32 r2 = R(pixelColor2);
    UInt32 g2 = G(pixelColor2);
    UInt32 b2 = B(pixelColor2);
    CGFloat a2 = A(pixelColor2)/255.0f;
}

Thank you guys very much!

iOS uses premultiplied alpha . (That's the Premultiplied part of kCGImageAlphaPremultipliedLast .).

This means that the R, G, and B channels of a pixel do not range from 0 ... 255. They range from 0 ... A. If the R channel is 127, but the A channel is also 127, then that R is at full intensity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM