1d61900aaSMatthew Wilber /*****************************************************************************/ 2d61900aaSMatthew Wilber // tgainfo 3d61900aaSMatthew Wilber // Written by Michael Wilber, OBOS Translation Kit Team 4d61900aaSMatthew Wilber // 5d61900aaSMatthew Wilber // Version: 6d61900aaSMatthew Wilber // 7d61900aaSMatthew Wilber // tgainfo is a command line program for displaying information about 8d61900aaSMatthew Wilber // TGA images. 9d61900aaSMatthew Wilber // 10d61900aaSMatthew Wilber // 11d61900aaSMatthew Wilber // This application and all source files used in its construction, except 12d61900aaSMatthew Wilber // where noted, are licensed under the MIT License, and have been written 13d61900aaSMatthew Wilber // and are: 14d61900aaSMatthew Wilber // 15d61900aaSMatthew Wilber // Copyright (c) 2003 OpenBeOS Project 16d61900aaSMatthew Wilber // 17d61900aaSMatthew Wilber // Permission is hereby granted, free of charge, to any person obtaining a 18d61900aaSMatthew Wilber // copy of this software and associated documentation files (the "Software"), 19d61900aaSMatthew Wilber // to deal in the Software without restriction, including without limitation 20d61900aaSMatthew Wilber // the rights to use, copy, modify, merge, publish, distribute, sublicense, 21d61900aaSMatthew Wilber // and/or sell copies of the Software, and to permit persons to whom the 22d61900aaSMatthew Wilber // Software is furnished to do so, subject to the following conditions: 23d61900aaSMatthew Wilber // 24d61900aaSMatthew Wilber // The above copyright notice and this permission notice shall be included 25d61900aaSMatthew Wilber // in all copies or substantial portions of the Software. 26d61900aaSMatthew Wilber // 27d61900aaSMatthew Wilber // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28d61900aaSMatthew Wilber // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29d61900aaSMatthew Wilber // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30d61900aaSMatthew Wilber // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31d61900aaSMatthew Wilber // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32d61900aaSMatthew Wilber // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 33d61900aaSMatthew Wilber // DEALINGS IN THE SOFTWARE. 34d61900aaSMatthew Wilber /*****************************************************************************/ 35d61900aaSMatthew Wilber #include <stdio.h> 36d61900aaSMatthew Wilber #include <stdlib.h> 37d61900aaSMatthew Wilber #include <string.h> 38d61900aaSMatthew Wilber #include <ByteOrder.h> 39d61900aaSMatthew Wilber #include <File.h> 40d61900aaSMatthew Wilber #include <TranslatorFormats.h> 41d61900aaSMatthew Wilber 42d61900aaSMatthew Wilber #define max(x,y) ((x > y) ? x : y) 43d61900aaSMatthew Wilber #define DATA_BUFFER_SIZE 64 44d61900aaSMatthew Wilber 45d61900aaSMatthew Wilber struct TGAFileHeader { 46d61900aaSMatthew Wilber uint8 idlength; 47d61900aaSMatthew Wilber // Number of bytes in the Image ID field 48d61900aaSMatthew Wilber uint8 colormaptype; 49d61900aaSMatthew Wilber uint8 imagetype; 50d61900aaSMatthew Wilber }; 51d61900aaSMatthew Wilber 52d61900aaSMatthew Wilber #define TGA_NO_COLORMAP 0 53d61900aaSMatthew Wilber #define TGA_COLORMAP 1 54d61900aaSMatthew Wilber 55d61900aaSMatthew Wilber #define TGA_NO_IMAGE_DATA 0 56d61900aaSMatthew Wilber 57d61900aaSMatthew Wilber #define TGA_NOCOMP_COLORMAP 1 58d61900aaSMatthew Wilber #define TGA_NOCOMP_TRUECOLOR 2 59d61900aaSMatthew Wilber #define TGA_NOCOMP_BW 3 60d61900aaSMatthew Wilber #define TGA_RLE_COLORMAP 9 61d61900aaSMatthew Wilber #define TGA_RLE_TRUECOLOR 10 62d61900aaSMatthew Wilber #define TGA_RLE_BW 11 63d61900aaSMatthew Wilber 64d61900aaSMatthew Wilber // Information about the color map (palette). These bytes are 65d61900aaSMatthew Wilber // always present, but are zero if no color map is present 66d61900aaSMatthew Wilber struct TGAColorMapSpec { 67d61900aaSMatthew Wilber uint16 firstentry; // first useful entry in the color map 68d61900aaSMatthew Wilber uint16 length; // number of color map entries 69d61900aaSMatthew Wilber uint8 entrysize; // number of bits per entry 70d61900aaSMatthew Wilber }; 71d61900aaSMatthew Wilber 72d61900aaSMatthew Wilber struct TGAImageSpec { 73d61900aaSMatthew Wilber uint16 xorigin; 74d61900aaSMatthew Wilber uint16 yorigin; 75d61900aaSMatthew Wilber uint16 width; 76d61900aaSMatthew Wilber uint16 height; 77d61900aaSMatthew Wilber uint8 depth; 78d61900aaSMatthew Wilber uint8 descriptor; 79d61900aaSMatthew Wilber }; 80d61900aaSMatthew Wilber 81d61900aaSMatthew Wilber #define TGA_ORIGIN_VERT_BIT 0x20 82d61900aaSMatthew Wilber #define TGA_ORIGIN_BOTTOM 0 83d61900aaSMatthew Wilber #define TGA_ORIGIN_TOP 1 84d61900aaSMatthew Wilber 85d61900aaSMatthew Wilber #define TGA_ORIGIN_HORZ_BIT 0x10 86d61900aaSMatthew Wilber #define TGA_ORIGIN_LEFT 0 87d61900aaSMatthew Wilber #define TGA_ORIGIN_RIGHT 1 88d61900aaSMatthew Wilber 89d61900aaSMatthew Wilber #define TGA_DESC_BITS76 0xc0 90d61900aaSMatthew Wilber #define TGA_DESC_ALPHABITS 0x0f 91d61900aaSMatthew Wilber 92d61900aaSMatthew Wilber #define TGA_HEADERS_SIZE 18 93d61900aaSMatthew Wilber #define TGA_FTR_LEN 26 94*735e7442SMatthew Wilber #define TGA_EXT_LEN 495 95*735e7442SMatthew Wilber #define LINE_LEN 82 96d61900aaSMatthew Wilber 97d61900aaSMatthew Wilber const char * 98d61900aaSMatthew Wilber colormaptype(uint8 n) 99d61900aaSMatthew Wilber { 100d61900aaSMatthew Wilber switch (n) { 101d61900aaSMatthew Wilber case 0: return "No colormap"; 102d61900aaSMatthew Wilber case 1: return "colormap"; 103d61900aaSMatthew Wilber } 104d61900aaSMatthew Wilber return "unknown"; 105d61900aaSMatthew Wilber } 106d61900aaSMatthew Wilber 107d61900aaSMatthew Wilber const char * 108d61900aaSMatthew Wilber imagetype(uint8 n) 109d61900aaSMatthew Wilber { 110d61900aaSMatthew Wilber switch (n) { 111d61900aaSMatthew Wilber case 0: return "No Image Data"; 112d61900aaSMatthew Wilber case 1: return "colormap"; 113d61900aaSMatthew Wilber case 2: return "true color"; 114d61900aaSMatthew Wilber case 3: return "grayscale"; 115d61900aaSMatthew Wilber case 9: return "RLE colormap"; 116d61900aaSMatthew Wilber case 10: return "RLE true color"; 117d61900aaSMatthew Wilber case 11: return "RLE grayscale"; 118d61900aaSMatthew Wilber } 119d61900aaSMatthew Wilber return "unknown"; 120d61900aaSMatthew Wilber } 121d61900aaSMatthew Wilber 122*735e7442SMatthew Wilber uint16 123*735e7442SMatthew Wilber tga_uint16(char *buffer, int32 offset) 124*735e7442SMatthew Wilber { 125*735e7442SMatthew Wilber return B_LENDIAN_TO_HOST_INT16(*(reinterpret_cast<uint16 *>(buffer + offset))); 126*735e7442SMatthew Wilber } 127*735e7442SMatthew Wilber 128*735e7442SMatthew Wilber uint32 129*735e7442SMatthew Wilber tga_uint32(char *buffer, int32 offset) 130*735e7442SMatthew Wilber { 131*735e7442SMatthew Wilber return B_LENDIAN_TO_HOST_INT32(*(reinterpret_cast<uint32 *>(buffer + offset))); 132*735e7442SMatthew Wilber } 133*735e7442SMatthew Wilber 134d61900aaSMatthew Wilber void 135d61900aaSMatthew Wilber print_tga_info(BFile &file) 136d61900aaSMatthew Wilber { 137d61900aaSMatthew Wilber uint8 buf[TGA_HEADERS_SIZE]; 138d61900aaSMatthew Wilber 139d61900aaSMatthew Wilber // read in TGA headers 140d61900aaSMatthew Wilber ssize_t size = TGA_HEADERS_SIZE; 141d61900aaSMatthew Wilber if (size > 0 && file.Read(buf, size) != size) { 142d61900aaSMatthew Wilber printf("Error: unable to read all TGA headers\n"); 143d61900aaSMatthew Wilber return; 144d61900aaSMatthew Wilber } 145d61900aaSMatthew Wilber 146d61900aaSMatthew Wilber // TGA file header 147d61900aaSMatthew Wilber TGAFileHeader fh; 148d61900aaSMatthew Wilber fh.idlength = buf[0]; 149d61900aaSMatthew Wilber fh.colormaptype = buf[1]; 150d61900aaSMatthew Wilber fh.imagetype = buf[2]; 151d61900aaSMatthew Wilber 152d61900aaSMatthew Wilber printf("\nFile Header:\n"); 153d61900aaSMatthew Wilber printf(" id length: %d\n", fh.idlength); 154d61900aaSMatthew Wilber 155d61900aaSMatthew Wilber printf("colormap type: %d (%s)\n", fh.colormaptype, 156d61900aaSMatthew Wilber colormaptype(fh.colormaptype)); 157d61900aaSMatthew Wilber printf(" image type: %d (%s)\n", fh.imagetype, imagetype(fh.imagetype)); 158d61900aaSMatthew Wilber 159d61900aaSMatthew Wilber 160d61900aaSMatthew Wilber // TGA color map spec 161d61900aaSMatthew Wilber TGAColorMapSpec mapspec; 162*735e7442SMatthew Wilber mapspec.firstentry = tga_uint16(reinterpret_cast<char *>(buf), 3); 163*735e7442SMatthew Wilber mapspec.length = tga_uint16(reinterpret_cast<char *>(buf), 5); 164d61900aaSMatthew Wilber mapspec.entrysize = buf[7]; 165d61900aaSMatthew Wilber 166d61900aaSMatthew Wilber printf("\nColormap Spec:\n"); 167d61900aaSMatthew Wilber printf("first entry: %d\n", mapspec.firstentry); 168d61900aaSMatthew Wilber printf(" length: %d\n", mapspec.length); 169d61900aaSMatthew Wilber printf(" entry size: %d\n", mapspec.entrysize); 170d61900aaSMatthew Wilber 171d61900aaSMatthew Wilber 172d61900aaSMatthew Wilber // TGA image spec 173d61900aaSMatthew Wilber TGAImageSpec imagespec; 174*735e7442SMatthew Wilber imagespec.xorigin = tga_uint16(reinterpret_cast<char *>(buf), 8); 175*735e7442SMatthew Wilber imagespec.yorigin = tga_uint16(reinterpret_cast<char *>(buf), 10); 176*735e7442SMatthew Wilber imagespec.width = tga_uint16(reinterpret_cast<char *>(buf), 12); 177*735e7442SMatthew Wilber imagespec.height = tga_uint16(reinterpret_cast<char *>(buf), 14); 178d61900aaSMatthew Wilber imagespec.depth = buf[16]; 179d61900aaSMatthew Wilber imagespec.descriptor = buf[17]; 180d61900aaSMatthew Wilber 181d61900aaSMatthew Wilber printf("\nImage Spec:\n"); 182d61900aaSMatthew Wilber printf(" x origin: %d\n", imagespec.xorigin); 183d61900aaSMatthew Wilber printf(" y origin: %d\n", imagespec.yorigin); 184d61900aaSMatthew Wilber printf(" width: %d\n", imagespec.width); 185d61900aaSMatthew Wilber printf(" height: %d\n", imagespec.height); 186d61900aaSMatthew Wilber printf(" depth: %d\n", imagespec.depth); 187d61900aaSMatthew Wilber printf("descriptor: 0x%.2lx\n", imagespec.descriptor); 188d61900aaSMatthew Wilber printf("\talpha (attr): %d\n", 189d61900aaSMatthew Wilber imagespec.descriptor & TGA_DESC_ALPHABITS); 190d61900aaSMatthew Wilber printf("\t origin: %d (%s %s)\n", 191d61900aaSMatthew Wilber imagespec.descriptor & (TGA_ORIGIN_VERT_BIT | TGA_ORIGIN_HORZ_BIT), 192d61900aaSMatthew Wilber ((imagespec.descriptor & TGA_ORIGIN_VERT_BIT) ? "top" : "bottom"), 193d61900aaSMatthew Wilber ((imagespec.descriptor & TGA_ORIGIN_HORZ_BIT) ? "right" : "left")); 194d61900aaSMatthew Wilber printf("\t bits 7 & 6: %d\n", imagespec.descriptor & TGA_DESC_BITS76); 195d61900aaSMatthew Wilber 196d61900aaSMatthew Wilber 197d61900aaSMatthew Wilber // Optional TGA Footer 198d61900aaSMatthew Wilber off_t filesize = 0; 199d61900aaSMatthew Wilber if (file.GetSize(&filesize) == B_OK) { 200d61900aaSMatthew Wilber 201d61900aaSMatthew Wilber char tgafooter[TGA_FTR_LEN + 1] = { 0 }; 202d61900aaSMatthew Wilber if (file.ReadAt(filesize - TGA_FTR_LEN, tgafooter, TGA_FTR_LEN) == TGA_FTR_LEN) { 203d61900aaSMatthew Wilber 204d61900aaSMatthew Wilber if (strcmp(tgafooter + 8, "TRUEVISION-XFILE.") == 0) { 205d61900aaSMatthew Wilber 206d61900aaSMatthew Wilber uint32 extoffset = 0, devoffset = 0; 207*735e7442SMatthew Wilber extoffset = tga_uint32(tgafooter, 0); 208*735e7442SMatthew Wilber devoffset = tga_uint32(tgafooter, 4); 209d61900aaSMatthew Wilber 210d61900aaSMatthew Wilber printf("\nTGA Footer:\n"); 211d61900aaSMatthew Wilber printf("extension offset: 0x%.8lx (%d)\n", extoffset, extoffset); 212d61900aaSMatthew Wilber printf("developer offset: 0x%.8lx (%d)\n", devoffset, devoffset); 213d61900aaSMatthew Wilber printf("signature: %s\n", tgafooter + 8); 214d61900aaSMatthew Wilber 215*735e7442SMatthew Wilber if (extoffset) { 216*735e7442SMatthew Wilber char extbuf[TGA_EXT_LEN]; 217*735e7442SMatthew Wilber if (file.ReadAt(extoffset, extbuf, TGA_EXT_LEN) == TGA_EXT_LEN) { 218*735e7442SMatthew Wilber 219*735e7442SMatthew Wilber printf("\nExtension Area:\n"); 220*735e7442SMatthew Wilber 221*735e7442SMatthew Wilber char strbuffer[LINE_LEN]; 222*735e7442SMatthew Wilber 223*735e7442SMatthew Wilber uint16 extsize = tga_uint16(extbuf, 0); 224*735e7442SMatthew Wilber if (extsize < TGA_EXT_LEN) { 225*735e7442SMatthew Wilber printf("\nError: extension area is too small (%d)\n", extsize); 226*735e7442SMatthew Wilber return; 227*735e7442SMatthew Wilber } 228*735e7442SMatthew Wilber printf("size: %d\n", extsize); 229*735e7442SMatthew Wilber 230*735e7442SMatthew Wilber memset(strbuffer, 0, LINE_LEN); 231*735e7442SMatthew Wilber strncpy(strbuffer, extbuf + 2, 41); 232*735e7442SMatthew Wilber printf("author: \"%s\"\n", strbuffer); 233*735e7442SMatthew Wilber 234*735e7442SMatthew Wilber printf("comments:\n"); 235*735e7442SMatthew Wilber for (int32 i = 0; i < 4; i++) { 236*735e7442SMatthew Wilber memset(strbuffer, 0, LINE_LEN); 237*735e7442SMatthew Wilber strcpy(strbuffer, extbuf + 43 + (i * 81)); 238*735e7442SMatthew Wilber printf("\tline %d: \"%s\"\n", i + 1, strbuffer); 239*735e7442SMatthew Wilber } 240*735e7442SMatthew Wilber 241*735e7442SMatthew Wilber printf("date/time (yyyy-mm-dd hh:mm:ss): %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", 242*735e7442SMatthew Wilber tga_uint16(extbuf, 367), tga_uint16(extbuf, 369), 243*735e7442SMatthew Wilber tga_uint16(extbuf, 371), tga_uint16(extbuf, 373), 244*735e7442SMatthew Wilber tga_uint16(extbuf, 375), tga_uint16(extbuf, 377)); 245*735e7442SMatthew Wilber 246*735e7442SMatthew Wilber memset(strbuffer, 0, LINE_LEN); 247*735e7442SMatthew Wilber strncpy(strbuffer, extbuf + 379, 41); 248*735e7442SMatthew Wilber printf("job name: \"%s\"\n", strbuffer); 249*735e7442SMatthew Wilber 250*735e7442SMatthew Wilber printf("job time (hh:mm:ss): %.2d:%.2d:%.2d\n", 251*735e7442SMatthew Wilber tga_uint16(extbuf, 420), tga_uint16(extbuf, 422), 252*735e7442SMatthew Wilber tga_uint16(extbuf, 424)); 253*735e7442SMatthew Wilber 254*735e7442SMatthew Wilber memset(strbuffer, 0, LINE_LEN); 255*735e7442SMatthew Wilber strncpy(strbuffer, extbuf + 426, 41); 256*735e7442SMatthew Wilber printf("software id: \"%s\"\n", strbuffer); 257*735e7442SMatthew Wilber 258*735e7442SMatthew Wilber char strver[] = "[null]"; 259*735e7442SMatthew Wilber if (extbuf[469] != '\0') { 260*735e7442SMatthew Wilber strver[0] = extbuf[469]; 261*735e7442SMatthew Wilber strver[1] = '\0'; 262*735e7442SMatthew Wilber } 263*735e7442SMatthew Wilber printf("software version, letter: %d, %s\n", 264*735e7442SMatthew Wilber tga_uint16(extbuf, 467), strver); 265*735e7442SMatthew Wilber 266*735e7442SMatthew Wilber printf("key color (A,R,G,B): %d, %d, %d, %d\n", 267*735e7442SMatthew Wilber extbuf[470], extbuf[471], extbuf[472], extbuf[473]); 268*735e7442SMatthew Wilber 269*735e7442SMatthew Wilber printf("pixel aspect ratio: %d / %d\n", 270*735e7442SMatthew Wilber tga_uint16(extbuf, 474), tga_uint16(extbuf, 476)); 271*735e7442SMatthew Wilber 272*735e7442SMatthew Wilber printf("gamma value: %d / %d\n", 273*735e7442SMatthew Wilber tga_uint16(extbuf, 478), tga_uint16(extbuf, 480)); 274*735e7442SMatthew Wilber 275*735e7442SMatthew Wilber printf("color correction offset: 0x%.8lx (%d)\n", 276*735e7442SMatthew Wilber tga_uint32(extbuf, 482), tga_uint32(extbuf, 482)); 277*735e7442SMatthew Wilber printf("postage stamp offset: 0x%.8lx (%d)\n", 278*735e7442SMatthew Wilber tga_uint32(extbuf, 486), tga_uint32(extbuf, 486)); 279*735e7442SMatthew Wilber printf("scan line offset: 0x%.8lx (%d)\n", 280*735e7442SMatthew Wilber tga_uint32(extbuf, 490), tga_uint32(extbuf, 490)); 281*735e7442SMatthew Wilber 282*735e7442SMatthew Wilber const char *strattrtype = NULL; 283*735e7442SMatthew Wilber uint8 attrtype = extbuf[494]; 284*735e7442SMatthew Wilber switch (attrtype) { 285*735e7442SMatthew Wilber case 0: strattrtype = "no alpha"; break; 286*735e7442SMatthew Wilber case 1: strattrtype = "undefined, ignore"; break; 287*735e7442SMatthew Wilber case 2: strattrtype = "undefined, retain"; break; 288*735e7442SMatthew Wilber case 3: strattrtype = "alpha"; break; 289*735e7442SMatthew Wilber case 4: strattrtype = "pre-multiplied alpha"; break; 290*735e7442SMatthew Wilber default: 291*735e7442SMatthew Wilber if (attrtype > 4 && attrtype < 128) 292*735e7442SMatthew Wilber strattrtype = "reserved"; 293*735e7442SMatthew Wilber else 294*735e7442SMatthew Wilber strattrtype = "unassigned"; 295*735e7442SMatthew Wilber break; 296*735e7442SMatthew Wilber } 297*735e7442SMatthew Wilber printf("attributes type: %d (%s)\n", attrtype, strattrtype); 298*735e7442SMatthew Wilber 299*735e7442SMatthew Wilber } else 300*735e7442SMatthew Wilber printf("\nError: Unable to read entire extension area\n"); 301*735e7442SMatthew Wilber } 302*735e7442SMatthew Wilber 303d61900aaSMatthew Wilber } else 304d61900aaSMatthew Wilber printf("\nTGA footer not found\n"); 305d61900aaSMatthew Wilber 306d61900aaSMatthew Wilber } else 307d61900aaSMatthew Wilber printf("\nError: Unable to read TGA footer section\n"); 308d61900aaSMatthew Wilber 309d61900aaSMatthew Wilber } else 310d61900aaSMatthew Wilber printf("\nError: Unable to get file size\n"); 311d61900aaSMatthew Wilber } 312d61900aaSMatthew Wilber 313d61900aaSMatthew Wilber int 314d61900aaSMatthew Wilber main(int argc, char **argv) 315d61900aaSMatthew Wilber { 316d61900aaSMatthew Wilber printf("\n"); 317d61900aaSMatthew Wilber 318*735e7442SMatthew Wilber if (argc == 1) { 319d61900aaSMatthew Wilber printf("tgainfo - reports information about a TGA image file\n"); 320d61900aaSMatthew Wilber printf("\nUsage:\n"); 321d61900aaSMatthew Wilber printf("tgainfo filename.tga\n"); 322d61900aaSMatthew Wilber } 323*735e7442SMatthew Wilber else { 324*735e7442SMatthew Wilber BFile file; 325*735e7442SMatthew Wilber 326*735e7442SMatthew Wilber for (int32 i = 1; i < argc; i++) { 327*735e7442SMatthew Wilber if (file.SetTo(argv[i], B_READ_ONLY) != B_OK) 328*735e7442SMatthew Wilber printf("\nError opening %s\n", argv[i]); 329*735e7442SMatthew Wilber else { 330*735e7442SMatthew Wilber printf("\nTGA image information for: %s\n", argv[i]); 331*735e7442SMatthew Wilber print_tga_info(file); 332*735e7442SMatthew Wilber } 333*735e7442SMatthew Wilber } 334*735e7442SMatthew Wilber 335*735e7442SMatthew Wilber } 336d61900aaSMatthew Wilber 337d61900aaSMatthew Wilber printf("\n"); 338d61900aaSMatthew Wilber 339d61900aaSMatthew Wilber return 0; 340d61900aaSMatthew Wilber } 341d61900aaSMatthew Wilber 342