Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Allegro can't load my bitmaps. Need help with bitmap file format.

Credits go to 23yrold3yrold for helping out!
This thread is locked; no one can reply to it. rss feed Print
Allegro can't load my bitmaps. Need help with bitmap file format.
Mr. Xboxor
Member #3,763
August 2003
avatar

I'm making an 8bit color game, and, as such, have spent alot of time creating a personlized palette and a method of my bitmap images all using that same palette. Here's where I stand: I have programs that will convert any 24bit bitmap into an 8bit bitmap which only uses my personalized palette. I also have drawn a color bar (saved as a 24bit bitmap) so that others may use paint's color selection tool to select from colors that are in my palette. This basically allows me to create 8bit bitmap images which only use my palette colors.
But there's a catch, allegro won't read my 8bit bitmaps correctly. If necessary, I'll show my code later, but I don't think it's necessary right now. I noticed that after I convert a 24bit bitmap to an 8bit one (using a program I wrote, but not using allegro), if I am in explorer, and highlight the 8 bit file, the preview it brings up is all wierd. Basically, there is some junk at the bottom of the picture (bmp's are stored upside down, so this junk is from the beginning of the file). My guess is that it is showing the palette data and/or bmp headers as part of the picture. But why? The image preview is using the correct palette. Anyways, when I open the file in paint, it is displayed just fine. When I use allegro to display it, though, I get the SAME EXACT results as with the image preview. Obviously, my bmp file format has a hole in it. I've also noticed that sometimes when I download a 24bit bitmap off the internet, and use my program to convert it to use my colors, the resulting image is messed up, even in paint. I've checked, and they don't use compression, and are linear bitmaps. So, for some reason, is there another bitmap file format or something. Here's the format I am using (if you'd like to see my code and get examples of the pictures I'm talking about, I'd be glad to attach them):

2 bytes: bm signature
4 bytes: file size
2 bytes: reserved(must be set to 0)
2 bytes: reserved(must be set to 0)
4 bytes: byte offset from header to start of image
(start of image includes the palette)
4 bytes: size of bm info header
4 bytes: bm width
4 bytes: bm height
2 bytes: planes
2 bytes: color depth
4 bytes: compression
4 bytes: size of image
4 bytes: hor pixels per meter
4 bytes: vert pixels per meter
4 bytes: # colors actually used
4 bytes: # colors important for displaying bitmap

That's it. One theory that I have is that the offset from header to image also includes the size of the palette. This would explain why allegro is treating the palette as part of the image, because it thinks that the image starts there. Also, when I load an 8bit bitmap and use it's palette, the palette is messed up. This is only with my 8bit bitmaps. So I think the key to this problem is the location of the palette. Can anyone help out? Thanks for your time.

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

4 bytes: byte offset from header to start of image
(start of image includes the palette)

Not according to my information ... let's see your code for saving an 8bpp bitmap. Might save some time.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Mr. Xboxor
Member #3,763
August 2003
avatar

Okay, thanks for your help. I'm gonna show part of my code, because some parts are irrelevant and a mess. But rest assure they have no effect on saving a bitmap.

Here's my combined header (meaning I put the file header an info header into one big thing)

struct bmpHeaderType
{
char magic1, magic2; // identity 'BM'
long fileSize; // size of file in bytes
long reserved; // always 0
long pixelOffset; // offset of data
long bmiSize; // remaining size of header in file
long cols, rows; // width and height of image
int nPlanes; // number of color planes
int bitsPerPixel; // number of bits used to represent a pixel
long compression, cmpSize; // compressed image?
long xScale, yScale;
long colors, impColors;
};

For saving a 24bit bitmap to an 8bit one:
read 24bit bitmap header
put same contents in 8bit one, then my code:

1bmpHeader.fileSize=bmpHeader.pixelOffset+((4-bmpHeader.cols&4)%4)*bmpHeader.rows;
2bmpHeader.bitsPerPixel=8;
3bmpHeader.colors=256;
4bmpHeader.impColors=0;
5fwrite(&bmpHeader,sizeof(bmpHeader),1,outfilestream);
6fseek(infilestream,bmpHeader.pixelOffset,SEEK_SET);
7 
8for (int k=0;k<bmpHeader.pixelOffset-sizeof(bmpHeader);k++)
9 fwrite(&zero/*a char equal to 0*/,1,1,outfilestream);//fills in space with 0's
10 
11unsigned char byte;
12 
13for (k=0;k<256;k++)
14{
15 byte=colors[k].b;//array for my palette data
16 byte*=4;//my data stored in 0-63, must convert to 0-255
17 fwrite(&byte,1,1,outfilestream);
18 //...repeat green and blue, then write a spare byte
19}
20 
21for (int y=0;y<bmpHeader.rows;y++)
22{
23 for (int x=0;x<bmpHeader.cols;x++)
24 {
25 //fread rgb pixel from 24bit file
26 //get appropriate color index for this rgb pixel
27 //fwrite this color byte to outfilestream
28 }
29 fseek(infilestream,(4-3*bmpHeader.cols%4)%4,SEEK_CUR);
30 for (k=0;k<(4-bmpHeader.cols%4)%4;k++)
31 fwrite(&zero/*char=0*/,1,1,outfilestream);
32}
33then close my data files
34 }
35}
36}

Hope this helps. Although, I don't think it is necessary to actually see my code, but you never know. You see, paint understands my bmp file, but allegro and explorer image preview do not. So what assumption do these make that paint doesn't?

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

So what assumption do these make that paint doesn't?

Well, if it's your file header that's wrong, maybe Explorer and Allegro are using that, and Paint just ignores it and reads in that data as it comes across it (entirely possible; you don't need the offset to the pixel data to read it in properly).

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Mr. Xboxor
Member #3,763
August 2003
avatar

Nevermind, I fix it. Like you said, it was my an incorrectness in my bitmap header, so I'll give you credit for that. It was a combination of things. To solve my problem, I converted a correct 8bit image to integer values for each byte, so I could compare it with my own 8 bit image of the incorrect type. Problems with my methods:
offset does include palette: 54+256*4
my filesize was way too small (I neglected to count the palette data as well as the image data, the only thing I did count were the blank pixels to make the columns divisible by four)
the cmpSize field is not supposed to be 0 (I thought this was for compression only), it is supposed to be the number of pixels in the image.

So everything works just fine now. Thanks for your help 23.

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

Evert
Member #794
November 2000
avatar

Quote:

So, for some reason, is there another bitmap file format or something.

I know the problem is solved, but as a random bit of trivia, I'd like to mention that there are indeed two different types of bmp file: Windows and OS/2 style.
As far as I know, the OS/2 format differs from the Windows version by not having its header crammed with lots of reserved or otherwise pointless fields. You can check Allegro's bmp loader if you want to see more details.

spellcaster
Member #1,493
September 2001
avatar

The OS2 version also stores the lines top-down instead of bottom-up.

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Irrelevant
Member #2,382
May 2002
avatar

OS/2 format seems much better to me...

IMO, all you need is:

  • width

  • height

  • col. count

  • palette (if applicable)

  • the bitmap itself

...not all that garb you had there.

Oh well, trust Micro$isth to make everything it touches bloated and hard to use. ::)

<code>//----------------//</code>Here be l33tsp33x0rz.

Korval
Member #1,538
September 2001
avatar

Quote:

Oh well, trust Micro$isth to make everything it touches bloated and hard to use.

Yeah. God forbid that they build in the possibility for expansion of the format, or, at the very least, user-defined data.

Mr. Xboxor
Member #3,763
August 2003
avatar

I'm going to have to agree. Microsoft's bmp format is very expansive. I mean, Microsoft was clearly looking forward to the future when they allowed the format to stored pictures with 65535 planes in 65535 bit color. And you though 32bit color was enough?

On a more serious note, I'm having some problems with 24bit bitmaps. I fixed my earlier problem, but this is for some weird reason. This one picture, and allegro logo, actually, always screws up when I try to convert it to use my colors. So, I deleted the entire picture, so it was just white, and it still messed up. Yet, when I created a new bmp the same size and all white, it worked just fine. Oh well, I guess I just won't use that logo. Even when I pasted it into another file, it screwed up the new file, which worked fine until I placed the logo in it. Does this mean Allegro sucks so much that it screws stuff up?

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

spellcaster
Member #1,493
September 2001
avatar

Quote:

Does this mean Allegro sucks so much that it screws stuff up?

Almost. That means that the problem is sitting in front of the computer you're using.
Replace user, then hit any key to continue.

EDIT:
I gave it another thought and came to the conclusion that you're right. It sucks. You should not waste your time with it.

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Mr. Xboxor
Member #3,763
August 2003
avatar

Umm, okay. I just find it odd how the picture of allegro is messing up any file I put it in, even when I delete the picture from the file afterwards. Oh well.

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

spellcaster
Member #1,493
September 2001
avatar

That's part of the voodoo magic.

Just because I'm curious... let's assume that you run that program, passing the path to the image as a parameter... is it still messed up?

1#include <allegro.h>
2 
3int main(int argc, char** argv) {
4 
5 BITMAP *bmp;
6 
7 if (argc !=2) {
8 allegro_message("Pass the name of the image as param!");
9 exit(0);
10 }
11 
12 allegro_init();
13 set_color_depth(24);
14 bmp = load_bitmap(argv[1], NULL);
15 set_gfx_mode(GFX_AUTODETECT_WINDOWED, bmp->w, bmp->h, 0, 0);
16 
17 install_keyboard();
18 while (!key[KEY_ESC]) {
19 blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h);
20 }
21 destroy_bitmap(bmp);
22}
23END_OF_MAIN()

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Mr. Xboxor
Member #3,763
August 2003
avatar

Sorry, I don't think I was clear enough. The programs I used to convert the bitmaps were written for 16bit realmode dos, they don't use allegro. And it isn't allegro's fault that the image doesn't look right, as the error is in paint too. Actually, I'm guessing its something with my code. I have no idea what, it's just one of those strange errors caused by something you would think would have no effect on it. I did notice that after converting the bitmap to integers that my file contained 2 more 0's in a certain spot than before the file was converted. Weirdly, though, I counted up all of the 0's, and there weren't enough for the image in either file. I don't think that will make any since to you, but it makes sense to me.

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

spellcaster
Member #1,493
September 2001
avatar

Ok, that raises the question why you're not using allegro to convert the bitmaps?

--
There are no stupid questions, but there are a lot of inquisitive idiots.

23yrold3yrold
Member #1,134
March 2001
avatar

I don't know if this is relevant, but something worth noting is that the bitmap format pads the lines of pixel data in 24bpp so one line is always a multiple of 4 bytes in length. So if your bitmap is 15 pixels wide, and each color requires 3 bytes to store in 24bpp, that's 45 bytes per line. The bitmap format requires that be padded to 48 bytes per line (next multiple of 4). If you're not aware of/compensating for that when loading/saving 24bpp images, it'll mess up any image that isn't a multiple of 4 in width (those images will require no padding).

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Mr. Xboxor
Member #3,763
August 2003
avatar

Yes, I know about the padding thing. That's not the reason, unless my calculations for how many blank bytes to put at the end of a line are incorrect.

"Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny

Korval
Member #1,538
September 2001
avatar

Doesn't the bitmap format, also, require that each 24-bit entry have an addition 8-bits (used for nothing), to pad each entry out to 32-bits? Or does it actually support packed 24-bit textures?

23yrold3yrold
Member #1,134
March 2001
avatar

Packed. Otherwise the aforementioned padding would be pointless :)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Go to: