Jonathan Jonathan - 3 months ago 27
iOS Question

AVFoundation Image orientation off by 90 degrees in the preview but fine in Camera roll

Something really strange is happening, I am trying to capture an image using AVFoundation, the Camera roll image seems just fine, but the image preview has the image rotated by 90 degrees.

This is the code I am using to capture an image

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

NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];

UIImage *image = [[UIImage alloc] initWithData:imageData];

self.vImage.image = image;

UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}];

Answer

yes ,it happens when you capture image in Portrait orientation of your device and use that image in your application, because the default orientation of image is Landscape in any IOS Device, so you need to change the orientation of image after picking from Gallery to use in your app.

I have put code to achieve this

Objective-C code

- (UIImage *)fixOrientationOfImage:(UIImage *)image {

    // No-op if the orientation is already correct
    if (image.imageOrientation == UIImageOrientationUp) return image;

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (image.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, image.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }

    switch (image.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationDown:
        case UIImageOrientationLeft:
        case UIImageOrientationRight:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
                                             CGImageGetBitsPerComponent(image.CGImage), 0,
                                             CGImageGetColorSpace(image.CGImage),
                                             CGImageGetBitmapInfo(image.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

Swift code

func fixOrientationOfImage(image: UIImage) -> UIImage? {
   if image.imageOrientation == .Up {
      return image
   }

   // We need to calculate the proper transformation to make the image upright.
   // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
   var transform = CGAffineTransformIdentity

   switch image.imageOrientation {
   case .Down, .DownMirrored:
      transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height)
      transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
   case .Left, .LeftMirrored:
      transform = CGAffineTransformTranslate(transform, image.size.width, 0)
      transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
   case .Right, .RightMirrored:
      transform = CGAffineTransformTranslate(transform, 0, image.size.height)
      transform = CGAffineTransformRotate(transform, -CGFloat(M_PI_2))
   default:
      break
   }

   switch image.imageOrientation {
   case .UpMirrored, .DownMirrored:
      transform = CGAffineTransformTranslate(transform, image.size.width, 0)
      transform = CGAffineTransformScale(transform, -1, 1)
   case .LeftMirrored, .RightMirrored:
      transform = CGAffineTransformTranslate(transform, image.size.height, 0)
      transform = CGAffineTransformScale(transform, -1, 1)
   default:
      break
   }

   // Now we draw the underlying CGImage into a new context, applying the transform
   // calculated above.
   guard let context = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage).rawValue) else {
      return nil
   }

   CGContextConcatCTM(context, transform)

   switch image.imageOrientation {
   case .Left, .LeftMirrored, .Right, .RightMirrored:
      CGContextDrawImage(context, CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width), image.CGImage)
   default:
      CGContextDrawImage(context, CGRect(origin: .zero, size: image.size), image.CGImage)
   }

   // And now we just create a new UIImage from the drawing context
   guard let CGImage = CGBitmapContextCreateImage(context) else {
      return nil
   }

   return UIImage(CGImage: CGImage)
}

Swift 3.0

func fixOrientationOfImage(image: UIImage) -> UIImage? {
    if image.imageOrientation == .up {
        return image
    }

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    var transform = CGAffineTransform.identity

    switch image.imageOrientation {
    case .down, .downMirrored:
        transform = transform.translatedBy(x: image.size.width, y: image.size.height)
        transform = transform.rotated(by: CGFloat(M_PI))
    case .left, .leftMirrored:
        transform = transform.translatedBy(x: image.size.width, y: 0)
        transform = transform.rotated(by: CGFloat(M_PI_2))
    case .right, .rightMirrored:
        transform = transform.translatedBy(x: 0, y: image.size.height)
        transform = transform.rotated(by: -CGFloat(M_PI_2))
    default:
        break
    }

    switch image.imageOrientation {
    case .upMirrored, .downMirrored:
        transform = transform.translatedBy(x: image.size.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    case .leftMirrored, .rightMirrored:
        transform = transform.translatedBy(x: image.size.height, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    default:
        break
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    guard let context = CGContext(data: nil, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: image.cgImage!.bitsPerComponent, bytesPerRow: 0, space: image.cgImage!.colorSpace!, bitmapInfo: image.cgImage!.bitmapInfo.rawValue) else {
        return nil
    }

    context.concatenate(transform)

    switch image.imageOrientation {
    case .left, .leftMirrored, .right, .rightMirrored:
        context.draw(in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width), image: image.cgImage!)
    default:
        context.draw(in: CGRect(origin: .zero, size: image.size), image: image.cgImage!)
    }

    // And now we just create a new UIImage from the drawing context
    guard let CGImage = context.makeImage() else {
        return nil
    }

    return UIImage(cgImage: CGImage)
}