Advertisement

Anyone here have experience with loading TGA files?

Started by December 10, 2000 02:57 PM
14 comments, last by Densun 24 years ago
I''m having trouble loading the header of a TGA file correctly because either the program saving the file is doing it incorrectly (I''ve tried two) or the documentation I have is outdated (I''ve looked at two, one of them the official standard). I know it''s not my code because I''ve tried two different methods of loading the header and I''ve made sure the header is exactly like the one listed in the documentation. The problem is that one of the variables is not stored in the file. I''ve printed out the values of the variables and at one undetermined point the value listed for a variable should be the value for the variable below it. I know it''s one of the color map variables that''s not stored, but it should be unless the standard has changed. Can anyone here help me with this? Choose a path: path one or path two
Post your code.
Advertisement
I hope you can read the small font ;P

/******************Includes******************/#include "stdio.h"/******************Data types******************/typedef struct targaheader_s{	unsigned char idlength;  /* The number of bytes in imageid. 0 means nothing is stored. */	unsigned char cmaptype;  /* If a color map has been stored and what type it is. */	unsigned char imagetype; /* What kind of image data is stored. */	/* Color map variables. */	unsigned short firstentry; /* Index of the first color map entry. */	unsigned short cmaplength; /* Number of color map entries stored. */	unsigned char  entrysize;  /* The number of bits per entry. */	/* Image specification variables. */	unsigned short xorigin;    /* X position on screen from lower left corner. */	unsigned short yorigin;    /* Y position on screen from lower left corner. */	unsigned short width;      /* Width of the image. */	unsigned short height;     /* Height of the image. */	unsigned char  bpp;        /* Bits per pixel (pixel depth). */	unsigned char  descriptor; /* Information on the pixels. */} targaheader_t;/******************Prototypes******************/int LoadTGA (char* filename, targaheader_t* tga);/******************Functions******************/int main (void){	targaheader_t test;	if (!LoadTGA ("test.tga", &test))	{		puts ("Error loading TGA file.");		return 0;	}	printf ("ID Length: %d\n", test.idlength);	printf ("Color map type: %d\n", test.cmaptype);	printf ("Image type: %d\n", test.imagetype);	printf ("First entry index: %d\n", test.firstentry);	printf ("Color map length: %d\n", test.cmaplength);	printf ("Entry size: %d\n", test.entrysize);	printf ("X origin: %d\n", test.xorigin);	printf ("Y origin: %d\n", test.yorigin);	printf ("Width: %d\n", test.width);	printf ("Height: %d\n", test.height);	printf ("BPP: %d\n", test.bpp);	printf ("Descriptor: %d\n", test.descriptor);	return 0;}int LoadTGA (char* filename, targaheader_t* tga){	FILE* fp;	fp = fopen (filename, "rb");	if (fp == NULL)		return 0;	fread (tga, sizeof (targaheader_t), 1, fp);	fclose (fp);	return 1;}  


Choose a path:
path one or path two

Edited by - Densun on December 10, 2000 8:25:05 PM
Check the the DX 7.0 SDK framework code. It has code to loading different
formats of encoded .tga files. Or visit wotsit.org for file formats.
wotsit.org is where I got the documents for it. I''ll look into the DirectX code, though.

Choose a path:
path one or path two
fread (tga, sizeof (targaheader_t), 1, fp);

This line is probably the problem. It''s dangerous to read into a struct like that because your compiler may add padding. Try reading in each field one at a time.
Advertisement
Probably the easiest way would be to use someone else''s code that has already done it, I grabbed the .tga loading code from the Quake 1 source myself

But I think your problem is the way you are reading the header in, in that you are reading the whole header at once into your targaheader_t structure. I don''t think this will work because of the byte alignment of the char''s and shorts. Basically, the char''s are 1 byte, the shorts are 2, but the header has 3 char''s and then a short. The short has to be aligned on a 2 byte boundary, so a wasted byte is used in the structure after the 3rd char. But when the .tga file is written, it doesn''t put that wasted byte in, it keeps it compact, so all of your data comes out misaligned. Kinda like this:

The file:
(char) (char) (char) (short-short)

The structure:
(char) (char) (char) (wasted) (short-short)

As you can see, when the (short-short) from the file is placed in the structure, and then you go to access the short value, you really are only getting the last byte of the short from the file.

So what this all means is you need to read in each field of the struct individually. It''s a pain, but I think it''s about the only way to do it (at least that''s what I''ve always seen). You can''t just do an:

fread (tga, sizeof (targaheader_t), 1, fp);

You have to do a:

fread (tga->idlength, sizeof(char), 1, fp);
fread (tga->cmaptype, sizeof(char), 1, fp);
fread (tga->imagetype, sizeof(char), 1, fp);
fread (tga->firstentry, sizeof(short), 1, fp);
etc. . . .

Hope I didn''t say something wrong there, but I believe it''s all correct. Good Luck
I had originally thought fread might be the problem, but I tried another method which gave the same results. Here's what I tried:

	temp = (unsigned char*)tga;	for (int n = 0; n < sizeof (targaheader_t); n++)		temp[n] = fgetc (fp);  


I also tried what Anonymous Poster suggested, but I got some "Variables are not of type void*" error. I then casted them as void* but the program crashed when I ran it. It could be because I'm forcing the compiler to use ANSI C only.

Choose a path:
path one or path two

Edited by - Densun on December 10, 2000 11:30:07 PM
Try something like this:

  typdef unsigned char uchar;struct TGA_HEADER{	uchar ID_Length;	uchar Color_MapType;	uchar Image_Type;	uchar Color_Map[5];	uchar X_Origin[2];	uchar Y_Origin[2];	uchar Width[2];	uchar Height[2];	uchar Pixel_Depth;	uchar Image_Desc;};int main(){        FILE * fileHandle;	TGA_HEADER tgaHead;	memset((void*)&tgaHead, 0, sizeof(TGA_HEADER));	fileHandle = fopen("check1.tga", "rb");	if(!fileHandle)	{		cout << "Unable to open TGA file." << endl;		return 0;	}	if(fread((void *)&tgaHead, sizeof(TGA_HEADER), 1, fileHandle) != 1)	{		cout << "Error occured while reading header file..." << endl;		fclose(fileHandle)		return 0;	}		//Reverse byte ordering...	int width = tgaHead.Width[1] * 256 + tgaHead.Width[0];	int height = tgaHead.Height[1] * 256 + tgaHead.Height[0];	int bpp = (int)tgaHead.Pixel_Depth;          //If you really actually need this....	int x_ori = tgaHead.X_Origin[1] * 256 + tgaHead.X_Origin[0];	int y_ori = tgaHead.Y_Origin[1] * 256 + tgaHead.Y_Origin[0];	cout << "ID_LENGTH: " << (int)tgaHead.ID_Length << endl;	cout << "COLOR_MAPTYPE: " << (int)tgaHead.Color_MapType << endl;	cout << "IMAGE_TYPE: " << (int)tgaHead.Image_Type << endl;           //I didn''t want any info about color_map data...	cout << "Skip Color_Map Data" << endl;	cout << "X_ORIGIN: " << x_ori << endl;	cout << "Y_ORIGIN: " << y_ori << endl;	cout << "WIDTH: " << width << endl;	cout << "HEIGHT: " << height << endl;	cout << "PIXEL DEPTH: " << bpp << endl;	cout << "IMAGE DESC: " << (int)tgaHead.Image_Desc << endl;       fclose(fileHandle);  



I know this worked on a TGA from Adobe Photoshop 5.0... Hope it helps you out some...

-mihkael
quote: fread (tga, sizeof (targaheader_t), 1, fp);

This line is probably the problem. It''s dangerous to read into a struct like that because your compiler may add padding. Try reading in each field one at a time.



If your using VC++, bingo. This is exactly what happened to me.
Try this:

#pragma pack(1)
//struct defenition here
#pragma pack

If your using VC++, all your woes shall dissappear (unless another bug in there), if your not using VC++, all I can say is "Hmmm - Try looking in the docs for anything similar."

Hope this helped.


IO_FissionSig();

This topic is closed to new replies.

Advertisement