resource_manager/domain/resize/resize.go

106 lines
2.6 KiB
Go

package resize
import (
"bytes"
"github.com/anthonynsimon/bild/transform"
"image"
"image/jpeg"
"image/png"
"io"
)
var mimeTypes = map[string]string{
"image/jpg": "image/jpg",
"image/jpeg": "image/jpeg",
"image/png": "image/png",
}
func IsResizable(mimeType string) bool {
_, present := mimeTypes[mimeType]
return present
}
type ResizeType int
const (
// Cover - resize preserving image aspect
// - resizes to the smallest image where both width and height are larger or equal to given size
Cover ResizeType = iota
// Contain - resize preserving image aspect
// - resizes to the largest image where both width and height are smaller or equal to given size
Contain ResizeType = iota
// ExactHeight - resize preserving image aspect
// - resizes to the image with given height
ExactHeight ResizeType = iota
// ExactWidth - resize preserving image aspect
// - resizes to the image with given width
ExactWidth ResizeType = iota
// Exact - resize without preserving image aspect
// - resizes to exact size defined in request
Exact ResizeType = iota
)
type Resize struct {
Height int
Width int
Type ResizeType
}
func ResizeImage(imageBytes []byte, resize Resize) ([]byte, error) {
img, format, err := image.Decode(bytes.NewReader(imageBytes))
if err != nil {
return nil, err
}
var buffer bytes.Buffer
writer := io.Writer(&buffer)
resizeWidth, resizeHeight := calculateResizedDimensions(img.Bounds(), resize)
img = transform.Resize(img, resizeWidth, resizeHeight, transform.Gaussian)
switch format {
case "png":
err = png.Encode(writer, img)
case "jpeg":
err = jpeg.Encode(writer, img, nil)
default:
err = jpeg.Encode(writer, img, nil)
}
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func calculateResizedDimensions(bounds image.Rectangle, resize Resize) (width int, height int) {
width = bounds.Dx()
height = bounds.Dy()
switch resize.Type {
case Cover:
rWidth := resize.Height * width / height
if rWidth >= resize.Width {
return rWidth, resize.Height
}
rHeight := resize.Width * height / width
if rHeight >= resize.Height {
return resize.Width, rHeight
}
case Contain:
rWidth := resize.Height * width / height
if rWidth <= resize.Width {
return rWidth, resize.Height
}
rHeight := resize.Width * height / width
if rHeight <= resize.Height {
return resize.Width, rHeight
}
case ExactHeight:
rWidth := resize.Height * width / height
return rWidth, resize.Height
case ExactWidth:
rHeight := resize.Width * height / width
return resize.Width, rHeight
}
return
}