Help w/ saving bitmaps...
Ok, well, the title may be misleading, its not exactly about saving bitmaps in the bitmap file format. I jusyt wanna write the data to a file without the headers. Im using this for a tile-map saving function and trying to save the bitmaps as my tileset. Im trying to accomplish this (buggy code to follow soon):
- Get the handle to the bitmap, and put the nessicary info into the struct w/ GetObject() call
- Save the BITMAP struct to a file
- Have it work
Now, for some reason
fread(&bitmap, sizeof(BITMAP), 1, fp);
is an Access Violation error, so I thought that i should save the structs members and read them individually, and then read .bmBits at size bitmap.bmWidth * bitmap.bmHeight as follows:
fread(&bitmap.bmType, sizeof(LONG), 1, fp);
fread(&bitmap.bmWidth, sizeof(LONG), 1, fp);
fread(&bitmap.bmHeight, sizeof(LONG), 1, fp);
fread(&bitmap.bmWidthBytes, sizeof(LONG), 1, fp);
fread(&bitmap.bmPlanes, sizeof(WORD), 1, fp);
fread(&bitmap.bmBitsPixel, sizeof(WORD), 1, fp);
fread(bitmap.bmBits, bitmap.bmWidth * bitmap.bmHeight, 1, fp);
Now, that doesn''t work, it won''t display with a blit, but the information that i was gonna save is good, because in the app, I can reconvert it, and it blits fine. So it must be the saving of the tileset. Im wondering if anyone has experience with this kind of really annoying, I want to shoot my computer and then spit on its part and laugh, problem. Or perhaps there is just a better way to save the bitmaps w/o unneccisary info.
-----------------------------
A wise man once said "A person with half a clue is more dangerous than a person with or without one."
The Micro$haft BSOD T-Shirt
-----------------------------A wise man once said "A person with half a clue is more dangerous than a person with or without one."The Micro$haft BSOD T-Shirt
Your formats is wrong. Here is some bitmap loading code.
Simply fopen a file for "wb" then use the line
fwrite(imgdata, fd.imglength, 1, data);
to write it back to a file without the header data. You might want to include a magic number or other data in the header of your new file so you don't run into errors with the file.
If it still doesn't work, flame me.
Edited by - Galileo430 on November 6, 2000 10:54:37 PM
#define TRUE 1#define FALSE 0struct BMPDATA{ // Needed Read Data unsigned char chrMagicNumber[2]; unsigned long filelength; unsigned long reserved; unsigned long dataoffset; unsigned long datahead; unsigned long sizex; unsigned long sizey; unsigned short planes; unsigned short bits; unsigned long compressiontype; unsigned long imglength; unsigned long resx; unsigned long resy; unsigned long colorsused; unsigned long impcolors; };unsigned char *imgdata;BMPDATA fd;int LoadBitmap(char *filename){ //--------------------------------------------- // Locals //--------------------------------------------- FILE *stream; //--------------------------------------------- // Test File and Load Data //--------------------------------------------- if ( (stream = fopen(filename,"rb")) == NULL) { cout << "File Does Not Exist" << endl; return FALSE; } //--------------------------- // Read the "Magic Number" //--------------------------- fread(&fd.chrMagicNumber, sizeof(fd.chrMagicNumber), 1, stream); //--------------------------- //--------------------------- // Check the "Magic Number" //--------------------------- if (fd.chrMagicNumber[0] == 'B' && fd.chrMagicNumber[1] == 'M') { cout << "Bitmap OK" << endl; } else { cout << "Not A Bitmap" << endl; return FALSE; } //---------------------------- //---------------------------- //Read On Good Man //---------------------------- fseek(stream, 2, SEEK_SET); //Make Sure We're In the Right Spot fread(&fd.filelength, sizeof(unsigned long), 1, stream); fread(&fd.reserved, sizeof(unsigned long), 1, stream); fread(&fd.dataoffset, sizeof(unsigned long), 1, stream); fread(&fd.datahead, sizeof(unsigned long), 1, stream); fread(&fd.sizex, sizeof(unsigned long), 1, stream); fread(&fd.sizey, sizeof(unsigned long), 1, stream); fread(&fd.planes, sizeof(unsigned short), 1, stream); fread(&fd.bits, sizeof(unsigned short), 1, stream); fread(&fd.compressiontype, sizeof(unsigned long), 1, stream); fread(&fd.imglength, sizeof(unsigned long), 1, stream); fread(&fd.resx, sizeof(unsigned long), 1, stream); fread(&fd.resy, sizeof(unsigned long), 1, stream); fread(&fd.colorsused, sizeof(unsigned long), 1, stream); fread(&fd.impcolors, sizeof(unsigned long), 1, stream); //---------------------------------------------- //-------------------------------- // Read ImgData //-------------------------------- fseek(stream, fd.dataoffset, SEEK_SET); imgdata = new unsigned char[fd.imglength]; ((unsigned char *)imgdata)[fd.imglength] = 0; fread(imgdata, fd.imglength, 1, stream); //--------------------------------
Simply fopen a file for "wb" then use the line
fwrite(imgdata, fd.imglength, 1, data);
to write it back to a file without the header data. You might want to include a magic number or other data in the header of your new file so you don't run into errors with the file.
If it still doesn't work, flame me.
Edited by - Galileo430 on November 6, 2000 10:54:37 PM
------------------------------------------------------------I wrote the best video game ever, then I woke up...
Holy crap thats overly complicated!! I assume you have a bitmap in memory in the BITMAP/HBITMAP format. What you need to do is call GetDIBits(HDC hdc, HBITMAP hbmp, UINT cScanLines, LPVOID lpvBits, LPVOID lpvBits, UINT uUsage)
HDC hdc // handle to DC
HBITMAP hbmp, // handle to bitmap
UINT uStartScan, // first scan line to set
UINT cScanLines, // number of scan lines to copy
LPVOID lpvBits, // array for bitmap bits
LPBITMAPINFO lpbi, // bitmap data buffer
UINT uUsage // RGB or palette index
lpvBits is a buffer that gets the actual image data, and lpbi is a structure of type BITMAPINFO that gets all the info. Just write this stuff out to a file and youre good to go. Well hold on a minute... You will need to look up in MSDN how to fill out a BITMAPFILEHEADER struct... the format of a file goes like this:
BITMAPFILEHEADER
BITMAPINFO
data
Good luck! Bitmaps are a pain in the ass!
Looking back at your post, I see you want to write just the data to a file and not the headers?? Unless youre storing that info somewhere else (why??), you'll end up with a bunch of worthless bits... Im so glad I have a working tileset!! =)
Edited by - Orpheum on November 6, 2000 11:17:46 PM
HDC hdc // handle to DC
HBITMAP hbmp, // handle to bitmap
UINT uStartScan, // first scan line to set
UINT cScanLines, // number of scan lines to copy
LPVOID lpvBits, // array for bitmap bits
LPBITMAPINFO lpbi, // bitmap data buffer
UINT uUsage // RGB or palette index
lpvBits is a buffer that gets the actual image data, and lpbi is a structure of type BITMAPINFO that gets all the info. Just write this stuff out to a file and youre good to go. Well hold on a minute... You will need to look up in MSDN how to fill out a BITMAPFILEHEADER struct... the format of a file goes like this:
BITMAPFILEHEADER
BITMAPINFO
data
Good luck! Bitmaps are a pain in the ass!
Looking back at your post, I see you want to write just the data to a file and not the headers?? Unless youre storing that info somewhere else (why??), you'll end up with a bunch of worthless bits... Im so glad I have a working tileset!! =)
Edited by - Orpheum on November 6, 2000 11:17:46 PM
There is no spoon.
Uh, I''m just guessing that you want to write the raw data from a surface to a file? In which case, all you will need to recrate the surface from the file would be the width, the height, and the bytes which describe the ''bitmap''.
I think that if you lock the surface and then read it into an array (or straight to a file). You need to typecast according to your videowidth, and use the pitch of the surface rather than just the width.
Probably not too clear, but if you''re a GNUMAN you''ll probably understand...
I think that if you lock the surface and then read it into an array (or straight to a file). You need to typecast according to your videowidth, and use the pitch of the surface rather than just the width.
Probably not too clear, but if you''re a GNUMAN you''ll probably understand...
The only problem with surfaces is that they arent device independant. I kind of need the bitmaps to work in different modes well....
Besides, I already got the conversion function down, no prob with that, just need to know why it wont load up as planned...
-----------------------------
A wise man once said "A person with half a clue is more dangerous than a person with or without one."
The Micro$haft BSOD T-Shirt
Besides, I already got the conversion function down, no prob with that, just need to know why it wont load up as planned...
-----------------------------
A wise man once said "A person with half a clue is more dangerous than a person with or without one."
The Micro$haft BSOD T-Shirt
-----------------------------A wise man once said "A person with half a clue is more dangerous than a person with or without one."The Micro$haft BSOD T-Shirt
November 08, 2000 08:21 PM
Well - here''s how I do it:
void Texture_Class::Load_Texture()
{
FILE *texturefile;
if ((texturefile = fopen(texture_file_name,"rb")) == NULL)
{
//We were not able to find a texture with the specified file name, so we will use the
//corresponding shading value instead.
is_color = true;
DEBUG_OUTPUT <<"Texture: \"" < }
else
{
is_color = false;
fread(&bit_depth,sizeof(int),1,texturefile);
fread(&x_dim,sizeof(int),1,texturefile);
fread(&y_dim,sizeof(int),1,texturefile);
//Load the data for the bitmap (depending on the bit depth).
switch(bit_depth)
{
case 8:
data_ptr = new BYTE[x_dim*y_dim];
fread(&data_ptr[0],sizeof(BYTE),x_dim*y_dim,texturefile);
break;
case 16:
data_ptr = reinterpret_cast(new WORD[x_dim*y_dim]);
fread(&data_ptr[0],sizeof(WORD),x_dim*y_dim,texturefile);
break;
case 32:
data_ptr = reinterpret_cast(new DWORD[x_dim*y_dim]);
fread(&data_ptr[0],sizeof(DWORD),x_dim*y_dim,texturefile);
break;
default:
DEBUG_OUTPUT <<"Invalid bit depth in texture file: \"" < exit(1);
}
fclose(texturefile);
DEBUG_OUTPUT <<"Texture: \"" < }
}
Don''t be confused by the "texture" part - that''s because I''m doing 3D - but it is just a normal bitmap. The first thing it reads is the bit-depth then the x-dimension, then the y-dimension. The saving code is the opposite - I have it here somewhere......
//Saves a 16 bit texture in .TEX file format.
void Save_Texture_16(char *file_name, Texture_16_Type *texture)
{
HANDLE Tex_File;
Tex_File = CreateFile(file_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(Tex_File == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"Could not create Texture file!",NULL,MB_OK);
exit(1);
}
int bit_depth = 16;
unsigned long temp;
WriteFile(Tex_File,(void *) &bit_depth,sizeof(bit_depth),&temp,NULL);
WriteFile(Tex_File,(void *) &texture->x_dim,sizeof(texture->x_dim),&temp,NULL);
WriteFile(Tex_File,(void *) &texture->y_dim,sizeof(texture->y_dim),&temp,NULL);
int tex_size = texture->x_dim*texture->y_dim;
WriteFile(Tex_File,(void *) texture->BMP_Data,(sizeof(texture->BMP_Data[0])*tex_size),&temp,NULL);
CloseHandle(Tex_File);
}
Hmmm, maybe that isn''t such a good peice to give you - looks like I was experimenting with windows file IO - here''s a better one that does 32 bit:
//Saves a 32 bit texture in .TEX file format.
void Save_Texture_32(char *file_name, Texture_32_Type *texture)
{
FILE *bmp_file;
if ((bmp_file = fopen(file_name,"w+b")) == NULL)
{
MessageBox(NULL,"Cannot create file for texture!",NULL,MB_OK);
exit(1);
}
int bit_depth = 32;
//write the bit depth of the bitmap into the file.
fwrite(&bit_depth,sizeof(int),1,bmp_file);
//write the width of the bitmap into the file.
fwrite(&texture->x_dim,sizeof(int),1,bmp_file);
//write the hight of the bitmap into the file.
fwrite(&texture->y_dim,sizeof(int),1,bmp_file);
int bmp_size = texture->x_dim*texture->y_dim;
for(int counter = 0; counter < bmp_size; counter++)
{
fwrite(&texture->BMP_Data[counter],sizeof(DWORD),1,bmp_file);
}
fclose(bmp_file);
}
Hope this stuff helps - It seemed that you were doing things very similarly to me so...
anyway, if you have Q''s, email me: cropperr@home.com
void Texture_Class::Load_Texture()
{
FILE *texturefile;
if ((texturefile = fopen(texture_file_name,"rb")) == NULL)
{
//We were not able to find a texture with the specified file name, so we will use the
//corresponding shading value instead.
is_color = true;
DEBUG_OUTPUT <<"Texture: \"" < }
else
{
is_color = false;
fread(&bit_depth,sizeof(int),1,texturefile);
fread(&x_dim,sizeof(int),1,texturefile);
fread(&y_dim,sizeof(int),1,texturefile);
//Load the data for the bitmap (depending on the bit depth).
switch(bit_depth)
{
case 8:
data_ptr = new BYTE[x_dim*y_dim];
fread(&data_ptr[0],sizeof(BYTE),x_dim*y_dim,texturefile);
break;
case 16:
data_ptr = reinterpret_cast(new WORD[x_dim*y_dim]);
fread(&data_ptr[0],sizeof(WORD),x_dim*y_dim,texturefile);
break;
case 32:
data_ptr = reinterpret_cast(new DWORD[x_dim*y_dim]);
fread(&data_ptr[0],sizeof(DWORD),x_dim*y_dim,texturefile);
break;
default:
DEBUG_OUTPUT <<"Invalid bit depth in texture file: \"" < exit(1);
}
fclose(texturefile);
DEBUG_OUTPUT <<"Texture: \"" < }
}
Don''t be confused by the "texture" part - that''s because I''m doing 3D - but it is just a normal bitmap. The first thing it reads is the bit-depth then the x-dimension, then the y-dimension. The saving code is the opposite - I have it here somewhere......
//Saves a 16 bit texture in .TEX file format.
void Save_Texture_16(char *file_name, Texture_16_Type *texture)
{
HANDLE Tex_File;
Tex_File = CreateFile(file_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(Tex_File == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"Could not create Texture file!",NULL,MB_OK);
exit(1);
}
int bit_depth = 16;
unsigned long temp;
WriteFile(Tex_File,(void *) &bit_depth,sizeof(bit_depth),&temp,NULL);
WriteFile(Tex_File,(void *) &texture->x_dim,sizeof(texture->x_dim),&temp,NULL);
WriteFile(Tex_File,(void *) &texture->y_dim,sizeof(texture->y_dim),&temp,NULL);
int tex_size = texture->x_dim*texture->y_dim;
WriteFile(Tex_File,(void *) texture->BMP_Data,(sizeof(texture->BMP_Data[0])*tex_size),&temp,NULL);
CloseHandle(Tex_File);
}
Hmmm, maybe that isn''t such a good peice to give you - looks like I was experimenting with windows file IO - here''s a better one that does 32 bit:
//Saves a 32 bit texture in .TEX file format.
void Save_Texture_32(char *file_name, Texture_32_Type *texture)
{
FILE *bmp_file;
if ((bmp_file = fopen(file_name,"w+b")) == NULL)
{
MessageBox(NULL,"Cannot create file for texture!",NULL,MB_OK);
exit(1);
}
int bit_depth = 32;
//write the bit depth of the bitmap into the file.
fwrite(&bit_depth,sizeof(int),1,bmp_file);
//write the width of the bitmap into the file.
fwrite(&texture->x_dim,sizeof(int),1,bmp_file);
//write the hight of the bitmap into the file.
fwrite(&texture->y_dim,sizeof(int),1,bmp_file);
int bmp_size = texture->x_dim*texture->y_dim;
for(int counter = 0; counter < bmp_size; counter++)
{
fwrite(&texture->BMP_Data[counter],sizeof(DWORD),1,bmp_file);
}
fclose(bmp_file);
}
Hope this stuff helps - It seemed that you were doing things very similarly to me so...
anyway, if you have Q''s, email me: cropperr@home.com
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement