Files
webp/models/image.go
2023-11-13 22:36:58 +08:00

127 lines
3.7 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 models
import (
"image"
"io"
"log"
"net/http"
"regexp"
"github.com/chai2010/webp"
"github.com/disintegration/imaging"
giftowebp "github.com/sizeofint/gif-to-webp"
)
// Image is a struct that contains the information of an image
type Image struct {
image image.Image
format string
data []byte
}
// 初始化图片
func (img *Image) Init(content string) (err error) {
var body io.ReadCloser
if len(regexp.MustCompile(`image.gameuiux.cn`).FindStringSubmatch(content)) > 0 {
key := regexp.MustCompile(`^https?://image.gameuiux.cn/`).ReplaceAllString(content, "")
// 从OSS中读取图片
bucket := GetBucket("gameui-image2")
body, err = bucket.GetObject(key)
if err != nil {
log.Println("读取图片失败", err)
return
}
defer body.Close()
// 判断图片格式是否为 gif 或 GIF
if len(regexp.MustCompile(`\.gif$`).FindStringSubmatch(key)) > 0 {
img.format = "gif"
img.data, err = io.ReadAll(body)
if err != nil {
log.Println("读取图片失败", err)
return
}
return
}
// 将文件解码为 image.Image
img.image, img.format, err = image.Decode(body)
if err != nil {
log.Println("解码图像失败", err)
return
}
return
} else {
var resp *http.Response
log.Println("直接从网络下载图片:", content)
resp, err = http.Get(content)
if err != nil {
log.Println("下载图片失败", err)
return
}
defer resp.Body.Close()
// 判断图片格式是否为 gif 或 GIF
if len(regexp.MustCompile(`\.gif$`).FindStringSubmatch(content)) > 0 {
img.format = "gif"
img.data, err = io.ReadAll(resp.Body)
if err != nil {
log.Println("读取图片失败", err)
return
}
println("数据长度:", len(img.data))
return
}
// 将文件解码为 image.Image
img.image, img.format, err = image.Decode(resp.Body)
if err != nil {
log.Println("解码图像失败", err)
return
}
return
}
}
// 将图片输出为指定尺寸的 webp 格式(默认使用 Lanczos 缩放算法)
func (img *Image) ToWebP(width int, height int, fit string) ([]byte, error) {
// 如果原图是GIF格式的动态图片直接不作尺寸处理直接转换为webp格式
if img.format == "gif" {
converter := giftowebp.NewConverter()
converter.LoopCompatibility = true // 是否兼容循环动画
converter.WebPConfig.SetLossless(1) // 0 有损压缩 1无损压缩
converter.WebPConfig.SetMethod(6) // 压缩速度 0-6 0最快 6质量最好
converter.WebPConfig.SetQuality(100) // 压缩质量 0-100
converter.WebPAnimEncoderOptions.SetKmin(9)
converter.WebPAnimEncoderOptions.SetKmax(17)
return converter.Convert(img.data)
}
// 如果指定了宽高却没有指定fit, 则默认fit为cover
if width != 0 && height != 0 && fit == "" {
fit = "cover"
}
// 如果未指定宽高和fit, 则不缩放图片直接返回webp
if width == 0 && height == 0 && fit == "" {
return webp.EncodeRGBA(img.image, 100)
}
switch fit {
case "cover":
return webp.EncodeRGBA(imaging.Fill(img.image, width, height, imaging.Center, imaging.Lanczos), 100)
case "contain":
return webp.EncodeRGBA(imaging.Fit(img.image, width, height, imaging.Lanczos), 100)
case "fill":
return webp.EncodeRGBA(imaging.Fill(img.image, width, height, imaging.Center, imaging.Lanczos), 100)
case "inside":
return webp.EncodeRGBA(imaging.Fit(img.image, width, height, imaging.Lanczos), 100)
case "outside":
return webp.EncodeRGBA(imaging.Fill(img.image, width, height, imaging.Center, imaging.Lanczos), 100)
case "scale-down":
return webp.EncodeRGBA(imaging.Fit(img.image, width, height, imaging.Lanczos), 100)
default:
return webp.EncodeRGBA(imaging.Resize(img.image, width, height, imaging.Lanczos), 100)
}
}