home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / tgatoppm.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  10KB  |  375 lines

  1. /* tgatoppm.c - read a TrueVision Targa file and write a portable pixmap
  2. **
  3. ** Partially based on tga2rast, version 1.0, by Ian MacPhedran.
  4. **
  5. ** Copyright (C) 1989 by Jef Poskanzer.
  6. **
  7. ** Permission to use, copy, modify, and distribute this software and its
  8. ** documentation for any purpose and without fee is hereby granted, provided
  9. ** that the above copyright notice appear in all copies and that both that
  10. ** copyright notice and this permission notice appear in supporting
  11. ** documentation.  This software is provided "as is" without express or
  12. ** implied warranty.
  13. */
  14.  
  15. #include "ppm.h"
  16. #include "tga.h"
  17.  
  18. #define MAXCOLORS 16384
  19.  
  20. static int mapped, rlencoded;
  21.  
  22. static pixel ColorMap[MAXCOLORS];
  23. static int RLE_count = 0, RLE_flag = 0;
  24.  
  25. static void readtga ARGS(( FILE* ifp, struct ImageHeader* tgaP ));
  26. static void get_map_entry ARGS(( FILE* ifp, pixel* Value, int Size ));
  27. static void get_pixel ARGS(( FILE* ifp, pixel* dest, int Size ));
  28. static unsigned char getbyte ARGS(( FILE* ifp ));
  29.  
  30. int
  31. main( argc, argv )
  32.     int argc;
  33.     char* argv[];
  34.     {
  35.     struct ImageHeader tga_head;
  36.     int i;
  37.     unsigned int temp1, temp2;
  38.     FILE* ifp;
  39.     int argn, debug, rows, cols, row, col, realrow, truerow, baserow;
  40.     int maxval;
  41.     pixel** pixels;
  42.     char* usage = " [-debug] [tgafile]";
  43.  
  44.  
  45.     ppm_init( &argc, argv );
  46.  
  47.     argn = 1;
  48.     debug = 0;
  49.  
  50.     if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  51.     {
  52.     if ( pm_keymatch( argv[argn], "-debug", 2 ) )
  53.         debug = 1;
  54.     else
  55.         pm_usage( usage );
  56.     ++argn;
  57.     }
  58.  
  59.     if ( argn != argc )
  60.     {
  61.     ifp = pm_openr( argv[argn] );
  62.     ++argn;
  63.     }
  64.     else
  65.     ifp = stdin;
  66.  
  67.     if ( argn != argc )
  68.     pm_usage( usage );
  69.  
  70.     /* Read the Targa file header. */
  71.     readtga( ifp, &tga_head );
  72.     if ( debug )
  73.     {
  74.     pm_message( "IDLength = %d\n", (int) tga_head.IDLength );
  75.     pm_message( "CoMapType = %d\n", (int) tga_head.CoMapType );
  76.     pm_message( "ImgType = %d\n", (int) tga_head.ImgType );
  77.     pm_message( "Index_lo = %d\n", (int) tga_head.Index_lo );
  78.     pm_message( "Index_hi = %d\n", (int) tga_head.Index_hi );
  79.     pm_message( "Length_lo = %d\n", (int) tga_head.Length_lo );
  80.     pm_message( "Length_hi = %d\n", (int) tga_head.Length_hi );
  81.     pm_message( "CoSize = %d\n", (int) tga_head.CoSize );
  82.     pm_message( "X_org_lo = %d\n", (int) tga_head.X_org_lo );
  83.     pm_message( "X_org_hi = %d\n", (int) tga_head.X_org_hi );
  84.     pm_message( "Y_org_lo = %d\n", (int) tga_head.Y_org_lo );
  85.     pm_message( "Y_org_hi = %d\n", (int) tga_head.Y_org_hi );
  86.     pm_message( "Width_lo = %d\n", (int) tga_head.Width_lo );
  87.     pm_message( "Width_hi = %d\n", (int) tga_head.Width_hi );
  88.     pm_message( "Height_lo = %d\n", (int) tga_head.Height_lo );
  89.     pm_message( "Height_hi = %d\n", (int) tga_head.Height_hi );
  90.     pm_message( "PixelSize = %d\n", (int) tga_head.PixelSize );
  91.     pm_message( "AttBits = %d\n", (int) tga_head.AttBits );
  92.     pm_message( "Rsrvd = %d\n", (int) tga_head.Rsrvd );
  93.     pm_message( "OrgBit = %d\n", (int) tga_head.OrgBit );
  94.     pm_message( "IntrLve = %d\n", (int) tga_head.IntrLve );
  95.     }
  96.     rows = ( (int) tga_head.Height_lo ) + ( (int) tga_head.Height_hi ) * 256;
  97.     cols = ( (int) tga_head.Width_lo ) + ( (int) tga_head.Width_hi ) * 256;
  98.  
  99.     switch ( tga_head.ImgType )
  100.     {
  101.     case TGA_Map:
  102.     case TGA_RGB:
  103.     case TGA_Mono:
  104.     case TGA_RLEMap:
  105.     case TGA_RLERGB:
  106.     case TGA_RLEMono:
  107.     break;
  108.  
  109.     default:
  110.     pm_error( "unknown Targa image type %d", tga_head.ImgType );
  111.     }
  112.  
  113.     if ( tga_head.ImgType == TGA_Map ||
  114.      tga_head.ImgType == TGA_RLEMap ||
  115.      tga_head.ImgType == TGA_CompMap ||
  116.      tga_head.ImgType == TGA_CompMap4 )
  117.     { /* Color-mapped image */
  118.     if ( tga_head.CoMapType != 1 )
  119.         pm_error( 
  120.         "mapped image (type %d) with color map type != 1",
  121.         tga_head.ImgType );
  122.     mapped = 1;
  123.     /* Figure maxval from CoSize. */
  124.     switch ( tga_head.CoSize )
  125.         {
  126.         case 8:
  127.         case 24:
  128.         case 32:
  129.         maxval = 255;
  130.         break;
  131.  
  132.         case 15:
  133.         case 16:
  134.         maxval = 31;
  135.         break;
  136.  
  137.         default:
  138.         pm_error(
  139.         "unknown colormap pixel size - %d", tga_head.CoSize );
  140.         }
  141.     if ( maxval > PPM_MAXMAXVAL )
  142.         pm_error(
  143. "CoSize is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  144.     }
  145.     else
  146.     { /* Not colormap, so figure maxval from PixelSize. */
  147.     mapped = 0;
  148.     switch ( tga_head.PixelSize )
  149.         {
  150.         case 8:
  151.         case 24:
  152.         case 32:
  153.         maxval = 255;
  154.         break;
  155.  
  156.         case 15:
  157.         case 16:
  158.         maxval = 31;
  159.         break;
  160.  
  161.         default:
  162.         pm_error( "unknown pixel size - %d", tga_head.PixelSize );
  163.         }
  164.     if ( maxval > PPM_MAXMAXVAL )
  165.         pm_error(
  166. "PixelSize is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  167.     }
  168.  
  169.     /* If required, read the color map information. */
  170.     if ( tga_head.CoMapType != 0 )
  171.     {
  172.     temp1 = tga_head.Index_lo + tga_head.Index_hi * 256;
  173.     temp2 = tga_head.Length_lo + tga_head.Length_hi * 256;
  174.     if ( ( temp1 + temp2 + 1 ) >= MAXCOLORS )
  175.         pm_error( "too many colors - %d", ( temp1 + temp2 + 1 ) );
  176.     for ( i = temp1; i < ( temp1 + temp2 ); ++i )
  177.         get_map_entry( ifp, &ColorMap[i], (int) tga_head.CoSize );
  178.     }
  179.  
  180.     /* Check run-length encoding. */
  181.     if ( tga_head.ImgType == TGA_RLEMap ||
  182.      tga_head.ImgType == TGA_RLERGB ||
  183.      tga_head.ImgType == TGA_RLEMono )
  184.     rlencoded = 1;
  185.     else
  186.     rlencoded = 0;
  187.  
  188.     /* Read the Targa file body and convert to portable format. */
  189.     pixels = ppm_allocarray( cols, rows );
  190.     truerow = 0;
  191.     baserow = 0;
  192.     for ( row = 0; row < rows; ++row )
  193.     {
  194.     realrow = truerow;
  195.     if ( tga_head.OrgBit == 0 )
  196.         realrow = rows - realrow - 1;
  197.  
  198.     for ( col = 0; col < cols; ++col )
  199.         get_pixel( ifp, &(pixels[realrow][col]), (int) tga_head.PixelSize );
  200.     if ( tga_head.IntrLve == TGA_IL_Four )
  201.         truerow += 4;
  202.     else if ( tga_head.IntrLve == TGA_IL_Two )
  203.         truerow += 2;
  204.     else
  205.         ++truerow;
  206.     if ( truerow >= rows )
  207.         truerow = ++baserow;
  208.     }
  209.     pm_close( ifp );
  210.  
  211.     ppm_writeppm( stdout, pixels, cols, rows, (pixval) maxval, 0 );
  212.     pm_close( stdout );
  213.  
  214.     exit( 0 );
  215.     }
  216.  
  217. static void
  218. readtga( ifp, tgaP )
  219.     FILE* ifp;
  220.     struct ImageHeader* tgaP;
  221.     {
  222.     unsigned char flags;
  223.     ImageIDField junk;
  224.  
  225.     tgaP->IDLength = getbyte( ifp );
  226.     tgaP->CoMapType = getbyte( ifp );
  227.     tgaP->ImgType = getbyte( ifp );
  228.     tgaP->Index_lo = getbyte( ifp );
  229.     tgaP->Index_hi = getbyte( ifp );
  230.     tgaP->Length_lo = getbyte( ifp );
  231.     tgaP->Length_hi = getbyte( ifp );
  232.     tgaP->CoSize = getbyte( ifp );
  233.     tgaP->X_org_lo = getbyte( ifp );
  234.     tgaP->X_org_hi = getbyte( ifp );
  235.     tgaP->Y_org_lo = getbyte( ifp );
  236.     tgaP->Y_org_hi = getbyte( ifp );
  237.     tgaP->Width_lo = getbyte( ifp );
  238.     tgaP->Width_hi = getbyte( ifp );
  239.     tgaP->Height_lo = getbyte( ifp );
  240.     tgaP->Height_hi = getbyte( ifp );
  241.     tgaP->PixelSize = getbyte( ifp );
  242.     flags = getbyte( ifp );
  243.     tgaP->AttBits = flags & 0xf;
  244.     tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
  245.     tgaP->OrgBit = ( flags & 0x20 ) >> 5;
  246.     tgaP->IntrLve = ( flags & 0xc0 ) >> 6;
  247.  
  248.     if ( tgaP->IDLength != 0 )
  249.     fread( junk, 1, (int) tgaP->IDLength, ifp );
  250.     }
  251.  
  252. static void
  253. get_map_entry( ifp, Value, Size )
  254.     FILE* ifp;
  255.     pixel* Value;
  256.     int Size;
  257.     {
  258.     unsigned char j, k, r, g, b;
  259.  
  260.     /* Read appropriate number of bytes, break into rgb & put in map. */
  261.     switch ( Size )
  262.     {
  263.     case 8:                /* Grey scale, read and triplicate. */
  264.     r = g = b = getbyte( ifp );
  265.     break;
  266.  
  267.     case 16:            /* 5 bits each of red green and blue. */
  268.     case 15:            /* Watch for byte order. */
  269.     j = getbyte( ifp );
  270.     k = getbyte( ifp );
  271.     r = ( k & 0x7C ) >> 2;
  272.     g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
  273.     b = j & 0x1F;
  274.     break;
  275.  
  276.     case 32:
  277.     case 24:            /* 8 bits each of blue green and red. */
  278.     b = getbyte( ifp );
  279.     g = getbyte( ifp );
  280.     r = getbyte( ifp );
  281.     if ( Size == 32 )
  282.         (void) getbyte( ifp );    /* Read alpha byte & throw away. */
  283.     break;
  284.  
  285.     default:
  286.     pm_error( "unknown colormap pixel size (#2) - %d", Size );
  287.     }
  288.     PPM_ASSIGN( *Value, r, g, b );
  289.     }
  290.  
  291. static void
  292. get_pixel( ifp, dest, Size )
  293.     FILE* ifp;
  294.     pixel* dest;
  295.     int Size;
  296.     {
  297.     static pixval Red, Grn, Blu;
  298.     unsigned char j, k;
  299.     static unsigned int l;
  300.  
  301.     /* Check if run length encoded. */
  302.     if ( rlencoded )
  303.     {
  304.     if ( RLE_count == 0 )
  305.         { /* Have to restart run. */
  306.         unsigned char i;
  307.         i = getbyte( ifp );
  308.         RLE_flag = ( i & 0x80 );
  309.         if ( RLE_flag == 0 )
  310.         /* Stream of unencoded pixels. */
  311.         RLE_count = i + 1;
  312.         else
  313.         /* Single pixel replicated. */
  314.         RLE_count = i - 127;
  315.         /* Decrement count & get pixel. */
  316.         --RLE_count;
  317.         }
  318.     else
  319.         { /* Have already read count & (at least) first pixel. */
  320.         --RLE_count;
  321.         if ( RLE_flag != 0 )
  322.         /* Replicated pixels. */
  323.         goto PixEncode;
  324.         }
  325.     }
  326.     /* Read appropriate number of bytes, break into RGB. */
  327.     switch ( Size )
  328.     {
  329.     case 8:                /* Grey scale, read and triplicate. */
  330.     Red = Grn = Blu = l = getbyte( ifp );
  331.     break;
  332.  
  333.     case 16:            /* 5 bits each of red green and blue. */
  334.     case 15:            /* Watch byte order. */
  335.     j = getbyte( ifp );
  336.     k = getbyte( ifp );
  337.     l = ( (unsigned int) k << 8 ) + j;
  338.     Red = ( k & 0x7C ) >> 2;
  339.     Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
  340.     Blu = j & 0x1F;
  341.     break;
  342.  
  343.     case 32:
  344.     case 24:            /* 8 bits each of blue green and red. */
  345.     Blu = getbyte( ifp );
  346.     Grn = getbyte( ifp );
  347.     Red = getbyte( ifp );
  348.     if ( Size == 32 )
  349.         (void) getbyte( ifp );    /* Read alpha byte & throw away. */
  350.     l = 0;
  351.     break;
  352.  
  353.     default:
  354.     pm_error( "unknown pixel size (#2) - %d", Size );
  355.     }
  356.  
  357. PixEncode:
  358.     if ( mapped )
  359.     *dest = ColorMap[l];
  360.     else
  361.     PPM_ASSIGN( *dest, Red, Grn, Blu );
  362.     }
  363.  
  364. static unsigned char
  365. getbyte( ifp )
  366.     FILE* ifp;
  367.     {
  368.     unsigned char c;
  369.  
  370.     if ( fread( (char*) &c, 1, 1, ifp ) != 1 )
  371.     pm_error( "EOF / read error" );
  372.  
  373.     return c;
  374.     }
  375.