简体   繁体   English

output Bitmap 在 window (WPF) 中的最佳方法是什么?

[英]What is the best way to output Bitmap in a window (WPF)?

What I want to do:我想做的事:

Given a simple Bitmap (System.Drawing.Bitmap) I am willing to output it to my window in WPF application.给定一个简单的 Bitmap (System.Drawing.Bitmap) 我愿意 output 将它添加到我的 window 应用程序中。 I am also willing to do it frequently, creating a frame stream.我也愿意经常做,创建一个框架stream。

What I've used:我用过的:

Firstly, I've been converting Bitmap to a BitmapImage and then assigning it to Source field of an Image control.首先,我一直在将 Bitmap 转换为 BitmapImage,然后将其分配给 Image 控件的 Source 字段。

The problem with this method is the conversion itself.这种方法的问题在于转换本身。 It's very slow.它很慢。 I haven't found a way that works fast enough, the best one took around 20 ms for a 640x480 Bitmap, which is slow.我还没有找到一种运行速度足够快的方法,对于 640x480 Bitmap,最好的方法大约需要 20 毫秒,这很慢。 I am hoping to find a way that would do this for less than 5 ms for any common resolution or a different approach to the whole problem.我希望找到一种方法可以在不到 5 毫秒的时间内完成任何常见的解决方案或解决整个问题的不同方法。 Perhaps, there is a different control other than Image that would work with pure Bitmap and I wouldn't need to convert.也许,除了 Image 之外,还有一个不同的控件可以与纯 Bitmap 一起使用,我不需要转换。 I am also not tied to using WPF, does UWP or the new WinUI 3 have this problem?我也没有使用 WPF,UWP 或新的 WinUI 3 有这个问题吗? I have checked UWP uses WriteableBitmap, which would also require conversion, but maybe there is a different way as well?我检查了 UWP 使用 WriteableBitmap,这也需要转换,但也许还有不同的方法?

I have found various conversions some of which are slow and some of which just produce a white image as a result for some reason.我发现了各种转换,其中一些很慢,而其中一些由于某种原因只会产生白色图像。 I am providing a list below (I've tried more but I don't remember what exactly):我在下面提供了一个列表(我尝试了更多,但我不记得具体是什么了):

  1. Using the method below.使用下面的方法。 This conversion works but it takes around 20 ms to convert 640x480 ms Bitmap.此转换有效,但转换 640x480 毫秒 Bitmap 大约需要 20 毫秒。

Method ( source ):方法( 来源):

public BitmapImage ToBitmapImage(Bitmap bitmap)
{
    using (MemoryStream memory = new MemoryStream())
    {
        bitmap.Save(memory, ImageFormat.Png);

        memory.Position = 0;

        BitmapImage bitmapImage = new BitmapImage();

        bitmapImage.BeginInit();

        bitmapImage.StreamSource = memory;

        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

        bitmapImage.EndInit();

        bitmapImage.Freeze();

        return bitmapImage;
    }
}
  1. Using Asmak9.EssentialToolKit library ( source ), but that conversion took around 27 ms, so that was not an option.使用 Asmak9.EssentialToolKit 库( source ),但转换大约需要 27 毫秒,所以这不是一个选择。

  2. Using the method below.使用下面的方法。 This one does not work for me for some strange reason.由于某种奇怪的原因,这个对我不起作用。 It runs with no problem, but the result of the conversion is a blank (white) image and not something that was fed into it.它运行没有问题,但转换的结果是一个空白(白色)图像,而不是输入其中的东西。

Method ( source ):方法( 来源):

private BitmapSource Convert(Bitmap bmp)
{
  
  var bitmapData = bmp.LockBits(
    new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
    System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);  
    
  var bitmapSource = BitmapSource.Create(
    bitmapData.Width, bitmapData.Height,
    bitmap.HorizontalResolution, bitmap.VerticalResolution,
    PixelFormats.Bgr24, null,
    bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
     
  bmp.UnlockBits(bitmapData);
  return bitmapSource;
}
  1. Using the method below.This produces the same result as the previous conversion - blank BitmapImage.使用下面的方法。这会产生与之前的转换相同的结果 - 空白 BitmapImage。 I am also not sure what could possibly go wrong here.我也不确定 go 可能在这里出错。

Method ( source ):方法( 来源):

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

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

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

    return retval;
}

Perhaps, the last 2 conversions are better, but they do not convert properly, or I am doing something wrong?也许,最后 2 次转换更好,但它们没有正确转换,或者我做错了什么? Or is there a better way in general to discard the conversion step and display the Bitmap straight?还是有更好的方法来放弃转换步骤并直接显示 Bitmap?

As Clement pointed out above, Method 3 is the fastest, but it requires 2 things:正如 Clement 上面指出的,方法 3 是最快的,但它需要两件事:

  1. Correct pixel format set.正确的像素格式集。
  2. The Convert method should be run in the main thread. Convert 方法应该在主线程中运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM