【问题标题】:cropping(to: CGRect) doesn't crop correctly裁剪(到:CGRect)没有正确裁剪
【发布时间】:2020-12-25 11:04:34
【问题描述】:

我正在为我的应用程序制作扫描仪,但是当我裁剪图像时,它总是错误地裁剪它。

图像上的裁剪矩形-

裁剪后的图像-

我的矩形裁剪代码...

func croppedImage(rect: CGRect) -> UIImage {
    print("rect: \(rect)")
    UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)

    let context = UIGraphicsGetCurrentContext()! as CGContext

    let drawRect : CGRect = CGRect(x: -rect.origin.x, y: -rect.origin.y, width: self.size.width, height: self.size.height)

    context.clip(to: CGRect(x:0, y:0, width: rect.size.width, height: rect.size.height))

    self.draw(in: drawRect)

    let croppedImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return croppedImage
}

我尝试了无数不同的代码 sn-ps 来正确裁剪图像,它们都得到了相同的结果。

docVC.croppedImage = pdfImage.croppedImage(rect: croppingRect)

docVC 是一个视图控制器,我将图像传递到 pdfImage 是您在第一张图片中看到的整个图像 croppingRect 是应该没问题的矩形

我真的需要这方面的帮助,过去 2 小时我一直在尝试只裁剪一张图像。

【问题讨论】:

    标签: swift xcode uiimage crop swift5


    【解决方案1】:

    您是否在图像视图中使用了其中一种缩放内容模式?如果是这样,图像的尺寸与图像视图的尺寸不同,您有两种选择:

    • 您可以在尝试裁剪之前调整图像大小以匹配图像视图的尺寸。然后一个标准的种植程序就可以工作了。但这可能会导致分辨率下降或引入像素化。

    • 更好的解决方案是在裁剪之前将裁剪矩形转换为图像尺寸的坐标。

    例如:

    extension UIImageView {
        func image(at rect: CGRect) -> UIImage? {
            guard
                let image = image,
                let rect = convertToImageCoordinates(rect)
            else {
                return nil
            }
    
            return image.cropped(to: rect)
        }
    
        func convertToImageCoordinates(_ rect: CGRect) -> CGRect? {
            guard let image = image else { return nil }
    
            let imageSize = CGSize(width: image.size.width, height: image.size.height)
            let imageCenter = CGPoint(x: imageSize.width / 2, y: imageSize.height / 2)
    
            let imageViewRatio = bounds.width / bounds.height
            let imageRatio = imageSize.width / imageSize.height
    
            let scale: CGPoint
    
            switch contentMode {
            case .scaleToFill:
                scale = CGPoint(x: imageSize.width / bounds.width, y: imageSize.height / bounds.height)
    
            case .scaleAspectFit:
                let value: CGFloat
                if imageRatio < imageViewRatio {
                    value = imageSize.height / bounds.height
                } else {
                    value = imageSize.width / bounds.width
                }
                scale = CGPoint(x: value, y: value)
    
            case .scaleAspectFill:
                let value: CGFloat
                if imageRatio > imageViewRatio {
                    value = imageSize.height / bounds.height
                } else {
                    value = imageSize.width / bounds.width
                }
                scale = CGPoint(x: value, y: value)
    
            case .center:
                scale = CGPoint(x: 1, y: 1)
    
            // unhandled cases include
            // case .redraw:
            // case .top:
            // case .bottom:
            // case .left:
            // case .right:
            // case .topLeft:
            // case .topRight:
            // case .bottomLeft:
            // case .bottomRight:
    
            default:
                fatalError("Unexpected contentMode")
            }
    
            var rect = rect
            if rect.width < 0 {
                rect.origin.x += rect.width
                rect.size.width = -rect.width
            }
    
            if rect.height < 0 {
                rect.origin.y += rect.height
                rect.size.height = -rect.height
            }
    
            return CGRect(x: (rect.minX - bounds.midX) * scale.x + imageCenter.x,
                          y: (rect.minY - bounds.midY) * scale.y + imageCenter.y,
                          width: rect.width * scale.x,
                          height: rect.height * scale.y)
        }
    }
    

    现在,我只处理四种可能的内容模式,如果你想处理更多,你必须自己实现这些。但希望这能说明模式,即在尝试裁剪之前将选择 CGRect 转换为图像内的坐标。

    FWIW,这是我使用的裁剪方法,cropped(to:) 来自 https://stackoverflow.com/a/28513086/1271826,使用更现代的 UIGraphicsImageRenderer,如果可以的话,使用 CoreGraphics 裁剪等。但是使用你想要的任何裁剪程序,但只要确保将坐标转换为适合图像的坐标。

    【讨论】:

    • 非常感谢您的回答,我已经尝试了几个小时。这是我第一次使用图像裁剪等。再次感谢您。
    猜你喜欢
    • 2016-06-10
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 2015-10-28
    • 2013-08-21
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    相关资源
    最近更新 更多