Search code examples
iosswiftuiimagepnguiimagepickercontroller

Swift PNG Image being saved with incorrect orientation


If I use the image before it is saved it is normal. But if I save it and use it later is is 90 degrees turned. How can I make sure it doesn't save sideways?

func saveEvent(_ center1: CLLocation, title2: String, imagePicked1: UIImage)
    {
        let data = UIImagePNGRepresentation(imagePicked1);///
        let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(NSUUID().uuidString+".dat")
        do {
            try data!.write(to: url!, options: [])
        } catch let e as NSError {
            print("Error! \(e)");
            return
        }
        let image11 = CKAsset(fileURL: url!)

        self.eventRecord.setObject(image11 as CKAsset, forKey: "Picture")
        let publicData = CKContainer.default().publicCloudDatabase
            publicData.save(self.eventRecord, completionHandler: { record, error in
                if error == nil
                {
                    print("Image saved")
                }else{
                    print(error!)
                }
        })
    }

Solution

  • If you need to save your PNG with correct rotation you will need to redraw your image if its orientation it is not .up. You can redraw it as follow:

    extension UIImage {
        func png(isOpaque: Bool = true) -> Data? { flattened(isOpaque: isOpaque)?.pngData() }
        func flattened(isOpaque: Bool = true) -> UIImage? {
            if imageOrientation == .up { return self }
            UIGraphicsBeginImageContextWithOptions(size, isOpaque, scale)
            defer { UIGraphicsEndImageContext() }
            draw(in: CGRect(origin: .zero, size: size))
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
    

    edit/update:

    For iOS10+ tvOS10+ you can use UIGraphicsImageRenderer:

    extension UIImage {
        func png(isOpaque: Bool = true) -> Data? { flattened(isOpaque: isOpaque).pngData() }
        func flattened(isOpaque: Bool = true) -> UIImage {
            if imageOrientation == .up { return self }
            let format = imageRendererFormat
            format.opaque = isOpaque
            return UIGraphicsImageRenderer(size: size, format: format).image { _ in draw(at: .zero) }
        }
    }
    

    Playground testing:

    Usage for images without transparency:

    let image = UIImage(data: try! Data(contentsOf: URL(string: "https://i.sstatic.net/varL9.jpg")!))!
    
    if let data = image.png() {
        let imageFromPNGData = UIImage(data: data)
    }
    

    With transparency :

    if let data = image.png(isOpaque: false) {
        let imageFromPNGData = UIImage(data: data)
    }