OutputGIF Class Reference

Contains functions to write a DIB to a GIF in segments, optionally with compression, optionally converting from one depth to another. To use: Open a CCLexFile for write. Call StartFile to write out the header. Call WriteBlock to write out each block of the bitmap, starting from low memory. When you're done, call TidyUp. Similar to OutputDIB but strangely enough writes the data as a GIF instead of a BMP or via the AccusoftFilters. More...

#include <outptgif.h>

Inheritance diagram for OutputGIF:

OutputDIB List of all members.

Public Member Functions

 OutputGIF ()
 Default constructor for the class. Just sets up the pointers to our buffers that may be used to be null so that the TidyUp function can do its job.
virtual ~OutputGIF ()
virtual BOOL StartFile (LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, INT32 ExportSize, UINT32 DitherType)
 Prepare to start the export of a GIF.
virtual BOOL ReStartFile (LOGPALETTE *pNewPal)
 Called to reset output before outputing another in a run of multiple images.
virtual BOOL WriteBlock (UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP=32, INT32 ProgressOffset=0)
 Writes a chunk of bitmap data to the device. Assumes a progress hourglass is required and the caller has started an hourglass with a size of 100 and will end it. Notes: Originally this routine assumed that it was being given a 32bpp bmp, but using the InputBPP param it will now handle 8bpp bmps as well...
virtual BOOL SetUpInfoHeader (const LPBITMAPINFOHEADER lpHeader, const UINT32 OutputDepth, const DWORD CompressionType, const UINT32 LIneWidth, const UINT32 FinalHeight, INT32 *PalSize)
 Set up the information header for the DIB.
virtual BOOL TidyUp ()
 When everything has been done via WriteBlock, call this to update the header etc. The caller is responsible for closing the file. The class CANNOT be used for further output until StartFile is called again.
BOOL OutputGifFileHeader (CCLexFile *File, LPBITMAPINFOHEADER pInfo, BOOL Enhanced, INT32 TransColour, LPLOGPALETTE pPalette=NULL, LPRGBQUAD pQuadPalette=NULL)
 Output a GIF file header for the specified bitmap to the file.
BOOL OutputGifFileHeader (CCLexFile *File, BOOL Enhanced, INT32 TransColour)
 Writes out the file header for the cached bitmap within this class.
BOOL OutputGifImageExtensionHeader (CCLexFile *File, BOOL InterlaceState, INT32 TransparentColour, UINT32 Delay, UINT32 RestoreType)
 Output a GIF image header for the specified bitmap to the file.
BOOL OutputGifImageBits (CCLexFile *File, LPBYTE pBlockStart, BOOL Interlace, BOOL LocalColourTable, BaseCamelotFilter *pFilter=NULL, UINT32 NewWidth=0, UINT32 NewHeight=0, UINT32 LeftOffset=0, UINT32 TopOffset=0, LPRGBQUAD pDestPalette=NULL, UINT32 PaletteColourDepth=0, UINT32 NewBitsPerPixel=0)
 Output the actual bits of a bitmap as compressed GIF data. Assumes that a header has already been output, possibly using OutputGifHeader. Assumes that all the data is present. The GIF specifcation allows us to output the next bitmap in an animation such that it is a subregion of a previous image. In this case we need to specify a new width and height plus a left and top offset.
BOOL OutputGifTerminator (CCLexFile *File)
 Outputs the GIF terminator sequence.
BOOL OutputAnimationControl (CCLexFile *File, unsigned short Repeats)
 Outputs a Netscape Animation Control block into the GIF file NOTE Must be inserted after file header but before image data.
virtual LPBITMAPINFO GetDestBitmapInfo (void)
 Access function to DestBitmapInfo.
virtual LPBYTE GetDestBitmapBits (void)
 Access function to DestBitmapBytes.
INT32 GetColourDepth (INT32 NumberOfColours)
 Converts the number of colours given into the colour depth that is required to output that number. This is not restricted to the colour depths of Window's DIBs i.e. 8, 4 and 1 but can be any colour depth less than 8 bpps.

Protected Types

typedef unsigned char char_type

Protected Member Functions

void CompressBlockToFile (LPBYTE Buffer, INT32 init_bits)
 Compress the specified bitmap out to the file specified in the class variable OutputFile. Assumes that variables such as Width, Height, WidthOfLine have been set up by the caller from the bitmap we are about to compress. This is done by the usual calling function of this OutputGifBits and OutputGifHeader.
void OutputCode (code_int code)
 Output the given code. This assumes that chars are 8 bits long. It maintains a GIFBITS character INT32 buffer (so that 8 codes will fit in it exactly). When the buffer fills up empty it and start over.
void ClearBlock ()
 Clear out the hash table for block compress.
void ClearHashTable (count_int hsize)
 reset the code table back to the default values
void CharacterInit ()
 Set up the 'byte output' routine.
void OutputCharacter (INT32 c)
 Add a character to the end of the current packet, and if it is 254 characters, flush the packet to disk.
void FlushCharacters ()
 Flush the packet to disk, and reset the accumulator (class variable a_count).
INT32 GIFNextPixel ()
 -Return the next pixel from the image using the class variables curx, cury as the current positions and afterwards moving them to the next positions. Takes into account if interlacing is on.
void BumpPixel ()
 Bump the class variables 'curx' and 'cury' to point to the next pixel taking into account interlacing if it is on.

Protected Attributes

LPBITMAPINFO DestBitmapInfo
LPBYTE DestBitmapBytes
LPBYTE pNextStrip
BaseCamelotFilterpCamFilter
INT32 Width
INT32 Height
INT32 curx
INT32 cury
INT32 CurrentLine
INT32 CountDown
BOOL InterlacingOn
INT32 Pass
WORD BitsPerPixel
INT32 InitCodeSize
INT32 Background
LPBYTE DataBuffer
UINT32 WidthOfLine
INT32 n_bits
code_int maxcode
count_int htab [5003]
unsigned short codetab [5003]
code_int free_ent
INT32 clear_flg
INT32 offset
INT32 in_count
INT32 out_count
INT32 g_init_bits
INT32 ClearCode
INT32 EOFCode
UINT32 cur_accum
INT32 cur_bits
INT32 a_count
char accum [256]

Detailed Description

Contains functions to write a DIB to a GIF in segments, optionally with compression, optionally converting from one depth to another. To use: Open a CCLexFile for write. Call StartFile to write out the header. Call WriteBlock to write out each block of the bitmap, starting from low memory. When you're done, call TidyUp. Similar to OutputDIB but strangely enough writes the data as a GIF instead of a BMP or via the AccusoftFilters.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/4/95
See also:
OutputDIB;

Definition at line 142 of file outptgif.h.


Member Typedef Documentation

typedef unsigned char OutputGIF::char_type [protected]
 

Definition at line 206 of file outptgif.h.


Constructor & Destructor Documentation

OutputGIF::OutputGIF  ) 
 

Default constructor for the class. Just sets up the pointers to our buffers that may be used to be null so that the TidyUp function can do its job.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/4/95
See also:
OutputGIF::TidyUp

OutputDIB;

Definition at line 129 of file outptgif.cpp.

00130 {
00131     OutputFile = NULL;
00132     lpBitmap = NULL;
00133     ExportBuffer = NULL;
00134     DoExportConvert = NULL;
00135     OutputForward = FALSE;
00136 
00137     DestBitmapInfo = NULL;
00138     DestBitmapBytes = NULL;
00139 
00140     InterlacingOn = FALSE;
00141 
00142     pCamFilter = NULL;
00143 }

virtual OutputGIF::~OutputGIF  )  [inline, virtual]
 

Definition at line 147 of file outptgif.h.

00147 {}


Member Function Documentation

void OutputGIF::BumpPixel  )  [protected]
 

Bump the class variables 'curx' and 'cury' to point to the next pixel taking into account interlacing if it is on.

Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1696 of file outptgif.cpp.

01697 {
01698     // Bump the current X position
01699     ++curx;
01700 
01701     // If we are at the end of a scan line, set curx back to the beginning
01702     // If we are interlaced, bump the cury to the appropriate spot,
01703     // otherwise, just increment it.
01704     if( curx == Width )
01705     {
01706         // Reset x to start of next line
01707         curx = 0;
01708         
01709         CurrentLine++;
01710         
01711         // If Interlacing off then just increment the line we are on
01712         if( !InterlacingOn )
01713             ++cury;
01714         else
01715         {
01716             // Otherwise get the next interlaced line in the sequence
01717             // Use the same style of code that we use for import in GIFUtil
01718             switch (Pass)
01719             {
01720                 case 0:
01721                 case 1:
01722                     cury += 8;
01723                     break;
01724                 case 2:
01725                     cury += 4;
01726                     break;
01727                 case 3:
01728                     cury += 2;
01729                     break;
01730             }
01731 
01732             while (cury >= Height && Pass <= 3)
01733             {
01734                 ++Pass;
01735                 switch (Pass)
01736                 {
01737                     case 1:
01738                         cury = 4;
01739                         break;
01740                     case 2:
01741                         cury = 2;
01742                         break;
01743                     case 3:
01744                         cury = 1;
01745                         break;
01746                     default:
01747                         cury = 0;
01748                         break;
01749                 }
01750             }
01751         }
01752     
01753         // Show a progress bar
01754         if (pCamFilter == NULL)
01755         {
01756             // Andy, 13-12-00: We don't want another progress bar if we're exporting
01757             //ContinueSlowJob( (INT32)(100 * CurrentLine/(Height)) );
01758         }
01759         else
01760             pCamFilter->IncProgressBarCount(1);
01761     }
01762 }

void OutputGIF::CharacterInit  )  [protected]
 

Set up the 'byte output' routine.

Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1511 of file outptgif.cpp.

01512 {
01513     a_count = 0;        // set accumlator to zero
01514 }

void OutputGIF::ClearBlock  )  [protected]
 

Clear out the hash table for block compress.

Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1441 of file outptgif.cpp.

01442 {
01443     ClearHashTable( (count_int) hsize );
01444     free_ent = ClearCode + 2;
01445     clear_flg = 1;
01446 
01447     OutputCode( (code_int)ClearCode );
01448 }

void OutputGIF::ClearHashTable count_int  hsize  )  [protected]
 

reset the code table back to the default values

Parameters:
hsize size of the maximum code size [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1461 of file outptgif.cpp.

01462 {
01463     // These used to have register in front of them
01464     count_int *htab_p = htab + hsize;
01465     INT32 i;
01466     INT32 m1 = -1;
01467 
01468     i = hsize - 16;
01469     do
01470     {
01471         *(htab_p - 16) = m1;
01472         *(htab_p - 15) = m1;
01473         *(htab_p - 14) = m1;
01474         *(htab_p - 13) = m1;
01475         *(htab_p - 12) = m1;
01476         *(htab_p - 11) = m1;
01477         *(htab_p - 10) = m1;
01478         *(htab_p - 9) = m1;
01479         *(htab_p - 8) = m1;
01480         *(htab_p - 7) = m1;
01481         *(htab_p - 6) = m1;
01482         *(htab_p - 5) = m1;
01483         *(htab_p - 4) = m1;
01484         *(htab_p - 3) = m1;
01485         *(htab_p - 2) = m1;
01486         *(htab_p - 1) = m1;
01487         htab_p -= 16;
01488     } while ((i -= 16) >= 0);
01489 
01490     for ( i += 16; i > 0; --i )
01491         *--htab_p = m1;
01492 }

void OutputGIF::CompressBlockToFile LPBYTE  Buffer,
INT32  init_bits
[protected]
 

Compress the specified bitmap out to the file specified in the class variable OutputFile. Assumes that variables such as Width, Height, WidthOfLine have been set up by the caller from the bitmap we are about to compress. This is done by the usual calling function of this OutputGifBits and OutputGifHeader.

Parameters:
Buffer pointer to the bits to be compressed [INPUTS] init_bits initial number of bits
- [OUTPUTS]
See also:
OutputGIF::OutputGifHeader; OutputGIF::OutputGifBits;

Definition at line 1255 of file outptgif.cpp.

01256 {
01257     // These used to have register before them
01258     INT32       fcode;
01259     code_int    i;  //= 0;
01260     INT32       c;
01261     code_int    ent;
01262     code_int    disp;
01263     code_int    hsize_reg;
01264     INT32       hshift;
01265 
01266     // Note the passed in buffer and size in our class variables
01267     DataBuffer  = Buffer;
01268 
01269     // Calculate number of bits we are expecting
01270     CountDown   = (INT32)Width * (INT32)Height;
01271 
01272     // Work out the word/byte rounded line width rather than the pixel width
01273     WidthOfLine = DIBUtil::ScanlineSize( Width, BitsPerPixel );
01274 
01275     // Set up the globals:  g_init_bits - initial number of bits
01276     g_init_bits = init_bits;
01277 
01278     // Set up the necessary values
01279     offset      = 0;
01280     out_count   = 0;
01281     clear_flg   = 0;
01282     in_count    = 1;
01283     maxcode     = MAXCODE(n_bits = init_bits);
01284     ClearCode   = (1 << (init_bits - 1));
01285     EOFCode     = ClearCode + 1;
01286     free_ent    = ClearCode + 2;
01287 
01288     // Indicate which pass we are on (if interlace)
01289     Pass        = 0;
01290 
01291     // Set up the current x and y position
01292     curx        = 0;
01293     cury        = 0;
01294     CurrentLine = 0;
01295 
01296     cur_accum   = 0;
01297     cur_bits    = 0;
01298 
01299     CharacterInit();    // a_count = 0;
01300 
01301     ent = GIFNextPixel();
01302 
01303     hshift = 0;
01304     for ( fcode = (INT32) hsize;  fcode < 65536L; fcode *= 2L )
01305         ++hshift;
01306     hshift = 8 - hshift;                // set hash code range bound
01307 
01308     // clear hash table
01309     hsize_reg = hsize;
01310     ClearHashTable( (count_int) hsize_reg); 
01311 
01312     OutputCode( (code_int)ClearCode );
01313 
01314     while ( (c = GIFNextPixel()) != EOF )
01315     {
01316         ++in_count;
01317 
01318         fcode = (INT32) (((INT32) c << maxbits) + ent);
01319         i = (((code_int)c << hshift) ^ ent);    // xor hashing
01320 
01321         if ( HashTabOf(i) == fcode )
01322         {
01323             ent = CodeTabOf(i);
01324             continue;
01325         }
01326         else if ( (INT32)HashTabOf(i) < 0 )      // empty slot
01327             goto nomatch;
01328 
01329         disp = hsize_reg - i;                   // secondary hash (after G. Knott)
01330         if ( i == 0 )
01331             disp = 1;
01332             
01333 probe:
01334         if ( (i -= disp) < 0 )
01335             i += hsize_reg;
01336 
01337         if ( HashTabOf(i) == fcode )
01338         {
01339             ent = CodeTabOf(i);
01340             continue;
01341         }
01342         if ( (INT32)HashTabOf(i) > 0 )
01343             goto probe;
01344             
01345 nomatch:
01346         OutputCode( (code_int) ent );
01347         ++out_count;
01348         ent = c;
01349         if ( free_ent < maxmaxcode )
01350         {
01351             CodeTabOf(i) = free_ent++; /* code -> hashtable */
01352             HashTabOf(i) = fcode;
01353         }
01354         else
01355             ClearBlock();
01356     }
01357     // Put out the final code.
01358     OutputCode( (code_int) ent );
01359     ++out_count;
01360     OutputCode( (code_int) EOFCode );
01361 }

void OutputGIF::FlushCharacters  )  [protected]
 

Flush the packet to disk, and reset the accumulator (class variable a_count).

Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1546 of file outptgif.cpp.

01547 {
01548     if( a_count > 0 )
01549     {
01550         OutputFile->put( a_count );
01551         OutputFile->write( &accum, a_count);
01552         a_count = 0;
01553     }
01554 }

INT32 OutputGIF::GetColourDepth INT32  NumberOfColours  ) 
 

Converts the number of colours given into the colour depth that is required to output that number. This is not restricted to the colour depths of Window's DIBs i.e. 8, 4 and 1 but can be any colour depth less than 8 bpps.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/5/97
Parameters:
NumberOfColours The number of colours in the palette of the bitmap [INPUTS]
- [OUTPUTS]
Returns:
The colour depth

Definition at line 773 of file outptgif.cpp.

00774 {
00775     INT32 ColourDepth = 8;
00776     if (NumberOfColours <= 2)
00777         // Changed by Craig Hamilton 14/9/00.
00778         ColourDepth = 1;
00779         // End changed.
00780     else if (NumberOfColours <= 4)
00781         ColourDepth = 2;
00782     else if (NumberOfColours <= 8)
00783         ColourDepth = 3;
00784     else if (NumberOfColours <= 16)
00785         ColourDepth = 4;
00786     else if (NumberOfColours <= 32)
00787         ColourDepth = 5;
00788     else if (NumberOfColours <= 64)
00789         ColourDepth = 6;
00790     else if (NumberOfColours <= 128)
00791         ColourDepth = 7;
00792     else if (NumberOfColours <= 256)
00793         ColourDepth = 8;
00794 
00795     return ColourDepth;
00796 }

LPBYTE OutputGIF::GetDestBitmapBits void   )  [virtual]
 

Access function to DestBitmapBytes.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/6/00
Parameters:
pPalette - Palette information that we want to copy from [INPUTS]
Returns:
A pointer to the bitmap itself.

Reimplemented from OutputDIB.

Definition at line 753 of file outptgif.cpp.

00754 {
00755     return DestBitmapBytes;
00756 }

LPBITMAPINFO OutputGIF::GetDestBitmapInfo void   )  [virtual]
 

Access function to DestBitmapInfo.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/6/00
Parameters:
pPalette - Palette information that we want to copy from [INPUTS]
Returns:
A pointer to the bitmap information structure.

Reimplemented from OutputDIB.

Definition at line 736 of file outptgif.cpp.

00737 {
00738     return DestBitmapInfo;
00739 }

INT32 OutputGIF::GIFNextPixel  )  [protected]
 

-Return the next pixel from the image using the class variables curx, cury as the current positions and afterwards moving them to the next positions. Takes into account if interlacing is on.

Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
the value of the specified pixel or 0 if badly specified

Definition at line 1607 of file outptgif.cpp.

01608 {
01609     INT32 Pixel;
01610 
01611     // First, check whether we have done all the pixels in the image
01612     if( CountDown == 0 )
01613         return EOF;
01614 
01615     // Decrement our pixel count
01616     --CountDown;
01617 
01618     //r = GetPixel(curx, cury);
01619     if ( !(((cury < 0) || (cury >= Height)) || ((curx < 0) || (curx >= Width))) && DataBuffer )
01620     {
01621         // Our DIBs are the wrong way up so we must output the data from the last 
01622         // line of the image and go up to the start
01623         // -1 as height = 1 .. Height whereas y goes from 0 .. Height - 1
01624         // Use the word/byte rounded line width rather than the pixel width
01625         // always compresses a byte regardless of colour depth. 
01626         switch (BitsPerPixel)
01627         {
01628             case 8:
01629                 {
01630                     // If 8 bpp then just use the whole byte straight
01631                     LPBYTE pData = DataBuffer + curx + ((Height - 1 - cury)  * WidthOfLine);
01632                     Pixel = *(pData);
01633                 }
01634                 break;
01635 
01636             case 4:
01637                 {
01638                     // 4bpp so we must get the high or low nibble. This will be dependent on
01639                     // whether we are on an odd or even pixel. So test the LSBit of the curx,
01640                     // if set we will be odd. Only move onto next byte every other pixel hence
01641                     // curx/2.
01642                     LPBYTE pData = DataBuffer + curx/2 + ((Height - 1 - cury)  * WidthOfLine);
01643                     Pixel = *(pData);
01644                     if (curx & 1)
01645                         Pixel = (Pixel & 0x0F);         // take low nibble 
01646                     else
01647                         Pixel = (Pixel & 0xF0) >> 4;    // take top nibble 
01648                 }
01649                 break;
01650             case 1:
01651                 {
01652                     // 1bpp - pixels are stored in bits.
01653                     LPBYTE pData = DataBuffer + curx/8 + ((Height - 1 - cury)  * WidthOfLine);
01654                     BYTE Mask = 0x80 >> (curx % 8);
01655                     if (((*pData) & Mask) == 0)
01656                         Pixel = 0;
01657                     else
01658                         Pixel = 1;
01659                 }
01660                 break;
01661             default:
01662                 ERROR3("Unknown export depth");
01663                 Pixel = 0;  // bad bpp but should not get here
01664             }
01665     }
01666     else
01667     {
01668         ERROR3("Something bad has happened");
01669         Pixel = 0;
01670     }
01671     
01672     // Move the curx, cury to the next pixel on the image taking into account interlacing
01673     BumpPixel();
01674 
01675     // Check that the pixel is not outside of the allowed range
01676     // If it is then what do we do with it? Set it 0 for now.
01677     ERROR3IF(Pixel >= ClearCode,"Trying to output pixel >= ClearCode");
01678     if (Pixel >= ClearCode)
01679         Pixel = 0;
01680 
01681     return Pixel;
01682 }

BOOL OutputGIF::OutputAnimationControl CCLexFile File,
unsigned short  Repeats
 

Outputs a Netscape Animation Control block into the GIF file NOTE Must be inserted after file header but before image data.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/6/96
Parameters:
File - file to output to [INPUTS]
- [OUTPUTS]
Returns:
TRUE if worked, FALSE if failed

Definition at line 686 of file outptgif.cpp.

00687 {
00688     ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputAnimationControl File pointer is null");
00689 
00690     BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
00691     BOOL OldReportingState = File->SetReportErrors( FALSE );
00692     try
00693     {
00694         // Generate the Netscape Extension block
00695         BYTE Block[19];
00696         Block[0] = 0x21;    // GIF extension code
00697         Block[1] = 0xFF;    // Application extension
00698         Block[2] = 0x0B;    // Length of application string
00699         memcpy(Block+3, "NETSCAPE2.0", 0x0B);   // Application string
00700         Block[14] = 0x03;   // Length of data sub-block
00701         Block[15] = 0x01;   // ??
00702         Block[16] = Repeats & 0xFF; // Low byte of repeats
00703         Block[17] = Repeats >> 8;   // High byte of repeats
00704         Block[18] = 0;      // Terminator
00705 
00706         File->write(Block, 19);
00707 
00708         File->SetThrowExceptions( OldThrowingState );
00709         File->SetReportErrors( OldReportingState );
00710 
00711         return TRUE;
00712     }
00713     catch(...)
00714     {
00715         File->SetThrowExceptions( OldThrowingState );
00716         File->SetReportErrors( OldReportingState );
00717 
00718         return FALSE;
00719     }
00720 
00721     ERROR2( FALSE, "Escaped exception clause somehow" );
00722 }   

void OutputGIF::OutputCharacter INT32  c  )  [protected]
 

Add a character to the end of the current packet, and if it is 254 characters, flush the packet to disk.

Parameters:
c character to add to the output stream [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 1528 of file outptgif.cpp.

01529 {
01530     accum[ a_count++ ] = c;
01531     if( a_count >= 255 )        // was 254 until 16/4/97 - Gavin suggested tweak
01532         FlushCharacters();
01533 }

void OutputGIF::OutputCode code_int  code  )  [protected]
 

Output the given code. This assumes that chars are 8 bits long. It maintains a GIFBITS character INT32 buffer (so that 8 codes will fit in it exactly). When the buffer fills up empty it and start over.

Parameters:
code A n_bits-bit integer. If == -1, then EOF. [INPUTS] This assumes that n_bits =< (INT32)wordsize - 1.
Outputs code to the file. [OUTPUTS]

Definition at line 1377 of file outptgif.cpp.

01378 {
01379     cur_accum &= masks[ cur_bits ];
01380 
01381     if( cur_bits > 0 )
01382         cur_accum |= ((INT32)code << cur_bits);
01383     else
01384         cur_accum = code;
01385 
01386     cur_bits += n_bits;
01387 
01388     while( cur_bits >= 8 )
01389     {
01390         OutputCharacter( (UINT32)(cur_accum & 0xff) );
01391         cur_accum >>= 8;
01392         cur_bits -= 8;
01393     }
01394 
01395     // If the next entry is going to be too big for the code size, then increase it,
01396     // if possible.
01397     if ( free_ent > maxcode || clear_flg )
01398     {
01399         if( clear_flg )
01400         {
01401             maxcode = MAXCODE(n_bits = g_init_bits);
01402             clear_flg = 0;
01403         }
01404         else
01405         {
01406             ++n_bits;
01407             if ( n_bits == maxbits )
01408                 maxcode = maxmaxcode;
01409             else
01410                 maxcode = MAXCODE(n_bits);
01411         }
01412     }
01413 
01414     if( code == EOFCode )
01415     {
01416         // At EOF, write the rest of the buffer.
01417         while( cur_bits > 0 )
01418         {
01419             OutputCharacter( (UINT32)(cur_accum & 0xff) );
01420             cur_accum >>= 8;
01421             cur_bits -= 8;
01422         }
01423 
01424         FlushCharacters();
01425 
01426         OutputFile->flush();
01427     }
01428 }

BOOL OutputGIF::OutputGifFileHeader CCLexFile File,
BOOL  Enhanced,
INT32  TransColour
 

Writes out the file header for the cached bitmap within this class.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/6/96
Parameters:
File - output file object [INPUTS] Enhanced - TRUE if enhanced GIF features are required (eg transpacency) TransColour - the index of the transparent colour (-1 for no transparency)
- [OUTPUTS]
Returns:
TRUE if worked, FALSE if failed
See also:
OutputGIF::OutputGifFileHeader (the other one)

Definition at line 418 of file outptgif.cpp.

00419 {
00420     return OutputGifFileHeader(File, &(DestBitmapInfo->bmiHeader), Enhanced, TransColour, OutputPalette);
00421 }

BOOL OutputGIF::OutputGifFileHeader CCLexFile File,
LPBITMAPINFOHEADER  pInfo,
BOOL  Enhanced,
INT32  TransColour,
LPLOGPALETTE  pPalette = NULL,
LPRGBQUAD  pQuadPalette = NULL
 

Output a GIF file header for the specified bitmap to the file.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/4/95
Parameters:
File file to output to [INPUTS] pInfo pointer to the bitmap info header Enhanced TRUE if useing advanced GIF features such as transparency or animation TransColour The transparent index or -1 if no transparency pPalette pointer to a palette in LOGPALETTE form (defaults to NULL) OR pQuadPalette pointer to a palette in RGBQUAD form (defaults to NULL)
- [OUTPUTS]
Returns:
TRUE if worked, FALSE if failed (error will be set accordingly but not reported)

Errors: Calls SetError on FALSE returns.

See also:
OutputGIF::StartFile; OutputGIF::WriteBlock; OutputGIF::TidyUp Scope: static

Definition at line 445 of file outptgif.cpp.

00446 {
00447     ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputGifHeader File pointer is null");
00448     ERROR2IF(pInfo==NULL,FALSE,"OutputGIF::OutputGifHeader BitmapInfo pointer is null");
00449     ERROR2IF(pPalette==NULL && pQuadPalette==NULL,FALSE,"OutputGIF::OutputGifHeader Bitmap palette pointer is null");
00450 
00451     // Note file in our class variable as used by all the low level routines
00452     OutputFile = File;
00453 
00454     // Must set the exception throwing flag to True and force reporting of errors to False.
00455     // This means that the caller must report an error if the function returns False.
00456     // Any calls to CCFile::GotError will now throw a file exception and should fall into
00457     // the catch handler at the end of the function.
00458     // Replaces the goto's that handled this before.
00459     BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
00460     BOOL OldReportingState = File->SetReportErrors( FALSE );
00461 
00462     try
00463     {
00464         // Set up the class variables
00465         // First the width/height of the bitmap
00466         Width = pInfo->biWidth;
00467         Height = pInfo->biHeight;
00468         INT32 PalSize = pInfo->biClrUsed;
00469         // Translate this into a bits per pixel which is not limited to 8, 4 and 1.
00470         INT32 ColourDepth = GetColourDepth(PalSize);
00471         // ColourDepth will be rounded to nearest power of two so need to output
00472         // that many palette entries
00473         INT32 NewPalSize = 1 << ColourDepth;
00474         InitCodeSize = ColourDepth;
00475 
00476         BitsPerPixel = pInfo->biBitCount;
00477 
00478         TRACEUSER( "Neville", _T("OutputGifFileHeader - Colour depth = %d\n"),ColourDepth);
00479 
00480         // Write out the unique GIF header
00481         GIFINFOHEADER Header;
00482         if (Enhanced)
00483             memcpy(Header.giName, "GIF89a", 6); 
00484         else
00485             memcpy(Header.giName, "GIF87a", 6); 
00486             
00487         // Indicate that there is a global colour map
00488         BYTE Flags = 0;
00489         // global colour table flag, colour resoltion sort flag and 
00490         // size of global colour table
00491         if ((pPalette || pQuadPalette) && (PalSize > 0))
00492             Flags  = 0x80;                  // Flag there is a colour map
00493         // 3 bit colour resolution value = number of bits per primary colour - 1
00494         Flags |= ((BitsPerPixel - 1) & 0x07) << 4;  // OR in the colour resolution
00495         // 3 bit size of global colour table = number of bits - 1
00496         Flags |= (ColourDepth - 1) & 0x07;  // OR in global colour table size
00497 
00498         Header.giWidth      = (WORD)Width;
00499         Header.giHeight     = (WORD)Height;
00500         Header.giFlags      = Flags;
00501         Header.giBackground = TransColour==-1 ? 0 : TransColour;
00502         Header.giAspect     = 0;
00503         // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13
00504         // as it rounds to the nearest word boundary
00505         const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3;
00506         File->write( &Header, HeaderSize );
00507 
00508         if (pQuadPalette && NewPalSize > 0)
00509         {
00510             // Palette supplied in RGBQUAD form 
00511             // write it to disk in GIFRGBTRIPLE format
00512             GIFRGBTRIPLE TempRGB;
00513             for (INT32 i = 0; i < NewPalSize; i++)
00514             {
00515                 // If we are using transparency then bodge the transparent colour to
00516                 // be White. Otherwise, if we load it back it then we could have a strange
00517                 // colour being shown as we don't support transparency on loading.
00518                 if (TransColour >= 0 && i == TransColour)
00519                 {
00520                     // Make transparent colour white
00521                     TempRGB.grgbtRed    = 0xFF;
00522                     TempRGB.grgbtGreen  = 0xFF;
00523                     TempRGB.grgbtBlue   = 0xFF;
00524                 }
00525                 else if (i > PalSize)
00526                 {
00527                     // Make blank palette entries black
00528                     TempRGB.grgbtRed    = 0x00;
00529                     TempRGB.grgbtGreen  = 0x00;
00530                     TempRGB.grgbtBlue   = 0x00;
00531                 }
00532                 else
00533                 {
00534                     TempRGB.grgbtRed    = pQuadPalette->rgbRed;
00535                     TempRGB.grgbtGreen  = pQuadPalette->rgbGreen;
00536                     TempRGB.grgbtBlue   = pQuadPalette->rgbBlue;
00537                 }
00538                 
00539                 File->write( &TempRGB, sizeof(GIFRGBTRIPLE) );
00540                 // skip to the next palette entry
00541                 pQuadPalette++;
00542             }
00543         }
00544         else if (pPalette && NewPalSize > 0)
00545         {
00546             // Palette supplied in LOGPALETTE form 
00547             // write it to disk in GIFRGBTRIPLE format
00548             GIFRGBTRIPLE TempRGB;
00549             for (INT32 i = 0; i < NewPalSize; i++)
00550             {
00551                 // If we are using transparency then bodge the transparent colour to
00552                 // be White. Otherwise, if we load it back it then we could have a strange
00553                 // colour being shown as we don't support transparency on loading.
00554                 if (TransColour >= 0 && i == TransColour)
00555                 {
00556                     // Make transparent colour white
00557                     TempRGB.grgbtRed    = 0xFF;
00558                     TempRGB.grgbtGreen  = 0xFF;
00559                     TempRGB.grgbtBlue   = 0xFF;
00560                 }
00561                 else if (i > PalSize)
00562                 {
00563                     // Make blank palette entries black
00564                     TempRGB.grgbtRed    = 0x00;
00565                     TempRGB.grgbtGreen  = 0x00;
00566                     TempRGB.grgbtBlue   = 0x00;
00567                 }
00568                 else
00569                 {
00570                     TempRGB.grgbtRed    = pPalette->palPalEntry[i].peRed;
00571                     TempRGB.grgbtGreen  = pPalette->palPalEntry[i].peGreen;
00572                     TempRGB.grgbtBlue   = pPalette->palPalEntry[i].peBlue;
00573                 }
00574                 File->write( &TempRGB, sizeof(GIFRGBTRIPLE) );
00575             }
00576         }
00577         else
00578             ERROR3("OutputGIF::OutputGifHeader No palette specified");
00579 
00580         // Must set the exception throwing and reporting flags back to their entry states
00581         File->SetThrowExceptions( OldThrowingState );
00582         File->SetReportErrors( OldReportingState );
00583 
00584         // er, we seem to have finished OK so say so
00585         return TRUE;
00586     }
00587     catch(...)
00588     {
00589         // catch our form of a file exception
00590         TRACE( _T("OutputGIF::OutputGifHeader CC catch handler\n"));
00591 
00592         // Must set the exception throwing and reporting flags back to their entry states
00593         File->SetThrowExceptions( OldThrowingState );
00594         File->SetReportErrors( OldReportingState );
00595 
00596         return FALSE;
00597     }
00598 
00599     ERROR2( FALSE, "Escaped exception clause somehow" );
00600 }   

BOOL OutputGIF::OutputGifImageBits CCLexFile File,
LPBYTE  pBlockStart,
BOOL  Interlace,
BOOL  LocalColourTable,
BaseCamelotFilter pFilter = NULL,
UINT32  NewWidth = 0,
UINT32  NewHeight = 0,
UINT32  LeftOffset = 0,
UINT32  TopOffset = 0,
LPRGBQUAD  pDestPalette = NULL,
UINT32  PaletteColourDepth = 0,
UINT32  NewBitsPerPixel = 0
 

Output the actual bits of a bitmap as compressed GIF data. Assumes that a header has already been output, possibly using OutputGifHeader. Assumes that all the data is present. The GIF specifcation allows us to output the next bitmap in an animation such that it is a subregion of a previous image. In this case we need to specify a new width and height plus a left and top offset.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/4/95
Parameters:
File pointer to file to output to [INPUTS] pBlockStart actual bitmap data to write out Interlace TRUE if image should be interlaced LocalColourTable True if need to specify a local colour table, False if the global one is all that is required pFilter is an alternative way of handling the progress bar, assume the progress bar has been start and just call the IncProgressBarCount in BaseCamelotFilter to do the progress bar update. Defaults to NULL i.e. no progress bar. NewWidth The new width of this bitmap, defaults to 0 meaning none NewHeight The new height of this bitmap, defaults to 0 meaning none LeftOffset The offset of this bitmap from the left hand side, defaults to 0 TopOffset The offset of this bitmap from the top hand side, defaults to 0 pDestPalette The local palette to output NumberOfPalColours The number of colours in this local palette NewBitsPerPixel The new bits per pixel of the bitmap, defaults to 0 meaning none
- [OUTPUTS]
Returns:
TRUE if worked, FALSE if failed (error will be set accordingly but not reported)

Errors: Calls SetError on FALSE returns.

See also:
OutputGIF::OutputGifHeader; SeeAlo: OutputGIF::StartFile; OutputGIF::WriteBlock; OutputGIF::TidyUp Scope: static
Note: If we use the NewWidth and NewHeight input variables then we must ALWAYS input the height and width of the bitmap.

Definition at line 842 of file outptgif.cpp.

00847 {
00848     ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputGifHeader File pointer is null");
00849     ERROR2IF(pBlockStart==NULL,FALSE,"OutputGIF::OutputGifHeader BitmapInfo pointer is null");
00850 
00851     // Note file in our class variable as used by all the low level routines
00852     OutputFile = File;
00853     InterlacingOn = Interlace;
00854 
00855     // Set up our pointer to the alternative way of handling the progress bar
00856     // If it is the NULL default then do not use.
00857     pCamFilter = pFilter;
00858 
00859     if (NewWidth > 0 && NewHeight > 0)
00860     {
00861         // Set the statics to the new values. If we use this method then we must ALWAYS input
00862         // the height and width of the bitmap.
00863         Width = NewWidth;
00864         Height = NewHeight;
00865     }
00866 
00867     ERROR3IF(NewBitsPerPixel > 8,"Bad BPP in OutputGifImageBits");
00868     if (NewBitsPerPixel > 0 && NewBitsPerPixel <= 8)
00869         BitsPerPixel = NewBitsPerPixel;
00870 
00871     // Must set the exception throwing flag to True and force reporting of errors to False.
00872     // This means that the caller must report an error if the function returns False.
00873     // Any calls to CCFile::GotError will now throw a file exception and should fall into
00874     // the catch handler at the end of the function.
00875     // Replaces the goto's that handled this before.
00876     BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
00877     BOOL OldReportingState = File->SetReportErrors( FALSE );
00878 
00879     try
00880     {
00881         // Write an Image separator
00882         File->put(0x2C);
00883 
00884         // The initial code size
00885         if( BitsPerPixel <= 1 )
00886             InitCodeSize = 2;
00887         else
00888             InitCodeSize = BitsPerPixel;
00889 
00890         UINT32 ColourDepth = 1;
00891         
00892         if (pDestPalette && PaletteColourDepth > 0)
00893         {
00894             // Translate the number of colours into a bits per pixel which is not limited to 8, 4 and 1.
00895             ColourDepth = GetColourDepth(PaletteColourDepth);
00896             InitCodeSize = ColourDepth;
00897         }
00898         else
00899         {
00900             // Direct saving a bitmap has this set to null
00901             //ERROR3IF(DestBitmapInfo == NULL,"Bad DestBitmapInfo in OutputGifImageBits");
00902             if (DestBitmapInfo)
00903             {
00904                 ColourDepth = DestBitmapInfo->bmiHeader.biBitCount;
00905                 InitCodeSize = GetColourDepth(DestBitmapInfo->bmiHeader.biClrUsed);
00906             }
00907             else
00908                 ColourDepth = BitsPerPixel;
00909         }
00910 
00911         // Sanity check on the code size
00912         if (InitCodeSize > 8)
00913             InitCodeSize = 8;
00914         if (InitCodeSize < 2)
00915             InitCodeSize = 2;
00916 
00917         TRACEUSER( "Neville", _T("OutputGifImageBits - Colour depth = %d\n"),ColourDepth);
00918         
00919         // Write the Image header
00920         GIFIMAGEBLOCK Im