音视频入门-19-使用giflib处理GIF图片
source link: https://segmentfault.com/a/1190000038934045
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
GIFLIB
上一篇 【手动生成一张GIF图片】 , 自己生成了一张 GIF 动态图 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
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。
参考资料:
How do I get the RGB colour data from a GIFLIB SavedImage structure
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK