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