iOS: Image get rotated 90 degree after saved as PN

2019-01-05 01:50发布

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:

The first photo is original, second is saved, and third and fourth after applying fixorientation and scaleandrotate functions on saved image

8条回答
时光不老,我们不散
2楼-- · 2019-01-05 02:10

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()
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-05 02:11

For Swift 2.1

Add the following as UIImage extension,

extension UIImage {
   func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.Up {
            return self
        }

        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.drawInRect(CGRectMake(0, 0, self.size.width, self.size.height))
        let normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return normalizedImage;
    }
}

Example usage:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
查看更多
Deceive 欺骗
4楼-- · 2019-01-05 02:21

I have found the following tips to be hugely useful:

1. natural output is landscape

2. .width / .height ARE affected by .imageOrientation

3 use short dimension rather than .width


(1) the 'natural' output of the camera for stills IS LANDSCAPE.

this is counterintuitive. portrait is the only way offered by UIImagePickerController etc. But you will get UIImageOrientationRight as the "normal" orientation when using the "normal" portrait camera

(The way I remember this - the natural output for video is (of course) landscape; so stills are the same - even though the iPhone is all about portrait.)


(2) .width and .height are indeed affected by the .imageOrientation!!!!!!!!!

Be sure to do this, and try it both ways on your iPhone,

NSLog(@"fromImage.imageOrientation is %d", fromImage.imageOrientation);
NSLog(@"fromImage.size.width  %f   fromImage.size.height  %f",
            fromImage.size.width, fromImage.size.height);

you'll see that the .height and .width swap, "even though" the real pixels are landscape.


(3) simply using the "short dimension" rather than .width, can often solve many problems

I found this to be incredibly helpful. Say you want maybe the top square of the image:

CGRect topRectOfOriginal = CGRectMake(0,0, im.size.width,im.size.width);

that actually won't work, you'll get a squished image, when the camera is ("really") being held landscape.

however if you very simply do this

float shortDimension = fminf(im.size.width, im.size.height);
CGRect topRectOfOriginal = CGRectMake(0,0, shortDimension,shortDimension);

then "everything is fixed" and you actually "do not need to worry about" the orientation flag. Again point (3) is not a cure-all, but it very often does solve all problems.

Hope it helps someone save some time.

查看更多
叼着烟拽天下
5楼-- · 2019-01-05 02:21

Pls Try the following code

UIImage *sourceImage = ... // Our image
CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage,
selectionRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

And

CGRect TransformCGRectForUIImageOrientation(CGRect source, UIImageOrientation orientation, CGSize imageSize) {
switch (orientation) {
case UIImageOrientationLeft: { // EXIF #8
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationDown: { // EXIF #3
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationRight: { // EXIF #6
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI + M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationUp: // EXIF #1 - do nothing
  default: // EXIF 2,4,5,7 - ignore
  return source;
}
}
  ...
UIImage *sourceImage = ... // Our image
 CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGRect transformedRect = TransformCGRectForUIImageOrientation(selectionRect,  sourceImage.imageOrientation, sourceImage.size);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, transformedRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

I have referanced from following link have look for more detail

Best Regards :-)

查看更多
趁早两清
6楼-- · 2019-01-05 02:23

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.

查看更多
一夜七次
7楼-- · 2019-01-05 02:23

Try this code:

NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100);
查看更多
登录 后发表回答