Подтвердить что ты не робот

Преобразование BitmapImage в Bitmap и наоборот

У меня есть BitmapImage в С#. Мне нужно делать операции с изображением. Например, серая печать, добавление текста на изображение и т.д.

Я нашел функцию в stackoverflow для оттенков серого, которая принимает битмап и возвращает битмап.

Поэтому мне нужно преобразовать BitmapImage в Bitmap, выполнить операцию и преобразовать обратно.

Как я могу это сделать? Это лучший способ?

4b9b3361

Ответ 1

Нет необходимости использовать внешние библиотеки.

Преобразовать BitmapImage в 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);
    }
}

Чтобы преобразовать Bitmap обратно в 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;
}

Ответ 2

Здесь используется метод расширения для преобразования Bitmap в 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;
        }
    }

Ответ 3

с использованием System.Windows.Interop; ...

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

Ответ 4

Я только что пытался использовать выше в моем коде, и я считаю, что есть проблема с функцией Bitmap2BitmapImage (и, возможно, с другой).

using (MemoryStream ms = new MemoryStream())

Вызывается ли вышеприведенная строка в потоке? Это означает, что возвращенный BitmapImage теряет свой контент.

Как я новичок WPF, я не уверен, что это правильное техническое объяснение, но код не работал в моем приложении, пока я не удалю директиву using.

Ответ 5

Если вам просто нужно перейти из BitmapImage в Bitmap, это довольно просто,

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

Ответ 6

Здесь асинхронная версия.

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;
        }
    });

}

Ответ 7

Это преобразование из System.Drawing.Bitmap в 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();

Ответ 8

Спасибо Гильермо Эрнандес, я создал вариацию вашего кода, который работает. Я добавил пространства имен в этот код для справки.

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();

Ответ 9

Вы можете использовать AForge.Net.

В частности, см. следующий пример из этого отправления AForge.Net:

using AForge.Imaging.Filters;  

// Loading some file  
using (Bitmap SampleImage = (Bitmap)Image.FromFile("test.jpg"))  
{  
    // We must convert it to grayscale because  
    // the filter accepts 8 bpp grayscale images  
    Grayscale GF = new Grayscale(0.2125, 0.7154, 0.0721);  
    using (Bitmap GSampleImage = GF.Apply(SampleImage))  
    {  
        // Saving the grayscale image, so we could see it later  
        GSampleImage.SaveAsJpeg("testBW.jpg", 100);  
    }
}

НТН