let renderer = UIGraphicsImageRenderer(size: size)
let newImage = renderer.image { context in
// ...
}
这是最简单的 UIGraphicsImageRenderer 用法,但用这种方法处理图片有可能占用大量内存。
分辨率问题
图片占内存大小并不是由图片文件大小决定的,而是由图片尺寸决定。假设上述代码中的 size
是 8000 * 8000,每像素大小为 4 字节,那这样最后生成的图片会占用大约 2.25GB 内存。
这是因为在默认情况下,UIGraphicsImageRenderer 会根据屏幕分辨率生成图片,iPhone 的分辨率一般都是 3x,所以最后生成的图片实际尺寸是 24000 * 24000。
如果想要确保 1:1 的显示比例,可以添加如下代码:
let format = UIGraphicsImageRendererFormat()
format.scale = 1
let renderer = UIGraphicsImageRenderer(size: size, format: format)
// ...
这样最终生成的图片的尺寸就是 8000 * 8000,内存占用则只有 250MB 左右。
色域问题
由于 UIGraphicsImageRenderer 会根据图片上下文自动确定色域,例如 sRGB、广色域等,所以在处理广色域图片时,内存也可能会暴增。
在 sRGB 色域下,每像素大小为 4 字节,在广色域下,每像素大小为 8 字节。如果上文提到的图片的色域是广色域,那图片在不做任何优化的情况下,会占用到 4.5GB 左右内存。
所以确定不需要广色域时,可以使用以下代码,指定 sRGB 色域:
let format = UIGraphicsImageRendererFormat()
format.preferredRange = .standard
let renderer = UIGraphicsImageRenderer(size: size, format: format)
// ...
最后
再提一下 UIGraphicsBeginImageContextWithOptions,这位老前辈只支持 sRGB 色域,不支持广色域,这也是应该造成 UIGraphicsBeginImageContextWithOptions 性能比 UIGraphicsImageRenderer 好这种误解的原因。