Рендеринг картинок через WPF на примере Pivot

    Pivot не нуждается в представлении. Если вбить это слово в поиск хабра, результатом будут 37 статей, среди которых есть как обзоры, так и туториалы. Поэтому я решил сосредоточить свои усилия лишь на одном аспекте работы с Pivot — на картинках.

    Удобство работы с Pivot сильно зависит от выбранных для него картинок. Картинки низкого разрешения или разных размеров и стилей могут испортить все впечатление. Бывают и такие ситуации, что картинок вообще нет и не может быть, так как все данные находятся в базе в виде чисел, строк и дат.

    Существует много способов программной генерации картинок по шаблону. Один из них даже встроен в библиотеку PautorLib, которая помогает подготавливать данные в формат, понятный PivotViewer. В качестве шаблона там используется HTML.

    В этой статье я рассмотрю решение задачи средствами WPF. Шаблоном в нашем случае будет являться UserControl, в котором могут быть различные TextBlock и Image, свойства которых можно устанавливать в коде. Чтобы не быть голословным, рассмотрим все на примере.

    Для примера была взята информация о первой тысяче пользователей из топа хабра. Для этого был написан бот, который неспеша собрал все данные и положил в MongoDB.

    Класс, который берет данные о пользователе и преобразует их в картинку, выглядит приблизительно так (pastebin).

    На выходе были получены вот такие картинки:



    Для того, чтобы добиться такого качества шрифтов, в шаблоне нужно установить слудующие свойства:

    TextOptions.TextFormattingMode="Display"
    RenderOptions.ClearTypeHint="Enabled"

    Для отрисовки контрола в картинку используется класс RenderTargetBitmap. У него есть своя особенность — картинки на выходе имеют нечеловеческий формат Pbgra32. Другие форматы не поддерживаются. Поэтому приходится дополнительно прогонять получившийся bitmap через класс FormatConvertedBitmap, чтобы на выходе получить Rgb24. После этого результат кодируется в PNG через PngBitmapEncoder и сохраняется в файл.

    Все это происходит по таймеру (DispatcherTimer) и выглядит это следующим образом — срабатывает таймер, шаблон заполняется новыми данными, снова срабатывает таймер, перерисованное окно с новыми данными преобразуется в картинку.

    Все это хозяйство с таймером, шаблоном и окном запускается в отдельном STA потоке, как того требуют WPF. Поток в свою очередь запускается вызовом функции.

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

    Пример программы для генерации картинок можно скачать по следующим ссылкам: bin, src. В конфиге программы есть два ключа. TilesPath содержит путь к папке, в которую будут сохраняться готовые картинки. DemoRender — бинарное значение, которое переключает режимы программы (демонстрационный и рабочий). В демонстрационном режиме картинки не сохраняются на диск, а отображаются в окне в виде слайдшоу. В рабочем режиме картинки сохраняются, а окно прячется.

    Ну и наконец здесь можно найти получившийся Pivot. Напоминаю, что это первая тысяча людей из топа хабра. Через поиск можно искать по UserName и DisplayName. По остальм свойствам можно фильтровать, сортировать и группировать. Вот несколько скриншотов для тех, кто по тем или иным причинам не может его увидеть: img1, img2, img3, img4, img5, img6.

    Комментарии 12

      0
      Может ли он выдавать картинки не в PNG24, а в PNG8 с оптимизацией до нужного количества цветов? У меня вручную получилось сделать из картинки «umputun» 16 Кбайт — PNG8, 32 цвета, 7.5 Кбайт, а с дополнительной экономией — 6.5.
        0
        Вот список поддерживаемых PixelFormats. Мне кажется, что RGB24 самый экономичный из них.
          0
          PNG8 — это Indexed8. но для перегона в него надо писать квантизатор
          0
          Встроенные в .Net средства не позволяют.
          Я использовал Freeimage библиотеку для этого.
          0
          это круто!
            0
            Видел такую штуку интегрированную в Microsoft Surface на ихнем устройстве. Это очень круто. Когда без тормозов и огромная база.
              +3
              на моно не работает!
                +2
                Заработает в четвертой версии Moonlight. Могу лишь посоветовать запастись терпением.
                • НЛО прилетело и опубликовало эту надпись здесь
                    +2
                    Поэтому я и сказал про «запастись терпением».
                0
                Странно, чего там DataTemplate'ы не поддерживаются что-ли? Обязательно картинки клепать руками?
                  0
                  В основе лежат картинки в формате DeepZoom. Делать все через ContentControls, которые поддерживают DataTemplate, было бы очень накладно.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое