iOS 10+ UIGraphicsImageRenderer能否输出灰度PNG数据?
如何用UIGraphicsImageRenderer保存灰度PNG图像
当然可以用UIGraphicsImageRenderer的新API保存灰度格式的PNG,问题出在你当前代码里用的是默认的渲染格式——默认的UIGraphicsImageRendererFormat会使用设备的RGB色空间,所以绘制时会把灰度图像强制转换为RGB格式输出。
解决思路
要保留灰度色空间,你需要手动创建匹配原图像色空间的UIGraphicsImageRendererFormat,而不是用默认的空初始化方法。核心是把格式的colorSpace属性设置为原图像CGImage的灰度色空间,同时保持其他参数(比如opaque)和原图像一致,避免额外的格式转换。
修改后的代码实现
extension UIImage { public func pngData_olderAPI() -> Data? { return UIImagePNGRepresentation(self) } public func pngDataPreservingGrayscale() -> Data? { guard let cgImage = self.cgImage else { return nil } // 创建匹配原图像色空间的渲染格式 let format = UIGraphicsImageRendererFormat() format.colorSpace = cgImage.colorSpace format.opaque = cgImage.isOpaque format.scale = self.scale let renderedSize = CGSize(width: size.width, height: size.height) let renderer = UIGraphicsImageRenderer(size: renderedSize, format: format) return renderer.pngData { rendererContext in let rect = CGRect(origin: .zero, size: renderedSize) self.draw(in: rect) } } }
测试验证
用修改后的方法测试,输出的色空间会和原图像保持一致:
let mask = UIImage(named: "mask.png") print(mask?.cgImage?.colorSpace.debugDescription) // 输出:...kCGColorSpaceModelMonochrome; Dot Gain 20%)) let data2 = mask?.pngDataPreservingGrayscale() let unwrappedMask2 = UIImage(data: data2!) print(unwrappedMask2?.cgImage?.colorSpace.debugDescription) // 输出:...kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Dot Gain 20%))
关键细节说明
format.colorSpace = cgImage.colorSpace:强制渲染上下文使用原图像的灰度色空间,避免自动转换为RGBformat.opaque = cgImage.isOpaque:保持原图像的不透明属性,防止自动添加Alpha通道(如果原灰度图没有Alpha的话)format.scale = self.scale:保留原图像的缩放比例,避免图像模糊或尺寸异常
这样修改后,新API就能像旧的UIImagePNGRepresentation一样,正确编码并输出灰度格式的PNG Data了。
内容的提问来源于stack exchange,提问作者HuaTham
相关产品推荐
相关产品推荐

