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
Dipen Panchasara's answer is great, but there could be one problem with it. When you process big images (for example from iPhoneX) there will be massive memory peak which can be an issue in some cases.
So, maybe you want to change that line:
context.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width))
for something with some memory optimization. For example, that will break image drawing in 16 (4*4) steps, which decrease memory consumption significantly:
let partInAxis: CGFloat = 4
let partWidth = image.size.height/partInAxis
let partHeight = image.size.width/partInAxis
for i in 0...Int(partInAxis)-1 {
for j in 0...Int(partInAxis)-1 {
let partialImage = image.cgImage?.cropping(to: CGRect(x: CGFloat(i)*partWidth, y: CGFloat(j)*partHeight, width: partWidth, height: partHeight))
context.draw(partialImage!, in: CGRect(x: CGFloat(i)*partWidth, y: CGFloat(Int(partInAxis)-1-j)*partHeight, width: partWidth, height: partHeight))
}
}
Be aware, that in this case height and width of image must be divided by 4.
The accepted answer works, but is much more complicated than it needs to be. You can use the following to rotate the image.
- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {
CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
return deg / 180.0f * (CGFloat) M_PI;
};
// determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position
CGAffineTransform rectTransform;
switch (image.imageOrientation) {
case UIImageOrientationLeft:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
break;
case UIImageOrientationRight:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
break;
case UIImageOrientationDown:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
break;
default:
rectTransform = CGAffineTransformIdentity;
};
// adjust the transformation scale based on the image scale
rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);
// apply the transformation to the rect to create a new, shifted rect
CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
// use the rect to crop the image
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
// create a new UIImage and set the scale and orientation appropriately
UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
// memory cleanup
CGImageRelease(imageRef);
return result;
}
To just rotate the image and not crop, you can simply call it like this:
UIImage *image;
[self cropImage:image toRect:rect.bounds];
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(Double.pi))
case .left, .leftMirrored:
transform = transform.translatedBy(x: image.size.width, y: 0)
transform = transform.rotated(by: CGFloat(Double.pi / 2))
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: image.size.height)
transform = transform.rotated(by: -CGFloat(Double.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(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width))
default:
context.draw(image.cgImage!, in: CGRect(origin: .zero, size: image.size))
}
// And now we just create a new UIImage from the drawing context
guard let CGImage = context.makeImage() else {
return nil
}
return UIImage(cgImage: CGImage)
}