Получение данных пикселей RGB из CGImage - PullRequest
16 голосов
/ 20 мая 2011

Я пытаюсь получить доступ к данным пикселей из CGImage.Я хочу иметь возможность получить доступ к значениям RGB в виде целых чисел.Я думаю, что я почти там с этим кодом:

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

Это затем регистрирует:

данные = <010002fe fffdff02 0200fe04 0003fc>

Изображение 5x1 pngсодержащий черный, белый, красный, зеленый и синий пиксель в указанном порядке.

Я не совсем понимаю, на что я здесь смотрю.Как я могу получить массив значений RGB или что-то подобное, чтобы я мог работать с ними.

Спасибо, Рич

1 Ответ

56 голосов
/ 21 мая 2011

Вот пример кода, который напечатает кучу соответствующей информации об изображении, а также дамп данных пикселей изображения. Он будет работать на изображениях с альфа-каналами, а также изображения без. Код будет работать даже с изображениями, которые не находятся в цветовом пространстве RGB, хотя я сомневаюсь, что вы получите такую ​​же на iOS.

Скопируйте и вставьте его в свой проект и попробуйте запустить его для нескольких файлов изображений, а затем, возможно, вы сможете адаптировать его к вашим потребностям

-(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(
        @"\n"
        "===== %@ =====\n"
        "CGImageGetHeight: %d\n"
        "CGImageGetWidth:  %d\n"
        "CGImageGetColorSpace: %@\n"
        "CGImageGetBitsPerPixel:     %d\n"
        "CGImageGetBitsPerComponent: %d\n"
        "CGImageGetBytesPerRow:      %d\n"
        "CGImageGetBitmapInfo: 0x%.8X\n"
        "  kCGBitmapAlphaInfoMask     = %s\n"
        "  kCGBitmapFloatComponents   = %s\n"
        "  kCGBitmapByteOrderMask     = 0x%.8X\n"
        "  kCGBitmapByteOrderDefault  = %s\n"
        "  kCGBitmapByteOrder16Little = %s\n"
        "  kCGBitmapByteOrder32Little = %s\n"
        "  kCGBitmapByteOrder16Big    = %s\n"
        "  kCGBitmapByteOrder32Big    = %s\n",
        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:\n");
    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("\n");
    }
}

Вот пример вывода двух изображений, которые я пробовал. Они оба 5х3 ргб. Изображение "a.png" имеет альфа-канал, а изображение "b.rgb" - нет.

===== 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)
...