1 /*****************************************************************************/
3 // Written by Michael Wilber, OBOS Translation Kit Team
7 // tgainfo is a command line program for displaying information about
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
15 // Copyright (c) 2003 OpenBeOS Project
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:
24 // The above copyright notice and this permission notice shall be included
25 // in all copies or substantial portions of the Software.
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 /*****************************************************************************/
38 #include <ByteOrder.h>
41 #include <TranslatorFormats.h>
42 #include <StorageDefs.h>
44 #undef B_TRANSLATE_CONTEXT
45 #define B_TRANSLATE_CONTEXT "tgainfo"
47 #define max(x,y) ((x > y) ? x : y)
48 #define DATA_BUFFER_SIZE 64
50 struct TGAFileHeader
{
52 // Number of bytes in the Image ID field
57 #define TGA_NO_COLORMAP 0
58 #define TGA_COLORMAP 1
60 #define TGA_NO_IMAGE_DATA 0
62 #define TGA_NOCOMP_COLORMAP 1
63 #define TGA_NOCOMP_TRUECOLOR 2
64 #define TGA_NOCOMP_BW 3
65 #define TGA_RLE_COLORMAP 9
66 #define TGA_RLE_TRUECOLOR 10
69 // Information about the color map (palette). These bytes are
70 // always present, but are zero if no color map is present
71 struct TGAColorMapSpec
{
72 uint16 firstentry
; // first useful entry in the color map
73 uint16 length
; // number of color map entries
74 uint8 entrysize
; // number of bits per entry
86 #define TGA_ORIGIN_VERT_BIT 0x20
87 #define TGA_ORIGIN_BOTTOM 0
88 #define TGA_ORIGIN_TOP 1
90 #define TGA_ORIGIN_HORZ_BIT 0x10
91 #define TGA_ORIGIN_LEFT 0
92 #define TGA_ORIGIN_RIGHT 1
94 #define TGA_DESC_BITS76 0xc0
95 #define TGA_DESC_ALPHABITS 0x0f
97 #define TGA_HEADERS_SIZE 18
98 #define TGA_FTR_LEN 26
99 #define TGA_EXT_LEN 495
103 colormaptype(uint8 n
)
106 case 0: return B_TRANSLATE("No colormap");
107 case 1: return B_TRANSLATE("colormap");
116 case 0: return B_TRANSLATE("No Image Data");
117 case 1: return B_TRANSLATE("colormap");
118 case 2: return B_TRANSLATE("true color");
119 case 3: return B_TRANSLATE("grayscale");
120 case 9: return B_TRANSLATE("RLE colormap");
121 case 10: return B_TRANSLATE("RLE true color");
122 case 11: return B_TRANSLATE("RLE grayscale");
125 return B_TRANSLATE("unknown");
129 tga_uint16(char *buffer
, int32 offset
)
131 return B_LENDIAN_TO_HOST_INT16(*(reinterpret_cast<uint16
*>(buffer
+ offset
)));
135 tga_uint32(char *buffer
, int32 offset
)
137 return B_LENDIAN_TO_HOST_INT32(*(reinterpret_cast<uint32
*>(buffer
+ offset
)));
141 print_tga_info(BFile
&file
)
143 uint8 buf
[TGA_HEADERS_SIZE
];
145 // read in TGA headers
146 ssize_t size
= TGA_HEADERS_SIZE
;
147 if (size
> 0 && file
.Read(buf
, size
) != size
) {
148 printf(B_TRANSLATE("Error: unable to read all TGA headers\n"));
154 fh
.idlength
= buf
[0];
155 fh
.colormaptype
= buf
[1];
156 fh
.imagetype
= buf
[2];
158 printf(B_TRANSLATE("\nFile Header:\n"));
159 printf(B_TRANSLATE(" id length: %d\n"), static_cast<int>(fh
.idlength
));
161 printf(B_TRANSLATE("colormap type: %d (%s)\n"),
162 static_cast<int>(fh
.colormaptype
),
163 static_cast<const char *>(colormaptype(fh
.colormaptype
)));
164 printf(B_TRANSLATE(" image type: %d (%s)\n"),
165 static_cast<int>(fh
.imagetype
),
166 static_cast<const char *>(imagetype(fh
.imagetype
)));
169 // TGA color map spec
170 TGAColorMapSpec mapspec
;
171 mapspec
.firstentry
= tga_uint16(reinterpret_cast<char *>(buf
), 3);
172 mapspec
.length
= tga_uint16(reinterpret_cast<char *>(buf
), 5);
173 mapspec
.entrysize
= buf
[7];
175 printf(B_TRANSLATE("\nColormap Spec:\n"));
176 printf(B_TRANSLATE("first entry: %d\n"),
177 static_cast<int>(mapspec
.firstentry
));
178 printf(B_TRANSLATE(" length: %d\n"),
179 static_cast<int>(mapspec
.length
));
180 printf(B_TRANSLATE(" entry size: %d\n"),
181 static_cast<int>(mapspec
.entrysize
));
185 TGAImageSpec imagespec
;
186 imagespec
.xorigin
= tga_uint16(reinterpret_cast<char *>(buf
), 8);
187 imagespec
.yorigin
= tga_uint16(reinterpret_cast<char *>(buf
), 10);
188 imagespec
.width
= tga_uint16(reinterpret_cast<char *>(buf
), 12);
189 imagespec
.height
= tga_uint16(reinterpret_cast<char *>(buf
), 14);
190 imagespec
.depth
= buf
[16];
191 imagespec
.descriptor
= buf
[17];
193 printf(B_TRANSLATE("\nImage Spec:\n"));
194 printf(B_TRANSLATE(" x origin: %d\n"),
195 static_cast<int>(imagespec
.xorigin
));
196 printf(B_TRANSLATE(" y origin: %d\n"),
197 static_cast<int>(imagespec
.yorigin
));
198 printf(B_TRANSLATE(" width: %d\n"),
199 static_cast<int>(imagespec
.width
));
200 printf(B_TRANSLATE(" height: %d\n"),
201 static_cast<int>(imagespec
.height
));
202 printf(B_TRANSLATE(" depth: %d\n"),
203 static_cast<int>(imagespec
.depth
));
204 printf(B_TRANSLATE("descriptor: 0x%.2x\n"),
205 static_cast<int>(imagespec
.descriptor
));
206 printf(B_TRANSLATE("\talpha (attr): %d\n"),
207 static_cast<int>(imagespec
.descriptor
& TGA_DESC_ALPHABITS
));
208 if (imagespec
.descriptor
& TGA_ORIGIN_VERT_BIT
)
209 if (imagespec
.descriptor
& TGA_ORIGIN_HORZ_BIT
)
210 printf(B_TRANSLATE("\t origin: %d (%s %s)\n"),
211 static_cast<int>(imagespec
.descriptor
& (TGA_ORIGIN_VERT_BIT
212 | TGA_ORIGIN_HORZ_BIT
)), static_cast<const char *>("top"),
213 static_cast<const char *>("right"));
215 printf(B_TRANSLATE("\t origin: %d (%s %s)\n"),
216 static_cast<int>(imagespec
.descriptor
& (TGA_ORIGIN_VERT_BIT
217 | TGA_ORIGIN_HORZ_BIT
)), static_cast<const char *>("top"),
218 static_cast<const char *>("left"));
220 if (imagespec
.descriptor
& TGA_ORIGIN_HORZ_BIT
)
221 printf(B_TRANSLATE("\t origin: %d (%s %s)\n"),
222 static_cast<int>(imagespec
.descriptor
& (TGA_ORIGIN_VERT_BIT
223 | TGA_ORIGIN_HORZ_BIT
)), static_cast<const char *>("bottom"),
224 static_cast<const char *>("right"));
226 printf(B_TRANSLATE("\t origin: %d (%s %s)\n"),
227 static_cast<int>(imagespec
.descriptor
& (TGA_ORIGIN_VERT_BIT
228 | TGA_ORIGIN_HORZ_BIT
)), static_cast<const char *>("bottom"),
229 static_cast<const char *>("left"));
232 printf(B_TRANSLATE("\t bits 7 & 6: %d\n"),
233 static_cast<int>(imagespec
.descriptor
& TGA_DESC_BITS76
));
236 // Optional TGA Footer
238 if (file
.GetSize(&filesize
) == B_OK
) {
240 char tgafooter
[TGA_FTR_LEN
+ 1] = { 0 };
241 if (file
.ReadAt(filesize
- TGA_FTR_LEN
, tgafooter
, TGA_FTR_LEN
) == TGA_FTR_LEN
) {
243 if (strcmp(tgafooter
+ 8, "TRUEVISION-XFILE.") == 0) {
245 uint32 extoffset
= 0, devoffset
= 0;
246 extoffset
= tga_uint32(tgafooter
, 0);
247 devoffset
= tga_uint32(tgafooter
, 4);
249 printf(B_TRANSLATE("\nTGA Footer:\n"));
250 printf(B_TRANSLATE("extension offset: 0x%.8lx (%ld)\n"),
251 static_cast<long int>(extoffset
),
252 static_cast<long int>(extoffset
));
253 printf(B_TRANSLATE("developer offset: 0x%.8lx (%ld)\n"),
254 static_cast<long int>(devoffset
),
255 static_cast<long int>(devoffset
));
256 printf(B_TRANSLATE("signature: %s\n"), tgafooter
+ 8);
259 char extbuf
[TGA_EXT_LEN
];
260 if (file
.ReadAt(extoffset
, extbuf
, TGA_EXT_LEN
) == TGA_EXT_LEN
) {
262 printf(B_TRANSLATE("\nExtension Area:\n"));
264 char strbuffer
[LINE_LEN
];
266 uint16 extsize
= tga_uint16(extbuf
, 0);
267 if (extsize
< TGA_EXT_LEN
) {
268 printf(B_TRANSLATE("\nError: extension "
269 "area is too small (%d)\n"), extsize
);
272 printf(B_TRANSLATE("size: %d\n"), extsize
);
274 memset(strbuffer
, 0, LINE_LEN
);
275 strncpy(strbuffer
, extbuf
+ 2, 41);
276 printf("author: \"%s\"\n", strbuffer
);
278 printf(B_TRANSLATE("comments:\n"));
279 for (int32 i
= 0; i
< 4; i
++) {
280 memset(strbuffer
, 0, LINE_LEN
);
281 strcpy(strbuffer
, extbuf
+ 43 + (i
* 81));
282 printf(B_TRANSLATE("\tline %ld: \"%s\"\n"),
283 static_cast<long int>(i
+ 1),
284 static_cast<const char *>(strbuffer
));
287 printf(B_TRANSLATE("date/time (yyyy-mm-dd hh:mm:ss): "
288 "%.4d-%.2d-%.2d %.2d:%.2d:%.2d\n"),
289 tga_uint16(extbuf
, 367), tga_uint16(extbuf
, 369),
290 tga_uint16(extbuf
, 371), tga_uint16(extbuf
, 373),
291 tga_uint16(extbuf
, 375), tga_uint16(extbuf
, 377));
293 memset(strbuffer
, 0, LINE_LEN
);
294 strncpy(strbuffer
, extbuf
+ 379, 41);
295 printf(B_TRANSLATE("job name: \"%s\"\n"), strbuffer
);
297 printf(B_TRANSLATE("job time (hh:mm:ss): "
298 "%.2d:%.2d:%.2d\n"), tga_uint16(extbuf
, 420),
299 tga_uint16(extbuf
, 422), tga_uint16(extbuf
, 424));
301 memset(strbuffer
, 0, LINE_LEN
);
302 strncpy(strbuffer
, extbuf
+ 426, 41);
303 printf(B_TRANSLATE("software id: \"%s\"\n"),
306 char strver
[] = "[null]";
307 if (extbuf
[469] != '\0') {
308 strver
[0] = extbuf
[469];
311 printf(B_TRANSLATE("software version, letter: %d, "
312 "%s\n"), tga_uint16(extbuf
, 467), strver
);
314 printf(B_TRANSLATE("key color (A,R,G,B): %d, %d, %d, "
315 "%d\n"), extbuf
[470], extbuf
[471], extbuf
[472],
318 printf(B_TRANSLATE("pixel aspect ratio: %d / %d\n"),
319 tga_uint16(extbuf
, 474), tga_uint16(extbuf
, 476));
321 printf(B_TRANSLATE("gamma value: %d / %d\n"),
322 tga_uint16(extbuf
, 478), tga_uint16(extbuf
, 480));
324 printf(B_TRANSLATE("color correction offset: 0x%.8lx "
325 "(%ld)\n"), tga_uint32(extbuf
, 482),
326 tga_uint32(extbuf
, 482));
327 printf(B_TRANSLATE("postage stamp offset: 0x%.8lx "
328 "(%ld)\n"), tga_uint32(extbuf
, 486),
329 tga_uint32(extbuf
, 486));
330 printf(B_TRANSLATE("scan line offset: 0x%.8lx "
331 "(%ld)\n"), tga_uint32(extbuf
, 490),
332 tga_uint32(extbuf
, 490));
334 const char *strattrtype
= NULL
;
335 uint8 attrtype
= extbuf
[494];
338 = B_TRANSLATE("no alpha"); break;
340 = B_TRANSLATE("undefined, ignore"); break;
342 = B_TRANSLATE("undefined, retain"); break;
344 = B_TRANSLATE("alpha"); break;
346 = B_TRANSLATE("pre-multiplied alpha"); break;
348 if (attrtype
> 4 && attrtype
< 128)
349 strattrtype
= B_TRANSLATE("reserved");
351 strattrtype
= B_TRANSLATE("unassigned");
354 printf(B_TRANSLATE("attributes type: %d (%s)\n"),
355 attrtype
, strattrtype
);
358 printf(B_TRANSLATE("\nError: Unable to read entire "
359 "extension area\n"));
363 printf(B_TRANSLATE("\nTGA footer not found\n"));
366 printf(B_TRANSLATE("\nError: Unable to read TGA footer "
370 printf(B_TRANSLATE("\nError: Unable to get file size\n"));
374 main(int argc
, char **argv
)
379 printf(B_TRANSLATE("tgainfo - reports information about a TGA image file\n"));
380 printf(B_TRANSLATE("\nUsage:\n"));
381 printf(B_TRANSLATE("tgainfo filename.tga\n"));
386 for (int32 i
= 1; i
< argc
; i
++) {
387 if (file
.SetTo(argv
[i
], B_READ_ONLY
) != B_OK
)
388 printf(B_TRANSLATE("\nError opening %s\n"), argv
[i
]);
390 printf(B_TRANSLATE("\nTGA image information for: %s\n"), argv
[i
]);
391 print_tga_info(file
);