You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
1.7 KiB
85 lines
1.7 KiB
package asset
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image"
|
|
"image/jpeg"
|
|
"image/png"
|
|
"io"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"golang.org/x/image/draw"
|
|
)
|
|
|
|
// IsImageResizable returns whether or not an image can be resized, based on its
|
|
// extension.
|
|
func IsImageResizable(path string) bool {
|
|
switch strings.ToLower(filepath.Ext(path)) {
|
|
case ".jpg", ".jpeg", ".png":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
type imageLoader struct {
|
|
loader Loader
|
|
}
|
|
|
|
// NewImageLoader wraps an existing Loader in order to perform various
|
|
// image-related transformations on any image assets being loaded. Non-image
|
|
// assets are loaded as-is.
|
|
func NewImageLoader(loader Loader) Loader {
|
|
return &imageLoader{loader}
|
|
}
|
|
|
|
func (l *imageLoader) Load(path string, into io.Writer, opts LoadOpts) error {
|
|
|
|
if opts.ImageWidth == 0 {
|
|
return l.loader.Load(path, into, opts)
|
|
}
|
|
|
|
if !IsImageResizable(path) {
|
|
return ErrCannotResize
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
if err := l.loader.Load(path, buf, opts); err != nil {
|
|
return fmt.Errorf("loading image into buffer: %w", err)
|
|
}
|
|
|
|
img, format, err := image.Decode(buf)
|
|
if err != nil {
|
|
return fmt.Errorf("decoding image: %w", err)
|
|
}
|
|
|
|
maxWidth := float64(opts.ImageWidth)
|
|
imgRect := img.Bounds()
|
|
imgW, imgH := float64(imgRect.Dx()), float64(imgRect.Dy())
|
|
|
|
if imgW > maxWidth {
|
|
|
|
newH := imgH * maxWidth / imgW
|
|
newImg := image.NewRGBA(image.Rect(0, 0, int(maxWidth), int(newH)))
|
|
|
|
// Resize
|
|
draw.BiLinear.Scale(
|
|
newImg, newImg.Bounds(), img, img.Bounds(), draw.Over, nil,
|
|
)
|
|
|
|
img = newImg
|
|
}
|
|
|
|
switch format {
|
|
case "jpeg":
|
|
return jpeg.Encode(into, img, nil)
|
|
case "png":
|
|
return png.Encode(into, img)
|
|
default:
|
|
return fmt.Errorf("unknown image format %q", format)
|
|
}
|
|
|
|
}
|
|
|