Я предположил, что вы делаете это для отображения части изображения на экране, потому что вы упомянули UIImageView
. А проблемы оптимизации всегда требуют специального определения.
Доверьтесь Apple в вопросах обычного пользовательского интерфейса
На самом деле UIImageView
с clipsToBounds
- это один из самых быстрых / простых способов заархивировать вашу цель, если ваша цель - просто вырезать прямоугольную область изображения (не слишком большую). Кроме того, вам не нужно отправлять setNeedsDisplay
сообщение.
Или вы можете попробовать поместить UIImageView
внутрь пустого UIView
и установить отсечение в виде контейнера. С помощью этой техники вы можете свободно трансформировать свое изображение, установив свойство transform
в 2D (масштабирование, поворот, перевод).
Если вам нужно трехмерное преобразование, вы все равно можете использовать CALayer
со свойством masksToBounds
, но использование CALayer
даст вам очень небольшую дополнительную производительность, обычно незначительную.
В любом случае вам нужно знать все низкоуровневые детали, чтобы правильно использовать их для оптимизации.
Почему это один из самых быстрых способов?
UIView
- это всего лишь тонкий слой поверх CALayer
, который реализован поверх OpenGL, который является практически прямым интерфейсом для GPU. Это означает, что UIKit ускоряется графическим процессором.
Так что, если вы используете их правильно (я имею в виду, в рамках установленных ограничений), он будет работать так же, как и обычная реализация. Если вы используете для отображения всего несколько изображений, вы получите приемлемую производительность с UIView
реализацией, поскольку она может получить полное ускорение базового OpenGL (что означает ускорение графического процессора).
В любом случае, если вам нужна экстремальная оптимизация для сотен анимированных спрайтов с точно настроенными пиксельными шейдерами, как в игровом приложении, вам следует использовать OpenGL напрямую, потому что CALayer
не хватает многих опций для оптимизации на более низких уровнях. В любом случае, по крайней мере, для оптимизации пользовательского интерфейса, быть лучше Apple невероятно сложно.
Почему ваш метод медленнее, чем UIImageView
?
Вам следует знать все об ускорении графического процессора. Во всех последних компьютерах высокая производительность графики достигается только с помощью графического процессора. Затем вопрос в том, реализован ли используемый вами метод поверх графического процессора или нет.
IMO, CGImage
методы рисования не реализованы на GPU. Думаю, я читал упоминание об этом в документации Apple, но не могу вспомнить где. Так что я не уверен в этом. В любом случае, я считаю, что CGImage
реализован в ЦП, потому что
- Его API выглядит так, как будто он был разработан для ЦП, например, интерфейс редактирования растровых изображений и рисование текста. Они не очень хорошо подходят к интерфейсу графического процессора.
- Интерфейс контекста растрового изображения обеспечивает прямой доступ к памяти. Это означает, что внутреннее хранилище находится в памяти ЦП. Может быть, несколько иначе в архитектуре унифицированной памяти (а также с Metal API), но в любом случае первоначальное намерение
CGImage
при проектировании должно быть связано с процессором.
- Многие недавно выпустили другие API-интерфейсы Apple, в которых явно упоминается ускорение графического процессора. Это означает, что их старые API не были такими. Если нет особого упоминания, обычно это делается в ЦП по умолчанию.
Похоже, что это делается в ЦП. Графические операции, выполняемые в CPU, намного медленнее, чем в GPU.
Простое вырезание изображения и составление слоев изображения - очень простые и дешевые операции для графического процессора (по сравнению с процессором), поэтому вы можете ожидать, что библиотека UIKit будет использовать это, потому что весь UIKit реализован поверх OpenGL.
Об ограничениях
Поскольку оптимизация - это своего рода работа над микроменеджментом, очень важны конкретные цифры и небольшие факты. Что за средний размер? OpenGL на iOS обычно ограничивает максимальный размер текстуры до 1024x1024 пикселей (возможно, больше в последних выпусках). Если ваше изображение больше этого размера, оно не будет работать или производительность будет значительно снижена (я думаю, что UIImageView оптимизирован для изображений в установленных пределах).
Если вам нужно отображать огромные изображения с обрезкой, вы должны использовать другую оптимизацию, например CATiledLayer
, и это совершенно другая история.
И не переходите на OpenGL, если вы не хотите знать все детали OpenGL. Требуется полное понимание низкоуровневой графики и как минимум в 100 раз больше кода.
О каком-то будущем
Хотя это маловероятно, но CGImage
вещи (или что-то еще) не нужно застревать только в ЦП. Не забудьте проверить базовую технологию API, который вы используете. Тем не менее, графические процессоры сильно отличаются от процессоров, и парни, занимающиеся API, обычно явно и четко упоминают о них.
person
eonil
schedule
26.11.2011