#define __GIFDECODER_C__
/******************************************************************************
* FileName: GifDecoder.c
* Dependencies: Image decoding library; project requires File System library
* Processor: PIC24/dsPIC30/dsPIC33/PIC32MX
* Compiler: C30 v2.01/C32 v0.00.18
* Company: Microchip Technology, Inc.
* Software License Agreement
*
* Copyright © 2008 Microchip Technology Inc. All rights reserved.
* Microchip licenses to you the right to use, modify, copy and distribute
* Software only when embedded on a Microchip microcontroller or digital
* signal controller, which is integrated into your product or third party
* product (pursuant to the sublicense terms in the accompanying license
* agreement).
*
* You should refer to the license agreement accompanying this Software
* for additional information regarding your rights and obligations.
*
* SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
* OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
* PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
* OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION,
* BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
* DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
* INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
* COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY
* CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
* OR OTHER SIMILAR COSTS.
Author Date Comments
--------------------------------------------------------------------------------
Pradeep Budagutta 03-Mar-2008 First release
*******************************************************************************/
#include "Image Decoders\ImageDecoder.h"
#ifdef IMG_SUPPORT_GIF
/*************************/
/**** DATA STRUCTURES ****/
/*************************/
typedef struct _GIFDECODER
{
IMG_FILE *pImageFile; /* Image file pointer */
WORD wImageWidth;
WORD wImageHeight;
WORD wImageX;
WORD wImageY;
WORD wScreenWidth;
WORD wScreenHeight;
WORD wGlobalPaletteEntries;
WORD wLocalPaletteEntries;
BYTE bBgColorIndex;
BYTE bPixelAspectRatio;
BYTE blGifMarkerFlag : 1;
BYTE blGloabalColorTableFlag : 1;
BYTE blLocalColorTableFlag : 1;
BYTE blInterlacedFlag : 1;
BYTE blFirstcodeFlag : 1;
BYTE bInterlacePass : 3;
#if GIF_USE_16_BITS_PER_PIXEL == 0
BYTE aPalette[256][3]; /* Each palette entry has RGB */
#else
WORD awPalette[256]; /* Each palette entry has RGB */
#endif
/* For decoding */
BYTE abSymbol[4096];
#if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0
WORD awPrevSymbolPtr[4096];
#else
WORD awPrevSymbolPtr[(4096 * 3)/4];
#endif
WORD wInitialSymbols;
WORD wMaxSymbol;
BYTE bInitialSymbolBits;
BYTE bMaxSymbolBits;
LONG lGlobalColorTablePos;
/* Work memory */
BYTE bWorkBits;
BYTE bRemainingDataInBlock;
BYTE bRemainingBits;
WORD wCurrentX;
WORD wCurrentY;
} GIFDECODER;
/**************************/
/****** LOOKUP TABLE ******/
/**************************/
static const WORD GIF_awMask[] = { 0x000, 0x001, 0x003, 0x007, 0x00F, 0x01F, 0x03F, 0x07F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0xFFF };
/**************************/
/******* FUNCTIONS *******/
/**************************/
/*******************************************************************************
Function: void GIF_vResetData(GIFDECODER *pGifDec)
Precondition: None
Overview: This function resets the variables so that new GIF image
can be decoded
Input: GIF decoder's data structure
Output: None
*******************************************************************************/
static void GIF_vResetData(GIFDECODER *pGifDec)
{
pGifDec->pImageFile = NULL;
pGifDec->wImageWidth = 0;
pGifDec->wImageHeight = 0;
pGifDec->wImageX = 0;
pGifDec->wImageY = 0;
pGifDec->wScreenWidth = 0;
pGifDec->wScreenHeight = 0;
pGifDec->wGlobalPaletteEntries = 0;
pGifDec->wLocalPaletteEntries = 0;
pGifDec->bBgColorIndex = 0;
pGifDec->bPixelAspectRatio = 0;
pGifDec->blGifMarkerFlag = 0;
pGifDec->blGloabalColorTableFlag = 0;
pGifDec->blLocalColorTableFlag = 0;
pGifDec->blInterlacedFlag = 0;
pGifDec->blFirstcodeFlag = 1;
pGifDec->bInterlacePass = 0;
pGifDec->wMaxSymbol = 0;
pGifDec->bMaxSymbolBits = 0;
pGifDec->wInitialSymbols = 0;
pGifDec->bInitialSymbolBits = 0;
pGifDec->bWorkBits = 0;
pGifDec->bRemainingDataInBlock = 0;
pGifDec->bRemainingBits = 0;
pGifDec->wCurrentX = 0;
pGifDec->wCurrentY = 0;
pGifDec->lGlobalColorTablePos = 0;
}
/*******************************************************************************
Function: void GIF_vPutPrevCode(GIFDECODER *pGifDec, WORD wAddress, WORD wCode)
Precondition: None
Overview: This function puts the data(code) to the provided address
Input: GIF decoder's data structure, Address, Data(Code)
Output: None
*******************************************************************************/
static void GIF_vPutPrevCode(GIFDECODER *pGifDec, WORD wAddress, WORD wCode)
{
#if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0
pGifDec->awPrevSymbolPtr[wAddress] = wCode;
#else
WORD wCrushedAddress = (wAddress * 3) / 4;
if((wAddress & 0x03) == 0)
{
pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0xF000;
pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode & 0x0FFF);
}
else if((wAddress & 0x03) == 1)
{
pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x0FFF;
pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] &= 0xFF00;
pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 12);
pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] |= ((wCode >> 4) & 0x00FF);
}
else if((wAddress & 0x03) == 2)
{
pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x00FF;
pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] &= 0xFFF0;
pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 8);
pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] |= ((wCode >> 8) & 0x000F);
}
else
{
pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x000F;
pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 4);
}
#endif
}
/*******************************************************************************
Function: WORD GIF_wGetPrevCode(GIFDECODER *pGifDec, WORD wAddress)
Precondition: None
Overview: This function gets the data(code) from the provided address
Input: GIF decoder's data structure, Address
Output: Data(Code)
*******************************************************************************/
static WORD GIF_wGetPrevCode(GIFDECODER *pGifDec, WORD wAddress)
{
WORD wCode;
#if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0
wCode = pGifDec->awPrevSymbolPtr[wAddress];
#else
WORD wCrushedAddress = (wAddress * 3) / 4;
if((wAddress & 0x03) == 0)
{
wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] & 0x0FFF);
}
else if((wAddress & 0x03) == 1)
{
wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 12);
wCode |= ((pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] & 0x00FF) << 4);
}
else if((wAddress & 0x03) == 2)
{
wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 8);
wCode |= ((pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] & 0x000F) << 8);
}
else
{
wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 4);
}
#endif
return wCode;
}
/*******************************************************************************
Function: void GIF_vInitializeTable(GIFDECODER *pGifDec)
Precondition: pGifDec->wInitialSymbols must be set to a proper value by
reading the Header
Overview: This function initializes the code table to the initial number
of symbols
Input: GIF decoder's data structure
Output: None
*******************************************************************************/
static void GIF_vInitializeTable(GIFDECODER *pGifDec)
{
WORD wCounter;
for(wCounter = 0; wCounter < pGifDec->wInitialSymbols; wCounter++)
{
pGifDec->abSymbol[wCounter] = wCounter;
GIF_vPutPrevCode(pGifDec, wCounter, pGifDec->wInitialSymbols);
}
}
/*******************************************************************************
Function: void GIF_vReadColorTable(GIFDECODER *pGifDec, WORD wNumberOfEntries)
Precondition: None
Overview: This function initializes the code table to the initial number
of symbols
Input: GIF decoder's data structure
Output: None
*******************************************************************************/
static void GIF_vReadColorTable(GIFDECODER *pGifDec, WORD wNumberOfEntries)
{
BYTE r, g, b;
WORD wCounter;
for(wCounter = 0; wCounter < wNumberOfEntries; wCounter++)
{
IMG_FREAD(&r, sizeof(BYTE), 1, pGifDec->pImageFile); /* R */
IMG_FREAD(&g, sizeof(BYTE), 1, pGifDec->pImageFile); /* G */
IMG_FREAD(&b, sizeof(BYTE), 1, pGifDec->pImageFile); /* B */
#if GIF_USE_16_BITS_PER_PIXEL == 0
pGifDec->aPalette[wCounter][0] = r;
pGifDec->aPalette[wCounter][1] = g;
pGifDec->aPalette[wCounter][2] = b;
#else
pGifDec->awPalette[wCounter] = RGB565CONVERT(r, g, b);
#endif
}
}
/*******************************************************************************
Function: BYTE GIF_bReadHeader(GIFDECODER *pGifDec)
Precondition: None
Overview: This function reads the GIF file's header information
Input: GIF decoder's data structure
Output: Error code - '0' means no error
*******************************************************************************/
static BYTE GIF_bReadHeader(GIFDECODER *pGifDec)
{
BYTE abByte[6];
BYTE bFlags;
IMG_FREAD(abByte, sizeof(BYTE), 6, pGifDec->pImageFile); /* Marker */
if(abByte[0] == 'G' && abByte[1] == 'I' && abByte[2] == 'F' &&
abByte[3] == '8' && (abByte[4] == '7' || abByte[4] == '9') &&
abByte[5] == 'a')
{
pGifDec->blGifMarkerFlag = 1;
}
else
{
return(100);
}
IMG_FREAD(&pGifDec->wScreenWidth, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&pGifDec->wScreenHeight, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&bFlags, sizeof(BYTE), 1, pGifDec->pImageFile); /* Packed fields */
IMG_FREAD(&pGifDec->bBgColorIndex, sizeof(BYTE), 1, pGifDec->pImageFile);
IMG_FREAD(&pGifDec->bPixelAspectRatio, sizeof(BYTE), 1, pGifDec->pImageFile);
if(bFlags & 0x80)
{
pGifDec->blGloabalColorTableFlag = 1;
}
pGifDec->wGlobalPaletteEntries = 0x01 << ((bFlags & 0x07) + 1);
if(pGifDec->blGloabalColorTableFlag == 1)
{
pGifDec->lGlobalColorTablePos = IMG_FTELL(pGifDec->pImageFile);
GIF_vReadColorTable(pGifDec, pGifDec->wGlobalPaletteEntries);
}
return(0);
}
/*******************************************************************************
Function: BYTE GIF_bReadNextImageDescriptor(GIFDECODER *pGifDec)
Precondition: File pointer must be pointing to proper location (Like start of
extension)
Overview: This function reads the next image descriptor
Input: GIF decoder's data structure
Output: Error code - '0' means no error
*******************************************************************************/
static BYTE GIF_bReadNextImageDescriptor(GIFDECODER *pGifDec)
{
BYTE bSection, bSectionDetails, bBlockSize, bTemp;
BYTE bFlags;
BYTE bCounter;
do
{
IMG_FREAD(&bSection, sizeof(BYTE), 1, pGifDec->pImageFile);
if(bSection == 0x21) /* Extension block */
{
IMG_FREAD(&bSectionDetails, sizeof(BYTE), 1, pGifDec->pImageFile);
switch(bSectionDetails)
{
/* GRAPHICS EXTENSION */ case 0xF9: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile);
IMG_FSEEK(pGifDec->pImageFile, bBlockSize, 1);
break;
/* PLAIN TEXT EXTENSION */ case 0x01:
/* APPLICATION EXTENSION */ case 0xFF: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile);
IMG_FSEEK(pGifDec->pImageFile, bBlockSize, 1);
/* COMMENT EXTENSION */ case 0xFE: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile);
for(bCounter = 0; bCounter < bBlockSize; bCounter++)
{
IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile);
}
break;
default: return(100);
}
/* BLOCK TERMINATOR */ IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile);
if(bTemp != 0)
{
return(100);
}
}
else if(bSection != 0x2C)
{
return(100);
}
}
while(bSection != 0x2C);
pGifDec->blFirstcodeFlag = 1;
pGifDec->bInterlacePass = 0;
pGifDec->bWorkBits = 0;
pGifDec->bRemainingDataInBlock = 0;
pGifDec->bRemainingBits = 0;
IMG_FREAD(&pGifDec->wImageX, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&pGifDec->wImageY, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&pGifDec->wImageWidth, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&pGifDec->wImageHeight, sizeof(WORD), 1, pGifDec->pImageFile);
IMG_FREAD(&bFlags, sizeof(BYTE), 1, pGifDec->pImageFile); /* Packed fields */
if(bFlags & 0x40)
{
pGifDec->blInterlacedFlag = 1;
}
if(bFlags & 0x80)
{
pGifDec->blLocalColorTableFlag = 1;
}
pGifDec->wLocalPaletteEntries = 0x01 << ((bFlags & 0x07) + 1);
if(pGifDec->blLocalColorTableFlag == 1)
{
GIF_vReadColorTable(pGifDec, pGifDec->wLocalPaletteEntries);
}
pGifDec->wCurrentX = pGifDec->wImageX;
pGifDec->wCurrentY = pGifDec->wImageY;
return 0;
}
/*******************************************************************************
Function: WORD GIF_wGetNextByte(GIFDECODER *pGifDec)
Precondition: None
Overview: This function reads the next data byte. It also handles the
data block intra-boundaries
Input: GIF decoder's data structure
Output: Data byte, 0xFFFF means error
*******************************************************************************/
static WORD GIF_wGetNextByte(GIFDECODER *pGifDec)
{
BYTE bByte;
if(pGifDec->bRemainingDataInBlock == 0)
{
IMG_FREAD(&pGifDec->bRemainingDataInBlock, sizeof(BYTE), 1, pGifDec->pImageFile);
if(pGifDec->bRemainingDataInBlock == 0)
{
return 0xFFFF; /* End of data */
}
}
IMG_FREAD(&bByte, sizeof(BYTE), 1, pGifDec->pImageFile);
pGifDec->bRemainingDataInBlock--;
return (WORD)bByte;
}
/*******************************************************************************
Function: WORD GIF_wGetNextSymbol(GIFDECODER *pGifDec)
Precondition: pGifDec->bMaxSymbolBits must be properly updated
Overview: This function reads the next code symbol brom the data stream
Input: GIF decoder's data structure
Output: Next Code, 0xFFFF means error
*******************************************************************************/
static WORD GIF_wGetNextSymbol(GIFDECODER *pGifDec)
{
WORD wDataBits = 0xFFFF;
if(pGifDec->bRemainingBits < pGifDec->bMaxSymbolBits)
{
WORD wTemp1, wTemp2;
BYTE bBitsRequired;
bBitsRequired = pGifDec->bMaxSymbolBits - pGifDec->bRemainingBits;
wDataBits = pGifDec->bWorkBits & GIF_awMask[pGifDec->bRemainingBits];
wTemp1 = GIF_wGetNextByte(pGifDec);
if(wTemp1 == 0xFFFF)
{
return 0xFFFF;
}
pGifDec->bWorkBits = (BYTE)wTemp1;
if(bBitsRequired > 8)
{
wTemp2 = GIF_wGetNextByte(pGifDec);
if(wTemp2 == 0xFFFF)
{
return 0xFFFF;
}
pGifDec->bWorkBits = (BYTE)wTemp2;
wTemp1 |= wTemp2 << 8;
}
wDataBits |= wTemp1 << pGifDec->bRemainingBits;
pGifDec->bRemainingBits = 8 - (bBitsRequired % 8);
if(bBitsRequired == 8)
{
pGifDec->bRemainingBits = 0;
}
pGifDec->bWorkBits >>= 8 - pGifDec->bRemainingBits;
}
else
{
wDataBits = pGifDec->bWorkBits;
pGifDec->bRemainingBits -= pGifDec->bMaxSymbolBits;
pGifDec->bWorkBits >>= pGifDec->bMaxSymbolBits;
}
wDataBits &= GIF_awMask[pGifDec->bMaxSymbolBits];
return wDataBits;
}
/*******************************************************************************
Function: void GIF_vPaintData(GIFDECODER *pGifDec, BYTE bData)
Precondition: pGifDec->blInterlacedFlag must be properly set
Overview: This function puts the actual pixel on the display. It also
takes care of the interlaced pixel arrangement.
Input: GIF decoder's data structure, palette index
Output: None
*******************************************************************************/
static void GIF_vPaintData(GIFDECODER *pGifDec, BYTE bData)
{
#if GIF_USE_16_BITS_PER_PIXEL == 0
IMG_vSetColor(pGifDec->aPalette[bData][0], pGifDec->aPalette[bData][1], pGifDec->aPalette[bData][2]);
#else
IMG_vSetColor565(pGifDec->awPalette[bData]);
#endif
IMG_vPutPixel(pGifDec->wCurrentX, pGifDec->wCurrentY);
pGifDec->wCurrentX++;
if(pGifDec->wCurrentX >= pGifDec->wImageWidth)
{
IMG_vLoopCallback();
pGifDec->wCurrentX = pGifDec->wImageX;
if(pGifDec->blInterlacedFlag == 0)
{
pGifDec->wCurrentY++;
}
else
{
switch(pGifDec->bInterlacePass)
{
case 0: pGifDec->wCurrentY += 8;
break;
case 1: pGifDec->wCurrentY += 8;
break;
case 2: pGifDec->wCurrentY += 4;
break;
case 3: pGifDec->wCurrentY += 2;
break;
}
if(pGifDec->wCurrentY - pGifDec->wImageY >= pGifDec->wImageHeight)
{
switch(pGifDec->bInterlacePass)
{
case 0: pGifDec->wCurrentY = pGifDec->wImageY + 4;
break;
case 1: pGifDec->wCurrentY = pGifDec->wImageY + 2;
break;
case 2: pGifDec->wCurrentY = pGifDec->wImageY + 1;
break;
case 3: pGifDec->wCurrentY = pGifDec->wImageY + 0;
break;
}
pGifDec->bInterlacePass++;
}
}
}
}
/*******************************************************************************
Function: void GIF_vDisplayCode(GIFDECODER *pGifDec, WORD wCode)
Precondition: None
Overview: This function puts the stream of pixels corresponding to the
code. This uses recursion.
Input: GIF decoder's data structure, code
Output: None
*******************************************************************************/
static void GIF_vDisplayCode(GIFDECODER *pGifDec, WORD wCode)
{
WORD wPrevCode = GIF_wGetPrevCode(pGifDec, wCode);
if(wPrevCode != pGifDec->wInitialSymbols)
{
GIF_vDisplayCode(pGifDec, wPrevCode);
}
GIF_vPaintData(pGifDec, pGifDec->abSymbol[wCode]);
}
/*******************************************************************************
Function: BYTE GIF_bTraceFirstData(GIFDECODER *pGifDec, WORD wCode)
Precondition: None
Overview: This function gets the first symbol of the code
Input: GIF decoder's data structure, code
Output: First symbol of the code
*******************************************************************************/
static BYTE GIF_bTraceFirstData(GIFDECODER *pGifDec, WORD wCode)
{
while(GIF_wGetPrevCode(pGifDec, wCode) != pGifDec->wInitialSymbols)
{
wCode = GIF_wGetPrevCode(pGifDec, wCode);
}
return pGifDec->abSymbol[wCode];
}
/*******************************************************************************
Function: GIF_vExecuteClearCode(GIFDECODER *pGifDec)
Precondition: None
Overview: This function sets the code table to the initial condition
Input: GIF decoder's data structure
Output: None
*******************************************************************************/
static void GIF_vExecuteClearCode(GIFDECODER *pGifDec)
{
pGifDec->wMaxSymbol = pGifDec->wInitialSymbols;
pGifDec->bMaxSymbolBits = pGifDec->bInitialSymbolBits;
pGifDec->blFirstcodeFlag = 1;
}
/*******************************************************************************
Function: BYTE GIF_bDecodeNextImage(GIFDECODER *pGifDec)
Precondition: Header must be read and file pointer should point to the end
of the previous image
Overview: This function sets the code table to the initial condition
Input: GIF decoder's data structure
Output: Error code - '0' means no error
*******************************************************************************/
static BYTE GIF_bDecodeNextImage(GIFDECODER *pGifDec)
{
BYTE bBlockTerminator;
WORD wCode;
if(GIF_bReadNextImageDescriptor(pGifDec) != 0)
{
return(100);
}
IMG_FREAD(&pGifDec->bMaxSymbolBits, sizeof(BYTE), 1, pGifDec->pImageFile);
if(pGifDec->bMaxSymbolBits > 11)
{
return(100);
}
pGifDec->wMaxSymbol = (0x01 << pGifDec->bMaxSymbolBits) + 1;
pGifDec->bMaxSymbolBits++;
pGifDec->wInitialSymbols = pGifDec->wMaxSymbol;
pGifDec->bInitialSymbolBits = pGifDec->bMaxSymbolBits;
GIF_vInitializeTable(pGifDec);
/* Actual decoding starts here */
while(!IMG_FEOF(pGifDec->pImageFile))
{
IMG_vCheckAndAbort();
wCode = GIF_wGetNextSymbol(pGifDec);
if(wCode >= 4096)
{
return(100);
}
if(wCode == pGifDec->wInitialSymbols) /* End code */
{
break;
}
if(wCode == pGifDec->wInitialSymbols - 1) /* Clear code */
{
GIF_vExecuteClearCode(pGifDec);
continue;
}
if(wCode <= pGifDec->wMaxSymbol) /* Code exists */
{
GIF_vDisplayCode(pGifDec, wCode);
if(pGifDec->blFirstcodeFlag == 0 && pGifDec->wMaxSymbol < 4095)
{
pGifDec->wMaxSymbol++;
pGifDec->abSymbol[pGifDec->wMaxSymbol] = GIF_bTraceFirstData(pGifDec, wCode);
}
if(pGifDec->wMaxSymbol < 4095)
{
GIF_vPutPrevCode(pGifDec, pGifDec->wMaxSymbol + 1, wCode);
}
pGifDec->blFirstcodeFlag = 0;
}
else if(wCode == pGifDec->wMaxSymbol + 1 && wCode <= 4095)
{
if(pGifDec->blFirstcodeFlag == 1)
{
return(100);
}
pGifDec->wMaxSymbol++;
pGifDec->abSymbol[pGifDec->wMaxSymbol] = GIF_bTraceFirstData(pGifDec, GIF_wGetPrevCode(pGifDec, pGifDec->wMaxSymbol));
GIF_vDisplayCode(pGifDec, wCode);
if(pGifDec->wMaxSymbol < 4095)
{
GIF_vPutPrevCode(pGifDec, pGifDec->wMaxSymbol + 1, wCode);
}
}
else
{
return(100);
}
if((pGifDec->bMaxSymbolBits < 12) && (pGifDec->wMaxSymbol >= (0x01 << pGifDec->bMaxSymbolBits) - 1))
{
pGifDec->bMaxSymbolBits++;
}
}
if(pGifDec->blLocalColorTableFlag == 1) /* Restore Global color table */
{
if(pGifDec->lGlobalColorTablePos > 0)
{
LONG lFilePos = IMG_FTELL(pGifDec->pImageFile);
IMG_FSEEK(pGifDec->pImageFile, pGifDec->lGlobalColorTablePos, 0);
GIF_vReadColorTable(pGifDec, pGifDec->wGlobalPaletteEntries);
IMG_FSEEK(pGifDec->pImageFile, lFilePos, 0);
}
}
IMG_FREAD(&bBlockTerminator, sizeof(BYTE), 1, pGifDec->pImageFile);
if(bBlockTerminator == 0)
{
BYTE bTemp;
IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile);
if(bTemp == 0x3B) /* End of GIF stream */
{
return 0x3B;
}
IMG_FSEEK(pGifDec->pImageFile, -1, 1);
}
return bBlockTerminator;
}
/*******************************************************************************
Function: BYTE GIF_bDecode(IMG_FILE *pFile)
Precondition: None
Overview: This function decodes and displays a GIF image
Input: Image file
Output: Error code - '0' means no error
*******************************************************************************/
BYTE GIF_bDecode(IMG_FILE *pFile)
{
GIFDECODER GifDec;
GIF_vResetData(&GifDec);
GifDec.pImageFile = pFile;
GIF_bReadHeader(&GifDec);
if(GifDec.blGifMarkerFlag == 0)
{
return(100);
}
IMG_wImageWidth = GifDec.wScreenWidth;
IMG_wImageHeight = GifDec.wScreenHeight;
IMG_vSetboundaries();
return GIF_bDecodeNextImage(&GifDec);
}
#endif
#undef __GIFDECODER_C__
|