MichalMoskala
MichalMoskala

Reputation: 927

How to create grayscale CGImage from iPhone Camera?

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: enter image description here

Any ideas?

Upvotes: 5

Views: 939

Answers (3)

Satachito
Satachito

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

rmp
rmp

Reputation: 3503

The easiest way to create a grayscale image is to use a CIFliterlike 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

Dheeraj Jami
Dheeraj Jami

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

Related Questions