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.

Cola is red, all is well.
When I run my snapshot code, I get this :

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;
}
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With