在 UIImageView 中裁剪 UIImage 的可见部分以获得显着性

问题描述 投票:0回答:1

我正在做基于注意力的显着性,应该将图像传递给请求。当contentMode为ScaleAspectFill时,请求的结果不正确,因为我使用的是完整图像(在屏幕部分不可见)

我正在尝试裁剪 UIImage,但此方法无法正确裁剪

 let newImage = cropImage(imageToCrop: imageView.image, toRect: imageView.frame)


 func cropImage(imageToCrop: UIImage?, toRect rect: CGRect) -> UIImage? {
        guard let imageRef = imageToCrop?.cgImage?.cropping(to: rect) else {
            return nil
        }
        let cropped: UIImage = UIImage(cgImage: imageRef)
        return cropped
    }

如何仅针对图像的可见部分(当更改 contentMode 时会发生变化)发出显着性请求?

swift uiimageview crop apple-vision
1个回答
0
投票

如果我正确理解你的目标...

假设我们有这个

640 x 360
图像:

enter image description here

我们使用

240 x 240
...
 将其显示在 
.scaleAspectFill

图像视图中

它看起来像这样(红色轮廓是图像视图框架):

enter image description here

并且,与

.clipsToBounds = true
:

enter image description here

我们想要生成这个

360 x 360
图像(也就是说,我们想要保持原始图像分辨率......我们不想最终得到一个
240 x 240
图像):

enter image description here

要裁剪图像的可见部分,我们需要计算缩放后的矩形,包括偏移量:

func cropImage(imageToCrop: UIImage?, toRect rect: CGRect) -> UIImage? {
    guard let imageRef = imageToCrop?.cgImage?.cropping(to: rect) else {
        return nil
    }
    let cropped: UIImage = UIImage(cgImage: imageRef)
    return cropped
}

func myCrop(imgView: UIImageView) -> UIImage? {
    
    // get the image from the imageView
    guard let img = imgView.image else { return nil }
    
    // image view rect
    let vr: CGRect = imgView.bounds
    
    // image size -- we need to account for scale
    let imgSZ: CGSize = CGSize(width: img.size.width * img.scale, height: img.size.height * img.scale)
    
    let viewRatio: CGFloat = vr.width / vr.height
    let imgRatio: CGFloat = imgSZ.width / imgSZ.height
    
    var newRect: CGRect = .zero
    
    // calculate the rect that needs to be clipped from the full image
    
    if viewRatio > imgRatio {
        
        // image has a wider aspect ratio than the image view
        //  so top and bottom will be clipped
        let f: CGFloat = imgSZ.width / vr.width
        let h: CGFloat = vr.height * f
        newRect.origin.y = (imgSZ.height - h) * 0.5
        newRect.size.width = imgSZ.width
        newRect.size.height = h
        
    } else {
        
        // image has a narrower aspect ratio than the image view
        //  so left and right will be clipped
        let f: CGFloat = imgSZ.height / vr.height
        let w: CGFloat = vr.width * f
        newRect.origin.x = (imgSZ.width - w) * 0.5
        newRect.size.width = w
        newRect.size.height = imgSZ.height
        
    }
    
    return cropImage(imageToCrop: img, toRect: newRect)
}

并这样称呼它:

if let croppedImage = myCrop(imgView: theImageView) {
    // do something with the new image
}
© www.soinside.com 2019 - 2024. All rights reserved.