zic*_*c10 4 iphone objective-c uiview uiimageview ios
我正在尝试使用UIView可以放置在任何位置的叠加层来裁剪图像视图的子图像UIImageView.当UIImageView内容模式为'Aspect Fit'时,我正在借用类似帖子中的解决方案来解决这个问题.建议的解决方案是:
func computeCropRect(for sourceFrame : CGRect) -> CGRect {
let widthScale = bounds.size.width / image!.size.width
let heightScale = bounds.size.height / image!.size.height
var x : CGFloat = 0
var y : CGFloat = 0
var width : CGFloat = 0
var height : CGFloat = 0
var offSet : CGFloat = 0
if widthScale < heightScale {
offSet = (bounds.size.height - (image!.size.height * widthScale))/2
x = sourceFrame.origin.x / widthScale
y = (sourceFrame.origin.y - offSet) / widthScale
width = sourceFrame.size.width / widthScale
height = sourceFrame.size.height / widthScale
} else {
offSet = (bounds.size.width - (image!.size.width * heightScale))/2
x = (sourceFrame.origin.x - offSet) / heightScale
y = sourceFrame.origin.y / heightScale
width = sourceFrame.size.width / heightScale
height = sourceFrame.size.height / heightScale
}
return CGRect(x: x, y: y, width: width, height: height)
}
Run Code Online (Sandbox Code Playgroud)
问题是当图像视图是宽高比填充时使用此解决方案会导致裁剪的段不与叠加层的UIView位置完全对齐.我不太确定如何调整此代码以适应Aspect Fill或重新定位我的叠加层,UIView以便它与我正在尝试裁剪的片段按1:1排列.
更新使用下面的Matt答案解决
class ViewController: UIViewController {
@IBOutlet weak var catImageView: UIImageView!
private var cropView : CropView!
override func viewDidLoad() {
super.viewDidLoad()
cropView = CropView(frame: CGRect(x: 0, y: 0, width: 45, height: 45))
catImageView.image = UIImage(named: "cat")
catImageView.clipsToBounds = true
catImageView.layer.borderColor = UIColor.purple.cgColor
catImageView.layer.borderWidth = 2.0
catImageView.backgroundColor = UIColor.yellow
catImageView.addSubview(cropView)
let imageSize = catImageView.image!.size
let imageViewSize = catImageView.bounds.size
var scale : CGFloat = imageViewSize.width / imageSize.width
if imageSize.height * scale < imageViewSize.height {
scale = imageViewSize.height / imageSize.height
}
let croppedImageSize = CGSize(width: imageViewSize.width/scale, height: imageViewSize.height/scale)
let croppedImrect =
CGRect(origin: CGPoint(x: (imageSize.width-croppedImageSize.width)/2.0,
y: (imageSize.height-croppedImageSize.height)/2.0),
size: croppedImageSize)
let renderer = UIGraphicsImageRenderer(size:croppedImageSize)
let _ = renderer.image { _ in
catImageView.image!.draw(at: CGPoint(x:-croppedImrect.origin.x, y:-croppedImrect.origin.y))
}
}
@IBAction func performCrop(_ sender: Any) {
let cropFrame = catImageView.computeCropRect(for: cropView.frame)
if let imageRef = catImageView.image?.cgImage?.cropping(to: cropFrame) {
catImageView.image = UIImage(cgImage: imageRef)
}
}
@IBAction func resetCrop(_ sender: Any) {
catImageView.image = UIImage(named: "cat")
}
}
Run Code Online (Sandbox Code Playgroud)
我们将问题分为两部分:
考虑到UIImageView的大小和UIImage的大小,如果UIImageView的内容模式是Aspect Fill,那么UIImage中适合UIImageView的部分是什么?实际上,我们需要裁剪原始图像以匹配UIImageView实际显示的内容.
给定UIImageView中的任意rect,裁剪图像的哪一部分(在第1部分中得出)对应于?
第一部分是有趣的部分,所以让我们试试吧.(第二部分将变得微不足道.)
这是我将使用的原始图像:
该图像是1000x611.这是它缩小的样子(但请记住,我将在整个过程中使用原始图像):
但是,我的图像视图将是139x182,并设置为Aspect Fill.当它显示图像时,它看起来像这样:
我们要解决的问题是:如果我的图像视图设置为Aspect Fill ,原始图像的哪个部分将在我的图像视图中显示?
开始了.假设这iv是图像视图:
let imsize = iv.image!.size
let ivsize = iv.bounds.size
var scale : CGFloat = ivsize.width / imsize.width
if imsize.height * scale < ivsize.height {
scale = ivsize.height / imsize.height
}
let croppedImsize = CGSize(width:ivsize.width/scale, height:ivsize.height/scale)
let croppedImrect =
CGRect(origin: CGPoint(x: (imsize.width-croppedImsize.width)/2.0,
y: (imsize.height-croppedImsize.height)/2.0),
size: croppedImsize)
Run Code Online (Sandbox Code Playgroud)
所以现在我们已经解决了问题:croppedImrect是在图像视图中显示的原始图像的区域.让我们继续使用我们的知识,通过将图像实际裁剪为与图像视图中显示的图像匹配的新图像:
let r = UIGraphicsImageRenderer(size:croppedImsize)
let croppedIm = r.image { _ in
iv.image!.draw(at: CGPoint(x:-croppedImrect.origin.x, y:-croppedImrect.origin.y))
}
Run Code Online (Sandbox Code Playgroud)
结果是这个图像(忽略灰色边框):
但是,看哪,这是正确的答案!我从原始图像中精确提取了图像视图内部描绘的区域.
所以现在你拥有了所需的所有信息.croppedIm是实际显示在图像视图的剪切区域中的UIImage.scale是图像视图和该图像之间的比例.因此,您可以轻松解决您最初提出的问题!给定图像视图上的任何矩形,在图像视图的边界坐标中,您只需应用比例(即将其所有四个属性除以scale) - 现在您具有与其一部分相同的矩形croppedIm.
(观察我们真的不需要裁剪原始图像croppedIm;实际上,知道如何执行该作物就足够了.重要的信息是scale与之相关origin的croppedImRect;鉴于这些信息,你可以采取强加在图像视图上的矩形,缩放它,并将其偏移以获得原始图像的所需矩形.)
编辑我添加了一个小小的截屏视频,以表明我的方法可以作为概念证明:
编辑还在这里创建了一个可下载的示例项目:
但请注意,我无法保证URL将永久存在,因此请阅读上面的讨论以了解所使用的方法.
| 归档时间: |
|
| 查看次数: |
1698 次 |
| 最近记录: |