ImageMagick 可以 运行 on Windows PowerShell 但不能 运行 with go
ImageMagick can run on Windows PowerShell but can't run with 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
在 macOS 上,可执行文件运行正常,水印已成功添加
在Windows(在PowerShell中),它returns一个错误,实际上没有指定的错误信息,它只是失败了
有人知道如何解决这个错误吗?
您没有使用PowerShell从您的 Go 应用程序中调用您的可执行文件 ,您正在使用 cmd.exe
,它具有不同的语法规则(它不将 `
(反引号)识别为转义字符,%
是元字符,不支持转义 "
作为 \"
, ...)
因此,由于您错误地将专为 powershell.exe
(Windows PowerShell CLI)设计的命令行传递给了 cmd.exe
,遗留的 Windows shell,由于语法差异,失败了。
因此,替换:
command = "cmd"
secondParam = "/c"
与:
command = "powershell.exe"
secondParam = "-c"
此外,考虑在 -c
之前放置以下参数以增加稳健性:
"-ExecutionPolicy", "Bypass", "-NoProfile"
参见documentation for powershell.exe
。
退一步:
您的可执行调用没有使用任何 shell 功能(例如重定向到文件、连接多个命令通过管道,...),所以你可以简单地调用magick
直接,用它和它的所有参数单独传递到exec.Command()
,这样可以加快运算速度,避免转义
我需要用 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
在 macOS 上,可执行文件运行正常,水印已成功添加
在Windows(在PowerShell中),它returns一个错误,实际上没有指定的错误信息,它只是失败了
有人知道如何解决这个错误吗?
您没有使用PowerShell从您的 Go 应用程序中调用您的可执行文件 ,您正在使用 cmd.exe
,它具有不同的语法规则(它不将 `
(反引号)识别为转义字符,%
是元字符,不支持转义 "
作为 \"
, ...)
因此,由于您错误地将专为 powershell.exe
(Windows PowerShell CLI)设计的命令行传递给了 cmd.exe
,遗留的 Windows shell,由于语法差异,失败了。
因此,替换:
command = "cmd"
secondParam = "/c"
与:
command = "powershell.exe"
secondParam = "-c"
此外,考虑在 -c
之前放置以下参数以增加稳健性:
"-ExecutionPolicy", "Bypass", "-NoProfile"
参见documentation for powershell.exe
。
退一步:
您的可执行调用没有使用任何 shell 功能(例如重定向到文件、连接多个命令通过管道,...),所以你可以简单地调用magick
直接,用它和它的所有参数单独传递到exec.Command()
,这样可以加快运算速度,避免转义