2010-06-30 28 views
22

Ich versuche, Video von einer Kamera zu erfassen. Ich habe die captureOutput:didOutputSampleBuffer: Callback zu triggern und es gibt mir einen Beispielpuffer, den ich dann in eine CVImageBufferRef konvertieren. Ich versuche dann, das Bild in eine UIImage konvertieren, die ich dann in meiner App anzeigen kann.Wie konvertiert man einen CVImageBufferRef zu UIImage

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    /*Lock the image buffer*/ 
    CVPixelBufferLockBaseAddress(imageBuffer,0); 
    /*Get information about the image*/ 
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    /*We unlock the image buffer*/ 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    /*Create a CGImageRef from the CVImageBufferRef*/ 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

    /*We release some components*/ 
    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace); 

    /*We display the result on the custom layer*/ 
    /*self.customLayer.contents = (id) newImage;*/ 

    /*We display the result on the image view (We need to change the orientation of the image so that the video is displayed correctly)*/ 
    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight]; 
    self.capturedView.image = image; 

    /*We relase the CGImageRef*/ 
    CGImageRelease(newImage); 
} 

der Code scheint gut, bis der Anruf CGBitmapContextCreate aufzuarbeiten. es gibt immer einen Zeiger NULL zurück. also funktioniert nichts vom Rest der Funktion. egal, was ich zu übergeben scheint, die Funktion gibt null zurück. ich habe keine Idee warum.

Antwort

19

Die Art und Weise, die auf dem baseaddress sind vorbei geht davon aus, dass die Bilddaten in Form

ACCC

ist (wobei C einige Farbkomponente ist, R G || || B).

Wenn Sie Ihre AVCaptureSession so eingerichtet haben, dass die Videobilder im nativen Format aufgenommen werden, erhalten Sie höchstwahrscheinlich die Videodaten im planaren YUV420-Format zurück. (Siehe: link text) Um das zu tun, was Sie hier tun möchten, sollten Sie am ehesten angeben, dass Sie die in kCVPixelFormatType_32RGBA erfassten Videoframes verwenden möchten. Apple empfiehlt, dass Sie die Videobilder in kCVPixelFormatType_32BGRA erfassen, wenn Sie sie überhaupt in einem nicht-planaren Format erfassen. Die Gründe dafür sind nicht angegeben, aber ich kann vernünftigerweise annehmen, dass dies auf Leistungsüberlegungen zurückzuführen ist.

Vorbehalt: Ich habe dies nicht getan, und bin unter der Annahme, dass der Zugriff auf die CVPixelBufferRef Inhalte wie folgt ist eine sinnvolle Möglichkeit, das Bild zu erstellen. Ich kann nicht dafür bürgen, dass das wirklich funktioniert, aber ich kann/kann Ihnen sagen, dass die Art und Weise, wie Sie Dinge jetzt gerade tun, aufgrund des Pixelformats, das Sie (wahrscheinlich) die Videoframes erfassen, zuverlässig nicht funktionieren wird.

+8

Ganz die richtige Antwort, so einfach als Kommentar: kCVPixelFormatType_32RGBA ist als Capture-Format auf dem iPhone 4 zumindest in iOS 4.2.1 nicht verfügbar . BGRA ist vollständig implementiert. – Tommy

2

Benjamin Loulier schrieb einen wirklich guten Beitrag über die Ausgabe eines CVImageBufferRef unter Berücksichtigung der Geschwindigkeit mit mehreren Ansätzen.

Sie auch ein funktionierendes Beispiel auf Github finden;)

Wie wäre es in der Zeit zurück? ;) Hier gehts: http://web.archive.org/web/20140426162537/http://www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera

+0

Dieser Blogeintrag scheint weg zu sein. – Brigham

+0

@Brigham - nur der Link aktualisiert. Bitte. – maaalex

10

Wenn Sie einfach eine CVImageBufferRef in UIImage konvertieren müssen, scheint es viel schwieriger als es sein sollte. Im Wesentlichen müssen Sie in CIImage, dann CGImage, THEN UIImage konvertieren. Ich wünschte, ich könnte dir sagen, warum. Wer weiß.

-(void) screenshotOfVideoStream:(CVImageBufferRef)imageBuffer 
{ 
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer]; 
    CIContext *temporaryContext = [CIContext contextWithOptions:nil]; 
    CGImageRef videoImage = [temporaryContext 
          createCGImage:ciImage 
          fromRect:CGRectMake(0, 0, 
          CVPixelBufferGetWidth(imageBuffer), 
          CVPixelBufferGetHeight(imageBuffer))]; 

    UIImage *image = [[UIImage alloc] initWithCGImage:videoImage]; 
    [self doSomethingWithOurUIImage:image]; 
    CGImageRelease(videoImage); 
} 

Diese besondere Methode für mich gearbeitet, wenn ich H.264 Video wurde Umwandeln des VTDecompressionSession Rückruf mit der CVImageBufferRef bekommen (aber es sollte für jeden CVImageBufferRef arbeiten). Ich habe iOS 8.1, XCode 6.2 benutzt.

+2

Sie brauchen nicht alle diese Schritte.Sie können [[UIImage alloc] initWithCIImage ...] anrufen –

+1

Ich habe versucht, das zu tun, aber es hat nicht für mich funktioniert und ich habe nur ein solides weißes Bild. Aus irgendeinem Grund brauchte ich den CIContext, um dies zu tun (wie [diese Antwort] (http://stackoverflow.com/a/7788510/3841734)). Vielleicht war es nur mein spezifischer Fall, dass ich es brauchte. Ich werde ehrlich sein, ich verstehe nicht das ganze Bildformat und Kontext-Zeug. –

+1

könnte all dies in einem @autorelease-Block umgeben wollen ... – theprojectabot

1

können Sie direkt anrufen:

self.yourImageView.image=[[UIImage alloc] initWithCIImage:[CIImage imageWithCVPixelBuffer:imageBuffer]]; 
+0

Dies funktioniert, scheint aber langsamer zu sein als Livius Storks –

Verwandte Themen