Отображение изображения в памяти WPF - PullRequest
0 голосов
/ 10 июня 2010

Я пытаюсь создать шаблон элемента для моего списка и я привязан к списку объектов. У моей сущности есть System.Drawing.Image, которую я хотел бы отобразить, но пока я не могу понять, как связать ее с блоком <Image>.

Каждый пример и документация, которую я могу найти в Интернете, относится к изображениям, доступным через uri, т.е. файл на жестком диске или на веб-сайте

    <DataTemplate x:Key="LogoPreviewItem">
        <Border BorderBrush="Black" BorderThickness="1">
            <DockPanel Width="150" Height="100">
                <Image>
                    <Image.Source>
                        <!--
                            {Binding PreviewImage} is where the System.Drawing.Image
                            is in this context
                        -->
                    </Image.Source>
                </Image>
                <Label DockPanel.Dock="Bottom" Content="{Binding CustomerName}" />
            </DockPanel>
        </Border>
    </DataTemplate>

Ответы [ 2 ]

4 голосов
/ 11 июня 2010

System.Drawing.Image является объектом WinForms / GDI + и действительно неуместен в мире WPF. Чистая программа WPF обычно не использует System.Drawing.Image, но вместо этого использует BitmapSource. Однако иногда мы на какое-то время застреваем со старыми вещами.

Вы можете преобразовать свое изображение из старой технологии в новую следующим образом:

var oldImage = ...;  // System.Drawing.Image

var oldBitmap =
  oldImage as System.Drawing.Bitmap ??
  new System.Drawing.Bitmap(oldImage);

var bitmapSource =
   System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
     oldBitmap.GetHbitmap(System.Drawing.Color.Transparent),
     IntPtr.Zero,
     new Int32Rect(0, 0, oldBitmap.Width, oldBitmap.Height),
     null);

Теперь вы можете установить:

myImage.Source = bitmapSource;

Это намного быстрее, чем подход MemoryStream, который вы найдете описанным в другом месте, поскольку он никогда не сериализует растровые данные в поток.

0 голосов
/ 07 июня 2019

Ответ Рэй Бернса приводит к утечке памяти, так как

oldBitmap.GetHbitmap(System.Drawing.Color.Transparent)

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

Как указано в разделе «Примечания» в документации для GetHbitmap ( Документы Microsoft ):

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

Следуя документации, освобождается память путем импорта и использования DeleteObject():

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

var hBitmap = someBitmap.GetHbitmap(...);

// Do something with hBitmap

DeleteObject(hBitmap);

Таким образом, ответ Рэй Бернса следует изменить на:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

...

var oldImage = ...;  // System.Drawing.Image

var oldBitmap =
  oldImage as System.Drawing.Bitmap ??
  new System.Drawing.Bitmap(oldImage);

var hOldBitmap = oldBitmap.GetHbitmap(System.Drawing.Color.Transparent);
var bitmapSource =
   System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
     hOldBitmap,
     IntPtr.Zero,
     new Int32Rect(0, 0, oldBitmap.Width, oldBitmap.Height),
     null);
DeleteObject(hOldBitmap);
...