[gifx.exe] -- version 1.0 (批处理 游戏制作必备)
Windows平台下的gif拼接、解包、格式转换、透明、裁剪工具。建议使用vs编译源码以获得不依赖dll的独立版本。对于不方便编译的坛友,请直接下载7KB附件。
链接: https://pan.baidu.com/s/1D7qKZB_8MWKkpOgWz4CM4Q?pwd=t8m3
(外部链接效果图)
GIFX.EXE (CONSOLE GIF JOIN TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0)
摘要:
=========================================================================
GIFX.EXE,是一款奇异的命令行gif拼接、解包利器。 能将gif动态图的每一帧拼接
为一整张静态图,亦能将gif文件解包。同时也支持其他图片格式的转换、裁剪、透
明色处理等操作。
=========================================================================
版本:
VERSION 1.0
用法:
-------------------------------------------------------------------------
gifx [输入文件]
-o [输出文件]
-c [[裁剪区域X坐标],[裁剪区域Y坐标],[裁剪区域宽度],[裁剪区域高度]]
-s [[显示宽度],[显示高度]]
-i [帧间隔]
-j [跳过的帧]
-t [[R],[G],[B]]
-m [l|v|x]
-------------------------------------------------------------------------
示例:
-------------------------------------------------------------------------
REM 解包test.gif并设白色为透明色,输出为png格式
gifx test.gif -o.png -t255,255,255 -mx
REM 解包test.gif并拼接每一帧为一整张纵向图,输出为jpg格式
gifx test.gif -o.\out.jpg -t255,255,255 -mv
REM 解包test.gif每帧为宽100、高300的位图并拼接每一帧为一整张横向图,输出为bmp格式
gifx test.gif -o.\out.jpg -s100,300 -ml
REM 图片格式转换
gifx test.png -o.\test.jpg
REM 图片裁剪
gifx test.png -c20,30,100,300 -s100,600 -o.\out.png
REM 设置某色为透明色,颜色为RGB格式,中间用英文逗号隔开
gifx test.png -t255,255,255 -o.\out.png
...
-------------------------------------------------------------------------
英译:
-------------------------------------------------------------------------
Gifx v1.0 - Console gif tool - Copyright (C) 2017-2019 by Happy
Usage:
gifx [input_file] -c[cut_area] -s[image_size]
-i[interval_number] -j[jump_number]
-t[transparent_color]
-m[mode_flag]
-o[output_file]
General options:
-c[[x],[y],[width],[height]] Cut area
-s[[width],[height]] Image size
-i[interval] The number of intervals
-j[skip] Skip the number of sheets
-o[path] Output file
-t[[R],[G],[B]] Transparent color
-m[l|v|x] Set the gif processing mode
-h Show help information
Official website:
http://www.bathome.net/thread-16666-6-6.html
-------------------------------------------------------------------------
FRI SEP 08 2017 17:28:16 GMT+0800
原创代码:- /*
- CONSOLE GIF JOIN TOOL, GIFX.EXE COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0
- FRI SEP 08 2017 17:28:16 GMT+0800
- **************************************************************************
- g++ gifx.cpp -lgdiplus -lgdi32 -lole32 -municode -O2 -static REM For MINGW
- cl gifx.cpp /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /MT REM For VS
- **************************************************************************
- */
-
- #if !defined(_UNICODE) && !defined(UNICODE)
- #define _UNICODE USED
- #define UNICODE USED
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <windows.h>
- #include <tchar.h>
-
- #if !defined(WIN32) && !defined(__WIN32__)
- #error Only run on windows system
- #endif
-
- #if defined(_MSC_VER)
- #include <Gdiplus.h>
- #pragma comment(lib, "Gdi32.lib")
- #pragma comment(lib, "Gdiplus.lib")
- #pragma comment(lib, "Ole32.lib")
- #else
- #include <gdiplus\gdiplus.h>
- #ifndef bool
- #include <stdbool.h>
- #endif
- #endif
-
- // 使用GDI+命名空间
- using namespace Gdiplus;
-
- // 定义帮助说明
- #define HELP_INFORMATION _T("\
- Gifx v1.0 - Console gif tool - Copyright (C) 2017-2019 by Happy\n\
- Usage:\n\
- gifx [input_file] -c[cut_area] -s[image_size]\n\
- -i[interval_number] -j[jump_number]\n\
- -t[transparent_color]\n\
- -m[mode_flag]\n\
- -o[output_file]\n\
- \n\
- General options:\n\
- -c[[x],[y],[width],[height]] Cut area\n\
- -s[[width],[height]] Image size\n\
- -i[interval] The number of intervals\n\
- -j[skip] Skip the number of sheets\n\
- -o[path] Output file\n\
- -t[[R],[G],[B]] Transparent color\n\
- -m[l|v|x] Set the gif processing mode\n\
- -h Show help information\n\
- \n\
- Official website:\n\
- http://www.bathome.net/thread-16666-6-6.html\n\
- ")
-
- // 开关解析宏名
- #define _OPT_TEOF -1
- #define _OPT_TILL -2
- #define _OPT_TERR -3
-
- // 开关解析变量
- int OPTIND=1, OPTOPT, UNOPTIND=-1;
- TCHAR* OPTARG;
-
- #if defined(_UNICODE) || defined(UNICODE)
- #define TCHARFORMAT WCHAR
- #else
- #define TCHARFORMAT CHAR
- #endif
-
- // 判断小写字母宏TCHAR版本
- #define ISLOWERLETTER(x) ((_T('a') <= (x)) && ((x) <= _T('z')))
-
- // 图片格式关键词
- static const TCHAR* IMAGE_TYPE[] = {_T("image/bmp"), _T("image/jpeg"), _T("image/gif"), _T("image/tiff"), _T("image/png"), NULL};
- static const TCHAR* IMAGE_SUFFIX[] = {_T(".bmp"), _T(".jpg"), _T(".gif"), _T(".tif"), _T(".png"), NULL};
-
- // 引入WINAPI
- extern "C" {
- WINBASEAPI
- HWND
- APIENTRY
- GetConsoleWindow(
- VOID
- );
- }
-
- // 开关解析模块
- int _tgetopt(int nargc, TCHAR* nargv[], TCHAR* ostr)
- {
- static TCHAR* place = (TCHAR*)_T("");
- static TCHAR* lastostr = NULL;
- register TCHAR* oli;
-
- if(ostr != lastostr)
- {
- lastostr = ostr;
- place=(TCHAR*)_T("");
- }
-
- if(!*place)
- {
- if
- (
- (OPTIND >= nargc) ||
- (*(place=nargv[OPTIND]) != (TCHAR)_T('-')) ||
- (!*(++place))
- )
- {
- if(*place != (TCHAR)_T('-') && OPTIND <nargc)
- {
- place = (TCHAR*)_T("");
- if(UNOPTIND == -1)
- {
- UNOPTIND = OPTIND++;
- return _OPT_TILL;
- }
- else
- {
- return _OPT_TERR;
- }
- }
-
- place = (TCHAR*)_T("");
- return _OPT_TEOF;
- }
- if (*place == (TCHAR)_T('-') && *(place+1) == (TCHAR)_T('\0'))
- {
- ++OPTIND;
- return _OPT_TEOF;
- }
- }
-
- if (
- (OPTOPT=*place++) == (TCHAR)_T(':') ||
- !(oli=(TCHAR*)_tcschr((TCHARFORMAT*)ostr, (TCHAR)OPTOPT))
- )
- {
- if(!*place)
- {
- ++OPTIND;
- }
- }
-
- if ((oli != NULL) && (*(++oli) != (TCHAR)_T(':')))
- {
- OPTARG=NULL;
- if(!*place)
- {
- ++OPTIND;
- }
- }
- else
- {
- if((*place != _T('\0')))
- {
- OPTARG = place;
- }
- else if(nargc <= ++OPTIND)
- {
- place = (TCHAR*)_T("");
- }
- else
- {
- OPTARG = nargv[OPTIND];
- }
- place = (TCHAR*)_T("");
- ++OPTIND;
- }
-
- if(*OPTARG == _T('-')){
- OPTARG = NULL;
- }
- return OPTOPT;
- }
-
- // 通用关键词识别函数
- int IdentifyKey(TCHAR* inStr, TCHAR** inKeyWords)
- {
- if (inStr == NULL)
- {
- return -1;
- }
-
- int SN = 0;
- while(inKeyWords[SN] != NULL)
- {
- TCHAR *op=inStr, *kp=inKeyWords[SN];
-
- while(*kp != _T('\0'))
- {
- if(
- ((ISLOWERLETTER(*op))?(*op-32):(*op)) != ((ISLOWERLETTER(*kp))?(*kp-32):(*kp))
- )
- {
- break;
- }
- op++;
- kp++;
- }
-
- if(*kp == _T('\0'))
- {
- if(*op == _T('\0'))
- {
- return SN;
- }
- }
-
- SN ++;
- }
- return -1;
- }
-
- // 获取编码器CLSID
- BOOL GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
- {
- UINT j, n=0, s=0;
- ImageCodecInfo* pInfo=NULL;
- GetImageEncodersSize(&n, &s);
- if(s == 0)
- {
- return FALSE;
- }
- pInfo=(ImageCodecInfo*)(malloc(s));
- if(pInfo == NULL)
- {
- return FALSE;
- }
- GetImageEncoders(n, s, pInfo);
- for(j=0; j<n; j++)
- {
- if(wcscmp(pInfo[j].MimeType, format) == 0)
- {
- *pClsid = pInfo[j].Clsid;
- free(pInfo);
- return TRUE;
- }
- }
- free(pInfo);
- return FALSE;
- }
-
- // gif拼接函数
- int JoinGif(TCHAR* inFile, TCHAR* outFile, int modeFlag, bool useTransparentColor, Color transparentColor, int cut_x, int cut_y, int cutWidth, int cutHeight, int showWidth, int showHeight, int intervalNumber, int skipNumber)
- {
- // 备份输出文件名
- TCHAR outFileS[MAX_PATH];
- _tcscpy(outFileS, outFile);
-
- // 识别扩展名
- TCHAR* outFileSuffix = _tcsrchr(outFile, _T('.'));
- int SN = IdentifyKey(outFileSuffix, (TCHAR**)IMAGE_SUFFIX);
- if(SN == -1)
- {
- _ftprintf(stderr, _T("Error output image suffix '%s'\n"), outFileSuffix);
- exit(1);
- }
-
- // 切分扩展名
- *(outFileSuffix++) = _T('\0');
-
- // 初始化GdiPlus
- ULONG_PTR gdipludToken;
- GdiplusStartupInput gdiplusInput;
- GdiplusStartup(&gdipludToken,&gdiplusInput,NULL);
-
- // 读取gif文件数据
- Image* gifImage = Image::FromFile((WCHAR*)inFile);
-
- // 获取gif原始宽高
- UINT gifWidth = gifImage->GetWidth();
- UINT gifHeight = gifImage->GetHeight();
-
- // 判断文件读取失败
- if((gifWidth & gifHeight) == 0)
- {
- _ftprintf(stderr, _T("Read gif file failed\n"));
- exit(1);
- }
-
- // 修正传递的参数
- if(cut_x < 0 || cut_x > gifWidth)
- {
- cut_x = 0;
- }
-
- if(cut_y < 0 || cut_y > gifHeight)
- {
- cut_y = 0;
- }
-
- if(cutWidth <= 0 || cutWidth >= gifWidth)
- {
- cutWidth = gifWidth;
- }
-
- if(cutHeight <= 0 || cutHeight >= gifHeight)
- {
- cutHeight = gifHeight;
- }
-
- if(showWidth <= 0)
- {
- showWidth = gifWidth;
- }
-
- if(showHeight <= 0)
- {
- showHeight = gifHeight;
- }
-
- UINT count = gifImage->GetFrameDimensionsCount();
- GUID* pDimensionIDs = (GUID*)new GUID[count];
- gifImage->GetFrameDimensionsList(pDimensionIDs,count);
-
- WCHAR strGuid[39];
- StringFromGUID2(pDimensionIDs[0], strGuid,39);
-
- // 获取gif帧数
- UINT FPSCount = gifImage->GetFrameCount(&pDimensionIDs[0]);
- delete []pDimensionIDs;
-
- // 如果gif仅含单帧,则直接退出
- if(FPSCount < 1)
- {
- _ftprintf(stderr, _T("The gif file has no FPS\n"));
- exit(1);
- }
-
- int size = gifImage->GetPropertyItemSize(PropertyTagFrameDelay);
- PropertyItem* pItem = (PropertyItem*)malloc(size);
- gifImage->GetPropertyItem(PropertyTagFrameDelay,size, pItem);
-
- GUID Guid = FrameDimensionTime;
- UINT FPSIndex = ((0 < skipNumber) && (skipNumber < FPSCount-1)) ?skipNumber :0;
-
- intervalNumber = (intervalNumber < 2) ?1 :intervalNumber;
-
- // 获取拼接位图宽高
- int joinWdith, joinHeight;
- if(modeFlag == 0)
- {
- joinWdith = (int)((FPSCount - FPSIndex) / intervalNumber +0.5f) * showWidth;
- joinHeight = showHeight;
- }
- else if(modeFlag == 1)
- {
- joinWdith = showWidth;
- joinHeight = (int)((FPSCount - FPSIndex) / intervalNumber +0.5f) * showHeight;
- }
- else if(modeFlag == 2)
- {
- joinWdith = showWidth;
- joinHeight = showHeight;
- }
-
- // 创建拼接位图
- Bitmap* pJoinGifMap = new Bitmap(joinWdith, joinHeight, PixelFormat32bppARGB);
- Graphics* pGraphics = new Graphics(pJoinGifMap);
-
- // 设置背景色透明
- Color bkColor(0,0,0,0);
- pGraphics->Clear(bkColor);
-
- // 设置ImageAttributes颜色属性
- ImageAttributes* pAttributes = new ImageAttributes();
-
- // 设置透明颜色高低色位
- if(useTransparentColor)
- {
- pAttributes->SetColorKey(transparentColor, transparentColor, ColorAdjustTypeBitmap);
- }
-
- /*
- // 创建颜色矩阵
- ColorMatrix colorMatrix = {
- 0.3f, 0.3f, 0.3f, 0.0f, 0.0f,
- 0.59f, 0.59f, 0.59f, 0.0f, 0.0f,
- 0.11f, 0.11f, 0.11f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.3f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
- };
- pAttributes->SetColorMatrix(&colorMatrix);
-
- // 为ColorAdjustTypeBitmap设置颜色阈值
- pAttributes->SetThreshold(0.7f, ColorAdjustTypeBitmap);
- */
-
- // 设置每帧输出尺寸
- Rect* pRect = new Rect(0, 0, showWidth, showHeight);
-
- // 获取编码器ID
- CLSID clsid;
- if(! GetEncoderClsid((WCHAR*)IMAGE_TYPE[SN], &clsid))
- {
- _ftprintf(stderr, _T("Get the CLSID failed\n"));
- exit(1);
- }
-
- // 循环获取帧
- int countNumber = 0;
- while(true)
- {
- if(modeFlag == 0)
- {
- pRect->X = countNumber * showWidth;
- }
- else if(modeFlag == 1)
- {
- pRect->Y = countNumber * showHeight;
- }
- else if(modeFlag == 2)
- {
- pGraphics->Clear(bkColor);
- _stprintf(outFileS, _T("%s%02d.%s"), outFile, countNumber+1, outFileSuffix);
- }
-
- // 拼接帧位图
- pGraphics->DrawImage(gifImage, *pRect, cut_x, cut_y, cutWidth, cutHeight, UnitPixel, pAttributes);
-
- // 保存拼接图
- if(pJoinGifMap->Save((WCHAR*)outFileS, &clsid, NULL) != Gdiplus::Ok)
- {
- _ftprintf(stderr, _T("Save the image: '%s' failed\n"), outFileS);
- exit(1);
- }
-
- gifImage->SelectActiveFrame(&Guid, FPSIndex);
-
- // 累加帧间隔
- FPSIndex += intervalNumber;
- countNumber ++;
-
- // 判断帧越界
- if (FPSIndex >= FPSCount)
- {
- break;
- }
- }
-
- //清理绘图工具
- DeleteObject(pGraphics);
- delete gifImage;
- delete pJoinGifMap;
- delete pAttributes;
-
- // 关闭Gdiplus
- GdiplusShutdown(gdipludToken);
-
- return 0;
- }
-
- // 主函数入口
- int _tmain(int argc, TCHAR** argv)
- {
- if(argc<2)
- {
- // 无参数则退出
- _ftprintf(stdout, HELP_INFORMATION);
- return 0;
- }
-
- // 初始化传递参数
- int modeFlag = 0;
- int cut_rect[4] = {0};
- int image_size[2] = {0};
- int intervalNumber = 0, skipNumber = 0;
-
- // 启用透明色过滤
- bool useTransparentColor = false;
- byte tRGB[3] = {0};
-
- // IO文件
- TCHAR *inFile=NULL, *outFile=NULL;
-
- // 开关解析
- int K = _OPT_TEOF;
- while((K=_tgetopt(argc, argv, (TCHAR*)_T("c:s:i:j:o:t:m:hC:S:I:J:O:T:M:H"))) != _OPT_TEOF)
- {
- switch(K)
- {
- case _T('c'):
- case _T('C'):
- if(OPTARG == NULL)
- {
- _ftprintf(stderr, _T("The switch '-c' needs a cut area\n"));
- exit(1);
- }
- {
- TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
- for(int i=0; i<4 && pTcstr; i++)
- {
- cut_rect[i] = _ttoi((TCHARFORMAT*)pTcstr);
- pTcstr = _tcstok(NULL, _T(","));
- }
- }
- break;
-
- case _T('s'):
- case _T('S'):
- if(OPTARG == NULL)
- {
- _ftprintf(stderr, _T("The switch '-s' needs image width and height\n"));
- exit(1);
- }
- {
- TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
- for(int i=0; i<2 && pTcstr; i++)
- {
- image_size[i] = _ttoi((TCHARFORMAT*)pTcstr);
- pTcstr = _tcstok(NULL, _T(","));
- }
- }
- break;
-
- case _T('i'):
- case _T('I'):
- if(OPTARG == NULL)
- {
- _ftprintf(stderr, _T("The switch '-i' needs a interval number\n"));
- exit(1);
- }
- {
- intervalNumber = _ttoi((TCHARFORMAT*)OPTARG);
- }
- break;
-
- case _T('j'):
- case _T('J'):
- if(OPTARG == NULL)
- {
- _ftprintf(stderr, _T("The switch '-j' needs a skip number\n"));
- exit(1);
- }
- {
- skipNumber = _ttoi((TCHARFORMAT*)OPTARG);
- }
- break;
-
- case _T('o'):
- case _T('O'):
- if(OPTARG != NULL)
- {
- outFile = OPTARG;
- }
- break;
-
- case _T('t'):
- case _T('T'):
- if(OPTARG == NULL)
- {
- _ftprintf(stderr, _T("The switch '-t' needs a transparent RGB color like [R,G,B]\n"));
- exit(1);
- }
- {
- TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
- for(int i=0; i<3 && pTcstr; i++)
- {
- tRGB[i] = (byte)_ttoi((TCHARFORMAT*)pTcstr);
- pTcstr = _tcstok(NULL, _T(","));
- }
- useTransparentColor = true;
- }
- break;
-
- case _T('m'):
- case _T('M'):
- if(OPTARG != NULL)
- {
- switch(*((TCHARFORMAT*)OPTARG))
- {
- case _T('v'):
- case _T('V'):
- modeFlag = 0;
- break;
-
- case _T('l'):
- case _T('L'):
- modeFlag = 1;
- break;
-
- case _T('x'):
- case _T('X'):
- modeFlag = 2;
- break;
-
- default:
- break;
- }
-
- if(*((TCHARFORMAT*)OPTARG + 1) != _T('\0'))
- {
- _ftprintf(stderr, _T("Unknown gif mode '-m%c'\n"), *((TCHARFORMAT*)OPTARG));
- exit(1);
- }
- }
- break;
-
- case _T('h'):
- case _T('H'):
- _ftprintf(stdout, HELP_INFORMATION);
- return 0;
-
- case _OPT_TILL:
- // 第一个无选项的参数识别为输入文件
- inFile = argv[UNOPTIND];
- break;
-
- case _OPT_TERR:
- _ftprintf(stderr, _T("Extra parameters \"%s\"\n"), argv[OPTIND]);
- exit(1);
-
- default:
- _ftprintf(stderr, _T("Unknown switch '-%c'\n"), K);
- exit(1);
- }
- }
-
- if(inFile == NULL)
- {
- _ftprintf(stderr, _T("Needs input file\n"));
- exit(1);
- }
- if(outFile == NULL)
- {
- _ftprintf(stderr, _T("Needs output file\n"));
- exit(1);
- }
-
- // 调用gif拼接手函数
- return JoinGif(inFile, outFile, modeFlag, useTransparentColor, Color(tRGB[0],tRGB[1],tRGB[2]), cut_rect[0], cut_rect[1], cut_rect[2], cut_rect[3], image_size[0], image_size[1], intervalNumber, skipNumber);
- }
复制代码
|