首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVCaptureSession旋转

AVCaptureSession旋转
EN

Stack Overflow用户
提问于 2013-05-15 01:03:42
回答 3查看 7.9K关注 0票数 3

我正在尝试让我的应用程序以正确的方式创建一个UIImage。

我的大部分代码都取自苹果的例子。

代码语言:javascript
复制
@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问题,它们的答案也声称可以解决这个问题。

这些都不管用。

有谁知道怎么把这个东西旋转到正确的方向吗?

EN

回答 3

Stack Overflow用户

发布于 2013-05-17 01:35:11

在调用captureStillImageAsynchronouslyFromConnection之前添加以下代码是我通常做的事情:

代码语言:javascript
复制
if ([videoConnection isVideoOrientationSupported]) {
    [videoConnection setVideoOrientation:[UIDevice currentDevice].orientation];
}
票数 4
EN

Stack Overflow用户

发布于 2013-10-24 19:53:08

也许你应该在captureStillImageAsynchronouslyFromConnection完成块中接收到图像数据后尝试设置图像方向:

代码语言:javascript
复制
UIImage *image = [[UIImage alloc] initWithData:imageData];
image = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0f orientation:UIImageOrientationDown];
票数 1
EN

Stack Overflow用户

发布于 2014-10-18 22:18:34

方向问题是前置摄像头的问题,所以检查设备类型并生成新图像,肯定会解决方向问题:

代码语言:javascript
复制
-(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);
    }
}];
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16548874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档