home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / fltga.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  18KB  |  549 lines

  1. /*****************************************************************
  2.  * fltga.c:  FBM Release 1.0 25-Feb-90 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.  * FBM is Copyright (C) 1989,1990 by Michael Mauldin.  Permission
  11.  * is granted to use this file in whole or in part for any purpose,
  12.  * educational, recreational or commercial, provided that this
  13.  * copyright notice is retained unchanged.  This software is
  14.  * available to all free of charge by anonymous FTP and in the
  15.  * UUNET archives.
  16.  *
  17.  * CONTENTS
  18.  *    read_tga (image, rfile, mstr, mlen)
  19.  *    write_tga (image, wfile)
  20.  *
  21.  * HISTORY
  22.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  23.  *    Package for Release 1.0
  24.  *
  25.  * 13-Mar-89  Ian J. MacPhedran
  26.  *    Add write_tga
  27.  *
  28.  * 07-Mar-89  Ian J. MacPhedran, University of Saskatchewan.
  29.  *    Created.
  30.  *****************************************************************/
  31.  
  32. #include <stdio.h>
  33. #include "fbm.h"
  34.  
  35. #ifndef lint
  36. static char *fbmid =
  37. "$FBM fltga.c <1.0> 25-Jun-90  by Ian MacPhedran, source code available \
  38. free from MLM@CS.CMU.EDU and from UUNET archives$";
  39. #endif
  40.  
  41. /* For convenience, the TGA header file is included herein. */
  42.  
  43. /*
  44.  * Header file for Targa file definitions.
  45.  *
  46.  * These definitions will allow a consistant interface to build Targa (.TGA)
  47.  * image files.
  48.  *
  49.  * Created NOV-15-1988 IJMP
  50.  *
  51.  */
  52.  
  53. /* File header definition */
  54.  
  55. struct TGA_ImageHeader {
  56.                 unsigned char IDLength;/* Length of Identifier String */
  57.                 unsigned char CoMapType; /* 0 = NoMap */
  58.                 unsigned char ImgType;  /* Image Type (1,2,3,9,10) */
  59.                 unsigned char Index_lo, Index_hi;
  60.                         /* Index of first colour map entry */
  61.                 unsigned char Length_lo, Length_hi;
  62.                         /* Length of colour map (number of entries) */
  63.                 unsigned char CoSize;   /* Length of colour map entry */
  64.                 unsigned char X_org_lo, X_org_hi;       /* X Origin of Image */
  65.                 unsigned char Y_org_lo, Y_org_hi;       /* Y Origin of Image */
  66.                 unsigned char Width_lo, Width_hi;       /* Width of Image */
  67.                 unsigned char Height_lo, Height_hi;     /* Height of Image */
  68.                 unsigned char PixelSize;        /* Pixel Size (8,16,24) */
  69.                 unsigned AttBits : 4;   /* Number of Attribute Bits per pixel */
  70.                 unsigned Rsrvd   : 1;   /* Reserved bit */
  71.                 unsigned OrgBit  : 1;
  72.                         /* Origin Bit (0=lower left, 1=upper left) */
  73.                 unsigned IntrLve : 2;   /* Interleaving Flag */
  74.                 };
  75.  
  76. char TGA_ImageIDField[256];
  77.  
  78. /* Definitions for Image Types */
  79.  
  80. #define TGA_MapRGBType 1
  81. #define TGA_RawRGBType 2
  82. #define TGA_RawMonoType 3
  83. #define TGA_MapEnCodeType 9
  84. #define TGA_RawEnCodeType 10
  85.  
  86. /*
  87.  * read_tga(image, rfile, mstr, mlen)
  88.  * from tga2rast.c:
  89.  * Version 1.0 - first released for public consumption, 21 Feb, 1989
  90.  *
  91.  */
  92.  
  93. #define MAXCOLOURS 16384
  94.  
  95. /* Define flags for mode - these indicate special conditions */
  96. #define GREYSC 0
  97. #define COLOUR 1
  98. #define MAPPED 2
  99. #define RLENCD 4
  100. #define INTERL 8
  101. #define FOURWY 16
  102.  
  103. unsigned char ColourMap[MAXCOLOURS][3];
  104. int RLE_count=0,RLE_flag=0;
  105.  
  106. read_tga(image, rfile, mstr, mlen)
  107. FBM *image;
  108. FILE *rfile;
  109. char *mstr;
  110. int mlen;
  111. {
  112. /* Define Identifiers */
  113. struct TGA_ImageHeader  *tga;
  114. int                     i, j, l;
  115. unsigned int            temp1, temp2, mode;
  116. unsigned char           r, g, b;
  117. unsigned long           k, baseline,linewidth;
  118. unsigned char           *Red, *Grn, *Blu, *Redk, *Grnk, *Bluk;
  119.  
  120. /* Input the Targa file header */
  121.         if ((tga=(struct TGA_ImageHeader *)
  122.                 malloc(sizeof(struct TGA_ImageHeader))) == NULL)
  123.         {
  124.                 fprintf(stderr,"Can't allocate TGA memory\n");
  125.                 exit(1);
  126.         }
  127.  
  128.         if ((i = fread(tga,1,18,rfile)) != 18)
  129.         {
  130.                 fprintf(stderr,"Read only %d bytes in header\n",i);
  131.                 exit(1);
  132.         }
  133.         switch (tga->ImgType)
  134.         {
  135.                 case TGA_MapRGBType:
  136.                 case TGA_RawRGBType:
  137.                 case TGA_RawMonoType:
  138.                 case TGA_MapEnCodeType:
  139.                 case TGA_RawEnCodeType:
  140.                         break;
  141.  
  142.                 default:
  143.                         fprintf(stderr,"Targa File Type %d",tga->ImgType);
  144.                         fprintf(stderr," not supported!\n");
  145.                         exit(1);
  146.         }
  147.  
  148. /* Create output image header */
  149.         temp1 = tga->Height_lo; temp2 = tga->Height_hi;
  150.         image->hdr.rows = temp1 + temp2 * 256;
  151.         temp1 = tga->Width_lo; temp2 = tga->Width_hi;
  152.         image->hdr.cols = temp1 + temp2 * 256;
  153.         /* If this is odd number of bytes, add one */
  154.         if ((image->hdr.cols & 1) != 0) image->hdr.cols++;
  155.  
  156. /* If greyscale, use only one plane */
  157.         if (tga->ImgType == TGA_RawMonoType)
  158.         {
  159.                 image->hdr.planes = 1;
  160.                 mode = GREYSC;
  161.         }
  162.         else
  163.         {
  164.                 image->hdr.planes = 3;
  165.                 mode = COLOUR;
  166.         }
  167.  
  168. /* Uses 8 bits, sort of - 16 bits/pixel is 5 bits per colour */
  169.         image->hdr.bits = 8;
  170.         image->hdr.physbits = 8;
  171.         image->hdr.rowlen = image->hdr.cols;
  172.         image->hdr.plnlen = image->hdr.rows * image->hdr.cols;
  173. /* Ignore colour map for this version. */
  174.         image->hdr.clrlen = 0;
  175.         image->hdr.aspect = 1.0;
  176.         image->hdr.title[0] = '\0';
  177.         image->hdr.credits[0] = '\0';
  178.  
  179. /* Get the Image */
  180.         alloc_fbm(image);
  181.  
  182. /* Read ID String, if present */
  183.         if (tga->IDLength != 0)
  184.                 fread(TGA_ImageIDField,1,tga->IDLength,rfile);
  185.  
  186. /* If present, read the colour map information */
  187.         if (tga->CoMapType != 0)
  188.         {
  189.                 temp1 = tga->Index_lo + tga->Index_hi * 256;
  190.                 temp2 = tga->Length_lo + tga->Length_hi * 256;
  191.                 if ((temp1+temp2+1) >= MAXCOLOURS)
  192.                 {
  193.                         fprintf(stderr,"Too many colours %d\n",(temp1+temp2+1));
  194.                         exit(1);
  195.                 }
  196.                 for (i=temp1; i<(temp1+temp2); i++)
  197.                         get_map_entry(&ColourMap[i][0],&ColourMap[i][1],
  198.                         &ColourMap[i][2],tga->CoSize,mode);
  199.                 if ((tga->ImgType != TGA_RawRGBType) &&
  200.                         (tga->ImgType != TGA_RawMonoType) &&
  201.                         (tga->ImgType != TGA_RawEnCodeType))
  202.                         mode = mode | MAPPED;
  203.         }
  204.  
  205. /* Check Run Length Encoding */
  206.         if ((tga->ImgType == TGA_MapEnCodeType) ||
  207.                 (tga->ImgType == TGA_RawEnCodeType))
  208.                 mode = mode | RLENCD;
  209.  
  210. /* Check for interlacing of the Targa file */
  211.         switch (tga->IntrLve)
  212.         {
  213.                 case 2: /* Four way interlace */
  214.                         mode = mode | FOURWY;
  215.                 case 1: /* Two way interlace */
  216.                         mode = mode | INTERL;
  217.                 case 0: /* No interlace */
  218.                         break;
  219.                 default: /* Reserved - we'll let it pass */
  220.                         break;
  221.         }
  222.  
  223. /* Set up byte map for writing */
  224.  
  225.         Red = image->bm;
  226.         if ((mode & COLOUR) != GREYSC)
  227.         {
  228.                 Grn = Red + image->hdr.plnlen;
  229.                 Blu = Grn + image->hdr.plnlen;
  230.         }
  231. /* Read the Targa file body and convert to image format */
  232.         linewidth = tga->Width_lo + tga->Width_hi * 256;
  233.         for (i=0; i< image->hdr.rows; i++)
  234.         {
  235.                 /* No interlace */
  236.                 if ((mode & INTERL) == 0)
  237.                 {
  238.                         j = i;
  239.                 }
  240.                 /* Two way interlace */
  241.                 else if ((mode & FOURWY) != 0)
  242.                 {
  243.                         if (2*i < image->hdr.rows)
  244.                                 j = 2*i;
  245.                         else
  246.                         {
  247.                                 j = i - image->hdr.rows/2;
  248.                                 j = 2*j + 1;
  249.                         }
  250.                 }
  251.                 /* Four way interlace */
  252.                 else
  253.                 {
  254.                         if (4*i < image->hdr.rows)
  255.                                 j = 4*i;
  256.                         else if (2*i < image->hdr.rows)
  257.                         {
  258.                                 j = i - image->hdr.rows/4;
  259.                                 j = 4*j + 1;
  260.                         }
  261.                         else if (4*i < 3*image->hdr.rows)
  262.                         {
  263.                                 j = i - image->hdr.rows/2;
  264.                                 j = 4*j + 2;
  265.                         }
  266.                         else
  267.                         {
  268.                                 j = i - image->hdr.rows/2 - image->hdr.rows/4;
  269.                                 j = 4*j + 3;
  270.                         }
  271.                 }
  272.                 k = (image->hdr.rows - 1 - j) * image->hdr.cols;
  273.                 Redk = Red + k;
  274.                 if ((mode & COLOUR) != GREYSC)
  275.                 {
  276.                         Grnk = Grn + k; Bluk = Blu + k;
  277.                 }
  278.                 for (j=0; j<linewidth; j++)
  279.                 {
  280.                         get_pixel(&r,&g,&b,tga->PixelSize,mode);
  281.                         *Redk++=r;
  282.                         if ((mode & COLOUR) != GREYSC)
  283.                         {
  284.                                 *Grnk++=g; *Bluk++=b;
  285.                         }
  286.                 }
  287.         }
  288.         free(tga);
  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,m;
  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.                 case 24: /* Eight bits each of red green and blue */
  319.                         fread(&i,1,1,stdin); b = i;
  320.                         fread(&i,1,1,stdin); g = i;
  321.                         fread(&i,1,1,stdin); r = i;
  322.                         if (Size == 32) fread(&i,1,1,stdin);
  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.         case 24: /* Eight bits each of red green and blue */
  385.                 fread(&i,1,1,stdin); Blu = i;
  386.                 fread(&i,1,1,stdin); Grn = i;
  387.                 fread(&i,1,1,stdin); Red = i;
  388.                 if (Size == 32) fread(&i,1,1,stdin);
  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 = 0; 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.