Jump to content
  • Advertisement
Sign in to follow this  
mercurium

Bitmaps In DirectDraw7

This topic is 4840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everybody, I've been trying to figure out how to draw a simple bitmap to the screen, but the function that I created is only half-working. Here's the function:
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

void ShowBitmap() {
	int lpitch = (int)lpdds_desc.lPitch >> 2;
	int k = 0;
	UCHAR red, green, blue;

	for (int i = 0; i < bitmap.infoHeader.biHeight; i++ ) {
		for (int j = 0; j < bitmap.infoHeader.biWidth; j++, k+=3 ) {
			blue = bitmap.buffer[k];
			green = bitmap.buffer[k+1];
			red = bitmap.buffer[k+2];
			scrRef[j + i * lpitch] = _RGB32BIT(0, red, green, blue);
		}
	}
}



and here's the struct that I am using, from Tricks Of The Windows Game Programming Guru's:
typedef struct BMP_FILE_TAG
{
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	PALETTEENTRY palette[256];
	unsigned char *buffer;

}	BMP_FILE, *BMP_FILE_PTR;



When I try to load this picture: It displays it like this: Am I missing some terribly important detail? Thanks in advance for your help. [edit: ok, I'm having trouble showing these images, but the first is just a black box centered on a white background and the second one looks like a trapazoid]

Share this post


Link to post
Share on other sites
Advertisement
Looking over your function, it seems you are doing a lot of work for something that DirectX can do for you. Why don't you make an offscreen surface and load a bitmap to it? Then you can just call the Blt function to draw the image without haveing to worry about the buffer or pitch. Also, DirectX surfaces will also manage clipping, too, if you attach a clipper to them.

If you need help on setting up DirectX Surfaces, I can also post information on creating the surfaces, attaching bitmaps, and rendering the surfaces to the screen.

Share this post


Link to post
Share on other sites
I'm pretty familiar with surfaces (well, relatively speaking), I just didn't know you could attatch bitmaps directly to them. After posting that I found this handy library online (ddutil.h) from Microsoft that loads and attatches bitmaps to surfaces for you. I'll post any more questions as they arise (I'm sure I'll have plenty). Thanks! [grin]

[Edited by - mercurium on August 13, 2005 10:32:27 PM]

Share this post


Link to post
Share on other sites
hey mercurium,

I wasn't able to see your images...but from your description, it looks like you forgot to account for the Zero padding that is common in BMPs. Just to make sure that this is the problem, please edit your image so its exactly a mutliple of 4( eg. if your image is 321x201 then use an image edit program to crop it so its 320x201) and then run your program again.

If this is the problem then what i have to say my help you out.Bmps like to align themselves so that their width is a multiple of four.
for example:
1) If width = 401,
- 401 is not multiple of 4...
- but the next nearest multiple is 404,
- So 3 bytes are automatically to make it a
multiple of 4
- These bytes have a value of 0 and they are
called "Zero padding".
- So you need to move over the zeropadding( dont draw them, because they arent part of the image)

2) If width = 402,
- The zero padding would consist of 2 bytes.

I've modified your code to include the zero padding correction.
Please See if this helps:

int ZeroPadCount=0;
int remainder = bitmap.infoHeader.biHeight % 4;
if(remainder>0)
{
ZeroPadCount = 4-remainder;
}
for (int i = 0; i < bitmap.infoHeader.biHeight; i++ )
{
for (int j = 0; j < bitmap.infoHeader.biWidth; j++, k+=3 )
{
blue = bitmap.buffer[k];
green = bitmap.buffer[k+1];
red = bitmap.buffer[k+2];
scrRef[j + i * lpitch] = _RGB32BIT(0, red, green,blue);
}
k+=ZeroPadCount; //Moving over ZeroPad
}
[\source]

I hope this helped.

v-EktOr-->


Share this post


Link to post
Share on other sites
Thanks, worked like a charm! You guys rock ! [grin]

Yeah, appearently Andre Lamothe left out that seemingly important detail when he went over bitmaps in his book. That, or I just glanced over it.

Share this post


Link to post
Share on other sites
One more tip: For better efficiency in you bitmap, don't access the bitmap using arrays and multiplication. That will slow your function down quite a bit, when instead, all you have to do is use some precomputed variables (such as pointers) and only need addition:
//NOTE!!!: I haven't tested this function, but I've done one similar to it! Be sure to TEST THIS!!!
void ShowBitmap(long x, long y) {
//Be sure you check for limits also!
//NOTE: This doesn't take into account flipped lines!!! (if biHeight < 0)
//srcDepth - Depth of the bitmap in bytes (3 for 24-bit, 4 for 32-bit)
ULONG srcWidth=bitmap.infoHeader.biWidth;
ULONG srcHeight=bitmap.infoHeader.biHeight;
ULONG srcPitch=(ULONG)srcWidth*srcDepth;
if (srcPitch%4!=0) srcPitch=srcPitch/4*4+4; //Align width DWORD
//Can't do all of the calc's yet
//destDepth - Depth of DDSurface in bytes
ULONG destWidth=[DDSurface Width], destHeight=[DDSurface Height];
ULONG destPitch=(ULONG)lpdds_desc.lPitch >> 2; //What you had for "lpitch"
//Calculate the actual set of coordinates to be blitted
RECT rectOut={x,y,x+srcWidth,y+srcHeight},
rectDest={0,0,destWidth,destHeight};
LimitRect(&rectOut,&rectDest); //Limit the rectangles
//Calculate data positions (pointers)
//Calculating it here allows the image to be 'cut off' if it is out of bounds
BYTE *srcChr=bitmap.buffer+(rectOut.left-x)+((rectOut.top-y)*srcPitch);
BYTE *destChr=(BYTE*)srcRef+rectOut.left+(rectOut.top*destPitch);
//Calculate line offsets
//How many bytes to skip to get to the next line
//Be sure to factor out a pixel! (Since it is added at the end of each pixel copying)
USHORT srcLine=srcPitch-((rectOut.right-rectOut.left-1)*srcDepth);
USHORT destLine=destPitch-((rectOut.right-destWidth-1)*destDepth);
//Now start the blittage!
for (USHORT b=rectOut.top;b<rectOut.bottom;b++) {
for (USHORT a=rectOut.left;a<rectOut.right;a++) {
//Copy data from source to destination
//I'm not sure what the formats are, so I'm guessing from BGR (24-bit) to BGRX (32-bit)
memcpy(destChr,srcChr,3); //This will probably be changed
srcChr+=srcDepth;
destChr+=destDepth;
}
//Next line!
srcChr+=srcLine;
destChr+=destLine;
}
//Simple enough
}

//A function I made up:
//Limits one rectangle by another's coordinates to the smallest (Similar to Windows GDI)
bool LimitRect(LPRECT lprcDst, const RECT *lprcSrc) {
if (IsRectEmpty(lprcSrc)) return false;
if (lprcDst->left < lprcSrc->left) lprcDst->left=lprcSrc->left;
if (lprcDst->top < lprcSrc->top) lprcDst->top=lprcSrc->top;
if (lprcDst->right > lprcSrc->right) lprcDst->right=lprcSrc->right;
if (lprcDst->bottom > lprcSrc->bottom) lprcDst->bottom=lprcSrc->bottom;
return true;
}




And you can see that all of that was done with out any arrays or multiplications in the for loop. This can probably still be more efficient, by probably eliminating the rectangle overhead calculations and stuff like that.

NOTE: For flipped line storage (if biHeight < 0), you would simply change "srcLine" so that it would start out at the 'last' line (first when displayed), and subtract the line offsets (byte-padding + pitch).
As for other special effects, mirroring and flipping are pretty easy to figure out.

EDIT: Wait a minute... I though the Zero-padding had to do with the Width in bytes (Width*Depth), not just the width...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!