2010-10-01 20 views
10

Voglio convertire un oggetto UIImage in un oggetto CVPixelBufferRef, ma non ho assolutamente alcuna idea. E non riesco a trovare alcun codice di esempio che faccia qualcosa di simile.Converti UIImage in CVPixelBufferRef

Qualcuno può aiutarmi? THX in anticipo!

C YA

+0

Vedi https://stackoverflow.com/a/44475334/1418457 – onmyway133

risposta

0

Un CVPixelBufferRef è ciò che il video nucleo utilizza per ingresso telecamera.

È possibile creare bitmap di pixel simili dalle immagini utilizzando CGBitmapContextCreate e quindi disegnare l'immagine nel contesto bitmap.

+1

Quello che voglio fare è quello di aggiungere singoli fotogrammi per un filmato utilizzando la Fondazione AV . Questo verrà fatto usando la classe AVAssetWriterInputPixelBufferAdaptor. Ma questa classe si aspetta oggetti CVPixelBufferRef. Quindi, come posso convertire una UIImage in un oggetto CVPixelBufferRef? – Nuker

1

Google è sempre tuo amico. Ricerca di "CVPixelBufferRef" il primo risultato porta a this snippet da snipplr:

- (CVPixelBufferRef)fastImageFromNSImage:(NSImage *)image{ 
CVPixelBufferRef buffer = NULL; 

// config 
size_t width = [image size].width; 
size_t height = [image size].height; 
size_t bitsPerComponent = 8; // *not* CGImageGetBitsPerComponent(image); 
CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
CGBitmapInfo bi = kCGImageAlphaNoneSkipFirst; // *not* CGImageGetBitmapInfo(image); 
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 

// create pixel buffer 
CVPixelBufferCreate(kCFAllocatorDefault, width, height, k32ARGBPixelFormat, (CFDictionaryRef)d, &buffer); 
CVPixelBufferLockBaseAddress(buffer, 0); 
void *rasterData = CVPixelBufferGetBaseAddress(buffer); 
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(buffer); 

// context to draw in, set to pixel buffer's address 
CGContextRef ctxt = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, cs, bi); 
if(ctxt == NULL){ 
    NSLog(@"could not create context"); 
    return NULL; 
} 

// draw 
NSGraphicsContext *nsctxt = [NSGraphicsContext graphicsContextWithGraphicsPort:ctxt flipped:NO]; 
[NSGraphicsContext saveGraphicsState]; 
[NSGraphicsContext setCurrentContext:nsctxt]; 
[image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy]; 
[NSGraphicsContext restoreGraphicsState]; 

CVPixelBufferUnlockBaseAddress(buffer, 0); 
CFRelease(ctxt); 

return buffer; 
} 

Non ho idea se questo funziona per niente, però. (Il tuo chilometraggio potrebbe diffidare :)

+3

La domanda riguardava la conversione di un 'UIImmagine' in' CVPixelBufferRef', non 'NSImage' – srgtuszy

+1

La riga su size_t bytesPerRow = CVPixelBufferGetBytesPerRow (buffer); è quello che ha fatto il trucco per me.Tutti gli altri esempi di codice utilizzavano una costante magica che si è rivelata errata su questo dispositivo, essendo in grado di determinare il valore reale come chiave. Grazie. –

1

È possibile utilizzare Core Image per creare un CVPixelBuffer da un UIImage.

// 1. Create a CIImage with the underlying CGImage encapsulated by the UIImage (referred to as 'image'): 

CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage]; 

// 2. Create a CIContext: 

Context *ciContext = [CIContext contextWithCGContext:UIGraphicsGetCurrentContext() options:nil]; 

// 3. Render the CIImage to a CVPixelBuffer (referred to as 'outputBuffer'): 

[self.ciContext render:img toCVPixelBuffer:outputBuffer]; 

AVFoundation fornisce classi che leggono i file video (chiamati attività) e dalla produzione di altri oggetti AVFoundation che gestiscono (o hanno già letto) attività nei buffer di pixel. Se questa è la tua unica preoccupazione, troverai ciò che stai cercando nel codice di esempio dell'estensione per l'editing di foto campione.

Se la sorgente è generata da una serie di oggetti UIImage (forse non c'era alcun file sorgente e si sta creando un nuovo file dal contenuto generato dall'utente), il codice di esempio fornito sopra sarà sufficiente.

NOTA: non è il mezzo più efficiente né l'unico mezzo per convertire un UIImage in un CVPixelBuffer; ma, è DI LONTANO il mezzo più facile. Usare Core Graphics per convertire un UIImage in un CVPixelBuffer richiede molto più codice per impostare gli attributi, come la dimensione del buffer dei pixel e lo spazio colore, che Core Image si prende cura di te.

6

Ci sono diversi modi per farlo, quelle funzioni convertono un buffer di pixel da un CGImage. UImage è un wrapper intorno a CGImage, quindi per ottenere un CGImage è sufficiente chiamare il metodo .CGImage.
Gli altri modi sono anche creare un CIImage dal buffer (già pubblicato) o utilizzare il framework Accelerate, che è probabilmente il più veloce ma anche il più difficile.

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image 
{ 
    NSDictionary *options = @{ 
           (NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES, 
           (NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES, 
           }; 

    CVPixelBufferRef pxbuffer = NULL; 
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image), 
         CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
         &pxbuffer); 
    if (status!=kCVReturnSuccess) { 
     NSLog(@"Operation failed"); 
    } 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image), 
               CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, CGImageGetHeight(image)); 
    CGContextConcatCTM(context, flipVertical); 
    CGAffineTransform flipHorizontal = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0); 
    CGContextConcatCTM(context, flipHorizontal); 

    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 
    return pxbuffer; 
} 
+0

perché dovresti capovolgere verticale e orizzontale? –

+0

@MaxiMus Poiché UIKit e core grphics hanno sistemi di coordinate diversi https://developer.apple.com/library/content/documentation/2DDrawings/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html – Andrea

+0

Le coordinate y si, ma non la x. ..? –

0

molto tardi però, ma per chi ha bisogno.

// call like this 
    CVPixelBufferRef videobuffer = [self pixelBufferFromCGImage:yourImage.CGImage]; 

// metodo che converte

-(CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image{ 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 
    CVPixelBufferRef pxbuffer = NULL; 
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, videoSize.width, videoSize.height, 
              kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)options, &pxbuffer); 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 
    NSParameterAssert(pxdata != NULL); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, videoSize.width, videoSize.height, 8, 4*videoSize.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 
    CGContextConcatCTM(context, CGAffineTransformIdentity); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
}