Подтвердить что ты не робот

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"

Заранее благодарим за любые ответы.

4b9b3361

Ответ 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();