为什么使用 UIGraphicsImageRenderer 绘制图像时会占用大量内存?
Why use a lot of memory when drawing image with UIGraphicsImageRenderer?
我想给照片加上白边,同时保留照片的质量,所以我用UIGraphicsImageRenderer画了一个白色的背景,然后把照片画上去,结果内存占用急剧增加,有没有更好的办法?
原图分辨率为4032*3024
let renderer = UIGraphicsImageRenderer(size: CGSize(width: canvasSideLength, height: canvasSideLength))
let newImage = renderer.image { context in
UIColor.white.setFill()
context.fill(CGRect(x: 0, y: 0, width: canvasSideLength, height: canvasSideLength))
image.draw(in: CGRect(x: photoCanvasX, y: photoCanvasY, width: photoCanvasWidth, height: photoCanvasHeight))
}
考虑使用的内存时,不要被 JPG 或 PNG 文件的大小所误导,因为它们通常是经过压缩的。在内存中执行图像操作时,每个像素需要四个字节(例如宽度×高度×4,以像素为单位)。
更糟糕的是,默认情况下,UIGraphicsImageRenderer
将以屏幕分辨率生成图像(例如可能为 2× 或 3×,具体取决于您的设备)。例如。在 3× 设备上,考虑:
let rect = CGRect(origin: .zero, size: CGSize(width: 8_519, height: 8_519))
let image = UIGraphicsImageRenderer(bounds: rect).image { _ in
UIColor.white.setFill()
UIBezierPath(rect: rect).fill()
}
print(image.cgImage!.width, "×", image.cgImage!.height)
将打印:
25557 × 25557
考虑到每个像素需要 4 个字节,加起来就是 2.6gb。即使图像只有 4,032 × 3,024,正如您修改后的问题所建议的那样,每张图像仍然是 439mb。
您可能需要确保明确指定比例 1:
let rect = CGRect(origin: .zero, size: CGSize(width: 8_519, height: 8_519))
let format = UIGraphicsImageRendererFormat()
format.scale = 1
let image = UIGraphicsImageRenderer(bounds: rect, format: format).image { _ in
UIColor.white.setFill()
UIBezierPath(rect: rect).fill()
}
print(image.cgImage!.width, "×", image.cgImage!.height)
这将如您所料打印:
8519 × 8519
那么您只需要 290mb 的图像空间。这仍然是很多内存,但比使用默认比例(在 Retina 设备上)要少得多。或者,考虑到你修改后的 4,032 × 3,024 图像,这个 1× 图像可能只需要 49mb,是你没有设置比例的相应 3× 图像大小的 1/9。
我想给照片加上白边,同时保留照片的质量,所以我用UIGraphicsImageRenderer画了一个白色的背景,然后把照片画上去,结果内存占用急剧增加,有没有更好的办法?
原图分辨率为4032*3024
let renderer = UIGraphicsImageRenderer(size: CGSize(width: canvasSideLength, height: canvasSideLength))
let newImage = renderer.image { context in
UIColor.white.setFill()
context.fill(CGRect(x: 0, y: 0, width: canvasSideLength, height: canvasSideLength))
image.draw(in: CGRect(x: photoCanvasX, y: photoCanvasY, width: photoCanvasWidth, height: photoCanvasHeight))
}
考虑使用的内存时,不要被 JPG 或 PNG 文件的大小所误导,因为它们通常是经过压缩的。在内存中执行图像操作时,每个像素需要四个字节(例如宽度×高度×4,以像素为单位)。
更糟糕的是,默认情况下,UIGraphicsImageRenderer
将以屏幕分辨率生成图像(例如可能为 2× 或 3×,具体取决于您的设备)。例如。在 3× 设备上,考虑:
let rect = CGRect(origin: .zero, size: CGSize(width: 8_519, height: 8_519))
let image = UIGraphicsImageRenderer(bounds: rect).image { _ in
UIColor.white.setFill()
UIBezierPath(rect: rect).fill()
}
print(image.cgImage!.width, "×", image.cgImage!.height)
将打印:
25557 × 25557
考虑到每个像素需要 4 个字节,加起来就是 2.6gb。即使图像只有 4,032 × 3,024,正如您修改后的问题所建议的那样,每张图像仍然是 439mb。
您可能需要确保明确指定比例 1:
let rect = CGRect(origin: .zero, size: CGSize(width: 8_519, height: 8_519))
let format = UIGraphicsImageRendererFormat()
format.scale = 1
let image = UIGraphicsImageRenderer(bounds: rect, format: format).image { _ in
UIColor.white.setFill()
UIBezierPath(rect: rect).fill()
}
print(image.cgImage!.width, "×", image.cgImage!.height)
这将如您所料打印:
8519 × 8519
那么您只需要 290mb 的图像空间。这仍然是很多内存,但比使用默认比例(在 Retina 设备上)要少得多。或者,考虑到你修改后的 4,032 × 3,024 图像,这个 1× 图像可能只需要 49mb,是你没有设置比例的相应 3× 图像大小的 1/9。