#include <outptgif.h>
Inheritance diagram for OutputGIF:

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 |
| BaseCamelotFilter * | pCamFilter |
| 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] |
Definition at line 142 of file outptgif.h.
|
|
Definition at line 206 of file outptgif.h. |
|
|
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.
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 }
|
|
|
Definition at line 147 of file outptgif.h.
|
|
|
Bump the class variables 'curx' and 'cury' to point to the next pixel taking into account interlacing if it is on.
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 }
|
|
|
Set up the 'byte output' routine.
Definition at line 1511 of file outptgif.cpp. 01512 { 01513 a_count = 0; // set accumlator to zero 01514 }
|
|
|
Clear out the hash table for block compress.
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 }
|
|
|
reset the code table back to the default values
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 }
|
|
||||||||||||
|
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.
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 }
|
|
|
Flush the packet to disk, and reset the accumulator (class variable a_count).
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 }
|
|
|
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.
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 }
|
|
|
Access function to DestBitmapBytes.
Reimplemented from OutputDIB. Definition at line 753 of file outptgif.cpp. 00754 { 00755 return DestBitmapBytes; 00756 }
|
|
|
Access function to DestBitmapInfo.
Reimplemented from OutputDIB. Definition at line 736 of file outptgif.cpp. 00737 { 00738 return DestBitmapInfo; 00739 }
|
|
|
-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.
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 }
|
|
||||||||||||
|
Outputs a Netscape Animation Control block into the GIF file NOTE Must be inserted after file header but before image data.
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 }
|
|
|
Add a character to the end of the current packet, and if it is 254 characters, flush the packet to disk.
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 }
|
|
|
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.
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 }
|
|
||||||||||||||||
|
Writes out the file header for the cached bitmap within this class.
Definition at line 418 of file outptgif.cpp. 00419 { 00420 return OutputGifFileHeader(File, &(DestBitmapInfo->bmiHeader), Enhanced, TransColour, OutputPalette); 00421 }
|
|
||||||||||||||||||||||||||||
|
Output a GIF file header for the specified bitmap to the file.
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 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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.
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 |