Sign in to follow this  

Dynamically convert a GDI Bitmap into a Direct2D bitmap

This topic is 680 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone,

 

I recently started with SlimDX to improve the display of dynamic camera images (up to 1920x1200, 40fps).

 

I use VB.NET with Visual Studio 2013 and so far I used a normal Picturebox and grabbing/assigning the camera images to the Picturebox with the help of a background worker.

 

Grabbing the images seems fast enough, but the display/resize of the Picturebox seems to be the bottleneck even in "Fullscreen" or if I start my program multiple times for multi camera display.

 

With now using SlimDX the display performance improved a lot but I think, that I can still enhance it even when "copying" the camera bitmap.

 

My render loop located in a separate thread looks like this:

Imports D2D = SlimDX.Direct2D

....

While AbortDirectXThread = False

	If Not IsNothing(CameraBMP) Then

		'Draw the bitmap
		Dim Direct2DBMP As D2D.Bitmap
		Direct2DBMP = LoadBitmap(CameraBMP)

		m_renderTarget.BeginDraw()
		Try
			m_renderTarget.Clear(New Color4(Me.PictureBox1.BackColor))

			picRect = GetDrawingRectangle(PictureBox1.SizeMode, Direct2DBMP.PixelSize)
                        m_renderTarget.DrawBitmap(Direct2DBMP, picRect)
			Try
				Direct2DBMP.Dispose()
			Catch
			End Try

		Catch ex As Exception

		Finally
			m_renderTarget.EndDraw()
		End Try
	End If

End While

At the moment, I use a function called "LoadBitmap" to convert the camera bitmap "CameraBMP" into a SlimDX.Direct2D.Bitmap:

Public Function LoadBitmap(ByVal drawingBitmap As Bitmap) As D2D.Bitmap
	Dim result As D2D.Bitmap = Nothing

	'Lock the gdi resource
	If Not IsNothing(drawingBitmap) Then
		Dim drawingBitmapData As BitmapData = drawingBitmap.LockBits(New Rectangle(0, 0, drawingBitmap.Width, drawingBitmap.Height), ImageLockMode.[ReadOnly], System.Drawing.Imaging.PixelFormat.Format32bppPArgb)

		'Prepare loading the image from gdi resource
		Dim dataStream As New DataStream(drawingBitmapData.Scan0, drawingBitmapData.Stride * drawingBitmapData.Height, True, False)
		Dim properties As New D2D.BitmapProperties()
		properties.PixelFormat = New D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied)

		'Load the image from the gdi resource
		result = New D2D.Bitmap(m_renderTarget, New Size(drawingBitmap.Width, drawingBitmap.Height), dataStream, drawingBitmapData.Stride, properties)

		'Unlock the gdi resource
		drawingBitmap.UnlockBits(drawingBitmapData)
	End If
	Return result

End Function

So, my main question is:

 

- Is there a faster / better way to convert the GDI bitmap to SlimDX.Direct2D.Bitmap?

 

Best regards.

Share this post


Link to post
Share on other sites
Creating a new d2d bitmap every frame is slow. You should lock it too (after creating it at program startup) and copy the data directly between the image data pointers.

For VB, the Marshal class wraps the necessary memory manipulation functions.

Share this post


Link to post
Share on other sites

Thank you for the quick reply.

 

Unfortunately I am unfamiliar with the Marshal class. Could you please provide an example / solution how to implement this in the above example?

 

Thanks in advance!

Edited by Thaledwyn

Share this post


Link to post
Share on other sites

I don't remember the specifics of the SlimDX D2D bitmap class, but I do know that in the native side, the Bitmap class has a method CopyFromMemory which copies bitmap data from an external pointer to the bitmap instance's memory. It does not reallocate the bitmap, so it is as fast as the memory transfer itself. I believe that SlimDX wraps this functionality.

 

This method works only if the pixel formats (and therefore individual pixels' memory layout) is the same between the source and the destination.

 

Marshal.Copy (which is equivalent to Win32 CopyMemory) would be used if you had two pointers, between of which you would want to copy the stuff. D2D bitmap does not offer the option to explicitly lock the memory, unlike I remembered. 

Edited by Nik02

Share this post


Link to post
Share on other sites

Thank you for the hint.

 

I got it working somehow with .FromMemory of SlimDX.Direct2D.Bitmap.

 

The CPU load went down abot 5-8% but suprisingly the FPS dropped from 214 to 96 FPS.

Share this post


Link to post
Share on other sites
I recommend profiling the code to see where your performance bottleneck is.

If the re-allocation of the bitmap is really faster than just the copying (which seems counterintuitive but might be true), then by all means you should keep doing that. Just keep in mind that reallocation taxes the OS as a whole, and at some point it will likely cause severe performance fluctuations.

Share this post


Link to post
Share on other sites
Do note that now that you do the memory copy instead of the reallocation, the copy has to wait while the image is actually drawn by the GPU. It is not actually a problem, the copy is just limited by your system's (monitor's) performance.

Most display devices can't do near 240Hz. Some do, though.

Share this post


Link to post
Share on other sites

This topic is 680 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this