2013-05-14 4 views
3

Я пытаюсь получить мое приложение, чтобы создать UIImage правильный путь.AVCaptureSession rotation

Большая часть моего кода взяты из примеров Apple, ...

@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

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); 
    } 
}]; 
} 
Смежные вопросы