2013-01-18 14 views
14

Ho un UIImage che viene caricato da un CIImage con:Ottenere un CGImage da CIImage

tempImage = [UIImage imageWithCIImage:ciImage];

Il problema è che ho bisogno di ritagliare tempImage ad una specifica CGRect e l'unico modo che conosco come fare questo è usando CGImage. Il problema è che nella documentazione di iOS 6.0 Ho trovato questo:

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

A. Come convertire da CIImage a CGImage? Sto usando questo codice, ma ho una perdita di memoria (e non riesco a capire dove):

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

Si dice che è necessario il CGImage per fare il raccolto. Come ha detto Joris Kluivers, puoi eseguire il ritaglio senza CGImage usando il filtro CICrop sul CIImage. C'è qualcos'altro che ti serve il CGImage? E allora? –

+0

Inoltre, per quanto riguarda la perdita di memoria, hai provato a usare il modello di Leaks di Instruments? Tra lo strumento Leaks e lo strumento Heapshot dello strumento Allocations, dovresti riuscire a individuare dove nella tua app stavi perdendo o accumulando memoria. –

+0

@PeterHosey Ho fatto e ho scoperto che per qualche ragione ho oltre 200 istanze live di CIImage e oltre 100 di CGImage, tutte originate da questo metodo. Semplicemente non vedo dove – tagyro

risposta

20

Vedere la documentazione CIContext per createCGImage:fromRect:

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

Da una risposta ad una domanda simile: https://stackoverflow.com/a/10472842/474896

Inoltre, poiché si dispone di un CIImage per iniziare, è possibile utilizzare CIFilter per ritagliare effettivamente l'immagine.

+2

Potrebbe e dovrebbe: L'immagine di base è * estremamente * pigra, in quanto 'createCGImage: fromRect:' (o qualsiasi altro metodo che richiede pixel finiti) è il punto in cui tutto il lavoro viene effettivamente eseguito; nessun vero filtraggio è avvenuto prima di allora. Ritagliare con un filtro Core Image in realtà risparmierà un bel po 'di lavoro (proporzionale a quanto si ritagliano), dal momento che non si chiederanno i pixel ritagliati, quindi non verranno renderizzati affatto. (Naturalmente, l'altro modo sarebbe quello di passare il rettangolo di ritaglio per il 'fromRect:', che avrà lo stesso effetto. –

+0

@Joris Kluivers ringrazia per la risposta, ma ottengo lo stesso risultato: CIContext * context = [CIContext new]; CGImageRef ref = [context createCGImage: ciImage fromRect: [ciImage extent]]; tempImage = [UIImage imageWithCGImage: ref]; CGImageRelease (rif); NSLog (@ "tempImage:% f% f", tempImage.size.width, tempImage.size.height); output: tempImage: 0,000000 0,000000 – tagyro

+0

@PeterHosey Hai ragione ma sfortunatamente non ho le informazioni sul ritaglio quando sto facendo la conversione e ho bisogno di fare la conversione prima perché utilizzo CGImage. Grazie – tagyro

-3

Dopo un po 'googling ho trovato questo metodo che converte un CMSampleBufferRef ad un 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; 
} 

(ma ho chiuso la scheda in modo da non so dove l'ho preso da)

+1

Ciò non implica affatto un CIImage. Quindi, in realtà avevi intenzione di creare un CGImage da un CMSampleBuffer per tutto il tempo, e il CIImage era solo il mezzo che avevi in ​​mente per farlo? –

+0

@PeterHosey Come probabilmente è possibile dedurre che sto ricevendo il sampleBuffer da "AVCaptureOutput' e sto utilizzando il CIImage per il rilevamento dei volti. L'obiettivo finale è quello di ritagliare solo la faccia dall'immagine catturata e poiché sono troppo stupido per capire CIImage e CGImage ho cercato un'altra soluzione: CMSampleBuffer ps. Ho accettato la risposta di Joris perché è la risposta giusta alla mia domanda. – tagyro

+0

Ah, rilevamento dei volti. È legittimo. Hai già esaminato AVCaptureMetadataOutput e AVMetadataFaceObject? –

3

Swift 3.1

Ecco una piccola funzione per convertire un CIImage in CGImage in Swift.

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