[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
原创代码: | | | | | | | | | | | | | | | | | | | #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 | | | | | | 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 | | | | | | #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}; | | | | | | 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; | | } | | | | | | 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; | | } | | | | | | 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'); | | | | | | ULONG_PTR gdipludToken; | | GdiplusStartupInput gdiplusInput; | | GdiplusStartup(&gdipludToken,&gdiplusInput,NULL); | | | | | | Image* gifImage = Image::FromFile((WCHAR*)inFile); | | | | | | 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); | | | | | | UINT FPSCount = gifImage->GetFrameCount(&pDimensionIDs[0]); | | delete []pDimensionIDs; | | | | | | 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* pAttributes = new ImageAttributes(); | | | | | | if(useTransparentColor) | | { | | pAttributes->SetColorKey(transparentColor, transparentColor, ColorAdjustTypeBitmap); | | } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rect* pRect = new Rect(0, 0, showWidth, showHeight); | | | | | | 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; | | | | | | 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}; | | | | | | 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); | | } | | | | | | 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); | | }COPY |
|