Как сделать отображение изображений на 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
Я знаю, что это старый нить, но если кто-то еще заинтересован.
Если вы работаете на виртуальной машине, вы, вероятно, сталкиваетесь с проблемами аппаратного (или, по крайней мере, эмулированного аппаратного) рендеринга графики. WPF интенсивно использует аппаратную графику, и на машинах с низкой графической способностью производительность пострадает.
вы можете обойти это, включив параметр реестра, который отключает аппаратное ускорение. Это особенно полезно на машинах, которые могут чрезмерно сообщать о своих возможностях (из опыта это особенно влияет ВМ и встроенные графические чипсеты).
раздел реестра вам нужно HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\DisableHWAcceleration
, a DWORD
что вы должны ставить 1
. Обратите внимание, что это общесистемное и повлияет на все приложения WPF-не устанавливайте его как часть приложения, а используйте его в среде виртуальной машины и убедитесь, что вы снова тестируете надлежащее оборудование перед выпуском.
более дальнеишее чтение здесь.