UIImagePNGRepresentation issues? / Images rotated by 90 degrees

前端 未结 6 753
臣服心动
臣服心动 2020-11-29 20:30

I want to load images from UIImagePickerController, then save the selected photo to my app\'s document directory.

UIImage *image = [info objectForKey:UIImage         


        
相关标签:
6条回答
  • 2020-11-29 20:49

    I have created this UIImage extension to fix this problem with UIImagePNGRepresentation, based on this response. So I propose to use this class func UIImage.PNGRepresentation(img: UIImage) instead of UIKit func UIImagePNGRepresentation.

    Swift 3 code :

    //  MyUIImage.swift
    //  MyEasyMovie-Public-App
    //
    //  Created by Ahmed Zahraz on 19/12/2016.
    //  Copyright © 2016 AhmedZahraz. All rights reserved.    
    
    import Foundation
    import UIKit
    
    extension UIImage {
    
    
        public class func PNGRepresentation(_ img: UIImage) -> Data? {
            // No-op if the orientation is already correct
            if (img.imageOrientation == UIImageOrientation.up) {
                return UIImagePNGRepresentation(img);
            }
            // 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 = CGAffineTransform.identity
    
            if (img.imageOrientation == UIImageOrientation.down
                || img.imageOrientation == UIImageOrientation.downMirrored) {
    
                transform = transform.translatedBy(x: img.size.width, y: img.size.height)
                transform = transform.rotated(by: CGFloat(M_PI))
            }
    
            if (img.imageOrientation == UIImageOrientation.left
                || img.imageOrientation == UIImageOrientation.leftMirrored) {
    
                transform = transform.translatedBy(x: img.size.width, y: 0)
                transform = transform.rotated(by: CGFloat(M_PI_2))
            }
    
            if (img.imageOrientation == UIImageOrientation.right
                || img.imageOrientation == UIImageOrientation.rightMirrored) {
    
                transform = transform.translatedBy(x: 0, y: img.size.height);
                transform = transform.rotated(by: CGFloat(-M_PI_2));
            }
    
            if (img.imageOrientation == UIImageOrientation.upMirrored
                || img.imageOrientation == UIImageOrientation.downMirrored) {
    
                transform = transform.translatedBy(x: img.size.width, y: 0)
                transform = transform.scaledBy(x: -1, y: 1)
            }
    
            if (img.imageOrientation == UIImageOrientation.leftMirrored
                || img.imageOrientation == UIImageOrientation.rightMirrored) {
    
                transform = transform.translatedBy(x: img.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.
            let ctx:CGContext = CGContext(data: nil, width: Int(img.size.width), height: Int(img.size.height),
                                          bitsPerComponent: img.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                          space: img.cgImage!.colorSpace!,
                                          bitmapInfo: img.cgImage!.bitmapInfo.rawValue)!
    
            ctx.concatenate(transform)
    
    
            if (img.imageOrientation == UIImageOrientation.left
                || img.imageOrientation == UIImageOrientation.leftMirrored
                || img.imageOrientation == UIImageOrientation.right
                || img.imageOrientation == UIImageOrientation.rightMirrored
                ) {
    
    
                ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.height,height:img.size.width))
    
            } else {
                ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.width,height:img.size.height))
            }
    
    
            // And now we just create a new UIImage from the drawing context
            let cgimg:CGImage = ctx.makeImage()!
            let imgEnd:UIImage = UIImage(cgImage: cgimg)
    
            return UIImagePNGRepresentation(imgEnd)
        }
    
    }
    
    0 讨论(0)
  • 2020-11-29 20:53

    Please try this one.

    func rotateImage(image: UIImage) -> UIImage? {
            if (image.imageOrientation == UIImage.Orientation.up ) {
                return image
            }
            UIGraphicsBeginImageContext(image.size)
            image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
            let copy = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return copy
        }
    

    Happy Codding :)

    0 讨论(0)
  • 2020-11-29 20:58

    I solve this issue with the following code.

    - (UIImage *)scaleAndRotateImage:(UIImage *)image
    {
        int kMaxResolution = 640; 
    
        CGImageRef imgRef = image.CGImage;
    
        CGFloat width = CGImageGetWidth(imgRef);
        CGFloat height = CGImageGetHeight(imgRef);
    
        CGAffineTransform transform = CGAffineTransformIdentity;
        CGRect bounds = CGRectMake(0, 0, width, height);
        if (width > kMaxResolution || height > kMaxResolution) {
            CGFloat ratio = width/height;
            if (ratio > 1) {
                bounds.size.width = kMaxResolution;
                bounds.size.height = bounds.size.width / ratio;
            }
            else {
                bounds.size.height = kMaxResolution;
                bounds.size.width = bounds.size.height * ratio;
            }
        }
    
        CGFloat scaleRatio = bounds.size.width / width;
        CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
        CGFloat boundHeight;
        UIImageOrientation orient = image.imageOrientation;
        switch(orient) {
    
            case UIImageOrientationUp: //EXIF = 1
                transform = CGAffineTransformIdentity;
                break;
    
            case UIImageOrientationUpMirrored: //EXIF = 2
                transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
                transform = CGAffineTransformScale(transform, -1.0, 1.0);
                break;
    
            case UIImageOrientationDown: //EXIF = 3
                transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
                transform = CGAffineTransformRotate(transform, M_PI);
                break;
    
            case UIImageOrientationDownMirrored: //EXIF = 4
                transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
                transform = CGAffineTransformScale(transform, 1.0, -1.0);
                break;
    
            case UIImageOrientationLeftMirrored: //EXIF = 5
                boundHeight = bounds.size.height;
                bounds.size.height = bounds.size.width;
                bounds.size.width = boundHeight;
                transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
                transform = CGAffineTransformScale(transform, -1.0, 1.0);
                transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
                break;
    
            case UIImageOrientationLeft: //EXIF = 6
                boundHeight = bounds.size.height;
                bounds.size.height = bounds.size.width;
                bounds.size.width = boundHeight;
                transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
                transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
                break;
    
            case UIImageOrientationRightMirrored: //EXIF = 7
                boundHeight = bounds.size.height;
                bounds.size.height = bounds.size.width;
                bounds.size.width = boundHeight;
                transform = CGAffineTransformMakeScale(-1.0, 1.0);
                transform = CGAffineTransformRotate(transform, M_PI / 2.0);
                break;
    
            case UIImageOrientationRight: //EXIF = 8
                boundHeight = bounds.size.height;
                bounds.size.height = bounds.size.width;
                bounds.size.width = boundHeight;
                transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
                transform = CGAffineTransformRotate(transform, M_PI / 2.0);
                break;
    
            default:
                [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
    
        }
    
        UIGraphicsBeginImageContext(bounds.size);
    
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
            CGContextScaleCTM(context, -scaleRatio, scaleRatio);
            CGContextTranslateCTM(context, -height, 0);
        }
        else {
            CGContextScaleCTM(context, scaleRatio, -scaleRatio);
            CGContextTranslateCTM(context, 0, -height);
        }
    
        CGContextConcatCTM(context, transform);
    
        CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
        UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return imageCopy;
    }
    
    0 讨论(0)
  • 2020-11-29 20:58

    The following swift function resolves the problem.

    func rotateImage(image: UIImage) -> UIImage? {
            if (image.imageOrientation == UIImage.Orientation.up ) {
                return image
            }
            UIGraphicsBeginImageContext(image.size)
            image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
            let copy = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return copy
        }
    

    Yup it is that simple, just because the drawInRect function will take image orientation in consideration.

    0 讨论(0)
  • 2020-11-29 21:02

    Stefan's answer updated for Swift 4:

    func rotateImage(image: UIImage) -> UIImage {
            if (image.imageOrientation == UIImage.Orientation.up) {
                return image
            }
            UIGraphicsBeginImageContext(image.size)
            image.draw(in: CGRect(origin: .zero, size: image.size))
            let copy = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return copy!
        }
    

    And then:

    var originalImage = yourImage.image!
    image = rotateImage(image: originalImage)
    
    0 讨论(0)
  • 2020-11-29 21:03

    I had the same problem and just figured out the reason: 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 PNGs you must rotate them yourself.

    I would call this a bug in the PNG saving function but that's just an opinion (they should at least warn you about this).

    0 讨论(0)
提交回复
热议问题