Ответ 1
Я не могу найти конкретный вопрос в вашем сообщении, кроме как просить комментарии о подходах ниже. Я не буду требовать знать все выше, но я расскажу вам, что я знаю, работая некоторое время, разрабатывая высокопроизводительные пользовательские интерфейсы, используя WPF и Silverlight.
Образец 0: Хак. Объединение всех в одно изображение
Я бы избегал этого, если это было возможно. Похоже, вы хотите отобразить большую панель с тысячами небольших изображений. Поэтому каждое изображение является миниатюрой (так как вы не можете отображать сразу 1000 больших изображений). В результате я защищал кеширование/изменение размера по сравнению с комбинацией.
Шаблон 1: Уменьшить размер изображения
Если вы одновременно показываете 1000 изображений на экране, рассмотрите доступную экранную недвижимость. Средний монитор - 1280x1024 пикселей или чуть более 1,3MPixels. 1000 изображений показывают, что вы получите максимальный размер 1300 пикселей на изображение или 36 * 36. Допустим, ваши изображения имеют размер 32 * 32. Вы должны создать миниатюру этого размера изображения для рендеринга на экране, а затем щелкнуть (или другое действие) показать изображение полного размера.
Также рассмотрите не только накладные расходы на изменение размера большого изображения, но и отправку большого изображения на GPU для изменения размера. Для этих данных требуется пропускная способность для отправки. Большое изображение может быть в несколько мегабайт, тогда как миниатюра размером 32 * 32 может составлять несколько килобайт.
Если вам требуется динамическая калибровка, хорошо, но вам нужно поэкспериментировать с созданием нескольких эскизов или их генерации на лету.
Шаблон 2: предварительная выборка фона
Это техника, о которой я не слышал, однако она кажется правдоподобной. Каковы накладные расходы в вашем приложении? это обновление свойства Image.Source или создание нового изображения, тесселяции, выполнение макета и отправка информации для рендеринга на GPU?
Все вышеперечисленное происходит на процессоре, за исключением окончательного рендеринга. Уменьшая накладные расходы на стороне процессора и обновляя источник, вы можете что-то сказать. Объедините это с WriteableBitmap в качестве источника, и вы можете дополнительно улучшить производительность (см. Ниже).
Рисунок 3: Контекст рисования
Хорошо, все это позволяет вам выстраивать очереди в режиме ожидания с использованием синтаксиса стиля "OnPaint", который не похож на старый GDI OnPaint. По моему опыту, OnRender не улучшает производительность, но это обеспечивает гибкую гибкость над тем, что нарисовано и когда. OnRender предоставляет вам контекст, который имеет функцию DrawImage, позволяя BitmapSource рисоваться в конвейере рендеринга без необходимости управления изображением. Это хорошо, поскольку он устраняет некоторые накладные расходы, однако вводит проблемы, подобные тем, которые наблюдаются в Pattern0 (вы потеряете макет и должны вычислить положение всех ваших изображений). Если вы это сделаете, вы можете также вызвать шаблон 0, о котором я посоветовал.
Рисунок 4: Записываемые растровые изображения
WriteableBitmaps - это малоиспользуемая и чрезвычайно мощная подсистема в WPF. Я использую их для создания диаграммного компонента, способного отображать большие объемы данных в реальном времени. Я бы посоветовал проверить проект WriteableBitmapEx codeplex Раскрытие информации, я внес свой вклад в этот раз и посмотреть, можете ли вы объединить его с другими шаблонами. В частности, функция Blit, которая позволит вам записать кэшированное растровое изображение в источник растрового изображения на изображении.
Например, хорошей техникой может быть шаблон 1 + 2 + 4.
У вас может быть сетка из N элементов управления изображением на экране в заданных местах в элементе управления сеткой. Каждый из них является статичным и не получает прокрутки вне поля зрения, поэтому никаких творений и исключений не происходит. Теперь, помимо этого, измените размер изображения и напишите в WriteableBitmap, который устанавливается как свойство Source для каждого изображения. Когда вы прокручиваете, получите следующие/предыдущие эскизы и обновите источники, используя WriteableBitmapEx.Blit. Pow! виртуализированную, кэшированную, многопоточную визуализацию.
Рисунок 5: Кэшированное растровое изображение
Это попытка microsoft сделать 1 + 2 + 4, как я уже говорил выше. То, что он пытается сделать, это после компоновки (процессорная сторона), тесселяции (процессорная сторона), отправки команд рендеринга сохраненного режима на процессорную плату (GPU) и рендеринг (сторона GPU), которая кэширует растровое изображение визуализируемого элемента, используется для следующего прохождения рендеринга. Да, малоизвестный факт о WPF заключается в том, что замечательный двигатель с графическим процессором очень медленный, так как он выполняет большую часть своей работы с CPU: P
Я бы экспериментировал с BitmapCache и видел, как он работает. Есть предостережения, и они таковы, что при обновлении UIElement он должен воссоздать кеш, поэтому статические элементы будут работать намного лучше, чем динамические. Кроме того, я не видел существенного улучшения производительности от использования этого, тогда как методы стиля WriteableBitmap могут дать порядок улучшения.
Образец 6: RenderTargetBitmap
Этот окончательный метод позволяет отображать UIElement в растровом изображении - вы знаете это, но интересно, что это может выполнять генератор миниатюр с низким разрешением (или изменение размера). Например, установите изображение с BitmapSource вашего полноразмерного изображения. Теперь установите размер элемента управления Image на 32 * 32 и сделайте растровое изображение. Вуаля! У вас есть миниатюра BitmapSource для использования в сочетании с некоторыми подкачками (шаблон 2) и/или записываемыми растровыми изображениями.
Хорошо, наконец, просто хотел сказать, что ваше требование будет подталкивать WPF до предела, однако есть способы заставить его выполнить. Как я уже сказал, у меня есть системы построения, которые отображали тысячи или миллионы элементов на экране сразу, используя замечательный обходной путь, который является WriteableBitmap. Переход по стандартным маршрутам WPF приведет к производительности ад, поэтому вам придется сделать что-то экзотическое, чтобы решить эту проблему.
Как я уже сказал, моя рекомендация 1 + 2 + 4. Вы должны изменить размер миниатюры, и я не сомневаюсь. Идея создания статической сетки элементов управления Image и обновления источников очень хороша. Идея использования WriteableBitmap (в частности, функция Blit-функции WriteableBitmapEx) для обновления источников также заслуживает изучения.
Удачи!