//#include
//#include
//#include
#define PEG_RGB16
#define DISPLAY_HEIGHT 220
#define DISPLAY_WIDTH 176
#define MAX_MALLOC_LEN 0xF0000
typedef unsigned long U32;
typedef unsigned short U16;
typedef unsigned char U8;
typedef signed short S16;
typedef signed long S32;
#define MAXCOLORMAPSIZE 256
#define TRUE 1
#define FALSE 0
#define MAX_LWZ_BITS 12
#define INTERLACE 0x40
#define LOCALCOLORMAP 0x80
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
#define LM_to_uint(a,b) ((((U16)(b))<<8)|((U16)a))
#define MAX_LENGTH_EXTENSION 128
typedef struct
{
U16 x;
U16 y;
}
PegPoint;
typedef struct
{
U16 Width;
U16 Height;
RGBQUAD ColorMap[MAXCOLORMAPSIZE];
U16 BitPixel;
U16 ColorResolution;
U16 Background;
U16 AspectRatio;
U16 GrayScale;
} GIFSCREEN;
typedef struct
{
U16 transparent;
U16 delayTime;
U16 inputFlag;
U16 disposal;
} GIF89;
typedef enum
{
DECODE_ERROR_FROMAT = -1, //Error decode file format!
DECODE_ERROR_SUPPORT = -2, //No surpport decode file format !
DECODE_ERROR_MAX
}
T_DECODE_ERROR_ID;
typedef struct tagGIFDECODE
{
U8 *pGIF;
U32 lGIF;
U32 sGIF;//offset
GIFSCREEN GifScreen;
GIF89 Gif89;
RGBQUAD cmap[256];
S16 ZeroDataBlock;
U32 wib;
U16 biBitCount;
U16 ImageLeftPosition;
U16 ImageTopPosition;
U16 OffsetHeight;
U16 OffsetWidth;
U32 lSrc;
U8 *pSrc; //the source jpeg encoded buffer
U32 lDst;
U8 *pDst; //the destination rgb16 or rgb24 buffer
#ifdef PEG_RGB16
U16 cpegmap[256];
#endif
U16 Gifnumber;
U16 ViewNumber;
}
GIFDECODE;
static GIFDECODE *gif;
S16
dib_wib (U16 bitcount,
U16 wi)
{
switch (bitcount)
{
case 1:
wi = (wi + 31) >> 3;
break;
case 4:
wi = (wi + 7) >> 1;
break;
case 8:
wi = wi + 3;
break;
case 16:
wi = (wi * 2) + 3;
break;
case 24:
wi = (wi * 3) + 3;
break;
case 32:
return wi * 4;
}
return wi & ~3;
}
U16 GIFReadOK(U8 *buffer,S16 len)
{
memcpy((void*)buffer,gif->pGIF+gif->sGIF,(S16)len);
gif->sGIF+=(S16)len;
return (S16)len;
}
#ifndef PEG_RGB16
typedef struct tagBITMAPFILEHEADEREX
{
U32 bfSize;
U32 bfReserved;
U32 bfOffBits;
}
BITMAPFILEHEADEREX;
typedef struct tagBITMAPINFOHEADER
{
U32 biSize;
U32 biWidth;
U32 biHeight;
U16 biPlanes;
U16 biBitCount;
U32 biCompression;
U32 biSizeImage;
U32 biXPelsPerMeter;
U32 biYPelsPerMeter;
U32 biClrUsed;
U32 biClrImportant;
}
BITMAPINFOHEADER;
short
Spew_header (S16 wi,
S16 hi,
S16 n,
RGBQUAD * cmap)
{
BITMAPINFOHEADER bi;
BITMAPFILEHEADEREX hdr;
U8 bfType[2];
S16 nn;
DEBUG_Message("........spew_header........");
bi.biBitCount = gif->biBitCount;
nn = 1 << ((S16) bi.biBitCount);
bi.biSize = sizeof (bi);
bi.biWidth = wi;
bi.biHeight = hi;
bi.biPlanes = 1;
bi.biCompression = 0;
bi.biSizeImage = bi.biHeight * gif->wib;
bi.biClrUsed = nn;
bi.biClrImportant = nn;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bfType[0] = 0x42; /* BM */
bfType[1] = 0x4D;
hdr.bfReserved = 0L;
hdr.bfOffBits = 2 + sizeof (hdr) + bi.biSize + nn * sizeof (RGBQUAD);
hdr.bfSize = hdr.bfOffBits + bi.biSizeImage;
gif->lDst=hdr.bfSize;
memcpy(gif->pDst,bfType,(S32)2*sizeof (U8));
memcpy(gif->pDst+2*sizeof(U8),&hdr,(S32)sizeof(BITMAPFILEHEADEREX));
memcpy(gif->pDst+sizeof (BITMAPFILEHEADEREX)+2*sizeof (U8),&bi,(S32)sizeof(BITMAPINFOHEADER));
if (nn > 0)
memcpy(gif->pDst+sizeof (BITMAPFILEHEADEREX)+2*sizeof (U8)+sizeof(BITMAPINFOHEADER),
cmap,(S32)sizeof (RGBQUAD)*nn);
return 1;
}
#endif
U16
GIFReadColorMap (U16 number,RGBQUAD * buffer)
{
U16 i;
U8 *rgb=NULL;
for (i = 0; i < number; ++i, buffer++)
{
rgb=gif->pGIF+gif->sGIF;
gif->sGIF += 3;
#ifndef PEG_RGB16
buffer->rgbRed = *rgb;
buffer->rgbGreen = *(rgb+1);
buffer->rgbBlue = *(rgb+2);
buffer->rgbReserved = 0;
#else
gif->cpegmap[i] = (rgb[2] >> 3) + ((rgb[1] >> 2) <<>> 3) << 11);
#endif
}
return (U16)0;
}
S16
GIFGetDataBlock (U8 * buf)
{
U8 count;
count=*(gif->pGIF+gif->sGIF);
gif->sGIF++;
gif->ZeroDataBlock = count == 0;
if ((count != 0) && (!GIFReadOK (buf, count)))
{
DEBUG_Message ( "error in reading DataBlock");
return -1;
}
return count;
}
S16
GIFDoExtension (S16 label)
{
U8 buf[256];
switch (label)
{
case 0x01: /* Plain Text Extension */
break;
case 0xff: /* Application Extension */
GIFGetDataBlock ((U8 *) buf);
break;
case 0xfe: /* Comment Extension */
while (GIFGetDataBlock ((U8 *) buf) != 0)
{
}
return FALSE;
case 0xf9: /* Graphic Control Extension */
(void) GIFGetDataBlock ((U8 *) buf);
gif->Gif89.disposal = (buf[0] >> 2) & 0x7;
gif->Gif89.inputFlag = (buf[0] >> 1) & 0x1;
gif->Gif89.delayTime = LM_to_uint (buf[1], buf[2]);
if ((buf[0] & 0x1) != 0)
gif->Gif89.transparent = 0xff&buf[3];
else
gif->Gif89.transparent = (U16)-1;
while (GIFGetDataBlock ( (U8 *) buf) != 0);
return FALSE;
default:
break;
}
while (GIFGetDataBlock ((U8 *) buf) != 0);
return FALSE;
}
S16
GIFGetCode (S16 code_size,S16 flag)
{
static U8 buf[280];
static S16 curbit, lastbit, done, last_byte;
S16 i, j, ret;
U8 count;
if (flag)
{
curbit = 0;
lastbit = 0;
done = FALSE;
return 0;
}
if ((curbit + code_size) >= lastbit)
{
if (done)
{
if (curbit >= lastbit)
DEBUG_Message("ran off the end of my bits");
return -1;
}
buf[0] = buf[last_byte - 2];
buf[1] = buf[last_byte - 1];
if ((count = (U8)GIFGetDataBlock ( &buf[2])) == 0)
done = TRUE;
last_byte = 2 + (S16)(0xff & count);
curbit = (curbit - lastbit) + 16;
lastbit = (2 + (U32) (0x00ff & count)) * 8;
}
ret = 0;
for (i = curbit, j = 0; j < code_size; ++i, ++j)
ret |= ((buf[i >> 3] & (1 << (i % 8))) != 0) << j;
curbit += code_size;
return ret;
}
S16
GIFLWZReadByte (S16 flag,S16 input_code_size)
{
static S16 fresh = FALSE;
S16 code, incode;
static S16 code_size, set_code_size;
static S16 max_code, max_code_size;
static S16 firstcode, oldcode;
static S16 clear_code, end_code;
static S16 table[2][(1 << MAX_LWZ_BITS)];
static S16 stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
S16 i;
if (flag)
{
set_code_size = input_code_size;
code_size = set_code_size + 1;
clear_code = 1 << set_code_size;
end_code = clear_code + 1;
max_code_size = 2 * clear_code;
max_code = clear_code + 2;
GIFGetCode (0, TRUE);
fresh = TRUE;
for (i = 0; i < clear_code; ++i)
{
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1 << MAX_LWZ_BITS); ++i)
table[0][i] = table[1][0] = 0;
sp = stack;
return 0;
}
else if (fresh)
{
fresh = FALSE;
do
{
firstcode = oldcode = GIFGetCode ( code_size, FALSE);
}
while (firstcode == clear_code);
return firstcode;
}
if (sp > stack)
return *--sp;
while ((code = GIFGetCode (code_size, FALSE)) >= 0)
{
if (code == clear_code)
{
for (i = 0; i < clear_code; ++i)
{
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1 << MAX_LWZ_BITS); ++i)
table[0][i] = table[1][i] = 0;
code_size = set_code_size + 1;
max_code_size = 2 * clear_code;
max_code = clear_code + 2;
sp = stack;
firstcode = oldcode = GIFGetCode (code_size, FALSE);
return firstcode;
}
else if (code == end_code)
{
S16 count;
U8 buf[260];
if (gif->ZeroDataBlock)
return -2;
while ((count = GIFGetDataBlock ( buf)) > 0);
if (count != 0)
DEBUG_Message ("missing EOD in data stream (common occurence)");
return -2;
}
incode = code;
if (code >= max_code)
{
*sp++ = firstcode;
code = oldcode;
}
while (code >= clear_code)
{
*sp++ = table[1][code];
if (code == table[0][code])
{
DEBUG_Message ("circular table entry BIG ERROR");
return -1;
}
code = table[0][code];
}
*sp++ = firstcode = table[1][code];
if ((code = max_code) < (1 << MAX_LWZ_BITS))
{
table[0][code] = oldcode;
table[1][code] = firstcode;
++max_code;
if ((max_code >= max_code_size) &&
(max_code_size < (1 << MAX_LWZ_BITS)))
{
max_code_size *= 2;
++code_size;
}
}
oldcode = incode;
if (sp > stack)
return *--sp;
}
return code;
}
U8
GIFReadImage (U16 len,U16 height,RGBQUAD * cmap,
U16 bpp,
U16 interlace,
U16 ignore)
{
U8 c;
S16 v;
S16 xpos = 0, ypos = 0, pass = 0;
U8 *scanline;
#ifndef PEG_RGB16
char strGiffile[256];
#endif
c=*(gif->pGIF+gif->sGIF);
gif->sGIF++;
if (GIFLWZReadByte (TRUE, c) < 0)
{
DEBUG_Message ("error reading imagea");
return 0;
}
if ((scanline = (U8 *) malloc (len)) == NULL)
{
DEBUG_Message ("couldn't alloc space for image");
return 0;
}
if (bpp > 16 || 0x0000)
gif->biBitCount = 8;
else if (bpp > 2)
gif->biBitCount = 4;
else
gif->biBitCount = 1;
gif->wib = dib_wib ((U16) gif->biBitCount, (U16) len);
#ifndef PEG_RGB16
//Spew_header (len, height, bpp, cmap);
//
Spew_header (gif->GifScreen.Width, gif->GifScreen.Height, bpp, cmap);
//
#endif
/* Fill the whole file with junk */
//for (v = 0; v < height; v++)
// bmp8bufwrite (scanline, 1, (S16) wib, fp);
while (ypos < v =" GIFLWZReadByte">= 0)
{
switch (gif->biBitCount)
{
case 1:
if (v)
scanline[xpos >> 3] |= 128 >> (xpos & 7);
else
scanline[xpos >> 3] &= 0xff7f >> (xpos & 7);
#ifdef PEG_RGB16
*(gif->pDst + ypos * (len * 2) + 2 * xpos) =
(U8) (gif->cpegmap[0x00ff & v & 1] & 0x00ff);
*(gif->pDst + ypos * (len * 2) + 2 * xpos + 1) =
(U8) ((gif->cpegmap[0x00ff & v & 1] >> 8) & 0x00ff);
#else
//memcpy((gif->pDst+gif->lDst -(ypos+ gif->ImageTopPosition+gif->OffsetHeight + 1) * gif->wib),scanline,(S16) gif->wib);
*(gif->pDst + gif->lDst - (ypos + gif->ImageTopPosition+gif->OffsetHeight + 1) * len + (xpos+gif->ImageLeftPosition+gif->OffsetWidth)) = v&1;
#endif
break;
case 4:
if (xpos & 1)
scanline[xpos >> 1] |= v & 15;
else
scanline[xpos >> 1] = (v & 15) << 4;
if(gif->Gif89.transparent != (S16)(0x00ff & v & 15))
{
#ifdef PEG_RGB16
*(gif->pDst + (ypos+gif->ImageTopPosition+gif->OffsetHeight) * (len * 2) + 2 * (xpos+gif->ImageLeftPosition+gif->OffsetWidth)) =
(U8) (gif->cpegmap[0x00ff & v & 15] & 0x00ff);
*(gif->pDst + (ypos+gif->ImageTopPosition+gif->OffsetHeight) * (len * 2) + 2 * (xpos+gif->ImageLeftPosition+gif->OffsetWidth) + 1) =
(U8) ((gif->cpegmap[0x00ff & v & 15] >> 8) & 0x00ff);
#else
//memcpy((gif->pDst+gif->lDst -(ypos+ gif->ImageTopPosition+gif->OffsetHeight + 1) * gif->wib),scanline,(S16) gif->wib);
*(gif->pDst + gif->lDst - (ypos + gif->ImageTopPosition+gif->OffsetHeight + 1) * len + (xpos+gif->ImageLeftPosition+gif->OffsetWidth)) = v&15;
#endif
}
break;
case 8:
scanline[xpos] = (U8)v;
if(gif->Gif89.transparent != (S16)(0x00ff & v))
{
#ifdef PEG_RGB16
*(gif->pDst + (ypos+gif->ImageTopPosition+gif->OffsetHeight) * (DISPLAY_WIDTH * 2) + 2 * (xpos+gif->ImageLeftPosition+gif->OffsetWidth)) =
(U8) (gif->cpegmap[0x00ff & v] & 0x00ff);
*(gif->pDst + (ypos+gif->ImageTopPosition+gif->OffsetHeight) * (DISPLAY_WIDTH * 2) + 2 * (xpos+gif->ImageLeftPosition+gif->OffsetWidth) + 1) =
(U8) ((gif->cpegmap[0x00ff & v] >> 8) & 0x00ff);
#else
//memcpy((gif->pDst+gif->lDst -(ypos+ gif->ImageTopPosition+gif->OffsetHeight + 1) * gif->wib),scanline,(S16) gif->wib);
*(gif->pDst + gif->lDst - (ypos + gif->ImageTopPosition+gif->OffsetHeight + 1) * len + (xpos+gif->ImageLeftPosition+gif->OffsetWidth)) = v;
#endif
}
break;
}
++xpos;
if (xpos == len)
{
xpos = 0;
if (interlace)
{
static S16 dpass[] = { 8, 8, 4, 2 };
ypos += dpass[pass];
if (ypos >= height)
{
static S16 restart[] = { 0, 4, 2, 1, 32767 };
ypos = restart[++pass];
}
}
else
++ypos;
}
}
#ifndef PEG_RGB16
sprintf(strGiffile,".\\bin\\gif%d.bmp",gif->Gifnumber++);
WriteBinFile(strGiffile,gif->pDst,gif->lDst);
#endif
if (GIFLWZReadByte (FALSE, c) >= 0)
{
DEBUG_Message ("too much input data, ignoring extra...");
}
return 1;
}
S32
GE_Initialize (U8 * buff, U32 len)
{
U8 *buf=NULL;
//U8 c;
//RGBQUAD localColorMap[MAXCOLORMAPSIZE];
//U16 useGlobalColormap;
//U16 bitPixel;
//U16 imageCount = 0;
U8 *version=NULL;
//U16 imageNumber =50;
gif->pGIF=buff;
gif->lGIF=len;
buf=gif->pGIF+gif->sGIF;
gif->sGIF += 6;
if((0x47 != (U8)(*buf))||(0x49 != (U8)(*(buf+1)))
||(0x46 != (U8)(*(buf+2))))//"GIF"
{
DEBUG_Message ("not a GIF file");
return 0;
}
version = buf+3;
if(!(((0x38 == (U8)(*version))||(0x37 == (U8)(*(version+1)))||(0x61 == (U8)(*(version+2))))//"87a"
||((0x38 == (U8)(*version))||(0x39 == (U8)(*(version+1)))||(0x61 == (U8)(*(version+2))))))//"89a"
{
DEBUG_Message ("bad version number, not '87a' or '89a'");
return 0;
}
buf=gif->pGIF+gif->sGIF;
gif->sGIF += 7;
gif->GifScreen.Width = LM_to_uint (*buf, *(buf+1));
gif->GifScreen.Height = LM_to_uint (*(buf+2),*(buf+3));
gif->GifScreen.BitPixel = 2 << ((*(buf+4)) & 0x07);
gif->GifScreen.ColorResolution = ((((*(buf+4)) & 0x70) >> 3) + 1);
gif->GifScreen.Background = *(buf+5);
gif->GifScreen.AspectRatio = *(buf+6);
DEBUG_Message ("gif->GifScreen.Width is 0x%X",gif->GifScreen.Width);
DEBUG_Message ("gif->GifScreen.Height is 0x%X",gif->GifScreen.Height);
DEBUG_Message ("gif->GifScreen.BitPixel is 0x%X",gif->GifScreen.BitPixel);
DEBUG_Message ("gif->GifScreen.ColorResolution is 0x%X",gif->GifScreen.ColorResolution);
DEBUG_Message ("gif->GifScreen.Background is 0x%X",gif->GifScreen.Background);
DEBUG_Message ("gif->GifScreen.AspectRatio is 0x%X",gif->GifScreen.AspectRatio);
#ifdef PEG_RGB16
gif->lDst = DISPLAY_HEIGHT * DISPLAY_WIDTH * 2;
//gif->lDst=gif->GifScreen.Width*gif->GifScreen.Height*2;
#endif
if (BitSet (buf[4], LOCALCOLORMAP))
{ /* Global Colormap */
if (GIFReadColorMap (gif->GifScreen.BitPixel, gif->GifScreen.ColorMap))
{
DEBUG_Message ("error reading global colormap");
return 0;
}
}
#ifdef PEG_RGB16
return gif->lDst;
#else
return 0;
#endif
}
#define MAX_IMAGE_NUMBER 50
int
GE_Decode (PegPoint Where)
{
U8 *buf=NULL;
U8 c;
RGBQUAD localColorMap[MAXCOLORMAPSIZE];
U16 useGlobalColormap;
U16 bitPixel;
U16 imageCount = 0;
//U8 *version=NULL;
//U16 imageNumber =50;
gif->OffsetWidth = Where.x;
gif->OffsetHeight = Where.y;
for (;;)
{
c=*(gif->pGIF+gif->sGIF);
gif->sGIF++;
if (c == ';')
{ /* GIF terminator */
if (imageCount < MAX_IMAGE_NUMBER)
{
DEBUG_Message ( "only %d image%s found in file",
imageCount, imageCount > 1 ? "s" : "");
return imageCount;
}
return imageCount;
}
if (c == '!')
{ /* Extension */
c=*(gif->pGIF+gif->sGIF);
gif->sGIF++;
GIFDoExtension ( c);
continue;
}
if (c != ',')
{ /* Not a valid start character */
DEBUG_Message ("bogus character 0x%02x, ignoring", (int) c);
continue;
}
++imageCount;
if(imageCount>gif->ViewNumber)
return 0;
buf=gif->pGIF+gif->sGIF;
gif->sGIF += 9;
useGlobalColormap = !((*(buf+8)) & LOCALCOLORMAP);
bitPixel = 1 << ((*(buf+8)) & 0x07) + 1;
gif->ImageLeftPosition=(U16)LM_to_uint (*buf, *(buf+1));
gif->ImageTopPosition=(U16)LM_to_uint (*(buf+2), *(buf+3));
DEBUG_Message("ImageLeftPosition is 0x%X",gif->ImageLeftPosition);
DEBUG_Message("ImageTopPosition is 0x%X",gif->ImageTopPosition);
if (!useGlobalColormap)
{
if (GIFReadColorMap (bitPixel, localColorMap))
{
DEBUG_Message ("error reading local colormap");
return 0;
}
GIFReadImage ((U16)LM_to_uint (*(buf+4), *(buf+5)),
(U16)LM_to_uint (*(buf+6), *(buf+7)),
localColorMap, bitPixel,
(U16)((*(buf+8)) & INTERLACE), (U16)( imageCount != MAX_IMAGE_NUMBER));
}
else
{
GIFReadImage ( (U16)LM_to_uint (*(buf+4), *(buf+5)),
(U16)LM_to_uint (*(buf+6), *(buf+7)),
gif->GifScreen.ColorMap, gif->GifScreen.BitPixel,
(U16)((*(buf+8)) & INTERLACE), (U16)(imageCount != MAX_IMAGE_NUMBER));
}
}
//return -1;
}
static GIFDECODE gifdecode;
U16
GE_MemInit (void)
{
if (gif != NULL)
{
gif = NULL;
}
gif = (GIFDECODE *) & gifdecode;
DEBUG_Message ("GE_MemInit!");
memset (gif, 0x00, sizeof (GIFDECODE));
gif->Gif89.transparent = (U16)-1;
gif->Gif89.delayTime = (U16) -1;
gif->Gif89.inputFlag = (U16) -1;
gif->Gif89.disposal = (U16) 0;
return sizeof (GIFDECODE);
}
U16
GE_MemAlloc (void)
{
gif->pDst = (U8 *) & display;
//#ifdef _SUPPORT_FILE
memset (gif->pDst, 0xFF, gif->lDst);
//#endif
return (U16) (gif->lDst);
}
void
GE_MemRelease (void)
{
#ifndef PEG_RGB16
if(!gif->pDst)
{
free(gif->pDst);
}
#endif
gif->pDst = NULL;
gif = NULL;
}
int
GIFDecodeMain (PegPoint Where, U8 * fp_gif_buffer, U32 gif_total_size)
{
S32 dstlen = 0;
DEBUG_Message ("........test........");
GE_MemInit (); //////////////////////////////////////////////////////////
dstlen=GE_Initialize(fp_gif_buffer, gif_total_size);
if ((dstlen == 0) || (dstlen > MAX_MALLOC_LEN))
{
DEBUG_Message ("........overflow........");
return -1;
}
#ifdef PEG_RGB16
gif->ViewNumber=9;
#else
gif->ViewNumber=55;
#endif
GE_MemAlloc (); //////////////////////////////////////////////////////////
GE_Decode (Where);
DEBUG_Message ("........test over........");
GE_MemRelease (); //////////////////////////////////////////////////////////
return 0;
}