User | Post |
HyperLamer
Posts: 3291/8210 |
Shoot, no wonder they kept lagging those old school computers. |
Parasyte
Posts: 299/514 |
Yes, it is necessary. You must select the old object back into the device context during the cleanup phase. And no, XP doesn't do much GDI cleaning up. You're creating memory leaks. ;D
To clean up Disch's code, you would use something like this:
SelectObject(mDC,oldbmp); DeleteObject(bmp); DeleteDC(mDC);
[I didn't notice that Disch included clean up code in his post. Oh well, doesn't hurt to post again.] |
HyperLamer
Posts: 3274/8210 |
Awesome... Though I notice he saves the value from SelectObject and does stuff with it at the end. Is that necessary? My programs seem to have been working fine without it, but that might just be XP cleaning it up for me. |
Parasyte
Posts: 297/514 |
Use CreateCompatibleDC(), CreateDIBSection(), and SelectObject(), as in Disch's example. |
HyperLamer
Posts: 3256/8210 |
Oooooooooh... Do I have to do something special when creating the bitmap though, or can I just use CreateCompatibleBitmap() and CreateDC() like I usually do? |
Parasyte
Posts: 292/514 |
Yes. The pointer points directly to the actual bitmap data. |
HyperLamer
Posts: 3234/8210 |
So when you modify the array, you're actually modifying the image? That's probably the problem. I did it in VB, so without pointers I had to copy the image to an array and back which was very confusing. |
Dish
Posts: 279/596 |
Originally posted by Exim yes, I'm using MFC. Creating all the windows, buttons, textfields, input, messagehandling my own would drive me crazy I think... never got far beyond creating a window and draw stuff in it with the mouse. I bet when I'd like to add buttons I'd use mfc-objects.
It's not as hard as you'd think. Dialogs and stuff are pretty much automated by the API. There's only like 4 things you have to do differently when making dialogs straight in the WinAPI than you'd do when working in MFC.
But I'm just talking. If you're more comfortable with MFC, it's alright to stick with it... just try to break from it eventually.
Originally posted by HyperHacker Ugh. I tried to use DIB sections once, damn near drove me nuts. WTF is this scanline crap anyway?
*shrug*
The code I gave in that other post pretty much takes care of all of it. All you have to do from there is treat "pixels" as a big array of pixels =P. Writes to it will change the image directly. Don't see what's so complicated about that. |
HyperLamer
Posts: 3209/8210 |
Ugh. I tried to use DIB sections once, damn near drove me nuts. WTF is this scanline crap anyway? |
Exim
Posts: 7/10 |
Thanks a lot. Hopefully I'll be able to get the job done with this.
yes, I'm using MFC. Creating all the windows, buttons, textfields, input, messagehandling my own would drive me crazy I think... never got far beyond creating a window and draw stuff in it with the mouse. I bet when I'd like to add buttons I'd use mfc-objects. |
Dish
Posts: 278/596 |
That works?
Haw |
FuSoYa
Posts: 147/255 |
Originally posted by Disch One funky side effect to take note of is that Windows bitmaps are stored upside-down... so 'pixels' actually points to the last row in the bitmap followed by the second last, etc... not the first followed by the second like you'd might expect.
Or you can just make the height value negative if you don't like working with upside-down images.
|
Dish
Posts: 277/596 |
I'm not really familiar with CImage (are you using MFC?)
Anyway... the HBITMAP handle is just that: a handle to the bitmap. It's the non-MFC equivilent of a CBitmap. You get the pointer to the bitmap data through one of the parameters you pass to the function.
Here's some sample code to help explain.
HDC mDC; HBITMAP bmp, oldbmp;
BITMAPINFO bi; memset(&bi,0,sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biHeight = 240; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biWidth = 256; void* pixels;
mDC = CreateCompatibleDC(NULL); if(!mDC) { //error getting offscreen DC }
bmp = CreateDIBSection(mDC,&bi,DIB_RGB_COLORS,&pixels,NULL,NULL); if(!bmp) { //error creating offscreen bitmap }
oldbmp = (HBITMAP)SelectObject(mDC,bmp);
This example makes a bitmap 256x240 pixels and puts it in an offscreen DC. You can write directly to the pixels as though it were a big array through the "pixels" pointer in this example. One funky side effect to take note of is that Windows bitmaps are stored upside-down... so 'pixels' actually points to the last row in the bitmap followed by the second last, etc... not the first followed by the second like you'd might expect.
Once you change your pixels and stuff you can do ordinary BitBlt()s with mDC as your source to blit the image to another surface (or to the display)
Once you're done with everything, you need to do cleanup:
SelectObject(mDC,oldbmp); DeleteObject(bmp); DeleteDC(mDC);
|
Exim
Posts: 6/10 |
what's about GetPixelAddress (availible in CImage) ? Or do I have to care about the pitch? CreateDIBSection returns a bitmaphandle (HBITMAP) ...?? or does this handle act like a pointer? |
Dish
Posts: 276/596 |
I second that. CreateDIBSection all the way.
If for some reason you can't use it.... SetDIBits is the next best thing. SetPixel is so far beyond slow it's practically useless. |
Parasyte
Posts: 286/514 |
Stay away from SetPixel. If you're going to draw many pixels at a time, it's better to use CreateDIBSection, which will create a bitmap that returns a pointer to the bitmap data in memory. Using that pointer, you can read and write the bitmap data directly. It gets rid of so much overhead that you would have to deal with when using SetPixel. (IE hundreds of times faster than SetPixel.) |
HyperLamer
Posts: 3177/8210 |
You need to know how to use GDI functions such as BitBlt and SetPixel. What you generally want to do is read the palettes and graphic data, and draw each pixel on a buffer based on the palette data. (Convert the palettes to BGR (RGB backward) and stick them in an array, and use the individual pixel data as the index.) Then you just copy 8x8 squares from the tile buffer onto one main buffer, stretching if necessary (use StretchBlt) and copy that onto the window's DC. (You could copy directly to the DC from the tile buffer, but you'll get flicker.) For sprites or BG layers with transparent colours, set the transparent colour's palette entry to something that won't be used in the game's palette data, and use TransparentBlt specifying that colour as the transparent colour. (TransparentBlt can also stretch the image. Tip: Since most systems use 15-bit colour or an index to a palette hard-coded into the system, the number of possible RGB colours is quite limited. For example, 15-bit colour will always translate to multiples of 8 for the red, green and blue values, so use something that isn't a multiple of 8 as your transparent colour and it's guaranteed not to conflict with the palettes. ) |
Exim
Posts: 5/10 |
I prefer C++, but I'm able to read/write VB, C-derivates, Delphi and Eiffel. |
dan
Posts: 411/782 |
What programming language are you using? |
Exim
Posts: 4/10 |
is there some source-code out there to read and display graphics from a rom file? I don't really feel like reading through hardware and emulation docs. |
This is a long thread. Click here to view it. |