webp
This commit is contained in:
		@@ -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{})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user