iOS: Image get rotated 90 degree after saved as PNG representation data
I have researched enough to get this working but not able to fix it. After taking picture from camera as long as I have image stored as UIImage, it's fine but as soon as I stored this image as PNG representation, its get rotated 90 degree.
Following is my code and all things I tried:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];
if([mediaType isEqualToString:(NSString*)kUTTypeImage])
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.originalPhoto = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
NSLog(@"Saving photo");
[self saveImage];
NSLog(@"Fixing orientation");
delegate.fixOrientationPhoto = [self fixOrientation:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];
NSLog(@"Scaling photo");
delegate.scaledAndRotatedPhoto = [self scaleAndRotateImage:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];
}
[picker dismissModalViewControllerAnimated:YES];
[picker release];
}
- (void)saveImage
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSData *imageData = UIImagePNGRepresentation(delegate.originalPhoto);
[imageData writeToFile:[delegate filePath:imageName] atomically:YES];
}
Here fixOrientation and scaleAndRotateImage functions taken from here and here respectively. They works fine and rotate image when I apply them on UIImage but doesn't work if I save image as PNG representation and apply them.
Please refere the following picture after executing above functions:
Solution 1:
Starting with iOS 4.0 when the camera takes a photo it does not rotate it before saving, it
simply sets a rotation flag in the EXIF data of the JPEG.If you save a UIImage as a JPEG, it
will set the rotation flag.PNGs do not support a rotation flag, so if you save a UIImage as a
PNG, it will be rotated incorrectly and not have a flag set to fix it. So if you want PNG
images you must rotate them yourself, for that check this link.
Solution 2:
Swift 3.1 version of the UIImage extension posted by Rao:
extension UIImage {
func fixOrientation() -> UIImage {
if self.imageOrientation == UIImageOrientation.up {
return self
}
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
UIGraphicsEndImageContext()
return normalizedImage
} else {
return self
}
}
}
Usage:
let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
Swift 4/5:
UIImageOrientation.up
has been renamed to UIImage.Orientation.up
Solution 3:
Swift 4.2
Add the following as UIImage extension,
extension UIImage {
func fixOrientation() -> UIImage? {
if self.imageOrientation == UIImage.Orientation.up {
return self
}
UIGraphicsBeginImageContext(self.size)
self.draw(in: CGRect(origin: .zero, size: self.size))
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return normalizedImage
}
}
Example usage:
let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
Explanation:
The magic happens when you call UIImage's draw(in:)
function, which redraws the image respecting originally captured orientation settings. [link to docs]
Make sure to call UIGraphicsBeginImageContext
with image's size before calling draw to let draw
rewrite the UIImage in current context's space.
UIGraphicsGetImageFromCurrentImageContext
lets you capture whatever is the result of the redrawn image, & UIGraphicsEndImageContext
ends and frees up the graphics context.