📄 gif89a.cpp
字号:
/***************************************
*
*
*
*
*********************************************/
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#include "gif89a.h"
#include <minigui/common.h>
#define MAX_LWZ_BITS 12
CGif89a::CGif89a()
{
opened = FALSE;
error = FALSE;
ZeroDataBlock = 0;
}
CGif89a::CGif89a(const char* fileName, BOOL inMem)
{
opened = FALSE;
ZeroDataBlock = 0;
if(open(fileName,inMem))
{
opened = TRUE;
error = FALSE;
}
else
{ opened = FALSE;
error = TRUE;
}
}
CGif89a::~CGif89a()
{
close();
}
BOOL CGif89a::operator!()
{
return error;
}
BOOL CGif89a::open(const char* fileName, BOOL b)
{
char cc[4];
BYTE be;
ifs= NULL;
inMem = b;
allFrames = NULL;
curIndex = 0;
curFrame.pColorTable = NULL;
curFrame.dataBuf = NULL;
ctrlExt.active = FALSE;
fprintf(stderr, "___GIF89a begin open file=%s\n", fileName);
if(opened)
return FALSE;
ifs = fopen(fileName,"r");
if(ifs == NULL)
return FALSE;
//GIF文件标识
fread(cc, sizeof(char), 3, ifs);
cc[3] = 0;
if(strncmp(cc,"GIF",3) != 0)
goto error;
fprintf(stderr, "___GIF89a begin Signature=%s\n", cc);
//GIF文件版本号
fread(version, sizeof(char), 3, ifs);
version[3] = 0;
if(strncmp(version,"89a",3) > 0)//&& (strncmp(version,"87a",3) != 0)
goto error;
fprintf(stderr, "___GIF89a begin version=%s\n", version);
//逻辑屏幕宽度
fread((char*)&gInfo.scrWidth, sizeof(char), 2, ifs);
fread((char*)&gInfo.scrHeight, sizeof(char), 2, ifs);
fprintf(stderr, "___GIF89a begin logicwidth=%d, logicheight=%d\n", gInfo.scrWidth, gInfo.scrHeight);
if(ferror(ifs))
goto error;
fread((char*)&be, sizeof(char), 1, ifs);
if((be&0x80) != 0)
gInfo.gFlag = TRUE;
else
gInfo.gFlag = FALSE;
gInfo.colorRes = ((be&0x70)>>4)+1;
fprintf(stderr, "___GIF89a begin colorRes =%d\n", gInfo.colorRes);
if(gInfo.gFlag)
{
if((be&0x08) != 0)
gInfo.gSort = TRUE;
else
gInfo.gSort = FALSE;
gInfo.gSize = 1;
gInfo.gSize <<= ((be&0x07)+1);
}
fread((char*)&be, sizeof(char), 1, ifs);
gInfo.BKColorIdx = be;
fread((char*)&be, sizeof(char), 1, ifs);
gInfo.pixelAspectRatio = be;
if(ferror(ifs))
goto error;
if(gInfo.gFlag)
{
fread((char*)gColorTable, sizeof(char), gInfo.gSize * 3, ifs);
gInfo.gColorTable = gColorTable;
}
else
gInfo.gColorTable = NULL;
fprintf(stderr, "___GIF89a begin check frames\n");
dataStart = ftell(ifs);
if((gInfo.frames = checkFrames(ifs)) == 0)
goto error;
if(inMem)
{
if((allFrames = new FRAME[gInfo.frames]) == NULL)
goto error;
memset(allFrames, 0, sizeof(FRAME)*gInfo.frames);
fprintf(stderr, "___GIF89a begin get all frames\n");
if(!getAllFrames(ifs))
{
delete[] allFrames;
allFrames = NULL;
goto error;
}
fclose(ifs);
}
opened = TRUE;
return TRUE;
error:
fclose(ifs);
return FALSE;
}
UINT CGif89a::checkFrames(FILE* ifs)
{
BYTE be;
BOOL fileEnd = FALSE;
UINT frames=0;
long pos;
fprintf(stderr, "___GIF89a checkframes begin \n");
pos = ftell(ifs);
while(!feof(ifs) && !fileEnd)
{
fread((char*)&be,sizeof(char), 1, ifs);
switch(be)
{
case 0x21:
{
fread((char*)&be,sizeof(char), 1, ifs);
switch(be)
{ case 0xf9:
case 0xfe:
case 0x01:
case 0xff:
while(!feof(ifs))
{
fread((char*)&be,sizeof(be), 1, ifs);
if(be == 0)
break;
fseek(ifs, be, SEEK_CUR);
}
break;
default:
return 0;
}
break;
}
case 0x2c:
{
BYTE bp;
BOOL lFlag=FALSE;
UINT lSize=1;
frames++;
fseek(ifs, 8, SEEK_CUR);
fread((char*)&bp, sizeof(char), 1, ifs);
if((bp&0x80) != 0)
lFlag = TRUE;
lSize <<= ((bp&0x07)+1);
if(lFlag)
fseek(ifs, lSize*3, SEEK_CUR);
if(ferror(ifs))
return 0;
fread((char*)&be, sizeof(char), 1, ifs);
while(!feof(ifs))
{
fread((char*)&be,sizeof(be), 1, ifs);
if(be == 0)
break;
fseek(ifs, be, SEEK_CUR);
}
break;
}
case 0x3b:
fileEnd = TRUE;
break;
case 0x00:
break;
default:
return 0;
}
}
fseek(ifs, pos, SEEK_SET);
fprintf(stderr, "___GIF89a checkframes end \n");
return frames;
}
int CGif89a::GetDataBlock(FILE *src, unsigned char *buf)
{
unsigned char count;
if (!fread(&count, 1, 1, src))
return 0;
ZeroDataBlock = count == 0;
if ((count != 0) && (!fread(buf, count, 1, src)))
return 0;
return count;
}
int CGif89a::GetCode(FILE *src, int code_size, int flag)
{
static unsigned char buf[280];
static int curbit, lastbit, done, last_byte;
int i, j, ret;
unsigned char count;
if (flag)
{
curbit = 0;
lastbit = 0;
done = FALSE;
return 0;
}
if ((curbit + code_size) >= lastbit)
{
if (done)
{
if (curbit >= lastbit)
return -1;
}
buf[0] = buf[last_byte - 2];
buf[1] = buf[last_byte - 1];
if ((count = GetDataBlock(src, &buf[2])) == 0)
done = TRUE;
last_byte = 2 + count;
curbit = (curbit - lastbit) + 16;
lastbit = (2 + count) * 8;
}
ret = 0;
for (i = curbit, j = 0; j < code_size; ++i, ++j)
ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
curbit += code_size;
return ret;
}
int CGif89a::bmpComputePitch (int bpp, Uint32 width, Uint32* pitch, BOOL does_round)
{
Uint32 linesize;
int bytespp = 1;
if(bpp == 1)
linesize = PIX2BYTES (width);
else if(bpp <= 4)
linesize = PIX2BYTES (width << 2);
else if (bpp <= 8)
linesize = width;
else if(bpp <= 16) {
linesize = width * 2;
bytespp = 2;
} else if(bpp <= 24) {
linesize = width * 3;
bytespp = 3;
} else {
linesize = width * 4;
bytespp = 4;
}
/* rows are DWORD right aligned*/
if (does_round)
*pitch = (linesize + 3) & -4;
else
*pitch = linesize;
return bytespp;
}
int CGif89a::LWZReadByte (FILE *src, int flag, int input_code_size)
{
int code, incode;
register int i;
static int fresh = FALSE;
static int code_size, set_code_size;
static int max_code, max_code_size;
static int firstcode, oldcode;
static int clear_code, end_code;
static int table[2][(1 << MAX_LWZ_BITS)];
static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
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;
GetCode(src, 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 = GetCode(src, code_size, FALSE);
} while (firstcode == clear_code);
return firstcode;
}
if (sp > stack)
return *--sp;
while ((code = GetCode(src, 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 = GetCode(src, code_size, FALSE);
return firstcode;
}
else if (code == end_code)
{
int count;
unsigned char buf[260];
if (ZeroDataBlock)
return -2;
while ((count = GetDataBlock(src, buf)) > 0);
if (count != 0) {
/*
* fprintf (stderr,"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])
fprintf (stderr,"load_gif: circular table entry\n");
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;
}
int CGif89a::ReadImage (FILE* src, MYBITMAP* bmp, FRAME * f, int ignore)
{
unsigned char c;
int v;
int xpos = 0, ypos = 0, pass = 0;
/*initialize the compression routines*/
if (!fread(&c, sizeof(char), 1, src))
{
fprintf (stderr,"load_gif: eof on image data\n");
return -1;
}
if (LWZReadByte(src, TRUE, c) < 0)
{
fprintf (stderr,"load_gif: error reading image\n");
return -1;
}
/*if this is an "uninteresting picture" ignore it.*/
if (ignore)
{
while (LWZReadByte(src, FALSE, c) >= 0);
return -0;
}
/*image = imagenewcmap(len, height, cmapsize);*/
bmp->w = f->imageWidth;
bmp->h = f->imageHeight;
bmp->flags = MYBMP_FLOW_DOWN;
if (f->ctrlExt.trsFlag)
{
bmp->flags |= MYBMP_TRANSPARENT;
bmp->transparent = f->ctrlExt.trsColorIndex;
}
bmp->frames = 1;
bmp->depth = 8;
bmpComputePitch (bmp->depth, bmp->w, &bmp->pitch, TRUE);
bmp->bits = malloc (bmp->h * bmp->pitch);
if(!bmp->bits)
return -1;
while ((v = LWZReadByte(src, FALSE, c)) >= 0)
{
#if 0
int index = (ypos) * bmp->pitch + (xpos)*3;
bmp->bits[index + 0 ] = ImageDesc->ColorMap[CM_RED][v];
bmp->bits[index + 1 ] = ImageDesc->ColorMap[CM_GREEN][v];
bmp->bits[index + 2 ] = ImageDesc->ColorMap[CM_BLUE][v];
#else
bmp->bits[ypos * bmp->pitch + xpos] = v;
#endif
++xpos;
if (xpos == f->imageWidth)
{
xpos = 0;
if (f->interlaceFlag)
{
switch (pass)
{
case 0:
case 1:
ypos += 8;
break;
case 2:
ypos += 4;
break;
case 3:
ypos += 2;
break;
}
if (ypos >= f->imageHeight)
{
++pass;
switch (pass)
{
case 1:
ypos = 4;
break;
case 2:
ypos = 2;
break;
case 3:
ypos = 1;
break;
default:
goto fini;
}
}
}
else
{
++ypos;
}
}
if (ypos >= f->imageHeight)
break;
}
fini:
return 0;
}
BOOL CGif89a::getAllFrames(FILE* ifs)
{
BYTE be;
BOOL fileEnd = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -