![]() |
|
Storing (16, 24, 32)bpp bitmaps in binary files. |
Paul whoknows
Member #5,081
September 2004
![]() |
Due to the complexity of my game I have decided to create my own file format for graphic data storage. typedef struct { int frame_number; char bytes[10000]; /* How many bytes do I need to store a single pixel in 16bpp? */ }my_frame;
I want to LEARN how to deal whit this, so detailed explanation, theory, and/or links will be accepted! thanks! ____ "The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner. |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
I don't have one with me, but I use typedef struct { int width; //pixels, not bytes per line int height; int color_depth; //in bytes, not bits per pixel int rgba; //set to 1 for rgba (when color_depth == 4) or 0 for bgra int version; //very helpful when you change this struct! }TEXHEADER; so size of image data is width*height*color_depth. You could also have another int for how many bytes past TEXHEADER the actual pixel data starts to make room for variable sized comment strings or something. I just seen you want 5 frames, maybe add yet another int for how many times the pixel data is repeated? [EDIT] I just remembered that the color_depth doesn't discriminate between 15/16 bits per pixel, but I don't use 15, or 8 for that matter. They all watch too much MSNBC... they get ideas. |
Paul whoknows
Member #5,081
September 2004
![]() |
Thanks very much! typedef struct { int width; //pixels, not bytes per line int height; int color_depth; //in bytes, not bits per pixel int rgba; //set to 1 for rgba (when color_depth == 4) or 0 for bgra int version; //very helpful when you change this struct! int frames; //amount of frames }TEXHEADER;
So the header should look like this: I don't understand the rgba flag, what's the diference between bgra or rgba? ____ "The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner. |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
Assuming for OpenGL: rgba vs. bgra is the order the red, blue, green values are stored, Windows uses bgr and I've read on an Nvidia page that they've optimized bgr as opposed to rgb due to Windows. Some older cards may not handle the bgr order, check the flags. If you're worried about porting to other cpu's, you could either store/load the bytes individually or (probably faster) swap them around after loading from disk. I haven't had a big-endian computer (well, Motorola 8 bit doesn't have an endianness) but union { int a; char b[4]; }endian; int is_small_endian = 0; endian.a = 1; is_small_endian = endian.b[3]; //little endian would set b[0]
They all watch too much MSNBC... they get ideas. |
ImLeftFooted
Member #3,935
October 2003
![]() |
#define POST_PACKED __attribute__((packed)) struct TEXHEADER { int32_t width; //pixels, not bytes per line int32_t height; int32_t color_depth; //in bytes, not bits per pixel int32_t rgba; //set to 1 for rgba (when color_depth == 4) or 0 for bgra int32_t version; //very helpful when you change this struct! int32_t frames; //amount of frames } POST_PACKED; Now you're rollin. |
orz
Member #565
August 2000
|
That doesn't actually change the size of the struct in question (try a sizeof on it both ways, on any platform gcc supports today), and it breaks compatibility with some compilers. edit: okay, I'm just whining pointlessly; the #define could be #ifdefed to something equivalent on another compiler to improve compatibility, and while packing it doesn't change this particular struct, it is vaguely appropriate for structs corresponding to formats on disk. |
Paul whoknows
Member #5,081
September 2004
![]() |
Quote:
union { int a; char b[4]; }endian;
That's amazing! really useful, thanks! Quote: #define POST_PACKED __attribute__((packed))
Dustin I don't know what are you doing here, please can you comment it? typedef struct { /* width */ char width[4]; char height[4]; . . . and so on EDITED!!! ____ "The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner. |
ImLeftFooted
Member #3,935
October 2003
![]() |
Quote:
Dustin I don't know what are you doing here, please can you comment it? If you're going to be accessing the data of a struct manually, then specify the packed option. Don't do it and the god of coding karma will strike you down. You might as well just use the struct name, unless you're trying to conform to an old C standard. typedef went out of style decades ago. Different sized ints are always a problem. |
Paul whoknows
Member #5,081
September 2004
![]() |
Quote: if you're going to be accessing the data of a struct manually, then specify the packed option. Don't do it and the god of coding karma will strike you down. The keyword _attribute_ doesn't exist in my Borland 5.0 compiler! is that ANSI C supported? Quote: You might as well just use the struct name, unless you're trying to conform to an old C standard. Like I said at the beginning of this post I am using C. ____ "The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner. |
orz
Member #565
August 2000
|
Quote: The keyword _attribute_ doesn't exist in my Borland 5.0 compiler! is that ANSI C supported? It's gcc-only. There are equivalents in most compilers though. I don't know about Borland. Try looking up "packing" or "alignment", or anything about controlling the actual layout of structure members in memory in any docs you have. |
Ron Ofir
Member #2,357
May 2002
![]() |
Isn't packing only relevant when you directly write the struct to disk? I thikn it's better to simply write the fields one after another insteda of all of them at the same time. |
orz
Member #565
August 2000
|
Quote: Isn't packing only relevant when you directly write the struct to disk? Pretty much. It can effect the size of the struct in memory as well, but that's not usually important. Quote: I thikn it's better to simply write the fields one after another insteda of all of them at the same time. Some people find it easier to code / maintain / examine / debug / etc to let that happen automatically in a single fwrite call or whatever. |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Quote: Some people find it easier to code / maintain / examine / debug / etc to let that happen automatically in a single fwrite call or whatever. And now you have endian dependant files. Not as important as it once was, but if you ever want those images to load properly on a BigEndian machine, never write the struct directly. -- |
orz
Member #565
August 2000
|
Quote: And now you have endian dependant files. Not as important as it once was, but if you ever want those images to load properly on a BigEndian machine, never write the struct directly. Some people use the structs with endian-independant integer types (ie plain ints on one endianness, #ifdefed to classes that emulate non-native endiannes ints on the other endianness). Not a very popular practice admittedly, but I know a few. |
Thomas Fjellstrom
Member #476
June 2000
![]() |
The "best" (IMO) method is just to store and read the ints in a single endian, and convert to the proper endian on load (if needed). for example, you can use: // set 1 pack_igetw(); pack_iputw(); // 16 bit pack_igetl(); pack_iputl(); // 32 bit // set 2 pack_mgetw(); pack_mputw(); pack_mgetl(); pack_mputl(); Use one or the other, and your ints will be properly saved and loaded, without having to worry about endianess. -- |
|