home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / rehack / graphics / pcx256.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  6.8 KB  |  318 lines

  1. //---------------------------------------------------------------------------
  2. //
  3. //      File:           PCX256.CPP
  4. //      Path:           ...\REHACK\graphics
  5. //      Version:                2.0
  6. //      Author:            Dave Boynton
  7. //      CIS Id:            71043,317
  8. //      Created On:     January 1992
  9. //      Modified On:    7/25/93
  10. //      Description:    reads/writes 256 color pcx files, including files
  11. //                        embedded in "resource" files.
  12. //      Tabs:           4
  13. //
  14. //---------------------------------------------------------------------------
  15. // extracted/modified from pcxlib 2.0 (c) 1992,1993 David Boynton
  16. // All rights reserved.
  17. //-----------------------------------------------------------------------//
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "..\general\types.hpp"
  22. #include "..\graphics\pcx.hpp"
  23.  
  24. PcxFile256::PcxFile256(char *filename) : PcxFile(filename)
  25. {
  26.     if ( validFlag == false )
  27.         return;
  28.     // else fp is valid and the header's already read in
  29.  
  30.     if ( (header->version != 5) ||
  31.          (header->bitsPixel != 8) ||
  32.          (header->planes != 1) )// planes == 3 indicates 24bit file
  33.         validFlag=false;
  34.  
  35.     if ( validFlag )
  36.     {
  37.         lineBuffer=new byte[bytesPerLine];
  38.         //palette=new struct PCXRGB[256];
  39.         palette=new Palette;
  40.         if ( readPalette() == false )
  41.             delete palette;
  42.     }
  43. }
  44.  
  45. PcxFile256::PcxFile256(FILE *fp) : PcxFile(fp)
  46. {
  47.     if ( (validFlag == false) ||
  48.          (header->version != 5) ||
  49.          (header->bitsPixel != 8) ||
  50.          (header->planes != 1) )// planes == 3 indicates 24bit file
  51.         validFlag=false;
  52.  
  53.     if ( validFlag )
  54.     {
  55.         lineBuffer=new byte[bytesPerLine];
  56.         palette=new Palette;
  57.         if ( readPalette() == false )
  58.             delete palette;
  59.         seekLine(0);
  60.     }
  61. }
  62.  
  63. // open an output file
  64. //     example:    PcxFile256 *pcx=new PcxFile256("name.pcx", 320, 200);
  65. //                pcx.writeHeader();
  66. //                <write lines of data>
  67. //                pcx.writePalette();
  68. //                delete pcx;
  69. PcxFile256::PcxFile256(char *filename, word xSize, word ySize)
  70.     : PcxFile(filename, xSize, ySize)
  71. {
  72.     if ( validFlag )
  73.     {
  74.         header->version=5;
  75.         header->bitsPixel=8;
  76.         header->planes=1;
  77.         palette=new Palette;
  78.         writeHeader();
  79.     }
  80. }
  81.  
  82. PcxFile256::~PcxFile256()
  83. {
  84.     if ( palette )
  85.         delete palette;
  86.     // ~PcxFile() will take care of lineBuffer, header, and fp
  87. }
  88.  
  89. // seek to the begining of line, (0-based)
  90. bool PcxFile256::seekLine(word line)
  91. {
  92.     if ( !validFlag )
  93.         return false;
  94.     if ( line >= vPixels )
  95.         return false;
  96.     fseek(fp, sizeof(PCXH)+filestart, SEEK_SET);
  97.  
  98.     int i;
  99.     for (i=0; i<line; i++)
  100.     {
  101.         if ( !skipLine() )
  102.             return false; // read-error
  103.     }
  104.     return true;
  105. }
  106.  
  107. bool PcxFile256::skipLine(void)
  108. {
  109.     return readLine(NULL,1,0);
  110. }
  111.  
  112. // x0 is first, x1 is the last ...
  113. bool PcxFile256::readLine(byte * destBuffer, word x0, word x1)
  114. {
  115.     if ( destBuffer == NULL )
  116.         return false;
  117.  
  118.     word destIndex; // next char to read into
  119.     word fileIndex; // next logical character to read from file
  120.     word charCount=0;
  121.  
  122.     static word runLength=0;
  123.     static int data;
  124.  
  125.     destIndex=fileIndex=0;
  126.     if ( x1 > bytesPerLine-1 )
  127.         x1=bytesPerLine-1;
  128.  
  129.     // handle left-overs ...
  130.     while(  (runLength) &&
  131.             (fileIndex < bytesPerLine) )
  132.     {
  133.         if ( (fileIndex >= x0) && (fileIndex <= x1) )
  134.         {
  135.             destBuffer[destIndex++]=(char)data;
  136.             charCount++;
  137.         }
  138.         fileIndex++;
  139.         runLength--;
  140.     }
  141.  
  142.     // done with left-overs, now the rest of the line.
  143.     while( fileIndex < bytesPerLine )
  144.     {
  145.         if ( (data=fgetc(fp)) == EOF)
  146.         {
  147.             return false;
  148.         }
  149.  
  150.         // If the two high bits are both set it's a run.
  151.         if ( (word)data >= 0x00c0)
  152.         {
  153.             runLength = data & 0x003f;    // get duplication count
  154.             if ( (data=fgetc(fp)) == EOF)
  155.             {
  156.                 return false;
  157.             }
  158.             while(    (runLength) &&
  159.                     (fileIndex < bytesPerLine) )
  160.             {
  161.                 if ( (fileIndex >= x0) &&
  162.                      (fileIndex <= x1) )
  163.                 {
  164.                     destBuffer[destIndex++]=(char)data;
  165.                     charCount++;
  166.                 }
  167.                 fileIndex++;
  168.                 runLength--;
  169.             } // end while
  170.         } else {    // non-run, single byte of data
  171.             if ( (fileIndex >= x0) &&
  172.                  (fileIndex <= x1) )
  173.             {
  174.                 destBuffer[destIndex++]=(char)data;
  175.                 charCount++;
  176.             }
  177.             fileIndex++;
  178.         } // end if ( (word)data >= 0x00c0) {} else
  179.  
  180.     } // end while( fileIndex < bytesPerLine )
  181.  
  182.     return true;
  183. }
  184.  
  185. // x0 is first column, x1 is last column
  186. // fixes needed: fputc's should be checked for errors
  187. bool PcxFile256::writeLine(byte * srcBuffer, word x0, word x1, byte fill)
  188. {
  189.     word srcIndex=0, fileIndex=0; // next bytes to read/write
  190.     word runLength;
  191.     int last;        // allow -1 for begining flag
  192.     byte data;
  193.     if ( x1 > hPixels-1)
  194.         x1=hPixels-1;
  195.  
  196.     /* pre- fill */
  197.     while (fileIndex < x0 )
  198.     {
  199.         runLength=(x0-fileIndex);
  200.         if ( runLength > 63 )
  201.             runLength=63;
  202.  
  203.         if ( (runLength != 1) || (fill > 191) )
  204.         {
  205.             fputc( ( runLength | 0xc0 ),fp);
  206.         }
  207.         fputc(fill,fp);
  208.         fileIndex+=runLength;
  209.     } // end fill to first column
  210.  
  211.     /* passed data */
  212.     last=-1;
  213.  
  214.     for (runLength=srcIndex=fileIndex=0; srcIndex <= x1; srcIndex++)
  215.     {
  216.         if ( (data=*(srcBuffer+srcIndex)) == last)
  217.         {
  218.             if ( runLength < 63 )
  219.             {
  220.                 runLength++;
  221.                 continue;
  222.             }
  223.         }
  224.         // handle previous run if necessary
  225.         if ( last != -1 )
  226.         {
  227.             if ( (runLength != 1) || (last > 0xbf) )
  228.             {
  229.                 fputc( (runLength | 0xc0),fp);
  230.             }
  231.             fputc(last,fp);
  232.             fileIndex+=runLength;
  233.         } // end if ( last != -1 )
  234.         last=data;
  235.         runLength=1;
  236.     } // end for(...; srcIndex <= x1; srcIndex++)
  237.  
  238.     // left-overs (ie., for() done, but we still have some runLength...)
  239.     if (runLength)
  240.     {
  241.         if ( (runLength != 1) || (last > 0xbfU) )
  242.         {
  243.             fputc( (runLength | 0xc0U),fp);
  244.         }
  245.         fputc(last,fp);
  246.         fileIndex+=runLength;
  247.         runLength=0;
  248.     } // end if (left-overs)
  249.  
  250.     // fill to the end of line
  251.     while (fileIndex < hPixels )
  252.     {
  253.         runLength=(hPixels - fileIndex + 1);
  254.         if ( runLength > 63 )
  255.             runLength=63;
  256.  
  257.         if ( (runLength != 1) || (fill > 191) )
  258.         {
  259.             fputc( ( runLength | 0xc0 ),fp);
  260.         }
  261.         fputc(fill,fp);
  262.         fileIndex+=runLength;
  263.     } // end fill to end-of-line
  264.  
  265.     return true;
  266. }
  267.  
  268. bool PcxFile256::readPalette(void)
  269. {
  270.     char Id256Pal;
  271.     if ( ( filestart != 0L ) || // don't bother with a resource file
  272.          ( fseek(fp, -769, SEEK_END) == -1) ||
  273.          ( fread(&Id256Pal,1,1,fp) != 1) ||
  274.          ( Id256Pal != 0x0cU ) ||
  275.          ( fread(palette, 768, 1, fp) != 1) )
  276.     {
  277.         return false;
  278.     } else {
  279.         return true;
  280.     }
  281. }
  282.  
  283. // assumes we're already in position.
  284. bool PcxFile256::writePalette(void)
  285. {
  286.     if ( (fputc(0x0cU, fp) == EOF) ||
  287.          (fwrite(palette, 768, 1, fp) != 1 ) )
  288.         return false;
  289.     else
  290.         return true;
  291. }
  292.  
  293. void PcxFile256::shiftPaletteDown(void)
  294. {
  295.     int i;
  296.     for (i=0; i<256; i++)
  297.     {
  298.         palette[i].r >>= 2;
  299.         palette[i].g >>= 2;
  300.         palette[i].b >>= 2;
  301.     }
  302. }
  303.  
  304. void PcxFile256::shiftPaletteUp(void)
  305. {
  306.     int i;
  307.     for (i=0; i<256; i++)
  308.     {
  309.         palette[i].r <<= 2;
  310.         palette[i].g <<= 2;
  311.         palette[i].b <<= 2;
  312.     }
  313. }
  314.  
  315.  
  316.  
  317.  
  318.