Как сделать отображение изображений на WPF более "быстрым"?

Я пишу средство просмотра изображений WPF, отображающее сетку изображений. Я озадачен из-за вялой производительности: отображение даже сетки 11 x 11 делает виртуальную машину невосприимчивой, медленной и вялой в течение длительного времени. Даже на мощном хосте производительность в non-snappy.

программа основана на дизайне в SO WPF: организация элементов коллекции в сетке: ItemsControl привязан к элементам, ObservableCollection. Каждый элемент содержит файловую систему абсолютный URI. DataTemplate ItemsControl содержит элемент изображения, источник которого привязан к URI.

похоже, проблема не может быть диском (SSD), памятью (8GB VM, хостом 24GB) или процессором (i750). Более того, большая часть работы выполняется WPF, поэтому я даже не могу найти проблему в своем коде: мой код просто загружает URIs (т. е. пути к изображениям, а не изображения) в коллекцию и быстро возвращается. Затем происходит ожидание, и WPF отображает изображения.

единственная проблема, о которой я мог думать, – это масштабирование обработки изображений с помощью WPF. Но даже на хосте, который имеет "достаточно хорошую" карту 5850 ATI Radeon HD, производительность не является быстрой.

Итак, мой вопрос: как я могу сделать отображение изображений на WPF более "быстрым"?

редактировать: изображения 1920x1080 22 бит HD JPEGs, захваченные из HD m2ts видео. Я попытался предварительно масштабировать их (используя FFmpeg) до 'ega' 640x350. Там был улучшение производительности, но уменьшенные изображения FFmpeg выглядят намного хуже, чем WPF.

редактировать: благодаря Дэвиду Осборну код теперь работает как x64. Все еще вяло.

редактировать что действительно улучшило ситуацию, так это то, что Матей Забски назвал масштабированием изображений: уменьшение разрешения. Для будущих читателей:

            fullPath = new Uri(path, UriKind.Absolute);


            BitmapImage smallerBitmapImage = new BitmapImage();
            smallerBitmapImage.BeginInit();
            smallerBitmapImage.DecodePixelWidth = (int) (theWidthOfTheGrid / theNumberOfColumns);
            smallerBitmapImage.UriSource = fullPath;
            smallerBitmapImage.EndInit();

            FormatConvertedBitmap formatConvertedBitmap = new FormatConvertedBitmap();
            formatConvertedBitmap.BeginInit();
            formatConvertedBitmap.Source = smallerBitmapImage;
            formatConvertedBitmap.DestinationFormat = PixelFormats.Gray16;
            formatConvertedBitmap.EndInit();
            formatConvertedBitmap.Freeze();

            this.ImageSource = formatConvertedBitmap;

4 ответов


Я был в аналогичном положении (мне пришлось отображать уменьшенные версии больших изображений в режиме реального времени).

Если вы используете привязку данных для отображения изображений, вы можете попробовать две вещи:

  • сделайте привязку OneWay (это помогло мне самой).
  • попробуйте сделать привязку асинхронные.

единственное для масштабирования изображений - желательно в отдельном потоке. Возможно, вы даже могли бы prescale изображения, которые могут быть потенциально использованы в будущем, в то время как простое - например, если вы разрабатываете приложение, похожее на карту, вы можете предустановить изображения в областях, в которые пользователь, скорее всего, переместится.


вы можете попробовать виртуализацию для управления, это поможет значительно При загрузке большего количества изображений в listview. VirtualizingStackPanel

<ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Vertical" VirtualizingStackPanel.IsVirtualizing="True"  VirtualizingStackPanel.VirtualizationMode="Recycling"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>

Если хотите использовать Viruatalization с wrap-panel, есть некоторые из Codeplex,Виртуализация Wrappanel

Я знаю, что это старый нить, но если кто-то еще заинтересован.


вы пробовали экспериментировать с различными настройками платформы? Т. е. x86 или AnyCPU.


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

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

раздел реестра вам нужно HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\DisableHWAcceleration, a DWORD что вы должны ставить 1. Обратите внимание, что это общесистемное и повлияет на все приложения WPF-не устанавливайте его как часть приложения, а используйте его в среде виртуальной машины и убедитесь, что вы снова тестируете надлежащее оборудование перед выпуском.

более дальнеишее чтение здесь.