2

I'm trying to capture pixel data from an AVCaptureStillImageOutput and noticed that upon cropping the image to a CGImage, it becomes re-oriented. To test this, I output a temporary image to the photo library. Now I've noticed that even before the image is cropped, it's thumbnail is rotated while the full image is not. (This later becomes a problem when I pass the UIImage to my custom pixelDataManager that requires proper dimensions of the image.)

Setting captureVideoPreviewLayer.orientation = AVCaptureVideoOrientationPortrait; and [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; did not seem to change anything.

Any thoughts??? I'll break it up into sections...

1) Setting up the session, input, and output:

    // Create a capture session
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetMedium;

    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];

    // Add capture layer to visible view    
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResize;
    captureVideoPreviewLayer.frame = screenBounds;
    captureVideoPreviewLayer.bounds = screenBounds;
    captureVideoPreviewLayer.orientation = AVCaptureVideoOrientationPortrait;
    [self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    // Setup error handling
    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];

    // Start session
    [session startRunning];

    // Output image data 
    stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [stillImageOutput setOutputSettings:outputSettings];

    [session addOutput:stillImageOutput];

2) Setting up the video connection:

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

if ([videoConnection isVideoOrientationSupported])
{
    [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}

3) Output the captured image:

NSLog(@"about to request a capture from: %@", stillImageOutput);
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{         
    NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
    UIImage *image = [[UIImage alloc] initWithData:imageData];
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    //......
}
Old McStopher
  • 6,295
  • 10
  • 60
  • 89
  • I would try looking at [image imageOrientation] and seeing what direction it is putting it in. If it's being set wrong, you can rotate the image first, and then write it to the Photo Album. Hope that helps! – msgambel Aug 10 '11 at 03:57
  • Thanks, I will give that a look tonight. I actually don't even need the photo album output. I was just doing it as a quick check to explain why my pixel data was behaving as though the image were rotated and sure enough it was. – Old McStopher Aug 10 '11 at 16:23
  • Even though you setup the video session to an orientation, you still need to decide what orientation your image should be when displayed/saved. Check out my answer here for a similar question: https://stackoverflow.com/a/54225440/753964 – bmjohns Jan 18 '19 at 20:00

1 Answers1

3

When you do this, though the image is being provided to you as a UIImage, it's actually using the underlying Quartz CGImage data which has a different origin point (lower left I think) which means that when you use the image it's rotated to the side.

I found a C function that you can call with the UIImage as parameter that fixes it and returns the fixed UIImage.

http://blog.logichigh.com/2008/06/05/uiimage-fix/

Cocoadelica
  • 3,006
  • 27
  • 30