Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
417 views
in Technique[技术] by (71.8m points)

iphone - Getting RGB pixel data from CGImage

I am trying to access pixel data from a CGImage. I want to be able to access the RGB values as integers. I think I am nearly there with this code:

UIImage* theImage = [UIImage imageNamed:@"rgb.png"];
CGImageRef cgImageRef = CGImageRetain(theImage.CGImage);
CFDataRef* imageData = CGDataProviderCopyData(CGImageGetDataProvider(cgImageRef));
NSLog(@"the data = %@", imageData);

This then logs:

the data = <010002fe fffdff02 0200fe04 0003fc>

The image is a 5x1 png containing a black, white, red, green and blue pixel in that order.

I don't really understand what I am looking at here. How can I get an array of RGB values, or something similar so I can work with them.

Thanks, Rich

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Here's some sample code that will print a bunch of relevant info about an image, as well as a dump of the image's pixel data. It will work on images with alpha channels, as well as images without. The code will even work on images that are not in the RGB color space, though I doubt you'd be likely to get any of those on iOS.

Copy-paste it into your project and try to run it against a few of your image files, and then perhaps you can adapt it to your needs

-(void)imageDump:(NSString*)file
{
    UIImage* image = [UIImage imageNamed:file];
    CGImageRef cgimage = image.CGImage;

    size_t width  = CGImageGetWidth(cgimage);
    size_t height = CGImageGetHeight(cgimage);

    size_t bpr = CGImageGetBytesPerRow(cgimage);
    size_t bpp = CGImageGetBitsPerPixel(cgimage);
    size_t bpc = CGImageGetBitsPerComponent(cgimage);
    size_t bytes_per_pixel = bpp / bpc;

    CGBitmapInfo info = CGImageGetBitmapInfo(cgimage);

    NSLog(
        @"
"
        "===== %@ =====
"
        "CGImageGetHeight: %d
"
        "CGImageGetWidth:  %d
"
        "CGImageGetColorSpace: %@
"
        "CGImageGetBitsPerPixel:     %d
"
        "CGImageGetBitsPerComponent: %d
"
        "CGImageGetBytesPerRow:      %d
"
        "CGImageGetBitmapInfo: 0x%.8X
"
        "  kCGBitmapAlphaInfoMask     = %s
"
        "  kCGBitmapFloatComponents   = %s
"
        "  kCGBitmapByteOrderMask     = 0x%.8X
"
        "  kCGBitmapByteOrderDefault  = %s
"
        "  kCGBitmapByteOrder16Little = %s
"
        "  kCGBitmapByteOrder32Little = %s
"
        "  kCGBitmapByteOrder16Big    = %s
"
        "  kCGBitmapByteOrder32Big    = %s
",
        file,
        (int)width,
        (int)height,
        CGImageGetColorSpace(cgimage),
        (int)bpp,
        (int)bpc,
        (int)bpr,
        (unsigned)info,
        (info & kCGBitmapAlphaInfoMask)     ? "YES" : "NO",
        (info & kCGBitmapFloatComponents)   ? "YES" : "NO",
        (info & kCGBitmapByteOrderMask),
        ((info & kCGBitmapByteOrderMask) == kCGBitmapByteOrderDefault)  ? "YES" : "NO",
        ((info & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Little) ? "YES" : "NO",
        ((info & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little) ? "YES" : "NO",
        ((info & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Big)    ? "YES" : "NO",
        ((info & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big)    ? "YES" : "NO"
    );

    CGDataProviderRef provider = CGImageGetDataProvider(cgimage);
    NSData* data = (id)CGDataProviderCopyData(provider);
    [data autorelease];
    const uint8_t* bytes = [data bytes];

    printf("Pixel Data:
");
    for(size_t row = 0; row < height; row++)
    {
        for(size_t col = 0; col < width; col++)
        {
            const uint8_t* pixel =
                &bytes[row * bpr + col * bytes_per_pixel];

            printf("(");
            for(size_t x = 0; x < bytes_per_pixel; x++)
            {
                printf("%.2X", pixel[x]);
                if( x < bytes_per_pixel - 1 )
                    printf(",");
            }

            printf(")");
            if( col < width - 1 )
                printf(", ");
        }

        printf("
");
    }
}

Here's some sample output on two images I tried. They're both 5x3 rgb. The "a.png" image has an alpha channel, while the "b.rgb" does not.

===== a.png =====
CGImageGetHeight: 5
CGImageGetWidth:  3
CGImageGetColorSpace: <CGColorSpace 0x4d08ff0> (kCGColorSpaceDeviceRGB)
CGImageGetBitsPerPixel:     32
CGImageGetBitsPerComponent: 8
CGImageGetBytesPerRow:      20
CGImageGetBitmapInfo: 0x00000003
  kCGBitmapAlphaInfoMask     = YES
  kCGBitmapFloatComponents   = NO
  kCGBitmapByteOrderMask     = NO
  kCGBitmapByteOrderDefault  = NO
  kCGBitmapByteOrder16Little = NO
  kCGBitmapByteOrder32Little = NO
  kCGBitmapByteOrder16Big    = NO
  kCGBitmapByteOrder32Big    = NO
Pixel Data:
(00,00,00,FF), (FF,FF,FF,FF), (FF,00,00,FF), (00,FF,00,FF), (00,00,FF,FF)
(00,00,00,FF), (FF,FF,FF,FF), (FF,00,00,FF), (00,FF,00,FF), (00,00,FF,FF)
(FF,FF,FF,00), (FF,FF,FF,00), (FF,FF,FF,00), (FF,FF,FF,00), (FF,FF,FF,00)


===== b.png =====
CGImageGetHeight: 5
CGImageGetWidth:  3
CGImageGetColorSpace: <CGColorSpace 0x4d08ff0> (kCGColorSpaceDeviceRGB)
CGImageGetBitsPerPixel:     24
CGImageGetBitsPerComponent: 8
CGImageGetBytesPerRow:      15
CGImageGetBitmapInfo: 0x00000000
  kCGBitmapAlphaInfoMask     = NO
  kCGBitmapFloatComponents   = NO
  kCGBitmapByteOrderMask     = NO
  kCGBitmapByteOrderDefault  = NO
  kCGBitmapByteOrder16Little = NO
  kCGBitmapByteOrder32Little = NO
  kCGBitmapByteOrder16Big    = NO
  kCGBitmapByteOrder32Big    = NO
Pixel Data:
(00,00,00), (FF,FF,FF), (FF,00,00), (00,FF,00), (00,00,FF)
(00,00,00), (FF,FF,FF), (FF,00,00), (00,FF,00), (00,00,FF)
(00,00,00), (FF,FF,FF), (FF,00,00), (00,FF,00), (00,00,FF)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...