home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / fbm / part06 / fltga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-08  |  12.9 KB  |  551 lines

  1. /*****************************************************************
  2.  * fltga.c: FBM Library 0.93 (Beta Test) 03-May-89  Ian MacPhedran
  3.  *
  4.  * Author Ian MacPhedran.
  5.  * Permission is given to use any portion of this file, (including
  6.  * its entirety) for whatever you wish. Howvever, please note that
  7.  * it was written for Michael Mauldin's FBM Library, and conditions
  8.  * therein are more restrictive.
  9.  *
  10.  * CONTENTS
  11.  *    read_tga (image, rfile, mstr, mlen)
  12.  *    write_tga (image, wfile)
  13.  *
  14.  * EDITLOG
  15.  *    LastEditDate = Sat May 20 19:53:58 1989 - Michael Mauldin
  16.  *    LastFileName = /usr2/mlm/src/misc/fbm/fltga.c
  17.  *
  18.  * HISTORY
  19.  * 03-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  20.  *    Beta release (version 0.93) mlm@cs.cmu.edu
  21.  *
  22.  * HISTORY
  23.  * 13-Mar-89  Ian J. MacPhedran
  24.  *    Add write_tga
  25.  *
  26.  * 07-Mar-89  Ian J. MacPhedran, University of Saskatchewan.
  27.  *    Created.
  28.  *****************************************************************/
  29.  
  30. #include <stdio.h>
  31. #include "fbm.h"
  32.  
  33. #ifndef lint
  34. static char *fbmid =
  35.     "$FBM fltga.c <0.93> 03-May-89  (C) 1989 by Ian MacPhedran$";
  36. #endif
  37.  
  38.  
  39. /* For convenience, the TGA header file is included herein. */
  40.  
  41. /*
  42.  * Header file for Targa file definitions.
  43.  *
  44.  * These definitions will allow a consistant interface to build Targa (.TGA)
  45.  * image files.
  46.  *
  47.  * Created NOV-15-1988 IJMP
  48.  *
  49.  */
  50.  
  51. /* File header definition */
  52.  
  53. struct TGA_ImageHeader {
  54.         unsigned char IDLength;/* Length of Identifier String */
  55.         unsigned char CoMapType; /* 0 = NoMap */
  56.         unsigned char ImgType;    /* Image Type (1,2,3,9,10) */
  57.         unsigned char Index_lo, Index_hi;
  58.             /* Index of first colour map entry */
  59.         unsigned char Length_lo, Length_hi;
  60.             /* Length of colour map (number of entries) */
  61.         unsigned char CoSize;    /* Length of colour map entry */
  62.         unsigned char X_org_lo, X_org_hi;    /* X Origin of Image */
  63.         unsigned char Y_org_lo, Y_org_hi;    /* Y Origin of Image */
  64.         unsigned char Width_lo, Width_hi;    /* Width of Image */
  65.         unsigned char Height_lo, Height_hi;    /* Height of Image */
  66.         unsigned char PixelSize;    /* Pixel Size (8,16,24) */
  67.         unsigned AttBits : 4;    /* Number of Attribute Bits per pixel */
  68.         unsigned Rsrvd   : 1;    /* Reserved bit */
  69.         unsigned OrgBit  : 1;
  70.             /* Origin Bit (0=lower left, 1=upper left) */
  71.         unsigned IntrLve : 2;    /* Interleaving Flag */
  72.         };
  73.  
  74. char TGA_ImageIDField[256];
  75.  
  76. /* Definitions for Image Types */
  77.  
  78. #define TGA_MapRGBType 1
  79. #define TGA_RawRGBType 2
  80. #define TGA_RawMonoType 3
  81. #define TGA_MapEnCodeType 9
  82. #define TGA_RawEnCodeType 10
  83.  
  84. /*
  85.  * read_tga(image, rfile, mstr, mlen)
  86.  * from tga2rast.c:
  87.  * Version 1.0 - first released for public consumption, 21 Feb, 1989
  88.  *
  89.  */
  90.  
  91. #define MAXCOLOURS 16384
  92.  
  93. /* Define flags for mode - these indicate special conditions */
  94. #define GREYSC 0
  95. #define COLOUR 1
  96. #define MAPPED 2
  97. #define RLENCD 4
  98. #define INTERL 8
  99. #define FOURWY 16
  100.  
  101. unsigned char ColourMap[MAXCOLOURS][3];
  102. int RLE_count=0,RLE_flag=0;
  103.  
  104. read_tga(image, rfile, mstr, mlen)
  105. FBM *image;
  106. FILE *rfile;
  107. char *mstr;
  108. int mlen;
  109. {
  110. /* Define Identifiers */
  111. struct TGA_ImageHeader    *tga;
  112. int            i, j;
  113. unsigned int        temp1, temp2, mode;
  114. unsigned char        r, g, b;
  115. unsigned long        k, baseline,linewidth;
  116. unsigned char        *Red, *Grn, *Blu, *Redk, *Grnk, *Bluk;
  117.  
  118. /* Input the Targa file header */
  119.     if ((tga=(struct TGA_ImageHeader *)
  120.          malloc(sizeof(struct TGA_ImageHeader))) == NULL)
  121.     {
  122.         fprintf(stderr,"Can't allocate TGA memory\n");
  123.         exit(1);
  124.     }
  125.  
  126.     if ((i = fread(tga,1,18,rfile)) != 18)
  127.     {
  128.         fprintf(stderr,"Read only %d bytes in header\n",i);
  129.         exit(1);
  130.     }
  131.     switch (tga->ImgType)
  132.     {
  133.         case TGA_MapRGBType:
  134.         case TGA_RawRGBType:
  135.         case TGA_RawMonoType:
  136.         case TGA_MapEnCodeType:
  137.         case TGA_RawEnCodeType:
  138.             break;
  139.  
  140.         default:
  141.             fprintf(stderr,"Targa File Type %d",tga->ImgType);
  142.             fprintf(stderr," not supported!\n");
  143.             exit(1);
  144.     }
  145.  
  146. /* Create output image header */
  147.     temp1 = tga->Height_lo; temp2 = tga->Height_hi;
  148.     image->hdr.rows = temp1 + temp2 * 256;
  149.     temp1 = tga->Width_lo; temp2 = tga->Width_hi;
  150.     image->hdr.cols = temp1 + temp2 * 256;
  151.     /* If this is odd number of bytes, add one */
  152.     if ((image->hdr.cols & 1) != 0) image->hdr.cols++;
  153.  
  154. /* If greyscale, use only one plane */
  155.     if (tga->ImgType == TGA_RawMonoType)
  156.     {
  157.         image->hdr.planes = 1;
  158.         mode = GREYSC;
  159.     }
  160.     else
  161.     {
  162.         image->hdr.planes = 3;
  163.         mode = COLOUR;
  164.     }
  165.  
  166. /* Uses 8 bits, sort of - 16 bits/pixel is 5 bits per colour */
  167.     image->hdr.bits = 8;
  168.     image->hdr.physbits = 8;
  169.     image->hdr.rowlen = image->hdr.cols;
  170.     image->hdr.plnlen = image->hdr.rows * image->hdr.cols;
  171. /* Ignore colour map for this version. */
  172.     image->hdr.clrlen = 0;
  173.     image->hdr.aspect = 1.0;
  174.     image->hdr.title[0] = '\0';
  175.     image->hdr.credits[0] = '\0';
  176.  
  177. /* Get the Image */
  178.     alloc_fbm(image);
  179.  
  180. /* Read ID String, if present */
  181.     if (tga->IDLength != 0)
  182.         fread(TGA_ImageIDField,1,tga->IDLength,rfile);
  183.  
  184. /* If present, read the colour map information */
  185.         if (tga->CoMapType != 0)
  186.         {
  187.         temp1 = tga->Index_lo + tga->Index_hi * 256;
  188.         temp2 = tga->Length_lo + tga->Length_hi * 256;
  189.         if ((temp1+temp2+1) >= MAXCOLOURS)
  190.         {
  191.             fprintf(stderr,"Too many colours %d\n",(temp1+temp2+1));
  192.             exit(1);
  193.         }
  194.         for (i=temp1; i<(temp1+temp2); i++)
  195.             get_map_entry(&ColourMap[i][0],&ColourMap[i][1],
  196.             &ColourMap[i][2],tga->CoSize,mode);
  197.         if ((tga->ImgType != TGA_RawRGBType) &&
  198.             (tga->ImgType != TGA_RawMonoType) &&
  199.             (tga->ImgType != TGA_RawEnCodeType))
  200.             mode = mode | MAPPED;
  201.     }
  202.  
  203. /* Check Run Length Encoding */
  204.     if ((tga->ImgType == TGA_MapEnCodeType) || 
  205.         (tga->ImgType == TGA_RawEnCodeType))
  206.         mode = mode | RLENCD;
  207.  
  208. /* Check for interlacing of the Targa file */
  209.     switch (tga->IntrLve)
  210.     {
  211.         case 2: /* Four way interlace */
  212.             mode = mode | FOURWY;
  213.         case 1: /* Two way interlace */
  214.             mode = mode | INTERL;
  215.         case 0: /* No interlace */
  216.             break;
  217.         default: /* Reserved - we'll let it pass */
  218.             break;
  219.     }
  220.  
  221. /* Set up byte map for writing */
  222.  
  223.     Red = image->bm;
  224.     if ((mode & COLOUR) != GREYSC)
  225.     {
  226.         Grn = Red + image->hdr.plnlen;
  227.         Blu = Grn + image->hdr.plnlen;
  228.     }
  229. /* Read the Targa file body and convert to image format */
  230.     linewidth = tga->Width_lo + tga->Width_hi * 256;
  231.     for (i=0; i< image->hdr.rows; i++)
  232.     {
  233.         /* No interlace */
  234.         if ((mode & INTERL) == 0)
  235.         {
  236.             j = i;
  237.         }
  238.         /* Two way interlace */
  239.         else if ((mode & FOURWY) != 0)
  240.         {
  241.             if (2*i < image->hdr.rows)
  242.                 j = 2*i;
  243.             else
  244.             {
  245.                 j = i - image->hdr.rows/2;
  246.                 j = 2*j + 1;
  247.             }
  248.         }
  249.         /* Four way interlace */
  250.         else
  251.         {
  252.             if (4*i < image->hdr.rows)
  253.                 j = 4*i;
  254.             else if (2*i < image->hdr.rows)
  255.             {
  256.                 j = i - image->hdr.rows/4;
  257.                 j = 4*j + 1;
  258.             }
  259.             else if (4*i < 3*image->hdr.rows)
  260.             {
  261.                 j = i - image->hdr.rows/2;
  262.                 j = 4*j + 2;
  263.             }
  264.             else
  265.             {
  266.                 j = i - image->hdr.rows/2 - image->hdr.rows/4;
  267.                 j = 4*j + 3;
  268.             }
  269.         }
  270.         k = (image->hdr.rows - 1 - j) * image->hdr.cols;
  271.         Redk = Red + k;
  272.         if ((mode & COLOUR) != GREYSC)
  273.         {
  274.             Grnk = Grn + k; Bluk = Blu + k;
  275.         }
  276.         for (j=0; j<linewidth; j++)
  277.         {
  278.             get_pixel(&r,&g,&b,tga->PixelSize,mode);
  279.             *Redk++=r;
  280.             if ((mode & COLOUR) != GREYSC)
  281.             {
  282.                 *Grnk++=g; *Bluk++=b;
  283.             }
  284.         }
  285.     }
  286.     free(tga);
  287.  
  288.     return (1);
  289. }
  290.  
  291.  
  292. get_map_entry(Red,Grn,Blu,Size,mode)
  293. unsigned char     *Red,*Grn,*Blu;
  294. int     Size,mode;
  295. {
  296. unsigned int j,k,l;
  297. unsigned char i,r,g,b;
  298.  
  299.         /* read appropriate number of bytes, break into rgb & put in map */
  300.         switch (Size)
  301.         {
  302.             case 8: /* Grey Scale already, read and triplicate */
  303.                     fread(&i,1,1,stdin);
  304.             r = i; g = i; b = i;
  305.                     break;
  306.  
  307.             case 16: /* 5 bits each of red green and blue */
  308.             case 15: /* Watch for byte order */
  309.                     fread(&j,1,1,stdin);
  310.                     fread(&k,1,1,stdin);
  311.                     l = j + k*256;
  312.                     r = ((l >> 10) & 31) << 3;
  313.                     g = ((l >>  5) & 31) << 3;
  314.                     b = (l & 31) << 3;
  315.                     break;
  316.  
  317.             case 32: /* Read alpha byte & throw away */
  318.                     fread(&i,1,1,stdin);
  319.             case 24: /* Eight bits each of red green and blue */
  320.                     fread(&i,1,1,stdin); r = i;
  321.                     fread(&i,1,1,stdin); g = i;
  322.                     fread(&i,1,1,stdin); b = i;
  323.                     break;
  324.  
  325.             default:
  326.                     fprintf(stderr,"Unknown Pixel Size\n"); exit(1);
  327.         }
  328.     *Red = r; *Grn = g; *Blu = b;
  329. }
  330.  
  331. get_pixel(rRed,rGrn,rBlu,Size,mode)
  332. unsigned char *rRed,*rGrn,*rBlu;
  333. int Size,mode;
  334. {
  335.     static unsigned char Red, Grn, Blu;
  336.     unsigned char i,j,k;
  337.     static unsigned int l;
  338.  
  339.     /* Check if run length encoded. */
  340.     if ((mode & RLENCD) != 0)
  341.     {
  342.         if (RLE_count == 0) /* Have to restart run */
  343.         {
  344.             fread(&i,1,1,stdin);
  345.             RLE_flag = (i & 0x80) >> 7;
  346.             if (RLE_flag == 0)
  347.             { /* Stream of unencoded pixels */
  348.                 RLE_count = i + 1;
  349.             }
  350.             else
  351.             { /* Single pixel replicated */
  352.                 RLE_count = i - 127;
  353.             }
  354.             RLE_count--; /* Decrement count & get pixel */
  355.         }
  356.         else
  357.         { /* Have already read count & (at least) first pixel */
  358.             RLE_count--;
  359.             if (RLE_flag != 0)
  360.             { /* Replicated pixels */
  361.                 goto PixEncode;
  362.             }
  363.         }
  364.     }
  365.     /* Read appropriate number of bytes, break into RGB */
  366.     switch(Size)
  367.     {
  368.     case 8: /* Grey Scale - read a byte and triplicate */
  369.         fread(&i,1,1,stdin);
  370.         Red = i; Grn = i; Blu = i; l = i;
  371.         break;
  372.  
  373.     case 16: /* Five bits each of red green and blue */
  374.     case 15: /* Watch byte order */
  375.         fread(&j,1,1,stdin);
  376.         fread(&k,1,1,stdin);
  377.         l = j + k*256;
  378.         Red = ((k & 0x7C) << 1);
  379.         Grn = ((k & 0x03) << 6) + ((j & 0xE0) >> 2);
  380.         Blu = ((j & 0x1F) << 3);
  381.         break;
  382.  
  383.     case 32: /* Read alpha byte & throw away */
  384.         fread(&i,1,1,stdin);
  385.     case 24: /* Eight bits each of red green and blue */
  386.         fread(&i,1,1,stdin); Red = i;
  387.         fread(&i,1,1,stdin); Grn = i;
  388.         fread(&i,1,1,stdin); Blu = i;
  389.         l = 0;
  390.         break;
  391.  
  392.     default:
  393.         fprintf(stderr,"Unknown Pixel Size\n"); exit(1);
  394.     }
  395.  
  396. PixEncode:
  397.     if ((mode & MAPPED) == MAPPED)
  398.     {
  399.         *rRed = ColourMap[l][0];
  400.         *rGrn = ColourMap[l][1];
  401.         *rBlu = ColourMap[l][2];
  402.     }
  403.     else
  404.     {
  405.         *rRed = Red;
  406.         *rGrn = Grn;
  407.         *rBlu = Blu;
  408.     }
  409. }
  410.  
  411. /*
  412.  * write_tga(image, wfile)
  413.  *
  414.  */
  415. write_tga(image, wfile)
  416. FBM *image;
  417. FILE *wfile;
  418. {
  419. unsigned char        *Red, *Grn, *Blu, *Redk, *Grnk, *Bluk;
  420. unsigned char        *Redc, *Grnc, *Bluc, *Redck, *Grnck, *Bluck;
  421. struct TGA_ImageHeader    *tga;
  422. unsigned char        buffer[MAXCOLOURS];
  423. unsigned int        mode;
  424. unsigned long        index, index2;
  425. int            i, j, k, l;
  426.  
  427.     if (image->hdr.cols > (MAXCOLOURS / 2))
  428.     {
  429.         fprintf(stderr,"Line too wide is %d, must be %d\n",
  430.         image->hdr.cols, MAXCOLOURS/2);
  431.         exit(1);
  432.     }
  433.  
  434.     if ((image->hdr.planes != 1) && (image->hdr.planes != 3))
  435.     {
  436.         fprintf(stderr,"TGA files must 1 or 3 planes deep\n");
  437.         exit(1);
  438.     }
  439.     if (image->hdr.planes == 1) mode = GREYSC;
  440.     else mode = COLOUR;
  441.     
  442.     if ((tga=(struct TGA_ImageHeader *)
  443.              malloc(sizeof(struct TGA_ImageHeader))) == NULL)
  444.     {
  445.         fprintf(stderr,"Can't allocate TGA memory\n");
  446.         exit(1);
  447.     }
  448.     tga->IDLength = 0; /* Don't write ID into file */
  449.     tga->CoMapType = 0; /* Use raw bytes, not mapped */
  450.     
  451.     tga->ImgType = TGA_RawRGBType;
  452.     if ((mode & COLOUR) == GREYSC) tga->ImgType = TGA_RawMonoType;
  453.     
  454.     tga->Index_hi = 0; tga->Index_lo = 0; /* Colour Mapped stuff */
  455.     tga->Length_hi = 0; tga->Length_lo = 0;
  456.     tga->CoSize = 8;
  457.  
  458.     tga->X_org_lo = 0; tga->X_org_hi = 0; /* Origin at 0,0 */
  459.     tga->Y_org_lo = 0; tga->Y_org_hi = 0;
  460.  
  461.     tga->Width_hi = (unsigned char)(image->hdr.cols / 256);
  462.     tga->Width_lo = (unsigned char)(image->hdr.cols % 256);
  463.     tga->Height_hi = (unsigned char)(image->hdr.rows / 256);
  464.     tga->Height_lo = (unsigned char)(image->hdr.rows % 256);
  465.     
  466.     tga->PixelSize = 16;
  467.     if ((mode & COLOUR) == GREYSC) tga->PixelSize = 8;
  468.     
  469.     /* All funny bits set to zero */
  470.     tga->AttBits = 0; tga->Rsrvd = 0; tga->OrgBit; tga->IntrLve = 0;
  471.  
  472.     fwrite(tga,1,18,wfile); /* Write out header */
  473.  
  474.     Red = image->bm;
  475.     l = image->hdr.cols;
  476.     if ((mode & COLOUR) == COLOUR)
  477.     {
  478.         l = l * 2;
  479.         Grn = Red + image->hdr.plnlen;
  480.         Blu = Grn + image->hdr.plnlen;
  481.     }
  482.  
  483.     if (image->hdr.clrlen > 0)
  484.     {
  485.         mode = mode | MAPPED;
  486.         Redc = image->cm;
  487.         if ((mode & COLOUR) == COLOUR)
  488.         {
  489.             Grnc = Redc + image->hdr.clrlen/3;
  490.             Bluc = Grnc + image->hdr.clrlen/3;
  491.         }
  492.     }
  493.     
  494.     Redk = Red + image->hdr.plnlen - image->hdr.cols;
  495.     if ((mode & COLOUR) == COLOUR)
  496.     {
  497.         Grnk = Grn + image->hdr.plnlen - image->hdr.cols;
  498.         Bluk = Blu + image->hdr.plnlen - image->hdr.cols;
  499.     }
  500.  
  501.     /* Okay, ready to write */
  502.     for (j=0; j<image->hdr.rows; j++)
  503.     {
  504.     for (i=0; i<image->hdr.cols; i++)
  505.     {
  506.         index = *Redk++;
  507.         if ((mode & COLOUR) == COLOUR)
  508.             index = (index << 16) + ((*Grnk++) << 8) +  *Bluk++;
  509.  
  510.         if ((mode & MAPPED) == MAPPED)
  511.         {
  512.             index2 = index;
  513.             Redck = Redc + index2;
  514.             index = *Redck;
  515.             if ((mode & COLOUR) == COLOUR)
  516.             {
  517.                 Grnck = Grnc + index2; Bluck = Bluc + index2;
  518.                 index = (index << 16) +
  519.                     ((unsigned long)*Grnck << 8) +
  520.                     *Bluck;
  521.             }
  522.         }
  523.         
  524.         if ((mode & COLOUR) == COLOUR)
  525.         {
  526.             index2 = ((index & 0x00f80000) >> 9)
  527.                    + ((index & 0x0000f800) >> 6)
  528.                    + ((index & 0x000000f8) >> 3);
  529.             k = 2 * i;
  530.             buffer[k] = (unsigned char)(index2 % 256);
  531.             k = k + 1;
  532.             buffer[k] = (unsigned char)(index2 / 256);
  533.         }
  534.         else
  535.         {
  536.             buffer[i] = (unsigned char)index;
  537.         }
  538.     }
  539.     fwrite(buffer,l,1,wfile);
  540.     Redk = Redk - 2 * image->hdr.cols;
  541.     if ((mode & COLOUR) == COLOUR)
  542.     {
  543.         Grnk = Grnk - 2 * image->hdr.cols;
  544.         Bluk = Bluk - 2 * image->hdr.cols;
  545.     }
  546.     }
  547.     free(tga);
  548.     
  549.     return (1);
  550. }
  551.