I am calling AVFoundation
\'s delegate method to handle a photo capture, but I am having difficulty converting the AVCapturePhoto
it generates into
To create our image with the right orientation we need to enter the correct UIImage.Orientation
when we initialize the image.
Its best to use the CGImagePropertyOrientation
that comes back from the photoOutput delegate to get the exact orientation the camera session was in when the picture was taken. Only problem here is that while the enum values between UIImage.Orientation
and CGImagePropertyOrientation
are the same, the raw values are not. Apple suggests a simple mapping to fix this.
https://developer.apple.com/documentation/imageio/cgimagepropertyorientation
Here is my implementation:
AVCapturePhotoCaptureDelegate
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let _ = error {
// Handle Error
} else if let cgImageRepresentation = photo.cgImageRepresentation(),
let orientationInt = photo.metadata[String(kCGImagePropertyOrientation)] as? UInt32,
let imageOrientation = UIImage.Orientation.orientation(fromCGOrientationRaw: orientationInt) {
// Create image with proper orientation
let cgImage = cgImageRepresentation.takeUnretainedValue()
let image = UIImage(cgImage: cgImage,
scale: 1,
orientation: imageOrientation)
}
}
Extension for Mapping
extension UIImage.Orientation {
init(_ cgOrientation: CGImagePropertyOrientation) {
// we need to map with enum values becuase raw values do not match
switch cgOrientation {
case .up: self = .up
case .upMirrored: self = .upMirrored
case .down: self = .down
case .downMirrored: self = .downMirrored
case .left: self = .left
case .leftMirrored: self = .leftMirrored
case .right: self = .right
case .rightMirrored: self = .rightMirrored
}
}
/// Returns a UIImage.Orientation based on the matching cgOrientation raw value
static func orientation(fromCGOrientationRaw cgOrientationRaw: UInt32) -> UIImage.Orientation? {
var orientation: UIImage.Orientation?
if let cgOrientation = CGImagePropertyOrientation(rawValue: cgOrientationRaw) {
orientation = UIImage.Orientation(cgOrientation)
} else {
orientation = nil // only hit if improper cgOrientation is passed
}
return orientation
}
}