裁剪 UIImage 没有产生预期的作物 - 迅速?

Posted

技术标签:

【中文标题】裁剪 UIImage 没有产生预期的作物 - 迅速?【英文标题】:Cropping UIImage not yielding expected crop - swift? 【发布时间】:2018-09-17 13:37:21 【问题描述】:

我正在尝试裁剪图像,但裁剪没有产生 UIImage 的预期部分。图像看起来没有方向和镜像。这很混乱。

 @IBOutlet weak var imgPreViewOutlet: UIImageView!

 guard
        let cgImage = self.imgPreViewOutlet.image.cgImage else return


// NORMALISE COORDINATES
let topXn = TOP_LEFT.x/screenWidth
let topYn = TOP_LEFT.y/screenHeight
let widthn = (TOP_RIGHT.x - TOP_LEFT.x)/screenWidth
let heightn = (BOTTOM_RIGHT.y - TOP_RIGHT.y)/screenHeight


// DIMENSION OF CGIMAGE
let cgImgWidth = cgImage.width
let cgImgHeight = cgImage.height

let cropRect = CGRect.init(x: topXn * CGFloat.init(widthn) , y: topYn * CGFloat.init(heightn), width: widthn * CGFloat.init(cgImgWidth), height: heightn * CGFloat.init(cgImgHeight))

if let cgCropImged = cgImage.cropping(to: cropRect)

        print("cropRect: \(cropRect)")

        self.imgPreViewOutlet.image = UIImage.init(cgImage: cgCropImged)
    

裁剪:

【问题讨论】:

@JonJ 提出了一个很好的观点。我可以添加第二个吗?您使用的是什么具体的CIFilter?你没有在你的代码中发布它。但根据您的图片,我强烈建议使用CIPerspectiveCorrection,而不是CICrop 或(正如您发布的代码所暗示的)CoreGraphics。 我目前没有使用任何过滤器,我只是想要裁剪矩形作为第一步。但感谢您的提示! 既然您将其标记为 CoreImage,我假设您这样做了。您的图像正是 CIPerspectiveCorrection 可以做到的。这个过滤器需要 any 4 个点 - 它不需要是...平行四边形? CGRect?...自从我学习几何学以来已经有几十年了......并且种植了其他所有东西。如果您之前没有使用过任何过滤器,我可以发布一个相当简单的示例(Swift 4)。让我知道。 developer.apple.com/library/archive/documentation/… @dfd 如果您可以在 swift 4 中发布一个示例,那就太好了! 【参考方案1】:

根据要求,这里有一个使用CIPerspectiveCorrection 裁剪图像的示例。我下载并使用 Sketch 来获取示例图像中 4 CGPoints 的近似值。

    let inputBottomLeft = CIVector(x: 38, y: 122)
    let inputTopLeft = CIVector(x: 68, y: 236)
    let inputTopRight = CIVector(x: 146, y: 231)
    let inputBottomRight = CIVector(x: 151, y: 96)

    let filter = CIFilter(name: "CIPerspectiveCorrection")
    filter?.setValue(inputTopLeft, forKey: "inputTopLeft")
    filter?.setValue(inputTopRight, forKey: "inputTopRight")
    filter?.setValue(inputBottomLeft, forKey: "inputBottomLeft")
    filter?.setValue(inputBottomRight, forKey: "inputBottomRight")

    filter?.setValue(ciOriginal, forKey: "inputImage")
    let ciOutput = filter?.outputImage

请注意几点:

永远不要忘记 CoreImage 的最重要的一点是 CIImage 的原点在 bottom 左侧,而不是 top 左侧。您需要“翻转” Y 轴点。 UIImage 有大小,而CIImage 有范围。这些都是一样的。 (唯一不是这样的情况是使用 CIFIlter 来“创建”一些东西——一种颜色,一个平铺的图像——然后它是无限的。) CIVector 可以有很多属性。在这种情况下,我使用 X/Y 签名,它是 CGPoint 的直接副本,除了 Y 轴被翻转。 我有一个使用UIImageView 的sample project here。请注意,模拟器上的性能远不及真实设备上的性能——我建议在涉及 CoreImage 的任何时候使用设备。此外,我将输出 CIImage 直接转换为 UIImage。如果您正在寻找性能,通常最好使用CIContextCoreGraphics

根据您的输入,这是输出:

【讨论】:

这个解决方案非常完美,因为我一直在尝试裁剪四边形。我正朝着一个非常迂回和密集的方向前进。非常感谢! 一个问题。当您说“翻转”y轴时。所以如果我有一个 CGPoint(x: 60, y: 60) 这在翻转时会转化为什么? 哼。四边形 - 我的描述很接近。无论如何 - 翻转 Y 轴。我使用的图像是 180 宽 x 320 高。假设您有一个 X == 38 和 Y == 188 的 CGPoint(在本例中为 inputBottomLeft)。保持 X 值,但通过获取高度(310)并减去 UIImage Y 值(188)“翻转”Y . 310 - 188 = 122。前段时间我有一个简单的函数可以做到这一点,但我找不到它。如果您在此处遵循 my 示例,那么您知道 CGPoint(x:60, y:60) 转换为...嗯,X 是 60... 但 Y 取决于 maxYCGRect.height 值。跨度> 根据您的上述解决方案,如果您能提出建议,我添加了对这个问题的跟进:***.com/questions/52374579/… 我下载了你的示例项目,但很遗憾它是空的。【参考方案2】:

核心图形坐标来自左下角的原点,UIKit 坐标来自左上角。我认为你混淆了两者。

这可能会有所帮助:

How to compensate the flipped coordinate system of core graphics for easy drawing?

【讨论】:

以上是关于裁剪 UIImage 没有产生预期的作物 - 迅速?的主要内容,如果未能解决你的问题,请参考以下文章

使用 VNRectangleObservation 裁剪 UIImage

UIScrollView 中图像上的cropImage 方法的问题会产生错误的图像

定义作物的大小

将方形 UIImage 裁剪为圆角矩形

android.os.TransactionTooLargeException 与作物活动

裁剪 UIImage 的部分以获得新的纵横比并缩小到大小