简体   繁体   中英

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. I am also willing to do it frequently, creating a frame 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.

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. 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. Perhaps, there is a different control other than Image that would work with pure Bitmap and I wouldn't need to convert. I am also not tied to using WPF, does UWP or the new WinUI 3 have this problem? I have checked UWP uses WriteableBitmap, which would also require conversion, but maybe there is a different way as well?

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.

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.

  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. I am also not sure what could possibly go wrong here.

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? Or is there a better way in general to discard the conversion step and display the Bitmap straight?

As Clement pointed out above, Method 3 is the fastest, but it requires 2 things:

  1. Correct pixel format set.
  2. The Convert method should be run in the main thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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