ImageMagick 可以在 Windows PowerShell 上运行,但无法在 go 上运行
我需要使用 ImageMagick 添加水印,由于某种原因,我需要使用 golang 运行它。
这是我的代码片段
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
func main() {
currentDir, _ := os.Getwd()
sourceImg := os.Args[1]
sourceName := filepath.Base(sourceImg)
sourceExt := filepath.Ext(sourceImg)
imgNameWithoutExt := strings.Replace(sourceName, sourceExt, "", 1)
targetImgName := imgNameWithoutExt + "_wm" + sourceExt
targetImg := filepath.Join(filepath.Dir(sourceImg), targetImgName)
command := "bash"
secondParam := "-c"
// In macOS or Linux, use backslash to escape parenthesis
cmdStr := `magick "` + sourceImg + `" -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none \\( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -font "arial.ttf" -size "%[watermarkWidth]x" label:"This is watermark" -gravity center -geometry +10+10 -rotate -30 \\) -composite -quality 40 "` + targetImg + `"`
if runtime.GOOS == "windows" {
sourceImg = strings.ReplaceAll(sourceImg, "\\", "\\\\")
targetImg = strings.ReplaceAll(targetImg, "\\", "\\\\")
// In PowerShell, use babckstick (`) to escape parenthesis
command = "cmd"
secondParam = "/c"
cmdStr = `magick "` + sourceImg + `" -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none ` + "`(" + ` -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -font "arial.ttf" -size "%[watermarkWidth]x" label:"This is watermark" -gravity center -geometry +10+10 -rotate -30 ` + "`)" + ` -composite -quality 40 "` + targetImg + `"`
}
fmt.Println(cmdStr)
cmd := exec.Command(command, secondParam, cmdStr)
cmd.Dir = currentDir
ouput, err := cmd.Output()
if err != nil {
fmt.Println("Error:", ouput, err.Error())
} else {
fmt.Println("Watermark was successfully added!")
}
}
因为我在代码中使用了 os.Getwd()
,所以我们不能直接通过 go run main.go
运行它,相反,我们应该构建可执行文件
# build Windows executable
GOOS=windows GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick.exe" main.go
# build macOS executable
GOOS=darwin GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick" main.go
# build Linux executable(I didn't test)
GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick" main.go
在Windows(在PowerShell中)上,它返回一个错误,实际上没有指定的错误消息,它只是失败了
有人知道如何解决这个错误吗?
I need to add watermark with ImageMagick, for some reason, I need to run it with golang.
Here is my code snippet
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
func main() {
currentDir, _ := os.Getwd()
sourceImg := os.Args[1]
sourceName := filepath.Base(sourceImg)
sourceExt := filepath.Ext(sourceImg)
imgNameWithoutExt := strings.Replace(sourceName, sourceExt, "", 1)
targetImgName := imgNameWithoutExt + "_wm" + sourceExt
targetImg := filepath.Join(filepath.Dir(sourceImg), targetImgName)
command := "bash"
secondParam := "-c"
// In macOS or Linux, use backslash to escape parenthesis
cmdStr := `magick "` + sourceImg + `" -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none \\( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -font "arial.ttf" -size "%[watermarkWidth]x" label:"This is watermark" -gravity center -geometry +10+10 -rotate -30 \\) -composite -quality 40 "` + targetImg + `"`
if runtime.GOOS == "windows" {
sourceImg = strings.ReplaceAll(sourceImg, "\\", "\\\\")
targetImg = strings.ReplaceAll(targetImg, "\\", "\\\\")
// In PowerShell, use babckstick (`) to escape parenthesis
command = "cmd"
secondParam = "/c"
cmdStr = `magick "` + sourceImg + `" -set option:watermarkWidth "%[fx:int(w*0.25)]" -alpha set -background none ` + "`(" + ` -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 3 -undercolor "#FF000080" -font "arial.ttf" -size "%[watermarkWidth]x" label:"This is watermark" -gravity center -geometry +10+10 -rotate -30 ` + "`)" + ` -composite -quality 40 "` + targetImg + `"`
}
fmt.Println(cmdStr)
cmd := exec.Command(command, secondParam, cmdStr)
cmd.Dir = currentDir
ouput, err := cmd.Output()
if err != nil {
fmt.Println("Error:", ouput, err.Error())
} else {
fmt.Println("Watermark was successfully added!")
}
}
Because I've use os.Getwd()
in the code, so we cannot run it directly through go run main.go
, instead, we should build an executable
# build Windows executable
GOOS=windows GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick.exe" main.go
# build macOS executable
GOOS=darwin GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick" main.go
# build Linux executable(I didn't test)
GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -o "test-magick" main.go
On macOS, the executable works fine, the watermark was successfully added
On Windows(in PowerShell), it returns an error, actually no specified error message, it just failed
Anyone who knows how to solve this error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不是使用 powershell 从您的Go Inserion 中调用您的可执行文件,您正在使用
cmd.exe
,具有不同的语法规则(它不识别`
(backtick)作为逃生字符,%
是一种元时间,不支持逃脱的”因此
代码> cmd.exe ,由于语法差异而失败的旧式Windows Shell。
因此,替换:
与:
另外,请考虑在
-c
之前放置以下参数,以增加鲁棒性:请参阅
powershell.exe
的文档。退后一步:
您的可执行电话不使用任何 shell功能 (例如重定向到文件,通过管道连接多个命令,...),所以您可以简单地调用
magick
直接,并且其所有参数通过exec.command ()
,可以加快操作并避免逃脱的需求。You're not using PowerShell to invoke your executable from inside your Go application, you're using
cmd.exe
, which has different syntax rules (it doesn't recognize`
(the backtick) as the escape character,%
is a metacharacter, no support for escaping"
as\"
, ...)Therefore, because you're mistakenly passing a command line designed for
powershell.exe
(the Windows PowerShell CLI) tocmd.exe
, the legacy Windows shell, which fails, due to the syntax differences.Therefore, replace:
with:
Additionally, consider placing the following arguments before
-c
, for added robustness:See the documentation for
powershell.exe
.Taking a step back:
Your executable call doesn't use any shell features (such as redirecting to a file, connecting multiple commands via a pipeline, ...), so you could simply invoke
magick
directly, with it and all its arguments passed individually toexec.Command()
, which speeds up the operation and avoids the need for escaping.