go-imager/pkg/img/info.go
2025-09-05 09:02:08 +02:00

152 lines
3.4 KiB
Go

package img
import (
"bytes"
"encoding/base64"
"image"
"image/jpeg"
_ "image/jpeg"
"image/png"
_ "image/png"
"math"
"os"
"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]float32 `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
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"]))
}
}
buff := new(bytes.Buffer)
if src.Type == "jpeg" {
err := jpeg.Encode(buff, result, &jpeg.Options{
Quality: 100,
})
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,
}
}