2017-01-28 13 views
0

Я пытаюсь преобразовать DrawingImage в MemoryStream. Мой код выглядит следующим образом:Как конвертировать System.Windows.Media.DrawingImage в поток?

public MemoryStream ImageStream(DrawingImage drawingImage) 
    { 
     MemoryStream stream = new MemoryStream(); 
     ImageSource imageSource = drawingImage; 
     if (imageSource != null) 
     { 
      BitmapSource bitmap = imageSource as BitmapSource; 
      if (bitmap != null) 
      { 
       BitmapEncoder encoder = new PngBitmapEncoder(); 
       encoder.Frames.Add(BitmapFrame.Create(bitmap)); 
       encoder.Save(stream); 
      }  
     } 

     return stream; 
    } 

Но проблема после литья ImageSource в BitmapSource растрового изображения всегда нуль. Любой вопрос, как это исправить?

ответ

1

Причина, по которой ваша переменная 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); 
} 

Тогда вы могли бы использовать его с любым видом потока. Например, чтобы сохранить чертеж в файл:

+0

Спасибо за ответ! У меня многопоточное приложение и «DrawingImage», который я создаю во втором потоке. Затем мне нужно передать этот «DrawImage» в поток пользовательского интерфейса и отобразить в элементе управления Image. Проблема в том, что я получаю сообщение об ошибке «Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток», когда я использую Dispatcher.Invoke для отображения «DrawImage» в элементе управления Image. Вот почему я думал о преобразовании «DrawImage» в поток, а затем передал этот поток в основной поток и отображение. Теперь я собираюсь попробовать ваше предложение. – Shagohad

+0

Спасибо за помощь, отлично работает! :) – Shagohad

+1

Вы должны быть способны выполнить то, что хотите, с меньшими шагами и лучшей производительностью. 'DrawingImage' является' Freezable'. Если вы назовете 'Freeze()' на нем, тогда вы сможете прочитать его из другого потока. Если вы также хотите изменить его в другом потоке, вы можете 'Clone()' it из этого потока. – Xavier

 Смежные вопросы

  • Нет связанных вопросов^_^