J'ai BitmapImage en C #. J'ai besoin de faire des opérations sur l'image. Par exemple, niveaux de gris, ajout de texte sur une image, etc.
J'ai trouvé une fonction dans stackoverflow pour le grayscaling qui accepte Bitmap et renvoie Bitmap.
J'ai donc besoin de convertir BitmapImage en Bitmap, effectuer l'opération et reconvertir.
Comment puis-je faire ceci? Est-ce le meilleur moyen?
Il n'est pas nécessaire d'utiliser des bibliothèques étrangères.
Convertir une image bitmap en 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);
}
}
Pour reconvertir le bitmap en image bitmap:
[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;
}
Voici une méthode d'extension pour convertir un bitmap en 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;
}
}
Si vous avez juste besoin de passer de BitmapImage à Bitmap, c'est assez simple,
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;
}
Je viens d'essayer d'utiliser ce qui précède dans mon code et je pense qu'il y a un problème avec la fonction Bitmap2BitmapImage (et peut-être aussi avec l'autre).
using (MemoryStream ms = new MemoryStream())
La ligne ci-dessus entraîne-t-elle l'élimination du flux? Ce qui signifie que BitmapImage renvoyé perd son contenu.
Comme je suis un débutant sur WPF, je ne suis pas sûr que ce soit l'explication technique correcte, mais le code ne fonctionnait pas dans mon application jusqu'à ce que je supprime la directive using.
Voici la version async.
public static Task<BitmapSource> 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;
}
});
}
Merci Guillermo Hernandez, j'ai créé une variante de votre code qui fonctionne. J'ai ajouté les espaces de noms dans ce code pour référence.
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();
Cela convertit System.Drawing.Bitmap en 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();