如何使用 ImageMagick 在 Windows 批处理文件中捕获图像比较结果
Posted
技术标签:
【中文标题】如何使用 ImageMagick 在 Windows 批处理文件中捕获图像比较结果【英文标题】:How to capture image comparison result in Windows batch file, using ImageMagick 【发布时间】:2020-03-11 17:52:34 【问题描述】:我正在尝试创建一个 Windows bat 文件以在 Windows 10 上使用 GhostScript 和 ImageMagick 7.0.9 比较两个 PDF 文件。第一步为每个页面创建 PNG 文件,并使用“比较”命令创建 magick.exe(没有单独的compare.exe 在 Windows 上)比较图像。不幸的是,即使图像不匹配,“%errorlevel”仍然为 0。
作为一种解决方法,我尝试使用 magick compare 的输出,它在成功时将“0 (0)”发送到 stderr。但是,在这里我无法将 stderr 捕获到环境变量中,可能是因为某些变量范围问题或缺少其他内容。 magick 输出被定向到临时文件,然后用 set /P 加载。通过在魔术比较之后添加暂停,我可以确认 txt 文件在匹配文件中包含“0 (0)”。 echo %SCRIPTRESULT% 什么也不打印。
set /P SCRIPTRESULT=<result/stdtmp.txt
整个bat文件:
@echo off
@rem we assume the current directory is root folder of the test that is being run
@rem get parameters
setlocal
set JOBNAME=%1
set FILETYPE=%2
set PAGECOUNT=%3
set PAGE=1
set FAILPAGE=1
set SCRIPTRESULT=
@rem create the PNG files for two PDFs in ./result/ and ./result_t/ folders
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_CURR%%d.png -r200 ./result_t/%JOBNAME%.%FILETYPE%
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_ORIG%%d.png -r200 ./result/%JOBNAME%.%FILETYPE%
@rem gs produces separate PNG for each PDF or PostScript page and we specify the expected count as parameter to this script
FOR /L %%P IN (1,1,%PAGECOUNT%) do (
set PAGE=%%P
rem echo Page %PAGE% of %PAGECOUNT%
magick compare -metric MAE ./result/%JOBNAME%_%FILETYPE%_CURR%PAGE%.png ./result/%JOBNAME%_%FILETYPE%_ORIG%PAGE%.png ./result/%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png 2> result/stdtmp.txt
rem Errorlevel in Windows ImageMagick is always 0 so we need to observe sderr instead?
echo The errorlevel is %errorlevel%
set /P SCRIPTRESULT=<result/stdtmp.txt
echo Compare returned %SCRIPTRESULT%
del /Q .\result\stdtmp.txt
del /Q ".\result\%JOBNAME%_%FILETYPE%_CURR%PAGE%.png"
del /Q ".\result\%JOBNAME%_%FILETYPE%_ORIG%PAGE%.png"
IF "%SCRIPTRESULT%" == "0 (0)" (
echo Deleting .\result\%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png
del /Q ".\result\%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png"
) ELSE (
echo Failed at page %PAGE%
set /A FAILPAGE=%PAGE%
)
)
echo Outside the loop SCRIPTRESULT=%SCRIPTRESULT%
IF "%SCRIPTRESULT%" == "0 (0)" (
echo Files compare OK >&2
)
IF NOT "%SCRIPTRESULT%" == "0 (0)" (
echo Visual compare failed, see ./result/%JOBNAME%_%FILETYPE%_DIFF%FAILPAGE%.png >&2
)
这个脚本可以运行为
compare.bat filename pdf 1
这假设我们有 .\result\filename.pdf 和 .\result_t\filename.pdf,每个都有 1 页。更复杂的是,此比较脚本旨在通过来自另一个脚本的调用来使用。在那种情况下,我会看到输出:
The errorlevel is 0
Compare returned
Fail at page 1
Outside the loop SCRIPTRESULT=0 (0)
Files compare OK
显然循环外的 SCRIPTRESULT 的值是“0 (0)”,正如预期的那样,但不在 FOR 循环内?添加 setlocal ENABLEDELAYEDEXPANSION 没有任何明显效果。
【问题讨论】:
您可以使用此处的第二个答案将 stderr 捕获到变量中:***.com/questions/29740883/… 您需要延迟变量扩展才能使用代码块内变量的更改值。在 for 循环中,您需要使用!SCRIPTRESULT!
而不是 %SCRIPTRESULT%
。
您还需要!PAGE!
,否则无论页数如何,您都只会比较第 1 页。虽然你可以改用%%P
。
哦,对了——%ERRORLEVEL%
也是如此。您可以查看!ERRORLEVEL!
是否有效,或者只使用内置的if errorlevel 1
逻辑。
与其读入stdtmp.txt
的内容,不如直接用FINDSTR
看看有没有你想要的……
【参考方案1】:
发布脚本的功能版本,感谢评论者。假设有两个单页 PDF 文件 .\result\some.pdf 和 .\result_t\some.pdf,运行比较:
compare.bat some pdf 1
它也适用于 PostScript 或 GhostScript 可以呈现的任何其他内容。匹配失败将在“结果”文件夹中留下一个视觉差异文件。
@rem we assume the current directory is root folder of the test that is being run
@echo off
@setlocal ENABLEDELAYEDEXPANSION
set JOBNAME=%1
set FILETYPE=%2
set PAGECOUNT=%3
set FAILPAGE=0
@rem Using either pngalpha or png16m device
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_CURR%%d.png -r200 ./result_t/%JOBNAME%.%FILETYPE%
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_ORIG%%d.png -r200 ./result/%JOBNAME%.%FILETYPE%
@rem gs produces separate PNG for each PDF or PostScript page and we specify the expected count as parameter to this script
@rem Note that we do not catch case where the result has more pages than template
FOR /L %%P IN (1,1,%PAGECOUNT%) do (
magick compare -metric MAE "./result/%JOBNAME%_%FILETYPE%_CURR%%P.png" "./result/%JOBNAME%_%FILETYPE%_ORIG%%P.png" "./result/%JOBNAME%_%FILETYPE%_DIFF%%P.png" 2>nul
rem echo The errorlevel is !errorlevel!
IF !errorlevel! == 0 (
del /Q ".\result\%JOBNAME%_!FILETYPE!_DIFF%%P.png"
) ELSE (
echo Difference on page %%P
set /A FAILPAGE=%%P
)
del /Q ".\result\%JOBNAME%_!FILETYPE!_CURR%%P.png"
del /Q ".\result\%JOBNAME%_!FILETYPE!_ORIG%%P.png"
)
IF !FAILPAGE! == 0 (
echo Files compare OK >&2
EXIT /B 0
) else (
echo Visual compare failed, see ./result/%JOBNAME%_!FILETYPE!_DIFF!FAILPAGE!.png >&2
EXIT /B 1
)
【讨论】:
以上是关于如何使用 ImageMagick 在 Windows 批处理文件中捕获图像比较结果的主要内容,如果未能解决你的问题,请参考以下文章
我应该将哪些文件复制到我的项目中以使用 ImageMagick?或如何在 Windows 上使用 MinGW 编译 ImageMagick?
ImageMagick:如何在没有背景的情况下使用 mogrify 按比例调整大小