apps/shrink/image.go 1.2 K raw
1
package main
2
3
import (
4
	"bytes"
5
	"fmt"
6
	"image"
7
	"image/jpeg"
8
	_ "image/png"
9
	"path/filepath"
10
	"strings"
11
12
	"golang.org/x/image/draw"
13
)
14
15
func compressImage(data []byte, quality int, width int) ([]byte, error) {
16
	exif := stripGPS(extractExif(data))
17
	img, _, err := image.Decode(bytes.NewReader(data))
18
	if err != nil {
19
		return nil, fmt.Errorf("Failed to decode image: %w", err)
20
	}
21
	if width > 0 && width != img.Bounds().Dx() {
22
		src := img
23
		bounds := src.Bounds()
24
		aspect := float64(bounds.Dy()) / float64(bounds.Dx())
25
		height := int(float64(width)*aspect + 0.5)
26
		dst := image.NewRGBA(image.Rect(0, 0, width, height))
27
		draw.CatmullRom.Scale(dst, dst.Bounds(), src, bounds, draw.Over, nil)
28
		img = dst
29
	}
30
	if quality < 1 {
31
		quality = 1
32
	}
33
	if quality > 100 {
34
		quality = 100
35
	}
36
	var out bytes.Buffer
37
	if err := jpeg.Encode(&out, img, &jpeg.Options{Quality: quality}); err != nil {
38
		return nil, fmt.Errorf("JPEG encoding failed: %w", err)
39
	}
40
	return injectExif(out.Bytes(), exif), nil
41
}
42
43
func buildDownloadFilename(original, newExt string) string {
44
	stem := strings.TrimSuffix(filepath.Base(original), filepath.Ext(filepath.Base(original)))
45
	if stem == "" {
46
		stem = "compressed"
47
	}
48
	return stem + "_compressed." + newExt
49
}