Losing image orientation while converting an image to CGImage

后端 未结 7 2078
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-31 04:30

I\'m facing an image orientation issue when cropping a square portion of an image out of a rectangular original image. When image is in landscape, it\'s fine. But when it is

7条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-31 05:08

    This is THE answer, credit to @awolf (Cropping an UIImage). Handles scale and orientation perfectly. Just call this method on the image you want to crop, and pass in the cropping CGRect without worrying about scale or orientation. Feel free to check whether cgImage is nil instead of force unwrapping it like I did here.

    extension UIImage {
        func croppedInRect(rect: CGRect) -> UIImage {
            func rad(_ degree: Double) -> CGFloat {
                return CGFloat(degree / 180.0 * .pi)
            }
    
            var rectTransform: CGAffineTransform
            switch imageOrientation {
            case .left:
                rectTransform = CGAffineTransform(rotationAngle: rad(90)).translatedBy(x: 0, y: -self.size.height)
            case .right:
                rectTransform = CGAffineTransform(rotationAngle: rad(-90)).translatedBy(x: -self.size.width, y: 0)
            case .down:
                rectTransform = CGAffineTransform(rotationAngle: rad(-180)).translatedBy(x: -self.size.width, y: -self.size.height)
            default:
                rectTransform = .identity
            }
            rectTransform = rectTransform.scaledBy(x: self.scale, y: self.scale)
    
            let imageRef = self.cgImage!.cropping(to: rect.applying(rectTransform))
            let result = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
            return result
        }
    }
    

    Another note: if you are working with imageView embedded in a scrollView, there is one additional step, you have to take the zoom factor into account. Assuming your imageView spans the entire content view of the scrollView, and you use the bounds of the scrollView as the cropping frame, the cropped image can be obtained as

    let ratio = imageView.image!.size.height / scrollView.contentSize.height
    let origin = CGPoint(x: scrollView.contentOffset.x * ratio, y: scrollView.contentOffset.y * ratio)
    let size = CGSize(width: scrollView.bounds.size.width * ratio, let height: scrollView.bounds.size.height * ratio)
    let cropFrame = CGRect(origin: origin, size: size)
    let croppedImage = imageView.image!.croppedInRect(rect: cropFrame)
    

提交回复
热议问题