音视频入门-19-使用giflib处理GIF图片

example-rainbow.gif

下面,使用 GIFLIB 分离出 GIF 每一帧的 RGB ,然后将分离出的 RGB 再合成 GIF。

GIF to RGB

GIFLIB 项目里的 gif2rgb.c 已经实现了解码 GIF -> RGB。不过 gif2rgb.c 只保存了最后一帧图片的 RGB,这里需要改造。

gif2rgb.c

gif2rgb.c 在 GIF2RGB 方法最后才调用 DumpScreen2RGB 保存 RGB。

...... static void DumpScreen2RGB(char *FileName, ColorMapObject *ColorMap, GifRowType *ScreenBuffer, int ScreenWidth, int ScreenHeight) { ...... } static void GIF2RGB(int NumFiles, char *FileName, bool OneFileFlag, char *OutFileName) { ...... /* Scan the content of the GIF file and load the image(s) in: */ do { ...... } while (RecordType != TERMINATE_RECORD_TYPE); /* Lets dump it - set the global variables required and do it: */ ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap : GifFile->SColorMap); if (ColorMap == NULL) { fprintf(stderr, "Gif Image does not have a colormap\n"); exit(EXIT_FAILURE); } /* check that the background color isn't garbage (SF bug #87) */ if (GifFile->SBackGroundColor < 0 || GifFile->SBackGroundColor >= ColorMap->ColorCount) { fprintf(stderr, "Background color out of range for colormap\n"); exit(EXIT_FAILURE); } DumpScreen2RGB(OutFileName, OneFileFlag, ColorMap, ScreenBuffer, GifFile->SWidth, GifFile->SHeight); (void)free(ScreenBuffer); if (DGifCloseFile(GifFile, &Error) == GIF_ERROR) { PrintGifError(Error); exit(EXIT_FAILURE); } } gif-to-rgb-library.c

需要把调用 DumpScreen2RGB 的位置移到循环体内 case IMAGE_DESC_RECORD_TYPE: 位置。

...... static void DumpScreen2RGB(char *FileName, ColorMapObject *ColorMap, GifRowType *ScreenBuffer, int ScreenWidth, int ScreenHeight) { ...... } static void GIF2RGB( char *FileName, char *OutFileNamePattern) { ...... do { ...... switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: ...... ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap : GifFile->SColorMap); if (ColorMap == NULL) { fprintf(stderr, "Gif Image does not have a colormap\n"); exit(EXIT_FAILURE); } /* check that the background color isn't garbage (SF bug #87) */ if (GifFile->SBackGroundColor < 0 || GifFile->SBackGroundColor >= ColorMap->ColorCount) { fprintf(stderr, "Background color out of range for colormap\n"); exit(EXIT_FAILURE); } char *name = malloc(255*sizeof(char)); sprintf(name, OutFileNamePattern, screenIndex++); printf("Final File Name: %s\n", name); DumpScreen2RGB(name, ColorMap, ScreenBuffer, GifFile->SWidth, GifFile->SHeight); break; case EXTENSION_RECORD_TYPE: ...... } } while (RecordType != TERMINATE_RECORD_TYPE); ...... } int main(int argc, char **argv) { GIF2RGB( "/Users/staff/Desktop/rainbow.gif", "/Users/staff/Desktop/rainbow-%d.rgb"); return 0; } 查看 GIF -> RGB 结果

根据 【手动生成一张GIF图片】 生成的 GIF rainbow.gif 含有 7 个图像,所以会得到 7 个 .RGB 文件。

ffplay 查看 RGB 文件:

ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-0.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-1.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-2.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-3.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-4.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-5.rgb ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-6.rgb

decode-gif-to-rgb.jpg

RGB to GIF

上面,从 rainbow.gif 中提取出了 7 个 RGB 文件。
下面,读取这 7 个 RGB 文件,使用 GIFLIB 编码成 GIF 动态图。

// LoadRGB 是 gif2rgb.c 文件中的方法 static void LoadRGB(char *FileName, GifByteType **RedBuffer, GifByteType **GreenBuffer, GifByteType **BlueBuffer, int Width, int Height) { ...... } // gif2rgb.c 文件中 RGB2GIF 只实现了 RGB to GIF 静态图功能 // 这里做了修改,可以生成动态 GIF static void RGB2GIF(char **RGBFileNames, int NumOfRGBFile, char *GIFFileName, int ExpNumOfColors, int Width, int Height) { int ColorMapSize; GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL, *OutputBuffer = NULL; ColorMapObject *OutputColorMap = NULL; // 打开输出的 GIF 文件 int Error; GifFileType *GifFile; if ((GifFile = EGifOpenFileName(GIFFileName, false, &Error)) == NULL) { PrintGifError(Error); exit(EXIT_FAILURE); } GifFile->SWidth = Width; GifFile->SHeight = Height; GifFile->SColorResolution = 1; GifFile->SBackGroundColor = 0; GifFile->SColorMap = NULL; for(int i = 0; i < NumOfRGBFile; i++) { ColorMapSize = 1 << ExpNumOfColors; printf("读取 RGB 文件:%d\n", i); LoadRGB(RGBFileNames[i], &RedBuffer, &GreenBuffer, &BlueBuffer, Width, Height); if ((OutputColorMap = GifMakeMapObject(ColorMapSize, NULL)) == NULL || (OutputBuffer = (GifByteType *) malloc(Width * Height * sizeof(GifByteType))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (GifQuantizeBuffer(Width, Height, &ColorMapSize, RedBuffer, GreenBuffer, BlueBuffer, OutputBuffer, OutputColorMap->Colors) == GIF_ERROR) exit(EXIT_FAILURE); free((char *) RedBuffer); free((char *) GreenBuffer); free((char *) BlueBuffer); printf("MakeSavedImage:%d\n", i); SavedImage *image = GifMakeSavedImage(GifFile, NULL); GifImageDesc *imageDesc = (GifImageDesc *) malloc(sizeof(GifImageDesc)); imageDesc->Left = 0; imageDesc->Top = 0; imageDesc->Width = Width; imageDesc->Height = Height; imageDesc->Interlace = false; imageDesc->ColorMap = OutputColorMap; image->ImageDesc = *imageDesc; image->RasterBits = OutputBuffer; GraphicsControlBlock *GCB = (GraphicsControlBlock *) malloc(sizeof(GraphicsControlBlock)); GCB->DisposalMode = DISPOSAL_UNSPECIFIED; GCB->DelayTime = 50; GCB->UserInputFlag = false; GCB->TransparentColor = NO_TRANSPARENT_COLOR; printf("GCBToSaved:%d\n", i); EGifGCBToSavedExtension(GCB, GifFile, i); } printf("输出文件。"); // 输出文件 EGifSpew(GifFile); } int main(int argc, char **argv) { char *rgbFiles[] = { "/Users/staff/Desktop/rainbow-0.rgb", "/Users/staff/Desktop/rainbow-1.rgb", "/Users/staff/Desktop/rainbow-2.rgb", "/Users/staff/Desktop/rainbow-3.rgb", "/Users/staff/Desktop/rainbow-4.rgb", "/Users/staff/Desktop/rainbow-5.rgb", "/Users/staff/Desktop/rainbow-6.rgb", }; RGB2GIF(rgbFiles, 7, "/Users/staff/Desktop/rainbow0.gif", 3, 700, 700); return 0; } 查看 RGB -> GIF 结果

成功实现了 GIF -> RGB(s) -> GIF。

gif-rgb-gif.jpg

encode-rgb-to-gif.jpg

代码:
audio-video-blog-demos

参考资料:

图像解码之三——giflib解码gif图片

How do I get the RGB colour data from a GIFLIB SavedImage structure

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpddjj.html