Bitblt in VB.net

snarfblam

Mega-Ultra Chicken
Joined
Jun 10, 2003
Messages
1,832
Location
USA
User Rank
*Expert*
I am drawing images composed of many smaller tiles (using 16px by 16px tiles, 16 tiles wide and 11 tiles high)

I already know about the DrawImage() function, that is what I am using. I have the drawing algorithm down; I just want to replace the DrawImage function for the sake of speed. I would prefer to use the API function Bitblt() because it is much faster.

What I have now is an image control which contains my tiles. I blit these to a panel control to draw my image.

What I need to do is create an offscreen bitmap which will act as a "tile source" to which I can load a bitmap containing all of my tiles. I need to blit these tiles to a second offscreen bitmap, where I construct my image. Then I can persist my image to a panel control (or any control).

I have no idea how to create the offscreen bitmaps. I know there are methods that involve the CreateCompatibleDC() API

If you show me how to do this, or gimme a link to a good, not confusing, tutorial I will be happy. I like to be happy.
 
Last edited by a moderator:
Why not use managed DirectX? Itll be much faster still than GDI and you wont need to interop.
 
Because I dont know directx and it is not worth learning for something so relatively trivial, and it is overkill for something so simple. It seems to me that a lot of programmers are willing to use whatever gets the job done (i.e. drawimage() or directx for my program), but I would like to use the right tool for the job, to get the best performance while using the least resources and minimizing unnecessary work.
 
Using GDI in a GDI+ environment is not the best way to minimize resources since youre translating GDI+ into GDI using more resources.
Code:
Declare Function BitBlt Lib "gdi32.dll" (ByVal hDestDC As Int32, ByVal x As Int32, ByVal y As Int32, _
   ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal hSrcDC As Int32, ByVal xSrc As Int32, _
     ByVal ySrc As Int32, ByVal dwRop As Int32) As Int32
Try www.apiviewer.de, the page is in German but the viewer can run in English(German/English language plugins are included in the download) about half way down the page youll find the download section. It shows APIs in many languages including VB.Net, VB6, C#
 
Last edited by a moderator:
What do you mean translating GDI+ into GDI? I want to use the API to blit from an offscreen bitmap to another offscreen bitmap to an onscreen DC. There is no GDI+ involved in that. None. Just API calls. Just GDI. So there is no translating involved. What do you mean translate from GDI to GDI+? There is no such thing as a GDI+ device context, is there? The GDI and GDI+ dont interface with eachother. My API function calls would go completely around GDI+. Since its windows API it would use very few recources. It is much faster than the VB.net equivalent, and uses less recources than directX. It completely avoids GDI+ and is incredibly simple compared to DirectX.

A VB.net application isnt a GDI+ environment. It uses the .net framework, a GDI+ environment. Thats only if you choose to use the .NET GDI+ functions. I wont be using any .net framework for this, just API. A VB.net panel or form or picturebox still has a WINDOWS device context that can be interacted with through the API. GDI+ is just meant to be an easier and more useful graphical device interface, but is NOT meant to be used for what Im doing. My bitblt calls would use API created bitmaps, which would be GDI object, to a device context, which is a windows thing, not a GDI+ thing. Windows things are exactly what the API is for.

Also, I know the declaration for BitBlt. I have the API viewer that comes with Visual Studio 6. I know how to use the API. Im not stupid. I have some idea as to what Im doing. Im not jumping into some random project thats way over my head and confusing the hell out of me. All I dont know is the exact process for using windows API do what im trying to do.

What Im asking is NOT how to use the API, not api declarations, and not other ways to what I want to do. Again, Im not stupid, I know what I want to do, and have reasons for wanting to do it.

I dont want the overhead of directX. I dont want the slowness of the GDI+ DrawImage(). I want to use GDI alone because it is easier to blit faster. So all I am asking is how to use the windows API to create offscreen bitmaps from which i can blit to eachother and blit to a device context in a form.
 
Last edited by a moderator:
I am sure you will find something if you use google and look it up on the net. I think the Code Project had an article about doing what you are trying to do...
 
Overhead of Directx? Its the fastest and most powerful drawing tool of Windows
VB.Net is a .Net Language therefore a GDI+ Environment, if youre going to use the CreateCompatibleDC API why dont just use VB6 since it has the best support for APIs. A Graphics Class is the GDI+ version of a DC. GDI is being replaced by GDI+. To get info on GDI+ read the articles here: MSDN GDI+ Info
I use WinXP and BitBlt and DrawImage take almost the exact same amount of time(DrawImage usually being slightly faster)
 
Heres a working example I knocked up (replace the bitmap and drawing code with your own, obviously):

Code:
    Offscreen bitmap
    Dim offscreen As New Bitmap("c:\bmp205.bmp")

    Private Declare Function BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As Integer) As Integer
    Private Declare Function CreateCompatibleDC Lib "gdi32" Alias "CreateCompatibleDC" (ByVal hdc As IntPtr) As IntPtr
    Private Declare Function DeleteDC Lib "gdi32" Alias "DeleteDC" (ByVal hdc As IntPtr) As Integer
    Private Declare Function SelectObject Lib "gdi32" Alias "SelectObject" (ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr

    Private Const SRCCOPY As Integer = &HCC0020  (DWORD) dest = source

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Create the target graphics and get an hDC from it
        Dim targetGraphics As Graphics = CreateGraphics()
        Dim targethDC As IntPtr = targetGraphics.GetHdc()

        Create an offscreen dc and select our bitmap in to it
        Dim offscreenhDC As IntPtr = CreateCompatibleDC(targethDC)
        Dim oldObject As IntPtr
        oldObject = SelectObject(offscreenhDC, offscreen.GetHbitmap())

        Blt a load of stuff (icons in this case) from it
        Dim i As Integer
        For i = 0 To 360 Step 24
            BitBlt(targethDC, i, i, 24, 24, offscreenhDC, i, 0, SRCCOPY)
        Next

        Select our bitmap out of the dc and delete it
        SelectObject(offscreenhDC, oldObject)
        DeleteDC(offscreenhDC)

        Release the target hDC
        targetGraphics.ReleaseHdc(targethDC)
        targetGraphics.Dispose()
    End Sub
 
In Divils code you can just use GetDC API and pass it the MyForm.Handle property so you dont need a graphics object
 
OK

First of all, thanks divil.

Second, for direct-x you need to create surfaces and other junk i dont know how to do. Functions are loaded and linked to. Its not a big deal and not alot of overhead. It is more than i want though. It is more comlplicated than i want. I dont know direct-x. Im not learning it when its not even necessary. I dont need the extra speed, i know its fast. I dont need the extra speed. Its a simple two dimensional, relatively small picture.

I know about the getdc api, what i didnt know was, for the fourth time i think, how to how to use createcompatibledc.

I dont want to use vb6 for many reasons. To name a few, winxp styles support and practice using vb.net. Sorry, but thats just a stupid question. Besides that, vb.net has the same support for apis as vb, as far as i can see, besides handles to a controls dc.

I have win xp and a 1.93 ghz processor with 512 megs ddr and the drawimage function, when called 88 times, is much much slower than bitblt called 88 times. Ive tried both. I know. Drawimage is slower. Drawimage is slower. Drawimage is slower. Tried and tested. Ok? Its too slow. Bitblt isnt.

I want to use gdi. It blits faster. I dont want to use gdi+. When vb.net, a .net application, creates a window with a device context, even if it creates a device context through gdi+, it still creates a dc, which isnt gdi+. I would rather work with the device context directly, through the api. A graphics object is not the same as a dc, it is a different way to work with a dc. A window has a dc either way. A graphics object must be created by code during run time with gdi+ to access a dc. They are two different things.

I am using gdi+ right now. Its works, but its slow. Ive used gdi in the past with vb6 on much slower computer, and it was faster.

And im not learning direct-x to draw a simple tile-based image.

I asked a simple question and noone but divil could just answer. Ive given my reasons time after time. You are not helping me by telling me repeatedly that i should do what i do not want to do for reasons ive clearly stated. Like i said before, im not stupid, im not jumping into something new, i know what im doing.

Also, gdi+ isnt replacing gdi. Gdi consists of windows api functions, gdi+ is just another interface. Gdi isnt going away, even if developers stop using it. Its not being replaced. I practically wrote and essay in an earlier post as to why i want to use gdi, and not directx or gdi+.

But thanks Divil.

[edit]Do not use all CAPS. My ears hurt:) [/edit]
 
Last edited by a moderator:
Hmm, I always thought GDI+ was faster, but upon doing some benchmarks, I found that 2000 image draws with BitBlt took 183ms while 2000 images draws with Graphics.DrawImage() took 587ms...

Anyway, I still prefer GDI+, since it can do quite a lot more than GDI32 "out of the box". If I need to do something requiring blazing speed, I will consider GDI32. :P

Also, perhaps for a simple tile game DX would be over kill, but if it elevates into something more, DX will be a great asset to you.
 
Is DrawImageUnscaled a reasonable comparison or does it not do the same thing that Bitblt does. I know that it is much faster than DrawImage.
 
Not much. Ok this explains how a program I have is able to fade 2 images out at the same time very quickly. And it looks great. Whereas when I try to do it with just one image it is very slow!
 
im all calmed now. i just didnt like how everyone was telling me what to do instead of how to it. after my second or third fit though everyone started to become constructive, so thanks
 
VF: Isnt GDI+ just a wrapper of GDI32 API? It would make sense that it would be slower if it was. If its not then that seems to be a bit odd.
 
wyrd: GDI+ is a layer above GDI, not really a wrapper. It allows you to do so much more, its bound to be slower.

GDI+ is an api in itself just like GDI is/was, you can use it from nonmanaged code.
 
I have another question: I dont understand, in divils example, "select our bitmap in to it", or what exactly the SelectObject GDI function does.

Also, in divils example, he creates a dc, draws on it, and disposes of it. I need to draw this on to a contol.
 
Last edited by a moderator:
Back
Top