go-imager/pkg/img/info.go
Simon Vieille 8d1567a54a
feat: add effects
feat: add setting types
2025-09-08 21:31:46 +02:00

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,
}
}