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
`
来源:oschina
链接:https://my.oschina.net/u/263768/blog/3158768