乐趣区

关于iOS开发:IOS-自定义View绘制UIImage出现锯齿如何解决

我须要制作一个疾速更新 UIImage 的性能,一开始应用 UIImageView 来显示图片,所以须要频繁的调用 UIImageView.image = newImage 办法来更新图片。代码看起来像这样。

func onSomethingChanged() {myUIImageView.image = newImage}

这样更新图片十分的卡顿,操作和画面响应有肯定的滞后,体验不好,因而思考本人做一个 UIView 来绘制图片,看看是否能够解决。

于是本人自定义了一个 View,继承 UIView 来做,在 draw(rect:) 办法外面做文章。

首先当然是简略粗犷间接 UIImage.draw(in: bounds) 先看看成果。

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)
    }
}

很好,更新速度很快,是现实的成果,不过目前画面是拉伸的,同时还有锯齿。

下图中右边是现实的显示成果,左边则是理论的显示成果,能够看到显著的锯齿。

通过我一番搜寻尝试了以下配置,均无任何帮忙:

ctx.setShouldAntialias(true)
ctx.setAllowsAntialiasing(true)
ctx.interpolationQuality = .high
layer.allowsEdgeAntialiasing = true
layer.minificationFilter = .trilinear

我回忆起之前用 CGImageContext 缩放图片的时候也没有这个问题啊,难道是因为 UIView 自带的这个 CGContext 无奈很好的缩放图片?

于是我想到一个计划:先用一个 CGImageContext 把图片画下来,再弄出一个 CGImage 来,再把这个 CGImage 放到 UIView 的 CGContext 上是否能够呢?

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))
    }
}

问题就此失去解决。

其实我的自身需要是能疾速的更新 image,因为是在做一块相似前期调照片的软件,有很多滑块,拖动后通过 CIFilter 批改照片,所以须要始终更新图像,如果有更好的办法,无妨通知我一下:D

如果以上内容对你有所帮忙,请在这些平台上关注我吧,谢谢:P

退出移动版