iOS Core Graphics, как оптимизировать пошаговое рисование очень большого изображения? - PullRequest
0 голосов
/ 26 марта 2020

У меня есть приложение, написанное на RXSwift, которое обрабатывает данные HealthKit за 500+ дней, чтобы нарисовать диаграмму для пользователя.

Изображение диаграммы рисуется постепенно, используя код ниже. Начиная с черного экрана, предыдущее изображение рисуется в графическом контексте, затем новый сегмент рисуется поверх этого изображения с определенным смещением. Объединенное изображение сохраняется, и процесс повторяется более 70 раз. Каждый раз изображение сохраняется, поэтому пользователь видит обновление. В результате получается одиночное графическое изображение , которое пользователь может экспортировать из приложения.

Даже с пулом autorelease я вижу всплески использования памяти до 1 Гб, что не позволяет мне делать это другие ресурсоемкие обработки.

Как оптимизировать пошаговое рисование очень большого (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
    }
}

enter image description here

1 Ответ

0 голосов
/ 01 мая 2020

Оказывается, моя ошибка заключалась в передаче неверного масштаба рисования (0.0) при создании графического контекста, который по умолчанию рисовался в масштабе исходного экрана устройства.

В случае iPhone 8 это было 3,0. В результате требуется чрезмерное количество памяти для рисования, масштабирования и экспорта этих изображений. Даже если все отладочные журналы печатают, что изображение имеет ширину 1440 пикселей, фактическое полотно в итоге получается 1440 * 3,0 = 4320.

Передача 1,0 в качестве масштаба чертежа делает изображение более размытым, но уменьшает использование памяти до менее чем 200 МБ.

// UIGraphicsBeginImageContext() <- also uses @3x scale, even when all display size printouts show 
let drawingScale: CGFloat = 1.0
UIGraphicsBeginImageContextWithOptions(size, true, drawingScale)
...