-
Notifications
You must be signed in to change notification settings - Fork 2
/
transform.go
83 lines (75 loc) · 2.01 KB
/
transform.go
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
package imagecoding
import (
"bytes"
"errors"
"image"
"image/color"
"image/gif"
"image/png"
"github.com/disintegration/imaging"
"github.com/h2non/filetype"
"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
"golang.org/x/image/webp"
)
// Transform scales, colormaps and orients an image according to input param
func Transform(data []byte, grayscale bool, scale ScaleFunc) (out image.Image, width, height int, scaleFactor float64, err error) {
if len(data) == 0 {
return nil, 0, 0, 0, ErrEmptyInput
}
// Look at the magic bytes to determine the file type
kind, err := filetype.Match(data)
if err != nil {
return nil, 0, 0, 0, errors.New("could not determine file type")
}
format := ImgFormat(kind.Extension)
var img image.Image
imagefile := bytes.NewReader(data)
switch format {
case Webp:
img, err = webp.Decode(imagefile)
case Png:
img, err = png.Decode(imagefile)
case Jpeg:
// Early return for JPEG fast path
return TransformJpeg(data, grayscale, scale)
case Tiff:
orient := GetOrientation(imagefile)
img, err = tiff.Decode(imagefile)
img = FixOrientation(img, orient)
case Gif:
img, err = gif.Decode(imagefile)
case Bmp:
img, err = bmp.Decode(imagefile)
case Heif:
return TransformHeif(data, grayscale, scale)
default:
err = image.ErrFormat
}
if err != nil {
return nil, 0, 0, 0, err
}
width = img.Bounds().Dx()
height = img.Bounds().Dy()
// Scale the image
imgWidth, imgHeight, scaleFactor := scale(img.Bounds().Dx(), img.Bounds().Dy())
if scaleFactor > 1.1 || scaleFactor < 0.9 {
img = imaging.Resize(img, imgWidth, imgHeight, imaging.CatmullRom)
} else {
scaleFactor = 1
}
if grayscale {
// Drop the channels we don't need by converting to image.Gray
bounds := img.Bounds()
imgGray := image.NewGray(bounds)
for y := 0; y < bounds.Max.Y; y++ {
for x := 0; x < bounds.Max.X; x++ {
oldPixel := img.At(x, y)
pixel := color.GrayModel.Convert(oldPixel)
imgGray.Set(x, y, pixel)
}
}
img = imgGray
}
return img, width, height, scaleFactor, nil
}