Sign in to follow this  
silvia_steven_2000

TGA Loader : Where did the WORD go ?

Recommended Posts

I am trying to load a tga image fle, I have the header struct below: struct TargaHeader { unsigned char id; unsigned char colorMapType; unsigned char imageType; unsigned short colorMapStart; unsigned short colorMapLength; unsigned char colorMapDepth; unsigned short xOffset; nsigned short yOffset; unsigned short width; unsigned short height; nsigned char pixelDepth; unsigned char imageDescriptor; }; load the header: void* buf = malloc(sizeof(rend::TargaHeader)); Read(buf, sizeof(rend::TargaHeader), 1); when I execute the above, the header gets loaded ok, if u check the memory dump it should be like: 01 00 0a 00 00 00 00 00 00 00 00 00 f6 06 f6 06 18 20 00 82 //extra two bytes I am wondering why VC++ evaluates sizeof(rend::TargaHeader) = 20 instead of 18 ?! but this is not my problem, I could live with that but I appreciate it if some one has an idea why 20 instead of 18, my problem is below: if I read the header directly into the header structue , I get the memory dump shown below, this is very weird : Read((void*)&m_tgaHeader, sizeof(rend::TargaHeader), 1); 01 00 0a 00 00 00 00 00 00 00 f6 06 f6 06 18 20 00 82 the 11th byte which is yOffset is not there ? thanks for any idea that might help

Share this post


Link to post
Share on other sites
What is happening is the struct is being padded by the compiler to fit on a particular alignment (in this case, an extra 2 bytes - from 18 to 20).

You'll have to use #pragma pack to ensure that you have the correct alignment and padding for your struct. Otherwise, you'll get all kinds of not-nice problems.

Loading and saving a struct directly is generally a "bad" idea. Unless you really know what you're doing and know how to get the correct padding and such, then I'd stay away from it.

Also, your code is not portable between different endians. The format specificly specifies each byte as being high or low. You really shouldn't implicitly expect the data to land on the correct place in your struct, even with the correct padding. While it "should" work on an Intel system (once you get the padding fixed), it will die a painful death on a Mac.

I highly recomend you go and look at NeHe's TGA loading tutorial for some much safer code.

Share this post


Link to post
Share on other sites
It's actually the shorts causing the problem. They have to be padded to an even byte. The first short follows three chars - three bytes - so it has to skip a byte before the short. Later, there is a single char surounded by shorts that causes the same problem. The usual solution for this sort of thing is to re-order the struct. This is obviously not an option. I've seen a lot of code that just uses a plain array of chars for this sort of thing, and interprets individual sets of bytes as different types when neccessary. I wouldn't recommend this. Your best solution would be to use a pragma to pack the struct. Just remember to turn it off after the struct.

Share this post


Link to post
Share on other sites
yeah, exactly. using pragma will solve problem on most systems. but those using inversed endian, it will choke, however, here's how it'S easily done:


#pragma pack(push,1)
struct blabla
{
};
#pragma pack(pop)


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this