xref: /haiku/src/tools/translation/tgainfo/tgainfo.cpp (revision e8e6c3e8add38406e0cc4e7110032a253a80f054)
1 /*****************************************************************************/
2 // tgainfo
3 // Written by Michael Wilber, OBOS Translation Kit Team
4 //
5 // Version:
6 //
7 // tgainfo is a command line program for displaying information about
8 // TGA images.
9 //
10 //
11 // This application and all source files used in its construction, except
12 // where noted, are licensed under the MIT License, and have been written
13 // and are:
14 //
15 // Copyright (c) 2003 OpenBeOS Project
16 //
17 // Permission is hereby granted, free of charge, to any person obtaining a
18 // copy of this software and associated documentation files (the "Software"),
19 // to deal in the Software without restriction, including without limitation
20 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
21 // and/or sell copies of the Software, and to permit persons to whom the
22 // Software is furnished to do so, subject to the following conditions:
23 //
24 // The above copyright notice and this permission notice shall be included
25 // in all copies or substantial portions of the Software.
26 //
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 // DEALINGS IN THE SOFTWARE.
34 /*****************************************************************************/
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ByteOrder.h>
39 #include <File.h>
40 #include <TranslatorFormats.h>
41 
42 #define max(x,y) ((x > y) ? x : y)
43 #define DATA_BUFFER_SIZE 64
44 
45 struct TGAFileHeader {
46 	uint8 idlength;
47 		// Number of bytes in the Image ID field
48 	uint8 colormaptype;
49 	uint8 imagetype;
50 };
51 
52 #define TGA_NO_COLORMAP			0
53 #define TGA_COLORMAP			1
54 
55 #define TGA_NO_IMAGE_DATA		0
56 
57 #define TGA_NOCOMP_COLORMAP		1
58 #define TGA_NOCOMP_TRUECOLOR	2
59 #define TGA_NOCOMP_BW			3
60 #define TGA_RLE_COLORMAP		9
61 #define TGA_RLE_TRUECOLOR		10
62 #define TGA_RLE_BW				11
63 
64 // Information about the color map (palette). These bytes are
65 // always present, but are zero if no color map is present
66 struct TGAColorMapSpec {
67 	uint16 firstentry;		// first useful entry in the color map
68 	uint16 length;			// number of color map entries
69 	uint8 entrysize;		// number of bits per entry
70 };
71 
72 struct TGAImageSpec {
73 	uint16 xorigin;
74 	uint16 yorigin;
75 	uint16 width;
76 	uint16 height;
77 	uint8 depth;
78 	uint8 descriptor;
79 };
80 
81 #define TGA_ORIGIN_VERT_BIT	0x20
82 #define TGA_ORIGIN_BOTTOM	0
83 #define TGA_ORIGIN_TOP		1
84 
85 #define TGA_ORIGIN_HORZ_BIT	0x10
86 #define TGA_ORIGIN_LEFT		0
87 #define TGA_ORIGIN_RIGHT	1
88 
89 #define TGA_DESC_BITS76		0xc0
90 #define TGA_DESC_ALPHABITS	0x0f
91 
92 #define TGA_HEADERS_SIZE 18
93 #define TGA_FTR_LEN 26
94 
95 const char *
96 colormaptype(uint8 n)
97 {
98 	switch (n) {
99 		case 0: return "No colormap";
100 		case 1: return "colormap";
101 	}
102 	return "unknown";
103 }
104 
105 const char *
106 imagetype(uint8 n)
107 {
108 	switch (n) {
109 		case 0:  return "No Image Data";
110 		case 1:  return "colormap";
111 		case 2:  return "true color";
112 		case 3:  return "grayscale";
113 		case 9:  return "RLE colormap";
114 		case 10: return "RLE true color";
115 		case 11: return "RLE grayscale";
116 	}
117 	return "unknown";
118 }
119 
120 void
121 print_tga_info(BFile &file)
122 {
123 	uint8 buf[TGA_HEADERS_SIZE];
124 
125 	// read in TGA headers
126 	ssize_t size = TGA_HEADERS_SIZE;
127 	if (size > 0 && file.Read(buf, size) != size) {
128 		printf("Error: unable to read all TGA headers\n");
129 		return;
130 	}
131 
132 	// TGA file header
133 	TGAFileHeader fh;
134 	fh.idlength = buf[0];
135 	fh.colormaptype = buf[1];
136 	fh.imagetype = buf[2];
137 
138 	printf("\nFile Header:\n");
139 	printf("    id length: %d\n", fh.idlength);
140 
141 	printf("colormap type: %d (%s)\n", fh.colormaptype,
142 		colormaptype(fh.colormaptype));
143 	printf("   image type: %d (%s)\n", fh.imagetype, imagetype(fh.imagetype));
144 
145 
146 	// TGA color map spec
147 	TGAColorMapSpec mapspec;
148 	memcpy(&mapspec.firstentry, buf + 3, 2);
149 	mapspec.firstentry = B_LENDIAN_TO_HOST_INT16(mapspec.firstentry);
150 	memcpy(&mapspec.length, buf + 5, 2);
151 	mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length);
152 	mapspec.entrysize = buf[7];
153 
154 	printf("\nColormap Spec:\n");
155 	printf("first entry: %d\n", mapspec.firstentry);
156 	printf("     length: %d\n", mapspec.length);
157 	printf(" entry size: %d\n", mapspec.entrysize);
158 
159 
160 	// TGA image spec
161 	TGAImageSpec imagespec;
162 	memcpy(&imagespec.xorigin, buf + 8, 2);
163 	imagespec.xorigin = B_LENDIAN_TO_HOST_INT16(imagespec.xorigin);
164 
165 	memcpy(&imagespec.yorigin, buf + 10, 2);
166 	imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin);
167 
168 	memcpy(&imagespec.width, buf + 12, 2);
169 	imagespec.width = B_LENDIAN_TO_HOST_INT16(imagespec.width);
170 
171 	memcpy(&imagespec.height, buf + 14, 2);
172 	imagespec.height = B_LENDIAN_TO_HOST_INT16(imagespec.height);
173 
174 	imagespec.depth = buf[16];
175 	imagespec.descriptor = buf[17];
176 
177 	printf("\nImage Spec:\n");
178 	printf("  x origin: %d\n", imagespec.xorigin);
179 	printf("  y origin: %d\n", imagespec.yorigin);
180 	printf("     width: %d\n", imagespec.width);
181 	printf("    height: %d\n", imagespec.height);
182 	printf("     depth: %d\n", imagespec.depth);
183 	printf("descriptor: 0x%.2lx\n", imagespec.descriptor);
184 		printf("\talpha (attr): %d\n",
185 			imagespec.descriptor & TGA_DESC_ALPHABITS);
186 		printf("\t      origin: %d (%s %s)\n",
187 			imagespec.descriptor & (TGA_ORIGIN_VERT_BIT | TGA_ORIGIN_HORZ_BIT),
188 			((imagespec.descriptor & TGA_ORIGIN_VERT_BIT) ? "top" : "bottom"),
189 			((imagespec.descriptor & TGA_ORIGIN_HORZ_BIT) ? "right" : "left"));
190 		printf("\t  bits 7 & 6: %d\n", imagespec.descriptor & TGA_DESC_BITS76);
191 
192 
193 	// Optional TGA Footer
194 	off_t filesize = 0;
195 	if (file.GetSize(&filesize) == B_OK) {
196 
197 		char tgafooter[TGA_FTR_LEN + 1] = { 0 };
198 		if (file.ReadAt(filesize - TGA_FTR_LEN, tgafooter, TGA_FTR_LEN) == TGA_FTR_LEN) {
199 
200 			if (strcmp(tgafooter + 8, "TRUEVISION-XFILE.") == 0) {
201 
202 				uint32 extoffset = 0, devoffset = 0;
203 				memcpy(&extoffset, tgafooter, 4);
204 				memcpy(&devoffset, tgafooter + 4, 4);
205 				extoffset = B_LENDIAN_TO_HOST_INT32(extoffset);
206 				devoffset = B_LENDIAN_TO_HOST_INT32(devoffset);
207 
208 				printf("\nTGA Footer:\n");
209 				printf("extension offset: 0x%.8lx (%d)\n", extoffset, extoffset);
210 				printf("developer offset: 0x%.8lx (%d)\n", devoffset, devoffset);
211 				printf("signature: %s\n", tgafooter + 8);
212 
213 			} else
214 				printf("\nTGA footer not found\n");
215 
216 		} else
217 			printf("\nError: Unable to read TGA footer section\n");
218 
219 	} else
220 		printf("\nError: Unable to get file size\n");
221 }
222 
223 int
224 main(int argc, char **argv)
225 {
226 	printf("\n");
227 
228 	if (argc == 2) {
229 		BFile file(argv[1], B_READ_ONLY);
230 		if (file.InitCheck() != B_OK)
231 			printf("Error opening %s\n", argv[1]);
232 		else {
233 			printf("TGA image information for: %s\n", argv[1]);
234 			print_tga_info(file);
235 		}
236 	}
237 	else {
238 		printf("tgainfo - reports information about a TGA image file\n");
239 		printf("\nUsage:\n");
240 		printf("tgainfo filename.tga\n");
241 	}
242 
243 	printf("\n");
244 
245 	return 0;
246 }
247 
248