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