Files
guz.one/internals/image.go
2024-06-12 16:08:12 -03:00

133 lines
2.1 KiB
Go

package internals
import (
"bytes"
"errors"
"image"
"image/gif"
"image/jpeg"
"image/png"
"io"
"math"
"net/http"
"github.com/chai2010/webp"
"github.com/disintegration/imaging"
)
type Image struct {
image.Image
mime string
JpegOptions jpeg.Options
GifOptions gif.Options
WebpOptions webp.Options
}
func NewImage(b []byte) (Image, error) {
m := http.DetectContentType(b)
r := bytes.NewReader(b)
var img image.Image
var err error
switch m {
case "image/png":
img, err = png.Decode(r)
case "image/jpeg":
img, err = jpeg.Decode(r)
case "image/gif":
img, err = gif.Decode(r)
case "image/webp":
img, err = webp.Decode(r)
default:
err = errors.ErrUnsupported
}
if err != nil {
return Image{}, err
}
image := img.(Image)
image.mime = m
image.JpegOptions = jpeg.Options{
Quality: 70,
}
image.GifOptions = gif.Options{
NumColors: 256 / 2,
}
image.WebpOptions = webp.Options{
Lossless: true,
Quality: 70.0,
Exact: true,
}
return image, nil
}
func (i *Image) Decode(b []byte) error {
img, err := NewImage(b)
*i = img
return err
}
func (i *Image) Encode(w io.Writer) error {
var err error
switch i.mime {
case "image/png":
err = png.Encode(w, i.Image)
case "image/jpeg":
err = jpeg.Encode(w, i.Image, &jpeg.Options{Quality: 70})
case "image/gif":
err = gif.Encode(w, i.Image, &gif.Options{NumColors: 256})
case "image/webp":
err = webp.Encode(w, i.Image, &webp.Options{Lossless: true})
default:
err = errors.ErrUnsupported
}
if err != nil {
return err
}
return nil
}
func (i *Image) Quality(q float64) {
i.WebpOptions.Quality = float32(q)
i.JpegOptions.Quality = int(math.Round(q))
}
func (i *Image) Optimize(threshold int) {
w := i.Bounds().Max.X
if threshold >= w {
return
}
d := threshold / w
i.Scale(d * -1)
}
func (i *Image) Scale(s int) {
r := i.Bounds()
w, h := r.Max.X, r.Max.Y
var nw, nh int
if s < 0 {
s = s * -1
nw, nh = w/s, h/s
} else if s > 0 {
s = s * -1
nw, nh = w*s, h*s
} else {
nw, nh = w, h
}
imaging.Resize(i, nw, nh, imaging.CatmullRom)
}
func (i *Image) GetMime() string {
return i.mime
}