Причина, по которой ваша переменная bitmap
всегда равна нулю, заключается в том, что DrawingImage
не распространяется на BitmapImage
или наоборот, поэтому литой гарантируется сбой. A DrawingImage
не содержит никаких пиксельных данных любого типа. Он ссылается на Drawing
, который используется всякий раз, когда изображение нужно растрировать.
Как вы оказались в ситуации, когда хотите растрировать DrawingImage
и сериализовать ее в поток? Я чувствую, что вы что-то делаете необычным образом, если вам нужна такая функция.
Тем не менее, вы могли бы реализовать эту функцию, рисуя DrawingImage
к DrawingVisual
, что делает его в RenderTargetBitmap
, а затем передать рендер цели кодера для упорядочивания растровых данных в поток.
public MemoryStream ImageStream(DrawingImage drawingImage)
{
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
dc.DrawDrawing(drawingImage.Drawing);
dc.Close();
}
RenderTargetBitmap target = new RenderTargetBitmap((int)visual.Drawing.Bounds.Right, (int)visual.Drawing.Bounds.Bottom, 96.0, 96.0, PixelFormats.Pbgra32);
target.Render(visual);
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(target));
encoder.Save(stream);
return stream;
}
Если вы хотите нечто более общее, я бы разделил его на два метода и изменил некоторые типы.
public BitmapSource Rasterize(Drawing drawing)
{
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
dc.DrawDrawing(drawing);
dc.Close();
}
RenderTargetBitmap target = new RenderTargetBitmap((int)drawing.Bounds.Right, (int)drawing.Bounds.Bottom, 96.0, 96.0, PixelFormats.Pbgra32);
target.Render(visual);
return target;
}
public void SavePng(BitmapSource source, Stream target)
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(target);
}
Тогда вы могли бы использовать его с любым видом потока. Например, чтобы сохранить чертеж в файл:
Спасибо за ответ! У меня многопоточное приложение и «DrawingImage», который я создаю во втором потоке. Затем мне нужно передать этот «DrawImage» в поток пользовательского интерфейса и отобразить в элементе управления Image. Проблема в том, что я получаю сообщение об ошибке «Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток», когда я использую Dispatcher.Invoke для отображения «DrawImage» в элементе управления Image. Вот почему я думал о преобразовании «DrawImage» в поток, а затем передал этот поток в основной поток и отображение. Теперь я собираюсь попробовать ваше предложение. – Shagohad
Спасибо за помощь, отлично работает! :) – Shagohad
Вы должны быть способны выполнить то, что хотите, с меньшими шагами и лучшей производительностью. 'DrawingImage' является' Freezable'. Если вы назовете 'Freeze()' на нем, тогда вы сможете прочитать его из другого потока. Если вы также хотите изменить его в другом потоке, вы можете 'Clone()' it из этого потока. – Xavier