2013-05-14 14 views
3

我試圖讓我的應用程序以正確的方式創建UIImage。AVCaptureSession旋轉

我的大部分代碼是從蘋果公司的例子所...

@interface CameraManager() <AVCaptureVideoDataOutputSampleBufferDelegate> 

@property (nonatomic, strong) CIContext *context; 
@property (nonatomic, strong) AVCaptureDevice *rearCamera; 

@end 

@implementation CameraManager 

- (id)init { 
    if ((self = [super init])) { 

     self.context = [CIContext contextWithOptions:nil]; 
     [self setupCamera]; 
     [self addStillImageOutput]; 
    } 
    return self; 
} 

- (void)setupCamera 
{ 
    self.session = [[AVCaptureSession alloc] init]; 
    [self.session beginConfiguration]; 

    [self.session setSessionPreset:AVCaptureSessionPresetPhoto]; 

    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 
    self.rearCamera = nil; 
    for (AVCaptureDevice *device in devices) { 
     if (device.position == AVCaptureDevicePositionBack) { 
      self.rearCamera = device; 
      break; 
     } 
    } 

    NSError *error = nil; 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.rearCamera error:&error]; 
    [self.session addInput:input]; 

    AVCaptureVideoDataOutput *dataOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    [dataOutput setAlwaysDiscardsLateVideoFrames:YES]; 

    NSDictionary *options = @{(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)}; 
    [dataOutput setVideoSettings:options]; 

    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 

    [self.session addOutput:dataOutput]; 
    [self.session commitConfiguration]; 
} 

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    // grab the pixel buffer 
    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) CMSampleBufferGetImageBuffer(sampleBuffer); 

    // create a CIImage from it, rotate it and zero the origin 
    CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer]; 
    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft) { 
     image = [image imageByApplyingTransform:CGAffineTransformMakeRotation(M_PI)]; 
    } 
    CGPoint origin = [image extent].origin; 
    image = [image imageByApplyingTransform:CGAffineTransformMakeTranslation(-origin.x, -origin.y)]; 

    // set it as the contents of the UIImageView 
    CGImageRef cgImage = [self.context createCGImage:image fromRect:[image extent]]; 
    UIImage *uiImage = [UIImage imageWithCGImage:cgImage]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"image" object:uiImage]; 

    CGImageRelease(cgImage); 
} 

- (void)addStillImageOutput 
{ 
    [self setStillImageOutput:[[AVCaptureStillImageOutput alloc] init]]; 
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey,nil]; 
    [[self stillImageOutput] setOutputSettings:outputSettings]; 

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

    [[self session] addOutput:[self stillImageOutput]]; 
} 

- (void)captureStillImage 
{ 
    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]); 
    [[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection 
                 completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 
                  CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 
                  if (exifAttachments) { 
                   NSLog(@"attachements: %@", exifAttachments); 
                  } else { 
                   NSLog(@"no attachments"); 
                  } 
                  NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 
                  UIImage *image = [[UIImage alloc] initWithData:imageData]; 

                  [[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:image]; 
                 }]; 
} 

這是我的相機管理類代碼。

我正在使用OutputSampleBufferDelegate顯示相機的預覽(出於各種原因)。

我正在使用會話輸出來「拍照」。

方法captureStillImage是我試圖解決的一點。

照片是在LandscapeLeft方向(該界面也是LandscapeLeft)與設備一起拍攝的。

預覽都顯示正確的方式,exif數據顯示寬度和高度也是正確的方式。 (X = 3264,Y = 2448)。

但是,當我顯示UIImage它逆時針旋轉90度。圖像的縱橫比是正確的(即一切看起來很好,圓圈仍然是圓形)就是旋轉。

我發現了幾個聲稱解決這個問題的類別。

我還發現幾個StackOverflow的問題與答案,也聲稱修復它。

這些都沒有工作。

有誰知道如何正確旋轉這個東西?

回答

3

添加以下代碼打電話之前captureStillImageAsynchronouslyFromConnection是我平時做:

if ([videoConnection isVideoOrientationSupported]) { 
    [videoConnection setVideoOrientation:[UIDevice currentDevice].orientation]; 
} 
+0

請注意,您必須調用-beginGeneratingDeviceOrientationNotifications,否則您將返回UIDeviceOrientationUnknown(0)。另外請注意,您不能在請求方向前立即調用-beginGeneratingDeviceOrientationNotifications,您必須在某個時間之前調用它(例如在viewWillAppear或某物中)。 – prewett 2014-01-24 12:03:44

1

也許你應該嘗試在captureStillImageAsynchronouslyFromConnection完成塊的接收圖像數據後,設置圖像方向:

UIImage *image = [[UIImage alloc] initWithData:imageData]; 
image = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0f orientation:UIImageOrientationDown]; 
0

定位問題是與前置攝像頭,所以檢查設備類型,併產生新的形象,這一定會解決方向問題:

-(void)capture:(void(^)(UIImage *))handler{ 

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

[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

    if (imageSampleBuffer != NULL) { 
     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 
     **UIImage *capturedImage = [UIImage imageWithData:imageData]; 
     if (self.captureDevice == [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo][1]) { 
      capturedImage = [[UIImage alloc] initWithCGImage:capturedImage.CGImage scale:1.0f orientation:UIImageOrientationLeftMirrored]; 
     }** 

     handler(capturedImage); 
    } 
}]; 
}