2013-01-18 38 views
14

得到一个CGImage我有从CIImage装有一个UIImage:从CIImage

tempImage = [UIImage imageWithCIImage:ciImage];

的问题是我需要裁剪tempImage到特定CGRect,我知道怎么做的唯一途径这是通过使用CGImage。 问题是,iOS的6.0文档中,我发现这个:

CGImage
If the UIImage object was initialized using a CIImage object, the value of the property is NULL.

A.如何转换CIImage到CGImage? 我使用这个代码,但我有内存泄漏(而不能明白的地方):

+(UIImage*)UIImageFromCIImage:(CIImage*)ciImage { 
    CGSize size = ciImage.extent.size; 
    UIGraphicsBeginImageContext(size); 
    CGRect rect; 
    rect.origin = CGPointZero; 
    rect.size = size; 
    UIImage *remImage = [UIImage imageWithCIImage:ciImage]; 
    [remImage drawInRect:rect]; 
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    remImage = nil; 
    ciImage = nil; 
    // 
    return result; 
} 
+0

您提到您需要使用CGImage进行裁剪。正如Joris Kluivers所说,您可以通过在CIImage上使用CICrop过滤器来在没有CGImage的情况下进行裁剪。还有什么您需要CGImage的?如果是这样,什么? –

+0

另外,关于内存泄漏,您是否尝试使用Instruments的泄漏模板?在Leaks工具和Allocations工具的Heapshot工具之间,您应该能够确定您的应用程序泄漏或累积内存的位置。 –

+0

@PeterHosey @PeterHosey我做过了,我发现出于某种原因,我有超过200个CIImage实例和超过100个CGImage,都来自这种方法。我只是看不到在哪里 – tagyro

回答

20

CIContext文档createCGImage:fromRect:

CGImageRef img = [myContext createCGImage:ciImage fromRect:[ciImage extent]]; 

从回答类似的问题: https://stackoverflow.com/a/10472842/474896

此外,既然您有一个CIImage开始,您可以使用CIFilter实际上裁剪您的图像。

+2

可能和应该:核心图像*非常*懒惰,因为'createCGImage:fromRect:'(或任何其他需要完成像素的方法)是实际完成所有工作的点;在此之前没有发生实际的过滤。使用核心图像过滤器进行裁剪实际上会节省相当多的工作量(与无论你裁剪多少都成比例),因为那样你就不会要求裁剪出像素,所以它们根本不会被渲染。 (当然,另一种方法是通过'fromRect:'的剪裁矩形,这将产生相同的效果。) –

+0

@Joris Kluivers谢谢你的回答,但我得到了同样的结果: CIContext * context = [CIContext new]; CGImageRef ref = [context createCGImage:ciImage fromRect:[ciImage extent]]; tempImage = [UIImage imageWithCGImage:ref]; CGImageRelease(ref); NSLog(@“tempImage:%f%f”,tempImage.size.width,tempImage.size.height); 输出:tempImage:0.000000 0.000000 – tagyro

+0

@PeterHosey你是对的,但不幸的是,当我正在进行转换时,我没有裁切信息,因为我使用CGImage,所以我需要先进行转换。谢谢 – tagyro

-3

一些google搜索后,我发现这个方法,一个CMSampleBufferRef转换成CGImage:

+ (CGImageRef)imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer // Create a CGImageRef from sample buffer data 
{ 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer,0);  // Lock the image buffer 

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); // Get information of the image 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 
    CGContextRelease(newContext); 

    CGColorSpaceRelease(colorSpace); 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 
    /* CVBufferRelease(imageBuffer); */ // do not call this! 

    return newImage; 
} 

(但我关闭的标签,所以我不知道我在哪里,从得到它)

+1

这根本不涉及CIImage。所以,你真的打算从CMSampleBuffer一直创建一个CGImage,而CIImage只是你想要做的那种手段吗? –

+0

@PeterHosey正如你可能可以扣除我从'AVCaptureOutput'获取sampleBuffer,并且我正在使用CIImage进行人脸检测。最终目标是从捕获的图像中裁剪出脸部,并且由于我太愚蠢无法理解CIImage和CGImage,我搜索了另一个解决方案:CMSampleBuffer ps。我接受了Joris的答案,因为这是我的问题的正确答案。 – tagyro

+0

啊,人脸检测。这是合法的。你看过AVCaptureMetadataOutput和AVMetadataFaceObject了吗? –

3

斯威夫特3.1

这是一个不错的小功能,可以将Swift中的CIImage转换为CGImage

func convertCIImageToCGImage(inputImage: CIImage) -> CGImage? { 
    let context = CIContext(options: nil) 
    if let cgImage = context.createCGImage(inputImage, from: inputImage.extent) { 
     return cgImage 
    } 
    return nil 
}