giflib521 图形解码

余生颓废 提交于 2020-02-27 02:50:04

giflib5.2.1 图形解码 ` 如果gif文件已读取到了内存,设置一个读取内存的函数,解码时会调用这个函数读取数据,一直向前读,不会回退

	static int gifReadFunc(GifFileType* gifFile,GifByteType* buf,int size)
	{
		GIF_DATA_T* gifData = (GIF_DATA_T*)gifFile->UserData;	
		if(gifData->pBuf + size <= gifData->pBufEnd)
		{
			memcpy(buf,gifData->pBuf,size);
			gifData->pBuf += size;
			return size;
		}	
		return -1;	
	}

	//函数解码入口,从文件解码比较简单,从不处理了。
		void decode(char* pBuf,int bufLen)
		{
			gifData->pBuf = pBuf;
			gifData->pBufEnd = pBuf + bufLen;
		   gifData->GifFile = DGifOpen((void*)gifData, gifReadFunc, &Error);
		}

//如果需要将解码后的数据转换成RGB色彩数据 参考gif2rgb.c 这个文件有个函数

static void GIF2RGB(int NumFiles, char *FileName, 
			bool OneFileFlag, 
			char *OutFileName)
			{
				 //其他省略
				 switch (RecordType) {
		case IMAGE_DESC_RECORD_TYPE:
		if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
			PrintGifError(GifFile->Error);
			exit(EXIT_FAILURE);
		}
	Row = GifFile->Image.Top; /* Image Position relative to Screen. */
	Col = GifFile->Image.Left;
	Width = GifFile->Image.Width;
	Height = GifFile->Image.Height;
	GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
	    PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
	if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||
	   GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) {
	    fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n",ImageNum);
	    exit(EXIT_FAILURE);
	}
	if (GifFile->Image.Interlace) {
	    /* Need to perform 4 passes on the images: */
	    for (Count = i = 0; i < 4; i++)
		for (j = Row + InterlacedOffset[i]; j < Row + Height;
					 j += InterlacedJumps[i]) {
		    GifQprintf("\b\b\b\b%-4d", Count++);
		    if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
			Width) == GIF_ERROR) {
			PrintGifError(GifFile->Error);
			exit(EXIT_FAILURE);
		    }
		}
	}
	else {
	    for (i = 0; i < Height; i++) {
		GifQprintf("\b\b\b\b%-4d", i);
		if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
			Width) == GIF_ERROR) {
		    PrintGifError(GifFile->Error);
		    exit(EXIT_FAILURE);
		}
	    }
	}
	//上面的代码,已解将颜色索引存储在ScreenBuffer这里面了
	//在此调用 DumpScreen2RGB,可得到每帧的图像数据
	// DumpScreen2RGB 函数中关键代码
	/*
if ((Buffer = (unsigned char *) malloc(ScreenWidth * 3)) == NULL)
        GIF_EXIT("Failed to allocate memory required, aborted.");
    for (i = 0; i < ScreenHeight; i++) {
        GifRow = ScreenBuffer[i];
        GifQprintf("\b\b\b\b%-4d", ScreenHeight - i);
        for (j = 0, BufferP = Buffer; j < ScreenWidth; j++) {
            ColorMapEntry = &ColorMap->Colors[GifRow[j]];
			//将rgb色彩赋值到了BufferP 得到的是图像色彩数据
			//这里没有对图像控制块的处理,后面可在此添加一段
            *BufferP++ = ColorMapEntry->Red;
            *BufferP++ = ColorMapEntry->Green;
            *BufferP++ = ColorMapEntry->Blue;
        }
        if (fwrite(Buffer, ScreenWidth * 3, 1, rgbfp[0]) != 1)
            GIF_EXIT("Write to file(s) failed.");
    }
	*/
	break;
	 //对扩展块进行处理
		case EXTENSION_RECORD_TYPE:
			   /* Skip any extension blocks in file: */
			   #if 0
				   if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
					    return JXW_FALSE;
				   }
				   while (Extension != NULL) {
					   if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
						    return JXW_FALSE;
					   }
				   }
				#endif
                  //下面处理了所有的扩展块
			    if (DGifGetExtension(GifFile,&ExtCode,&Extension) == GIF_ERROR)	
			  	{				
					return JXW_FALSE;
				}
			  
				if (Extension != NULL) 
				{
				  if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,&GifFile->ExtensionBlocks, ExtCode, Extension[0], &Extension[1]) == GIF_ERROR)
				  {
				    return JXW_FALSE;
				  }	
				}
				
				for (;;) 
				{
				  if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR)
				  {
				   	return JXW_FALSE;
				  }	
				  if (Extension == NULL)
				      break;
				  /* Continue the extension block */
				  if (Extension != NULL)
				      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
							       &GifFile->ExtensionBlocks,
							       CONTINUE_EXT_FUNC_CODE, 
							       Extension[0], &Extension[1]) == GIF_ERROR)
				              return JXW_FALSE;
				}
		
		}

//在转换颜色为图片帧数据时,对图形扩展块的处理如下,可处理透明色 //图形扩展块要跳过,否则会留下黑色块数据

if(GifFile->ExtensionBlocks != NULL && GifFile->ExtensionBlockCount>0)
{
 	ExtensionBlocks= GifFile->ExtensionBlocks +GifFile->ExtensionBlockCount-1;

	if(ExtensionBlocks != NULL)		{
	
		if(ExtensionBlocks->Function == GRAPHICS_EXT_FUNC_CODE)
		{
		   //初始化图像控制块的值
			GCB.DisposalMode = DISPOSAL_UNSPECIFIED;
		    GCB.UserInputFlag = false;
		    GCB.DelayTime = 0;//这里是延迟时间
		    GCB.TransparentColor = NO_TRANSPARENT_COLOR;//透明色索引
			if(DGifExtensionToGCB(ExtensionBlocks->ByteCount, ExtensionBlocks->Bytes, &GCB)!=GIF_ERROR)
			{//GCB的值会发生变化,可以分别查看,
				flag = JXW_TRUE;					
			}
		}
	}		
}	

for (i = 0; i < GifFile->SHeight; i++) {
	GifRow = gifData->ScreenBuffer[i];
	BufferP = Buffer+i* lineBytes;//下一行数据起始位置
	for (j = 0; j < GifFile->SWidth; j++) {
		if(flag == JXW_TRUE && GCB.TransparentColor==GifRow[j])
		{
			BufferP +=3;
			continue;
		}			
		ColorMapEntry = &ColorMap->Colors[GifRow[j]];
		*BufferP++ = ColorMapEntry->Red;
		*BufferP++ = ColorMapEntry->Green;
		*BufferP++ = ColorMapEntry->Blue;
	}		
}

移植编译只需如下文件即可
	SOURCES = 
	   dgif_lib.c //解码文件
		egif_lib.c // 此文件可选 编 码gif文件才需要,解码可以不用
		gifalloc.c 
		gif_err.c 
		gif_font.c  //此文件可选
		gif_hash.c 
		openbsd-reallocarray.c
		//头文件
	HEADERS = gif_hash.h  gif_lib.h  gif_lib_private.h

参考: https://www.oschina.net/question/12_58381?sort=default https://sourceforge.net/projects/giflib/ 下载 giflib

`

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!