将BitmapImage转换为Bitmap,反之亦然

Tig*_*yan 56 .net c# bitmap

我在C#中有BitmapImage.我需要对图像进行操作.例如灰度,在图像上添加文本等.

我在stackoverflow中找到了grayscaling函数,它接受Bitmap并返回Bitmap.

所以我需要将BitmapImage转换为Bitmap,进行操作并转换回来.

我怎样才能做到这一点?这是最好的方式吗?

Sas*_*nig 87

没有必要使用外国图书馆.

将BitmapImage转换为Bitmap:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
    // BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));

    using(MemoryStream outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapImage));
        enc.Save(outStream);
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

        return new Bitmap(bitmap);
    }
}
Run Code Online (Sandbox Code Playgroud)

要将位图转换回BitmapImage:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
    IntPtr hBitmap = bitmap.GetHbitmap();
    BitmapImage retval;

    try
    {
        retval = (BitmapImage)Imaging.CreateBitmapSourceFromHBitmap(
                     hBitmap,
                     IntPtr.Zero,
                     Int32Rect.Empty,
                     BitmapSizeOptions.FromEmptyOptions());
    }
    finally
    {
        DeleteObject(hBitmap);
    }

    return retval;
}
Run Code Online (Sandbox Code Playgroud)

  • Bitmap2BitmapImage 函数对我不起作用。我得到 System.InvalidCastException Unable to Cast object of type 'System.Windows.Interop.InteropBitmap' to type 'System.Windows.Media.Imaging.BitmapImage' (6认同)
  • Bitmap2BitmapImage的更简洁的实现是:return Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions()); (3认同)
  • @SaschaHennig:在“ BitmapImage2Bitmap”中:在最后一行中,为什么要“返回新的位图(位图)”而不是仅仅“返回位图”? (2认同)

Law*_*Man 40

这是将Bitmap转换为BitmapImage的扩展方法.

    public static BitmapImage ToBitmapImage(this Bitmap bitmap)
    {
        using (var memory = new MemoryStream())
        {
            bitmap.Save(memory, ImageFormat.Png);
            memory.Position = 0;

            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memory;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
            bitmapImage.Freeze();

            return bitmapImage;
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 在`bitmapImage.EndInit();`之后,调用`bitmapImage.Freeze();`以避免在与GUI的单独线程上完成此操作时出错. (4认同)
  • 与 Imaging.CreateBitmapSourceFromHBitmap 版本相比,MemoryStream 版本慢 10 倍。 (2认同)

小智 9

如果你只需要从BitmapImage转到Bitmap,这很容易,

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
    {
        return new Bitmap(bitmapImage.StreamSource);
    }
Run Code Online (Sandbox Code Playgroud)

  • 也许不会?如果图像有 Uri 源,那么 StreamSource 肯定为 null 吗? (2认同)

小智 5

使用 System.Windows.Interop;...

 private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
        {                
            BitmapSource i = Imaging.CreateBitmapSourceFromHBitmap(
                           bitmap.GetHbitmap(),
                           IntPtr.Zero,
                           Int32Rect.Empty,
                           BitmapSizeOptions.FromEmptyOptions());
            return (BitmapImage)i;
        }
Run Code Online (Sandbox Code Playgroud)

  • 也许我错过了一些东西,但你不能根据弹出的 **InvalidCastException** 将“_System.Windows.Interop.InteropBitmap_”转换为“_System.Windows.Media.Imaging.BitmapImage_” (7认同)
  • @WiiMaxx它确实会抛出异常,但如果您想转换“System.Drawing.Image”以便能够在WPF“Image”控件中显示它,您可以返回“BitmapSource”而不是“BitmapImage”并删除强制转换。那么它就可以完美工作了。 (3认同)