Leaders snarfblam Posted June 16, 2003 Leaders Posted June 16, 2003 (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 June 16, 2003 by snarfblam Quote [sIGPIC]e[/sIGPIC]
*Gurus* divil Posted June 16, 2003 *Gurus* Posted June 16, 2003 Why not use managed DirectX? It'll be much faster still than GDI and you won't need to interop. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
Leaders snarfblam Posted June 16, 2003 Author Leaders Posted June 16, 2003 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. Quote [sIGPIC]e[/sIGPIC]
AndreRyan Posted June 17, 2003 Posted June 17, 2003 (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 June 17, 2003 by AndreRyan Quote .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 snarfblam Posted June 18, 2003 Author Leaders Posted June 18, 2003 (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 June 18, 2003 by snarfblam Quote [sIGPIC]e[/sIGPIC]
aewarnick Posted June 18, 2003 Posted June 18, 2003 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... Quote C#
AndreRyan Posted June 18, 2003 Posted June 18, 2003 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) Quote .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* divil Posted June 18, 2003 *Gurus* Posted June 18, 2003 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 Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
AndreRyan Posted June 21, 2003 Posted June 21, 2003 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 Quote .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 snarfblam Posted June 24, 2003 Author Leaders Posted June 24, 2003 (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 June 24, 2003 by Robby Quote [sIGPIC]e[/sIGPIC]
*Experts* Volte Posted June 24, 2003 *Experts* Posted June 24, 2003 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. Quote
aewarnick Posted June 24, 2003 Posted June 24, 2003 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. Quote C#
*Experts* Volte Posted June 24, 2003 *Experts* Posted June 24, 2003 DrawImageUnscaled took about 21ms less time than DrawImage. :-\ Quote
aewarnick Posted June 24, 2003 Posted June 24, 2003 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! Quote C#
*Gurus* divil Posted June 25, 2003 *Gurus* Posted June 25, 2003 Calm down marble_eater, we're all friends here. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
Leaders snarfblam Posted June 29, 2003 Author Leaders Posted June 29, 2003 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 Quote [sIGPIC]e[/sIGPIC]
wyrd Posted June 30, 2003 Posted June 30, 2003 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. Quote Gamer extraordinaire. Programmer wannabe.
RazerWriter Posted June 30, 2003 Posted June 30, 2003 How can I bitblt onto a picturebox with that code? Is it possible? Quote
*Gurus* divil Posted June 30, 2003 *Gurus* Posted June 30, 2003 wyrd: GDI+ is a layer above GDI, not really a wrapper. It allows you to do so much more, it's bound to be slower. GDI+ is an api in itself just like GDI is/was, you can use it from nonmanaged code. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
Leaders snarfblam Posted July 1, 2003 Author Leaders Posted July 1, 2003 (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 July 1, 2003 by snarfblam Quote [sIGPIC]e[/sIGPIC]
*Gurus* divil Posted July 1, 2003 *Gurus* Posted July 1, 2003 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. Quote 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* Volte Posted July 1, 2003 *Experts* Posted July 1, 2003 (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 July 1, 2003 by Volte Quote
aewarnick Posted July 2, 2003 Posted July 2, 2003 Ok, it looks like VF's method would be faster...Correct? Quote C#
*Gurus* divil Posted July 3, 2003 *Gurus* Posted July 3, 2003 Personally I wouldn't deviate from the recommended way. Especially when VolteFace says you should :P Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
Recommended Posts