Преобразование ImageSource в Bitmap [дубликат]

Имейте в виду, что независимо от сценария причина всегда одинакова в .NET:

Вы пытаетесь использовать ссылочную переменную, значение которой Nothing / null. Если для ссылочной переменной значение Nothing / null, это означает, что на самом деле оно не содержит ссылку на экземпляр любого объекта, который существует в куче.

Вы либо никогда не присваивали какую-либо переменную, никогда не создавали экземпляр значения, присвоенного переменной, или вы вручную устанавливали переменную, равную Nothing / null, или вы вызывали функцию, которая установите для этой переменной значение Nothing / null.

35
задан JohannesH 17 February 2010 в 21:59
поделиться

6 ответов

Можно обойтись без использования небезопасного кода с помощью Bitmap.LockBits и скопировать пиксели с BitmapSource прямо на Bitmap

Bitmap 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;
}
55
ответ дан josef.axa 3 September 2018 в 14:00
поделиться
  • 1
    Это будет работать только в том случае, если формат пикселей известен заранее, его почти так же, как и я, и дополнительной функции для отображения между форматами пикселей. – JohannesH 26 May 2010 в 21:43
  • 2
    Это работает с WPF? Похоже, что Bitmap исходит из System.Drawing и используется в WinForms. Однако BitmapSource используется в WPF. – Jonas 9 May 2014 в 10:41
  • 3
    Приведенный выше код используется для преобразования BitmapSource WPF в битмап Windows Forms, код должен «работать», в WPF при условии ссылки на правильные сборки, однако это будет не очень полезно, так как если у вас уже есть BitmapSource, вы можете использовать его непосредственно в WPF. – josef.axa 9 May 2014 в 10:49
  • 4
    :-) Извините, я не очень хорошо читал заголовок. Я искал способ конвертировать между пиксельными форматами. Найденный здесь: msdn.microsoft.com/en-us/library/aa970785 (v = vs.110) .aspx – Jonas 9 May 2014 в 11:32
  • 5
    Если в файле ссылаются оба Windows.Media и System.Drawing.Imaging, этот PixelFormat должен быть специально записан как System.Drawing.Imaging.PixelFormat. То же самое с System.Drawing.Point. – Nyerguds 21 August 2016 в 14:34

Это то, что вы ищете?

Bitmap bmp = System.Drawing.Image.FromHbitmap(pBits);
1
ответ дан caesay 3 September 2018 в 14:00
поделиться
  • 1
    Я не думаю, что это правильно - вы передаете указатель на массив байтов, где вместо этого он ожидает Win32 Bitmap Handle. - Спасибо, что указали, что эта функция существует, но это аккуратно. – BrainSlugs83 5 November 2013 в 08:01

Вы можете делиться пиксельными координатами между обоими пространствами имен. Вам не нужно преобразовывать.

Использовать SharedBitmapSource. https://stackoverflow.com/a/32841840/690656

0
ответ дан Community 3 September 2018 в 14:00
поделиться

Вы можете просто использовать эти два метода:

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

Он отлично работает для меня.

28
ответ дан Mateen Ulhaq 3 September 2018 в 14:00
поделиться
  • 1
    Я пытался это веками! Спасибо огромное! Работает отлично! – Noel Widmer 12 September 2014 в 08:10
  • 2
    Это надежное решение, но будьте осторожны, что его не так эффективно, как растровое изображение копируется в поток памяти, а затем копируется в память нового растрового изображения второй раз. Для изображений с высоким разрешением это может быть проблемой производительности. В принятом ответе речь идет об этом. – snort 20 February 2015 в 18:37
  • 3
    MSDN говорит: «Вы должны оставить поток открытым для жизни Bitmap». Обходной путь - это клонирование растрового изображения для нового и Dispose bitmap, созданного из потока. – Arci 4 March 2015 в 16:19
  • 4
    ConvertBitmap() утечка памяти. См. этот ответ для аналогичной альтернативы, которой нет. – Mateen Ulhaq 15 April 2016 в 19:00
  • 5
    Это заняло у меня возраст ... СПАСИБО !!!! – C0LD 10 February 2018 в 13:03

Это аккуратно и быстрее света:

  return Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero,
      Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() );
1
ответ дан sam 3 September 2018 в 14:00
поделиться

Здесь приведен код для установки прозрачного фона для любого растрового ресурса в словаре ресурсов (не Resource.resx, часто используемого в возрасте Windows.Forms). Я называю этот метод перед InitializeComponent () - методу. Методы «ConvertBitmap (источник битмапа)» и «BitmapFromSource» (битмапсурс источника 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;
                }
            }

        }

    }
1
ответ дан user3318309 3 September 2018 в 14:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: