2010-02-17 37 views
35

至於我可以告訴從的BitmapSource轉換爲位圖的唯一途徑是通過不安全的代碼......像這樣(從Lesters WPF blog):有沒有一種很好的方式來轉換BitmapSource和位圖?

myBitmapSource.CopyPixels(bits, stride, 0); 

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

     System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(
     width, 
     height, 
     stride, 
     System.Drawing.Imaging.PixelFormat.Format32bppPArgb,ptr); 

     return bitmap; 
    } 
} 

要反過來做:

System.Windows.Media.Imaging.BitmapSource bitmapSource = 
    System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    bitmap.GetHbitmap(), 
    IntPtr.Zero, 
    Int32Rect.Empty, 
    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); 

在框架中有更簡單的方法嗎?它不在那裏的原因是什麼(如果不是)?我認爲這是相當有用的。

我需要它的原因是因爲我使用AForge在WPF應用程序中執行某些圖像操作。 WPF希望顯示BitmapSource/ImageSource,但是AForge在位圖上工作。

+10

要做相反的事情,你*必須**刪除你用'GetHbitmap'得到的位圖句柄。這個錯誤遍佈互聯網。這是不可修復的。世界正在緩慢泄漏GDI手柄;我們很快就會在他們身上游泳! – 2011-12-31 04:25:10

+0

Thx,指出:) – JohannesH 2012-01-03 10:22:28

+2

romkyns指的是這個:http://stackoverflow.com/questions/1546091/wpf-createbitmapsourcefromhbitmap-memory-leak – 2012-04-26 21:24:44

回答

54

這是可以做到不使用不安全的代碼使用Bitmap.LockBitsBitmapSource像素直接複製到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; 
} 
+4

只有像素格式是事先知道的,它纔會起作用,它與我一起使用的方式以及在像素格式之間映射的附加功能非常相似。 – JohannesH 2010-05-26 20:43:26

+0

這是適用於WPF的?位圖似乎來自System.Drawing並在WinForms中使用。 儘管在WPF中使用了BitmapSource。 – Jonas 2014-05-09 09:41:42

+0

上面的代碼用於將WPF BitmapSource轉換爲Windows窗體位圖,如果正確的程序集被引用,代碼應該在WPF中「工作」,但它不會非常有用,因爲如果您已經有了可以使用的BitmapSource它直接在WPF中。 – 2014-05-09 09:49:30

2

這是你要找的嗎?

Bitmap bmp = System.Drawing.Image.FromHbitmap(pBits); 
+2

我不認爲這是正確的 - 你正在傳遞一個指向字節數組的指針,而它指向的是一個Win32位圖句柄。 - 謝謝你指出這個函數存在,但它很整潔。 – BrainSlugs83 2013-11-05 06:01:34

27

你可以使用這兩種方法:

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

它適用於我。

+0

我正在嘗試這個年齡!非常感謝!完美的作品! – 2014-09-12 07:10:55

+3

這是一個強大的解決方案,但要注意它不如位圖複製到內存流那麼高效,然後再次複製到新位圖的內存中。對於高分辨率圖像,這可能是性能問題。接受的答案解決這個問題。 – snort 2015-02-20 17:37:25

+0

MSDN說:「您必須保持該流在Bitmap的生命週期中打開。」解決方法是將新的克隆位圖和從流創建的Dispose位圖。 – Arci 2015-03-04 15:19:56

1

這裏是一個代碼,用於設置資源字典中任何位圖資源的透明背景(而不是Windows.Forms age中常用的Resources.resx)。我在InitializeComponent()方法之前調用這個方法。方法的'ConvertBitmap(Bitmap source)'和BitmapFromSource(BitmapSource 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

這是整潔得比光還快:

return Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, 
     Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 
相關問題