Есть ли хороший способ конвертировать между BitmapSource и Bitmap?
Насколько я могу судить, единственный способ преобразовать BitmapSource в Bitmap-это использовать небезопасный код... Вот так (из блога Lesters 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 работает на растровых изображениях.
6 ответов:
Можно обойтись без использования небезопасного кода с помощью
Bitmap.LockBitsи скопировать пиксели изBitmapSourceпрямо вBitmapBitmap 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; }Это прекрасно работает для меня.
Здесь код для установки прозрачного фона для любого растрового ресурса в словаре ресурсов(не ресурсов.resx часто используется в Windows.Формы возрастные). Я называю это методом перед метода initializecomponent () методом. Методы "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() );
Вы можете совместно использовать pixeldata между обоими пространствами имен. Вам не нужно обращаться.
Используйте SharedBitmapSource. https://stackoverflow.com/a/32841840/690656
Comments