BMP Loading question

Started by
-1 comments, last by A. Buza 23 years, 9 months ago
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(ℑ[((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

This topic is closed to new replies.

Advertisement