Получение пиксельных данных RGB из CGImage

Я пытаюсь получить доступ к данным пикселей из 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>

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

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

Спасибо, Рич


person Rich    schedule 20.05.2011    source источник
comment
возможный дубликат это   -  person Rayfleck    schedule 20.05.2011


Ответы (1)


Вот пример кода, который распечатает кучу релевантной информации об изображении, а также дамп пиксельных данных изображения. Он будет работать с изображениями с альфа-каналами, а также с изображениями без. Код будет работать даже с изображениями, которые не находятся в цветовом пространстве 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");
    }
}

Вот пример вывода двух изображений, которые я пробовал. Они оба 5x3 rgb. Изображение «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)
person fieldtensor    schedule 20.05.2011
comment
bytes[row * bpr + col * bytes_per_pixel] В прошлый раз, когда я писал подобный код (правда, очень давно, на устаревшем по сегодняшним стандартам оборудовании), выполнение этого для каждого пикселя было медленным для больших изображений. Увеличение указателя и использование сложения, а не умножения будет быстрее. Вы можете подумать, что в этом нет ничего страшного, но большое изображение имеет значение, эти пиксели складываются быстро. - person asveikau; 19.11.2012
comment
Спасибо за это, полезно. Я заметил, что вы печатаете ширину как высоту и наоборот. - person user441669; 30.12.2012
comment
Не забудьте подробно изучить AlphaInfoMask, некоторые графические функции суетливы, чтобы принять их. - person Nick; 11.02.2013