C # - конвертировать WPF Image.source в System.Drawing.Bitmap - PullRequest
18 голосов
/ 17 апреля 2011

Я нашел множество людей, конвертирующих BitmapSource в Bitmap, но как насчет ImageSource в Bitmap? Я делаю программу обработки изображений, и мне нужно извлечь растровые изображения из изображения, отображаемого в элементе Image. Кто-нибудь знает, как это сделать?

РЕДАКТИРОВАТЬ 1:

Это функция для преобразования BitmapImage в Bitmap. Не забудьте установить опцию unsafe в настройках компилятора.

public static System.Drawing.Bitmap BitmapSourceToBitmap(BitmapSource srs)
{
    System.Drawing.Bitmap btm = null;

    int width = srs.PixelWidth;

    int height = srs.PixelHeight;

    int stride = width * ((srs.Format.BitsPerPixel + 7) / 8);

    byte[] bits = new byte[height * stride];

    srs.CopyPixels(bits, stride, 0);

    unsafe
    {
        fixed (byte* pB = bits)
        {
            IntPtr ptr = new IntPtr(pB);

            btm = new System.Drawing.Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format1bppIndexed, ptr);
        }
    }
    return btm;
}

Далее теперь нужно получить BitmapImage:

RenderTargetBitmap targetBitmap = new RenderTargetBitmap(
    (int)inkCanvas1.ActualWidth,
    (int)inkCanvas1.ActualHeight,
    96d, 96d,
    PixelFormats.Default);

targetBitmap.Render(inkCanvas1);

MemoryStream mse = new MemoryStream();
System.Windows.Media.Imaging.BmpBitmapEncoder mem = new BmpBitmapEncoder();
mem.Frames.Add(BitmapFrame.Create(targetBitmap));
mem.Save(mse);

mse.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = mse;
bi.EndInit();

Далее следует преобразовать его:

Bitmap b = new Bitmap(BitmapSourceToBitmap(bi));

Ответы [ 4 ]

22 голосов
/ 19 апреля 2011

На самом деле вам не нужно использовать небезопасный код. Существует перегрузка CopyPixels, которая принимает IntPtr:

public static System.Drawing.Bitmap BitmapSourceToBitmap2(BitmapSource srs)
{
    int width = srs.PixelWidth;
    int height = srs.PixelHeight;
    int stride = width * ((srs.Format.BitsPerPixel + 7) / 8);
    IntPtr ptr = IntPtr.Zero;
    try
    {
        ptr = Marshal.AllocHGlobal(height * stride);
        srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height * stride, stride);
        using (var btm = new System.Drawing.Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format1bppIndexed, ptr))
        {
            // Clone the bitmap so that we can dispose it and
            // release the unmanaged memory at ptr
            return new System.Drawing.Bitmap(btm);
        }
    }
    finally
    {
        if (ptr != IntPtr.Zero)
            Marshal.FreeHGlobal(ptr);
    }
}
3 голосов
/ 24 сентября 2013

Этот пример работал для меня:

    public static Bitmap ConvertToBitmap(BitmapSource bitmapSource)
    {
        var width = bitmapSource.PixelWidth;
        var height = bitmapSource.PixelHeight;
        var stride = width * ((bitmapSource.Format.BitsPerPixel + 7) / 8);
        var memoryBlockPointer = Marshal.AllocHGlobal(height * stride);
        bitmapSource.CopyPixels(new Int32Rect(0, 0, width, height), memoryBlockPointer, height * stride, stride);
        var bitmap = new Bitmap(width, height, stride, PixelFormat.Format32bppPArgb, memoryBlockPointer);
        return bitmap;
    }
2 голосов
/ 17 апреля 2011

Ваш ImageSource не является BitmapSource?Если вы загружаете изображения из файлов, они должны быть.

Ответ на ваш комментарий:

Похоже, что они должны быть BitmapSource, BitmapSource является подтипом ImageSource.Приведите ImageSource к BitmapSource и следуйте одному из этих блогов.

1 голос
/ 10 января 2012

Вам не нужен BitmapSourceToBitmap метод вообще.Просто сделайте следующее после создания потока памяти:

mem.Position = 0;  
Bitmap b = new Bitmap(mem);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...