Skip to main content
GameDev.net gamedev.net
🔒 Locked

Bitmap frustrations

Started by Turtlebread Aug 5, 2001 at 5:45 PM 9 replies 700+ views
Original Post
Turtlebread
Turtlebread
Ok, maybe someone new looking at this problem can help me out. I'm loading a bitmap with the following code, and then transfering it to a DDraw surface, and blitting it. The only problem is, there are blank lines on the image blted to the screen. I've narrowed it down to either the bitmap loader or the bitmap to surface function. The bitmap does not have any padding issues(its DWORD aligned) and I am converting to the right 16-bit mode. Heres the coder for the loader:
    
for(iHeight = spBitmap->infoheader.biHeight - 1; iHeight >=0; iHeight --){
   for(iWidth = 0; iWidth < spBitmap->infoheader.biWidth*2; iWidth += 2){
             //read in one pixel, converting it to either RGB 565 or 555 

             //and switching it from BGR to RGB

             file.get((char&)sTemp.blue);
	file.get((char&)sTemp.green);
	file.get((char&)sTemp.red);
	//convert the pixel to 16 bit

	wColor = Convert16(sTemp.red, sTemp.green, sTemp.blue);//Converts it to a 16-bit WORD value

	//store low-end of WORD

				
             spBitmap->buffer[iHeight*spBitmap->infoheader.biWidth+iWidth] = wColor & 0xFF;
             //The buffer is a BYTE buffer that IS big enough to hold everything

	//store high-end of WORD

	spBitmap->buffer[iHeight*spBitmap->infoheader.biWidth+iWidth + 1] = wColor>>8;
				
   }
}
  
And now heres the part that copies the bitmap from buffer to a surface.
  
             wBitmap_Buffer = (WORD*)spBitmap->buffer;//Again, BUFFER points to a BYTE buffer

	wScreen_Buffer = (WORD*)SurfaceDesc.lpSurface; //make the buffer valid

	//Now copy the bitmap to the newly locked surface

	for(y = 0; y < spBitmap->infoheader.biHeight; y++)
	{
		
		//copy the bitmap one line at a time

		memcpy((void*)wScreen_Buffer,
			   (void*)wBitmap_Buffer, 
			   spBitmap->infoheader.biWidth*2);
		//advance pointers

		wScreen_Buffer += SurfaceDesc.lPitch;
		wBitmap_Buffer += spBitmap->infoheader.biWidth;
	
	}
    
Any ideas at this point would be MUCH appreciated. I'm sick of staring at my screen trying to figure out whats wrong. -Chris EDIT: Fixed the formatting Edited by - Turtlebread on August 5, 2001 6:48:46 PM
Big Sassy
Big Sassy
When you say blank lines do you mean every other line is blank, or that just random lines are blank, or that the lines at the end are blank?

Prime
Prime
Hi Turtlebread,

I''ve found that the easiest thing to do is to use the loader that comes with the DirectX SDK. There is a function called DDLoadBitmap() in ddutil.h and .cpp that does just what you need. The ddutil files are in some of the sample directories. Just do a search for them and you should find them. Here''s the prototype:


IDirectDrawSurface7 *DDLoadBitmap(IDirectDraw7 *pdd, LPCSTR szBitmap, int dx, int dy);


If I remember correctly dx and dy are used to specify where the bitmap is to be put on the surface. So I put 0,0 it indicate the top left corner. It loads a bitmap from a file specified by szBitmap and puts it onto a surface, and returns a pointer to that surface. Once you have that pointer, you can use it to blt the bitmap to your backbuffer or whatever. Here''s how I used it in my code:


// load bitmap
if((myBitmap = DDLoadBitmap( ddObject, "mybitmap.bmp", 0, 0) ) != NULL )
log << "Bitmap loaded" << endl;
else
{
log << "ERROR: unable to load bitmap" << endl;
return false;
}

Anyway, hope that helps.
Turtlebread
Turtlebread
Its hard to explain what the .bmps look like when their blted. Heres an example of just a big purple square that I tried to BLT to the screen.

http://www.geocities.com/turtlebread/test2.jpg.


It seems like instead of blank space, its printing garabage values, like the surface is not getting totally written too. And I don't want to use a function to load a bitmap, I'm trying to create one myself, so I have some control over how it is loaded.

Thanks,
-Chris

EDIT: Link didn't work

Edited by - Turtlebread on August 5, 2001 8:35:03 PM
Turtlebread
Turtlebread
Hmm...it seems another little problem has entered the game. Since I''m in 16-bit mode, I''m casting the lpSurface pointer to a WORD. To advance it, I''m adding lPitch to it. However, lPitch is the number of BYTES, and I''m using a WORD pointer. AHA! I thought, now I have it. I''ll just divide lPitch by 2 (16/8) However, it didn''t work. It is STILL showing up wrong, but this leads me to another question. What happens if lPitch is say, 41 bytes. 41/2 = 21.5. This would be very bad, as the WORD pointer couldn''t advance to the right spot. What happens in this situation? Is lPitch ALWAYS going to be even? If not, what happens if yer using a WORD pointer to the surface?

-Chris
lshadow
lshadow
Well I can''t really tell without a little more code, but one thing that seems off is your for statement. If you''re reading in a 24-bit bitmap (which it appears you are and then converting it to 16-bit), then the for statement would be...
  
for(iWidth=0; iWidth<infoHeader.biWidth*3; iWidth+=3)

This because there are three bytes, the R, G, and B values.
Working on: DoP
Turtlebread
Turtlebread
I''m reading in a pixel at a time though, so I should just run through the entire bitmap once. The only reason I''m adding two at a time is because of my BYTE buffer. Anyway, I''ve been running some test, and found out that it reads the first row of pixels fine, and then only the second half. For example, take a 4x4 bitmap
X X X X
0 0 X X
0 0 X X
0 0 X X

The X''s represent the pixels that appear on the screen of a 4x4 bitmap. The problem seems to be somewhere in the bitmap reading loop...Let me know if anyone sees a problem.

-Chris
Turtlebread
Turtlebread
Aha! It finally works. It was a combination of problems, including the fact I wasn''t taking into account the BYTE buffer addressing. Thanks to all who helped

-Chris
Big Sassy
Big Sassy
Glad you finally got it working

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.