1

In my app, I am importing selected photos from a user's photo library and using them as thumbnails/displaying them in UIImageViews. They are imported and saved to the user's documents folder.

The code used is below, however the images are being automatically rotated before being saved, and I'm not sure why.

For example, this image is rotated 180°: https://imgur.com/a/r2xm0if, as are some others that are wider than they are high. I'm not sure why, but not all images are rotated like this. Some are rotated 90°, and some not at all.

They are rotated on the disk - not just in the UIImageView, so I know it's not an issue with how that is set up.

importPicture() is called when the user taps a "+" button.

@objc func importPicture() {
    let picker                  = UIImagePickerController()
    picker.mediaTypes           = [kUTTypeMovie as String, kUTTypeImage as String]
    picker.allowsEditing        = true
    picker.delegate             = self

    present(picker, animated: true)
}


@objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {


    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    // create a name for your image
    let addedURL = UUID().uuidString
    let fileURL = documentsDirectoryURL.appendingPathComponent("\(addedURL).png")

    let videoURL2 = documentsDirectoryURL.appendingPathComponent("\(addedURL).mov")



    let mediaType = info[UIImagePickerController.InfoKey.mediaType] as AnyObject

    // Movie
    if mediaType as! String == kUTTypeMovie as String {
        let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL
        print("VIDEO URL: \(videoURL!)")

        let myVideoVarData = try! Data(contentsOf: videoURL! as URL)
        if !FileManager.default.fileExists(atPath: videoURL2.path) {
            do {
                try myVideoVarData.write(to: videoURL2)
                print("Video Added Successfully")
                print(videoURL2)
            } catch {
                print(error)
            }
        } else {
            print("Video not added")
        }

        photosNew.append("\(addedURL).mov")

        collectionView.reloadData()



    }


    // Image
    if mediaType as! String == kUTTypeImage as String {

        guard let image = info[.originalImage] as? UIImage else {
            return
        }
        if let imageData = image.pngData() {
            if !FileManager.default.fileExists(atPath: fileURL.path) {
                do {
                    try imageData.write(to: fileURL)
                    print("Image Added Successfully")
                    print(fileURL)
                } catch {
                    print(error)
                }
            } else {
                print("Image Not Added")
            }
        }

        photosNew.append("\(addedURL).png")

        collectionView.reloadData()

    }
  • 1
    The problem is that when you save your image as png it discards the image orientation. Just save as jpeg instead of png – Leo Dabus Dec 27 '18 at 19:30
  • Ah ok, thanks. I avoided jpeg due to compression/quality issues, but may look into this for future development. –  Dec 27 '18 at 19:33
  • Just use quality 1.0 there will be no visible loss – Leo Dabus Dec 27 '18 at 19:33
  • @LeoDabus Will try, thanks! –  Dec 27 '18 at 19:35
  • You are welcome If you need to use png you just need to create a new image context as shown in the duplicate link https://stackoverflow.com/questions/42098390/swift-png-image-being-saved-with-incorrect-orientation – Leo Dabus Dec 27 '18 at 19:37

1 Answers1

3

Created an UIImage extension to keep the image in the original position,

extension UIImage {
    func fixedOrientation() -> UIImage {
        
        if imageOrientation == .up {
            return self
        }
        
        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)
        case .right, .rightMirrored:
            transform = transform.translatedBy(x: 0, y: size.height)
            transform = transform.rotated(by: CGFloat.pi / -2)
        case .up, .upMirrored:
            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)
        case .up, .down, .left, .right:
            break
        }
        
        if let cgImage = self.cgImage, let colorSpace = cgImage.colorSpace,
            let ctx: CGContext = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) {
            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))
            }
            if let ctxImage: CGImage = ctx.makeImage() {
                return UIImage(cgImage: ctxImage)
            } else {
                return self
            }
        } else {
            return self
        }
    }
}

To use the extension's method, please should do the following with your image,

let orientedImage = image?.fixedOrientation()

In your case, inside func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) method,

...
guard let image = info[.originalImage] as? UIImage else {
        return
    }
let orientedImage = image.fixedOrientation()
if let imageData = orientedImage.pngData() {
...
Mohammad Eslami
  • 536
  • 1
  • 6
  • 17
Bappaditya
  • 9,494
  • 3
  • 20
  • 29