GIFUtil Class Reference

Contains functions to read in a GIF file as a DIB. More...

#include <gifutil.h>

List of all members.

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


Detailed Description

Contains functions to read in a GIF file as a DIB.

Author:
Neville Humphrys
Date:
24/4/95
See also:
OutputGIF;

Definition at line 230 of file gifutil.h.


Member Function Documentation

int GIFUtil::GetCode CCLexFile fd,
int  code_size,
int  flag
[static, protected]
 

Returns the next code in the stream.

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS] code_size flag
- [OUTPUTS]
Returns:
The code found.
See also:

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 }

int GIFUtil::GetDataBlock CCLexFile fd,
unsigned char *  buf
[static, protected]
 

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.

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS]
- [OUTPUTS]
Returns:
Number of bytes read
See also:

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 }

static UINT32 GIFUtil::GetGlobalHeight  )  [inline, static]
 

Definition at line 251 of file gifutil.h.

00251 { return m_GlobalHeight; }

static UINT32 GIFUtil::GetGlobalWidth  )  [inline, static]
 

Definition at line 250 of file gifutil.h.

00250 { return m_GlobalWidth; }

int GIFUtil::LWZReadByte CCLexFile fd,
int  flag,
int  input_code_size
[static, protected]
 

To read the next LZW byte from the stream.

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS] flag input_code_size
- [OUTPUTS]
Returns:
The next LZW byte in the stream.
See also:

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 }

BOOL GIFUtil::ProcessExtension CCLexFile fd  )  [static, protected]
 

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS]
- [OUTPUTS]
Returns:
True if worked ok, False otherwise.
See also:

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 }

BOOL GIFUtil::ProcessHeader  )  [protected]
 

Author:
Colin
Date:
11/06/96
Parameters:
[INPUTS] 
[OUTPUTS] 
Returns:
See also:

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 }

BOOL GIFUtil::ProcessImageBlock CCLexFile File,
LPBITMAPINFO Info,
LPBYTE Bits,
UINT32 pLeftOffset = NULL,
UINT32 pTopOffset = NULL,
BOOL *  pLocalPalette = NULL
[static, protected]
 

Author:
Colin
Date:
11/06/96
Parameters:
[INPUTS] 
[OUTPUTS] 
Returns:
See also:

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 }

BOOL GIFUtil::ReadColourMap CCLexFile fd,
int  number,
LPRGBQUAD  lpPalette
[static, protected]
 

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS]
- [OUTPUTS]
Returns:
True if worked ok, False otherwise.
See also:

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 }

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
[static]
 

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 }

BOOL GIFUtil::ReadFromFile CCLexFile File,
LPBITMAPINFO Info,
LPBYTE Bits,
int *  TransColour,
String_64 ProgressString = NULL,
BaseCamelotFilter pFilter = NULL
[static]
 

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.

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
File A opened CCLexFile that can be read from. It should be positioned at the [INPUTS] start. Caller is responsible for closing it. The file needs to be in Binary mode. nBitmapToRead The number of the bitmap in the GIF that you wish to read. If 1 then the GIF will be read from the beginning obtaining the header information. For any number other than 1 it should be noted that bitmaps can only be read in an incremental sequence and that the first one must have been read prior to any call with a non-1 value. ProgressString allows the user to specify whether they require a progress hourglass or not. If NULL then none is shown, otherwise an progress bar is shown using the text supplied. Defaults to NULL i.e. no progress bar. 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.
Info points to a new LPBITMAPINFO struct and Bits points to the bytes. [OUTPUTS] These can be freed up with FreeDIB. TransColour is either -1 == none or equal to the transparency colour found nBitmapToRead Returns the number of the next bitmap that can be read from the GIF or -1 if no further bitmaps exist.
Returns:
TRUE if worked, FALSE if failed (error will be set accordingly but not reported)

Errors: Calls SetError on FALSE returns. Scope: Static, Public

See also:
DIBUtil::ReadFromFile; AccusoftFilters::ReadFromFile;

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 }

BOOL GIFUtil::ReadImage CCLexFile fd,
LPBYTE  pBitsData,
int  width,
int  height,
int  bpp,
BOOL  interlace,
BaseCamelotFilter pFilter = NULL
[static, protected]
 

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.

Author:
Neville Humphrys
Date:
29/6/95
Parameters:
fd pointer to a CCLexFile to read the data from [INPUTS] pBitsData pointer to the place to put the bitmap data, should have been claimed so that it is the correct size to contain it. width width of the bitmap in pixels height height of the bitmap in pixels bpp colour depth of the bitmap in bits per pixel interlace flag to say if this data is interlaced or not. 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.
See also:
GIFUtil::ReadFromFile;

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 }


Member Data Documentation

int GIFUtil::GlobalPaletteSize = 0 [static, private]
 

Definition at line 292 of file gifutil.h.

BOOL GIFUtil::Interlace = FALSE [static, private]
 

Definition at line 274 of file gifutil.h.

LPRGBQUAD GIFUtil::lpGlobalPalette = NULL [static, private]
 

Definition at line 291 of file gifutil.h.

BOOL GIFUtil::m_bImageRead = FALSE [static, private]
 

Definition at line 294 of file gifutil.h.

UINT32 GIFUtil::m_Delay = 0 [static, private]
 

Definition at line 276 of file gifutil.h.

WORD GIFUtil::m_GlobalHeight = 0 [static, private]
 

Definition at line 272 of file gifutil.h.

Palette GIFUtil::m_GlobalPalette [private]
 

Definition at line 288 of file gifutil.h.

WORD GIFUtil::m_GlobalWidth = 0 [static, private]
 

Definition at line 271 of file gifutil.h.

int GIFUtil::m_nCurrentBitmap = 0 [static, private]
 

Definition at line 279 of file gifutil.h.

FilePos GIFUtil::m_NextImageStartPosition = 0 [static, private]
 

Definition at line 296 of file gifutil.h.

GIFDisposalMethod GIFUtil::m_Restore = GDM_LEAVE [static, private]
 

Definition at line 277 of file gifutil.h.

int GIFUtil::Transparent = -1 [static, private]
 

Definition at line 275 of file gifutil.h.

BOOL GIFUtil::ZeroDataBlock = FALSE [static, private]
 

Definition at line 286 of file gifutil.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:54:51 2007 for Camelot by  doxygen 1.4.4