vision/heic.go

101 lines
2.4 KiB
Go
Raw Normal View History

package vision
import (
"fmt"
"os"
"os/exec"
"runtime"
)
// HEICConverter 定义了处理 HEIC/HEIF 转换的工具路径
var heicConverter string
// DetectHEICConverter 探测系统中可用的 HEIC 转换工具。
// 优先级: sips (macOS) > heif-convert (libheif) > magick (ImageMagick)
func DetectHEICConverter() string {
if heicConverter != "" {
return heicConverter
}
// 1. macOS 专属原生工具
if runtime.GOOS == "darwin" {
if p, err := exec.LookPath("sips"); err == nil {
heicConverter = p
return p
}
}
// 2. 跨平台开源工具 heif-convert (libheif)
if p, err := exec.LookPath("heif-convert"); err == nil {
heicConverter = p
return p
}
// 3. 跨平台全能工具 ImageMagick
if p, err := exec.LookPath("magick"); err == nil {
heicConverter = p
return p
}
// 记录警告信息,指导用户安装
printHEICWarning()
return ""
}
func printHEICWarning() {
fmt.Fprintln(os.Stderr, "⚠️ Warning: No HEIC converter found in PATH.")
switch runtime.GOOS {
case "darwin":
fmt.Fprintln(os.Stderr, " Hint: macOS should have 'sips' pre-installed.")
case "linux":
fmt.Fprintln(os.Stderr, " Hint: Install libheif: 'sudo apt install libheif-examples'")
case "windows":
fmt.Fprintln(os.Stderr, " Hint: Install ImageMagick or libheif for Windows.")
}
}
// ConvertHEIC 使用探测到的工具将 HEIC 转换为 PNG 临时文件
func ConvertHEIC(src, dst string) error {
cmdPath := DetectHEICConverter()
if cmdPath == "" {
return fmt.Errorf("no HEIC converter available")
}
var cmd *exec.Cmd
base := ""
if runtime.GOOS == "windows" {
// 简单处理 Windows 下的路径
base = cmdPath
} else {
// 仅获取文件名判断类型
// 这里简单处理,直接用 DetectHEICConverter 返回的路径
base = cmdPath
}
// 根据不同工具构造命令
if contains(base, "sips") {
// sips -s format png input --out output
cmd = exec.Command(cmdPath, "-s", "format", "png", src, "--out", dst)
} else if contains(base, "heif-convert") {
// heif-convert input output
cmd = exec.Command(cmdPath, src, dst)
} else if contains(base, "magick") {
// magick input output.png
cmd = exec.Command(cmdPath, src, dst)
} else {
return fmt.Errorf("unsupported converter: %s", cmdPath)
}
return cmd.Run()
}
func contains(s, substr string) bool {
// 简单的字符串包含判断
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}