我有一个a的实例,System.Drawing.Bitmap并希望以一种形式将它提供给我的WPF应用程序System.Windows.Media.Imaging.BitmapImage.
对此最好的方法是什么?
Paw*_*ski 260
如何从MemoryStream加载它?
using(MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
Run Code Online (Sandbox Code Playgroud)
Kev*_*vin 81
感谢Hallgrim,这是我最终得到的代码:
ScreenCapture = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmp.GetHbitmap(),
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(width, height));
Run Code Online (Sandbox Code Playgroud)
我也最终绑定到BitmapSource而不是像我原来的问题中的BitmapImage
Ala*_*tts 53
我知道这已经得到了解答,但这里有一些扩展方法(适用于.NET 3.0+)进行转换.:)
/// <summary>
/// Converts a <see cref="System.Drawing.Image"/> into a WPF <see cref="BitmapSource"/>.
/// </summary>
/// <param name="source">The source image.</param>
/// <returns>A BitmapSource</returns>
public static BitmapSource ToBitmapSource(this System.Drawing.Image source)
{
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(source);
var bitSrc = bitmap.ToBitmapSource();
bitmap.Dispose();
bitmap = null;
return bitSrc;
}
/// <summary>
/// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
/// </summary>
/// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
/// </remarks>
/// <param name="source">The source bitmap.</param>
/// <returns>A BitmapSource</returns>
public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
{
BitmapSource bitSrc = null;
var hBitmap = source.GetHbitmap();
try
{
bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
catch (Win32Exception)
{
bitSrc = null;
}
finally
{
NativeMethods.DeleteObject(hBitmap);
}
return bitSrc;
}
Run Code Online (Sandbox Code Playgroud)
和NativeMethods类(安抚FxCop)
/// <summary>
/// FxCop requires all Marshalled functions to be in a class called NativeMethods.
/// </summary>
internal static class NativeMethods
{
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr hObject);
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*olf 22
我花了一些时间让转换工作在两个方面,所以这里是我提出的两种扩展方法:
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Media.Imaging;
public static class BitmapConversion {
public static Bitmap ToWinFormsBitmap(this BitmapSource bitmapsource) {
using (MemoryStream stream = new MemoryStream()) {
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(stream);
using (var tempBitmap = new Bitmap(stream)) {
// According to MSDN, one "must keep the stream open for the lifetime of the Bitmap."
// So we return a copy of the new bitmap, allowing us to dispose both the bitmap and the stream.
return new Bitmap(tempBitmap);
}
}
}
public static BitmapSource ToWpfBitmap(this Bitmap bitmap) {
using (MemoryStream stream = new MemoryStream()) {
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
BitmapImage result = new BitmapImage();
result.BeginInit();
// According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
// Force the bitmap to load right now so we can dispose the stream.
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Hal*_*rim 10
最简单的方法是如果你可以直接从文件中制作WPF位图.
否则,您将不得不使用System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap.
// at class level;
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject); // https://stackoverflow.com/a/1546121/194717
/// <summary>
/// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
/// </summary>
/// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
/// </remarks>
/// <param name="source">The source bitmap.</param>
/// <returns>A BitmapSource</returns>
public static System.Windows.Media.Imaging.BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
{
var hBitmap = source.GetHbitmap();
var result = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
return result;
}
Run Code Online (Sandbox Code Playgroud)
我在一家成像供应商工作,并为我们的图像格式编写了一个WPF适配器,类似于System.Drawing.Bitmap.
我写了这篇KB来向客户解释:
http://www.atalasoft.com/kb/article.aspx?id=10156
那里有代码可以做到.你需要用Bitmap替换AtalaImage并做我们正在做的事情 - 它应该非常简单.
您只需编写自定义位图源,即可在两个名称空间(媒体和图形)之间共享pixeldata。转换将立即发生,并且不会分配额外的内存。如果您不想显式创建位图的副本,则可以使用这种方法。
class SharedBitmapSource : BitmapSource, IDisposable
{
#region Public Properties
/// <summary>
/// I made it public so u can reuse it and get the best our of both namespaces
/// </summary>
public Bitmap Bitmap { get; private set; }
public override double DpiX { get { return Bitmap.HorizontalResolution; } }
public override double DpiY { get { return Bitmap.VerticalResolution; } }
public override int PixelHeight { get { return Bitmap.Height; } }
public override int PixelWidth { get { return Bitmap.Width; } }
public override System.Windows.Media.PixelFormat Format { get { return ConvertPixelFormat(Bitmap.PixelFormat); } }
public override BitmapPalette Palette { get { return null; } }
#endregion
#region Constructor/Destructor
public SharedBitmapSource(int width, int height,System.Drawing.Imaging.PixelFormat sourceFormat)
:this(new Bitmap(width,height, sourceFormat) ) { }
public SharedBitmapSource(Bitmap bitmap)
{
Bitmap = bitmap;
}
// Use C# destructor syntax for finalization code.
~SharedBitmapSource()
{
// Simply call Dispose(false).
Dispose(false);
}
#endregion
#region Overrides
public override void CopyPixels(Int32Rect sourceRect, Array pixels, int stride, int offset)
{
BitmapData sourceData = Bitmap.LockBits(
new Rectangle(sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height),
ImageLockMode.ReadOnly,
Bitmap.PixelFormat);
var length = sourceData.Stride * sourceData.Height;
if (pixels is byte[])
{
var bytes = pixels as byte[];
Marshal.Copy(sourceData.Scan0, bytes, 0, length);
}
Bitmap.UnlockBits(sourceData);
}
protected override Freezable CreateInstanceCore()
{
return (Freezable)Activator.CreateInstance(GetType());
}
#endregion
#region Public Methods
public BitmapSource Resize(int newWidth, int newHeight)
{
Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(Bitmap, 0, 0, newWidth, newHeight);
}
return new SharedBitmapSource(newImage as Bitmap);
}
public new BitmapSource Clone()
{
return new SharedBitmapSource(new Bitmap(Bitmap));
}
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Protected/Private Methods
private static System.Windows.Media.PixelFormat ConvertPixelFormat(System.Drawing.Imaging.PixelFormat sourceFormat)
{
switch (sourceFormat)
{
case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
return PixelFormats.Bgr24;
case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
return PixelFormats.Pbgra32;
case System.Drawing.Imaging.PixelFormat.Format32bppRgb:
return PixelFormats.Bgr32;
}
return new System.Windows.Media.PixelFormat();
}
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
_disposed = true;
}
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
211707 次 |
| 最近记录: |