J'essaie d'utiliser le nouveau AVFoundation framework
pour prendre des photos avec l'iPhone.
Avec un bouton appuyez sur cette methos est appelée. Je peux entendre le son de l'obturateur mais je ne peux pas voir la sortie du journal. Si j'appelle cette méthode plusieurs fois, l'aperçu de la caméra se fige.
Existe-t-il un tutoriel sur l'utilisation de captureStillImageAsynchronouslyFromConnection
?
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:
[[self stillImageOutput].connections objectAtIndex:0]
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer,
NSError *error) {
NSLog(@"inside");
}];
- (void) initCapture { AVCaptureDeviceInput * captureInput = [AVCaptureDeviceInput [.________] AVCaptureVideoDataOutput * captureOutput = [[AVCaptureVideoDataOutput alloc] init]; CaptureOutput.alwaysDiscardsLateVideoFrames = YES; dispatch_queue_t file d'attente; queue = dispatch_queue_create ("cameraQueue", NULL); [captureOutput setSampleBufferDelegate: self file: queue]; dispatch_release (file d'attente); NSString * clé = (NSString *) kCVPixelBufferPixelFormatTypeKey; NSNumber * value = [NSNumber numberWithUnsignedInt: kCVPixelFormatType_32BGRA]; NSDictionary * videoSettings = [NSDictionary dictionaryWithObject: valeur pourKey: clé]; [captureOutput setVideoSettings: videoSettings]; self.captureSession = [[AVCaptureSession alloc] init]; self.captureSession.srespreset = AVCaptureSessionPresetLow; [self.captureSession addInput : captureInput]; [self.captureSession addOutput: captureOutput]; self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession: self.captureSession]; [auto.prevLayer setOrientation: AVCaptureVideoOrientationLandscapeLeft]; self.prevLayer.frame = CGRectMake (0.0, 0.0, 480.0, 320.0); self.prevLayer.frame = AVL. [self.view.layer addSublayer: self.prevLayer]; // Configurer les sorties de fichier par défaut AVCaptureStillImageOutput * _stillImageOutput = [[[[AVCaptureStillImageOutput all] init] autorelease]; NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVide oCodecJPEG, AVVideoCodecKey, nil]; [_stillImageOutput setOutputSettings: paramètres de sortie]; if ([self.captureSession canAddOutput: stillImageOutput]) { [self.captureSession addOutput: stillImageOutput]; } [Self.captureSession commitConfiguration]; [self.captureSession startRunning]; }
Nous avons eu ce problème lorsque la version 4.0 était encore en version bêta. J'ai essayé pas mal de choses. Voici:
J'ai fini par capturer des images vidéo. Le bouton "prendre une photo" définit simplement un drapeau; dans le rappel d'image vidéo, si l'indicateur est défini, il renvoie l'image vidéo au lieu d'un UIImage *. C’était suffisant pour nos besoins en traitement d’images - "prendre une photo" existe en grande partie afin que l’utilisateur puisse obtenir une réponse négative (et une option pour soumettre un rapport de bogue); nous ne voulons pas réellement d'images 2/3/5 mégapixels, car leur traitement prend beaucoup de temps.
Si les images vidéo ne sont pas suffisantes (par exemple, si vous souhaitez capturer des images du viseur entre des captures d’images haute résolution), je commencerai par vérifier si elles ont été corrigées à l’aide de plusieurs sessions AVCapture, car c’est le seul moyen de définir les deux paramètres prédéfinis.
Cela vaut probablement le coup de rapporter un bogue. J'ai déposé un bogue lors du lancement de la version 4.0 de GM; Apple m'a demandé un exemple de code, mais j'avais alors décidé d'utiliser la solution de contournement d'image vidéo et j'avais une version à publier.
De plus, le préréglage "bas" est très basse résolution (et donne un aperçu vidéo basse résolution et basse fréquence d'images). J'irais pour 640x480 si disponible, retombant à moyen sinon.
Après beaucoup d'essais et d'erreurs, j'ai trouvé comment faire.
Astuce: les documents officiels d'Apple sont - tout simplement - faux. Le code qu'ils vous donnent ne fonctionne pas réellement.
Je l'ai écrit ici avec des instructions étape par étape:
Beaucoup de code sur le lien, mais en résumé:
-(void) viewDidAppear:(BOOL)animated
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
CALayer *viewLayer = self.vImagePreview.layer;
NSLog(@"viewLayer = %@", viewLayer);
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.vImagePreview.bounds;
[self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(@"ERROR: trying to open camera: %@", error);
}
[session addInput:input];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
}
-(IBAction) captureNow
{
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections)
{
for (AVCaptureInputPort *port in [connection inputPorts])
{
if ([[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
NSLog(@"about to request a capture from: %@", stillImageOutput);
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
CFDictionaryRef exifAttachments = CMGetAttachment( imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments)
{
// Do something with the attachments.
NSLog(@"attachements: %@", exifAttachments);
}
else
NSLog(@"no attachments");
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.vImage.image = image;
}];
}
Cela a été une aide précieuse - j'ai été coincé dans les mauvaises herbes pendant un bon bout de temps en essayant de suivre l'exemple d'AVCam.
Voici un projet complet avec mes commentaires qui expliquent ce qui se passe. Ceci illustre comment utiliser le gestionnaire de capture avec plusieurs sorties. Dans cet exemple, il existe deux sorties.
Le premier est la sortie d'image fixe de l'exemple ci-dessus.
La seconde fournit un accès image par image à la vidéo sortant de la caméra. Vous pouvez ajouter plus de code pour créer quelque chose d’intéressant avec les images si vous le souhaitez. Dans cet exemple, je mets à jour un compteur de trames sur l’écran depuis le rappel du délégué.
Apple a quelques notes et exemples de code à ce sujet:
QA1702: Comment capturer des images vidéo de l'appareil photo sous forme d'images avec AV Foundation
Vous devriez utiliser la réponse de Adam , mais si vous utilisez Swift (comme beaucoup le font probablement de nos jours), voici un portage Swift 1.2 de son code:
import ImageIO
private var stillImageOutput: AVCaptureStillImageOutput!
stillImageOutput
avant captureSession.startRunning()
:Comme ça:
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
captureSession.addOutput(stillImageOutput)
Puis utilisez ce code pour capturer une image:
private func captureImage() {
var videoConnection: AVCaptureConnection?
for connection in stillImageOutput.connections as! [AVCaptureConnection] {
for port in connection.inputPorts {
if port.mediaType == AVMediaTypeVideo {
videoConnection = connection
break
}
}
if videoConnection != nil {
break
}
}
print("about to request a capture from: \(stillImageOutput)")
stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) { (imageSampleBuffer: CMSampleBuffer!, error: NSError!) -> Void in
let exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, nil)
if let attachments = exifAttachments {
// Do something with the attachments
print("attachments: \(attachments)")
} else {
print("no attachments")
}
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer)
let image = UIImage(data: imageData)
// Do something with the image
}
}
Tout cela suppose que vous ayez déjà une configuration AVCaptureSession
et que vous ayez juste besoin de prendre une photo, comme moi.