182 lines
4.3 KiB
Go
182 lines
4.3 KiB
Go
package img
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"image"
|
|
"image/color"
|
|
"image/jpeg"
|
|
_ "image/jpeg"
|
|
"image/png"
|
|
_ "image/png"
|
|
"math"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/disintegration/imaging"
|
|
"github.com/spf13/cast"
|
|
)
|
|
|
|
type ImageInfo struct {
|
|
Path string `json:"path"`
|
|
Base64 string `json:"base64"`
|
|
Type string `json:"type"`
|
|
Width int `json:"width"`
|
|
Height int `json:"height"`
|
|
Image image.Image `json:"-"`
|
|
}
|
|
|
|
type ImageEffect struct {
|
|
Name string `json:"name"`
|
|
Settings map[string]any `json:"settings"`
|
|
}
|
|
|
|
func GetImageInfo(file string) *ImageInfo {
|
|
content, err := os.ReadFile(file)
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
reader, err := os.Open(file)
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
defer reader.Close()
|
|
|
|
i, t, err := image.Decode(reader)
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
info := ImageInfo{
|
|
Path: file,
|
|
Base64: base64.StdEncoding.EncodeToString(content),
|
|
Type: t,
|
|
Width: i.Bounds().Dx(),
|
|
Height: i.Bounds().Dy(),
|
|
Image: i,
|
|
}
|
|
|
|
return &info
|
|
}
|
|
|
|
func ApplyFilters(src *ImageInfo, effects []ImageEffect) *ImageInfo {
|
|
base := GetImageInfo(src.Path)
|
|
result := base.Image
|
|
quality := 100
|
|
|
|
for _, effect := range effects {
|
|
if effect.Name == "scale-width" {
|
|
width := cast.ToFloat64(effect.Settings["value"])
|
|
height := cast.ToInt(math.Round(float64(result.Bounds().Dy()) * width / float64(result.Bounds().Dx())))
|
|
|
|
result = imaging.Resize(
|
|
result,
|
|
cast.ToInt(width),
|
|
cast.ToInt(height),
|
|
imaging.Lanczos,
|
|
)
|
|
} else if effect.Name == "scale-height" {
|
|
height := cast.ToFloat64(effect.Settings["value"])
|
|
width := cast.ToInt(math.Round(float64(result.Bounds().Dx()) * height / float64(result.Bounds().Dy())))
|
|
|
|
result = imaging.Resize(
|
|
result,
|
|
cast.ToInt(width),
|
|
cast.ToInt(height),
|
|
imaging.Lanczos,
|
|
)
|
|
} else if effect.Name == "crop" {
|
|
result = imaging.Crop(
|
|
result,
|
|
image.Rect(
|
|
cast.ToInt(effect.Settings["x0"]),
|
|
cast.ToInt(effect.Settings["y0"]),
|
|
cast.ToInt(effect.Settings["x1"]),
|
|
cast.ToInt(effect.Settings["y1"]),
|
|
),
|
|
)
|
|
} else if effect.Name == "crop-center" {
|
|
result = imaging.CropCenter(
|
|
result,
|
|
cast.ToInt(effect.Settings["width"]),
|
|
cast.ToInt(effect.Settings["height"]),
|
|
)
|
|
} else if effect.Name == "resize" {
|
|
result = imaging.Resize(
|
|
result,
|
|
cast.ToInt(effect.Settings["width"]),
|
|
cast.ToInt(effect.Settings["height"]),
|
|
imaging.Lanczos,
|
|
)
|
|
} else if effect.Name == "brightness" {
|
|
result = imaging.AdjustBrightness(result, cast.ToFloat64(effect.Settings["value"]))
|
|
} else if effect.Name == "contrast" {
|
|
result = imaging.AdjustContrast(result, cast.ToFloat64(effect.Settings["value"]))
|
|
} else if effect.Name == "saturation" {
|
|
result = imaging.AdjustSaturation(result, cast.ToFloat64(effect.Settings["value"]))
|
|
} else if effect.Name == "gamma" {
|
|
result = imaging.AdjustGamma(result, cast.ToFloat64(effect.Settings["value"]))
|
|
} else if effect.Name == "blur" {
|
|
result = imaging.Blur(result, cast.ToFloat64(effect.Settings["value"]))
|
|
} else if effect.Name == "flip-v" {
|
|
result = imaging.FlipV(result)
|
|
} else if effect.Name == "flip-h" {
|
|
result = imaging.FlipH(result)
|
|
} else if effect.Name == "rotate-90" {
|
|
result = imaging.Rotate90(result)
|
|
} else if effect.Name == "rotate-180" {
|
|
result = imaging.Rotate180(result)
|
|
} else if effect.Name == "rotate-270" {
|
|
result = imaging.Rotate270(result)
|
|
} else if effect.Name == "quality" {
|
|
quality = cast.ToInt(effect.Settings["value"])
|
|
} else if effect.Name == "rotate" {
|
|
values, err := strconv.ParseUint(string(effect.Settings["backgroundColor"].(string)[1:]), 16, 32)
|
|
|
|
if err == nil {
|
|
result = imaging.Rotate(
|
|
result,
|
|
cast.ToFloat64(effect.Settings["value"]),
|
|
color.RGBA{
|
|
R: uint8(values >> 16),
|
|
G: uint8((values >> 8) & 0xFF),
|
|
B: uint8(values & 0xFF),
|
|
A: 255,
|
|
},
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
buff := new(bytes.Buffer)
|
|
|
|
if src.Type == "jpeg" {
|
|
err := jpeg.Encode(buff, result, &jpeg.Options{
|
|
Quality: quality,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
} else {
|
|
err := png.Encode(buff, result)
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return &ImageInfo{
|
|
Path: "",
|
|
Base64: base64.StdEncoding.EncodeToString(buff.Bytes()),
|
|
Type: base.Type,
|
|
Width: result.Bounds().Dx(),
|
|
Height: result.Bounds().Dy(),
|
|
Image: result,
|
|
}
|
|
}
|