2010-08-03 12 views
13

Sto tentando di emulare l'animazione visualizzata nell'applicazione fotocamera predefinita, in cui un'istantanea del mirino della fotocamera è animata nell'angolo del display delle app.AVCaptureVideoPreviewLayer: acquisizione di un'istantanea

L'AVCaptureVideoPreviewLayer oggetto che contiene la chiave per risolvere questo problema non è molto aperto a questi requisiti: cercando di creare una copia di esso in un nuovo livello con ..

- (id)initWithLayer:(id)layer 

.. restituisce un vuoto strato, senza l'istantanea dell'immagine, quindi chiaramente qui c'è un po 'di magia più profonda.

I tuoi indizi/boos sono i benvenuti.

M.

risposta

22

affrontare gli stessi mali, da un angolo leggermente diverso.

Qui ci sono le possibili soluzioni, che nessuno è troppo grande IMO:

  • È possibile aggiungere a un AVCaptureSession sia un AVCaptureStillImageOutput e un AVCaptureVideoDataOutput. Quando si imposta la sessionPreset-AVCaptureSessionPresetHigh potrai iniziare a ricevere fotogrammi dalle API, e quando si passa a AVCaptureSessionPresetPhoto si può prendere immagini reali. Quindi, subito prima di scattare la foto, puoi passare al video, ottenere una cornice e poi tornare alla videocamera. Un avvertimento importante è che ci vuole un "lungo" tempo (un paio di secondi) affinché la telecamera passi dalla videocamera alla videocamera.

  • Un'altra opzione sarebbe quella di utilizzare solo l'uscita della telecamera (AVCaptureStillImageOutput), e utilizzare UIGetScreenImage per ottenere una cattura dello schermo del telefono. Potresti quindi ritagliare i controlli e lasciare solo l'immagine. Questo diventa complicato se stai mostrando i controlli dell'interfaccia utente sull'immagine. Inoltre, in base al post this, Apple ha iniziato a rifiutare le app che utilizzano questa funzione (era sempre incerto).

  • Oltre a questi ho anche provato a giocare con AVCaptureVideoPreviewLayer. C'è il post this per salvare un UIView o CALayer su una UIImage. Ma tutto produce immagini chiare o bianche. Ho provato ad accedere al livello, al livello della vista, al superleggero, allo presentationLayer, al modello , allo modelLayer, ma senza risultati. Immagino che i dati in AVCaptureVideoPreviewLayer siano molto interni e non facciano parte dell'infrastruttura di livello normale.

Spero che questo aiuti, Odiato.

+0

quale è meglio Oded Ben Dov nei tre precedenti. Dai il miglior suggerimento \ –

0

ci sono 2 modi per afferrare fotogrammi dell'anteprima .. AVCaptureVideoDataOutput & AVCaptureStillImageOutput :)

è la vostra sessione di cattura è configurato per afferrare fotogrammi video, quindi rendere il vostro livello con il CGImage da una cornice scelta.se è impostato per le immagini fisse, attendi fino a ottenere il fermo immagine e crea il tuo livello da una versione ridotta di quel cgimage. se non hai ancora un output sulla tua sessione, dovrai aggiungerne uno.

5

Penso che si dovrebbe aggiungere un AVCaptureVideoDataOutput alla sessione corrente con:

AVCaptureVideoDataOutput *videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 
videoOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) }; 
[session addOutput:videoOutput]; 

dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL); 
[videoOutput setSampleBufferDelegate:self queue:queue]; 
dispatch_release(queue); 

Quindi, implementare il metodo delegato qui sotto per ottenere l'istantanea dell'immagine:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 
    // Add your code here that uses the image. 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     _imageView.image = image; 
    }); 
} 

Questo consumerà la memoria e ridurre le prestazioni dell'app. Per migliorare, si può anche ottimizzare il vostro AVCaptureVideoDataOutput con:

videoOutput.minFrameDuration = CMTimeMake(1, 15); 

È anche possibile utilizzare alwaysDiscardsLateVideoFrames.

+0

Piccola nota: 'alwaysDiscardsLateVideoFrames' è' true' per impostazione predefinita – xaphod

-7

A partire da iOS 7, è possibile utilizzare UIView::snapshotViewAfterScreenUpdates per eseguire un'istantanea di UIView avvolgendo AVCaptureVideoPreviewLayer. Questo non è lo stesso di UIGetScreenImage, per cui la tua app verrà respinta.

UIView *snapshot = [self.containerView snapshotViewAfterScreenUpdates:YES]; 

Ricordare il modo vecchio di trasformare una vista in un'immagine. Per qualche motivo ha funzionato su tutto tranne che per le anteprime delle telecamere:

UIGraphicsBeginImageContextWithOptions(self.containerView.bounds.size, NO, [UIScreen mainScreen].scale); 
[self.containerView drawViewHierarchyInRect:self.containerView.bounds afterScreenUpdates:YES]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
+3

snapshotViewAfterScreenUpdates: non funziona su AVCaptureVideoPreviewLayer. –

+0

Molto fastidioso che questo è stato pubblicato, non funziona su un AVCaptureVideoPreviewLayer, solo tempo sprecato –

Problemi correlati