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 #include <StorageDefs.h> 42 43 #define max(x,y) ((x > y) ? x : y) 44 #define DATA_BUFFER_SIZE 64 45 46 struct TGAFileHeader { 47 uint8 idlength; 48 // Number of bytes in the Image ID field 49 uint8 colormaptype; 50 uint8 imagetype; 51 }; 52 53 #define TGA_NO_COLORMAP 0 54 #define TGA_COLORMAP 1 55 56 #define TGA_NO_IMAGE_DATA 0 57 58 #define TGA_NOCOMP_COLORMAP 1 59 #define TGA_NOCOMP_TRUECOLOR 2 60 #define TGA_NOCOMP_BW 3 61 #define TGA_RLE_COLORMAP 9 62 #define TGA_RLE_TRUECOLOR 10 63 #define TGA_RLE_BW 11 64 65 // Information about the color map (palette). These bytes are 66 // always present, but are zero if no color map is present 67 struct TGAColorMapSpec { 68 uint16 firstentry; // first useful entry in the color map 69 uint16 length; // number of color map entries 70 uint8 entrysize; // number of bits per entry 71 }; 72 73 struct TGAImageSpec { 74 uint16 xorigin; 75 uint16 yorigin; 76 uint16 width; 77 uint16 height; 78 uint8 depth; 79 uint8 descriptor; 80 }; 81 82 #define TGA_ORIGIN_VERT_BIT 0x20 83 #define TGA_ORIGIN_BOTTOM 0 84 #define TGA_ORIGIN_TOP 1 85 86 #define TGA_ORIGIN_HORZ_BIT 0x10 87 #define TGA_ORIGIN_LEFT 0 88 #define TGA_ORIGIN_RIGHT 1 89 90 #define TGA_DESC_BITS76 0xc0 91 #define TGA_DESC_ALPHABITS 0x0f 92 93 #define TGA_HEADERS_SIZE 18 94 #define TGA_FTR_LEN 26 95 #define TGA_EXT_LEN 495 96 #define LINE_LEN 82 97 98 const char * 99 colormaptype(uint8 n) 100 { 101 switch (n) { 102 case 0: return "No colormap"; 103 case 1: return "colormap"; 104 } 105 return "unknown"; 106 } 107 108 const char * 109 imagetype(uint8 n) 110 { 111 switch (n) { 112 case 0: return "No Image Data"; 113 case 1: return "colormap"; 114 case 2: return "true color"; 115 case 3: return "grayscale"; 116 case 9: return "RLE colormap"; 117 case 10: return "RLE true color"; 118 case 11: return "RLE grayscale"; 119 } 120 return "unknown"; 121 } 122 123 uint16 124 tga_uint16(char *buffer, int32 offset) 125 { 126 return B_LENDIAN_TO_HOST_INT16(*(reinterpret_cast<uint16 *>(buffer + offset))); 127 } 128 129 uint32 130 tga_uint32(char *buffer, int32 offset) 131 { 132 return B_LENDIAN_TO_HOST_INT32(*(reinterpret_cast<uint32 *>(buffer + offset))); 133 } 134 135 void 136 print_tga_info(BFile &file) 137 { 138 uint8 buf[TGA_HEADERS_SIZE]; 139 140 // read in TGA headers 141 ssize_t size = TGA_HEADERS_SIZE; 142 if (size > 0 && file.Read(buf, size) != size) { 143 printf("Error: unable to read all TGA headers\n"); 144 return; 145 } 146 147 // TGA file header 148 TGAFileHeader fh; 149 fh.idlength = buf[0]; 150 fh.colormaptype = buf[1]; 151 fh.imagetype = buf[2]; 152 153 printf("\nFile Header:\n"); 154 printf(" id length: %d\n", fh.idlength); 155 156 printf("colormap type: %d (%s)\n", fh.colormaptype, 157 colormaptype(fh.colormaptype)); 158 printf(" image type: %d (%s)\n", fh.imagetype, imagetype(fh.imagetype)); 159 160 161 // TGA color map spec 162 TGAColorMapSpec mapspec; 163 mapspec.firstentry = tga_uint16(reinterpret_cast<char *>(buf), 3); 164 mapspec.length = tga_uint16(reinterpret_cast<char *>(buf), 5); 165 mapspec.entrysize = buf[7]; 166 167 printf("\nColormap Spec:\n"); 168 printf("first entry: %d\n", mapspec.firstentry); 169 printf(" length: %d\n", mapspec.length); 170 printf(" entry size: %d\n", mapspec.entrysize); 171 172 173 // TGA image spec 174 TGAImageSpec imagespec; 175 imagespec.xorigin = tga_uint16(reinterpret_cast<char *>(buf), 8); 176 imagespec.yorigin = tga_uint16(reinterpret_cast<char *>(buf), 10); 177 imagespec.width = tga_uint16(reinterpret_cast<char *>(buf), 12); 178 imagespec.height = tga_uint16(reinterpret_cast<char *>(buf), 14); 179 imagespec.depth = buf[16]; 180 imagespec.descriptor = buf[17]; 181 182 printf("\nImage Spec:\n"); 183 printf(" x origin: %d\n", imagespec.xorigin); 184 printf(" y origin: %d\n", imagespec.yorigin); 185 printf(" width: %d\n", imagespec.width); 186 printf(" height: %d\n", imagespec.height); 187 printf(" depth: %d\n", imagespec.depth); 188 printf("descriptor: 0x%.2lx\n", imagespec.descriptor); 189 printf("\talpha (attr): %d\n", 190 imagespec.descriptor & TGA_DESC_ALPHABITS); 191 printf("\t origin: %d (%s %s)\n", 192 imagespec.descriptor & (TGA_ORIGIN_VERT_BIT | TGA_ORIGIN_HORZ_BIT), 193 ((imagespec.descriptor & TGA_ORIGIN_VERT_BIT) ? "top" : "bottom"), 194 ((imagespec.descriptor & TGA_ORIGIN_HORZ_BIT) ? "right" : "left")); 195 printf("\t bits 7 & 6: %d\n", imagespec.descriptor & TGA_DESC_BITS76); 196 197 198 // Optional TGA Footer 199 off_t filesize = 0; 200 if (file.GetSize(&filesize) == B_OK) { 201 202 char tgafooter[TGA_FTR_LEN + 1] = { 0 }; 203 if (file.ReadAt(filesize - TGA_FTR_LEN, tgafooter, TGA_FTR_LEN) == TGA_FTR_LEN) { 204 205 if (strcmp(tgafooter + 8, "TRUEVISION-XFILE.") == 0) { 206 207 uint32 extoffset = 0, devoffset = 0; 208 extoffset = tga_uint32(tgafooter, 0); 209 devoffset = tga_uint32(tgafooter, 4); 210 211 printf("\nTGA Footer:\n"); 212 printf("extension offset: 0x%.8lx (%d)\n", extoffset, extoffset); 213 printf("developer offset: 0x%.8lx (%d)\n", devoffset, devoffset); 214 printf("signature: %s\n", tgafooter + 8); 215 216 if (extoffset) { 217 char extbuf[TGA_EXT_LEN]; 218 if (file.ReadAt(extoffset, extbuf, TGA_EXT_LEN) == TGA_EXT_LEN) { 219 220 printf("\nExtension Area:\n"); 221 222 char strbuffer[LINE_LEN]; 223 224 uint16 extsize = tga_uint16(extbuf, 0); 225 if (extsize < TGA_EXT_LEN) { 226 printf("\nError: extension area is too small (%d)\n", extsize); 227 return; 228 } 229 printf("size: %d\n", extsize); 230 231 memset(strbuffer, 0, LINE_LEN); 232 strncpy(strbuffer, extbuf + 2, 41); 233 printf("author: \"%s\"\n", strbuffer); 234 235 printf("comments:\n"); 236 for (int32 i = 0; i < 4; i++) { 237 memset(strbuffer, 0, LINE_LEN); 238 strcpy(strbuffer, extbuf + 43 + (i * 81)); 239 printf("\tline %d: \"%s\"\n", i + 1, strbuffer); 240 } 241 242 printf("date/time (yyyy-mm-dd hh:mm:ss): %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", 243 tga_uint16(extbuf, 367), tga_uint16(extbuf, 369), 244 tga_uint16(extbuf, 371), tga_uint16(extbuf, 373), 245 tga_uint16(extbuf, 375), tga_uint16(extbuf, 377)); 246 247 memset(strbuffer, 0, LINE_LEN); 248 strncpy(strbuffer, extbuf + 379, 41); 249 printf("job name: \"%s\"\n", strbuffer); 250 251 printf("job time (hh:mm:ss): %.2d:%.2d:%.2d\n", 252 tga_uint16(extbuf, 420), tga_uint16(extbuf, 422), 253 tga_uint16(extbuf, 424)); 254 255 memset(strbuffer, 0, LINE_LEN); 256 strncpy(strbuffer, extbuf + 426, 41); 257 printf("software id: \"%s\"\n", strbuffer); 258 259 char strver[] = "[null]"; 260 if (extbuf[469] != '\0') { 261 strver[0] = extbuf[469]; 262 strver[1] = '\0'; 263 } 264 printf("software version, letter: %d, %s\n", 265 tga_uint16(extbuf, 467), strver); 266 267 printf("key color (A,R,G,B): %d, %d, %d, %d\n", 268 extbuf[470], extbuf[471], extbuf[472], extbuf[473]); 269 270 printf("pixel aspect ratio: %d / %d\n", 271 tga_uint16(extbuf, 474), tga_uint16(extbuf, 476)); 272 273 printf("gamma value: %d / %d\n", 274 tga_uint16(extbuf, 478), tga_uint16(extbuf, 480)); 275 276 printf("color correction offset: 0x%.8lx (%d)\n", 277 tga_uint32(extbuf, 482), tga_uint32(extbuf, 482)); 278 printf("postage stamp offset: 0x%.8lx (%d)\n", 279 tga_uint32(extbuf, 486), tga_uint32(extbuf, 486)); 280 printf("scan line offset: 0x%.8lx (%d)\n", 281 tga_uint32(extbuf, 490), tga_uint32(extbuf, 490)); 282 283 const char *strattrtype = NULL; 284 uint8 attrtype = extbuf[494]; 285 switch (attrtype) { 286 case 0: strattrtype = "no alpha"; break; 287 case 1: strattrtype = "undefined, ignore"; break; 288 case 2: strattrtype = "undefined, retain"; break; 289 case 3: strattrtype = "alpha"; break; 290 case 4: strattrtype = "pre-multiplied alpha"; break; 291 default: 292 if (attrtype > 4 && attrtype < 128) 293 strattrtype = "reserved"; 294 else 295 strattrtype = "unassigned"; 296 break; 297 } 298 printf("attributes type: %d (%s)\n", attrtype, strattrtype); 299 300 } else 301 printf("\nError: Unable to read entire extension area\n"); 302 } 303 304 } else 305 printf("\nTGA footer not found\n"); 306 307 } else 308 printf("\nError: Unable to read TGA footer section\n"); 309 310 } else 311 printf("\nError: Unable to get file size\n"); 312 } 313 314 int 315 main(int argc, char **argv) 316 { 317 printf("\n"); 318 319 if (argc == 1) { 320 printf("tgainfo - reports information about a TGA image file\n"); 321 printf("\nUsage:\n"); 322 printf("tgainfo filename.tga\n"); 323 } 324 else { 325 BFile file; 326 327 for (int32 i = 1; i < argc; i++) { 328 if (file.SetTo(argv[i], B_READ_ONLY) != B_OK) 329 printf("\nError opening %s\n", argv[i]); 330 else { 331 printf("\nTGA image information for: %s\n", argv[i]); 332 print_tga_info(file); 333 } 334 } 335 336 } 337 338 printf("\n"); 339 340 return 0; 341 } 342 343