Convertendo BitmapImage para Bitmap e vice-versa

Eu tenho BitmapImage em c #. Eu preciso fazer operações na imagem. Por exemplo, grayscaling, adicionando texto na imagem, etc.

Eu encontrei a function em stackoverflow para grayscaling que aceita Bitmap e retorna Bitmap.

Então eu preciso converter BitmapImage para Bitmap, fazer a operação e converter de volta.

Como posso fazer isso? Esse é o melhor caminho?

Não há necessidade de usar bibliotecas estrangeiras.

Converta um BitmapImage em Bitmap:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage) { // BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative)); using(MemoryStream outStream = new MemoryStream()) { BitmapEncoder enc = new BmpBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(bitmapImage)); enc.Save(outStream); System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream); return new Bitmap(bitmap); } } 

Para converter o Bitmap de volta em um BitmapImage:

 [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); private BitmapImage Bitmap2BitmapImage(Bitmap bitmap) { IntPtr hBitmap = bitmap.GetHbitmap(); BitmapImage retval; try { retval = (BitmapImage)Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } finally { DeleteObject(hBitmap); } return retval; } 

Aqui está um método de extensão para converter um Bitmap em BitmapImage.

  public static BitmapImage ToBitmapImage(this Bitmap bitmap) { using (var memory = new MemoryStream()) { bitmap.Save(memory, ImageFormat.Png); memory.Position = 0; var bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = memory; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); bitmapImage.Freeze(); return bitmapImage; } } 

Se você só precisa ir de BitmapImage para Bitmap é muito fácil,

 private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage) { return new Bitmap(bitmapImage.StreamSource); } 

using System.Windows.Interop; …

  private BitmapImage Bitmap2BitmapImage(Bitmap bitmap) { BitmapSource i = Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); return (BitmapImage)i; } 

Acabei de tentar usar o código acima em meu código e acredito que há um problema com a function Bitmap2BitmapImage (e possivelmente a outra também).

 using (MemoryStream ms = new MemoryStream()) 

A linha acima resulta no stream sendo descartado? O que significa que o BitmapImage retornado perde seu conteúdo.

Como sou um novato do WPF, não tenho certeza se essa é a explicação técnica correta, mas o código não funcionou no meu aplicativo até que eu removesse a diretiva using.

Aqui a versão assíncrona.

 public static Task ToBitmapSourceAsync(this Bitmap bitmap) { return Task.Run(() => { using (System.IO.MemoryStream memory = new System.IO.MemoryStream()) { bitmap.Save(memory, ImageFormat.Png); memory.Position = 0; BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = memory; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); bitmapImage.Freeze(); return bitmapImage as BitmapSource; } }); } 

Isso converte de System.Drawing.Bitmap para BitmapImage:

 MemoryStream ms = new MemoryStream(); YOURBITMAP.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); BitmapImage image = new BitmapImage(); image.BeginInit(); ms.Seek(0, SeekOrigin.Begin); image.StreamSource = ms; image.EndInit(); 

Obrigado Guillermo Hernandez, criei uma variação do seu código que funciona. Eu adicionei os namespaces neste código para referência.

 System.Reflection.Assembly theAsm = Assembly.LoadFrom("My.dll"); // Get a stream to the embedded resource System.IO.Stream stream = theAsm.GetManifestResourceStream(@"picture.png"); // Here is the most important part: System.Windows.Media.Imaging.BitmapImage bmi = new BitmapImage(); bmi.BeginInit(); bmi.StreamSource = stream; bmi.EndInit();