home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / TGAUTL.ZIP / TGADUMP.C < prev    next >
C/C++ Source or Header  |  1990-03-26  |  18KB  |  772 lines

  1. /*
  2. ** Copyright (c) 1989
  3. ** Truevision, Inc.
  4. ** All Rights Reserverd
  5. **
  6. ** TGADUMP reads the contents of a Truevision TGA(tm) File and displays
  7. ** information about the file contents on the console device.  This
  8. ** program does not display the image.
  9. */
  10.  
  11. #include <malloc.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include "tga.h"
  18.  
  19. extern void        main( int, char ** );
  20. extern void        PrintColorTable( TGAFile * );
  21. extern void        PrintExtendedTGA( TGAFile * );
  22. extern void        PrintImageType( int );
  23. extern void        PrintMonth( UINT16 );
  24. extern void        PrintScanLineTable( TGAFile * );
  25. extern void        PrintTGAInfo( TGAFile * );
  26. extern UINT8    ReadByte( FILE * );
  27. extern void        ReadCharField( FILE *, char *, int );
  28. extern int        ReadColorTable( FILE *, TGAFile * );
  29. extern int        ReadExtendedTGA( FILE *, TGAFile * );
  30. extern int        ReadScanLineTable( FILE *, TGAFile * );
  31. extern UINT16    ReadShort( FILE * );
  32. extern UINT32    ReadLong( FILE * );
  33.  
  34.  
  35. /*
  36. ** String data for performing month conversions
  37. */
  38. char    *monthStr[] =
  39. {
  40.     "January",
  41.     "February",
  42.     "March",
  43.     "April",
  44.     "May",
  45.     "June",
  46.     "July",
  47.     "August",
  48.     "September",
  49.     "October",
  50.     "November",
  51.     "December"
  52. };
  53.  
  54. /*
  55. ** String data for interpretting image orientation specification
  56. */
  57. char    *orientStr[] =
  58. {
  59.     "Bottom Left",
  60.     "Bottom Right",
  61.     "Top Left",
  62.     "Top Right"
  63. };
  64.  
  65. /*
  66. ** String data for interpretting interleave flag defined with VDA
  67. ** This field is now obsolete and should typically be set to zero.
  68. */
  69. char    *interleaveStr[] =
  70. {
  71.     "  Two Way (Even-Odd) Interleave (e.g., IBM Graphics Card Adapter), Obsolete",
  72.     "  Four Way Interleave (e.g., AT&T 6300 High Resolution), Obsolete",
  73. };
  74.  
  75. TGAFile        f;                /* control structure of image data */
  76. char        *versionStr =
  77. "Truevision(R) TGA(tm) File Dump Utility Version 1.3 - January 2, 1990";
  78.  
  79. void
  80. main( argc, argv )
  81. int argc;
  82. char **argv;
  83. {
  84.     int            fileFound;
  85.     char        *q;
  86.     FILE        *fp;
  87.     long        fsize;
  88.     int            xTGA;            /* flags extended TGA file */
  89.     UINT16        devDirEntries;    /* number of entries in developer area */
  90.     char        fileName[80];
  91.     struct stat    statbuf;
  92.  
  93.     puts( versionStr );
  94.     /*
  95.     ** The program can be invoked without an argument, in which case
  96.     ** the user will be prompted for the name of the image file to be
  97.     ** examined, or the image file name can be provided as an argument
  98.     ** to the command.
  99.     **
  100.     ** File names provided do not need to include the extension if
  101.     ** the image file extension is one of the standard strings common
  102.     ** to Truevision TGA image file names ( e.g., TGA, WIN, VST, VDA, ICB )
  103.     */
  104.     if ( argc == 1 )
  105.     {
  106.         printf( "Enter name of file to examine: " );
  107.         gets( fileName );
  108.         if ( strlen( fileName ) == 0 ) exit( 0 );
  109.     }
  110.     else
  111.     {
  112.         strcpy( fileName, argv[1] );
  113.     }
  114.     if ( fileName[0] == '-' )
  115.     {
  116.         puts( "Usage: tgadump [filename]" );
  117.         exit( 0 );
  118.     }
  119.     /*
  120.     ** See if we can find the file as specified or with one of the
  121.     ** standard filename extensions...
  122.     */
  123.     fileFound = 0;
  124.     if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  125.     else
  126.     {
  127.         strcat( fileName, ".tga" );
  128.         q = strchr( fileName, '.' );
  129.         if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  130.         else
  131.         {
  132.             strcpy( q, ".vst" );
  133.             if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  134.             else
  135.             {
  136.                 strcpy( q, ".vda" );
  137.                 if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  138.                 else
  139.                 {
  140.                     strcpy( q, ".icb" );
  141.                     if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  142.                     else
  143.                     {
  144.                         strcpy( q, ".win" );
  145.                         if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
  146.                         else
  147.                         {
  148.                             *q = '\0';
  149.                             printf("Unable to open image file %s\n", fileName );
  150.                         }
  151.                     }
  152.                 }
  153.             }
  154.         }
  155.     }
  156.     if ( fileFound )
  157.     {
  158.         printf( "TGA File: %s\n", fileName );
  159.         fp = fopen( fileName, "rb" );
  160.         /*
  161.         ** It would be nice to be able to read in the entire
  162.         ** structure with one fread, but compiler dependent
  163.         ** structure alignment precludes the simplistic approach.
  164.         ** Instead, fill each field individually, and use routines
  165.         ** that will allow code to execute on various hosts by
  166.         ** recompilation with particular compiler flags.
  167.         **
  168.         ** Start by reading the fields associated with the original
  169.         ** TGA format.
  170.         */
  171.         f.idLength = ReadByte( fp );
  172.         f.mapType = ReadByte( fp );
  173.         f.imageType = ReadByte( fp );
  174.         f.mapOrigin = ReadShort( fp );
  175.         f.mapLength = ReadShort( fp );
  176.         f.mapWidth = ReadByte( fp );
  177.         f.xOrigin = ReadShort( fp );
  178.         f.yOrigin = ReadShort( fp );
  179.         f.imageWidth = ReadShort( fp );
  180.         f.imageHeight = ReadShort( fp );
  181.         f.pixelDepth = ReadByte( fp );
  182.         f.imageDesc = ReadByte( fp );
  183.         memset( f.idString, 0, 256 );
  184.         if ( f.idLength > 0 )
  185.         {
  186.             fread( f.idString, 1, f.idLength, fp );
  187.         }
  188.         PrintTGAInfo( &f );
  189.         /*
  190.         ** Now see if the file is the new (extended) TGA format.
  191.         */
  192.         xTGA = 0;
  193.         if ( !fseek( fp, statbuf.st_size - 26, SEEK_SET ) )
  194.         {
  195.             f.extAreaOffset = ReadLong( fp );
  196.             f.devDirOffset = ReadLong( fp );
  197.             fgets( f.signature, 18, fp );
  198.             if ( strcmp( f.signature, "TRUEVISION-XFILE." ) )
  199.             {
  200.                 /*
  201.                 ** Reset offset values since this is not a new TGA file
  202.                 */
  203.                 f.extAreaOffset = 0L;
  204.                 f.devDirOffset = 0L;
  205.             }
  206.             else xTGA = 1;
  207.             /*
  208.             ** If the file is an original TGA file, and falls into
  209.             ** one of the uncompressed image types, we can perform
  210.             ** an additional file size check with very little effort.
  211.             */
  212.             if ( f.imageType > 0 && f.imageType < 4 && !xTGA )
  213.             {
  214.                 /*
  215.                 ** Based on the header info, we should be able to calculate
  216.                 ** the file size.
  217.                 */
  218.                 fsize = 18;    /* size of header in bytes */
  219.                 fsize += f.idLength;
  220.                 /* expect 8, 15, 16, 24, or 32 bits per map entry */
  221.                 fsize += ((f.mapWidth + 1) >> 3) * (long)f.mapLength;
  222.                 fsize += ((f.pixelDepth+1) >> 3) * (long)f.imageWidth *
  223.                             f.imageHeight;
  224.                 if ( fsize != statbuf.st_size )
  225.                 {
  226.                     puts( "Image File Format Error" );
  227.                     printf("  Uncompressed File Size Should Be %ld Bytes\n",
  228.                         fsize );
  229.                 }
  230.             }
  231.             if ( xTGA && f.extAreaOffset )
  232.             {
  233.                 if ( ReadExtendedTGA( fp, &f ) >= 0 )
  234.                 {
  235.                     PrintExtendedTGA( &f );
  236.                 }
  237.             }
  238.             if ( xTGA && f.devDirOffset )
  239.             {
  240.                 puts( "Developer Area Specified:" );
  241.                 if ( !fseek( fp, f.devDirOffset, SEEK_SET ) )
  242.                 {
  243.                     devDirEntries = ReadShort( fp );
  244.                     printf( "Developer Directory contains %d Entries\n",
  245.                         devDirEntries );
  246.                 }
  247.                 else
  248.                 {
  249.                     printf( "Error seeking to Developer Area, offset = 0x%08lx\n",
  250.                         f.devDirOffset );
  251.                 }
  252.             }
  253.         }
  254.         else
  255.         {
  256.             puts( "Error seeking to end of file for possible extension data" );
  257.         }
  258.         if ( f.scanLineTable ) free( f.scanLineTable );
  259.         if ( f.colorCorrectTable ) free( f.colorCorrectTable );
  260.         fclose( fp );
  261.     }
  262. }
  263.  
  264.  
  265. void
  266. PrintColorTable( sp )
  267. TGAFile    *sp;
  268. {
  269.     unsigned int    n;
  270.     UINT16            *p;
  271.  
  272.     puts( "Color Correction Table:" );
  273.     p = sp->colorCorrectTable;
  274.     for ( n = 0; n < 256; ++n )
  275.     {
  276.         printf( "Color Entry %3u: 0x%04x(%5u) A, ", n, *p, *p );
  277.         ++p;
  278.         printf( "0x%04x(%5u) R, ", *p, *p );
  279.         ++p;
  280.         printf( "0x%04x(%5u) G, ", *p, *p );
  281.         ++p;
  282.         printf( "0x%04x(%5u) B\n", *p, *p );
  283.         ++p;
  284.     }
  285. }
  286.  
  287.  
  288.  
  289. void
  290. PrintExtendedTGA( sp )
  291. TGAFile *sp;        /* TGA structure pointer */
  292. {
  293.     register int    strSize;
  294.     char            *blankChars = " \t";
  295.  
  296.     puts( "***** Extended TGA Fields *****" );
  297.     printf( "Truevision TGA File Format Version = " );
  298.     if ( sp->extSize == 495 ) puts( "2.0" );
  299.     else printf( "UNKNOWN, extension size = %d\n", sp->extSize );
  300.  
  301.     /*
  302.     ** Make sure the strings have length, and contain something
  303.     ** other than blanks and tabs
  304.     */
  305.     strSize = strlen( sp->author );
  306.     if ( strSize && strspn( sp->author, blankChars ) < strSize )
  307.     {
  308.         printf( "Author                             = %s\n", sp->author );
  309.     }
  310.     strSize = strlen( &sp->authorCom[0][0] );
  311.     if ( strSize && strspn( &sp->authorCom[0][0], blankChars ) < strSize )
  312.     {
  313.         puts( "Author Comments:" );
  314.         puts( &sp->authorCom[0][0] );
  315.         strSize = strlen( &sp->authorCom[1][0] );
  316.         if ( strSize && strspn( &sp->authorCom[1][0], blankChars ) < strSize )
  317.         {
  318.             puts( &sp->authorCom[1][0] );
  319.         }
  320.         strSize = strlen( &sp->authorCom[2][0] );
  321.         if ( strSize && strspn( &sp->authorCom[2][0], blankChars ) < strSize )
  322.         {
  323.             puts( &sp->authorCom[2][0] );
  324.         }
  325.         strSize = strlen( &sp->authorCom[3][0] );
  326.         if ( strSize && strspn( &sp->authorCom[3][0], blankChars ) < strSize )
  327.         {
  328.             puts( &sp->authorCom[3][0] );
  329.         }
  330.         puts( "[End of Author Comments]" );
  331.     }
  332.  
  333.     if ( sp->month )
  334.     {
  335.         printf( "Date Image Saved                   = " );
  336.         PrintMonth( sp->month );
  337.         printf( " %02u, %4u at %02u:%02u:%02u\n", sp->day, sp->year,
  338.             sp->hour, sp->minute, sp->second );
  339.     }
  340.  
  341.     strSize = strlen( sp->jobID );
  342.     if ( strSize && strspn( sp->jobID, blankChars ) < strSize )
  343.     {
  344.         printf( "Job Name/ID                        = %s\n", sp->jobID );
  345.     }
  346.  
  347.     if ( sp->jobHours != 0 || sp->jobMinutes != 0 || sp->jobSeconds != 0 )
  348.     {
  349.         printf( "Job Elapsed Time                   = %02u:%02u:%02u\n",
  350.             sp->jobHours, sp->jobMinutes, sp->jobSeconds );
  351.     }
  352.  
  353.     strSize = strlen( sp->softID );
  354.     if ( strSize && strspn( sp->softID, blankChars ) < strSize )
  355.     {
  356.         printf( "Software ID                        = %s\n", sp->softID );
  357.     }
  358.  
  359.     if ( sp->versionNum != 0 || sp->versionLet != ' ' )
  360.     {
  361.         printf( "Software Version                   = %u.%u%c\n",
  362.             sp->versionNum/100, sp->versionNum % 100, sp->versionLet );
  363.     }
  364.  
  365.     printf( "Key Color: 0x%02lx(%ld) Alpha, 0x%02lx(%ld) Red, 0x%02lx(%ld) Green, 0x%02lx(%ld) Blue\n",
  366.         sp->keyColor >> 24, sp->keyColor >> 24,
  367.         (sp->keyColor >> 16) & 0xff, (sp->keyColor >> 16) & 0xff,
  368.         (sp->keyColor >> 8) & 0xff, (sp->keyColor >> 8) & 0xff,
  369.         sp->keyColor & 0xff, sp->keyColor & 0xff );
  370.  
  371.     if ( sp->pixNumerator != 0 && sp->pixDenominator != 0 )
  372.     {
  373.         printf( "Pixel Aspect Ratio                 = %f\n",
  374.                 (double)sp->pixNumerator / (double)sp->pixDenominator );
  375.     }
  376.  
  377.     if ( sp->gammaDenominator != 0 )
  378.     {
  379.         printf( "Gamma Correction                   = %f\n",
  380.                 (double)sp->gammaNumerator / (double)sp->gammaDenominator );
  381.     }
  382.  
  383.     if ( sp->colorCorrectOffset != 0L )
  384.     {
  385.         printf( "Color Correction Offset            = 0x%08lx\n",
  386.                     sp->colorCorrectOffset);
  387.         if ( sp->colorCorrectTable )
  388.         {
  389.             PrintColorTable( sp );
  390.         }
  391.     }
  392.     if ( sp->stampOffset )
  393.     {
  394.         printf( "Postage Stamp Offset               = 0x%08lx\n",
  395.                     sp->stampOffset );
  396.         printf( "Postage Stamp Width, Height        = %3u, %3u\n",
  397.                     sp->stampWidth, sp->stampHeight );
  398.     }
  399.     if ( sp->scanLineOffset != 0L )
  400.     {
  401.         printf( "Scan Line Offset                   = 0x%08lx\n",
  402.                     sp->scanLineOffset );
  403.         if ( sp->scanLineTable )
  404.         {
  405.             PrintScanLineTable( sp );
  406.         }
  407.     }
  408.  
  409.     switch (sp->alphaAttribute )
  410.     {
  411.     case 0:
  412.         if ( (sp->imageDesc & 0xf) == 0 ) puts( "No Alpha Data Present" );
  413.         else puts( "Inconsistent Alpha Data Specification" );
  414.         break;
  415.     case 1:
  416.         puts( "Alpha Data Undefined and Can Be Ignored" );
  417.         break;
  418.     case 2:
  419.         puts( "Alpha Data Undefined but Should Be Retained" );
  420.         break;
  421.     case 3:
  422.         puts( "Useful Alpha Data Present" );
  423.         break;
  424.     case 4:
  425.         puts( "Pre-Multiplied Alpha Data Present" );
  426.         break;
  427.     default:
  428.         puts( "Undefined Alpha Attribute Field" );
  429.         break;
  430.     }
  431. }
  432.  
  433.  
  434.  
  435. void
  436. PrintImageType( Itype )
  437. register int Itype;
  438. {
  439.     if ( Itype > 255 || Itype < 0 )
  440.     {
  441.         puts("Illegal/Undefined Image Type");
  442.         return;
  443.     }
  444.  
  445.     if ( Itype > 127 )
  446.     {
  447.         puts("Unknown Image Type - Application Specific");
  448.         return;
  449.     }
  450.  
  451.     switch (Itype)
  452.     {
  453.     case 0:
  454.         puts("Unknown Image Type - No Image Data Present");
  455.         break;
  456.     case 1:
  457.         puts("Uncompressed Color Mapped Image (e.g., VDA/D, TARGA M8)");
  458.         break;
  459.     case 2:
  460.         puts("Uncompressed True Color Image (e.g., ICB, TARGA 16/24/32)");
  461.         break;
  462.     case 3:
  463.         puts("Uncompressed Black & White Image (e.g., TARGA 8/M8)");
  464.         break;
  465.     case 9:
  466.         puts("Run Length Encoded Color Mapped Image (e.g., VDA/D, TARGA M8)");
  467.         break;
  468.     case 10:
  469.         puts("Run Length Encoded True Color Image (e.g., ICB, TARGA 16/24/32)");
  470.         break;
  471.     case 11:
  472.         puts("Compressed Black & White Image (e.g., TARGA 8/M8)");
  473.         break;
  474.     case 32:
  475.     case 34:
  476.         puts("Compressed (Huffman/Delta/RLE) Color Mapped Image (e.g., VDA/D) - Obsolete");
  477.         break;
  478.     case 33:
  479.     case 35:
  480.         puts("Compressed (Huffman/Delta/RLE) Color Mapped Four Pass Image (e.g., VDA/D) - Obsolete");
  481.         break;
  482.     default:
  483.         puts("Unknown Image Type");
  484.         break;
  485.     }
  486. }
  487.  
  488.  
  489. void
  490. PrintMonth( month )
  491. UINT16    month;
  492. {
  493.     if ( month > 0 && month < 13 ) printf( monthStr[month - 1] );
  494.     else printf( "Month Error" );
  495. }
  496.  
  497.  
  498. void
  499. PrintScanLineTable( sp )
  500. TGAFile    *sp;
  501. {
  502.     UINT16    n;
  503.     UINT32    *p;
  504.  
  505.     puts( "Scan Line Table:" );
  506.     p = sp->scanLineTable;
  507.     for ( n = 0; n < sp->imageHeight; ++n )
  508.     {
  509.         printf( "Scan Line %6u, Offset 0x%08lx(%8d)\n", n, *p, *p );
  510.         ++p;
  511.     }
  512. }
  513.  
  514.  
  515.  
  516. void
  517. PrintTGAInfo( sp )
  518. TGAFile *sp;        /* TGA structure pointer */
  519. {
  520.     int    i;
  521.  
  522.     printf("ID Field Length          = %3d\n", sp->idLength);
  523.  
  524.     printf("Color Map Type           = %3d  (Color Map Data is ", sp->mapType);
  525.     if (sp->mapType) puts("Present)");
  526.     else puts("Absent)");  
  527.  
  528.     printf("Image Type               = %3d\n  ", sp->imageType);
  529.     PrintImageType( sp->imageType );
  530.  
  531.     printf("Color Map Origin         = 0x%04x (%5d)",
  532.         sp->mapOrigin, sp->mapOrigin);
  533.     puts( "  (First Index To Be Loaded)" );
  534.     printf("Color Map Length         = 0x%04x (%5d)\n",
  535.         sp->mapLength,sp->mapLength);
  536.     printf("Color Map Entry Size     = %6d\n", sp->mapWidth);
  537.  
  538.     printf("Image X-Origin, Y-Origin =  %05d, %05d\n",
  539.         sp->xOrigin, sp->yOrigin);
  540.     printf("Image Width, Height      =  %05d, %05d\n",
  541.             sp->imageWidth, sp->imageHeight);
  542.  
  543.     printf("Image Pixel Depth        = 0x%04x (%5d)\n",
  544.         sp->pixelDepth, sp->pixelDepth);
  545.     printf("Image Descriptor         = 0x%04x\n", sp->imageDesc);
  546.     printf("  %d Attribute Bits Per Pixel\n", sp->imageDesc & 0xf );
  547.     printf("  First Pixel Destination is ");
  548.  
  549.     i = (sp->imageDesc & 0x30) >> 4;
  550.     puts( orientStr[i] );
  551.  
  552.     i = (sp->imageDesc & 0xc0) >> 6;
  553.     if ( i > 0 && i < 3 ) puts( interleaveStr[i - 1] );
  554.  
  555.     if ( sp->idLength )
  556.     {
  557.         printf( "Image ID:\n  " );
  558.         puts( f.idString );
  559.     }
  560. }
  561.  
  562.  
  563. UINT8
  564. ReadByte( fp )
  565. FILE *fp;
  566. {
  567.     UINT8    value;
  568.  
  569. #if MSDOS
  570.     fread( &value, 1, 1, fp );
  571. #else
  572. #endif
  573.     return( value );
  574. }
  575.  
  576.  
  577. void
  578. ReadCharField( fp, p, n )
  579. FILE    *fp;
  580. char    *p;
  581. int        n;
  582. {
  583.     while ( n )
  584.     {
  585.         *p++ = (char)fgetc( fp );    /* no error check, no char conversion */
  586.         --n;
  587.     }
  588. }
  589.  
  590.  
  591. int
  592. ReadColorTable( fp, sp )
  593. FILE    *fp;
  594. TGAFile    *sp;
  595. {
  596.     UINT16    *p;
  597.     UINT16    n;
  598.  
  599.     if ( !fseek( fp, sp->colorCorrectOffset, SEEK_SET ) )
  600.     {
  601.         if ( sp->colorCorrectTable = malloc( 1024 * sizeof( UINT16 ) ) )
  602.         {
  603.             p = sp->colorCorrectTable;
  604.             for ( n = 0; n < 1024; ++n )
  605.             {
  606.                 *p++ = ReadShort( fp );
  607.             }
  608.         }
  609.         else
  610.         {
  611.             puts( "Unable to allocate Color Correction Table" );
  612.             return( -1 );
  613.         }
  614.     }
  615.     else
  616.     {
  617.         printf( "Error seeking to Color Correction Table, offset = 0x%08lx\n",
  618.             sp->colorCorrectOffset );
  619.         return( -1 );
  620.     }
  621.     return( 0 );
  622. }
  623.  
  624.  
  625. int
  626. ReadExtendedTGA( fp, sp )
  627. FILE    *fp;
  628. TGAFile    *sp;
  629. {
  630.     if ( !fseek( fp, sp->extAreaOffset, SEEK_SET ) )
  631.     {
  632.         sp->extSize = ReadShort( fp );
  633.         memset( sp->author, 0, 41 );
  634.         ReadCharField( fp, sp->author, 41 );
  635.         memset( &sp->authorCom[0][0], 0, 81 );
  636.         ReadCharField( fp, &sp->authorCom[0][0], 81 );
  637.         memset( &sp->authorCom[1][0], 0, 81 );
  638.         ReadCharField( fp, &sp->authorCom[1][0], 81 );
  639.         memset( &sp->authorCom[2][0], 0, 81 );
  640.         ReadCharField( fp, &sp->authorCom[2][0], 81 );
  641.         memset( &sp->authorCom[3][0], 0, 81 );
  642.         ReadCharField( fp, &sp->authorCom[3][0], 81 );
  643.  
  644.         sp->month = ReadShort( fp );
  645.         sp->day = ReadShort( fp );
  646.         sp->year = ReadShort( fp );
  647.         sp->hour = ReadShort( fp );
  648.         sp->minute = ReadShort( fp );
  649.         sp->second = ReadShort( fp );
  650.  
  651.         memset( sp->jobID, 0, 41 );
  652.         ReadCharField( fp, sp->jobID, 41 );
  653.         sp->jobHours = ReadShort( fp );
  654.         sp->jobMinutes = ReadShort( fp );
  655.         sp->jobSeconds = ReadShort( fp );
  656.  
  657.         memset( sp->softID, 0, 41 );
  658.         ReadCharField( fp, sp->softID, 41 );
  659.         sp->versionNum = ReadShort( fp );
  660.         sp->versionLet = ReadByte( fp );
  661.  
  662.         sp->keyColor = ReadLong( fp );
  663.         sp->pixNumerator = ReadShort( fp );
  664.         sp->pixDenominator = ReadShort( fp );
  665.  
  666.         sp->gammaNumerator = ReadShort( fp );
  667.         sp->gammaDenominator = ReadShort( fp );
  668.  
  669.         sp->colorCorrectOffset = ReadLong( fp );
  670.         sp->stampOffset = ReadLong( fp );
  671.         sp->scanLineOffset = ReadLong( fp );
  672.  
  673.         sp->alphaAttribute = ReadByte( fp );
  674.  
  675.         sp->colorCorrectTable = (UINT16 *)0;
  676.         if ( sp->colorCorrectOffset )
  677.         {
  678.             ReadColorTable( fp, sp );
  679.         }
  680.  
  681.         sp->postStamp = (void *)0;
  682.         if ( sp->stampOffset )
  683.         {
  684.             if ( !fseek( fp, sp->stampOffset, SEEK_SET ) )
  685.             {
  686.                 sp->stampWidth = ReadByte( fp );
  687.                 sp->stampHeight = ReadByte( fp );
  688.             }
  689.             else
  690.             {
  691.                 printf( "Error seeking to Postage Stamp, offset = 0x%08lx\n",
  692.                     sp->stampOffset );
  693.             }
  694.         }
  695.  
  696.         sp->scanLineTable = (UINT32 *)0;
  697.         if ( sp->scanLineOffset )
  698.         {
  699.             ReadScanLineTable( fp, sp );
  700.         }
  701.     }
  702.     else
  703.     {
  704.         printf( "Error seeking to Extended TGA Area, offset = 0x%08lx\n",
  705.             sp->extAreaOffset );
  706.         return( -1 );
  707.     }
  708.     return( 0 );
  709. }
  710.  
  711.  
  712. UINT32
  713. ReadLong( fp )
  714. FILE *fp;
  715. {
  716.     UINT32    value;
  717.  
  718. #if MSDOS
  719.     fread( &value, 1, 4, fp );
  720. #else
  721. #endif
  722.     return( value );
  723. }
  724.  
  725.  
  726. int
  727. ReadScanLineTable( fp, sp )
  728. FILE    *fp;
  729. TGAFile    *sp;
  730. {
  731.     UINT32    *p;
  732.     UINT16    n;
  733.  
  734.     if ( !fseek( fp, sp->scanLineOffset, SEEK_SET ) )
  735.     {
  736.         if ( sp->scanLineTable = malloc( sp->imageHeight << 2 ) )
  737.         {
  738.             p = sp->scanLineTable;
  739.             for ( n = 0; n < sp->imageHeight; ++n )
  740.             {
  741.                 *p++ = ReadShort( fp );
  742.             }
  743.         }
  744.         else
  745.         {
  746.             puts( "Unable to allocate Scan Line Table" );
  747.             return( -1 );
  748.         }
  749.     }
  750.     else
  751.     {
  752.         printf( "Error seeking to Scan Line Table, offset = 0x%08lx\n",
  753.             sp->scanLineOffset );
  754.         return( -1 );
  755.     }
  756.     return( 0 );
  757. }
  758.  
  759.  
  760. UINT16
  761. ReadShort( fp )
  762. FILE *fp;
  763. {
  764.     UINT16    value;
  765.  
  766. #if MSDOS
  767.     fread( &value, 1, 2, fp );
  768. #else
  769. #endif
  770.     return( value );
  771. }
  772.