package image import ( "encoding/json" "fmt" "os" "path/filepath" "syscall" "unsafe" ) var ( gImageDll *ImageDLL // Windows API - 使用 C 运行时库 libc = syscall.NewLazyDLL("msvcrt.dll") procFree = libc.NewProc("free") procMalloc = libc.NewProc("malloc") ) // ImageDLL 图片工具DLL结构 type ImageDLL struct { Dll *syscall.DLL AddWatermarkFromURLEx *syscall.Proc // 打水印 } // InitImageDll 初始化 imageDLL func InitImageDll(url string) (*ImageDLL, error) { dllPath := filepath.Join(url, "image.dll") if _, err := os.Stat(dllPath); os.IsNotExist(err) { return nil, fmt.Errorf("Image DLL 不存在: %s", dllPath) } dll, err := syscall.LoadDLL(dllPath) if err != nil { return nil, fmt.Errorf("加载Image DLL 失败: %s", err) } gImageDll = &ImageDLL{ Dll: dll, AddWatermarkFromURLEx: dll.MustFindProc("AddWatermarkFromURLEx"), } return gImageDll, nil } // WatermarkConfig 添加水印 type WatermarkConfig struct { SourceImageURL string // 源图片URL地址 WatermarkURL string // 水印图片URL地址 WatermarkBase64 string // 水印图片base64编码字符串(新增,优先使用) Opacity float64 // 不透明度 (0.0-1.0) Position string // 位置: center, top-left, top-right, bottom-left, bottom-right, tile TileSpacing int // 平铺时的间距 Scale float64 // 水印缩放比例 (0.0-1.0) Rotation float64 // 旋转角度 (度数) XOffset int // X轴偏移量 YOffset int // Y轴偏移量 Timeout int // 下载超时时间(秒),默认30秒 OutputFormat string // 输出格式: "jpeg", "png", "auto"(默认auto,根据源图片格式)auto JPEGQuality int // JPEG质量 (1-100),默认95 TargetWidth int // 目标宽度(0表示不缩放) TargetHeight int // 目标高度(0表示不缩放) ResizeMode string // 缩放模式: "fit"(适应,保持比例,可能有黑边), "fill"(填充,裁剪), "stretch"(拉伸) } // AddWatermarkFromURLExs 添加水印 func (m *ImageDLL) AddWatermarkFromURLExs(sourceImageUrl, watermarkUrl string) (string, error) { watermarkConfig := WatermarkConfig{ SourceImageURL: sourceImageUrl, WatermarkBase64: watermarkUrl, Position: "center", Opacity: 1.0, Scale: 1.0, TileSpacing: 50, Timeout: 30, OutputFormat: "jpeg", JPEGQuality: 95, TargetWidth: 800, TargetHeight: 800, ResizeMode: "fit", } watermarkConfigJson, err := json.Marshal(watermarkConfig) if err != nil { return "", fmt.Errorf("JSON序列化失败: %v", err) } proc, err := m.Dll.FindProc("AddWatermarkFromURLEx") if err != nil { return "", fmt.Errorf("找不到函数 AddWatermarkFromURLEx: %v", err) } // 分配内存并确保释放 jsonStr := string(watermarkConfigJson) jsonPtr := cString(jsonStr) defer freeCString(jsonPtr) // 调用 DLL 函数 resultPtr, _, _ := proc.Call( uintptr(unsafe.Pointer(jsonPtr)), ) result := cStr(resultPtr) return result, nil } // cString 分配 C 字符串(使用 malloc) func cString(str string) unsafe.Pointer { // 计算需要的内存大小 size := len(str) + 1 ptr, _, _ := procMalloc.Call(uintptr(size)) if ptr == 0 { return nil } // 复制字符串内容 for i := 0; i < len(str); i++ { *(*byte)(unsafe.Pointer(ptr + uintptr(i))) = str[i] } *(*byte)(unsafe.Pointer(ptr + uintptr(len(str)))) = 0 // 结尾加 \0 return unsafe.Pointer(ptr) } // freeCString 释放 C 字符串 func freeCString(ptr unsafe.Pointer) { if ptr != nil { procFree.Call(uintptr(ptr)) } } // cStr 将 C 字符串指针转换为 Go 字符串 func cStr(ptr uintptr) string { if ptr == 0 { return "" } var b []byte for { c := *(*byte)(unsafe.Pointer(ptr)) if c == 0 { break } b = append(b, c) ptr++ } return string(b) }