Archived

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

BMP Loading question

This topic is 6361 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

I have a few functions for loading bitmaps and then loading the data into a DDSurface (basically copied from laMothe's books), but it wasn't working correctly, so I went and asked about it and found that bitmaps add 'padding' to the nearest 4 bytes (or something like that). So after attempting to fix it so the loader skips these dead bytes, nothing works (Not that anything worked before, but...). So, basically, I was hoping someone would scan over my code and tell me what went wrong. I usually try to avoid posting "look at this code" questions, but I've been working on this for quite a while and am pretty much stumped. Anyway, here's the code for the .bmp loader, and below that is a little macro I used to find the length of the padding.
        
int FIL_LoadBmp(BMPFILE_PTR bmpFile, char *filename)
{
	int fileHandle, index;
	int	realWidth;

	UCHAR		*tempBuffer	=NULL;
	
	if((fileHandle = _open(filename, _O_RDONLY))==-1) {
		ERR_Log("ERROR FIL_LoadBmp : Can't open file %s\n", filename);
		return 0;
	}

	_read(fileHandle, &bmpFile->bmpFileHdr, sizeof(BITMAPFILEHEADER));


	if(bmpFile->bmpFileHdr.bfType != BITMAP_ID)
	{
		ERR_Log("ERROR FIL_LoadBmp : File '%s' isn't a bitmap.\n", filename);
		_close(fileHandle);
		return 0;
	}

	_read(fileHandle, &bmpFile->bmpInfoHdr,sizeof(BITMAPINFOHEADER));

	if(bmpFile->bmpInfoHdr.biBitCount==8)
	{
		_read(fileHandle, &bmpFile->palette, BMP_PALETTESIZE*sizeof(PALETTEENTRY));

		for(index=0; index < BMP_PALETTESIZE; index++)
		{
			int tempColor					= bmpFile->palette[index].peRed;
			bmpFile->palette[index].peRed	= bmpFile->palette[index].peBlue;
			bmpFile->palette[index].peBlue	= tempColor;

			bmpFile->palette[index].peFlags =PC_NOCOLLAPSE;
		}
	}

	_lseek(fileHandle, -(int)(bmpFile->bmpInfoHdr.biSizeImage), SEEK_END);

	if(bmpFile->bmpInfoHdr.biBitCount == 8  ||
	   bmpFile->bmpInfoHdr.biBitCount == 16 ||
	   bmpFile->bmpInfoHdr.biBitCount == 24)
	{
		if(bmpFile->buffer)		free(bmpFile->buffer);

		if(!(bmpFile->buffer=(UCHAR *) malloc (bmpFile->bmpInfoHdr.biSizeImage)))
		{
			ERR_Log("ERROR FIL_LoadBmp : Problem allocing size.\n");
			_close(fileHandle);
			return 0;
		}

////////NOTICE//////I think this is where its screwing up///////

	    realWidth=bmpFile->bmpInfoHdr.biWidth - ExtendDIB(bmpFile->bmpInfoHdr.biWidth);
		int bmpLoc=0;

		for(int z=0; z < bmpFile->bmpInfoHdr.biHeight; z++) {
			int bytesRead=_read(fileHandle, bmpFile->buffer+bmpLoc, realWidth);
			bmpLoc+=bytesRead;
	
			_lseek(fileHandle, ExtendDIB(bmpFile->bmpInfoHdr.biWidth), SEEK_CUR);
		}
		

	}
	else
	{
		ERR_Log("ERROR FIL_LoadBmp: Error reading image.\n");
		return 0;
	}

	_close(fileHandle);

	FIL_FlipBmp(bmpFile->buffer, 
				bmpFile->bmpInfoHdr.biWidth * (bmpFile->bmpInfoHdr.biBitCount/8),
				bmpFile->bmpInfoHdr.biHeight);


	return 1;
}
[/source]

The macro..
[source]
inline int ExtendDIB(int widthvar)
{
	if(widthvar % 4 !=0)
		return(4 - (widthvar % 4));
	else
		return(0);
}
[/source]

And here is the func to flip the bitmap
[source]
int FIL_FlipBmp(UCHAR *image, int bytes_per_line, int height)
{
	UCHAR *buffer; 
	int index;    

	if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
		return(0);

// copy image to work area

	memcpy(buffer,image,bytes_per_line*height);

// flip vertically

	for (index=0; index < height; index++)
		memcpy(&image[((height-1) - index)*bytes_per_line],
			   &buffer[index*bytes_per_line], bytes_per_line);

// release the memory

	free(buffer);

// return success

	return(1);	

}
[/source]

And finally, the code to copy it to a DDSurf
[source]
int GFX_BmpToSurface(BMPFILE_PTR bitmap, LPDIRECTDRAWSURFACE4 lpdds)
{
	UCHAR *sourcePtr, *destPtr;
	

	memset(&DDSDesc, 0, sizeof(DDSURFACEDESC2));
	DDSDesc.dwSize = sizeof(DDSURFACEDESC2);
	
	// lock the display surface


	if(FAILED(hRslt= lpdds->Lock(NULL, &DDSDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) {
		ERR_Log("ERROR GFX_BmpToSurface : %s\n",GFX_GetNameForErr(hRslt));
		return 0;
	}
	

	// extract bitmap data

	sourcePtr = bitmap->buffer;
	
	// assign a pointer to the memory surface for manipulation

	destPtr = (UCHAR *)DDSDesc.lpSurface;
	
/* Line-for-line commented out since I (should) be able to do it in one memcpy..
	// iterate thru each scanline and copy bitmap

	for (int index_y=0; index_y < (int)DDSDesc.dwHeight ; index_y++)
    {
		// copy next line of data to destination

		memcpy(destPtr, sourcePtr, DDSDesc.dwWidth);

		// advance pointers

		destPtr   += (DDSDesc.dwWidth);
		sourcePtr += bitmap->bmpInfoHdr.biWidth - ExtendDIB(bitmap->bmpInfoHdr.biWidth);
		
    } 
*/
	memcpy(destPtr, sourcePtr, bitmap->bmpInfoHdr.biWidth * bitmap->bmpInfoHdr.biHeight);

	lpdds->Unlock(NULL);
	
	return(1);
	
}
        
Edited by - A. Buza on 7/16/00 10:39:40 PM

Share this post


Link to post
Share on other sites