在drawRect中绘制时图像稍微模糊了一点 (Swift)

3
我正在使用 Swift 编写圆形裁剪函数。几乎所有功能都已经实现,但是当我保存裁剪后的照片时,它会略微模糊:

enter image description here

enter image description here

不确定这里是否可见,但在我的iPhone上我可以看到一个微小的模糊区别。我没有放大图像的实际大小。我正在使用最大缩放因子为1.0的UIScrollView。裁剪代码如下:

  func didTapOk() {

    let scale = scrollView.zoomScale
    let newSize = CGSize(width: image!.size.width*scale, height: image!.size.height*scale)
    let offset = scrollView.contentOffset

    UIGraphicsBeginImageContext(CGSize(width: 240, height: 240))
    let circlePath = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 240, height: 240))
    circlePath.addClip()
    var sharpRect = CGRect(x: -offset.x, y: -offset.y, width: newSize.width, height: newSize.height)
    sharpRect = CGRectIntegral(sharpRect)

    image?.drawInRect(sharpRect)
    let finalImage = UIGraphicsGetImageFromCurrentImageContext()
    UIImageWriteToSavedPhotosAlbum(finalImage, nil, nil, nil)

}

我正在尝试使用CGRectIntegral来改善结果,但似乎没有任何区别。您有什么建议可以帮助我改善这个问题吗?

3个回答

14

发生的情况是你的作物因为没有考虑到屏幕的比例(无论你是否使用Retina显示屏等)而变得模糊。

使用UIGraphicsBeginImageContextWithOptions(CGSize(width: 240, height: 240), true, 0)来适应Retina屏幕。请查看这里以获取有关如何使用此函数的更多详细信息。


1
是的。这是正确的解决方案。(投票)我正准备发布相同的答案,但你比我先了。 - Duncan C
1
搞定了。现在完美了。谢谢你的帮助!然而,圆形的外部似乎从未是透明的。实际上是白色的。在更改为您描述的代码后,现在变成了黑色。有什么想法吗? - Kex
1
@Kex,你正在将true传递到函数的opaque参数中。如果你想要透明度,应该传递false - Hamish

3
我怀疑虽然上面的答案对你有用,但它只适用于屏幕比例与图像比例相同的情况。
由于你不是从屏幕本身渲染图像(你是从一个UIImage渲染到另一个UIImage),因此屏幕比例应该是无关紧要的。
相反,你应该在创建上下文时传入图像的比例,例如:
UIGraphicsBeginImageContextWithOptions(CGSize(width: 240, height: 240), false, image.scale)

抱歉回复晚了。我尝试将比例(scale)更改为image.scale,但生成的图像模糊了。虽然对于比例设置为0就很好。有什么原因吗? - Kex
@Kex 你正在使用什么尺寸和比例的图片?如果比例低于屏幕比例 - iOS 在以屏幕比例呈现图像时会有效地对其进行上采样。虽然这在设备本身上看起来可能还好,但是如果您在图像编辑器中查看它(尝试放大图像) - 您应该会看到上采样的效果。我不确定为什么使用图像比例时对您不起作用...我刚刚自己尝试了一下,并在缩放输出图像时得到了这个结果(https://infinit.io/_/E5UjCX6)。 - Hamish

3

以下是在Swift 3中禁用任何插值的方法。

    UIGraphicsBeginImageContextWithOptions(imageSize, false, UIScreen.main.scale)    
    let context = UIGraphicsGetCurrentContext()
    context?.interpolationQuality = CGInterpolationQuality.none

另外,由于通常这是用于像素绘画目的,您可能需要添加:

    // Ensure the image is not drawn upside down 
    context?.saveGState()
    context?.translateBy(x: 0.0, y: maxHeight)
    context?.scaleBy(x: 1.0, y: -1.0)

    // Make the drawing
    context?.draw(yourImage, in: CGRect(x: 0, y: 0, width: maxWidth, height: maxHeight))

    // Restore the GState of the context
    context?.restoreGState()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接