2012-04-07 24 views
5

Tôi muốn chụp ảnh ở các trường hợp cụ thể, ví dụ như khi nhấn nút; nhưng tôi không muốn hiển thị bất kỳ màn hình xem trước video nào. Tôi đoán captureStillImageAsynchronouslyFromConnection là những gì tôi cần phải sử dụng cho kịch bản này. Hiện tại, tôi có thể chụp ảnh nếu tôi hiển thị bản xem trước video. Tuy nhiên, nếu tôi loại bỏ mã để hiển thị xem trước, các tai nạn ứng dụng với đầu ra sau đây:Cách chụp ảnh mà không hiển thị xem trước trong iOS

2012-04-07 11: 25: 54,898 imCapWOPreview [748: 707] *** Chấm dứt ứng dụng do uncaught exception 'NSInvalidArgumentException', lý do: '*** - [AVCaptureStillImageOutput captureStillImageAsynchronouslyFromConnection: completionHandler:] - kết nối không hoạt động/không hợp lệ được chuyển.' *** Đầu tiên gọi ném stack: (0x336ee8bf 0x301e21e5 0x3697c35d 0x34187 0x33648435 0x310949eb 0x310949a7 0x31094985 0x310946f5 0x3109502d 0x3109350f 0x31092f01 0x310794ed 0x31078d2d 0x37db7df3 0x336c2553 0x336c24f5 0x336c1343 0x336444dd 0x336443a5 0x37db6fcd 0x310a7743 0x33887 0x3382c) chấm dứt gọi là ném một ngoại lệ (LLĐB)

Vì vậy, đây là thực hiện của tôi:

BIDViewController.h:

#import <UIKit/UIKit.h> 
#import <AVFoundation/AVFoundation.h> 

@interface BIDViewController : UIViewController 
{ 
    AVCaptureStillImageOutput *stillImageOutput; 
} 
@property (strong, nonatomic) IBOutlet UIView *videoPreview; 
- (IBAction)doCap:(id)sender; 

@end 

nhân viên có liên quan bên trong BIDViewController.m:

#import "BIDViewController.h" 

@interface BIDViewController() 

@end 

@implementation BIDViewController 
@synthesize capturedIm; 
@synthesize videoPreview; 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 
[self setupAVCapture]; 
} 

- (BOOL)setupAVCapture 
{ 
NSError *error = nil; 

AVCaptureSession *session = [AVCaptureSession new]; 
[session setSessionPreset:AVCaptureSessionPresetHigh]; 

/* 
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
captureVideoPreviewLayer.frame = self.videoPreview.bounds; 
[self.videoPreview.layer addSublayer:captureVideoPreviewLayer];  
*/ 

// Select a video device, make an input 
AVCaptureDevice *backCamera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error]; 
if (error) 
    return NO; 
if ([session canAddInput:input]) 
    [session addInput:input]; 

// Make a still image output 
stillImageOutput = [AVCaptureStillImageOutput new]; 
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; 
[stillImageOutput setOutputSettings:outputSettings];  
if ([session canAddOutput:stillImageOutput]) 
    [session addOutput:stillImageOutput]; 

[session startRunning]; 

return YES; 
} 

- (IBAction)doCap:(id)sender { 
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; } 
} 

[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection 
    completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *__strong error) { 
     // Do something with the captured image 
    }]; 

} 

Với đoạn mã trên, nếu doCap được gọi, thì tai nạn xảy ra. Mặt khác, nếu tôi xóa các nhận xét sau trong hàm setupAVCapture

/* 
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
captureVideoPreviewLayer.frame = self.videoPreview.bounds; 
[self.videoPreview.layer addSublayer:captureVideoPreviewLayer];  
*/ 

thì nó hoạt động mà không có bất kỳ sự cố nào.

Tóm lại, câu hỏi của tôi là, Làm cách nào để chụp ảnh ở các trường hợp được kiểm soát mà không hiển thị bản xem trước?

+0

cách đơn giản nhất sẽ là 'self.videoPreview.hidden = YES;' – Felix

+0

mã hoạt động trên iphone 4s của tôi – Felix

+0

@ phix23 ẩn videoPreview đã làm việc cho tôi quá ... Sau đó, câu hỏi tiếp theo là; có một hình phạt hiệu suất với cách tiếp cận này? tức là xử lý dự phòng dành cho việc gửi dữ liệu xem trước video đến một lớp ẩn? –

Trả lời

8

Tôi sử dụng mã sau đây để chụp từ máy ảnh mặt trước (nếu có) hoặc sử dụng máy ảnh sau. Hoạt động tốt trên iPhone 4S của tôi.

-(void)viewDidLoad{ 

    AVCaptureSession *session = [[AVCaptureSession alloc] init]; 
    session.sessionPreset = AVCaptureSessionPresetMedium; 

    AVCaptureDevice *device = [self frontFacingCameraIfAvailable]; 

    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 is a global variable in .h file: "AVCaptureStillImageOutput *stillImageOutput;" 
    stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; 
    [stillImageOutput setOutputSettings:outputSettings]; 

    [session addOutput:stillImageOutput]; 

    [session startRunning]; 
} 

-(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; 
} 

-(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 if you want to. 
      NSLog(@"attachements: %@", exifAttachments); 
     } 
     else 
      NSLog(@"no attachments"); 

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

     self.vImage.image = image; 
    }]; 
} 
+0

Làm việc tuyệt vời. Cảm ơn ! –

+1

tôi gặp lỗi tại stillImageOutput.connections rỗng hoặc chứa 0 đối tượng. chuyện gì thế? –

+0

Đây là giải pháp thực sự tốt. Nhưng màn hình sẽ trống trong một giây sau khi xảy ra snap để lấy hình ảnh. Trong ứng dụng SnapChat, nó không giống như vậy. Làm thế nào tôi có thể nhận được hành vi như trong ứng dụng SnapChat? – Satyam

1

Vâng, tôi đã phải đối mặt với một vấn đề tương tự mà bởi captureStillImageAsynchronouslyFromConnection:stillImageConnection được nâng cao một ngoại lệ rằng thông qua connection không hợp lệ. Sau đó, tôi đã tìm ra rằng khi tôi thực hiện properties cho phiên và stillImageOutPut để giữ lại các giá trị, vấn đề đã được giải quyết.

Các vấn đề liên quan