You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绘制和合成UIImage时如何正确应用scale适配Retina屏幕

适配方案

你代码中仅addCentered方法存在Retina适配问题:UIGraphicsBeginImageContext默认缩放系数固定为1,在2x/3x Retina屏上渲染的图片会出现像素模糊。你现有circularImage方法使用的UIGraphicsBeginImageContextWithOptions第三个参数传0的写法已经符合适配要求,0代表自动匹配当前屏幕的缩放系数,无需额外修改。

修改后的完整扩展代码

extension UIImage
{
    var width: CGFloat
    {
        return size.width
    }
    
    var height: CGFloat
    {
        return size.height
    }
    
    private static func circularImage(diameter: CGFloat, color: UIColor) -> UIImage
    {
        // 此处已适配Retina,最后一个参数0为自动取当前屏幕scale
        UIGraphicsBeginImageContextWithOptions(CGSize(width: diameter, height: diameter), false, 0)
        let context = UIGraphicsGetCurrentContext()!
        context.saveGState()

        let rect = CGRect(x: 0, y: 0, width: diameter, height: diameter)
        context.setFillColor(color.cgColor)
        context.fillEllipse(in: rect)

        context.restoreGState()
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return image
    }
    
    private func addCentered(image: UIImage, tintColor: UIColor) -> UIImage
    {            
        let topImage = image.withTintColor(tintColor, renderingMode: .alwaysTemplate)
        let bottomImage = self
        
        // 替换原来的UIGraphicsBeginImageContext,适配Retina
        // 第二个参数false代表保留透明通道,如果你的图片不需要透明可以改为true提升渲染性能
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        
        let bottomRect = CGRect(x: 0, y: 0, width: bottomImage.width, height: bottomImage.height)
        bottomImage.draw(in: bottomRect)
        
        let topRect = CGRect(x: (bottomImage.width - topImage.width) / 2.0,
                             y: (bottomImage.height - topImage.height) / 2.0,
                             width: topImage.width,
                             height: topImage.height)
        topImage.draw(in: topRect, blendMode: .normal, alpha: 1.0)
        
        let mergedImage = UIGraphicsGetImageFromCurrentImageContext()!
        
        UIGraphicsEndImageContext()
        
        return mergedImage
    }
}

补充说明

  • 你也可以显式将第三个参数替换为UIScreen.main.scale,和传0的效果完全一致,传0是系统推荐的更简洁的写法
  • 如果你需要在非主屏幕的设备(比如外接显示器)上渲染对应分辨率的图片,才需要手动指定对应屏幕的scale参数,普通App主屏幕场景传0即可覆盖所有需求

内容的提问来源于stack exchange,提问作者meaning-matters

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 11:54:03