Jump to content
Xtreme .Net Talk

Recommended Posts

  • Leaders
Posted (edited)

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.

Edited by snarfblam
[sIGPIC]e[/sIGPIC]
  • Leaders
Posted
Because I don't 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.
[sIGPIC]e[/sIGPIC]
Posted (edited)

Using GDI in a GDI+ environment is not the best way to minimize resources since you're translating GDI+ into GDI using more resources.

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 http://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 you'll find the download section. It shows APIs in many languages including VB.Net, VB6, C#

Edited by AndreRyan
.Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
  • Leaders
Posted (edited)

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+ don't interface with eachother. My API function calls would go completely around GDI+. Since it's 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 isn't a GDI+ environment. It uses the .net framework, a GDI+ environment. That's only if you choose to use the .NET GDI+ functions. I won't 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 I'm 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. I'm not stupid. I have some idea as to what I'm doing. I'm not jumping into some random project thats way over my head and confusing the hell out of me. All I don't know is the exact process for using windows API do what i'm trying to do.

 

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

 

I don't want the overhead of directX. I don't 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.

Edited by snarfblam
[sIGPIC]e[/sIGPIC]
Posted

Overhead of Directx? It's the fastest and most powerful drawing tool of Windows

VB.Net is a .Net Language therefore a GDI+ Environment, if you're going to use the CreateCompatibleDC API why don't 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)

.Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
  • *Gurus*
Posted

Here's a working example I knocked up (replace the bitmap and drawing code with your own, obviously):

 

   '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

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Posted
In Divil's code you can just use GetDC API and pass it the MyForm.Handle property so you don't need a graphics object
.Net allows software to be written for any version of Windows and not break like Unmanaged applications unless using Unmanaged procedures like APIs. If your program uses large amounts of memory but releases it when something else needs it, then what's the problem?
  • Leaders
Posted (edited)

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. I'm 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 control's 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. I've 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]

Edited by Robby
[sIGPIC]e[/sIGPIC]
  • *Experts*
Posted

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.

Posted
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!
C#
  • Leaders
Posted
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
[sIGPIC]e[/sIGPIC]
Posted
VF: Isn't GDI+ just a wrapper of GDI32 API? It would make sense that it would be slower if it was. If it's not then that seems to be a bit odd.
Gamer extraordinaire. Programmer wannabe.
  • Leaders
Posted (edited)

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.

Edited by snarfblam
[sIGPIC]e[/sIGPIC]
  • *Gurus*
Posted
Before you use GDI objects on a dc, you have to select them in to it. If you want to use a pen, bitmap, brush or whatever, you select them in to the device context with SelectObject. That api returns a handle to the last object, which you should always restore when you're done using SelectObject again.

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

  • *Experts*
Posted (edited)
If you are using SelectObject() on a DC that you have created yourself that you'll delete at the end of the sub, and don't plan on using the previously selected object any more, it is safe to delete it.
DeleteObject(SelectObject(hDc, hGdiObject))

Edited by Volte
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...