daShangDao_utils/imglib/loader.go
Cai1Cai1 a92f8e2c10 feat: 初始版本 v1.0.0
- 新增 imglib 包,支持 FilePath/URL/Base64 三种图片输入方式
- 纯白占比检测、白底居中合成、等比缩放、去白边、裁切
- 二维码生成与识别、条形码生成(Code128/EAN13/Code39)
- 中文文字图片、书籍信息水印、通用水印叠加
- 输出辅助:EncodeToBytes/EncodeToBase64/SaveToFile/SaveJPEG/SavePNG
- 字体缓存,避免重复加载
- 完整测试覆盖(23个测试用例)
2026-06-30 11:56:28 +08:00

124 lines
3.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package imglib
import (
"bytes"
"encoding/base64"
"fmt"
"image"
_ "image/jpeg"
_ "image/png"
"os"
"strings"
"time"
"github.com/valyala/fasthttp"
)
// ImageInput 统一图片输入源,支持三种加载方式
type ImageInput struct {
FilePath string // 磁盘文件路径
URL string // 网络 URLhttp/https
Base64 string // Base64 编码的图片数据(可带 data:image/xxx;base64, 前缀)
}
// NewImageInputFromFile 从文件路径创建输入源
func NewImageInputFromFile(path string) ImageInput {
return ImageInput{FilePath: path}
}
// NewImageInputFromURL 从网络 URL 创建输入源
func NewImageInputFromURL(url string) ImageInput {
return ImageInput{URL: url}
}
// NewImageInputFromBase64 从 Base64 字符串创建输入源
func NewImageInputFromBase64(b64 string) ImageInput {
return ImageInput{Base64: b64}
}
// Load 加载图片,返回解码后的 image.Image 和格式名称
func (in ImageInput) Load() (image.Image, string, error) {
switch {
case in.Base64 != "":
return loadImageFromBase64(in.Base64)
case in.URL != "":
return loadImageFromURL(in.URL, 120)
case in.FilePath != "":
return loadImageFromFile(in.FilePath)
default:
return nil, "", fmt.Errorf("ImageInput 未设置任何输入源FilePath/URL/Base64 均为空)")
}
}
// loadImageFromFile 从磁盘文件加载图片
func loadImageFromFile(path string) (image.Image, string, error) {
file, err := os.Open(path)
if err != nil {
return nil, "", fmt.Errorf("打开图片文件失败: %v", err)
}
defer file.Close()
img, format, err := image.Decode(file)
if err != nil {
return nil, "", fmt.Errorf("解码图片失败: %v", err)
}
return img, format, nil
}
// loadImageFromURL 从网络 URL 加载图片
func loadImageFromURL(url string, timeout int) (image.Image, string, error) {
if timeout <= 0 {
timeout = 120
}
req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseRequest(req)
defer fasthttp.ReleaseResponse(resp)
req.SetRequestURI(url)
req.Header.SetMethod("GET")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
req.Header.Set("Accept", "image/avif,image/webp,image/apng,image/*,*/*;q=0.8")
client := &fasthttp.Client{
ReadTimeout: time.Duration(timeout) * time.Second,
WriteTimeout: time.Duration(timeout) * time.Second,
}
err := client.Do(req, resp)
if err != nil {
return nil, "", fmt.Errorf("请求失败: %v", err)
}
body := resp.Body()
imgData := make([]byte, len(body))
copy(imgData, body)
img, format, err := image.Decode(bytes.NewReader(imgData))
if err != nil {
return nil, "", fmt.Errorf("解码图片失败: %v", err)
}
return img, format, nil
}
// loadImageFromBase64 从 Base64 字符串加载图片
func loadImageFromBase64(b64 string) (image.Image, string, error) {
b64 = strings.TrimPrefix(b64, "data:image/jpeg;base64,")
b64 = strings.TrimPrefix(b64, "data:image/jpg;base64,")
b64 = strings.TrimPrefix(b64, "data:image/png;base64,")
b64 = strings.TrimPrefix(b64, "data:image/gif;base64,")
b64 = strings.TrimPrefix(b64, "data:image/webp;base64,")
imgData, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
return nil, "", fmt.Errorf("解码 base64 失败: %v", err)
}
img, format, err := image.Decode(bytes.NewReader(imgData))
if err != nil {
return nil, "", fmt.Errorf("解码 base64 图片失败: %v", err)
}
return img, format, nil
}