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:
- Correct pixel format set.
- 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
Write a Well Designed Async/Non-Async API
When Is a Static Constructor Called in C#
Two Different Dll with Same Namespace
Regular Expression to Remove HTML Tags
Transparent Background Image for Form - Smooth Edge Shape for the Form
Gradient Circles for Map Generator
Oledbcommand Parameters Order and Priority
Adding Multiple Parameterized Variables to a Database in C#
What Are the True Benefits of Expandoobject
Get Mime Type from Filename Extension
Most Efficient Way to Remove Special Characters from String
General Purpose Fromevent Method
Is a Memory Leak Created If a Memorystream in .Net Is Not Closed
Pass Table Valued Parameter Using Ado.Net
Why Can't I Unbox an Int as a Decimal