Go语言 ImageMagick命令未在Powershell窗口中运行,但可以在cmd窗口中运行

fnatzsnv  于 2023-05-04  发布在  Go
关注(0)|答案(2)|浏览(191)

这个命令是给图像添加水印

magick nature.jpg -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none ( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -size "%[watermarkWidth]x" label:"THIS IS WATERMARK" -gravity center -geometry +10+10 -rotate -30 ) -composite -quality 40 nature_wm.jpg

它可以在Windows cmd Windows x1c 0d1x上运行
但它不能在Powershell窗口中运行(见错误截图)

我还尝试在()之前添加\(在macOS或Linux上应该这样做)

magick nature.jpg -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none \( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -size "%[watermarkWidth]x" label:"THIS IS WATERMARK" -gravity center -geometry +10+10 -rotate -30 \) -composite -quality 40 nature_wm.jpg

但它会抛出相同的错误

错误翻译:-fill:-fill无法识别为cmdlet、函数、脚本文件或可运行程序。请检查名称的拼写,如果包含路径,请确保路径正确,然后重试。
我确信magick指令在环境变量


看起来PowerShell可以运行简单的命令,但不能运行复杂的命令(下面的命令可以运行,没有错误)

magick nature.jpg -fill yellow nature.png

谁知道如何解决这个问题?
实际上我需要用golang运行它,通过使用cmd = exec.Command("cmd", "/k", cmdStr),但如果“cmdStr”不能在PowerShell中运行,它就不起作用,因为我用golang构建的可执行文件也需要在PowerShell上运行(我不想在cmd窗口上运行,因为它与PowerShell相比太原始了)。

az31mfrm

az31mfrm1#

在PowerShell中测试EXE文件时,EchoArgs.exe是一个非常有用的工具。这个工具的原始源代码似乎已经消失了,但是你仍然可以从www.example.com下载它ss64.com。
在处理EXE文件的复杂命令行时,Stop-parsing token (--%)是一个非常有用的特殊解析标记。
在命令行中,使用参数执行EchoArgs:

EchoArgs nature.jpg -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none ( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -size "%[watermarkWidth]x" label:"THIS IS WATERMARK" -gravity center -geometry +10+10 -rotate -30 ) -composite -quality 40 nature_wm.jpg

记录您的结果:

Arg 0 is <nature.jpg>
Arg 1 is <-set>
Arg 2 is <option:watermarkWidth>
Arg 3 is <%[fx:int(w*0.25)]>
Arg 4 is <-alpha>
Arg 5 is <set>
Arg 6 is <-background>
Arg 7 is <none>
Arg 8 is <(>
Arg 9 is <-fill>
Arg 10 is <#FFFFFF80>
Arg 11 is <-stroke>
Arg 12 is <#FF000080>
Arg 13 is <-strokeWidth>
Arg 14 is <3>
Arg 15 is <-undercolor>
Arg 16 is <#FF000080>
Arg 17 is <-size>
Arg 18 is <%[watermarkWidth]x>
Arg 19 is <label:THIS IS WATERMARK>
Arg 20 is <-gravity>
Arg 21 is <center>
Arg 22 is <-geometry>
Arg 23 is <+10+10>
Arg 24 is <-rotate>
Arg 25 is <-30>
Arg 26 is <)>
Arg 27 is <-composite>
Arg 28 is <-quality>
Arg 29 is <40>
Arg 30 is <nature_wm.jpg>

为了避免问题,在PowerShell中命令行变得复杂的地方使用--%:

EchoArgs nature.jpg -set option:watermarkWidth --% "%[fx:int(w*0.25)]" -alpha set -background none ( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -size "%[watermarkWidth]x" label:"THIS IS WATERMARK" -gravity center -geometry +10+10 -rotate -30 ) -composite -quality 40 nature_wm.jpg

检查您的结果:

Arg 0 is <nature.jpg>
Arg 1 is <-set>
Arg 2 is <option:watermarkWidth>
Arg 3 is <%[fx:int(w*0.25)]>
Arg 4 is <-alpha>
Arg 5 is <set>
Arg 6 is <-background>
Arg 7 is <none>
Arg 8 is <(>
Arg 9 is <-fill>
Arg 10 is <#FFFFFF80>
Arg 11 is <-stroke>
Arg 12 is <#FF000080>
Arg 13 is <-strokeWidth>
Arg 14 is <3>
Arg 15 is <-undercolor>
Arg 16 is <#FF000080>
Arg 17 is <-size>
Arg 18 is <%[watermarkWidth]x>
Arg 19 is <label:THIS IS WATERMARK>
Arg 20 is <-gravity>
Arg 21 is <center>
Arg 22 is <-geometry>
Arg 23 is <+10+10>
Arg 24 is <-rotate>
Arg 25 is <-30>
Arg 26 is <)>
Arg 27 is <-composite>
Arg 28 is <-quality>
Arg 29 is <40>
Arg 30 is <nature_wm.jpg>

但是,如果您需要动态替换Stop-parsing标记(--%)之后的部分参数,该怎么办?这可以通过环境变量来实现:

$Env:FirstValue = '%[fx:int(w*0.25)]'
$Env:Alpha = 'set'
$Env:Background = 'none'
$Env:Fill = '#FFFFFF80'
$Env:Stroke = '#FF000080'
$Env:StrokeWidth = '3'
$Env:Undercolor = '#FF000080'
$Env:Size =  '%[watermarkWidth]x'
$Env:Label = 'THIS IS WATERMARK'
$Env:Gravity = 'center'
$Env:Geometry = '+10+10'
$Env:Rotate = '-30'
$Env:Quality = '40'
$Env:ImgName = 'nature_wm.jpg'
EchoArgs nature.jpg -set option:watermarkWidth --% "%FirstValue%" -alpha %Alpha% -background %Background% ( -fill "%Fill%" -stroke "%Stroke%" -strokeWidth %StrokeWidth% -undercolor "%Undercolor%" -size "%[watermarkWidth]x" label:"%Label%" -gravity %Gravity% -geometry %Geometry% -rotate %Rotate% ) -composite -quality %Quality% %ImgName%

再次检查您的结果:

Arg 0 is <nature.jpg>
Arg 1 is <-set>
Arg 2 is <option:watermarkWidth>   
Arg 3 is <%[fx:int(w*0.25)]>       
Arg 4 is <-alpha>
Arg 5 is <set>
Arg 6 is <-background>
Arg 7 is <none>
Arg 8 is <(>
Arg 9 is <-fill>
Arg 10 is <#FFFFFF80>
Arg 11 is <-stroke>
Arg 12 is <#FF000080>
Arg 13 is <-strokeWidth>
Arg 14 is <3>
Arg 15 is <-undercolor>
Arg 16 is <#FF000080>
Arg 17 is <-size>
Arg 18 is <%[watermarkWidth]x>     
Arg 19 is <label:THIS IS WATERMARK>
Arg 20 is <-gravity>
Arg 21 is <center>
Arg 22 is <-geometry>
Arg 23 is <+10+10>
Arg 24 is <-rotate>
Arg 25 is <-30>
Arg 26 is <)>
Arg 27 is <-composite>
Arg 28 is <-quality>
Arg 29 is <40>
Arg 30 is <nature_wm.jpg>

但是如果您不知道EXE在哪里,必须在硬盘上搜索它并从变量中调用它,该怎么办?使用The call operator (&)

$Program = 'C:\Program Files\ImageMagick-7.0.11-Q16-HDRI\magick.exe'
$Env:FirstValue = '%[fx:int(w*0.25)]'
$Env:Alpha = 'set'
$Env:Background = 'none'
$Env:Fill = '#FFFFFF80'
$Env:Stroke = '#FF000080'
$Env:StrokeWidth = '3'
$Env:Undercolor = '#FF000080'
$Env:Size =  '%[watermarkWidth]x'
$Env:Label = 'THIS IS WATERMARK'
$Env:Gravity = 'center'
$Env:Geometry = '+10+10'
$Env:Rotate = '-30'
$Env:Quality = '40'
$Env:ImgName = 'nature_wm.jpg'
& $Program nature.jpg -set option:watermarkWidth --% "%FirstValue%" -alpha %Alpha% -background %Background% ( -fill "%Fill%" -stroke "%Stroke%" -strokeWidth %StrokeWidth% -undercolor "%Undercolor%" -size "%[watermarkWidth]x" label:"%Label%" -gravity %Gravity% -geometry %Geometry% -rotate %Rotate% ) -composite -quality %Quality% %ImgName%

现在,说了这么多,真实的的测试是实际执行命令,看看它是否有效。我没有你的图像文件,也没有真正做任何实验与图像魔术。但是,从理论上讲,这个命令应该为您工作:

magick nature.jpg -set option:watermarkWidth --% "%[fx:int(w*0.25)]" -alpha set -background none ( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -size "%[watermarkWidth]x" label:"THIS IS WATERMARK" -gravity center -geometry +10+10 -rotate -30 ) -composite -quality 40 nature_wm.jpg

编辑:

如果你想让MagicK在GoLang中运行,请使用以下代码:

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    data, err := exec.Command("magick", "nature.jpg", "-set", "option:watermarkWidth", "%[fx:int(w*0.25)]", "-alpha", "set", "-background", "none", "(", "-fill", "#FFFFFF80", "-stroke", "#FF000080", "-strokeWidth", "3", "-undercolor", "#FF000080", "-size", "%[watermarkWidth]x", "label:THIS IS WATERMARK", "-gravity", "center", "-geometry", "+10+10", "-rotate", "-30", ")", "-composite", "-quality", "40", "nature_wm.jpg").Output()
    if err != nil {
        panic(err)
    }
    fmt.Println(string(data))
}
pcrecxhr

pcrecxhr2#

TL;DR

在这篇文章的最后给出了一种非常简单的、独立于引用的、跨平台的ImageMagick脚本编写方法……

bash、CMD 32和Powershell中的引号、引号、转义和转义ImageMagick命令

由于其强大的多功能性,ImageMagick提供了比大多数命令行程序更丰富的选项,开关和参数(列出了大约300个选项和开关here),并且它使用字符和符号允许用户以非常自然的方式表达事物。因此,在多种环境下使用ImageMagick时需要一定程度的谨慎,即:

  • bash或其他Unix/Linux shell下,例如zshkshtcsh
  • 在Windows CMD 32和Windows BATCH文件中,
  • Powershell
  • 在MinGW、MSYS、Cygwin等软件下

例如,就其本身而言,不考虑shell,ImageMagick理解以下内容:

  • #或hash,又名:磅符号用于以自然的方式表示十六进制颜色,如-fill #ff0000表示红色填充色。但是,bash将该字符解释为引入了注解,因此在bash中,通常应写成-fill '#ff0000'
  • ()或括号。ImageMagick使用圆括号对堆栈中的特定图像进行处理,也称为 “旁处理”。因此,此命令加载两个图像并调整magick IMAGE1.PNG IMAGE2.PNG -resize 800x600 ...的大小,但如果您只想调整第二个图像的大小,则可以执行magick IMAGE1.PNG ( IMAGE2.PNG -resize 800x600 ) ...。然而,bash使用括号表示子进程,因此它会认为您希望运行名为IMAGE2.PNG的子进程,除非您使用magick IMAGE1.PNG \( IMAGE2.PNG -resize 800x600 \) ...转义括号。同样,Powershell将反对括号,并且必须在打开和关闭括号之前加上反引号。CMD 32根本不把圆括号当作特殊的,所以在那种环境中它们不需要转义。
  • ()或括号。ImageMagick使用这些来引入十六进制或hsl颜色,例如-fill RGBA(255,0,0)-fill hsl(50,60,70)。同样,bash会不喜欢这样,认为你需要一个子shell,所以人们写-fill "rgb(255,0,0)"。我想Powershell也不会喜欢它。
  • %或百分比。ImageMagick通常使用该方法或类似方法将图像大小调整为原始大小的50% -resize 50%。但是,如果您在Windows BATCH文件中使用百分号,则需要将其加倍,否则它会认为您引用的是其命令行参数。
  • <>,或小于和大于。ImageMagick使用>表示您只希望对大于特定大小的图像应用调整大小,例如-resize 800>,这意味着您只希望将大于800的图像缩小到800,但不希望将小于800的图像放大。<也是如此。然而,bash使用这些字符来重定向输入和输出,因此在bash中,您通常会写-resize '800>'。同样,在CMD 32中,您需要通过在^前面插入一个脱字符来转义<>。然后在Powershell中加上反引号。
  • !或感叹号,即* “bang”*.ImageMagick用它来表示 “Just do it!“。例如,-resize 800x600表示您希望调整大小,使宽度不超过800,高度不超过600,并且应考虑纵横比。然而,当你添加像这样的爆炸-resize 800x600!你会得到确切的800 x600像素,即使这扭曲了你的图像可怕。shell可以将感叹号解释为对以前命令的历史记录进行了一些操作,因此您经常会看到转义
  • [],或方括号。ImageMagick使用这些来引用多页文档(如PDF或TIFF)中的页面或页面子集。例如,以下表示PDF的第一页和最后一页,magick DOCUMENT.PDF[0,-1] ...如果不小心处理,可能会与用于交替的shell语法混淆
  • *或星号。ImageMagick将星号理解为一个globbing字符,用于扩展所有匹配文件的列表,例如*.tif表示当前目录中的所有TIFF文件。这与bash相同,但这里有细微差别。如果使用magick *.tif ...,TIFF列表将由bash中的shell展开,并且将受系统的ARGMAX的影响。但是如果你做magick '*.TIF' ...,它会通过ImageMagick进行内部扩展,不受这样的限制。
  • bash和Unix/Linux shell的一般提示 *
  • 行继续字符是反斜杠
  • 开括号和闭括号必须在紧挨它们前面用反斜杠转义
  • 哈希必须在双引号或单引号字符串内
  • bash命令示例 *
magick IMAGE1.PNG \
   \( IMAGE2.PNG -resize 50% -fill '#ff0000' -colorize 100% \) \
  -composite -transparent 'hsl(40,50,60)' result.png
  • Windows CMD 32的一般提示 *

  • 插入符号^用作转义字符

  • CMD 32通常不喜欢使用单引号。通常,如果从bashImageMagick的咒语翻译,请尝试将单引号替换为双引号。例外情况是当已经在双引号内时,您可以使用单引号,例如。-draw "text 100,100 'Works like magick'"

  • 插入符号用作行连续字符,并且在以这种方式使用时不能后跟任何空格

  • 在BATCH中百分号必须加倍

  • 括号不需要转义

  • Windows CMD 32 BATCH命令示例 *

magick IMAGE1.PNG ^
   ( IMAGE2.PNG -resize 50%% -fill "#ff0000" -colorize 100% ) ^
  -composite -transparent "hsl(40,50,60)" result.png
  • PowerShell的一般提示 *
  • 反引号用作转义字符,行继续字符用作
  • 左括号和右括号必须使用前面的反引号进行转义
  • Powershell命令示例 *
magick IMAGE1.PNG `
   `( IMAGE2.PNG -resize 50% -fill "#ff0000" -colorize 100% `) `
  -composite -transparent "hsl(40,50,60)" result.png

TL;DR

如果您想要一种跨平台,或平台无关的方式来编写ImageMagick脚本,最简单的方法是将所有命令放在一个文件中,该文件的内容仅由ImageMagick本身读取,而不依赖于您的shell。因此,编写一个这样的脚本,它是纯的,没有引号,并将其保存为script.mgk

-size 640x480 xc:#ffff00
( foreground.png -resize 50% )
-gravity center -composite -write result.png

然后用以下命令调用它:

magick -script script.mgk

而你的shell,不管它是什么,甚至看不到引号、百分号、散列号、行延续或括号:
bash进行比较和对比,您需要:

magick -size 640x480 xc:'#ffff00'    \
   \( foreground.png -resize 50% \)  \
   -gravity centre -composite result.png

和Windows CMD32.EXE,您需要:

magick -size 640x480 xc:#ffff00     ^
   ( foreground.png -resize 50%% )  ^
   -gravity centre -composite result.png

相关问题