2017-01-28 50 views
0

我試圖將DrawingImage轉換成MemoryStream。我的代碼如下所示:如何將System.Windows.Media.DrawingImage轉換爲Stream?

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

然後,你可以使用它與任何類型的流。例如,將繪圖保存到文件中:

using (FileStream file = File.Create("somepath.png")) 
{ 
    SavePng(Rasterize(drawingImage.Drawing), file); 
} 
+0

感謝您的回覆!我有一個多線程應用程序,以及我在第二個線程上創建的「DrawingImage」。比我需要將該「DrawImage」傳遞到UI線程,並顯示在圖像控制。問題是我收到錯誤「調用線程無法訪問此對象,因爲不同的線程擁有它」當我使用Dispatcher.Invoke在圖像控件中顯示「DrawImage」。這就是爲什麼我正在考慮將「DrawImage」轉換爲流,並將該流傳遞給主線程並顯示。現在我要嘗試你的提議。 – Shagohad

+0

感謝您的幫助,工作正常! :) – Shagohad

+1

你應該能夠用更少的步驟和更好的表現完成你想要的任務。 'DrawingImage'是一個'Freezable'。如果你調用'Freeze()',你應該可以從另一個線程讀取它。如果你還想在其他線程上修改它,那麼你可以從該線程克隆()。 – Xavier

相關問題