From 560151a72d989001762453a2f96e8e8b872c4507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A1=9C=E8=8F=AF?= Date: Wed, 7 Jun 2023 00:37:59 +0800 Subject: [PATCH] webp --- go.mod | 9 +++++++- go.sum | 14 ++++++++++++ models/Image.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index cf2d832..276540a 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,18 @@ require ( gorm.io/gorm v1.25.1 ) -require github.com/mattn/go-sqlite3 v1.14.16 // indirect +require ( + github.com/mattn/go-sqlite3 v1.14.16 // indirect + github.com/sizeofint/webp-animation v0.0.0-20190207194838-b631dc900de9 // indirect + golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect +) require ( + github.com/chai2010/webp v1.1.1 + github.com/disintegration/imaging v1.6.2 github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/sizeofint/gif-to-webp v0.0.0-20210224202734-e9d7ed071591 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.669 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.669 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index e6fd2e6..24d7247 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk= +github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -13,10 +17,20 @@ github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwp github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/sizeofint/gif-to-webp v0.0.0-20210224202734-e9d7ed071591 h1:dCWBD4Xchp/XFIR/x6D2l74DtQHvIpHsmpPRHgH9oUo= +github.com/sizeofint/gif-to-webp v0.0.0-20210224202734-e9d7ed071591/go.mod h1:IXC7KN2FEuTEISdePm37qcFyXInAh6pfW35yDjbdfOM= +github.com/sizeofint/webp-animation v0.0.0-20190207194838-b631dc900de9 h1:i3LYMwQ0zkh/BJ47vIZN+jBYqV4/f6DFoAsW8rwV490= +github.com/sizeofint/webp-animation v0.0.0-20190207194838-b631dc900de9/go.mod h1:/NQ8ciRuH+vxYhrFlnX70gvXBugMYQbBygCRocFgSZ4= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.669 h1:5KKJBcemqKONBFxMdMyLMvk+TrqXaEPhqe9TrZqB3r0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.669/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.669 h1:gc1bPO/YVfuXEIs+HbQ/gFlFjdkJjOsjm8xWqF7hPww= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.669/go.mod h1:hhy13j6NKKxt/g62JZEDekJNQx3EAevnHopmwlt2tRc= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/models/Image.go b/models/Image.go index ea24499..22bd85e 100644 --- a/models/Image.go +++ b/models/Image.go @@ -1,10 +1,18 @@ package models import ( + "bytes" "database/sql/driver" "encoding/json" + "fmt" + "image" + "io/ioutil" "main/configs" "time" + + "github.com/chai2010/webp" + "github.com/disintegration/imaging" + giftowebp "github.com/sizeofint/gif-to-webp" ) type Image struct { @@ -24,6 +32,56 @@ type Image struct { UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` } +// 将图片输出为指定尺寸的 webp 格式(默认使用 Lanczos 缩放算法) +func (img *Image) ToWebP(width int, height int, fit string) ([]byte, error) { + // 從絕對路徑讀原始圖片 + data, err := ioutil.ReadFile(fmt.Sprintf("data/images/%d", img.ID)) + if err != nil { + return nil, err + } + // 將原始圖片轉換為 Image + imageData, format, err := image.Decode(bytes.NewReader(data)) + if err != nil { + return nil, err + } + + // 如果原图是GIF格式的动态图片,直接不作尺寸处理,直接转换为webp格式 + if 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(data) + } + // 如果指定了宽高却没有指定fit, 则默认fit为cover + if width != 0 && height != 0 && fit == "" { + fit = "cover" + } + // 如果未指定宽高和fit, 则不缩放图片直接返回webp + if width == 0 && height == 0 && fit == "" { + return webp.EncodeRGBA(imageData, 100) + } + switch fit { + case "cover": + return webp.EncodeRGBA(imaging.Fill(imageData, width, height, imaging.Center, imaging.Lanczos), 100) + case "contain": + return webp.EncodeRGBA(imaging.Fit(imageData, width, height, imaging.Lanczos), 100) + case "fill": + return webp.EncodeRGBA(imaging.Fill(imageData, width, height, imaging.Center, imaging.Lanczos), 100) + case "inside": + return webp.EncodeRGBA(imaging.Fit(imageData, width, height, imaging.Lanczos), 100) + case "outside": + return webp.EncodeRGBA(imaging.Fill(imageData, width, height, imaging.Center, imaging.Lanczos), 100) + case "scale-down": + return webp.EncodeRGBA(imaging.Fit(imageData, width, height, imaging.Lanczos), 100) + default: + return webp.EncodeRGBA(imaging.Resize(imageData, width, height, imaging.Lanczos), 100) + } +} + func init() { configs.ORMDB().AutoMigrate(&Image{}) }