Image Orientation
Image Orientation
If your images are sideways or upside-down, you probably aren’t alone! We can fix this by implementing an ImageUtilities class, a chunk of code someone else wrote. Unlike Apple classes we’ve inherited from, we have to manually add the code into our project. Follow the directions below to implement this.
Build an ImageUtilities
class
-
Add a new
Swift
file: File ➡ New ➡ File ➡ iOS ➡ Swift File ➡ ClickNext
➡ name the dileImageUtilities
-
Copy and paste the following code into that file. It’s not important that you understand this, but you can feel free to read through it if you are interested! It will essentially check the orientation of an image and change that orientation if it isn’t currently presented as it was originally taken.
import UIKit
class ImageUtilities {
public static func fixImageOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {
guard let imgRef = imageSource.cgImage else {
return nil
}
let width = CGFloat(imgRef.width)
let height = CGFloat(imgRef.height)
var bounds = CGRect(x: 0, y: 0, width: width, height: height)
var scaleRatio : CGFloat = 1
if (width > maxResolution || height > maxResolution) {
scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
bounds.size.height = bounds.size.height * scaleRatio
bounds.size.width = bounds.size.width * scaleRatio
}
var transform = CGAffineTransform.identity
let orient = imageSource.imageOrientation
let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))
switch(imageSource.imageOrientation) {
case .up:
transform = .identity
case .upMirrored:
transform = CGAffineTransform
.init(translationX: imageSize.width, y: 0)
.scaledBy(x: -1.0, y: 1.0)
case .down:
transform = CGAffineTransform
.init(translationX: imageSize.width, y: imageSize.height)
.rotated(by: CGFloat.pi)
case .downMirrored:
transform = CGAffineTransform
.init(translationX: 0, y: imageSize.height)
.scaledBy(x: 1.0, y: -1.0)
case .left:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: 0, y: imageSize.width)
.rotated(by: 3.0 * CGFloat.pi / 2.0)
case .leftMirrored:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: imageSize.height, y: imageSize.width)
.scaledBy(x: -1.0, y: 1.0)
.rotated(by: 3.0 * CGFloat.pi / 2.0)
case .right :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: imageSize.height, y: 0)
.rotated(by: CGFloat.pi / 2.0)
case .rightMirrored:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(scaleX: -1.0, y: 1.0)
.rotated(by: CGFloat.pi / 2.0)
}
UIGraphicsBeginImageContext(bounds.size)
if let context = UIGraphicsGetCurrentContext() {
if orient == .right || orient == .left {
context.scaleBy(x: -scaleRatio, y: scaleRatio)
context.translateBy(x: -height, y: 0)
} else {
context.scaleBy(x: scaleRatio, y: -scaleRatio)
context.translateBy(x: 0, y: -height)
}
context.concatenate(transform)
context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
}
let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageCopy
}
}
extension UIImage {
func createThumbnail() -> UIImage{
let ratio = self.size.width / self.size.height
return self.scaleImage(toSize: CGSize(width: 100, height: 100 / ratio))!
}
func scaleImage(toSize newSize: CGSize) -> UIImage? {
let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
if let context = UIGraphicsGetCurrentContext() {
context.interpolationQuality = .high
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height)
context.concatenate(flipVertical)
context.draw(self.cgImage!, in: newRect)
let newImage = UIImage(cgImage: context.makeImage()!)
UIGraphicsEndImageContext()
return newImage
}
return nil
}
}
- Now, that
ImageUtilities
class won’t magically work. In theAddPhotoViewController
, we need to add one line of code and change one line of code. In yourimagePickerController
you currently have something like this:
if let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
photoToSave.image = selectedImage
}
Before we assign the selectedImage
to the photoToSave.image
, we need to “fix” it:
if let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
let fixedImaged = ImageUtilities.fixImageOrientation(imageSource: selectedImage)
photoToSave.image = fixedImaged
}
Now, re-run your application
- You’ll see that pictures you saved before this will still be sideways or upside-down because they were stored that way. Add a new picture and check its orientation - it should be correct!