How to generate an UIImage from AVCapturePhoto with correct orientation?

后端 未结 5 922
清酒与你
清酒与你 2020-12-28 15:29

I am calling AVFoundation\'s delegate method to handle a photo capture, but I am having difficulty converting the AVCapturePhoto it generates into

5条回答
  •  情话喂你
    2020-12-28 16:09

    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
        }
    }
    

提交回复
热议问题