forked from h2non/imaginary
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgif_handler.go
109 lines (88 loc) · 2.38 KB
/
gif_handler.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
"bytes"
"image"
"math"
"time"
"github.com/kumparan/bimg"
log "github.com/sirupsen/logrus"
"github.com/disintegration/imaging"
"willnorris.com/go/gifresize"
)
var resampleFilter = imaging.Lanczos
func ProcessGIF(imageBuf []byte, opts bimg.Options) (out Image, err error) {
start := time.Now()
resultBuffer := new(bytes.Buffer)
fn := func(img image.Image) image.Image {
return transformGIFFrame(img, opts)
}
err = gifresize.Process(resultBuffer, bytes.NewReader(imageBuf), fn)
if err != nil {
return Image{}, err
}
// keep this loggerto monitor performance?
log.Println("gif process duration: ", time.Since(start))
resultByte := resultBuffer.Bytes()
mime := GetImageMimeType(bimg.DetermineImageType(resultByte))
return Image{Body: resultByte, Mime: mime}, nil
}
func transformGIFFrame(m image.Image, opts bimg.Options) image.Image {
// Parse crop and resize parameters before applying any transforms.
// This is to ensure that any percentage-based values are based off the
// size of the original image.
w, h, resize := resizeGIFParams(m, opts)
// resize if needed
if resize {
if opts.Crop {
m = imaging.Thumbnail(m, w, h, resampleFilter)
} else {
m = imaging.Resize(m, w, h, resampleFilter)
}
}
// rotate
rotate := float64(opts.Rotate) - math.Floor(float64(opts.Rotate)/360)*360
switch rotate {
case 90:
m = imaging.Rotate90(m)
case 180:
m = imaging.Rotate180(m)
case 270:
m = imaging.Rotate270(m)
}
// flip vertical
if opts.Flip {
m = imaging.FlipV(m)
}
// flip horizontal
if opts.Flop {
m = imaging.FlipH(m)
}
return m
}
func resizeGIFParams(m image.Image, opts bimg.Options) (w, h int, resize bool) {
// convert percentage width and height values to absolute values
imgW := m.Bounds().Dx()
imgH := m.Bounds().Dy()
w = EvaluateFloat(float64(opts.Width), imgW)
h = EvaluateFloat(float64(opts.Height), imgH)
// if requested width and height match the original, skip resizing
if (w == imgW || w == 0) && (h == imgH || h == 0) {
return 0, 0, false
}
if opts.Crop && w == 0 { // if crop = true and w is 0, then set w with source image width
w = imgW
}
if opts.Crop && h == 0 { // if crop = true and h is 0, then set h with source image height
h = imgH
}
return w, h, true
}
func EvaluateFloat(f float64, max int) int {
if 0 < f && f < 1 {
return int(float64(max) * f)
}
if f < 0 {
return 0
}
return int(f)
}