WPF - 将位图转换为 ImageSource
Posted
技术标签:
【中文标题】WPF - 将位图转换为 ImageSource【英文标题】:WPF - converting Bitmap to 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找到的。我在
得到一个 NullReferenceExceptionreturn (ImageSource) c.ConvertFrom(Resources.my_banner);
如何初始化 ImageSource 以避免此异常?还是有其他方法? 之后我想使用它:
<xctk:WizardPage x:Name="StartPage" Height="500" Width="700"
HeaderImage="Binding HeaderBitmap"
Enter="StartPage_OnEnter"
提前感谢您的任何回答。
【问题讨论】:
见这里:What is a NullReferenceException and how do I fix it? 【参考方案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 下面的回答 (***.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 格式;如果您正在处理其他格式,则可能需要添加转换。
【讨论】:
以上是关于WPF - 将位图转换为 ImageSource的主要内容,如果未能解决你的问题,请参考以下文章
使用medata数据wpf c#将位图保存为png [重复]