Reputation: 927
I want to create grayscale CGImage from iPhones camera data. I'm using AVFoundation and set pixel format type to
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
If I understand correctly I should be able to create grayscale image from Y component so I have implemented delegate 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'm getting strange images like this:
Any ideas?
Upvotes: 5
Views: 939
Reputation: 5888
You must get 'bytesPerRow' for the Y plane, and supply it to CGImageCreate.
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane( w, 0 );
let imageRef = CGImageCreate(
width
, height
, 8
, 8
, bytesPerRow
Upvotes: 3
Reputation: 3503
The easiest way to create a grayscale image is to use a CIFliter
like this, just play with the values to get the desired level of effect. You can also put several filter in series 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;
}
Upvotes: -1
Reputation: 190
Previously, I have used a framework called GPU Image by BradLarson, pretty amazing one, to make custom filters. They have some predefined filters too, which can be used. Works pretty fast.
Try it out!
Upvotes: -1