通过Data创建UIImage时CGImage分辨率异常问题排查
问题:UIImage尺寸正确但底层CGImage尺寸偏大3倍的原因及修复方法
我需要将RAW图片转换为JPEG格式,之后对图片进行一些计算处理,同时需要获取UIImage和CGImage两种格式的图片。但发现UIImage的分辨率显示正确,其底层的CGImage分辨率却偏大3倍。
相关代码:
// original RAW image: (3504.0, 2336.0) let imageUrl = Bundle.main.url(forResource: "IMG_3136", withExtension: "CR2")! let ciImage = CIFilter(imageURL: imageUrl).outputImage! let uiImage = UIImage(ciImage: ciImage) let data = uiImage.jpegData(compressionQuality: 0.92)! let recreatedUiImage = UIImage(data: data, scale: UIScreen.main.scale)! let cgImage = recreatedUiImage.cgImage! let cgImageSize = CGSize(width: cgImage.width, height: cgImage.height) print(recreatedUiImage.size) // (3504.0, 2336.0) CORRECT print(cgImageSize) // (10512.0, 7008.0) WRONG
原因分析
- UIImage的scale属性是核心差异:UIImage的
size是逻辑尺寸,由底层CGImage的像素尺寸除以scale计算得到;而CGImage存储的是实际像素尺寸。你创建recreatedUiImage时指定了scale: UIScreen.main.scale(当前iPhone屏幕默认是3x),所以CGImage的像素尺寸自然是UIImage逻辑尺寸的3倍。 - 额外影响:从CIImage初始化UIImage时,默认会使用屏幕scale,后续转JPEG再重建时又手动指定了屏幕scale,进一步固化了像素尺寸的放大倍数。
修复方法
方法1:重建UIImage时指定scale为1.0
如果需要CGImage的像素尺寸和UIImage的逻辑尺寸完全一致,直接在创建recreatedUiImage时把scale设为1.0:
let recreatedUiImage = UIImage(data: data, scale: 1.0)! let cgImage = recreatedUiImage.cgImage! print(CGSize(width: cgImage.width, height: cgImage.height)) // 输出(3504.0, 2336.0)
这种方式最简单,重建后的UIImage和CGImage尺寸完全匹配原始RAW图的分辨率。
方法2:手动绘制缩放CGImage
如果需要保留UIImage的屏幕适配scale,但要获取指定像素尺寸的CGImage,可以通过绘图上下文缩放:
// 目标像素尺寸就是原始RAW图的尺寸 let targetPixelSize = CGSize(width: 3504, height: 2336) UIGraphicsBeginImageContextWithOptions(targetPixelSize, false, 1.0) recreatedUiImage.draw(in: CGRect(origin: .zero, size: targetPixelSize)) let scaledCGImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage UIGraphicsEndImageContext() if let scaledCGImage = scaledCGImage { print(CGSize(width: scaledCGImage.width, height: scaledCGImage.height)) // 输出(3504.0, 2336.0) }
这种方式适合需要灵活调整CGImage尺寸的场景。
内容的提问来源于stack exchange,提问作者xinatanil
相关产品推荐
相关产品推荐

