/* * Reads the GIF screen and the global color table. */ void GIFReadScreen(struct GIFScreen *screen, FILE *stream) { unsigned char buffer[7]; GIF_TRACE(("Reading Header\n")); GIF_FREAD(buffer, 6, stream); if (memcmp(buffer, "GIF", 3) != 0) GIFError("Not a GIF file"); if ((memcmp(buffer + 3, "87a", 3) != 0) && (memcmp(buffer + 3, "89a", 3) != 0)) GIFWarning("Invalid GIF version number, not \"87a\" or \"89a\""); GIF_TRACE(("Reading Logical Screen Descriptor\n")); GIF_FREAD(buffer, 7, stream); screen->Width = GIF_GETW(buffer + 0); screen->Height = GIF_GETW(buffer + 2); screen->GlobalColorFlag = (buffer[4] & 0x80) ? 1 : 0; screen->ColorResolution = ((buffer[4] & 0x70) >> 3) + 1; screen->SortFlag = (buffer[4] & 0x08) ? 1 : 0; screen->GlobalNumColors = 2 << (buffer[4] & 0x07); screen->Background = buffer[5]; screen->PixelAspectRatio = buffer[6]; if (screen->GlobalColorFlag) { GIF_TRACE(("Reading Global Color Table\n")); GIF_FREAD(screen->GlobalColorTable, 3 * screen->GlobalNumColors, stream); } GIF_TRACE(("Validating Logical Screen Descriptor\n")); if (screen->Width == 0 || screen->Height == 0) GIFError("Invalid image dimensions"); if (screen->Background > 0) { if ((screen->GlobalColorFlag && (screen->Background >= screen->GlobalNumColors)) || !screen->GlobalColorFlag) { #if 0 /* too noisy */ GIFWarning("Invalid background color index"); #endif screen->Background = 0; } } }
static int GIFReadDataBlock(unsigned char *buffer, FILE *stream) { int count; GIF_FGETC(count, stream); DataBlockSize = count; if (count > 0) { GIF_FREAD(buffer, (unsigned int)count, stream); } return count; }
/* * Reads the next GIF image and local color table. */ static void GIFReadNextImage(struct GIFImage *image, FILE *stream) { struct GIFScreen *screen; unsigned char buffer[9]; GIF_TRACE(("Reading Local Image Descriptor\n")); GIF_FREAD(buffer, 9, stream); if (image == NULL) { GIFSkipDataBlocks(stream); return; } image->LeftPos = GIF_GETW(buffer + 0); image->TopPos = GIF_GETW(buffer + 2); image->Width = GIF_GETW(buffer + 4); image->Height = GIF_GETW(buffer + 6); image->LocalColorFlag = (buffer[8] & 0x80) ? 1 : 0; image->InterlaceFlag = (buffer[8] & 0x40) ? 1 : 0; image->SortFlag = (buffer[8] & 0x20) ? 1 : 0; image->LocalNumColors = image->LocalColorFlag ? (2 << (buffer[8] & 0x07)) : 0; if (image->LocalColorFlag) { GIF_TRACE(("Reading Local Color Table\n")); GIF_FREAD(image->LocalColorTable, 3 * image->LocalNumColors, stream); } GIF_TRACE(("Validating Logical Screen Descriptor\n")); screen = image->Screen; if (image->Width == 0 || image->Height == 0 || image->LeftPos + image->Width > screen->Width || image->TopPos + image->Height > screen->Height) GIFError("Invalid image dimensions"); GIFReadImageData(image, stream); }
//函数调用了一个定位文件和读文件的函数 //调用前将pgif->fp定位到lzw开始,初始化pgif的调色板等显示参数 void GIFShowImage(GIF *pgif) { LZW lzw; //保存lzw解压缩参数 u8 temp; GIFImageDescriptor imagedes; //gif图像描述 GraphicControlExtension gce; //图像扩展 u8 blockflag; GIF_FREAD((UINT8*)&imagedes, sizeof(GIFImageDescriptor), pgif->fp);//帧图像描述块 pgif->Interlace = imagedes.ColorFlag.InterlaceFlag; pgif->width = imagedes.Width; pgif->height = imagedes.Height; pgif->curx = 0; pgif->cury = 0; //lzw解码 GIF_FREAD(&temp, sizeof(u8),pgif->fp); //lzw编码长度 LzwInit(LzwTable, temp, &lzw,pgif->fp); //初始化管理结构体 LzwStart(&lzw,pgif); //解码输出 GIF_FSEEK(pgif->fp, 1, FSEEK_CUR); //跳过块结束标记 }
static void GIFSkipDataBlocks(FILE *stream) { int count; unsigned char buffer[GIF_UCHAR_MAX + 1]; for ( ; ; ) { GIF_FGETC(count, stream) if (count > 0) { GIF_FREAD(buffer, (unsigned int)count, stream); } else return; } }
//打开一个gif图像,需用GIFShowImage输出 //成功返回0 u8 GIFOpen(GIF *pgif,struct FileInfo *fp) { GIFLSDescriptor ls; //gif逻辑屏幕描述 u8 blockflag; //块标记 数据块:; ...... GraphicControlExtension gce; //图形扩展 pgif->fp = fp; GIF_FSEEK(pgif->fp, sizeof(GIFHeader), FSEEK_SET); //跳过文件头 GIF_FREAD((UINT8*)&ls, sizeof(GIFLSDescriptor), pgif->fp);//逻辑屏幕描述 40byte if (ls.ColorFlag.GlobalColorTableFlag) //如果有全局调色板 { // pgif->globleClrTable = new GIFRGBITEM[1 << (ls.ColorFlag.Pixel + 1)]; GIF_FREAD((UINT8*)(pgif->globleClrTable), sizeof(GIFRGBITEM)*(1 << (ls.ColorFlag.Pixel + 1)), pgif->fp); } else pgif->globleClrTable = NULL; pgif->scWidth = ls.Width; pgif->scHeight = ls.Height; pgif->bkColorIndex = ls.BackColor; pgif->DelayTime = 0; //初始化为静态图 pgif->TransparentColorFlag = 0; //默认无透明色 pgif->skimage = pgif->fp->File_CurOffset; //读取各种控制块 while (1) { GIF_FREAD(&blockflag, 1, pgif->fp); if (blockflag == ',') //帧图像数据(2C) { //保存该位置指针 return 0; } else if (blockflag == 0x21) //扩展块 { GIF_FREAD(&blockflag, 1, pgif->fp); if (blockflag == 0xF9) //图形控制扩展块 { GIF_FREAD((UINT8*)&gce, sizeof(GraphicControlExtension), pgif->fp); pgif->DelayTime = gce.DelayTime; //本帧图像延时 pgif->TransparentColorFlag = gce.Flag.TransparentColorFlag;//透明标志 pgif->DisposalMethod = gce.Flag.DisposalMethod; //处理方法 pgif->TransparentColorIndex = gce.TransparentColorIndex; //透明色引索 GIF_FSEEK(pgif->fp, 1, FSEEK_CUR); //块结束标记 } else if (blockflag == 0xFF)//应用程序扩展 { GIF_FSEEK(pgif->fp, sizeof(ApplicationExtension), FSEEK_CUR); //跳过应用数据 while (1) { GIF_FREAD(&blockflag, 1, pgif->fp); //应用程序数据大小 if (blockflag == 0)break; else GIF_FSEEK(pgif->fp, blockflag, FSEEK_CUR); } } else if (blockflag == 0xFE) //跳过注释扩展块 { while (1) { GIF_FREAD(&blockflag, 1, pgif->fp); if (blockflag == 0)break; else GIF_FSEEK(pgif->fp, blockflag, FSEEK_CUR); } } else if (blockflag == 0x01) //跳过图形文本扩展 { GIF_FSEEK(pgif->fp, sizeof(PlainTextExtension), FSEEK_CUR); while (1) { GIF_FREAD(&blockflag, 1, pgif->fp); if (blockflag == 0)break; else GIF_FSEEK(pgif->fp, blockflag, FSEEK_CUR); } } else { return 2; } } else if (blockflag == ';') //文件结束 { return 3; //文件结束 } else { return 1; } } }