I'm trying to read a TGA header of the file I created in Paint.net. It seems that there is something wrong with it. If I use the header structure from the specification, like this one:
typedef struct {
CHAR idlength;
CHAR colourmaptype;
CHAR datatypecode;
WORD colourmaporigin;
WORD colourmaplength;
CHAR colourmapdepth;
WORD x_origin;
WORD y_origin;
WORD width;
WORD height;
CHAR bitsperpixel;
CHAR imagedescriptor;
} TGAHEADER;
I get this:
Data size: 0
Color Map type: 0
Data Type code: 2
Bits per-pixel: 0
Size: 501 x 2080
Which is wrong, since my image is 501x501, 32-bits per pixel. However, if I comment out two bytes from the structure, f.e. this one colourmaporigin
, I get this:
Data size: 0
Color Map type: 0
Data Type code: 2
Bits per-pixel: 32
Size: 501 x 501
Which is correct. I was reading everything I found on this file format. It never says that any of those fields are optional or something.
How come I get results like this?
Here's the code for reading the data:
void Image::readTGA()
{
TGAHEADER fileHeader;
std::ifstream fileHandle(fileName, std::ios::binary);
if (fileHandle.is_open())
{
fileHandle.read((char*)(&fileHeader), sizeof(TGAHEADER));
fileHandle.close();
}
else
{
std::cout << "An error occured when opening a file." << std::endl;
}
}
I'm using VS2015, targeting x86 platform.
It's a padding issue. With Visual Studio you can use the #pragma pack(1)
compiler directive disable any padding of structures.
Demonstration
#include<stdio.h>
#include<windows.h>
// Default packing of structure with padding
typedef struct {
CHAR idlength;
CHAR colourmaptype;
CHAR datatypecode;
WORD colourmaporigin;
WORD colourmaplength;
CHAR colourmapdepth;
WORD x_origin;
WORD y_origin;
WORD width;
WORD height;
CHAR bitsperpixel;
CHAR imagedescriptor;
} TGAHEADER;
#pragma pack(1) // structure fields are aligned to byte boundary (no padding)
typedef struct {
CHAR idlength;
CHAR colourmaptype;
CHAR datatypecode;
WORD colourmaporigin;
WORD colourmaplength;
CHAR colourmapdepth;
WORD x_origin;
WORD y_origin;
WORD width;
WORD height;
CHAR bitsperpixel;
CHAR imagedescriptor;
} TGAHEADER_PACKED;
int main()
{
printf("Offset of field bitsperpixel in TGAHEADER structure %d\n", offsetof(TGAHEADER, bitsperpixel));
printf("Offset of field bitsperpixel in packed TGAHEADER structure %d\n", offsetof(TGAHEADER_PACKED, bitsperpixel));
}
Output:
Offset of field bitsperpixel in TGAHEADER structure 18
Offset of field bitsperpixel in packed TGAHEADER structure 16