2013-11-30 3 views
12

У меня есть слой предварительного просмотра, который вытягивается из камеры и работает как следует. Я хотел бы иметь возможность сделать снимок, когда я нажимаю кнопку. Я inited в AVCaptureStillImageOutput так:Как использовать AVCaptureStillImageOutput для съемки изображения

AVCaptureStillImageOutput *avCaptureImg = [[AVCaptureStillImageOutput alloc] init]; 

Тогда я пытаюсь сделать снимок с помощью этого объекта:

[avCaptureImg captureStillImageAsynchronouslyFromConnection:(AVCaptureConnection *) completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { }]; 

мне нужна помощь в том, чтобы сделать снимок и сохранить его в переменной. Спасибо

ответ

27

Вы должны быть уверены, чтобы определить AVCaptureVideoPreviewLayer & добавить его в вид слоя:

AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
[self.view.layer addSublayer:captureVideoPreviewLayer]; 

Это будет подключен к вашему AVCaptureDeviceInput

Вот полное решение:

///////////////////////////////////////////////// 
//// 
//// Utility to find front camera 
//// 
///////////////////////////////////////////////// 
-(AVCaptureDevice *) frontFacingCameraIfAvailable{ 

    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 
    AVCaptureDevice *captureDevice = nil; 

    for (AVCaptureDevice *device in videoDevices){ 

     if (device.position == AVCaptureDevicePositionFront){ 

      captureDevice = device; 
      break; 
     } 
    } 

    // couldn't find one on the front, so just get the default video device. 
    if (!captureDevice){ 

     captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 
    } 

    return captureDevice; 
} 

///////////////////////////////////////////////// 
//// 
//// Setup Session, attach Video Preview Layer 
//// and Capture Device, start running session 
//// 
///////////////////////////////////////////////// 
-(void) setupCaptureSession { 
    AVCaptureSession *session = [[AVCaptureSession alloc] init]; 
    session.sessionPreset = AVCaptureSessionPresetMedium; 

    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
    [self.view.layer addSublayer:captureVideoPreviewLayer]; 

    NSError *error = nil; 
    AVCaptureDevice *device = [self frontFacingCameraIfAvailable]; 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; 
    if (!input) { 
     // Handle the error appropriately. 
     NSLog(@"ERROR: trying to open camera: %@", error); 
    } 
    [session addInput:input]; 

    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; 
    [self.stillImageOutput setOutputSettings:outputSettings]; 

    [session addOutput:self.stillImageOutput]; 

    [session startRunning]; 
} 


///////////////////////////////////////////////// 
//// 
//// Method to capture Still Image from 
//// Video Preview Layer 
//// 
///////////////////////////////////////////////// 
-(void) captureNow { 
    AVCaptureConnection *videoConnection = nil; 
    for (AVCaptureConnection *connection in self.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: %@", self.stillImageOutput); 
    __weak typeof(self) weakSelf = self; 
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 
     UIImage *image = [[UIImage alloc] initWithData:imageData]; 

     [weakSelf displayImage:image]; 
    }]; 
} 
+2

Если вам нужно сделать хорошие снимки, используйте это в настройке: session.sessionPreset = AVCaptureSessionPresetPhoto –

+0

спасибо за это. для ленивых, которые могут последовать, «AVCaptureConnection», вытащенный двойными for-loops, здесь * отличается *, чем «AVCaptureConnection», бегущий в «AVCaptureVideoPreviewLayer». Если вы передадите это соединение «captureStillImageAsynchronouslyFromConnection», вы получите сообщение об ошибке. –

+0

Кстати, обратите внимание, что 'captureStillImageAsynchronously(): вы не должны предполагать, что обработчик завершения будет вызываться в определенном потоке.'. Существует '[weakSelf displayImage: image]', который, вероятно, предполагается запущенным в основном потоке. – SoftDesigner

3
-(void)captureImage:(NSString *)string successCallback:(void (^)(id))successCallback errorCallback:(void (^)(NSString *))errorCallback{ 

    __block UIImage *image; 
    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); 
    [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 

    [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]; 
     image = [[UIImage alloc] initWithData:imageData]; 


     successCallback(image); 
     //UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 
    }]; 


    NSError *error; 
    if (error) { 
     errorCallback(@"error"); 
    }else{ 

    } 
} 
4

для быстрой версии:

@IBAction func capture(sender: AnyObject) { 

    var videoConnection :AVCaptureConnection? 

    if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo){ 
     stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: { (buffer:CMSampleBuffer!, error: NSError!) -> Void in 

      if let exifAttachments = CMGetAttachment(buffer, kCGImagePropertyExifDictionary, nil) { 
       let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer) 
       self.previewImage.image = UIImage(data: imageData) 
       UIImageWriteToSavedPhotosAlbum(self.previewImage.image, nil, nil, nil) 
      } 
     }) 
    } 
} 
+1

Не забудьте добавить 'import ImageIO' для доступа к константе kCGImagePropertyExifDictionary. – FBente

Смежные вопросы