📄 gif_pic.c
字号:
/********************************************************************/
/* 本软件所有权归深圳诺亚舟软件有限公司,任何未经 */
/* 授权使用或复制均属侵权行为,本公司有权予以追究。 */
/* 特 此 审 明! */
/* 文件名: Forula.h */
/* 功 能: 图片预览窗口,GIF图片处理程序 */
/* 版 本: V0.10 */
/* 作 者: */
/********************************************************************/
#include "..\\noahsys\\noahsys.h"
#include "..\\neplayer\\nepgdi.h"
#include "gif_pic.h"
#define GIFSIGN "GIF89a"
#define LZW_MAXCODES 4096
#define LZW_MAXBITS 12
#define TABLESIZES 4999
#define NOCODE -1
#define UINT_MAX 65536
#define TIMER_DELAY 20 //一个timer周期的时间
typedef struct{
BYTE *BlockBuf;
INT32 *EncodeTable;
INT32 InitBits;
INT32 ClearCode;
INT32 EofCode;
INT32 Encode;
INT32 RunBits;
INT32 MaxCodeSize;
INT32 ByteCount;
INT32 ShiftBits;
DWORD TempCode;
}LZWEncodeType;
static INT32 MaskCode[] = {
0x0000,0x0001,0x0003,0x0007,
0x000f,0x001f,0x003f,0x007f,
0x00ff,0x01ff,0x03ff,0x07ff,
0x0fff
};
static INT32 LineStart[] = {0,4,2,1};
static INT32 RowCount[] = {8,8,4,2};
static void GetGifLine(Image *Img, BYTE* LineBuf, WORD LineCount, WORD LineBytes);
static int DecodeGifImage(Image *Img, PFILE File, BYTE Mode );
HPICVIEW hPicview;
/***************************************************
功能: 根据所传入图象文件的名称,先申请所需要的Image数据结构
存储单元,在读取该文件内的识别信息和图象数据
输入: FileName ==> GIF图象文件名
输出:
返回:
成功时,返回申请给Image数据结构的存贮单元指针
失败时,则返回NULL值
***************************************************/
Image *ImageGifFileRead(PFILE File)
{
Image *Img = NULL;
INT32 RetVal = SUCCESS;
char ByteBuf[16]; //= NULL;
char *Palette = NULL;
BYTE Lable;
WORD Type,GColorBits,ColorBytes;
hPicview->nMaxPic = 0;
//申请12个字节,用来保存GIF的文件头
// if( (ByteBuf = (BYTE*)NepMalloc(14)) == NULL )
// {
// hPicview->fError = MEMERROR;
// RetVal = MEMERROR;
// return Img;
// }
if( NepFsRead(File,ByteBuf,13) != 13)
{
hPicview->fError = READERROR;
RetVal = READERROR;
return Img;
}
/* 读取表头信息 */
if( !RetVal && strncmp(ByteBuf,"GIF",3) != 0 )
{
hPicview->fError = LABELERROR;
RetVal = LABELERROR;
return Img;
}
else
{ //得到全局调色板的个数
GColorBits = (ByteBuf[10] & 0x07 ) + 1;
ColorBytes = 3 * ( 1 << GColorBits);
//根据全居调色板的颜色个数,设置图象显得显示模式
if( GColorBits == 1 )
Type = 1;
else if( GColorBits == 4 )
Type = 2;
else if( GColorBits == 8 )
Type = 3;
else
{
Type = 0;
hPicview->fError = COLORERROR;
RetVal = COLORERROR;
return Img;
}
/* 读取通用调色板数据 */
if( ByteBuf[10] & 0x80 )
{
if( (Palette = (BYTE*)NepMalloc(ColorBytes))== NULL)
{
hPicview->fError = MEMERROR;
RetVal = MEMERROR;
return Img;
}
else
{
if( NepFsRead(File,Palette,ColorBytes) != ColorBytes )
{
NepFree(Palette);
Palette = NULL;
hPicview->fError = LABELERROR;
RetVal = LABELERROR;
return Img;
}
//保存全局颜色变量
memcpy(hPicview->pExternPattle,Palette,ColorBytes);
hPicview->nColorBytes = 1 << GColorBits;
NepFree(Palette);
Palette = NULL;
}
}
}
NepFsRead(File,&Lable,1);
while( !RetVal && (Lable == ',' || Lable == '!' || Lable == 0 ))
{
if( Lable == ',' )
{
//WORD* WordBuf;
WORD Width;
WORD Height;
WORD Color;
WORD LColorBits;
//读取图象描述块的结构
if( !RetVal && NepFsRead(File,ByteBuf,9) != 9 )
{
hPicview->fError = LABELERROR;
RetVal = LABELERROR;
return Img;
}
//WordBuf = (WORD*)ByteBuf;
//Width = WordBuf[2]; //图象的宽度
//Height = WordBuf[3]; //图象的高度
Width = ((WORD)ByteBuf[5]<<8) + (ByteBuf[4]&0x00ff);
Height = ((WORD)ByteBuf[7]<<8) + (ByteBuf[6]&0x00ff);
LColorBits = (ByteBuf[8] & 0x07 ) + 1; //得到图象是否存在局部调色板标志位
//读取图象的局部调色板
if( !RetVal && ByteBuf[8] & 0x80 )
{
if( LColorBits == 1 )
Type = 1;
else if( LColorBits == 4 )
Type = 2;
else if( LColorBits == 8 )
Type = 3;
else
{
Type = 0;
hPicview->fError = COLORERROR;
RetVal = COLORERROR;
return Img;
}
ColorBytes = 3 * ( 1<< LColorBits );
if( Palette != NULL && LColorBits > GColorBits )
{
NepFree( Palette );
Palette = NULL;
}
/* 读取局部调色板数据 */
if( Palette == NULL )
{
if( (Palette = (BYTE*)NepMalloc(ColorBytes)) ==NULL )
{
hPicview->fError = MEMERROR;
RetVal = MEMERROR;
return NULL;
}
else
{
if( !RetVal && NepFsRead(File,Palette,ColorBytes) != ColorBytes )
{
//NepFree(Palette);
//Palette = NULL;
hPicview->fError = READERROR;
RetVal = READERROR;
return NULL;
}
}
}
}
//判断是否存在调色板(无论是局部调色板还是全局调色板)
if( Palette == NULL )
Color = 0;
else
Color = 1;
//申请image
if( !RetVal && Type && (Img = ImageAlloc(Type,Width,Height,1)) != NULL )
{
//判断是否需要初始化调色板
if( Color )
{
if( ByteBuf[8] & 0x80)
{ //保存局部颜色变量
memcpy( Img->Color, Palette,ColorBytes);
NepFree(Palette);
Palette = NULL;
Img->ColorBytes = 1<< LColorBits;
}
else
{ //保存全局颜色变量
memcpy( Img->Color, hPicview->pExternPattle,ColorBytes);
Img->ColorBytes = hPicview->nColorBytes;
}
}
else
{ //保存全局颜色变量
memcpy( Img->Color, hPicview->pExternPattle,ColorBytes);
Img->ColorBytes = hPicview->nColorBytes;
}
//利用LZW解压缩方式解压图象数据
if( RetVal = DecodeGifImage(Img,File, ByteBuf[8] & 0x40 ))
{ //解压失败,退出
GifImageFree(Img);
Img = NULL;
}
else
{
//保存GIF的一桢图片数据
hPicview->pImg[hPicview->nMaxPic] = Img;
hPicview->nMaxPic++;
}
}
else
{
if( !RetVal )
{
if(Type)
{
hPicview->fError = MEMERROR;
RetVal = MEMERROR;
}
else
{
hPicview->fError = COLORERROR;
RetVal = COLORERROR;
}
}
}
}
else if( Lable == '!' )
{
//图形控制模块,0x21 + 0xf9
//无格式文本扩展模块,0x21 + 0x01
//注释模块,0x21 + 0xfe
//应用扩展模块,0x21 + 0xff
//匀以0x00结束
BYTE Data;
NepFsRead(File,&Data,1);
if( Data == 0xf9 )
{ //图形控制模块,0x21 + 0xf9
BYTE length;
BYTE* pInfo;
//
NepFsRead(File,&length,1); //读取块的长度
pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
NepFsRead(File,pInfo,length); //读取块信息
//计算下一副图片的时间长度
hPicview->PicTimeDelayBuf[hPicview->nMaxPic] = (pInfo[2]<<8) + pInfo[3];
hPicview->PicTimeDelayBuf[hPicview->nMaxPic] /= TIMER_DELAY;
if( hPicview->PicTimeDelayBuf[hPicview->nMaxPic] == 0 )
hPicview->PicTimeDelayBuf[hPicview->nMaxPic] = 1;
NepFree(pInfo);
}
else if( Data == 0xff )
{ //应用扩展模块,0x21 + 0xff
BYTE length;
BYTE* pInfo;
//读取Application Identifier和Appl. Authentication Code
//Application Identifier为8个字节,用来提供程序设计者的补充命名字
//Appl. Authentication Code为3个字节,用来做扩展标识符号
NepFsRead(File,&length,1); //读取块的长度
pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
NepFsRead(File,pInfo,length); //读取块信息
NepFree(pInfo);
//读取Application Data
//2007-7-21 tqh modify
//修改原因,应用扩展块的结构为11个字节的标记+N个数据子块
NepFsRead(File,&Data,1);
while( Data != 0 )
{
//读取数据块的大小
pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * Data);
NepFsRead(File,pInfo,Data); //读取块信息
NepFree(pInfo);
NepFsRead(File,&Data,1);
}
}
else if( Data == 0x01 )
{ //无格式文本扩展模块,0x21 + 0x01
BYTE length;
BYTE* pInfo;
NepFsRead(File,&length,1); //读取块的长度
pInfo = (BYTE*)NepMalloc(sizeof(BYTE) * length);
NepFsRead(File,pInfo,length); //读取块信息
NepFree(pInfo);
}
else
{ //注释模块,0x21 + 0xfe
while( Data != 0 )
{
NepFsRead(File,&Data,1);
}
}
}
NepFsRead(File,&Lable,1);
}
if(Palette != NULL)
{
NepFree(Palette);
Palette = NULL;
}
// if( ByteBuf!= NULL )
// {
// NepFree( ByteBuf );
// ByteBuf = NULL;
// }
return Img;
}
/***************************************************
功能: 解译GIF图象文件内以LZW压缩法编码的图象数据
存储单元,在读取该文件内的识别信息和图象数据
输入: Img ==> 存放Image数据结构的存储单元指针
File ==> 图象文件的文件指针
mode ==> 设定图象数据的处理方式
0x00 顺序排列
0x40 交叉排列
输出:
返回:
成功时,返回SUCCESS
失败时,则返回错误代码
***************************************************/
/*static*/ int DecodeGifImage(Image *Img, PFILE File, BYTE Mode )
{
BYTE *SuffixTable; //字尾表
BYTE *StackTable; //堆栈表
BYTE *LineBuf;
BYTE *BlockBuf;
BYTE *PrefixTable; //字头表
INT32 TableIndex = 0; //代表字头及字尾索引值,也是字符对代码的启始值
INT32 StackIndex = 0;
INT32 InitBits = 0; //代表图象点的Bits数
INT32 EofCode = 0; //代表结束码
INT32 ClearCode = 0; //代表清除码
INT32 RunBits = 0; //代表压缩数据的长度
INT32 MaxCodeSize = 0;
INT32 CurrentCode = 0;
INT32 LastCode = 0;
INT32 PrefixCode = 0;
INT32 SuffixCode = 0;
INT32 BlockIndex = 0;
INT32 RetVal = SUCCESS;
WORD LineCount = 0;
WORD Pass = 0;
int DataCount = 0;
WORD ByteCount = 0;
WORD ShiftBits = 0;
WORD LineBytes = 0;
DWORD TempCode;
if( Img->Type == 1 || Img->Type == 2 )
{
LineBytes = (Img->width / 8 + (Img->width %8 ? 1:0)) * (Img->Type==2?4:1);
}
else
LineBytes = Img->width;
ByteCount = (LZW_MAXCODES<<2) + 256 + Img->width;
StackTable = (BYTE*)NepMalloc(ByteCount*2);
if( StackTable == NULL )
{
hPicview->fError = MEMERROR;
RetVal = MEMERROR;
return RetVal;
}
PrefixTable = (BYTE*)&StackTable[LZW_MAXCODES];
SuffixTable = (BYTE*)&PrefixTable[LZW_MAXCODES*2];
BlockBuf = &SuffixTable[LZW_MAXCODES];
LineBuf = &BlockBuf[256];
NepFsRead(File,&InitBits,1);
ClearCode = 1 << InitBits;
EofCode = ClearCode + 1;
RunBits = InitBits + 1;
LineCount = Pass = DataCount = ByteCount = ShiftBits = 0;
BlockIndex = 0;
TempCode = 0;
while(!RetVal)
{
while(!RetVal && ShiftBits < RunBits )
{
if( BlockIndex == DataCount )
{
BlockIndex = 0;
NepFsRead(File, &DataCount,1);
if( !RetVal && DataCount == EOF )
{
hPicview->fError = DECODEERROR;
RetVal = DECODEERROR;
}
if( !RetVal && NepFsRead(File,BlockBuf,DataCount) != DataCount )
{
hPicview->fError = DECODEERROR;
RetVal = DECODEERROR;
}
}
TempCode |= (DWORD)BlockBuf[BlockIndex++] << ShiftBits;
ShiftBits += 8;
}
CurrentCode = TempCode & MaskCode[RunBits];
TempCode >>= RunBits;
ShiftBits -= RunBits;
if( CurrentCode == EofCode )
break;
if( CurrentCode == ClearCode )
{
RunBits = InitBits + 1;
TableIndex = EofCode + 1;
MaxCodeSize = 1 << RunBits;
PrefixCode = SuffixCode = NOCODE;
}
else
{
LastCode = CurrentCode;
StackIndex = 0;
if( CurrentCode == TableIndex )
{
StackTable[StackIndex++] = SuffixCode;
CurrentCode = PrefixCode;
}
while( CurrentCode > EofCode && StackIndex < LZW_MAXCODES )
{
StackTable[StackIndex++] = SuffixTable[CurrentCode];
//CurrentCode = PrefixTable[CurrentCode];
CurrentCode = PrefixTable[2*CurrentCode] + ((WORD)PrefixTable[2*CurrentCode+1]<<8);
}
if( !RetVal && CurrentCode > EofCode || StackIndex >= LZW_MAXCODES )
{
hPicview->fError = DECODEERROR;
RetVal = DECODEERROR;
}
SuffixCode = CurrentCode;
while(!RetVal)
{
LineBuf[ByteCount++] = CurrentCode;
if( ByteCount >= Img->width )
{
GetGifLine(Img,LineBuf,LineCount,LineBytes);
ByteCount = 0 ;
if( Mode != 0 )
{
LineCount += RowCount[Pass];
if( LineCount >= Img->height)
{
Pass++;
LineCount = LineStart[Pass];
}
}
else
LineCount++;
}
if( StackIndex == 0 )
break;
CurrentCode = StackTable[--StackIndex];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -