Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color distortion in CGImageCreate

I am trying to build a image capture for my iOS app, but I keep getting color distortion on my CGImage result. Here is the camera preview, right colors.

enter image description here

Cola is red, all is well.

When I run my snapshot code, I get this :

enter image description here

Cola is blue... where did this come from?

I tried messing with some of the parameters, but only end up getting no image at all. Here is my snapshot code :

int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = [cameraVideo bufRowBytes];
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, [cameraVideo bufDataPtr], [cameraVideo bufWidth]*[cameraVideo bufHeight]*4, NULL);

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentPerceptual;

    CGImageRef imageRef = CGImageCreate( [cameraVideo bufWidth], [cameraVideo bufHeight], bitsPerComponent, bitsPerPixel,
                                        bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    CGColorSpaceRelease(colorSpaceRef);

I am at my wits end, so if anyone can see what I am doing wrong, please let me know.

FIXED

Here is the final code:

if (cameraVideo.ARPixelFormat == kCVPixelFormatType_32ARGB) {
    bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst;
} else {
    bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;
}
like image 746
Nils Munch Avatar asked Mar 29 '12 07:03

Nils Munch


1 Answers

It looks like your R (red) and B (blue) channels are swapped. The camera is filling the buffer in BGR order, but you're telling the CGImage that the data is in RGB order. I believe you control this using one of the kCGBitmapByteOrder... constants in your CGBitmapInfo. Try setting bitmapInfo like this:

CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;

If that doesn't work, try the other kCGBitmapByteOrder... constants (kCGBitmapByteOrder32Little, kCGBitmapByteOrder16Big, kCGBitmapByteOrder16Little).

EDIT

Apple's SquareCam sample project has a file named SquareCam/SqareCamViewController.m (yes, “Square” is misspelled in the filename). It contains this code:

    sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer );
    if ( kCVPixelFormatType_32ARGB == sourcePixelFormat )
        bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst;
    else if ( kCVPixelFormatType_32BGRA == sourcePixelFormat )
        bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;
    else
        return -95014; // only uncompressed pixel formats

You might want to do the same thing.

like image 168
rob mayoff Avatar answered Nov 10 '22 18:11

rob mayoff