Рисование изображения с помощью CoreGraphics на Retina iPad медленное

В моем приложении iPad я обрабатываю растровое изображение вне экрана, а затем рисую растровое изображение на экране. (Это связано с тем, что я хочу повторно использовать существующий код рендеринга растрового изображения.) На iPad 2 это работает как шарм, но на новом iPad с дисплеем Retina рисование растрового изображения происходит очень медленно, хотя его разрешение по-прежнему остается то же самое.

Чтобы нарисовать растровое изображение, мы используем обычные кварцевые 2D-функции: CGImageCreate с поставщиком данных, созданным с помощью CGDataProviderCreateWithData, 32-битного формата RGBA с kCGImageAlphaNoneSkipLast. В UIView, который отображает растровое изображение, в drawRect:, мы используем CGContextDrawImage, чтобы нарисовать его в контексте, возвращаемом UIGraphicsGetCurrentContext.

Заметьте, что я даже не пытаюсь рисовать в двойном разрешении: на данный момент я в порядке с тем же разрешением, что и на iPad 2. Похоже, что CoreGraphics внутренне удваивает пиксели, а затем отправляет на графический процессор, хотя CGImage, который я создаю, должен быть хорошим для непосредственного перехода на GPU. Любые идеи?

Ответ 1

Похоже, что CoreGraphics внутренне удваивает пиксели, а затем отправляет их на GPU,

В значительной степени. Точнее (по крайней мере, по духу):

  • UIKit делает CGBitmapContext размер ваших границ обзора, в пикселях устройства
  • Он делает этот контекст текущим контекстом
  • Вы рисуете CGImage в этом контексте
  • ... поэтому CG должен перемасштабировать исходное изображение и коснуться всех целевых пикселей.
  • После того, как вы закончите рисование, UIKit создает CGImage из контекста растрового изображения.
  • и присваивает его содержимому уровня представления.

CGImage, который я создаю, должен быть хорошим для непосредственного перехода на GPU.

Если вы хотите, чтобы это произошло, вам нужно сообщить системе об этом, вырезав некоторые из приведенных выше шагов.

(Нет связи между UIKit, CoreAnimation и CoreGraphics, которая обеспечивает "быстрый путь", как вы ожидаете.)

Самый простой способ - сделать UIImageView и установить его image на UIImage, завернув ваш CGImageRef.

Или, установите view.layer.contents на CGImageRef. (И не забудьте переопределить -drawRect:, а не вызвать -setNeedsDisplay, и убедитесь, что contentMode не UIViewContentModeRedraw. Легче просто использовать UIImageView.)