【问题标题】:WPF - converting Bitmap to ImageSourceWPF - 将位图转换为 ImageSource
【发布时间】:2014-12-03 08:02:23
【问题描述】:

我需要将 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);
   }
}

转换器是我here找到的。我在

得到一个 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


【解决方案1】:
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;
    }
}

【讨论】:

    【解决方案2】:

    对其他人来说,这是可行的:

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

    【讨论】:

    • 你是我的英雄。用它来为 Bitmap 类做一个扩展,效果很好。干得好。
    • @ARidder101 我确定我是从其他人那里得到的。
    • 这种方法提供了非常低质量的透明度。 Mike Strobel 下面的回答 (stackoverflow.com/a/26261562/418362) 要好得多,不需要任何互操作。
    • 让我知道当我没有调用 DeleteObject(handle) 时会发生什么。我有一个问题。谢谢。
    • 早在 .NET 2.0 天的 Windows XP 上,可以同时打开 10.000 个句柄的限制。当达到该限制时,机器冻结了。 - 所以不调用删除,意味着你会泄漏一个句柄。 .NET 可以在某处适当地清理它,但您很可能会受到性能影响。'
    【解决方案3】:

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

    【讨论】:

    • 你的一个更漂亮的变体:) ``` var handle = bmp.GetHbitmap();尝试 { 返回 Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } 捕捉 { 返回空值; } 最后 { Win32.DeleteObject(handle); } ```
    【解决方案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();
    

    【讨论】:

    • 我认为GetHbitmap的hande应该被释放。
    【解决方案5】:

    为了搜索者的利益,我基于detailed solution 创建了一个快速转换器。

    目前没有问题。

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

    【讨论】:

    • 今天你是我的神
    • 我喜欢这个。我喜欢这个。
    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 2022-01-20
      • 1970-01-01
      • 2015-08-23
      • 2018-12-27
      • 1970-01-01
      相关资源
      最近更新 更多