Archived

This topic is now archived and is closed to further replies.

giant

Bitmaps using DirectX

Recommended Posts

giant    205
Hi. I am trying to load and display bitmaps using DirectX. I am loading the bitmap ok, and creating the surface, but when I try and display it, if is all messed up. The resolution I am using is 640 x 480, and if I load a bitmap of this size and create a surface the smae size, that bitmap is displayed correctly, however if I try and display a bitmap of a smaller size, (the one I am trying to use is 81x122) it loads and creates the surface fine, but it is displayed to the screen as a pile of garbage. Any ideas? Giant "Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
giant    205
Hi
I am using Code taken from "The Tricks of the Windows Programming Guru''s". The bitmap has 256 colours.

I am using DirectX 7, so I dount know if that will be available to use.

I just dont understand why, it works for full screen bitmaps but not for smaller ones.

"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
TheFez    151
The problem is that the file your using does not have a width which is a power of four. What happens is that when a program saves a bitmap it saves each line and wants it to be a power of four. Since yours is just 81 in width it pads it to 84 with 0s. Your best bet is to load the bitmap normally, find out the next multiple of 4 (in this case 84), and create two surfaces. The first surface will have the new width of 84, the second will have the old width of 81. First copy the bitmap to the first surface using the width of 84. Second blit the first surface to the second (make sure you bound the first surface to the correct width of 81). Then your done.

Share this post


Link to post
Share on other sites
giant    205
Hi.
Thanks for the info. Do you mean a multiple of 4 or a power of 4? There is a huge difference. I cannot imagine it being a power of 4, cause then there would only be a few size bitmaps that you would be able to load.

Again, thanks for the info.

Giant

"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
CaptainJester    523
Your bitmap does not have to be a multiple of 4. I have loaded a bitmap that was 310 x 50 and neither dimension is a multtiple of 4 and I have no problems. If you are using LaMothes code to load the bitmaps, I find that his stuff is more complpex than it needs to be. Try using the DDUtil.cpp that comes with DirectX. It is much easier to use. You just give it the file name and it loads the bitmap and returns an OFFSCREEN_PLAIN surface containing your bitmap that you can easily blit to the back buffer.

PS. I thought that that book was great, except I never use his libs, I find they are more cryptic and complex than needed.


---
Make it work.
Make it right.
Make it fast.

Share this post


Link to post
Share on other sites
crazemanx    128
Direct3D likes powers of 2, but DirectDraw (which i think giant is using) doesn''t mind.
However, .BMP format images are stored with lines padded to multiples of 4 bytes. LaMothe doesnt seem to take any note of this in his book (not that i could see). Think about these bytes when maniuplating the buffer containing the image, and strip them out when copying to the surface.

Share this post


Link to post
Share on other sites
BASSOFeeSH    122
Let me try to simplify what they are saying:

LaMothe''s code works, but this bitmap loading function only works on bitmaps that have dimenions that are a power of(2 or 4).

I suppose you could stick with those kinds of bitmaps or fix his function.

Another option is to use a better function like those listed above.

^^^^^^^^^^^^^^^^^^^^^^^^^
Wait, wait, wait....who''s Nambla Fett?

Share this post


Link to post
Share on other sites
giant    205
Thanks Everyone for you help.

I have never heard of DDUtil.cpp but will try and use it. What function calls do I use to achive what you were saying about off screen plains.

Thanks
Giant

"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
TheFez    151
Jester, if your loading bitmaps using ddutil thats why you''ve never run into problems, it handles all of that for you. Try loading a 78 by 90 file with your own loader (make sure you make the bitmap in paint that way you know its going to be padded. :-) ). Its fun to watch what comes out onto the screen (took me forever to figure out why it was doing it though). Anyway, giant try looking here http://www.gamedev.net/reference/articles/article1078.asp its a pretty good tutorial as to how to use ddutil. (also I meant multiple, not power. :-) )

Share this post


Link to post
Share on other sites
CaptainJester    523
quote:
Original post by TheFez
Jester, if your loading bitmaps using ddutil thats why you''ve never run into problems, it handles all of that for you.



Thanks Fez.




---
Make it work.
Make it right.
Make it fast.

Share this post


Link to post
Share on other sites
gandolf1212    100
I agree w/ using Ddutil. I got the same Guru''s book and lamoths bitmaps loader was extreamly complex. Ddutil works alot better and is what i''m using in my game right now. Microsoft doesn''t put this in the direct draw include files though because they didn''t want to, or couldn''t figure out how, or somthing like that...

The good news is if you have Guru''s you already have Ddutil! Go to "R:\DirectX\DirectXSDK\SAMPLES\MULTIMEDIA\DDRAW\INCLUDE" and take a copy of the Ddutil.cpp and Ddutil.h files. Also, R is suposed to be your CD (hopefully you figured that out).

Share this post


Link to post
Share on other sites
giant    205
Gentlemen
Thanks a lot for all your help. I had ddutil.cpp and .h on my PC, so I copied them and placed them in the project folder and added them to the file place of the project. (whatever you call it. workspace or something)
God must hate me or something cause despite all your help I can''t get it to work. I hate putting code on messageboards cause it is so anoying to read, but here are my init function and game function. Real basic, but could you please spot where it is wrong, cause I am at a loss.


#include // include directdraw
#include "ddutil.h"


...
...
...

LPDIRECTDRAW4 lpdd = NULL; // dd4 object
LPDIRECTDRAWSURFACE4 lpddsprimary = NULL; // dd primarysurface
LPDIRECTDRAWSURFACE4 lpddsback = NULL; // dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; LPDIRECTDRAWSURFACE4 lpddspaddle = NULL;// this will hold the paddle image

...
...
...

int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here

LPDIRECTDRAW lpdd_temp;

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreate(NULL, &lpdd_temp, NULL)))
return(0);

// now query for IDirectDraw4
if (FAILED(lpdd_temp->QueryInterface(IID_IDirectDraw4,(LPVOID *)&lpdd)))
return(0);

// set cooperation to full screen
if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
return(0);

// set display mode to 640x480x8
if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
return(0);

// we need a complex surface system with a primary and backbuffer

// clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd);

// enable valid fields
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

// set the backbuffer count field to 1, use 2 for triple buffering
ddsd.dwBackBufferCount = 1;

// request a complex, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;

// create the primary surface
if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return(0);

// now query for attached surface from the primary surface

// this line is needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

// get the attached back buffer surface
if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
return(0);

// build up the palette data array
for (int color=1; color < 255; color++)
{
// fill with random RGB values
palette[color].peRed = rand()%256;
palette[color].peGreen = rand()%256;
palette[color].peBlue = rand()%256;

// set flags field to PC_NOCOLLAPSE
palette[color].peFlags = PC_NOCOLLAPSE;
} // end for color

// now fill in entry 0 and 255 with black and white
palette[0].peRed = 0;
palette[0].peGreen = 0;
palette[0].peBlue = 0;
palette[0].peFlags = PC_NOCOLLAPSE;

palette[255].peRed = 255;
palette[255].peGreen = 255;
palette[255].peBlue = 255;
palette[255].peFlags = PC_NOCOLLAPSE;

// create the palette object
if (FAILED(lpdd->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256 |
DDPCAPS_INITIALIZE,
palette,&lpddpal, NULL)))
return(0);

// finally attach the palette to the primary surface
if (FAILED(lpddsprimary->SetPalette(lpddpal)))
return(0);

// set clipper up on back buffer since that''s where well clip
RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);

// clean the surfaces
DDraw_Fill_Surface(lpddsprimary,0);
DDraw_Fill_Surface(lpddsback,0);

// Load the bitmap
if(( lpddspaddle = DDLoadBitmap (lpdd, "paddle.bmp", 0, 0 ))==NULL)
return -1;

// seed random number generator
srand(GetTickCount());

// return success or failure or your own return code here
return(1);

} // end Game_Init



int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here

// lookup for proper walking sequence
static int animation_seq[4] = {0,1,0,2};

//int index; // general looping variable

// make sure this isn''t executed again
if (window_closed)
return(0);

// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
{
PostMessage(main_window_handle,WM_CLOSE,0,0);
window_closed = 1;
} // end if

RECT rcFrom;
rcFrom.left = 0;
rcFrom.top = 0;
rcFrom.right = 100;
rcFrom.bottom = 100;

//
if (FAILED( lpddsback->BltFast( 0,0, lpddspaddle, &rcFrom, DDBLTFAST_WAIT )))
return -1;

// flip pages
while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));

// wait a sec
Sleep(30);

// return success or failure or your own return code here
return(1);

} // end Game_Main

Thanks
Giant


"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
giant    205
THanks Man!!
Are you tlking about the lpddspaddle surface. Lock it before I load the bitmap then unlock it after.
Giant

"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
CaptainJester    523
No, you do not have to lock the surface to load a bitmap. You do have to use the right interface. I don''t know what version of DirectX SDK you have installed, but if it is verson 7, DDUtil functions to load a bitmap will return a pointer to LPDIRECTDRAWSURFACE7. Everything else looks OK. Just check the DDUtil.h file and see what LoadBitmap returns.

---
Make it work.
Make it right.
Make it fast.

Share this post


Link to post
Share on other sites
giant    205
Hi.
I''m starting to get confused again. What do you mean by "You do have to use the right interface. "?

I will never get this crap working!!!

"Only two things are infinite, the universe and human stupidity, and I''m not sure about the former." --Albert Einstein

Share this post


Link to post
Share on other sites
CaptainJester    523
As newer versions of DirectX came out, new interfaces were developed. The old ones are still accessable, but it is always recommended to use the new ones. So in the case of LaMothe''s book, he wrote it using DirectX v6. So to get the most up to date interface, he creates a LPDIRECTDRAW interface and then queries for an LPDREICTDRAW4 interface. This is the part of the code that you used:

LPDIRECTDRAW4 lpdd = NULL; // dd4 object

...
...
...

LPDIRECTDRAW lpdd_temp;

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreate(NULL, &lpdd_temp, NULL)))
return(0);

// now query for IDirectDraw4
if (FAILED(lpdd_temp->QueryInterface(IID_IDirectDraw4,(LPVOID *)&lpdd)))
return(0);

Now when you use the LPDIRECTDRAW4 interface, you have to use the LPDIRECTDRAWSURFACE4 for surfaces. If you downloaded the DirectX 7 or 8 SDK from microsoft, the DDUtil function LoadBitmap returns a surface that is an LPDIRECTDRAWSURFACE7, which is not the same, so it just doesn''t work.

---
Make it work.
Make it right.
Make it fast.

Share this post


Link to post
Share on other sites
Anthracks    122
When you say they look strange when you display they, I *might* be able to help. I had a heck of a time coding a bitmap loader myself earlier this year (I also used LaMothe's book for reference) and got help from these boards. The problem, it turned out, is that the .bmp format for some reason requires images to have a width that is a multiple of 4. If it is not, it adds enough 0's to the end of each row of the image to make it that wide.

So, if you had a picture that was 50 pixels wide, for example, there would be two additional bytes of 0 at the end of each line, to bump it up to 52 pixels wide (52 = 13 * 4 so it's a multiple of 4). If you ignore this fact, sometimes you will end up reading in these 0's instead of the real image data, which causes your image to look really weird .

To get around it, do something like this:

    
char junk[3]; // Temporary variable to hold the 0's


if(imageWidth%4!=0)
{
read(junk,imageWidth%4);
}


I don't know how much C++ you know, so I'm sorry if this seems basic. In the above, basically it checks if the image is a multiple of 4 pixels wide (you can get the width from the image header), and if it is, does nothing. If it is not, however, it reads in all the extra 0's. That is what the width%4 does, calculate how many 0's the width needs to be a multiple of 4.

Add this feature to your code, and it might not look messed up anymore! Hope that helps,

Anthracks

EDIT: Fixed a stupid typo.

Edited by - Anthracks on December 13, 2001 9:14:11 PM

Share this post


Link to post
Share on other sites
giant    205
Hi CaptainJester!

What types will I use to make it work?
I do not fully understand this crap.

Do you have a code example or anything that might explain it to me.

Giant

"Only two things are infinite, the universe and human stupidity, and I'm not sure about the former." --Albert Einstein

Edited by - giant on December 14, 2001 6:18:33 AM

Share this post


Link to post
Share on other sites