WPF - 将位图转换为 ImageSource

问题描述 投票:0回答:6

我需要将

System.Drawing.Bitmap
转换为
System.Windows.Media.ImageSource
类,以便将其绑定到 WizardPage(扩展 WPF 工具包)的 HeaderImage 控件中。 位图被设置为我编写的程序集的资源。 它被这样引用:

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);
   }
}

转换器是我在这里找到的。我在

处收到 NullReferenceException
return (ImageSource) c.ConvertFrom(Resources.my_banner);

如何初始化 ImageSource 以避免出现此异常?或者还有别的办法吗? 我想以后使用它,例如:

<xctk:WizardPage x:Name="StartPage" Height="500" Width="700"
                 HeaderImage="{Binding HeaderBitmap}" 
                 Enter="StartPage_OnEnter"

提前感谢您的回答。

c# wpf bitmap type-conversion imagesource
6个回答
51
投票

对于其他人来说,这有效:

// 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); }
}

32
投票

为了搜索者的利益,我基于这个更详细的解决方案创建了一个快速转换器。

到目前为止没有任何问题。

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;
        }
    }
}

14
投票

我不相信

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格式;如果您正在处理其他格式,您可能需要添加转换。


14
投票

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
投票
void Draw()
{
    System.Drawing.Bitmap bmp = new Bitmap();
    ...
    Image img = new Image();
    img.Source = BitmapToImageSource(bmp)
 }


private BitmapImage BitmapToImageSource(System.Drawing.Bitmap bitmap)
{
    using (MemoryStream memory = new MemoryStream())
    {
        bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
        memory.Position = 0;
        BitmapImage bitmapimage = new BitmapImage();
        bitmapimage.BeginInit();
        bitmapimage.StreamSource = memory;
        bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapimage.EndInit();
        return bitmapimage;
    }
}

4
投票

对我来说最简单的解决方案:

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();
© www.soinside.com 2019 - 2024. All rights reserved.