WPF - преобразование Bitmap в ImageSource
Мне нужно преобразовать System.Drawing.Bitmap в класс System.Windows.Media.ImageSource, чтобы связать его с элементом управления HeaderImage в WizardPage (расширенный набор инструментов WPF).
Растровое изображение устанавливается как ресурс сборки, которую я пишу.
Он ссылается так:
public Bitmap GetBitmap
{
get
{
Bitmap bitmap = new Bitmap(Resources.my_banner);
return bitmap;
}
}
public ImageSource HeaderBitmap
{
get
{
ImageSourceConverter c = new ImageSourceConverter();
return (ImageSource) c.ConvertFrom(GetBitmap);
}
}
Конвертор был найден мной здесь: http://www.codeproject.com/info/621920/How-to-convert-Bitmap-to-ImageSource
Я получаю исключение NullReferenceException в
return (ImageSource) c.ConvertFrom(Resources.my_banner);
Как я могу инициализировать ImageSource, чтобы избежать этого исключения? Или есть другой способ?
Я хочу использовать его после:
<xctk:WizardPage x:Name="StartPage" Height="500" Width="700"
HeaderImage="{Binding HeaderBitmap}" Enter="StartPage_OnEnter"
Заранее благодарим за любые ответы.
Ответы
Ответ 1
Для других это работает:
//If you get 'dllimport unknown'-, then add 'using System.Runtime.InteropServices;'
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
public ImageSource ImageSourceFromBitmap(Bitmap bmp)
{
var handle = bmp.GetHbitmap();
try
{
return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
finally { DeleteObject(handle); }
}
Ответ 2
В интересах поисковиков я создал быстрый конвертер на основе этого более подробного решения .
Пока никаких проблем.
using System;
using System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;
namespace XYZ.Helpers
{
public class ConvertBitmapToBitmapImage
{
/// <summary>
/// Takes a bitmap and converts it to an image that can be handled by WPF ImageBrush
/// </summary>
/// <param name="src">A bitmap image</param>
/// <returns>The image as a BitmapImage for WPF</returns>
public BitmapImage Convert(Bitmap src)
{
MemoryStream ms = new MemoryStream();
((System.Drawing.Bitmap)src).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();
return image;
}
}
}
Ответ 3
Я не считаю, что ImageSourceConverter
будет конвертировать из System.Drawing.Bitmap
. Однако вы можете использовать следующее:
public static BitmapSource CreateBitmapSourceFromGdiBitmap(Bitmap bitmap)
{
if (bitmap == null)
throw new ArgumentNullException("bitmap");
var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
var bitmapData = bitmap.LockBits(
rect,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
try
{
var size = (rect.Width * rect.Height) * 4;
return BitmapSource.Create(
bitmap.Width,
bitmap.Height,
bitmap.HorizontalResolution,
bitmap.VerticalResolution,
PixelFormats.Bgra32,
null,
bitmapData.Scan0,
size,
bitmapData.Stride);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
}
Это решение требует, чтобы исходное изображение находилось в формате Bgra32; если вы имеете дело с другими форматами, вам может потребоваться добавить конверсию.
Ответ 4
dethSwatch - Спасибо за ваш ответ выше! Это очень помогло! После его реализации я получил желаемое поведение, но обнаружил, что у меня возникает проблема с памятью/дескриптором в другом разделе моей программы. Я изменил код следующим образом, сделав его более многословным, и проблема исчезла. Еще раз спасибо!
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
public ImageSource ImageSourceForBitmap(Bitmap bmp)
{
var handle = bmp.GetHbitmap();
try
{
ImageSource newSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
DeleteObject(handle);
return newSource;
}
catch (Exception ex)
{
DeleteObject(handle);
return null;
}
}
Ответ 5
Самое простое решение для меня:
ImageBrush myBrush = new ImageBrush();
var bitmap = System.Drawing.Image.FromFile("pic1.bmp");
Bitmap bitmap = new System.Drawing.Bitmap(image);//it is in the memory now
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());
myBrush.ImageSource = bitmapSource;
cover.MainGrid.Background = myBrush;
cover.Show();
bitmap.Dispose();