我须要制做一个快速更新 UIImage 的功能,一开始使用 UIImageView 来显示图片,因此须要频繁的调用 UIImageView.image = newImage
方法来更新图片。代码看起来像这样。git
func onSomethingChanged() { myUIImageView.image = newImage }
这样更新图片很是的卡顿,操做和画面响应有必定的滞后,体验很差,所以考虑本身作一个 UIView 来绘制图片,看看是否能够解决。github
因而本身自定义了一个 View,继承 UIView 来作,在 draw(rect:)
方法里面作文章。swift
首先固然是简单粗暴直接 UIImage.draw(in: bounds)
先看看效果。ide
var image: UIImage? { didSet { setNeedsDisplay() } } override func draw(_ rect: CGRect) { guard let ctx = UIGraphicsGetCurrentContext() else { return } ctx.addRect(bounds) ctx.setFillColor(UIColor.black.cgColor) ctx.fillPath() if var im = image { im.draw(in: bounds) } }
很好,更新速度很快,是理想的效果,不过目前画面是拉伸的,同时还有锯齿。spa
下图中左边是理想的显示效果,右边则是实际的显示效果,能够看到明显的锯齿。code
通过我一番搜索尝试了如下配置,均无任何帮助:继承
ctx.setShouldAntialias(true) ctx.setAllowsAntialiasing(true) ctx.interpolationQuality = .high layer.allowsEdgeAntialiasing = true layer.minificationFilter = .trilinear
我回忆起以前用 CGImageContext 缩放图片的时候也没有这个问题啊,难道是由于 UIView 自带的这个 CGContext 没法很好的缩放图片?图片
因而我想到一个方案:先用一个 CGImageContext 把图片画上去,再弄出一个 CGImage 来,再把这个 CGImage 放到 UIView 的 CGContext 上是否能够呢?get
override func draw(_ rect: CGRect) { guard let ctx = UIGraphicsGetCurrentContext() else { return } ctx.addRect(bounds) ctx.setFillColor(UIColor.black.cgColor) ctx.fillPath() if var im = image { // 计算出在当前view的bounds内,保持图片比例最大的size let size = Math.getMaxSizeWithAspect(size: CGSize(width: bounds.width, height: bounds.height), radioWidthToHeight: im.size.width / im.size.height) // 再换算成pixel size let pixelSize = CGSize(width: size.width * layer.contentsScale, height: size.height * layer.contentsScale) // 建立一个和 pixel size 同样大的 ImageContext UIGraphicsBeginImageContextWithOptions(pixelSize, true, 1) guard let imgCtx = UIGraphicsGetCurrentContext() else { return } // 把 UIImage 画到这个 ImageContext 上 im.draw(in: CGRect(x: 0, y: 0, width: pixelSize.width, height: pixelSize.height)) // 再把 cgImg 搞出来 guard let cgImg = imgCtx.makeImage() else { return } // 图片直接绘制的话,会上下翻转,所以先翻转一下 ctx.scaleBy(x: 1, y: -1) ctx.translateBy(x: 0, y: -bounds.height) // 再把cgImg 画到 UIView 的 Context 上,大功告成 ctx.draw(cgImg, in: CGRect(x: (bounds.width - size.width) / 2, y: (bounds.height - size.height) / 2, width: size.width, height: size.height)) } }
问题就此获得解决。it
其实个人自己需求是能快速的更新 image,由于是在作一块相似后期调照片的软件,有不少滑块,拖动后经过 CIFilter 修改照片,因此须要一直更新图像,若是有更好的方法,不妨告诉我一下:D
若是以上内容对你有所帮助,请在这些平台上关注我吧,谢谢:P