// // UIImage+Orientation.swift // WeScan // // Created by Boris Emorine on 2/16/18. // Copyright © 2018 WeTransfer. All rights reserved. // import Foundation @available(iOS 10, *) extension UIImage { /// Returns the same image with a portrait orientation. func applyingPortraitOrientation() -> UIImage { switch imageOrientation { case .up: return rotated(by: Measurement(value: Double.pi, unit: .radians), options: []) ?? self case .down: return rotated(by: Measurement(value: Double.pi, unit: .radians), options: [.flipOnVerticalAxis, .flipOnHorizontalAxis]) ?? self case .left: return self case .right: return rotated(by: Measurement(value: Double.pi / 2.0, unit: .radians), options: []) ?? self default: return self } } /// Data structure to easily express rotation options. struct RotationOptions: OptionSet { let rawValue: Int static let flipOnVerticalAxis = RotationOptions(rawValue: 1) static let flipOnHorizontalAxis = RotationOptions(rawValue: 2) } /// Rotate the image by the given angle, and perform other transformations based on the passed in options. /// /// - Parameters: /// - rotationAngle: The angle to rotate the image by. /// - options: Options to apply to the image. /// - Returns: The new image rotated and optentially flipped (@see options). func rotated(by rotationAngle: Measurement, options: RotationOptions = []) -> UIImage? { guard let cgImage = self.cgImage else { return nil } let rotationInRadians = CGFloat(rotationAngle.converted(to: .radians).value) let transform = CGAffineTransform(rotationAngle: rotationInRadians) let cgImageSize = CGSize(width: cgImage.width, height: cgImage.height) var rect = CGRect(origin: .zero, size: cgImageSize).applying(transform) rect.origin = .zero let format = UIGraphicsImageRendererFormat() format.scale = 1 let renderer = UIGraphicsImageRenderer(size: rect.size, format: format) let image = renderer.image { renderContext in renderContext.cgContext.translateBy(x: rect.midX, y: rect.midY) renderContext.cgContext.rotate(by: rotationInRadians) let x = options.contains(.flipOnVerticalAxis) ? -1.0 : 1.0 let y = options.contains(.flipOnHorizontalAxis) ? 1.0 : -1.0 renderContext.cgContext.scaleBy(x: CGFloat(x), y: CGFloat(y)) let drawRect = CGRect(origin: CGPoint(x: -cgImageSize.width / 2.0, y: -cgImageSize.height / 2.0), size: cgImageSize) renderContext.cgContext.draw(cgImage, in: drawRect) } return image } }