home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / Drtf / DGIFHandler.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  27.1 KB  |  1,200 lines  |  [TEXT/R*ch]

  1. // DGIFHandler.cpp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include "Dvibrant.h"
  6. #include "DFile.h"
  7. #include "DGIFHandler.h"
  8. #include "DRichProcess.h"
  9. #include "DRichViewNu.h"  
  10. #include "DDrawPICT.h"    
  11. #include "DPICTprocess.h"    
  12. #include <stdio.h>
  13.  
  14.  
  15. typedef        unsigned char    byte;
  16. typedef        unsigned char    pixel;
  17. typedef        unsigned short    ushort;
  18. //typedef        unsigned long     ulong;
  19.  
  20. struct macRGBColor 
  21. {
  22.     ushort red;
  23.     ushort green;
  24.     ushort blue;
  25. };
  26.  
  27.  
  28. class DPictWriter;
  29.  
  30. class DGifReader
  31. {
  32. public:
  33.     DGifReader( DFile* itsFile, DPictWriter* pictwriter = NULL, short imageNumber = 1);
  34.     ~DGifReader();
  35.         
  36.     const char*     Error()     { return fError; }
  37.     short     Height()     { return fHeight; }
  38.     short     Width()      { return fWidth; }
  39.     short  BitsPerPixel()    { return fBitPixel; }
  40.     char*     GetPixels()     { return fPixels; }
  41.     KolorTable GetColormap() { return fColortable; }
  42.     long   NColors() { return fNColors; }
  43.     
  44. private:
  45.     enum {
  46.         MAXCOLORMAPSIZE=256,
  47.         CM_RED=0,
  48.         CM_GREEN=1,
  49.         CM_BLUE=2,
  50.         MAX_LZW_BITS=12,
  51.         LZW_TABLE_SIZE = (1<<12), //1<<MAX_LZW_BITS
  52.         INTERLACE    =0x40,
  53.         MaxGETCBUF = 280,
  54.         COLORMAPFLAG=0x80
  55.         };
  56.     
  57.     DPictWriter*    fPictWriter;
  58.     ushort    fWidth,fHeight,fBitPixel;
  59.     ushort    fColorResolution,fBackground,fAspectRatio; // not used
  60.     Boolean    fInterlace, fEof;
  61.     char        * fPixels;    
  62.     short        fImageNumber;
  63.     KolorSpec    * fColormap;
  64.     KolorTable    fColortable;
  65.     byte        * fColorswap;
  66.     short        fNColors;
  67.     DFile        * fFile;
  68.     char        * fError;
  69.     struct {
  70.         short    transparent;
  71.         short    delayTime;
  72.         short    inputFlag;
  73.         short    disposal;
  74.         } fGif89;
  75.             // GetCode static vars
  76.     byte    codebuf[MaxGETCBUF];
  77.     long    curbit, lastbit, lastbyte;
  78.     Boolean    out_of_blocks;
  79.             //LZWReadByte static vars
  80.     Boolean    lzwfresh;
  81.     long    code_size, set_code_size, input_code_size;
  82.     long    max_code, max_code_size;
  83.     long    firstcode, oldcode, clear_code, end_code, limit_code;
  84.     ushort lzwhead[LZW_TABLE_SIZE]; /* => table of prefix symbols */
  85.     byte  lzwtail[LZW_TABLE_SIZE]; /* => table of suffix bytes */
  86.     byte  lzwstack[LZW_TABLE_SIZE]; /* stack for symbol expansions */
  87.     byte  *lzwsp;        /* stack pointer */
  88.                 
  89.     void         ReadImage( Boolean ignore);
  90.     void         ReadGIFtop();
  91.     Boolean ReadColorMap();
  92.     void        OpenPicture();
  93.     void         StorePoint( long x, long y, short color);
  94.     Boolean DoExtension();
  95.     short     GetDataBlock( void *buf);
  96.     void      SkipDataBlocks();
  97.     ulong      GetCode();
  98.     inline byte MapColor( byte oldcolor);
  99.     long      LZWReadByte();
  100.     void         ReInitLZW();
  101.     void         InitLZWCode( short inCodeSize);
  102.     Boolean ReadOK( void* buffer, ulong len);
  103.     short     ReadByte();
  104.     Boolean BitSet( byte byte, long bit)    { return ( (byte & bit) == bit ); }
  105.     ushort     LM_to_uint( byte a, byte b) { return (ushort) (b << 8) | a ; }
  106. };
  107.  
  108.  
  109.  
  110.  
  111. class DPictWriter
  112. {
  113. public:
  114.     DPictWriter( Boolean wantPictHeader= false, Boolean ownpict= false);
  115.     DPictWriter( short rows, short cols, short ncolors, KolorTable colortable,
  116.                                 char* pixels, Boolean wantPictHeader= false, Boolean ownpict= false);
  117.     ~DPictWriter();
  118.     byte* Pict();  
  119.     ulong    PictSize() { return fPictSize; }
  120.     void  Open( short rows, short cols, short ncolors, KolorTable colortable);
  121.     void  WriteLine( char* pixelrow) {    fBytesPut += putRow( pixelrow); }
  122.     void    Close()  { PutPictEnd(); }
  123.     
  124. private:
  125.     enum {    
  126.         HEADER_SIZE =    512,
  127.         PICT_clipRgn    =0x01,
  128.         PICT_picVersion=0x11,
  129.         PICT_PackBitsRect=0x98,
  130.         PICT_EndOfPicture=0xFF,
  131.         PICT_headerOp=0x0C00,
  132.         RUN_THRESH = 3,
  133.         MAX_RUN    = 128,        /* 0xff = 2, 0xfe = 3, etc */
  134.         MAX_COUNT = 128        /* 0x00 = 1, 0x01 = 2, etc */
  135.         };
  136.     
  137.     Boolean fWantHeader, fOwnPict;
  138.     byte  * fPict;
  139.     char     * fPacked;
  140.     ulong     fPictSize, fPicSizeAt, fPictMax, fBytesPut;
  141.     short        fWidth, fHeight, fRowbytes;
  142.     short     fNColors;
  143.     KolorSpec * fColormap;
  144.     KolorTable    fColortable;
  145.     DFile*    fPicFile;
  146.  
  147.     void PutPictTop();
  148.     void PutPictEnd();
  149.     void putChar( byte c);
  150.     void putFill( char c, ulong size);
  151.     void putShort( short i);
  152.     void putLong( long i);
  153.     void putFixed( short in, short frac);
  154.     long putRow( char* pixelrow);
  155.     void putRect( short x1, short x2, short y1, short y2);
  156. };
  157.  
  158.  
  159.  
  160.  
  161. class DGIFprocess : public DPICTprocess
  162. {
  163. public:
  164.     DGIFprocess( DFile* itsFile, DFile* itsTempData, DRichView* itsDoc, Nlm_MonitorPtr progress);
  165. protected:
  166.     virtual void  ReadDataFromFile();
  167. };
  168.  
  169.  
  170.  
  171. //class DGIFprocess
  172.  
  173. DGIFprocess::DGIFprocess( DFile* itsFile, DFile* itsTempData, 
  174.                                     DRichView* itsDoc, Nlm_MonitorPtr progress) :
  175.         DPICTprocess( itsFile, itsTempData, itsDoc, progress)
  176. {     
  177. }
  178.             
  179. void DGIFprocess::ReadDataFromFile()
  180. {    
  181.     if (!fDataFile) fDataFile= fTempData;
  182.     if ( fNotDone && fDataFile) {
  183.         fDataFile->Close(); // !?!? are we done writing to fTempData ??
  184.         fDataFile->Open("rb"); 
  185.         fNotDone= false;
  186. #if 1
  187.         DPictWriter* picwriter = new DPictWriter( false, false);
  188.         DGifReader* gif= new DGifReader( fDataFile, picwriter);
  189. #else
  190.         DGifReader* gif= new DGifReader( fDataFile);
  191.         DPictWriter* picwriter = new DPictWriter( gif->Height(), gif->Width(),
  192.                     gif->NColors(), gif->GetColormap(), gif->GetPixels(), false, false);
  193. #endif
  194.         delete gif;
  195.  
  196.         fPict= (char*) picwriter->Pict();
  197.         fPictSize= picwriter->PictSize();
  198.         delete picwriter;
  199.         }
  200. }            
  201.  
  202.  
  203.  
  204. //class  DGIFHandler
  205.  
  206. DGIFHandler::DGIFHandler(DRichView* itsDoc, DFile* savefile) :
  207.     DPICTHandler( itsDoc, savefile)
  208. {
  209.     fFormatName = "GIF";
  210.     fMinDataToProcess= 10; // ?? only need 1st 6 bytes to check "GIF89a" or "GIF87a"
  211.     //if (fDocFile) fDocFile->Open("wb"); // make sure it is binary
  212. }
  213.  
  214. char* DGIFHandler::IsRich(char* buf, ulong buflen)
  215. {
  216.         // magic keys are "GIF87a" and "GIF89a" as 1st 6 bytes of data
  217.     if (buflen < 6)
  218.         return NULL;    
  219.     if (buf[0] != 'G' || buf[1] != 'I' || buf[2] != 'F') 
  220.         return NULL;
  221.     if (buf[3] != '8' || (buf[4] != '7' && buf[4] != '9') || buf[5] != 'a') 
  222.         return NULL;
  223.   return buf;
  224. }
  225.  
  226. DRichprocess* DGIFHandler::NewProcessor( DFile* itsFile, Nlm_MonitorPtr progress)
  227. {
  228.     fProcessor = new DGIFprocess( itsFile, fDocFile, fDoc, progress);
  229.     return fProcessor;
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239. /* from gifread.c */
  240. /* +-------------------------------------------------------------------+ */
  241. /* | Copyright 1990, David Koblas.                                     | */
  242. /* |   Permission to use, copy, modify, and distribute this software   | */
  243. /* |   and its documentation for any purpose and without fee is hereby | */
  244. /* |   granted, provided that the above copyright notice appear in all | */
  245. /* |   copies and that both that copyright notice and this permission  | */
  246. /* |   notice appear in supporting documentation.  This software is    | */
  247. /* |   provided "as is" without express or implied warranty.           | */
  248. /* +-------------------------------------------------------------------+ */
  249.  
  250. /* and from jrdgif.c 
  251.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  252.  * This file is part of the Independent JPEG Group's software.
  253. */
  254.  
  255.  
  256. DGifReader::DGifReader( DFile* itsFile, DPictWriter* pictwriter, short imageNumber)
  257. {
  258.     fWidth = 0;
  259.     fHeight = 0;
  260.     fNColors= 0;
  261.     fBitPixel = 8;
  262.     fColorResolution = 0;
  263.     fBackground = 0; // ? background color ??
  264.     fAspectRatio = 0;
  265.     fPixels = NULL;
  266.     fColorswap = NULL;    
  267.     fColormap = NULL;
  268.     fPictWriter= pictwriter;
  269.     fImageNumber= imageNumber;
  270.     fFile= itsFile;
  271.     fError= NULL;
  272.     fInterlace= false;
  273.     fEof= false;
  274.     fGif89.disposal    = -1;
  275.     fGif89.inputFlag   = -1;
  276.     fGif89.delayTime   = -1;
  277.     fGif89.transparent = 0;
  278.     lzwfresh = false;
  279.     
  280.     if (fFile) ReadGIFtop();
  281. }
  282.  
  283.  
  284. DGifReader::~DGifReader()
  285. {
  286.     MemFree( fPixels);  
  287.     MemFree( fColorswap);  
  288.     MemFree( fColormap);  
  289. }
  290.  
  291. Boolean DGifReader::ReadOK( void* buffer, ulong len)
  292. {
  293.     ulong count= len;
  294.     short err= fFile->ReadData( buffer, count);
  295.     //fEof = fFile->Eof();
  296.     return (count > 0); // (count == len);
  297. }
  298.  
  299. short DGifReader::ReadByte()
  300. {
  301.     short c = fgetc( fFile->fFile);
  302.     fEof= (c == EOF);
  303.     return c;
  304. }
  305.  
  306.  
  307. void DGifReader::ReadGIFtop()
  308. {
  309.     byte    buf[16];
  310.     byte    c;
  311.     short    imageCount = 0;
  312.     
  313.     if (! ReadOK(buf,6)) {
  314.         fError= "error reading magic number";
  315.         return;
  316.         }
  317.  
  318.     if (buf[0] != 'G' || buf[1] != 'I' || buf[2] != 'F') {
  319.         fError= "not a GIF file";
  320.         return;
  321.         }
  322.  
  323.     if (buf[3] != '8' || (buf[4] != '7' && buf[4] != '9') || buf[5] != 'a') {
  324.         fError= "bad version number, not '87a' or '89a'";
  325.         return;
  326.         }
  327.  
  328.     if (! ReadOK(buf,7)) {
  329.         fError= "failed to read screen descriptor";
  330.         return;
  331.         }
  332.  
  333.     fWidth                      = LM_to_uint(buf[0],buf[1]); 
  334.     fHeight                     = LM_to_uint(buf[2],buf[3]); 
  335.     fBitPixel        = (buf[4] & 0x07) + 1;
  336.     fColorResolution = ((buf[4] & 0x70) >> 3) + 1;
  337.     fBackground      = buf[5];
  338.     fAspectRatio     = buf[6];
  339.  
  340.     Boolean haveColorMap = BitSet(buf[4], COLORMAPFLAG);
  341.     if (haveColorMap) {     
  342.         if (!ReadColorMap()) {
  343.             fError= "error reading global colormap";
  344.             return;
  345.             }
  346.         }
  347.  
  348.     if (fAspectRatio != 0 && fAspectRatio != 49) {
  349.         float    r;
  350.         r = ( (float) fAspectRatio + 15.0 ) / 64.0;
  351.         //fError= "Warning:  non-square pixels!";
  352.         }
  353.  
  354.     for (imageCount= 0; imageCount < fImageNumber; ) {
  355.         c= ReadByte();
  356.         if (fEof) {
  357.             fError= "EOF / read error on image data";
  358.             return;
  359.             }
  360.  
  361.         if (c == ';') {        /* GIF terminator */
  362.             if (imageCount < fImageNumber) {
  363.                 fError= "No images found in file";
  364.                 return;
  365.                 }
  366.             break;
  367.             }
  368.  
  369.         if (c == '!') {     /* Extension */
  370.             DoExtension();
  371.             continue;
  372.             }
  373.  
  374.         if (c != ',') {        /* Not a valid start character */
  375.             //fError= "bogus character 0x%02x, ignoring"; // print( msg, c) 
  376.             continue;
  377.             }
  378.  
  379.         if (! ReadOK( buf,9)) {
  380.             fError= "couldn't read left/top/width/height";
  381.             return;
  382.             }
  383.  
  384.         haveColorMap = BitSet(buf[8], COLORMAPFLAG);
  385.         fBitPixel     = (buf[8] & 0x07) + 1;
  386.             // ^^^^^ if this is 1 ?2?, save lots of space doing bitmap not pixmap ??!
  387.         fWidth             = LM_to_uint(buf[4],buf[5]);
  388.         fHeight         = LM_to_uint(buf[6],buf[7]);
  389.         fInterlace    = BitSet(buf[8], INTERLACE);
  390.  
  391.         if (haveColorMap) {
  392.             if (!ReadColorMap()) {
  393.                 fError= "error reading local colormap";
  394.                 return;
  395.                 }
  396.             } 
  397.             
  398.         ++imageCount;            
  399.         if (imageCount <= fImageNumber) {
  400.             ReadImage(imageCount != fImageNumber);
  401.             }
  402.         }
  403. }
  404.  
  405.  
  406. Boolean DGifReader::ReadColorMap()
  407. {
  408.     byte    gifrgb[3];
  409.     KolorSpec    kolor;
  410.     long scale = 65536 / MAXCOLORMAPSIZE;
  411.     long    i;
  412.  
  413.     fNColors = 1 << fBitPixel;
  414.     if (fColormap) MemFree( fColormap);
  415.     //fColormap= (macRGBColor*) MemNew( (ulong)fNColors * sizeof(macRGBColor)); 
  416.     fColormap= (KolorSpec*) MemNew( (ulong)fNColors * sizeof(KolorSpec)); 
  417.   fColortable.ctTable= fColormap;
  418.     fColortable.ctFlags= 0;
  419.     fColortable.ctSeed= 0;
  420.     fColortable.ctSize= fNColors-1;
  421.     
  422.     if (!fColormap) {
  423.         fError= "Can't allocate colormap array";
  424.         return(false);
  425.         }
  426.     for (i = 0; i < fNColors; ++i) {
  427.         if (! ReadOK( gifrgb, sizeof(gifrgb))) {
  428.             fError= "bad colormap";
  429.             return(false);
  430.             }
  431.         kolor.value= i;
  432.         kolor.rgb.red     = gifrgb[0] * scale;
  433.         kolor.rgb.green = gifrgb[1] * scale;
  434.         kolor.rgb.blue     = gifrgb[2] * scale;
  435.         fColormap[i] = kolor;
  436.         }
  437.         
  438. #ifdef WIN_MOTIF
  439.     //fColortable.ctFlags = DDrawPICT::kXColorTableFlag;
  440.     MemFree( fColorswap);
  441.     fColorswap= (byte*) MemNew( sizeof(byte)*257);
  442.     DDrawPict::Pixmap2Xcolors( fColortable, fColorswap, 256, true);
  443. #endif
  444.  
  445.     return true;
  446. }
  447.  
  448.  
  449. void DGifReader::StorePoint( long x, long y, short color)
  450. {
  451.     byte *dptr = (byte *)(fPixels + (y * fWidth) + x);
  452.     *dptr = (byte)color;
  453. }
  454.  
  455.  
  456. inline byte DGifReader::MapColor( byte oldcolor)
  457. {
  458. #ifdef WIN_MOTIF
  459.     if (fColorswap) return fColorswap[oldcolor];
  460.     else 
  461. #endif
  462.     return oldcolor;
  463. }
  464.  
  465.  
  466. void DGifReader::OpenPicture()
  467. {
  468.     if (fPictWriter) {
  469.         fPictWriter->Open( this->Height(), this->Width(), this->NColors(), this->GetColormap());        
  470.         }
  471.     else
  472.         ; //Nlm_Message(MSG_FATAL,"GIF Reader: can't write picture");
  473. }
  474.  
  475.  
  476.  
  477. void DGifReader::ReadImage( Boolean ignore)
  478. {
  479.     short        codesize;
  480.     long        xpos = 0, ypos = 0, pass = 0;
  481.   register long col;
  482.     long        row;
  483.     register byte     * dptr;
  484.     byte     * dmax;
  485.  
  486.     codesize= ReadByte();
  487.   if (fEof || codesize < 2 || codesize >= MAX_LZW_BITS) {
  488.         fError= "EOF / read error on image data";
  489.         return;
  490.         }
  491.     InitLZWCode(codesize);
  492.  
  493.     if (ignore) {
  494.         SkipDataBlocks();
  495.         return;
  496.         }
  497.     
  498.     OpenPicture();
  499.  
  500. #if 1
  501.     if (fPictWriter && !fInterlace) {
  502.         // we can write each fPixels row to disk as written
  503.         // since ypos increases stepwise
  504.         byte * buf = (byte*)MemNew( fWidth+10);
  505.         for (row = 0; row < fHeight; row++) {
  506.             dptr= (byte*)buf;
  507.             for (col = fWidth; col > 0; col--) {
  508.                 *dptr++ = (byte) MapColor( LZWReadByte());
  509.           }
  510.         fPictWriter->WriteLine( (char*)buf);
  511.           }
  512.         MemFree( buf);
  513.         fPictWriter->Close();
  514.         return;
  515.         }
  516. #endif
  517.  
  518.             // CHECK FOR LOW MEMORY HERE !!
  519.     ulong width= fWidth;
  520.     ulong height= fHeight;
  521.     ulong pixsize= width * height;
  522.     fPixels = (char*) MemNew(pixsize);
  523.             // ^^^^ THIS CAN BE A BIG MOTHER ! (300 x 300 image == 90K )
  524.     dmax= (byte*) (fPixels + pixsize);
  525.     if (fPixels == NULL) {
  526.         fError= "Cannot allocate space for image data";
  527.         return;
  528.         }
  529.  
  530.     if (!fInterlace) {
  531.         dptr= (byte*)fPixels;
  532.         for (row = 0; row < height; row++) {
  533.             for (col = width; col > 0; col--) {
  534.                 if (dptr > dmax) break;
  535.                 else *dptr++ = (byte) MapColor( LZWReadByte());
  536.           }
  537.           }
  538.         }
  539.         
  540.     else {
  541.         xpos= ypos= 0;
  542.         for (row = 0; row < height; row++) {
  543.             for (col = width; col > 0; col--)
  544.                 dptr = (byte *) (fPixels + xpos + (ypos * fWidth));
  545.           *dptr = (byte) MapColor( LZWReadByte());
  546.                 ++xpos;
  547.                 if (xpos == fWidth) {
  548.                     xpos = 0;
  549.                     if (fInterlace) {
  550.                         switch (pass) {
  551.                         case 0:
  552.                         case 1:
  553.                             ypos += 8; break;
  554.                         case 2:
  555.                             ypos += 4; break;
  556.                         case 3:
  557.                             ypos += 2; break;
  558.                             }
  559.                         if (ypos >= fHeight) {
  560.                             ++pass;
  561.                             switch (pass) {
  562.                             case 1:
  563.                                 ypos = 4; break;
  564.                             case 2:
  565.                                 ypos = 2; break;
  566.                             case 3:
  567.                                 ypos = 1; break;
  568.                             default:
  569.                                 goto fini;
  570.                             }
  571.                         }
  572.                     } else 
  573.                         ++ypos;
  574.                 }
  575.                 if (ypos >= fHeight)
  576.                     break;
  577.           }
  578.         }
  579.  
  580. fini:
  581.     // this is no longer valid??
  582.     if (LZWReadByte()>=0) fError= "too much input data, ignoring extra...";
  583. }
  584.  
  585.  
  586.  
  587. Boolean DGifReader::DoExtension()
  588. {
  589.     static char    buf[256];
  590.     char        *str;
  591.  
  592.     short label = ReadByte();
  593.     if (fEof) {
  594.         fError= "EOF / read error on extention function code";
  595.         return false;
  596.         }
  597.  
  598.     switch (label) {
  599.     case 0x01:     
  600.         str = "Plain Text Extension";
  601. #if 0
  602.         if (GetDataBlock( buf) == 0) ;
  603.  
  604.         lpos   = LM_to_uint(buf[0], buf[1]);
  605.         tpos   = LM_to_uint(buf[2], buf[3]);
  606.         width  = LM_to_uint(buf[4], buf[5]);
  607.         height = LM_to_uint(buf[6], buf[7]);
  608.         cellw  = buf[8];
  609.         cellh  = buf[9];
  610.         foreground = buf[10];
  611.         background = buf[11];
  612.  
  613.         while (GetDataBlock( buf) != 0) {
  614.             PPM_ASSIGN(image[ypos][xpos],
  615.                     cmap[CM_RED][v],
  616.                     cmap[CM_GREEN][v],
  617.                     cmap[CM_BLUE][v]);
  618.             ++index;
  619.         }
  620.  
  621.         return false;
  622. #else
  623.         break;
  624. #endif
  625.  
  626.     case 0xff:         
  627.         str = "Application Extension";
  628.         break;
  629.         
  630.     case 0xfe:         
  631.         str = "Comment Extension";
  632.         while (GetDataBlock(  buf) != 0) {
  633.             //if (showComment) fprintf(stderr, "gif comment: %s\n", buf);
  634.             }
  635.         return false;
  636.         
  637.     case 0xf9:         
  638.         str = "Graphic Control Extension";
  639.         (void) GetDataBlock(  buf);
  640.         fGif89.disposal    = (buf[0] >> 2) & 0x7;
  641.         fGif89.inputFlag   = (buf[0] >> 1) & 0x1;
  642.         fGif89.delayTime   = LM_to_uint(buf[1],buf[2]);
  643.         if ((buf[0] & 0x1) != 0) fGif89.transparent = buf[3];
  644.         SkipDataBlocks();
  645.         return false;
  646.         
  647.     default:
  648.         str = buf;
  649.         //sprintf(buf, "UNKNOWN (0x%02x)", label);
  650.         strcpy(buf,"UNKNOWN Extension");
  651.         break;
  652.     }
  653.  
  654.     SkipDataBlocks();
  655.     return false;
  656. }
  657.  
  658.  
  659.  
  660. short DGifReader::GetDataBlock( void *buf)
  661. {
  662.     short    count;   
  663.     count= ReadByte();
  664.     if (fEof) {
  665.         fError= "error reading DataBlock size";
  666.         return -1;
  667.         }
  668.     if ( count > 0 && !ReadOK( buf, count)) {
  669.         fError= "error reading DataBlock";
  670.         return -1;
  671.         }
  672.     return count;
  673. }
  674.  
  675. void DGifReader::SkipDataBlocks()
  676. {
  677.   char buf[256];
  678.   while ( GetDataBlock(buf) > 0) ; /* skip */
  679. }
  680.  
  681. ulong DGifReader::GetCode()
  682. {
  683.     ulong        ret, count, offs;
  684.   register ulong accum;
  685.      
  686.     if ( (curbit+code_size) >= lastbit) {
  687.         if (out_of_blocks) {
  688.             fError= "ran out of GIF bits";
  689.             return end_code;
  690.             }
  691.         codebuf[0] = codebuf[lastbyte-2];
  692.         codebuf[1] = codebuf[lastbyte-1];
  693.  
  694.         if ((count = GetDataBlock( &codebuf[2])) == 0) {
  695.       out_of_blocks = TRUE;
  696.             fError= "ran out of GIF bits";
  697.       return end_code;        /* fake something useful */
  698.             }
  699.         curbit = (curbit - lastbit) + 16;
  700.         lastbyte = 2 + count;
  701.         lastbit = lastbyte * 8;
  702.         }
  703.  
  704.             /* Form up next 24 bits in accum */
  705.     offs = curbit >> 3;        /* byte containing cur_bit */
  706.   accum = codebuf[offs+2];
  707.   accum <<= 8;
  708.   accum |= codebuf[offs+1];
  709.   accum <<= 8;
  710.   accum |= codebuf[offs];
  711.           /* Right-align cur_bit in accum, then mask off desired number of bits */
  712.   accum >>= (curbit & 7);
  713.   ret = ((ulong) accum) & ((1 << code_size) - 1);
  714.  
  715.     curbit += code_size;
  716.     return ret;
  717. }
  718.  
  719.  
  720. void DGifReader::ReInitLZW()
  721. /* (Re)initialize LZW state; shared code for startup and Clear processing */
  722. {
  723.   code_size = input_code_size+1;
  724.   limit_code = clear_code << 1;    /* 2^code_size */
  725.   max_code = clear_code + 2;    /* first unused code value */
  726.   lzwsp = lzwstack;        /* init stack to empty */
  727. }
  728.  
  729.  
  730. void DGifReader::InitLZWCode( short inCodeSize)
  731. /* Initialize for a series of LZWReadByte (and hence GetCode) calls */
  732. {
  733.   /* GetCode initialization */
  734.   lastbyte = 2;        /* make safe to "recopy last two bytes" */
  735.   lastbit = 0;            /* nothing in the buffer */
  736.   curbit = 0;            /* force buffer load on first call */
  737.   out_of_blocks = FALSE;
  738.  
  739.     input_code_size= inCodeSize;
  740.   /* LZWReadByte initialization */
  741.   clear_code = 1 << input_code_size; /* compute special code values */
  742.   end_code = clear_code + 1;    /* note that these do not change */
  743.   lzwfresh = TRUE;
  744.   ReInitLZW();
  745. }
  746.  
  747.  
  748. long DGifReader::LZWReadByte()
  749. {
  750.     register long  code;
  751.     long incode;   
  752.  
  753.     if (lzwfresh) {
  754.         lzwfresh = false;
  755.     code = clear_code;        /* enables sharing code with Clear case */
  756.         }
  757.     else {
  758.         /* If any codes are stacked from a previously read symbol, return them */
  759.     if (lzwsp > lzwstack)
  760.       return (short) *(--lzwsp);
  761.  
  762.         /* Time to read a new symbol */
  763.     code = GetCode();
  764.         }
  765.         
  766.   if (code == clear_code) {
  767.     /* Reinit static state, swallow any extra Clear codes, and */
  768.     /* return next code, which is expected to be a raw byte. */
  769.     ReInitLZW();
  770.     do {
  771.       code = GetCode();
  772.     } while (code == clear_code);
  773.     if (code > clear_code) {    /* make sure it is a raw byte */
  774.       fError= "Corrupt data in GIF file";
  775.       code = 0;            /* use something valid */
  776.         }
  777.     firstcode = oldcode = code;    /* make firstcode, oldcode valid! */
  778.     return code;
  779.       }
  780.  
  781.   if (code == end_code) {
  782.     /* Skip the rest of the image, unless GetCode already read terminator */
  783.     if (! out_of_blocks) {
  784.       SkipDataBlocks();
  785.       out_of_blocks = TRUE;
  786.         }
  787.     /* Complain that there's not enough data */
  788.     fError= "Premature end of GIF image";
  789.     /* Pad data with 0's */
  790.     return 0;            /* fake something usable */
  791.       }
  792.  
  793.   /* Got normal raw byte or LZW symbol */
  794.   incode = code;        /* save for a moment */
  795.   
  796.   if (code >= max_code) {    /* special case for not-yet-defined symbol */
  797.     /* code == max_code is OK; anything bigger is bad data */
  798.     if (code > max_code) {
  799.       fError= "Corrupt data in GIF file";
  800.       incode = 0;        /* prevent creation of loops in symbol table */
  801.         }
  802.     *lzwsp++ = (byte) firstcode;    /* it will be defined as oldcode/firstcode */
  803.     code = oldcode;
  804.           }
  805.  
  806.   /* If it's a symbol, expand it into the stack */
  807.   while (code >= clear_code) {
  808.     *lzwsp++ = lzwtail[code];     /* tail of symbol: a simple byte value */
  809.     code = lzwhead[code];    /* head of symbol: another LZW symbol */
  810.       }
  811.   /* At this point code just represents a raw byte */
  812.   firstcode = code;        /* save for possible future use */
  813.  
  814.   /* If there's room in table, */
  815.   if ((code = max_code) < LZW_TABLE_SIZE) {
  816.     /* Define a new symbol = prev sym + head of this sym's expansion */
  817.     lzwhead[code] = oldcode;
  818.     lzwtail[code] = (byte) firstcode;
  819.     max_code++;
  820.     /* Is it time to increase code_size? */
  821.     if ((max_code >= limit_code) && (code_size < MAX_LZW_BITS)) {
  822.       code_size++;
  823.       limit_code <<= 1;        /* keep equal to 2^code_size */
  824.             }
  825.         }
  826.   
  827.   oldcode = incode;        /* save last input symbol for future use */
  828.   return firstcode;        /* return first byte of symbol's expansion */
  829. }
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841. // class DPictWriter
  842.  
  843. #define PICFILE 1
  844.  
  845. DPictWriter::DPictWriter( short rows, short cols, short ncolors, KolorTable colortable,
  846.                             char* pixels, Boolean wantPictHeader, Boolean ownpict)
  847. {
  848.     fHeight= rows;
  849.     fWidth= cols;
  850.     fNColors= ncolors;
  851.     fColortable= colortable;
  852.     fColormap= colortable.ctTable;
  853.     
  854.     fWantHeader= wantPictHeader;
  855.     fOwnPict= ownpict;
  856.     fPicFile= new DTempFile();
  857.     fPicFile->Open("wb");
  858.     fBytesPut= fPictSize= fPicSizeAt= fPictMax= 0;
  859.     fPict= NULL;
  860.     fPacked = (char*) MemNew( (unsigned)(fWidth + fWidth/MAX_COUNT + 1));
  861.     
  862.     PutPictTop();
  863.     for (short arow = 0; arow < fHeight; arow++) 
  864.         WriteLine( pixels + (arow * fWidth));
  865.         //fBytesPut += putRow( pixels + (arow * fWidth));
  866.                     // ^^^^^ for bitmaps, this has to be changed to handle 1 bit pixels
  867.                     // but i don't know what the algorithm for RLE of that is !
  868.     PutPictEnd();
  869. }
  870.     
  871. DPictWriter::DPictWriter(  Boolean wantPictHeader, Boolean ownpict)
  872. {
  873.     fWidth= 0;
  874.     fNColors= 0;
  875.     fColormap= NULL;    
  876.     fWantHeader= wantPictHeader;
  877.     fOwnPict= ownpict;
  878.     fBytesPut= fPictSize= fPicSizeAt= fPictMax= 0;
  879.     fPict= NULL;
  880.     fPicFile= NULL;
  881.     fPacked = NULL;  
  882. }
  883.  
  884. DPictWriter::~DPictWriter()
  885. {
  886.     if (fOwnPict) MemFree( fPict);
  887.     if (fPicFile) {
  888.         fPicFile->Delete();
  889.         delete fPicFile;
  890.         }
  891.     MemFree( fPacked);
  892. }
  893.  
  894.  
  895. void  DPictWriter::Open( short rows, short cols, short ncolors, KolorTable colortable) 
  896. {
  897.     fHeight= rows;
  898.     fWidth= cols;
  899.     fNColors= ncolors;
  900.     fColortable= colortable;
  901.     fColormap= colortable.ctTable;
  902.     fPacked = (char*) MemNew( (unsigned)(fWidth + fWidth/MAX_COUNT + 1));
  903.     fPicFile= new DTempFile();
  904.     fPicFile->Open("wb");
  905.     PutPictTop();
  906. }
  907.  
  908.     
  909.     
  910. byte* DPictWriter::Pict()
  911. {
  912. #if PICFILE
  913.     if (!fPict && fPicFile) {
  914.         fPicFile->Close();
  915.         fPicFile->Open("rb");
  916.         fPict= (byte*) MemNew( fPictSize+1);
  917.         fPicFile->ReadData( fPict, fPictSize);
  918.         }
  919. #endif
  920.     return fPict; 
  921.     
  922.  
  923. void DPictWriter::putChar( byte c)
  924. {
  925. #if PICFILE
  926.     fputc( c, fPicFile->fFile);
  927.     fPictSize++;
  928. #else
  929.     if (fPictSize >= fPictMax) {
  930.         fPictMax = fPictSize + 1025;
  931.         if (!fPict) fPict= (byte*) Nlm_MemNew(fPictMax);
  932.         else fPict= (byte*) Nlm_MemMore( fPict, fPictMax);
  933.         }
  934.     if (fPict) fPict[fPictSize++]=  c;
  935. #endif
  936. }
  937.  
  938. void DPictWriter::putFill( char c, ulong size)
  939. {
  940.     for ( ; size>0; size--) putChar( c);
  941. }
  942.  
  943. void DPictWriter::putShort( short i)
  944. {
  945.     putChar( (i >> 8) & 0xff);
  946.     putChar( i & 0xff);
  947. }
  948.  
  949. void DPictWriter::putLong( long i)
  950. {
  951.     putChar( (i >> 24) & 0xff);
  952.     putChar( (i >> 16) & 0xff);
  953.     putChar( (i >> 8) & 0xff);
  954.     putChar( i & 0xff);
  955. }
  956.  
  957. void DPictWriter::putFixed( short in, short frac)
  958. {
  959.     putShort( in);
  960.     putShort( frac);
  961. }
  962.  
  963. void DPictWriter::putRect( short x1, short x2, short y1, short y2)
  964. {
  965.     putShort( x1);
  966.     putShort( x2);
  967.     putShort( y1);
  968.     putShort( y2);
  969. }
  970.  
  971.  
  972. void DPictWriter::PutPictEnd()
  973. {
  974.     if (fBytesPut & 1) putChar(0); //if we wrote an odd number of pixdata bytes, pad 
  975.     putShort( PICT_EndOfPicture);
  976. #if PICFILE
  977.     fPicFile->Seek(fPicSizeAt);
  978.     putShort( (short)(fPictSize & 0xffff));
  979. #else
  980.     ulong saveSize= fPictSize;
  981.     fPictSize= fPicSizeAt;
  982.     putShort( (short)(saveSize & 0xffff));
  983.     fPictSize= saveSize;
  984. #endif
  985. }
  986.  
  987. void DPictWriter::PutPictTop()
  988. {
  989.     fRowbytes= fWidth;
  990.     //if (fRowbytes & 1)  fRowbytes ++;    // ?????
  991.     if (fWantHeader) putFill( 0, HEADER_SIZE);
  992.  
  993.             // write picSize and picFrame 
  994. #if PICFILE
  995.     fPicSizeAt= fPicFile->Tell();
  996. #else
  997.     fPicSizeAt= fPictSize;
  998. #endif
  999.     putShort( 0);   // write pictSize again at end when size is known
  1000.     putRect(0, 0, fHeight, fWidth);
  1001.  
  1002.             // write version op and version 
  1003.     putShort( PICT_picVersion);
  1004.     putShort( 0x02FF);
  1005.     putShort( PICT_headerOp);
  1006.     putLong( -1L);
  1007.     putFixed( 0, 0);
  1008.     putFixed( 0, 0);
  1009.     putFixed( fWidth, 0);
  1010.     putFixed( fHeight, 0);
  1011.     putFill( 0, 4);
  1012.  
  1013.             // seems to be needed by many PICT2 programs 
  1014.     putShort( PICT_clipRgn);
  1015.     putShort( 10);
  1016.     putRect( 0, 0, fHeight, fWidth);
  1017.  
  1018.     if (false) {  // (fNColors<3)
  1019.              //  save lots of space doing bitmap not pixmap !
  1020.         putShort( PICT_PackBitsRect);
  1021.         putShort( fRowbytes );  // rowbytes !? make even if odd ??
  1022.                 // bitmap params
  1023.         putRect( 0, 0, fHeight, fWidth);    // bounds
  1024.         putRect( 0, 0, fHeight, fWidth);    /* srcRect */
  1025.         putRect( 0, 0, fHeight, fWidth);    /* dstRect */
  1026.         putShort( 0);            /* mode */
  1027.         }
  1028.     else {
  1029.         putShort( PICT_PackBitsRect);
  1030.         putShort( fRowbytes | 0x8000);   // 8 is flag to do pixmap !
  1031.                 // pixmap params
  1032.         putRect( 0, 0, fHeight, fWidth); // bounds
  1033.         putShort( 0);    /* pmVersion */
  1034.         putShort( 0);    /* packType */
  1035.         putLong( 0L);    /* packSize */
  1036.         putFixed( 72, 0);    /* hRes */
  1037.         putFixed( 72, 0);    /* vRes */
  1038.         putShort( 0);    /* pixelType */
  1039.         putShort( 8);    // pixelSize  ???????
  1040.         putShort( 1);    /* cmpCount */
  1041.         putShort( 8);    // cmpSize  -- must == pixelSize
  1042.         putLong( 0L);    /* planeBytes */
  1043.         putLong( 0L);    /* pmTable */
  1044.         putLong( 0L);    /* pmReserved */
  1045.     
  1046.              // Write out the colortable. 
  1047.         putLong ( fColortable.ctSeed);     
  1048.         putShort( fColortable.ctFlags);     
  1049.         putShort( fColortable.ctSize);     
  1050.         for (unsigned short i = 0; i <= fColortable.ctSize; i++) {
  1051.             putShort( fColormap[i].value);
  1052.             putShort( fColormap[i].rgb.red);
  1053.             putShort( fColormap[i].rgb.green);
  1054.             putShort( fColormap[i].rgb.blue);
  1055.             }
  1056.     
  1057.         putRect( 0, 0, fHeight, fWidth);    /* srcRect */
  1058.         putRect( 0, 0, fHeight, fWidth);    /* dstRect */
  1059.         putShort( 0);            /* mode */
  1060.         }
  1061. }
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067. #define    RUNLENGTH
  1068. #ifdef    RUNLENGTH
  1069.  
  1070. #define        runtochar(c)    (257-(c))
  1071. #define        counttochar(c)    ((c)-1)
  1072.  
  1073. long DPictWriter::putRow( char* pixelrow)
  1074. {
  1075.     register short i;
  1076.     register pixel *pP;
  1077.     pixel lastp;
  1078.     register char *p;
  1079.     long packcols, count, run, rep, oc;
  1080.     short cols= fRowbytes-1;
  1081.     pixel* rowpixels= (pixel*) pixelrow;  //(pixel*) fPixels + (row * fWidth); // * sizeof(pixel);
  1082.  
  1083.     run = count = 0;
  1084.     for (cols--, i = cols, pP = rowpixels + cols, p = fPacked, lastp = *pP;
  1085.             i >= 0; 
  1086.             i--, lastp = *pP, pP--) {
  1087.         if ( lastp == *pP )
  1088.             run++;
  1089.         else if (run < RUN_THRESH) {
  1090.             while (run > 0) {
  1091.                 *p++ = lastp; //ppm_lookupcolor(cht, &lastp);
  1092.                 run--;
  1093.                 count++;
  1094.                 if (count == MAX_COUNT) {
  1095.                     *p++ = counttochar(MAX_COUNT);
  1096.                     count -= MAX_COUNT;
  1097.                     }
  1098.                 }
  1099.             run = 1;
  1100.             }
  1101.         else {
  1102.             if (count > 0) *p++ = counttochar(count);
  1103.             count = 0;
  1104.             while (run > 0) {
  1105.                 rep = run > MAX_RUN ? MAX_RUN : run;
  1106.                 *p++ = lastp; //ppm_lookupcolor(cht, &lastp);
  1107.                 *p++ = runtochar(rep);
  1108.                 run -= rep;
  1109.                 }
  1110.             run = 1;
  1111.             }
  1112.         }
  1113.         
  1114.     if (run < RUN_THRESH) {
  1115.         while (run > 0) {
  1116.             *p++ = lastp; //ppm_lookupcolor(cht, &lastp);
  1117.             run--;
  1118.             count++;
  1119.             if (count == MAX_COUNT) {
  1120.                 *p++ = counttochar(MAX_COUNT);
  1121.                 count -= MAX_COUNT;
  1122.                 }
  1123.             }
  1124.         }
  1125.     else {
  1126.         if (count > 0) *p++ = counttochar(count);
  1127.         count = 0;
  1128.         while (run > 0) {
  1129.             rep = run > MAX_RUN ? MAX_RUN : run;
  1130.             *p++ = lastp; //ppm_lookupcolor(cht, &lastp);
  1131.             *p++ = runtochar(rep);
  1132.             run -= rep;
  1133.             }
  1134.         run = 1;
  1135.         }
  1136.     if (count > 0)     *p++ = counttochar(count);
  1137.  
  1138.     packcols = p -  fPacked;        /* how many did we write? */
  1139.     if (cols > 250) {
  1140.         putShort( packcols);
  1141.         oc = packcols + 2;
  1142.         }
  1143.     else {
  1144.         putChar(packcols);
  1145.         oc = packcols + 1;
  1146.         }
  1147.  
  1148.     /* now write out the packed row */
  1149.     while (p != fPacked) {
  1150.         --p;
  1151.         putChar(*p);
  1152.         }
  1153.  
  1154.     return (oc);
  1155. }
  1156.  
  1157.  
  1158. #else    /* RUNLENGTH */
  1159.  
  1160. /* real dumb putRow with no compression */
  1161. long DPictWriter::putRow( char* pixelrow)
  1162. {
  1163.     register short i, j, bc, oc;
  1164.     register pixel *pP;
  1165.      short cols= fRowbytes;
  1166.     pixel* rowpixels= (pixel*) pixelrow;  //(pixel*) fPixels + (row * fWidth); // * sizeof(pixel);
  1167.  
  1168.     bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
  1169.     if (bc > 250) {
  1170.         putShort( bc);
  1171.         oc = bc + 2;
  1172.         }
  1173.     else {
  1174.         putChar(bc);
  1175.         oc = bc + 1;
  1176.         }
  1177.     for (i = 0, pP = rowpixels; i < cols; ) {
  1178.         if (cols - i > MAX_COUNT) {
  1179.             putChar(MAX_COUNT - 1);
  1180.             for (j = 0; j < MAX_COUNT; j++) {
  1181.                 putChar( *pP); //ppm_lookupcolor(cht, pP)
  1182.                 pP++;
  1183.                 }
  1184.             i += MAX_COUNT;
  1185.             }
  1186.         else {
  1187.             putChar(cols - i - 1);
  1188.             for (j = 0; j < cols - i; j++) {
  1189.                 putChar( *pP);  //ppm_lookupcolor(cht, pP)
  1190.                 pP++;
  1191.                 }
  1192.             i = cols;
  1193.             }
  1194.         }
  1195.     return (oc);
  1196. }
  1197.  
  1198. #endif    /* RUNLENGTH */
  1199.