拼图脚本工具 jimg
Jimg是一款控制台下拼图脚本工具,类似gawk的性质,但处理的是图片并非文本。可以将拼接好的图片出书为各种格式。可以绘制图片的切片,透明色、图片旋转 等多种属性。同时可以很好的继承批处理中的环境变量。可以在脚本中使用%变量名%之类的扩展语法。语法完全模仿cmd,易于掌握。功能妙用,请自己体验,一般很少能找到这类批处理下替代ps拼图功能的第三方。对不善于编译的坛友,提供一个7KB附件下载:
[url]http://bcn.bathome.net/s/tool/index.html?key=Jimg[/url]
下面是一个jimg格式的脚本示例:(警告:脚本的文件编码必须存为UNICODE)[code]
REM 脚本演示:
:MAIN1
ECHO TEST1.JPG -C 0,0 -S %VAR1%,%VAR2%,300,100
ECHO %ENV_FILE% -C 0,0 -S 0,100,0,0 -R 0,0,30
ECHO TEST3.PNG -C 0,0 -S 0,300,0,0
ECHO TEST4.JPG -C 0,0 -S 0,600,0,0 -R 300,0,60
ECHO TEST5.JPG -C 0,0 -S 0,900,0,0 -R 0,200,130
EXIT
:MAIN2
ECHO TEST2.JPG -C 0,0 -S 0,0,0,0
ECHO TEST2.JPG -C 0,0 -S 0,100,0,0 -R 0,0,30
ECHO TEST3.PNG -C 0,0 -S 0,300,0,0 -T 100,255,255,127
EXIT
[/code]就是这样便捷,将图片echo到图形文件里。
[quote]JIMG.EXE (CONSOLE IMAGE JOIN TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.0)
摘要:
===============================================================
JIMG.EXE,是一款奇异的命令行拼图工具。同时也支持其他图片格式的转换、裁剪、透明色处理等操作。
===============================================================
版本:
VERSION 1.0
用法:
-------------------------------------------------------------------------
jimg [输入文件]
-o [输出文件]
-s [[显示宽度],[显示高度]]
-b [[A],[R],[G],[B]]
-j [要跳到的标签]
脚本中的拼图用法
[输入文件]
-c[[x],[y],[width],[height]]
-s[[x],[y],[width],[height]]
-t[[A],[R],[G],[B]]
-------------------------------------------------------------------------
主程序调用示例:
-------------------------------------------------------------------------
REM 运行test.ji绘图输出1024*7200尺寸的图片1024,7200
jimg test.ji -otest.png -s1024,7200
...
-------------------------------------------------------------------------
英译:
-------------------------------------------------------------------------
Jimg v1.0 - Console image join tool - Copyright (C) 2017-2019 by Happy
Usage:
jimg [input_script] -o[output_image] -s[image_size] -b[image_background_color]
General options:
-o[path] Output image file
-s[[width],[height]] Output image size
-b[[A],[R],[G],[B]] Output image background color
-j[jump_mark] Goto the jump mark of the input script
-h Show help information
Script options:
-c[[x],[y],[width],[height]] Cut rect
-s[[x],[y],[width],[height]] Show rect
-t[[A],[R],[G],[B]] Transparent ARGB
Official website:
[url]http://www.bathome.net/thread-18888-8-8.html[/url]
-------------------------------------------------------------------------
SAT SEP 09 2017 10:28:16 GMT+0800
[/quote]
原创代码:[code]/*
CONSOLE IMAGE JOIN TOOL, JIMG.EXE COPYRIGHT(C)2017~2019 BY HAPPY, VERSION 1.0
SAT SEP 09 2017 10:28:16 GMT+0800
**************************************************************************
g++ jimg.cpp -lgdiplus -lgdi32 -lole32 -municode -O2 -static REM For MINGW
cl jimg.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 <ctype.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")
#pragma comment(lib, "Shell32.lib")
#else
#include <gdiplus\gdiplus.h>
#endif
// 使用GDI+命名空间
using namespace Gdiplus;
// 定义帮助说明
#define HELP_INFORMATION _T("\
Jimg v1.0 - Console image join tool - Copyright (C) 2017-2019 by Happy\n\
Usage:\n\
jimg [input_script] -o[output_image] -s[image_size] -b[image_background_color]\n\
\n\
General options:\n\
-o[path] Output image file\n\
-s[[width],[height]] Output image size\n\
-b[[A],[R],[G],[B]] Output image background color\n\
-j[jump_mark] Goto the jump mark of the input script\n\
-h Show help information\n\
\n\
Script options:\n\
-c[[x],[y],[width],[height]] Cut rect\n\
-s[[x],[y],[width],[height]] Show rect\n\
-t[[A],[R],[G],[B]] Transparent ARGB\n\
\n\
Official website:\n\
http://www.bathome.net/thread-18888-8-8.html\n\
")
// 标准行长
#define MAX_BUFF_SIZE 1024
// 开关解析宏名
#define _OPT_TEOF -1
#define _OPT_TILL -2
#define _OPT_TERR -3
// 开关解析变量
int OPTIND = 1, OPTOPT = 0, UNOPTIND = -1;
TCHAR* OPTARG = NULL;
#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};
// 开关解析函数
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;
}
// image拼接手函数
int DrawImageFile(Graphics* pGraphics, TCHAR* inImageFile, int lineNumber, BOOL useTransparentColor, Color transparentColor, int cut_x, int cut_y, int cutWidth, int cutHeight, int showX, int showY, int showWidth, int showHeight, REAL roteX, REAL roteY, REAL roteAngle)
{
// 读取gif文件数据
Image* imageFile = Image::FromFile((WCHAR*)inImageFile);
// 获取gif原始宽高
UINT imageWidth = imageFile->GetWidth();
UINT imageHeight = imageFile->GetHeight();
// 判断文件读取失败
if((imageWidth & imageHeight) == 0)
{
_ftprintf(stderr, _T("[%d]: Read image '%s' failed\n"), lineNumber, inImageFile);
exit(1);
}
// 修正传递的参数
if(cut_x < 0 || cut_x > imageWidth)
{
cut_x = 0;
}
if(cut_y < 0 || cut_y > imageHeight)
{
cut_y = 0;
}
if(cutWidth <= 0 || cutWidth > imageWidth)
{
cutWidth = imageWidth;
}
if(cutHeight <= 0 || cutHeight > imageHeight)
{
cutHeight = imageHeight;
}
if(showWidth <= 0)
{
showWidth = imageWidth;
}
if(showHeight <= 0)
{
showHeight = imageHeight;
}
if(showX < 0 || showX >= imageWidth)
{
showX = 0;
}
if(showY < 0 || showY >= imageHeight)
{
showY = 0;
}
// 设置ImageAttributes颜色属性
ImageAttributes* pAttributes = new ImageAttributes();
// 设置透明颜色高低色位
if(useTransparentColor)
{
pAttributes->SetColorKey(transparentColor, transparentColor, ColorAdjustTypeBitmap);
}
// 设置每帧输出尺寸
Rect* pRect = new Rect(showX, showY, showWidth, showHeight);
// 旋转矩阵
Matrix* pMatri = new Matrix();
pMatri->Reset();
pMatri->RotateAt(roteAngle, PointF(roteX, roteY));
// 旋转画布
pGraphics->SetTransform(pMatri);
// 拼接位图
pGraphics->DrawImage(imageFile, *pRect, cut_x, cut_y, cutWidth, cutHeight, UnitPixel, pAttributes);
// 清理绘图工具
delete imageFile;
delete pAttributes;
delete pMatri;
delete pRect;
return 0;
}
// 脚本命令行解析函数
int ParseScript(int scriptArgc, TCHAR** scriptArgv, int lineNumber, Graphics* pGraphics)
{
// 初始化开关解析变量
OPTIND = 0, OPTOPT = 0, UNOPTIND = -1;
OPTARG = NULL;
// 初始化传递参数
int cut_rect[4] = {0};
int show_rect[4] = {0};
REAL rote_matri[3] = {0};
// 启用透明色过滤ARGB
BOOL useTransparentColor = FALSE;
byte tRGB[4] = {0};
// 脚本中的图像文件
TCHAR* inImageFile = NULL;
// 开关解析
int K = _OPT_TEOF;
while((K=_tgetopt(scriptArgc, scriptArgv, (TCHAR*)_T("c:s:t:C:S:T:"))) != _OPT_TEOF)
{
switch(K)
{
case _T('c'):
case _T('C'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("[%d]: The switch '-c' needs a cut rect\n"), lineNumber);
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("[%d]: The switch '-s' needs a image show rect\n"), lineNumber);
exit(1);
}
{
TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
for(int i=0; i<4 && pTcstr; i++)
{
show_rect[i] = _ttoi((TCHARFORMAT*)pTcstr);
pTcstr = _tcstok(NULL, _T(","));
}
}
break;
case _T('t'):
case _T('T'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("[%d]: The switch '-t' needs a transparent ARGB color like [[A],[R],[G],[B]]\n"), lineNumber);
exit(1);
}
{
TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
for(int i=0; i<4 && pTcstr; i++)
{
tRGB[i] = (byte)_ttoi((TCHARFORMAT*)pTcstr);
pTcstr = _tcstok(NULL, _T(","));
}
useTransparentColor = TRUE;
}
break;
case _T('r'):
case _T('R'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("[%d]: The switch '-r' needs a rote matri like [[roteX],[roteY],[roteAngle]]\n"), lineNumber);
exit(1);
}
{
TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
for(int i=0; i<3 && pTcstr; i++)
{
rote_matri[i] = (REAL)_tcstod((TCHARFORMAT*)pTcstr, NULL);
pTcstr = _tcstok(NULL, _T(","));
}
}
break;
case _OPT_TILL:
// 第一个无选项的参数识别为输入文件
inImageFile = scriptArgv[UNOPTIND];
break;
case _OPT_TERR:
_ftprintf(stderr, _T("[%d]: Extra parameters '%s'\n"), lineNumber, scriptArgv[OPTIND]);
exit(1);
break;
default:
_ftprintf(stderr, _T("[%d]: Unknown switch '-%c'\n"), lineNumber, K);
exit(1);
}
}
if(inImageFile == NULL)
{
_ftprintf(stderr, _T("[%d]: Needs input file\n"), lineNumber);
exit(1);
}
// 调用image拼接手函数
DrawImageFile(pGraphics, inImageFile, lineNumber, useTransparentColor, Color(tRGB[0],tRGB[1],tRGB[2],tRGB[3]), cut_rect[0], cut_rect[1], cut_rect[2], cut_rect[3], show_rect[0], show_rect[1], show_rect[2], show_rect[3], rote_matri[0], rote_matri[1], rote_matri[2]);
return 0;
}
// 主函数入口
int _tmain(int argc, TCHAR** argv)
{
if(argc<2)
{
// 无参数则退出
_ftprintf(stdout, HELP_INFORMATION);
return 0;
}
// 初始化传递参数
int image_size[2] = {1280, 720};
// 设置背景色ARGB
byte bARGB[4] = {0};
// IO文件
TCHAR *inFile=NULL, *outFile=NULL, *jumpMark=NULL;
// 开关解析
int K = _OPT_TEOF;
while((K=_tgetopt(argc, argv, (TCHAR*)_T("s:o:b:hS:O:B:H"))) != _OPT_TEOF)
{
switch(K)
{
case _T('s'):
case _T('S'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("The switch '-s' needs a output image size like [[width],[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('o'):
case _T('O'):
if(OPTARG != NULL)
{
outFile = OPTARG;
}
break;
case _T('j'):
case _T('J'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("The switch '-j' needs a jump mark\n"));
exit(1);
}
jumpMark = OPTARG;
break;
case _T('b'):
case _T('B'):
if(OPTARG == NULL)
{
_ftprintf(stderr, _T("The switch '-b' needs a background ARGB color like [[A],[R],[G],[B]]\n"));
exit(1);
}
{
TCHAR* pTcstr = _tcstok(OPTARG, _T(","));
for(int i=0; i<4 && pTcstr; i++)
{
bARGB[i] = (byte)_ttoi((TCHARFORMAT*)pTcstr);
pTcstr = _tcstok(NULL, _T(","));
}
}
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);
}
// 备份输出文件名
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);
}
// 初始化GdiPlus
ULONG_PTR gdipludToken;
GdiplusStartupInput gdiplusInput;
GdiplusStartup(&gdipludToken,&gdiplusInput,NULL);
// 获取编码器ID
CLSID clsid;
if(! GetEncoderClsid((WCHAR*)IMAGE_TYPE[SN], &clsid))
{
_ftprintf(stderr, _T("Get the CLSID failed\n"));
exit(1);
}
// 创建拼接位图
Bitmap* pJoinImageMap = new Bitmap(image_size[0], image_size[1], PixelFormat32bppARGB);
Graphics* pGraphics = new Graphics(pJoinImageMap);
// 设置背景色ARGB
Color bkColor(bARGB[0],bARGB[1],bARGB[2],bARGB[3]);
pGraphics->Clear(bkColor);
// 进入脚本解析阶段
int scriptArgc, lineNumber = 0;
TCHAR** scriptArgv = NULL;
TCHAR scriptLine[MAX_BUFF_SIZE + 1];
TCHAR scriptLineTmp[MAX_BUFF_SIZE + 1];
TCHAR expandScriptLine[MAX_BUFF_SIZE + 1];
FILE* fp = _tfopen(inFile, _T("rb"));
if(fp == NULL)
{
_ftprintf(stderr, _T("Read input script: '%s' failed\n"), inFile);
exit(1);
}
// 读取BOM头
byte scriptFileBOM[2] = {0};
fread(scriptFileBOM, 1, 2, fp);
if(! (scriptFileBOM[0] == 0xFF && scriptFileBOM[1] == 0xFE) )
{
_ftprintf(stderr, _T("Error input script file: '%s', you must save it as a unicode encoding txt\n"), inFile);
exit(1);
}
BOOL jumpScriptFlag = (jumpMark==NULL) ?TRUE :FALSE;
// 执行脚本循环
while(! feof(fp))
{
_fgetts(scriptLine, MAX_BUFF_SIZE, fp);
// 计行
lineNumber ++;
// 去掉尾部换行符
TCHAR *pLine = scriptLine, *pLineTmp = scriptLineTmp;
while(*pLine == _T(' ') || *pLine == _T('\t'))
{
pLine ++;
}
while(*pLine != _T('\0') && *pLine != _T('\r') && *pLine != _T('\n'))
{
*(pLineTmp ++) = *(pLine ++);
}
*pLineTmp = _T('\0');
// 启用环境变量扩展字串
ExpandEnvironmentStrings(scriptLineTmp, expandScriptLine, MAX_BUFF_SIZE);
// 解析脚本行标签
if(*expandScriptLine == _T(':'))
{
if(jumpScriptFlag == FALSE)
{
int jumpMarkLen = _tcslen(jumpMark);
TCHAR* expandMarkStr = expandScriptLine + 1;
// 解析标签
if(_tcsnicmp(expandMarkStr, jumpMark, jumpMarkLen) == 0)
{
if(
*(expandMarkStr + jumpMarkLen) == _T(' ') ||
*(expandMarkStr + jumpMarkLen) == _T('\t') ||
*(expandMarkStr + jumpMarkLen) == _T('\0')
)
{
jumpScriptFlag = TRUE;
}
}
// 执行跳行
continue;
}
else if(jumpMark != NULL)
{
// 退出脚本
break;
}
}
// 解析ECHO命令
if(
(_tcsnicmp(expandScriptLine, _T("ECHO"), 4) == 0) &&
(
*(expandScriptLine+4) == _T(' ') ||
*(expandScriptLine+4) == _T('\t')
)
)
{
TCHAR* pExpandScriptLine = expandScriptLine + 4;
while(*pExpandScriptLine == _T(' ') || *pExpandScriptLine == _T('\t'))
{
pExpandScriptLine ++;
}
// 拟化命令行参数
scriptArgv = (TCHAR**)CommandLineToArgvW(pExpandScriptLine, &scriptArgc);
// 调用脚本命令行解析函数
ParseScript(scriptArgc, scriptArgv, lineNumber, pGraphics);
// 释放局部空间
LocalFree(scriptArgv);
}
// 解析EXIT命令
else if(
(_tcsnicmp(expandScriptLine, _T("EXIT"), 4) == 0) &&
(
*(expandScriptLine+4) == _T(' ') ||
*(expandScriptLine+4) == _T('\t') ||
*(expandScriptLine+4) == _T('\0')
)
)
{
break;
}
}
// 保存拼接图
if(pJoinImageMap->Save((WCHAR*)outFileS, &clsid, NULL) != Gdiplus::Ok)
{
_ftprintf(stderr, _T("Save the image: '%s' failed\n"), outFileS);
exit(1);
}
// 清理绘图工具
DeleteObject(pGraphics);
delete pJoinImageMap;
// 关闭Gdiplus
GdiplusShutdown(gdipludToken);
return 0;
}
[/code] 大佬啊============ [quote]Jimg是一款控制台下拼图脚本工具,类似gawk的性质,但处理的是图片并非文本。可以将拼接好的图片出书为各种 ...
[size=2][color=#999999]happy886rr 发表于 2017-9-9 21:48[/color] [url=http://www.bathome.net/redirect.php?goto=findpost&pid=202892&ptid=45360][img]http://www.bathome.net/images/common/back.gif[/img][/url][/size][/quote]
似乎不错,不过帮助、范例太少了,不知道如何用。
页:
[1]