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

Any ideas?

+3


source to share


3 answers


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

      

+2


source


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!

-1


source


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;
}

      

-1


source







All Articles