Archived

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

Metal Typhoon

Before i go to sleep :D ... shoulds this fucntion load a bitmap ?

Recommended Posts

i get the error unhadle something somgthins Access Violation
BYTE *GetLine (int line ,BYTE * surface,int stride)
{return (surface + stride * line);}


bool Load_BMP (char *filename)
{
	HBITMAP				Bitmap;
	BITMAPINFO			Info;
	BITMAPINFOHEADER	InfoHeader;
	BITMAPFILEHEADER	Header;
	HDC					Temp = CreateCompatibleDC (NULL);
	BYTE				Surface = NULL;
	unsigned int		BytesPerLine;

	if (!filename)
		return 0;

	FILE	*File = fopen (filename,"rb");

	if (!File)
	{
		return false;
	}

	if (!fread (&Header,sizeof (BITMAPFILEHEADER),1,File))
	{
		fclose (File);
		return false;
	}

	if (memcmp (&Header.bfType ,"BM",2))
	{
		fclose (File);
		return false;
	}

	if (!fread (&InfoHeader,sizeof (BITMAPINFOHEADER),1,File))
	{
		fclose (File);
		Error();
		return false;
	}

	if (InfoHeader.biBitCount != 24 && InfoHeader.biBitCount != 32)
	{
		fclose (File);
		Error();
		return false;
	}

	Info.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); 
	Info.bmiHeader.biBitCount = InfoHeader.biBitCount;
	Info.bmiHeader.biWidth = InfoHeader.biWidth;
	Info.bmiHeader.biHeight = InfoHeader.biHeight;
	Info.bmiHeader.biClrUsed = 0; 
	Info.bmiHeader.biPlanes = 1;
	Info.bmiHeader.biCompression = BI_RGB; 
	
	Bitmap = CreateDIBSection (Temp,&Info,DIB_RGB_COLORS,(void **)&Surface,0,0);
	
	if (!Bitmap)
		return false;

	BytesPerLine = Info.bmiHeader.biWidth * Info.bmiHeader.biBitCount;

	for (int Y = 0 ; Y < Info.bmiHeader.biHeight ; Y++)
	{
		BYTE *pLine = GetLine (Y,&Surface,BytesPerLine);
		
		if (!fread (pLine,BytesPerLine,1,File))
		{
			fclose (File);
			return false;
		}
		if (fseek (File,BytesPerLine,SEEK_CUR))
		{
			fclose (File);
			return false;
		}
	}

	fclose (File);
	return true;
}
 
Metal Typhoon

Share this post


Link to post
Share on other sites
Hmm, I see an error or two right off the bat (such as not accounting for padding bytes in the BMP/DIB). Look here. They have a 24&32 bit BMP loader that works with DIB sections. I used it as a reference to make my own loading function (and was subsequently saved quite a few headaches).

HTH

Share this post


Link to post
Share on other sites
quote:
Original post by SysOp_1101
Hmm, I see an error or two right off the bat (such as not accounting for padding bytes in the BMP/DIB). Look here. They have a 24&32 bit BMP loader that works with DIB sections. I used it as a reference to make my own loading function (and was subsequently saved quite a few headaches).

HTH


Stride = Width * Channels
BytesPerLine = Width * Channels
Padding = Stride - Bytes.

ok i got that error.. but if i assume the there wont be a pad or put a 0 on the last fseek ... the erro still shows up

Metal Typhoon

Share this post


Link to post
Share on other sites
Change:


        
if (fseek (File,BytesPerLine,SEEK_CUR))...


To:

if (fseek (File,Padding,SEEK_CUR))...


Otherwise your skipping over far more than the padding bytes. In the event of no padding bytes, you've just skipped an entire line of data (and also cause your line pointer to attempt to access data beyond your image data array which would explain the access violation you get).

HTH

[edited by - SysOp_1101 on August 16, 2002 4:43:58 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by SysOp_1101
Change:



    
if (fseek (File,BytesPerLine,SEEK_CUR))...


To:

if (fseek (File,Padding,SEEK_CUR))...


Otherwise your skipping over far more than the padding bytes.

HTH

i found the erro on my thingy to be this part


BYTE *pLine = GetLine (Y,&Surface,Stride);

if (!fread (pLine,BytesPerLine,1,File))
{
fclose (File);
return false;
}


and the GetLine function is here


BYTE *GetLine (int line ,BYTE * surface,int stride)
{return (surface + stride * line);}


the program just quits... any suggestion ??

Metal Typhoon

Share this post


Link to post
Share on other sites
Well, here's my implementation (yes I know it's totally unoptimized, but it's still a 'raw' project right now -- please don't laugh). I also have my DIB information stored as a class (DD_DIB, so assume that mDIBBits is an unsigned char[] and that acess to the surface bits is provided through a function call to InDIB which returns an unsigned char* as well -- which is equivelant to your surface variable).


      
unsigned char* DD_DIB::GetLine(int iLine) {
//Start from the beginning offset of our DIB data in

//memory, then add the product of iLine * stride to

//calculate the start of our DWORD color location.

return (mDIBBits + mStride * iLine);
}



bool LoadDIBFromFile(HDC uHDC, DD_DIB* InDIB, const char* cDIB_File) {
FILE *dib_file;
BITMAPFILEHEADER bmp_fileheader = {0};
BITMAPINFOHEADER bmp_infoheader = {0};

InDIB->Free();

if(!cDIB_File) {
MessageBox(NULL, "Invalid file name passed to function.", "LoadDIBFromFile", MB_OK);
return false;
}

dib_file = fopen(cDIB_File, "rb");

if(!dib_file) {
MessageBox(NULL, "Failed to open DIB file.", "LoadDIBFromFile", MB_OK);
return false;
}

if(!fread(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, dib_file)) {
MessageBox(NULL, "Failed to read BITMAPFILEHEADER.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// Check the type field to make sure we have a .bmp file

// bfType should contain the letters "BM"

if(memcmp(&bmp_fileheader.bfType, "BM", 2)) {
MessageBox(NULL, "Invalid file type found in BITMAPFILEHEADER.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

if(!fread(&bmp_infoheader, sizeof(BITMAPINFOHEADER), 1, dib_file)) {
MessageBox(NULL, "Invalid file type found in BITMAPINFOHEADER.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// Double Check to make sure we got a correct BITMAPINFOHEADER

if(bmp_infoheader.biSize != sizeof(bmp_infoheader)) {
MessageBox(NULL, "Invalid BITMAPINFOHEADER size.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// Check for unsupported format

// biPlanes MUST equal 1

if(bmp_infoheader.biPlanes != 1) {
MessageBox(NULL, "Invalid number of planes found in BITMAPINFOHEADER.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}


// Jump to the location where the bitmap data is stored

// **Note** fseek() returns 0 on success

if(fseek(dib_file, bmp_fileheader.bfOffBits, SEEK_SET)) {
MessageBox(NULL, "Failed to locate DIB pixel data in file.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// One more double check that we have a .bmp we can handle

// We can only handle uncompressed .bmps

if(bmp_infoheader.biCompression != BI_RGB)
{
MessageBox(NULL, "Unsupported file type found -- compressed.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

if(!InDIB->Init(uHDC, bmp_infoheader.biWidth, bmp_infoheader.biHeight)) {
MessageBox(NULL, "Unable to initialize memory DIB data.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// Calculate the number of padding bytes

unsigned int bytesUsed = InDIB->GetWidth() << 2; //Width * channels (Note: 32-bit always uses 4 channels)

unsigned int padding = InDIB->GetStride() - bytesUsed;

// Fill our HC_BMP pixel data

for(int y = 0; y < InDIB->GetHeight(); y++) {
// Get the current scan line in our HC_BMP

unsigned char *LinePtr = InDIB->GetLine(y);

// Read the precise number of bytes that the line requires into the bitmap.

// Don't read the padding bytes

if(!fread(LinePtr, bytesUsed, 1, dib_file)) {
MessageBox(NULL, "Failed to read line of DIB data.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

// Skip over any padding bytes.

if(fseek(dib_file, padding, SEEK_CUR)) {
MessageBox(NULL, "Unable to skip padding bytes.", "LoadDIBFromFile", MB_OK);
fclose(dib_file);
return false;
}

}


fclose(dib_file);
return true;
}


One thing to note is that you have to be careful when saving the file (Photoshop has a tendency to produce 32bit DIBs that are incompatible with my program at times yet works great with everything else). Make sure your output format is in A8R8G8B8 format, else the load function fails miserably (thus the reason for the abundence of MessageBox calls in my function).

We'll get that load working one way or another.

EDIT: All of my create DIB section and initialization work is done in a member function as well, so it's not reflected in the above block of code. Darookie was keen enough to spot another error which could very well be the root of your problem. Try his suggestion first.

HTH

[edited by - SysOp_1101 on August 16, 2002 5:05:21 AM]

Share this post


Link to post
Share on other sites
Two things:
Shouldn''t this be a pointer:

  
LPBYTE Surface = NULL;
// instead of

BYTE Surface = NULL;


And second, due to the fact that ''Surface'' is a pointer, you don''t need to take it''s address here:


  
BYTE *pLine = GetLine (Y,Surface,Stride);
// instead of

BYTE *pLine = GetLine (Y,&Surface,Stride);


This should help,
Pat

Share this post


Link to post
Share on other sites