Fast Converting Bitmap to Bitmapsource Wpf

fast converting Bitmap to BitmapSource wpf

Here is a method that (to my experience) is at least four times faster than CreateBitmapSourceFromHBitmap.

It requires that you set the correct PixelFormat of the resulting BitmapSource.

public static BitmapSource Convert(System.Drawing.Bitmap bitmap)
{
var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

var bitmapSource = BitmapSource.Create(
bitmapData.Width, bitmapData.Height,
bitmap.HorizontalResolution, bitmap.VerticalResolution,
PixelFormats.Bgr24, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);

bitmap.UnlockBits(bitmapData);

return bitmapSource;
}

Is there a good way to convert between BitmapSource and Bitmap?

It is possible to do without using unsafe code by using Bitmap.LockBits and copy the pixels from the BitmapSource straight to the 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;
}

Fast conversion of Bitmap to ImageSource

Try converting it to a BitmapImage first:

public BitmapImage ConvertBitmap(System.Drawing.Bitmap bitmap)
{
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();

return image;
}

Then:

public void MyMethod(System.Drawing.Bitmap myBitmap)
{
var myImage = new Image();
myImage.Source = ConvertBitmap(myBitmap);
}

You didn't explain where the Bitmap was coming from so I had to leave that part out.

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

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.

Faster way to convert BitmapSource to BitmapImage

The conversion isn't necessary at all. Change the type of your VideoImage property to ImageSource or BitmapSource. Now you directly pass it as parameter to DrawImage:

this.VideoImage = bitmapsource;
drawingContext.DrawImage(this.VideoImage, new Rect(0, 0, imageWidth, imageHeight));

Constant garbage collection from converting Bitmap to BitmapImage

Instead of creating a new BitmapImage for each frame, you should use a WriteableBitmap that is once assigned to the Source property of an Image element.

int frameWidth = ...
int frameHeight = ...
var pixelFormat = PixelFormats.Bgr24; // must match Bitmap.PixelFormat

var writeableBitmap = new WriteableBitmap(
frameWidth, frameHeight, 96, 96, pixelFormat, null);

image.Source = writeableBitmap;

You would then cyclically update the WriteableBitmap (and hence also the Image element) from a Bitmap like this:

Bitmap bitmap = ... // a frame

var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

image.Dispatcher.Invoke(() => writeableBitmap.WritePixels(
new Int32Rect(0, 0, bitmap.Width, bitmap.Height),
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride));

bitmap.UnlockBits(bitmapData);

C# Convert BitMap into BitmapImage from Properties.Resources

I have now found a way to convert the Bitmap to bitmapSource / bitmapimage. It's a slightly different version than the versions of the Stackoverflow thread I linked in the OP:

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

try
{
retval = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

return retval;
}

This returns a BitmapSource Object, which can be used to display an Image in the WPF image Element



Related Topics



Leave a reply



Submit