summaryrefslogtreecommitdiff
path: root/src/post/asset/loader_image.go
blob: dc996a9f8c35b18301060f48c7ff81a044bede54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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)
	}

}