Camera image orientation

15,003

Solution 1

you should fix orientation of image captured by camera the code follows, by default the orientation of camera image is not correct

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

    if (image.imageOrientation == UIImageOrientationUp) return image;
    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;
}

Solution 2

-[UIImage imageOrientation] might help :)

Image orientation affects the way the image data is displayed when drawn. By default, images are displayed in the “up” orientation. If the image has associated metadata (such as EXIF information), however, this property contains the orientation indicated by that metadata. For a list of possible values for this property, see “UIImageOrientation.”

Since that property is readonly, and depending on what you want to do, a possible (but ugly) solution could be:

UIImage *sourceImage = [arrayImage objectAtIndex:0];
NSData *data = UIImagePNGRepresentation(sourceImage);
UIImage *tmp = [UIImage imageWithData:data];
UIImage *fixed = [UIImage imageWithCGImage:tmp.CGImage
                                     scale:sourceImage.scale
                               orientation:sourceImage.imageOrientation];

(untested and there might/must be something cleaner)

EDIT : First part was an answer to your question, an explanation more than a fix.

This and this (old?) blog posts might be interesting readings for you. Strangely I've never met this issue while I'm using UIImageJPEGRepresentation to send images to a server... What iOS version are you working on? That could be an old SDK bug?

Solution 3

I think this is a bug with the SDK. I ran into this exact problem and then switched over to UIImageJPEGRepresentation which fixed the problem.

Solution 4

//iOS Swift 3

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

        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: .pi)
        case .left, .leftMirrored:
            transform = transform.translatedBy(x: image.size.width, y: 0)
            transform = transform.rotated(by: .pi / 2)
        case .right, .rightMirrored:
            transform = transform.translatedBy(x: 0, y: image.size.height)
            transform = transform.rotated(by: -(.pi / 2))
        case .up, .upMirrored:
            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)
        case .up, .down, .left, .right:
            break
        }

        // Now we draw the underlying CGImage into a new context, applying the transform
        // calculated above.

        let cgimage = image.cgImage
        let bitsPerComponent = cgimage?.bitsPerComponent
        let colorSpace = cgimage?.colorSpace
        let bitmapInfo = cgimage?.bitmapInfo

        let ctx = CGContext(data: nil, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: bitsPerComponent! , bytesPerRow: 0, space: colorSpace!, bitmapInfo: bitmapInfo!.rawValue)

        ctx?.concatenate(transform)

        switch image.imageOrientation {
        case .left, .leftMirrored, .right, .rightMirrored:
            // Grr...
            ctx?.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width))
        default:
            ctx?.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
        }

        let cgimg: CGImage = ctx!.makeImage()!
        let img = UIImage(cgImage: cgimg)
        return img
    }
Share:
15,003
DNewell
Author by

DNewell

Updated on June 05, 2022

Comments

  • DNewell
    DNewell almost 2 years

    In my app I'm capturing images using the Camera. These are being stored in an NSArray as an NSData representation. When I convert the NSData back to the image, the orientation is now landscape instead of portrait as I took it.

        NSData *data = UIImagePNGRepresentation([arrayImage objectAtIndex:0]);
        UIImage *tmp = [UIImage imageWithData:data];
    

    Anyone have an explanation? Thanks.

  • DNewell
    DNewell about 13 years
    Well that did solve the problem inside the app. However, it doesn't matter which way I orient the image in the app, when I convert back to NSData for sending the image in an email, the image goes back to the 90 degrees CCW from the original. This certainly seems like a bug?
  • Vincent Guerci
    Vincent Guerci about 13 years
    edited answer with interesting links, next time please post a more detailed question.
  • Boeckm
    Boeckm about 12 years
    Any confirmation on this? I'm having the same problem and can't find a fix for the life of me. Using JPEG representation is out of the question for me as I need the alpha channel PNGs offer.
  • A-Live
    A-Live about 11 years
    The orientation is correct. Incorrect is the logic of some developers who do not respect metadata when transferring or displaying the image.
  • William T.
    William T. over 8 years
    This helped me. I have confirmed that the image orientation issue doesn't happen with JPEG conversion