Taking pictures with camera rotates asset.fullScreenImage 90 degrees? - ios

I have a user pick a picture to crop from their Camera Roll. I display all of these pictures as thumbnails for the user to press.
I use UIImage(CGImage: asset.fullScreenImage!.CGImage!, scale: scale, orientation: UIImageOrientation.Up) to ensure that my image remains the same way it faces in the thumbnail. With asset.fullResolutionImage! this doesn't work.
Now comes the weird part. When I take a picture with the iPhone camera, then head to my cropping ViewController, the image is rotated 90 degrees! I have no idea why.
If I leave my app, take a picture with the camera normally, save it to my camera roll, and then choose it from the list of thumbnails like I do other pictures, it works perfectly fine.
What is the cause of this? How does one fix it?
Edit: There are two solutions posted below. One in Objective-C, and the other being a translated copy of that into Swift.

You can try to use this category:
UIImage+FixOrientation.h
UIImage+FixOrientation.m
It is built in Objective-C, then you can use bridging header to use ObjC in combination with Swift, or you can just have a look to understand how to fix that.
Usage example:
UIImage *image = <image from camera image>
image = [image fixOrientation];

This answer is to complement gontovnik's answer.
I have taken his Objective-C solution and written it in Swift. Put this function wherever needed. Just pass in the UIImage in question.
That said, you could probably just make this a UIImage class function. Would actually be nice to just call UIImage.fixOrientation(image: imageInQuestion).
func fixOrientation(image: UIImage) -> UIImage {
// No-op if the orientation is already correct
if (image.imageOrientation == UIImageOrientation.Up) { return image; }
println(image.imageOrientation)
// 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))
break
case .Left, .LeftMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0)
transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
break
case .Right, .RightMirrored:
transform = CGAffineTransformTranslate(transform, 0, image.size.height)
transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
break
case .Up, .UpMirrored:
break
}
switch (image.imageOrientation) {
case .UpMirrored, .DownMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0)
transform = CGAffineTransformScale(transform, -1, 1)
break
case .LeftMirrored, .RightMirrored:
transform = CGAffineTransformTranslate(transform, image.size.height, 0)
transform = CGAffineTransformScale(transform, -1, 1)
break
case .Up, .Down, .Left, .Right:
break
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
var ctx = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage))
CGContextConcatCTM(ctx, transform);
switch (image.imageOrientation) {
case .Left, .LeftMirrored, .Right, .RightMirrored:
// 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
var cgimg = CGBitmapContextCreateImage(ctx)
var img = UIImage(CGImage: cgimg)
return img!
}

Swift 3 version
func fixOrientation(image: UIImage) -> UIImage {
// No-op if the orientation is already correct
if (image.imageOrientation == UIImageOrientation.up) { return image; }
print(image.imageOrientation)
// 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))
break
case .left, .leftMirrored:
transform = transform.translatedBy(x: image.size.width, y: 0)
transform = transform.rotated(by: CGFloat(M_PI_2))
break
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: image.size.height)
transform = transform.rotated(by: CGFloat(-M_PI_2))
break
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)
break
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: image.size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
break
case .up, .down, .left, .right:
break
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
let ctx = 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)
ctx!.concatenate(transform);
switch (image.imageOrientation) {
case .left, .leftMirrored, .right, .rightMirrored:
// Grr...
ctx?.draw(image.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: image.size.height, height: image.size.width)))
break
default:
ctx?.draw(image.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: image.size.width, height: image.size.height)))
break
}
// And now we just create a new UIImage from the drawing context
let cgimg = ctx!.makeImage()
let img = UIImage(cgImage: cgimg!)
return img
}

Related

Fix orientation of images taken with front camera ios

I'm using custom camera implementation in my app using Swift.
When the image is captured, is called func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?). I get the image data with photo.fileDataRepresentation() and after that I'm fixing the orientation of the photo using the following extension on UIImage.
func fixedOrientation() -> UIImage? {
guard imageOrientation != UIImage.Orientation.up else {
// This is default orientation, don't need to do anything
return self.copy() as? UIImage
}
guard let cgImage = self.cgImage else {
// CGImage is not available
return nil
}
guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
return nil // Not able to create CGContext
}
var transform = CGAffineTransform.identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2.0)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat.pi / -2.0)
case .up, .upMirrored:
break
#unknown default:
break
}
// Flip image one more time if needed to, this is to prevent flipped image
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .up, .down, .left, .right:
break
#unknown default:
break
}
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
guard let newCGImage = ctx.makeImage() else { return nil }
return UIImage(cgImage: newCGImage, scale: 1, orientation: .up)
}
Apparently this is working fine for images taken with back camera, but taking with frontal one I'm facing issues.
If the selfie photo is taken in portrait, the the method returns the photo mirrored.(which is not a big deal)
If the selfie photo is taken in landscape right/left, the outcode is photo also mirrored but wrongfully rotated. Here is where I want your help, to get the correct rotation of the photo.
Note: I'm also changing the videoOrientation from AVCaptureConnection when rotating the device.
It turned out that i was changing the videoOrientation when rotation did change, which was wrong. I had to move that logic before capturing the photo. Now it works fine. Also I've fixed the mirroring problem, by setting isVideoMirrored to true if using the front camera.

How to load an image and rotate it according to it's orientation exif data and save it with UIImageOrientationUp exif data

How to load an image and rotate it according to it's orientation exif data and save it with UIImageOrientationUp exif data (or without any orientation exif data) so that software that don't handle exif orientation data will show correctly the image ?
Loading an image is as simple as this line:
UIImage *image = [UIImage imageNamed:#"NameOfImageHere"];
Or if you got image data:
NSData *imageData = [[NSData alloc] init];
UIImage *image = [UIImage imageWithData: imageData];
And following method will help you to fix the orientation using exif data within UIImage
- (UIImage *)imageByFixingOrientation {
UIImage *image = self;
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:
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 4 equivalent of my previous objective-c method as an extension:
extension UIImage {
func byFixingOrientation(andResizingImageToNewSize newSize: CGSize? = nil) -> UIImage {
guard let cgImage = self.cgImage else { return self }
let orientation = self.imageOrientation
guard orientation != .up else { return UIImage(cgImage: cgImage, scale: 1, orientation: .up) }
var transform = CGAffineTransform.identity
let size = newSize ?? self.size
if (orientation == .down || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: .pi)
}
else if (orientation == .left || orientation == .leftMirrored) {
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2)
}
else if (orientation == .right || orientation == .rightMirrored) {
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: -(CGFloat.pi / 2))
}
if (orientation == .upMirrored || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: 0);
transform = transform.scaledBy(x: -1, y: 1)
}
else if (orientation == .leftMirrored || orientation == .rightMirrored) {
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
}
// Now we draw the underlying CGImage into a new context, applying the transform calculated above.
guard let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0,
space: cgImage.colorSpace!, bitmapInfo: cgImage.bitmapInfo.rawValue)
else {
return UIImage(cgImage: cgImage, scale: 1, orientation: orientation)
}
ctx.concatenate(transform)
// Create a new UIImage from the drawing context
switch (orientation) {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
return UIImage(cgImage: ctx.makeImage() ?? cgImage, scale: 1, orientation: .up)
}
}
Usage-1
let newImage = image.byFixingOrientation()
Usage-2 (Fix orientation and resize image to new size)
let newImage = image.byFixingOrientation(andResizingImageToNewSize: CGSize(width: 200, height: 200))

Replacing UIImageJPEGRepresentation with UIGraphicsImageRenderer's jpegData

I am working to add support for wide color photos in iOS 10. When the user takes a photo from the camera, I need to use the new API that supports the new color space to save the photo data - UIGraphicsImageRenderer's jpegData instead of UIImageJPEGRepresentation.
I'm running into some troubles with image orientations. Taking a photo on my iPad in portrait, the image isn't being drawn correctly. See the comments below:
Old API:
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageData = UIImageJPEGRepresentation(image, 1)
New API:
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let cgImage = image.cgImage!
let ciImage = CIImage(cgImage: cgImage)
let format = UIGraphicsImageRendererFormat()
format.scale = 1
format.prefersExtendedRange = true
let renderer = UIGraphicsImageRenderer(bounds: ciImage.extent, format: format)
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in
context.cgContext.draw(cgImage, in: ciImage.extent) //draws flipped horizontally
//image.draw(at: .zero) //draws rotated 90 degrees leaving black at bottom
//image.draw(in: ciImage.extent) //draws rotated 90 degrees stretching and compressing the image to fill the rect
})
What's the correct way to replace UIImageJPEGRepresentation with UIGraphicsImageRenderer's jpegData?
UIImage can have different orientation depending on camera rotation.
You can dynamically resolve the transformation needed to be applied to the image depending on that orientation, like this:
let renderer = UIGraphicsImageRenderer(size: image.size, format: format)
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in
var workSize = image.size;
workSize.width = floor(workSize.width / image.scale)
workSize.height = floor(workSize.height / image.scale)
// No-op if the orientation is already correct
// if image.imageOrientation == .up { draw 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: workSize.width, y: workSize.height)
transform = transform.rotated(by: CGFloat(Double.pi))
break
case .left, .leftMirrored:
transform = transform.translatedBy(x: workSize.width, y: 0.0)
transform = transform.rotated(by: CGFloat(Double.pi / 2.0))
break
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0.0, y: workSize.height)
transform = transform.rotated(by: CGFloat(-Double.pi / 2.0))
break
case .up, .upMirrored:
break
}
switch image.imageOrientation
{
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: workSize.width, y: 0.0)
transform = transform.scaledBy(x: -1.0, y: 1.0)
break
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: workSize.height, y: 0.0);
transform = transform.scaledBy(x: -1.0, y: 1.0);
break
case .up, .down, .left, .right:
break
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
let ctx = context.cgContext
ctx.concatenate(transform)
switch image.imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(image.cgImage!, in: CGRect(x: 0.0, y:0.0, width: workSize.height, height: workSize.width))
break;
default:
ctx.draw(image.cgImage!, in: CGRect(origin: .zero, size: workSize))
break;
}
})
Answer based on UIImage+fixOrientation
The image.draw() method should correct the orientation automatically for you:
This method draws the entire image in the current graphics context, respecting the image’s orientation setting. In the default coordinate system, images are situated down and to the right of the origin of the specified rectangle. This method respects any transforms applied to the current graphics context, however.
I'm not sure why you need to use ci.extent. The extent seems to be (I make no claims to be an expert in Core Image APIs) the dimensions of the "raw" image data, which is stored without any image orientation correction. If you raw data needs rotation (non-Up orientations like Left, Right), the extent will still be the original rect that the data is stored.
I use the following code for an image with imageOrientation.rawValue = 3 and my data turns out perfectly fine at the right size with "corrected" imageOrientation.rawValue = 0 when reloaded.
let imageSize = image.Size
let renderer = UIGraphicsImageRenderer(size: renderedSize, format: UIGraphicsImageRendererFormat())
return renderer.jpegData(withCompressionQuality: 0.95) { (rendererContext) in
let rect = CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height)
image.draw(in: rect)
}
My input image "renders" its data correctly with my code, taking into account the image orientation. On the right, I use draw(in: extent). The image isn't rotated though. Just stretched.

iOS UIImage uploaded to server are rotated [duplicate]

This question already has answers here:
iOS UIImagePickerController result image orientation after upload
(20 answers)
Closed 9 years ago.
I'm using the following code to send an image to a web server. It works, the problem is that the images are rotated for some reason when they get uploaded.
here's my upload method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:nil];
NSData *image = UIImageJPEGRepresentation([info objectForKey:UIImagePickerControllerOriginalImage], 0.1);
// use token with url for json data from contents of url
NSString *savedValue = [[NSUserDefaults standardUserDefaults]
stringForKey:#"token"];
NSString *urlString = [NSString stringWithFormat:#"%#%#/photos?token=%#", kIDURLPhoto, listingId, savedValue];
NSLog(#"urlstring for comment is %#",urlString);
self.flUploadEngine = [[fileUploadEngine alloc] initWithHostName:urlString customHeaderFields:nil];
NSMutableDictionary *postParams = [NSMutableDictionary dictionaryWithObjectsAndKeys: #"image", #"caption", nil];
self.flOperation = [self.flUploadEngine postDataToServer:postParams path:nil];
[self.flOperation addData:image forKey:#"picture" mimeType:#"image/jpeg" fileName:#"upload.jpg"];
[self.flOperation addCompletionHandler:^(MKNetworkOperation* operation) {
NSLog(#"%#", [operation responseString]);
// handle a successful 200 response
[self.flUploadEngine enqueueOperation:self.flOperation];
// for iOS7
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
[self forceReload];
}
Swift 5 Extension:
extension UIImage {
/// Fix image orientaton to protrait up
func fixedOrientation() -> UIImage? {
guard imageOrientation != UIImage.Orientation.up else {
// This is default orientation, don't need to do anything
return self.copy() as? UIImage
}
guard let cgImage = self.cgImage else {
// CGImage is not available
return nil
}
guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
return nil // Not able to create CGContext
}
var transform: CGAffineTransform = CGAffineTransform.identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2.0)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat.pi / -2.0)
case .up, .upMirrored:
break
#unknown default:
fatalError("Missing...")
break
}
// Flip image one more time if needed to, this is to prevent flipped image
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .up, .down, .left, .right:
break
#unknown default:
fatalError("Missing...")
break
}
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
break
}
guard let newCGImage = ctx.makeImage() else { return nil }
return UIImage.init(cgImage: newCGImage, scale: 1, orientation: .up)
}
}
Objective C Code :
-(UIImage *)scaleAndRotateImage:(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;
}
Use of code
UIImage *img=[info objectForKey:UIImagePickerControllerOriginalImage];
img=[self scaleAndRotateImage:img];
NSData *image = UIImageJPEGRepresentation(img, 0.1);
Most probably you are not taking into account exif data, they give the rotation of the camera and you should add them to the image EXIF dictionary. In this way when you open the image the reading software can rotate the image accordingly. Check this question and relative answers, it would be helpful

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);
}];
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)
}
Swift 5.5 +
you should set the orientation of the output before you capture the image.
// set the image orientation in output
if let photoOutputConnection = self.photoOutput.connection(with: .video) {
photoOutputConnection.videoOrientation = videoPreviewLayerOrientation!
}
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureProcessor) // capture image
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];
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.
I'd recommend using Yodagama's answer, since it's a one-liner and much cleaner. However, if you need to correct the orientation in another way, here's Dipen's answer without forced optionals, as a UIImage extension. For better memory optimization, mix it with this answer.
extension UIImage {
var fixedOrientation: UIImage? {
if imageOrientation == .up {
return self
}
// 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 imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: .pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: .pi / 2)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: -.pi / 2)
default: break
}
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
default: break
}
guard let cgImage = cgImage,
let colorSpace = cgImage.colorSpace else {
return nil
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
let context = CGContext(
data: nil,
width: Int(size.width),
height: Int(size.height),
bitsPerComponent: cgImage.bitsPerComponent,
bytesPerRow: 0,
space: colorSpace,
bitmapInfo: cgImage.bitmapInfo.rawValue
)
guard let context = context else {
return nil
}
context.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
context.draw(cgImage, in: .init(x: 0, y: 0, width: size.height, height: size.width))
default:
context.draw(cgImage, in: .init(origin: .zero, size: size))
}
// And now we just create a new UIImage from the drawing context
guard let newCgImage = context.makeImage() else {
return nil
}
return .init(cgImage: newCgImage)
}
}

Resources