Orb/Doxygen/src/gifenc.cpp
changeset 0 42188c7ea2d9
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * $Id$
       
     4  *
       
     5  *
       
     6  * Copyright (C) 1997-2009 by Dimitri van Heesch.
       
     7  *
       
     8  * Permission to use, copy, modify, and distribute this software and its
       
     9  * documentation under the terms of the GNU General Public License is hereby 
       
    10  * granted. No representations are made about the suitability of this software 
       
    11  * for any purpose. It is provided "as is" without express or implied warranty.
       
    12  * See the GNU General Public License for more details.
       
    13  *
       
    14  * All output generated with Doxygen is not covered by this license.
       
    15  *
       
    16  * The GIF compression code below is based on the file ppmtogif.c of the
       
    17  * netpbm package. The original copyright message follows:
       
    18  *
       
    19  * ---------------------------------------------------------------------------
       
    20  * 
       
    21  * Copyright (C) 1989 by Jef Poskanzer.
       
    22  *
       
    23  * Permission to use, copy, modify, and distribute this software and its
       
    24  * documentation for any purpose and without fee is hereby granted, provided
       
    25  * that the above copyright notice appear in all copies and that both that
       
    26  * copyright notice and this permission notice appear in supporting
       
    27  * documentation.  This software is provided "as is" without express or
       
    28  * implied warranty.
       
    29  *
       
    30  * ---------------------------------------------------------------------------
       
    31  *
       
    32  * The Graphics Interchange Format(c) is the Copyright property of
       
    33  * CompuServe Incorporated.  GIF(sm) is a Service Mark property of
       
    34  * CompuServe Incorporated.
       
    35  */
       
    36 
       
    37 #include "gifenc.h"
       
    38 
       
    39 static const unsigned int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
       
    40                                       0x001F, 0x003F, 0x007F, 0x00FF,
       
    41                                       0x01FF, 0x03FF, 0x07FF, 0x0FFF,
       
    42                                       0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
       
    43 
       
    44 GifEncoder::GifEncoder(Byte *rawBytes,Color *p,int w,int h, Byte d,
       
    45                        int t)
       
    46   : colorResolution(8),globalPaletteFlag(0x80),bits(12),
       
    47     maxMaxCode(1<<bits)
       
    48 {
       
    49   width = w;
       
    50   height = h;
       
    51   depth = d;
       
    52   transIndex = t;
       
    53   palette = p;
       
    54   data = rawBytes;
       
    55   dataPtr = data;
       
    56 }
       
    57 
       
    58 GifEncoder::~GifEncoder()
       
    59 {
       
    60 }
       
    61 
       
    62 void GifEncoder::writeGIF(QFile &fp)
       
    63 {
       
    64   // Write the Magic header
       
    65   fp.writeBlock( transIndex < 0 ? "GIF87a" : "GIF89a", 6 );
       
    66 
       
    67   // Write the logical screen descriptor
       
    68   putWord( width,   fp );
       
    69   putWord( height,  fp );
       
    70   Byte pack = globalPaletteFlag | ((colorResolution-1)<<4) | (depth-1);
       
    71   putByte( pack,    fp );
       
    72   putByte( 0,       fp ); // the background color
       
    73   putByte( 0,       fp ); // no aspect ration defined
       
    74 
       
    75   // Write global color table
       
    76   int i; for ( i=0 ; i< (1<<depth) ; i++)
       
    77   {
       
    78     putByte(palette[i].red,  fp);
       
    79     putByte(palette[i].green,fp);
       
    80     putByte(palette[i].blue, fp);
       
    81   }
       
    82   
       
    83   if ( transIndex >= 0)
       
    84   {
       
    85     // Write graphic control extension (needed for GIF transparancy)
       
    86     putByte( 0x21, fp); // extension introducer
       
    87     putByte( 0xf9, fp); // graphic control label
       
    88     putByte(    4, fp); // block size
       
    89     putByte(    1, fp); // announce transparacy value
       
    90     putWord(    0, fp); // zero delay time
       
    91     putByte( transIndex, fp); // write transparant index
       
    92     putByte(    0, fp); // end block
       
    93   }
       
    94   
       
    95   // Write the image descriptor
       
    96   putByte(   0x2c, fp); // image separator
       
    97   putWord(      0, fp); // image left position
       
    98   putWord(      0, fp); // image top position
       
    99   putWord(  width, fp); // image width
       
   100   putWord( height, fp); // image height
       
   101   putByte(      0, fp); // no local color table, no interlacing
       
   102  
       
   103   // Write table based image data
       
   104   Byte initCodeSize = depth<=1 ? 2 : depth;
       
   105   putByte( initCodeSize, fp); // LZW Minimum Code Size
       
   106   compress( initCodeSize+1, fp);
       
   107   putByte( 0, fp); // end of blocks
       
   108  
       
   109   // Write GIF Trailer
       
   110   putByte( 0x3b, fp);
       
   111 }
       
   112 
       
   113 void GifEncoder::compress( int ibits, QFile &outfile )
       
   114 {
       
   115   int i;
       
   116   int entry;
       
   117 
       
   118   initBits  = ibits;
       
   119   numPixels = width*height;
       
   120   dataPtr   = data;
       
   121   clearFlag = FALSE;
       
   122   nBits     = initBits;
       
   123   maxCode   = (1<<nBits) -1;
       
   124   ClearCode = (1 << (initBits - 1));
       
   125   EOFCode   = ClearCode + 1;
       
   126   freeEntry = ClearCode + 2;
       
   127   aCount    = 0;
       
   128   curAccum  = 0;
       
   129   curBits   = 0;
       
   130 
       
   131   entry = nextPixel();
       
   132 
       
   133   int hshift = 0;
       
   134   int fcode;
       
   135   for ( fcode = hashTableSize;  fcode < 65536L; fcode *= 2L ) ++hshift;
       
   136   hshift = 8 - hshift;                /* set hash code range bound */
       
   137 
       
   138   clearHashTable();                   /* clear hash table */
       
   139 
       
   140   writeCode( ClearCode,outfile );
       
   141 
       
   142   int c;
       
   143   while ( (c = nextPixel()) != EOF ) 
       
   144   {  
       
   145     fcode = (c << bits) + entry;
       
   146     i = (c << hshift) ^ entry;    /* xor hashing */
       
   147 
       
   148     bool found=FALSE;
       
   149     if (htab[i]==fcode) 
       
   150     {
       
   151       entry = codetab[i];
       
   152       found=TRUE;
       
   153     } 
       
   154     else if (htab[i]>=0)
       
   155     {
       
   156       int disp = hashTableSize - i;
       
   157       if (i==0) disp=1;
       
   158       do
       
   159       {
       
   160         if ((i-=disp)<0) i+=hashTableSize;
       
   161         if (htab[i]==fcode)
       
   162         {
       
   163           entry=codetab[i];
       
   164           found=TRUE;
       
   165         }
       
   166       } while (htab[i]>0 && !found);
       
   167     }
       
   168     if (!found)
       
   169     {
       
   170       writeCode( entry, outfile );
       
   171       entry = c;
       
   172       if ( freeEntry < maxMaxCode ) 
       
   173       {
       
   174         codetab[i] = freeEntry++; /* code -> hashtable */
       
   175         htab[i]    = fcode;
       
   176       } 
       
   177       else
       
   178       {
       
   179         clearHashTable();
       
   180         freeEntry = ClearCode + 2;
       
   181         clearFlag = TRUE;
       
   182         writeCode( ClearCode, outfile );
       
   183       }
       
   184     }
       
   185   }
       
   186   writeCode( entry, outfile );
       
   187   writeCode( EOFCode, outfile );
       
   188 }
       
   189 
       
   190 void GifEncoder::putWord( Word w, QFile &fp )
       
   191 {
       
   192   fp.putch( w & 0xff );
       
   193   fp.putch( (w>>8) & 0xff );
       
   194 }
       
   195 
       
   196 void GifEncoder::putByte( Byte b, QFile &fp )
       
   197 {
       
   198   fp.putch( b );
       
   199 }
       
   200 
       
   201 void GifEncoder::writeCode( int code, QFile &outfile )
       
   202 {
       
   203   curAccum &= masks[ curBits ];
       
   204 
       
   205   if ( curBits > 0 ) 
       
   206   {
       
   207     curAccum |= (code << curBits);
       
   208   }
       
   209   else
       
   210   {
       
   211     curAccum = code;
       
   212   }
       
   213 
       
   214   curBits += nBits;
       
   215 
       
   216   while( curBits >= 8 ) 
       
   217   {
       
   218     writeChar( (Byte)(curAccum & 0xff),outfile );
       
   219     curAccum >>= 8;
       
   220     curBits -= 8;
       
   221   }
       
   222 
       
   223   /*
       
   224    * If the next entry is going to be too big for the code size,
       
   225    * then increase it, if possible.
       
   226    */
       
   227   if ( freeEntry > maxCode || clearFlag ) 
       
   228   {
       
   229     if( clearFlag ) 
       
   230     {
       
   231       nBits = initBits;
       
   232       maxCode = (1<<nBits)-1;
       
   233       clearFlag = FALSE;
       
   234     } 
       
   235     else 
       
   236     {
       
   237       ++nBits;
       
   238       if ( nBits == bits )
       
   239         maxCode = maxMaxCode;
       
   240       else
       
   241         maxCode = (1<<nBits)-1;
       
   242     }
       
   243   }
       
   244 
       
   245   if ( code == EOFCode ) 
       
   246   {
       
   247     /* At EOF, write the rest of the buffer.  */
       
   248     while( curBits > 0 ) 
       
   249     {
       
   250       writeChar( (Byte)(curAccum & 0xff), outfile );
       
   251       curAccum >>= 8;
       
   252       curBits -= 8;
       
   253     }
       
   254 
       
   255     writePacket(outfile);
       
   256   }
       
   257 }
       
   258 
       
   259 /*
       
   260  * Add a character to the end of the current packet, and if it is 254
       
   261  * characters, flush the packet to disk.
       
   262  */
       
   263 void GifEncoder::writeChar( Byte c, QFile &fp )
       
   264 {
       
   265   accum[ aCount++ ] = c;
       
   266   if( aCount >= 254 ) writePacket(fp);
       
   267 }
       
   268 
       
   269 /*
       
   270  * Flush the packet to disk, and reset the accumulator
       
   271  */
       
   272 void GifEncoder::writePacket(QFile &fp)
       
   273 {
       
   274   if ( aCount > 0 ) 
       
   275   {
       
   276     fp.putch( aCount );
       
   277     fp.writeBlock( (const char *)accum, aCount );
       
   278     aCount = 0;
       
   279   }
       
   280 }
       
   281 
       
   282 void GifEncoder::clearHashTable()          /* reset code table */
       
   283 {
       
   284   int *htab_p = htab;
       
   285   int i; for (i=0;i<hashTableSize;i++) *htab_p++ = -1;
       
   286 }
       
   287