2013-01-18 5 views
14

Ich habe eine UIImage, die von einem CIImage mit geladen wird:eine CGImage von CIImage Ersten

tempImage = [UIImage imageWithCIImage:ciImage];

Das Problem ist, ich brauche tempImage zu einer bestimmten CGRect und dem einzigen Weg zu beschneiden Ich weiß, wie zu tun Dies ist mit CGImage. Das Problem ist, dass in der iOS 6.0-Dokumentation ich dies gefunden:

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

A. von CIImage zu CGImage Wie konvertiert? Ich verwende diesen Code, aber ich habe ein Speicherleck (und kann nicht verstehen, wo):

+(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

Sie erwähnen, dass Sie das CGImage benötigen, um die Ernte durchzuführen. Wie Joris Kluivers sagte, können Sie die Bildausschnitte ohne CGImage verwenden, indem Sie den CICrop-Filter auf dem CIImage verwenden. Gibt es noch etwas, für das Sie das CGImage benötigen? Wenn ja, was? –

+0

Haben Sie in Bezug auf das Speicherleck auch versucht, die Leaks-Vorlage von Instruments zu verwenden? Zwischen dem Leaks-Instrument und dem Heapshot-Tool des Zuordnungsinstruments sollten Sie in der Lage sein, herauszufinden, wo Sie in Ihrer App undicht waren oder Speicher angesammelt haben. –

+0

@PeterHosey Ich tat, und ich fand, dass aus irgendeinem Grund habe ich über 200 Live-Instanzen von CIImage und über 100 von CGImage, die alle von dieser Methode stammen. Ich sehe nur nicht wo – tagyro

Antwort

20

Siehe CIContext Dokumentation für createCGImage:fromRect:

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

Aus einer Antwort auf eine ähnliche Frage: https://stackoverflow.com/a/10472842/474896

Auch, weil Sie eine CIImage zu beginnen, können Sie CIFilter verwenden, um Ihr Bild tatsächlich zu beschneiden.

+2

Könnte und sollte: Core Image ist * extrem * faul, in dem 'createCGImage: fromRect:' (oder jede andere Methode, die fertige Pixel erfordert) ist der Punkt, an dem alle Arbeit tatsächlich erledigt wird; Bis dahin hat keine eigentliche Filterung stattgefunden. Das Zuschneiden mit einem Core Image-Filter spart tatsächlich eine Menge Arbeit (proportional zu dem, wie viel Sie ausschneiden), da Sie dann nicht nach den abgeschnittenen Pixeln gefragt werden, so dass sie überhaupt nicht gerendert werden. (Der andere Weg wäre natürlich, das Beschneidungsrechteck für das 'fromRect:' zu übergeben, was den gleichen Effekt hat.) –

+0

@Joris Kluivers danke für die Antwort aber ich bekomme das gleiche Ergebnis: CIContext * context = [CIContext new]; CGImageRef ref = [Kontext createCGImage: ciImage fromRect: [ciImage Umfang]]; tempImage = [UIImage imageWithCGImage: ref]; CGImageRelease (ref); NSLog (@ "tempBild:% f% f", tempImage.size.width, tempImage.size.height); outputs: tempImage: 0.000000 0.000000 – tagyro

+0

@PeterHosey Sie haben recht, aber leider habe ich die Crop-Informationen nicht, wenn ich die Konvertierung mache, und ich muss die Konvertierung vorher durchführen, weil ich CGImage verwende. Danke – tagyro

-3

Nach einigen googeln fand ich diese Methode, die eine CMSampleBufferRef zu einem CGImage konvertiert:

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

(aber ich schloss die Registerkarte, damit ich weiß nicht, wo ich es von bekam)

+1

Es handelt sich hierbei nicht um einen CI-Fehler. Also, wirklich beabsichtigten Sie, eine CGImage von einem CMSampleBuffer die ganze Zeit zu erstellen, und der CImage war nur das Mittel, das Sie im Sinn hatten, das zu tun? –

+0

@PeterHosey Wie Sie wahrscheinlich abziehen können, bekomme ich den SampleBuffer von 'AVCaptureOutput' und ich benutze den CImage für Gesichtserkennung. Das letzte Ziel ist es, nur das Gesicht aus dem aufgenommenen Bild zu schneiden und weil ich zu dumm bin, um CImage und CGImage zu verstehen, suchte ich nach einer anderen Lösung: CMSampleBuffer ps. Ich habe die Antwort von Joris angenommen, weil das die richtige Antwort auf meine Frage ist. – tagyro

+0

Ah, Gesichtserkennung. Das ist legitim. Haben Sie sich AVCaptureMetadataOutput und AVMetadataFaceObject schon angesehen? –

3

Swift 3.1

Hier ist eine nette kleine Funktion eines CIImage-CGImage in Swift zu konvertieren.

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