How to create grayscale CGImage from iPhone camera?
I want to create a grayscale CGImage from iPhone camera data. I am using AVFoundation and set the pixel format type to
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
If I understood correctly, I could create a grayscale image from the Y component, so I applied the delegation method like this:
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
CVPixelBufferLockBaseAddress(imageBuffer, 0)
let yPlanBufferAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)
let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)
let data = NSData(bytes: yPlanBufferAddress, length: width * height)
let colorSpace = CGColorSpaceCreateDeviceGray()
let dataProvider = CGDataProviderCreateWithCFData(data)
let imageRef = CGImageCreate(width, height, 8, 8, width * 8, colorSpace, CGBitmapInfo.ByteOrderDefault, dataProvider, nil, false, kCGRenderingIntentDefault)
let img = UIImage(CGImage: imageRef)
CVPixelBufferUnlockBaseAddress(imageBuffer, 0)
delegate?.cameraController(self, didCreateImage: img)
}
but I am getting weird images:
Any ideas?
You should get the 'bytesPerRow' for the Y plane and pass it to CGImageCreate.
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane( w, 0 );
let imageRef = CGImageCreate(
width
, height
, 8
, 8
, bytesPerRow
I used to use a framework called the GPU image from BradLarson , which is pretty good at creating custom filters. They also have predefined filters that you can use. It works pretty fast.
Try it!
The easiest way to create a grayscale image is to use CIFliter
it like this, just play with the values to get the desired level of effect. You can also place multiple filters in a row to have even more control over things like contrast, exposure, color, etc.
+ (UIImage *)makeBW:(UIImage *)imageToConvert
{
CIImage *beginImage = [CIImage imageWithCGImage:[imageToConvert CGImage]];
CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls"
keysAndValues:
kCIInputImageKey, beginImage,
@"inputBrightness", [NSNumber numberWithFloat:0.0],
@"inputContrast", [NSNumber numberWithFloat:1.12],
@"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage;
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
UIImage *newImg = [UIImage imageWithCGImage:cgiimage];
CGImageRelease(cgiimage);
return newImg;
}