Есть ли хороший способ конвертировать между BitmapSource и Bitmap?
-
21-09-2019 - |
Вопрос
Насколько я могу судить, единственный способ преобразовать BitmapSource в Bitmap - это использовать небезопасный код...Вот так (из Лестерс блог WPF):
myBitmapSource.CopyPixels(bits, stride, 0);
unsafe
{
fixed (byte* pBits = bits)
{
IntPtr ptr = new IntPtr(pBits);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(
width,
height,
stride,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb,ptr);
return bitmap;
}
}
Чтобы сделать обратное:
System.Windows.Media.Imaging.BitmapSource bitmapSource =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
Есть ли более простой способ в фреймворке?И по какой причине этого там нет (если это не так)?Я бы подумал, что это вполне пригодно для использования.
Причина, по которой мне это нужно, заключается в том, что я использую AForge для выполнения определенных операций с изображениями в приложении WPF.WPF хочет показать BitmapSource / ImageSource, но AForge работает с растровыми изображениями.
Решение
Это можно сделать без использования небезопасного кода, используя Bitmap.LockBits
и скопируйте пиксели из BitmapSource
прямо к Bitmap
Bitmap GetBitmap(BitmapSource source) {
Bitmap bmp = new Bitmap(
source.PixelWidth,
source.PixelHeight,
PixelFormat.Format32bppPArgb);
BitmapData data = bmp.LockBits(
new Rectangle(Point.Empty, bmp.Size),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppPArgb);
source.CopyPixels(
Int32Rect.Empty,
data.Scan0,
data.Height * data.Stride,
data.Stride);
bmp.UnlockBits(data);
return bmp;
}
Другие советы
Вы можете просто использовать эти два метода:
public static BitmapSource ConvertBitmap(Bitmap source)
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
source.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
public static Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
Bitmap bitmap;
using (var outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new Bitmap(outStream);
}
return bitmap;
}
У меня это работает идеально.
Это то, что ты ищешь?
Bitmap bmp = System.Drawing.Image.FromHbitmap(pBits);
Вот код для установки прозрачного фона для любого растрового ресурса в словаре ресурсов (не Resources.resx, часто используемого в Windows.Возраст форм).Я вызываю этот метод перед InitializeComponent() - methode .Методы 'ConvertBitmap (Bitmap source)' и BitmapFromSource (BitmapSource bitmapsource) упомянуты в сообщении melvas выше.
private void SetBitmapResourcesTransparent()
{
Image img;
BitmapSource bmpSource;
System.Drawing.Bitmap bmp;
foreach (ResourceDictionary resdict in Application.Current.Resources.MergedDictionaries)
{
foreach (DictionaryEntry dictEntry in resdict)
{
// search for bitmap resource
if ((img = dictEntry.Value as Image) is Image
&& (bmpSource = img.Source as BitmapSource) is BitmapSource
&& (bmp = BitmapFromSource(bmpSource)) != null)
{
// make bitmap transparent and assign it back to ressource
bmp.MakeTransparent(System.Drawing.Color.Magenta);
bmpSource = ConvertBitmap(bmp);
img.Source = bmpSource;
}
}
}
}
Это аккуратно и быстрее света:
return Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero,
Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() );
Вы можете совместно использовать пиксельные данные между обоими пространствами имен.Вам не нужно переходить в другую веру.
Используйте SharedBitmapSource. https://stackoverflow.com/a/32841840/690656