Подтвердить что ты не робот

Получение данных пикселя 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 >

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

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

Спасибо, Рич

4b9b3361

Ответ 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)