#include <gifutil.h>
Static Public Member Functions | |
static BOOL | ReadFromFile (CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, int *TransColour, String_64 *ProgressString=NULL, BaseCamelotFilter *pFilter=NULL) |
Default constructor for the class. Default destructor for the class. Reads a .gif file into memory decompressing it as it goes. Errors on 16-bit builds*** A progress hourglass can be shown if required. | |
static BOOL | ReadFromFile (CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, int *TransColour, int &nBitmapToRead, String_64 *ProgressString=NULL, BaseCamelotFilter *pFilter=NULL, UINT32 *Delay=NULL, GIFDisposalMethod *Restore=NULL, UINT32 *pLeftOffset=NULL, UINT32 *pTopOffset=NULL, BOOL *pLocalPalette=NULL) |
static UINT32 | GetGlobalWidth () |
static UINT32 | GetGlobalHeight () |
Protected Member Functions | |
BOOL | ProcessHeader () |
Static Protected Member Functions | |
static BOOL | ProcessExtension (CCLexFile *fd) |
static BOOL | ProcessImageBlock (CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, UINT32 *pLeftOffset=NULL, UINT32 *pTopOffset=NULL, BOOL *pLocalPalette=NULL) |
static BOOL | ReadColourMap (CCLexFile *fd, int number, LPRGBQUAD lpPalette) |
static int | GetDataBlock (CCLexFile *fd, unsigned char *buf) |
To read in a block of data from the specifed file. Reads a 1 byte count and then reads that many bytes in, as long as the count is non-zero. Any non-image calls must set ZeroDataBlock to False before calling this as otherwise it may just return zero. | |
static int | GetCode (CCLexFile *fd, int code_size, int flag) |
Returns the next code in the stream. | |
static int | LWZReadByte (CCLexFile *fd, int flag, int input_code_size) |
To read the next LZW byte from the stream. | |
static BOOL | ReadImage (CCLexFile *fd, LPBYTE pBitsData, int width, int height, int bpp, BOOL interlace, BaseCamelotFilter *pFilter=NULL) |
The read the bitmap data into the specified buffer. It decompresses the data from the specified file and then puts the pixel data into the buffer. Copes with interlaced GIFs. Assumes progress hourglass has been started with 100. | |
Private Attributes | |
Palette | m_GlobalPalette |
Static Private Attributes | |
static WORD | m_GlobalWidth = 0 |
static WORD | m_GlobalHeight = 0 |
static BOOL | Interlace = FALSE |
static int | Transparent = -1 |
static UINT32 | m_Delay = 0 |
static GIFDisposalMethod | m_Restore = GDM_LEAVE |
static int | m_nCurrentBitmap = 0 |
static BOOL | ZeroDataBlock = FALSE |
static LPRGBQUAD | lpGlobalPalette = NULL |
static int | GlobalPaletteSize = 0 |
static BOOL | m_bImageRead = FALSE |
static FilePos | m_NextImageStartPosition = 0 |
Definition at line 230 of file gifutil.h.
|
Returns the next code in the stream.
Definition at line 622 of file gifutil.cpp. 00623 { 00624 static unsigned char buf[280]; 00625 static int curbit; 00626 static int lastbit; 00627 static int done; 00628 static int last_byte; 00629 int i; 00630 int j; 00631 int ret; 00632 unsigned char count; 00633 00634 if (flag) 00635 { 00636 curbit = 0; 00637 lastbit = 0; 00638 done = FALSE; 00639 return 0; 00640 } 00641 00642 if ( (curbit+code_size) >= lastbit) 00643 { 00644 if (done) 00645 { 00646 if (curbit >= lastbit) 00647 { 00648 /* Oh well */ 00649 } 00650 return -1; 00651 } 00652 buf[0] = buf[last_byte-2]; 00653 buf[1] = buf[last_byte-1]; 00654 00655 if ((count = GetDataBlock(fd, &buf[2])) == 0) 00656 done = TRUE; 00657 00658 last_byte = 2 + count; 00659 curbit = (curbit - lastbit) + 16; 00660 lastbit = (2+count)*8 ; 00661 } 00662 00663 ret = 0; 00664 for (i = curbit, j = 0; j < code_size; ++i, ++j) 00665 ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; 00666 00667 curbit += code_size; 00668 00669 return ret; 00670 }
|
|
To read in a block of data from the specifed file. Reads a 1 byte count and then reads that many bytes in, as long as the count is non-zero. Any non-image calls must set ZeroDataBlock to False before calling this as otherwise it may just return zero.
Definition at line 578 of file gifutil.cpp. 00579 { 00580 unsigned char count; 00581 00582 // Added, as if we encounter the zero block then that is the end of this image 00583 // and we should never read any more info from that image. (added 14/8/95) 00584 if (ZeroDataBlock) 00585 return 0; 00586 00587 fd->read( &count, 1 ); 00588 00589 // If there is a count then read that many bytes in 00590 // If zero then this is a terminator so return that 00591 if (count == 0) 00592 { 00593 ZeroDataBlock = TRUE; 00594 // Fall through to return 0 00595 } 00596 else 00597 { 00598 ZeroDataBlock = FALSE; 00599 fd->read( buf, count ); 00600 // fall through to return the number of bytes found 00601 } 00602 00603 return count; 00604 }
|
|
Definition at line 251 of file gifutil.h. 00251 { return m_GlobalHeight; }
|
|
Definition at line 250 of file gifutil.h. 00250 { return m_GlobalWidth; }
|
|
To read the next LZW byte from the stream.
Definition at line 689 of file gifutil.cpp. 00690 { 00691 static int fresh = FALSE; 00692 int code; 00693 int incode; 00694 static int code_size; 00695 static int set_code_size; 00696 static int max_code; 00697 static int max_code_size; 00698 static int firstcode; 00699 static int oldcode; 00700 static int clear_code; 00701 static int end_code; 00702 static int table[2][(1<< MAX_LWZ_BITS)]; 00703 static int stack[(1<<(MAX_LWZ_BITS))*2]; 00704 static int *sp; 00705 int i; 00706 00707 if (flag) 00708 { 00709 set_code_size = input_code_size; 00710 code_size = set_code_size+1; 00711 clear_code = 1 << set_code_size ; 00712 end_code = clear_code + 1; 00713 max_code_size = 2*clear_code; 00714 max_code = clear_code+2; 00715 00716 GetCode(fd, 0, TRUE); 00717 00718 fresh = TRUE; 00719 00720 for (i = 0; i < clear_code; ++i) 00721 { 00722 table[0][i] = 0; 00723 table[1][i] = i; 00724 } 00725 for (; i < (1<<MAX_LWZ_BITS); ++i) 00726 table[0][i] = table[1][0] = 0; 00727 00728 sp = stack; 00729 00730 return 0; 00731 } 00732 else if (fresh) 00733 { 00734 fresh = FALSE; 00735 do 00736 { 00737 firstcode = oldcode = GetCode(fd, code_size, FALSE); 00738 } while (firstcode == clear_code); 00739 00740 return firstcode; 00741 } 00742 00743 if (sp > stack) 00744 return *--sp; 00745 00746 while ((code = GetCode(fd, code_size, FALSE)) >= 0) 00747 { 00748 if (code == clear_code) 00749 { 00750 for (i = 0; i < clear_code; ++i) 00751 { 00752 table[0][i] = 0; 00753 table[1][i] = i; 00754 } 00755 00756 for (; i < (1<<MAX_LWZ_BITS); ++i) 00757 table[0][i] = table[1][i] = 0; 00758 00759 code_size = set_code_size+1; 00760 max_code_size = 2*clear_code; 00761 max_code = clear_code+2; 00762 sp = stack; 00763 firstcode = oldcode = GetCode(fd, code_size, FALSE); 00764 00765 return firstcode; 00766 } 00767 else if (code == end_code) 00768 { 00769 int count; 00770 unsigned char buf[260]; 00771 00772 if (ZeroDataBlock) 00773 return -2; 00774 00775 while ((count = GetDataBlock(fd, buf)) > 0) 00776 ; 00777 00778 if (count != 0) 00779 return -2; 00780 } 00781 00782 incode = code; 00783 00784 if (code >= max_code) 00785 { 00786 *sp++ = firstcode; 00787 code = oldcode; 00788 } 00789 00790 while (code >= clear_code) 00791 { 00792 *sp++ = table[1][code]; 00793 if (code == table[0][code]) 00794 { 00795 /* Oh well */ 00796 } 00797 code = table[0][code]; 00798 } 00799 00800 *sp++ = firstcode = table[1][code]; 00801 00802 if ((code = max_code) <(1<<MAX_LWZ_BITS)) 00803 { 00804 table[0][code] = oldcode; 00805 table[1][code] = firstcode; 00806 ++max_code; 00807 if ((max_code >= max_code_size) && (max_code_size < (1<<MAX_LWZ_BITS))) 00808 { 00809 max_code_size *= 2; 00810 ++code_size; 00811 } 00812 } 00813 00814 oldcode = incode; 00815 00816 if (sp > stack) 00817 return *--sp; 00818 } 00819 return code; 00820 }
|
|
Definition at line 443 of file gifutil.cpp. 00444 { 00445 static char buf[256]; 00446 00447 // Get the type of this extension and then process it 00448 unsigned char ExtensionType; 00449 fd->read( &ExtensionType, 1 ); 00450 00451 switch (ExtensionType) 00452 { 00453 case TRANSPARENTBLOCK: 00454 { 00455 // The next image in the file might need to start here to get transparency 00456 // information. So remember the position 00457 m_NextImageStartPosition = fd->tellIn() - 2; 00458 00459 // Graphic Control Extension 00460 // We have read in the identfier and the type of extension block so we 00461 // really need to read the data from that point onwards 00462 GIFTRANSBLOCK TransBlock; 00463 00464 // This is really sizeof(GIFTRANSBLOCK) but this returns 14 instead of 13 00465 // as it rounds to the nearest word boundary 00466 const size_t TransBlockSize = sizeof(WORD) * 1 + sizeof(BYTE) * 6; 00467 fd->read( &(TransBlock.gtbBlockSize), TransBlockSize - 2); 00468 00469 // Contains lots of random rubbish we are not interested in. 00470 // Just skip to the crux of the matter and read in the transparency colour, 00471 // if the transparency flag is set. 00472 00473 if (!m_bImageRead) 00474 { 00475 BOOL fTrans = TransBlock.gtbFlags & 0x1; 00476 if (fTrans != 0) 00477 Transparent = TransBlock.gtbTransparency; 00478 else 00479 { 00480 Transparent = -1; // no transparency 00481 } 00482 00483 TRACEUSER("Neville", _T("ProcessExtension - transparent fTrans = %d Transparent = %d\n"), fTrans, Transparent ); 00484 00485 // Animation Restore\Delay values. 00486 m_Delay = TransBlock.gtbDelay; 00487 m_Restore = GIFDisposalMethod((TransBlock.gtbFlags >> 2) & 0x03); 00488 } 00489 00490 return TRUE; 00491 } 00492 00493 case PLAINTEXTBLOCK: 00494 { 00495 // We need to bin any transparency information we have since 00496 // "The scope of this [Graphic Control (TRANSPARENTBLOCK)] Extension is the 00497 // graphic rendering block that follows it" 00498 00499 if (m_bImageRead) 00500 { 00501 // We've read the image but don't need to start with any TRANSPARENT block 00502 // that might have been read after the image, so make sure we don't 00503 m_NextImageStartPosition = 0; 00504 } 00505 else 00506 { 00507 // We haven't read any image yet so just make sure no transparency 00508 Transparent = -1; 00509 } 00510 // ...and drop through 00511 } 00512 00513 default: 00514 break; 00515 } 00516 00517 // Must set this as otherwise, if this is after we have loaded an image then we have 00518 // the possibility that the zero block has been encountered and GetDataBlock will 00519 // always return 0, so force it not to. 00520 ZeroDataBlock = FALSE; 00521 00522 // If not recognised then read the rest of that extension 00523 while (GetDataBlock(fd, (unsigned char*) buf) != 0) 00524 ; 00525 00526 return FALSE; 00527 }
|
|
Definition at line 1128 of file gifutil.cpp. 01129 { 01130 ERROR3("GIFUtil::ProcessHeader : not implemented"); 01131 if (TRUE) return FALSE; 01132 01133 CCLexFile* File; 01134 GIFINFOHEADER Header; 01135 // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13 01136 // as it rounds to the nearest word boundary 01137 const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3; 01138 // const size_t HeaderSize = (sizeof(GIFINFOHEADER)* sizeof(WORD)) / sizeof(WORD); 01139 01140 File->read( &Header, HeaderSize ); 01141 if (File->bad()) 01142 File->GotError( _R(IDE_FORMATNOTSUPPORTED) ); 01143 01144 // Just double check that the signature is correct, if not then fail immediately 01145 if ( 01146 ( strncmp( Header.giName, "GIF89a", 6 ) != 0 ) && 01147 ( strncmp( Header.giName, "GIF87a", 6 ) != 0 ) 01148 ) 01149 File->GotError( _R(IDE_BADFORMAT) ); 01150 01151 // Note the overall size of the GIF from the header, may be the animation size 01152 m_GlobalWidth = Header.giWidth; 01153 m_GlobalHeight = Header.giHeight; 01154 // int ColorResolution = (((Header.giFlags >> 4) & 0x07) + 1); 01155 // int AspectRatio = Header.giAspect; 01156 01157 UINT32 nGlobalPaletteSize = 2 << (Header.giFlags & 0x07); 01158 // m_nBackground = Header.giBackground; 01159 01160 // Check if we have a global colour map present or not, if so then read it in. 01161 if (BitSet(Header.giFlags, GLOBALCOLOURMAP)) 01162 { 01163 // Read in the global colour map into a palette structure for possible later use 01164 if (m_GlobalPalette.SetSize(nGlobalPaletteSize) == FALSE) 01165 { 01166 ERROR3("GIFUtil::ProcessHeader() - can't renew palette"); 01167 return FALSE; 01168 } 01169 ::ReadColourMap(File, m_GlobalPalette); 01170 } 01171 m_nCurrentBitmap = 0; 01172 }
|
|
Definition at line 1190 of file gifutil.cpp. 01192 { 01193 GIFIMAGEBLOCK ImageBlock; 01194 // This is really sizeof(GIFIMAGEBLOCK) but this returns 10 instead of 9 as it rounds to the nearest word boundary 01195 const size_t ImageHeaderSize = sizeof(WORD) * 4 + sizeof(BYTE) * 1; 01196 File->read( &ImageBlock, ImageHeaderSize ); 01197 01198 // Check whether we there is a local colour map or not 01199 // If there is use that otherwise use the global one read in earlier 01200 BOOL UseLocalColourMap = BitSet(ImageBlock.gibFlags, LOCALCOLOURMAP); 01201 int LocalColourMapSize = 1 << ((ImageBlock.gibFlags & 0x07) + 1); 01202 01203 int Width = ImageBlock.gibWidth; //LM_to_uint(buf[4],buf[5]); 01204 int Height = ImageBlock.gibDepth; //LM_to_uint(buf[6],buf[7]); 01205 01206 // If the user asked for them and they are within the animation's boundaries 01207 // Then return the offsets to the user 01208 if (pLeftOffset && ImageBlock.gibLeft < m_GlobalWidth) 01209 *pLeftOffset = ImageBlock.gibLeft; 01210 if (pTopOffset && ImageBlock.gibTop < m_GlobalHeight) 01211 *pTopOffset = ImageBlock.gibTop; 01212 if (pLocalPalette) 01213 *pLocalPalette = UseLocalColourMap; 01214 01215 Interlace = BitSet(ImageBlock.gibFlags, INTERLACE); 01216 01217 int ColoursInPalette = UseLocalColourMap ? LocalColourMapSize : GlobalPaletteSize; 01218 int BitsPerPixel; 01219 if (ColoursInPalette > 16) 01220 BitsPerPixel = 8; 01221 else if (ColoursInPalette > 2) 01222 BitsPerPixel = 4; 01223 else 01224 BitsPerPixel = 1; 01225 01226 TRACEUSER("Neville", _T("Colours in palette = %d bpp = %d\n"), ColoursInPalette, BitsPerPixel ); 01227 01228 // Allocate the space that we require for this bitmap 01229 // Sanity checks on the file that we have been asked to load. 01230 if ((BitsPerPixel != 8) && (BitsPerPixel != 4) && (BitsPerPixel != 1) && (Width != 0) && (Height != 0)) 01231 File->GotError( _R(IDE_FORMATNOTSUPPORTED) ); 01232 01233 // we know what sort of bitmap we are - lets allocate a new LPBITMAPINFO and some bytes 01234 *Info = AllocDIB( Width, Height, BitsPerPixel, Bits, NULL ); 01235 01236 if (*Info == NULL || *Bits == NULL) 01237 File->GotError( _R(IDS_OUT_OF_MEMORY) ); 01238 01239 // if the clrUsed field is zero, put a sensible value in it 01240 01241 BOOL ok = FALSE; 01242 if (UseLocalColourMap) 01243 { 01244 // There is a local colour table specified so read this directly into 01245 // the palette of the DIB 01246 if (LocalColourMapSize > (1 << BitsPerPixel)) 01247 File->GotError( _R(IDE_BADFORMAT) ); 01248 01249 ReadColourMap(File, LocalColourMapSize, (*Info)->bmiColors); 01250 } 01251 else 01252 { 01253 // No local palette so copy the global palette into the palette of the DIB, if 01254 if (lpGlobalPalette && ((*Info)->bmiColors)) 01255 { 01256 const size_t TotalPal = sizeof(RGBQUAD) * GlobalPaletteSize; 01257 memcpy((*Info)->bmiColors, lpGlobalPalette, TotalPal); 01258 } 01259 } 01260 01261 // Note how many colours are in the palette 01262 (*Info)->bmiHeader.biClrUsed = ColoursInPalette; 01263 01264 ok = ReadImage(File, *Bits, Width, Height, BitsPerPixel, Interlace); 01265 // Now read all that lovely data in 01266 if (!ok) 01267 File->GotError( _R(IDE_BADFORMAT) ); 01268 01269 return TRUE; 01270 }
|
|
Definition at line 543 of file gifutil.cpp. 00544 { 00545 GIFRGBTRIPLE rgb; 00546 for (int i = 0; i < number; ++i) 00547 { 00548 fd->read( &rgb, sizeof(GIFRGBTRIPLE) ); 00549 lpPalette->rgbBlue = rgb.grgbtBlue; 00550 lpPalette->rgbGreen = rgb.grgbtGreen; 00551 lpPalette->rgbRed = rgb.grgbtRed; 00552 lpPalette->rgbReserved = 0; 00553 lpPalette++; 00554 } 00555 00556 return TRUE; 00557 }
|
|
static BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, int *TransColour, int& nBitmapToRead, String_64 *ProgressString = NULL, BaseCamelotFilter *pFilter = NULL, UINT32* Delay=NULL, GIFDisposalMethod *Restore=NULL, UINT32 * pLeftOffset = NULL, UINT32 * pTopOffset = NULL, BOOL * pLocalPalette = NULL) Author: - Created: - Inputs/Outputs Refer to the above Function Header for a full explanation. Definition at line 162 of file gifutil.cpp. 00167 { 00168 if ((nBitmapToRead > 1 && nBitmapToRead == m_nCurrentBitmap) || nBitmapToRead < 1) 00169 { 00170 ERROR3("GIFUtil::ReadFromFile() - can't read that bitmap"); 00171 return FALSE; 00172 } 00173 00174 *Info = NULL; // in case of early exit 00175 *Bits = NULL; 00176 Transparent = -1; 00177 *TransColour = -1; // in case of early exit set to none 00178 int Background = 0; // background colour number !!! not used !!! 00179 Interlace = FALSE; // set interlace to false by default 00180 00181 // Must set the exception throwing flag to True and force reporting of errors to False. 00182 // This means that the caller must report an error if the function returns False. 00183 // Any calls to CCLexFile::GotError will now throw a file exception and should fall into 00184 // the catch handler at the end of the function. 00185 BOOL OldThrowingState = File->SetThrowExceptions( TRUE ); 00186 BOOL OldReportingState = File->SetReportErrors( FALSE ); 00187 00188 // If the caller has specified a string then assume they require a progress bar 00189 // Start it up. 00190 if (ProgressString != NULL) 00191 BeginSlowJob(100, FALSE, ProgressString); 00192 00193 try 00194 { 00195 // If we want the first bitmap we'll assume we're at the start of the file & read the header 00196 if (nBitmapToRead == 1) 00197 { 00198 // place to store the global palette, if present, for later use 00199 lpGlobalPalette = NULL; // pointer to temporary palette store 00200 GlobalPaletteSize = 0; // size of the global palette found 00201 00202 GIFINFOHEADER Header; 00203 // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13 00204 // as it rounds to the nearest word boundary 00205 const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3; 00206 00207 File->read( &Header, HeaderSize ); 00208 if (File->bad()) 00209 File->GotError( _R(IDE_FORMATNOTSUPPORTED) ); 00210 00211 // Just double check that the signature is correct, if not then fail immediately 00212 if ( 00213 (strncmp(Header.giName, "GIF89a", 6) != 0) && 00214 (strncmp(Header.giName, "GIF87a", 6) != 0) 00215 ) 00216 File->GotError( _R(IDE_BADFORMAT) ); 00217 00218 // Note the overall size of the GIF from the header, may be the animation size 00219 m_GlobalWidth = Header.giWidth; 00220 m_GlobalHeight = Header.giHeight; 00221 // flags word consists of:- 00222 // - bit 7 colour table flag = set if global colour table follows 00223 // - bits 6-4 colour resolution = bpps - 1 00224 // - bit 3 sort flag = set global colour table sorted 00225 // - bits 3-0 size of global colour table = size is 2^(value+1) 00226 int ColorResolution = (((Header.giFlags >> 4) & 0x07) + 1); 00227 GlobalPaletteSize = 2 << (Header.giFlags & 0x07); 00228 Background = Header.giBackground; 00229 // int AspectRatio = Header.giAspect; 00230 00231 TRACEUSER("Neville",_T("Gif Global Width = %d Height = %d\n"), m_GlobalWidth, m_GlobalHeight); 00232 TRACEUSER("Neville",_T("Gif ColorResolution = %d\n"), ColorResolution); 00233 00234 // Check if we have a global colour map present or not, if so then read it in. 00235 if (BitSet(Header.giFlags, GLOBALCOLOURMAP)) 00236 { 00237 TRACEUSER("Neville",_T("Gif read global colour table size = %d\n"), GlobalPaletteSize); 00238 // Read in the global colour map into a palette structure for possible later use 00239 const size_t TotalPal = sizeof(RGBQUAD) * GlobalPaletteSize; 00240 lpGlobalPalette = (LPRGBQUAD)CCMalloc( TotalPal ); 00241 if (lpGlobalPalette==NULL) 00242 return FALSE; 00243 00244 ReadColourMap(File, GlobalPaletteSize, lpGlobalPalette); 00245 } 00246 m_nCurrentBitmap = 0; 00247 m_NextImageStartPosition = 0; 00248 } 00249 00250 // We now need to go through and process the data in this file which 00251 // should now consist off GIF blocks until we hit the end of file or 00252 // we have processed the lot. 00253 BOOL FileProcessed = FALSE; 00254 00255 m_bImageRead = FALSE; 00256 unsigned char c; 00257 // Set up bad values so that the DIB alloc claim will fail if there 00258 // has been no GIFIMAGEBLOCK found 00259 // int Width = 0; // Width of bitmap 00260 // int Height = 0; // Height of bitmap 00261 // int BitsPerPixel = 0; //ColorResolution; // Colour depth required 00262 00263 if (m_NextImageStartPosition != 0) 00264 { 00265 File->seekIn(m_NextImageStartPosition, ios::beg); 00266 m_NextImageStartPosition = 0; 00267 } 00268 00269 while (!File->eof() && !File->bad() && !FileProcessed) 00270 { 00271 // Get the next character in the stream and see what it indicates 00272 // comes next in the file 00273 // Use Get as this will read the EOF character (255) and exit via the 00274 // File->eof() test rather than Read which will throw an exception. 00275 //File->read( &c, 1 ); 00276 File->get( (char&)c ); 00277 00278 switch (c) 00279 { 00280 case ';': 00281 { 00282 // GIF terminator 00283 // Cannot assume that the terminator immediately follows the image data 00284 // Might have some extensions following the image data. 00285 FileProcessed = TRUE; 00286 nBitmapToRead = -1; 00287 break; 00288 } 00289 00290 case '!': //EXTENSIONBLOCK: 00291 { 00292 // Extension 00293 ProcessExtension(File); 00294 break; 00295 } 00296 00297 case ',': 00298 { 00299 // start of image character 00300 if (m_bImageRead) // another bitmap - save it for the next call to ReadFromFile() 00301 { 00302 if (m_NextImageStartPosition == 0) 00303 { 00304 // No transparency info for the next one so start here 00305 m_NextImageStartPosition = File->tellIn() - 1; 00306 } 00307 ++nBitmapToRead; 00308 FileProcessed = TRUE; 00309 break; 00310 } 00311 00312 UINT32 LeftOffset = 0; 00313 UINT32 TopOffset = 0; 00314 BOOL LocalPalette = FALSE; 00315 00316 // Should be followed by a GIFIMAGE BLOCK 00317 ProcessImageBlock(File, Info, Bits, &LeftOffset, &TopOffset, &LocalPalette); 00318 ++m_nCurrentBitmap; 00319 00320 if (nBitmapToRead == m_nCurrentBitmap) 00321 { 00322 m_bImageRead = TRUE; 00323 } 00324 00325 // return the values back to the caller if it desired them 00326 if (pLeftOffset) 00327 *pLeftOffset = LeftOffset; 00328 if (pTopOffset) 00329 *pTopOffset = TopOffset; 00330 if (pLocalPalette) 00331 *pLocalPalette = LocalPalette; 00332 break; 00333 } 00334 00335 default: 00336 // We have found something other than what we are expecting 00337 // so fail with an error 00338 //File->GotError( IDE_BADFORMAT ); 00339 // Cannot do this as some files have random bits 00340 // e.g. galileo.gif has a random zero before the ; 00341 // colsec.gif has a rampant > at the end instead of ; 00342 if (m_bImageRead) 00343 { 00344 // We've already got something so ignore anything else in case it goes 00345 // completely wrong. 00346 FileProcessed = TRUE; 00347 nBitmapToRead = -1; 00348 } 00349 TRACE( _T("Unrecognized Character %x at %d\n"), (int)c, File->tellIn()); 00350 00351 break; 00352 } 00353 } 00354 00355 // If we reach here and the bitmap allocations are still null then no valid image 00356 // was found and so we should error now. 00357 // Might have just been a GIF file with extension tags in and no images! 00358 if (*Info == NULL || *Bits == NULL) 00359 File->GotError( _R(IDE_BADFORMAT) ); 00360 00361 // We read the desired bitmap but the EOF came along before we could try anything else 00362 // Signal this is the last bitmap 00363 if (m_bImageRead && File->eof()) 00364 { 00365 TRACE( _T("GIF: Premature end of file") ); 00366 nBitmapToRead = -1; 00367 } 00368 00369 // Return the transparency/delay/restore found to the caller. 00370 *TransColour = Transparent; 00371 if (Delay) 00372 { 00373 *Delay = m_Delay; 00374 } 00375 if (Restore) 00376 { 00377 *Restore = m_Restore; 00378 } 00379 00380 // Free up the bit of memory for a palette we grabbed, if present & no more images to read 00381 if (lpGlobalPalette && nBitmapToRead == -1) 00382 { 00383 CCFree(lpGlobalPalette); 00384 lpGlobalPalette = NULL; 00385 } 00386 00387 // If started, then stop then progress bar 00388 if (ProgressString != NULL) 00389 EndSlowJob(); 00390 00391 // Must set the exception throwing and reporting flags back to their entry states 00392 File->SetThrowExceptions( OldThrowingState ); 00393 File->SetReportErrors( OldReportingState ); 00394 00395 // er, we seem to have finished OK so say so 00396 return TRUE; 00397 } 00398 catch( CFileException e ) 00399 { 00400 // catch our form of a file exception 00401 TRACE( _T("GIFUtil::ReadFromFile CC catch handler\n") ); 00402 00403 FreeDIB( *Info, *Bits ); // free any alloced memory 00404 *Info = NULL; // and NULL the pointers 00405 *Bits = NULL; 00406 00407 // Free up the bit of memory for a palette we grabbed, if present 00408 if (lpGlobalPalette) 00409 { 00410 CCFree(lpGlobalPalette); 00411 lpGlobalPalette = NULL; 00412 } 00413 00414 // If started, then stop then progress bar 00415 if (ProgressString != NULL) 00416 EndSlowJob(); 00417 00418 // Must set the exception throwing and reporting flags back to their entry states 00419 File->SetThrowExceptions( OldThrowingState ); 00420 File->SetReportErrors( OldReportingState ); 00421 00422 return FALSE; 00423 } 00424 00425 ERROR2( FALSE, "Escaped exception clause somehow" ); 00426 }
|
|
Default constructor for the class. Default destructor for the class. Reads a .gif file into memory decompressing it as it goes. Errors on 16-bit builds*** A progress hourglass can be shown if required.
Definition at line 139 of file gifutil.cpp. 00142 { 00143 int nBitmap = 1; 00144 00145 return (ReadFromFile( File, Info, Bits, TransColour, nBitmap, ProgressString, pFilter)); 00146 }
|
|
The read the bitmap data into the specified buffer. It decompresses the data from the specified file and then puts the pixel data into the buffer. Copes with interlaced GIFs. Assumes progress hourglass has been started with 100.
Definition at line 848 of file gifutil.cpp. 00850 { 00851 ERROR2IF(pBitsData == NULL, FALSE, "GIFUtil::ReadImage given null pointer to bits data"); 00852 ERROR2IF(bpp != 8 && bpp != 4 && bpp != 1, FALSE, "GIFUtil::ReadImage - bpp invalid"); 00853 00854 unsigned char c; 00855 int v = 0; 00856 int xpos = 0; 00857 int ypos = 0; 00858 int pass = 0; 00859 int yposcount = 0; 00860 00861 ZeroDataBlock = FALSE; 00862 00863 // Work out how often we need to update the progress bar 00864 int UpdateEvery = 1; 00865 INT32 UpdateValue = 1; 00866 if (pFilter == NULL) 00867 UpdateEvery = height/100 + 1; 00868 else 00869 { 00870 // Ask the filter what the record size for this bitmap is and hence 00871 // what the allocation we have for progress bar updates are. 00872 // We will then have to update our progress bar by 00873 // current scanline/total number of scanlines * allocation 00874 // so that we get update by a proportion of the value. 00875 // We can assume no interlacing as in native/web files this is turned off. 00876 INT32 RecordSize = pFilter->GetCurrentRecordSize(); 00877 if (RecordSize == 0) 00878 RecordSize = 1; 00879 UpdateValue = RecordSize/height; 00880 UpdateEvery = 0; // So it updates every time round the loop 00881 } 00882 00883 int LastProgressUpdate = 0; 00884 00885 // Work out the word/byte rounded line width rather than the pixel width 00886 INT32 WidthOfLine = DIBUtil::ScanlineSize( width, bpp ); 00887 00888 // Initialize the Compression routines 00889 fd->read( &c, 1 ); 00890 ERROR3IF(c > GIFBITS,"Bad code size in GIFUtil ReadImage"); 00891 00892 if (LWZReadByte(fd, TRUE, c) < 0) 00893 { 00894 return FALSE; 00895 } 00896 00897 while ((v = LWZReadByte(fd, FALSE, c)) >= 0 ) 00898 { 00899 //GIFSetPixel(pBitsData, xpos, ypos, v); 00900 // Check that the specified pixel is within the bounds specified and that we 00901 // have a buffer to write to 00902 00903 // if ( !(((ypos < 0) || (ypos >= height)) || ((xpos < 0) || (xpos >= width))) && pBitsData ) 00904 // { 00905 // Our DIBs are the wrong way up so we must output the data from the last 00906 // line of the image and go up to the start 00907 // -1 as height = 1 .. Height whereas y goes from 0 .. Height - 1 00908 // Use the word/byte rounded line width rather than the pixel width 00909 if (bpp == 8) 00910 { 00911 // If 8 bpp then just use the whole byte straight 00912 LPBYTE pData = pBitsData + xpos + ((height - 1 - ypos) * WidthOfLine); 00913 *(pData) = v; 00914 } 00915 else if (bpp == 4) 00916 { 00917 // 4bpp so we must put the data into either the high or low nibble. 00918 // This will be dependent on whether we are on an odd or even pixel. 00919 // So test the LSBit of the curx, if set we will be odd. 00920 // Only move onto next byte every other pixel hence curx/2. 00921 LPBYTE pData = pBitsData + xpos/2 + ((height - 1 - ypos) * WidthOfLine); 00922 // Get whole present byte 00923 if (xpos & 1) 00924 *(pData) = ((*(pData)) & 0xF0) | (v & 0x0F); // add into low nibble 00925 else 00926 *(pData) = ((*(pData)) & 0x0F) | ((v << 4) & 0xF0); // add into top nibble 00927 } 00928 else if (bpp == 1) 00929 { 00930 // 1bpp so we must put the data into either the high or low nibble. 00931 // This will be dependent on whether we are on an odd or even pixel. 00932 // So test the LSBit of the curx, if set we will be odd. 00933 // Only move onto next byte every other pixel hence curx/2. 00934 LPBYTE pOutputBitmap = pBitsData + (xpos / 8) + ((height - 1 - ypos) * WidthOfLine); 00935 // Get whole present byte 00936 UINT32 BitPosition = 7 - (xpos % 8); 00937 BYTE SetBit = v << BitPosition; 00938 BYTE Mask = ~(1 << BitPosition); 00939 00940 *pOutputBitmap = ((*pOutputBitmap) & Mask) | SetBit; 00941 } 00942 else 00943 { 00944 ERROR3IF(TRUE, "GIFUtil::ReadImage() - Invalid bpp"); 00945 // bad bpp but should not get here so do nothing 00946 } 00947 00948 // } 00949 00950 ++xpos; 00951 00952 BOOL JobState = TRUE; 00953 // if we have reached the end of the current line then work out the next 00954 // line that we must do, if interlacing is on 00955 if (xpos >= width) 00956 { 00957 xpos = 0; 00958 00959 // Do different filing methods depending on whether interlaced on non-interlaced. 00960 if (interlace) 00961 { 00962 // We are interlaced so learn not to count properly! 00963 switch (pass) 00964 { 00965 case 0: 00966 case 1: 00967 ypos += 8; break; 00968 case 2: 00969 ypos += 4; break; 00970 case 3: 00971 ypos += 2; break; 00972 } 00973 00974 while (ypos >= height && pass <= 3) 00975 { 00976 ++pass; 00977 switch (pass) 00978 { 00979 case 1: 00980 ypos = 4; 00981 break; 00982 case 2: 00983 ypos = 2; 00984 break; 00985 case 3: 00986 ypos = 1; 00987 break; 00988 default: 00989 goto finish; 00990 } 00991 } 00992 } 00993 else 00994 { 00995 // Non-interlaced case 00996 ++ypos; 00997 } 00998 00999 yposcount++; 01000 01001 if (yposcount > (LastProgressUpdate + UpdateEvery)) 01002 { 01003 // Note the update point so that we know the next one 01004 LastProgressUpdate = yposcount; 01005 01006 // Now update the progress display, started with 100 01007 if (pFilter == NULL) 01008 JobState = ContinueSlowJob( (long)(100 * yposcount/height) ); 01009 else 01010 JobState = pFilter->IncProgressBarCount(UpdateValue); 01011 01012 // If JobState is False then the user has probably pressed escape and we should 01013 // immediately stop what we are doing. 01014 if (!JobState) 01015 { 01016 fd->GotError( _R(IDW_CANCELLEDBMPIMPORT) ); // Expects error set on cancel 01017 return FALSE; 01018 } 01019 } 01020 } 01021 01022 if (ypos >= height) 01023 break; 01024 } 01025 01026 finish: 01027 if (LWZReadByte(fd, FALSE, c) >= 0) 01028 { 01029 /* Ignore extra */ 01030 } 01031 01032 // Everything seemed to go ok 01033 return TRUE; 01034 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|