📄 gifenc.cpp
字号:
/****************************************************************************** * * $Id: gifenc.cpp,v 1.7 2001/03/19 19:27:40 root Exp $ * * * Copyright (C) 1997-2001 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * * The GIF compression code below is based on the file ppmtogif.c of the * netpbm package. The original copyright message follows: * * --------------------------------------------------------------------------- * * Copyright (C) 1989 by Jef Poskanzer. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. * * --------------------------------------------------------------------------- * * The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated. */#include "gifenc.h"static const unsigned int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };GifEncoder::GifEncoder(Byte *rawBytes,Color *p,int w,int h, Byte d, int t) : colorResolution(8),globalPaletteFlag(0x80),bits(12), maxMaxCode(1<<bits){ width = w; height = h; depth = d; transIndex = t; palette = p; data = rawBytes; dataPtr = data;}GifEncoder::~GifEncoder(){}void GifEncoder::writeGIF(QFile &fp){ // Write the Magic header fp.writeBlock( transIndex < 0 ? "GIF87a" : "GIF89a", 6 ); // Write the logical screen descriptor putWord( width, fp ); putWord( height, fp ); Byte pack = globalPaletteFlag | ((colorResolution-1)<<4) | (depth-1); putByte( pack, fp ); putByte( 0, fp ); // the background color putByte( 0, fp ); // no aspect ration defined // Write global color table int i; for ( i=0 ; i< (1<<depth) ; i++) { putByte(palette[i].red, fp); putByte(palette[i].green,fp); putByte(palette[i].blue, fp); } if ( transIndex >= 0) { // Write graphic control extension (needed for GIF transparancy) putByte( 0x21, fp); // extension introducer putByte( 0xf9, fp); // graphic control label putByte( 4, fp); // block size putByte( 1, fp); // announce transparacy value putWord( 0, fp); // zero delay time putByte( transIndex, fp); // write transparant index putByte( 0, fp); // end block } // Write the image descriptor putByte( 0x2c, fp); // image separator putWord( 0, fp); // image left position putWord( 0, fp); // image top position putWord( width, fp); // image width putWord( height, fp); // image height putByte( 0, fp); // no local color table, no interlacing // Write table based image data Byte initCodeSize = depth<=1 ? 2 : depth; putByte( initCodeSize, fp); // LZW Minimum Code Size compress( initCodeSize+1, fp); putByte( 0, fp); // end of blocks // Write GIF Trailer putByte( 0x3b, fp);}void GifEncoder::compress( int ibits, QFile &outfile ){ int i; int entry; initBits = ibits; numPixels = width*height; dataPtr = data; clearFlag = FALSE; nBits = initBits; maxCode = (1<<nBits) -1; ClearCode = (1 << (initBits - 1)); EOFCode = ClearCode + 1; freeEntry = ClearCode + 2; aCount = 0; curAccum = 0; curBits = 0; entry = nextPixel(); int hshift = 0; int fcode; for ( fcode = hashTableSize; fcode < 65536L; fcode *= 2L ) ++hshift; hshift = 8 - hshift; /* set hash code range bound */ clearHashTable(); /* clear hash table */ writeCode( ClearCode,outfile ); int c; while ( (c = nextPixel()) != EOF ) { fcode = (c << bits) + entry; i = (c << hshift) ^ entry; /* xor hashing */ bool found=FALSE; if (htab[i]==fcode) { entry = codetab[i]; found=TRUE; } else if (htab[i]>=0) { int disp = hashTableSize - i; if (i==0) disp=1; do { if ((i-=disp)<0) i+=hashTableSize; if (htab[i]==fcode) { entry=codetab[i]; found=TRUE; } } while (htab[i]>0 && !found); } if (!found) { writeCode( entry, outfile ); entry = c; if ( freeEntry < maxMaxCode ) { codetab[i] = freeEntry++; /* code -> hashtable */ htab[i] = fcode; } else { clearHashTable(); freeEntry = ClearCode + 2; clearFlag = TRUE; writeCode( ClearCode, outfile ); } } } writeCode( entry, outfile ); writeCode( EOFCode, outfile );}void GifEncoder::putWord( Word w, QFile &fp ){ fp.putch( w & 0xff ); fp.putch( (w>>8) & 0xff );}void GifEncoder::putByte( Byte b, QFile &fp ){ fp.putch( b );}void GifEncoder::writeCode( int code, QFile &outfile ){ curAccum &= masks[ curBits ]; if ( curBits > 0 ) { curAccum |= (code << curBits); } else { curAccum = code; } curBits += nBits; while( curBits >= 8 ) { writeChar( (Byte)(curAccum & 0xff),outfile ); curAccum >>= 8; curBits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if ( freeEntry > maxCode || clearFlag ) { if( clearFlag ) { nBits = initBits; maxCode = (1<<nBits)-1; clearFlag = FALSE; } else { ++nBits; if ( nBits == bits ) maxCode = maxMaxCode; else maxCode = (1<<nBits)-1; } } if ( code == EOFCode ) { /* At EOF, write the rest of the buffer. */ while( curBits > 0 ) { writeChar( (Byte)(curAccum & 0xff), outfile ); curAccum >>= 8; curBits -= 8; } writePacket(outfile); }}/* * Add a character to the end of the current packet, and if it is 254 * characters, flush the packet to disk. */void GifEncoder::writeChar( Byte c, QFile &fp ){ accum[ aCount++ ] = c; if( aCount >= 254 ) writePacket(fp);}/* * Flush the packet to disk, and reset the accumulator */void GifEncoder::writePacket(QFile &fp){ if ( aCount > 0 ) { fp.putch( aCount ); fp.writeBlock( (const char *)accum, aCount ); aCount = 0; }}void GifEncoder::clearHashTable() /* reset code table */{ int *htab_p = htab; int i; for (i=0;i<hashTableSize;i++) *htab_p++ = -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -