我有一个用RXSwift写的应用,处理500多天的HealthKit数据,为用户绘制一个图表。
使用下面的代码增量绘制图表图片。从黑屏开始,在图形上下文中绘制前一个图像,然后在这个图像上以一定的偏移量绘制一个新的片段。合并后的图像被保存,这个过程大约重复70多次。每一次图像都被保存,所以用户看到的是更新。结果是一个 单图 用户可以从应用中导出。
即使有了 autorelease
池,我看到内存使用量的峰值高达1Gb,这使我无法进行其他资源密集型处理。
如何优化超大(1440×5000像素)图像的增量绘制?
当图像以3倍比例显示或保存时,它实际上是4320×15360。
有没有比尝试在图像上绘制更好的方法?
autoreleasepool {
//activeEnergyCanvas is custom data processing class
let newActiveEnergySegment = activeEnergyCanvas.draw(in: CGRect(x: 0, y: 0, width: 1440, height: days * 10), with: energyPalette)
let size = CGSize(width: 1440, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
//draw existing image
self.activeEnergyImage.draw(in: CGRect(origin: CGPoint(x: 0, y: 0),
size: size))
//calculate where to draw smaller image over larger one
let offsetRect = CGRect(origin: CGPoint(x: 0, y: offset * 10),
size: newActiveEnergySegment.size)
newActiveEnergySegment.draw(in: offsetRect)
//get the combined image
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//assign combined image to be displayed
if let unwrappedImage = newImage {
self.activeEnergyImage = unwrappedImage
}
}
原来我的错误是在创建图形上下文时传递了无效的绘制比例(0.0),默认以设备的原生屏幕比例绘制。
在iPhone 8的情况下,它是3.0,结果是需要极多的内存来绘制、缩放和导出这些图像。即使所有的调试日志打印出该图像是1440像素宽,实际画布最终也是1440 * 3.0 = 4320。
传递1.0作为绘制比例会使图像更加模糊,但将内存使用量降低到200mb以下。
// UIGraphicsBeginImageContext() <- also uses @3x scale, even when all display size printouts show
let drawingScale: CGFloat = 1.0
UIGraphicsBeginImageContextWithOptions(size, true, drawingScale)