@@ -18,13 +18,14 @@ import (
18
18
"github.com/chai2010/webp"
19
19
"github.com/disintegration/imaging"
20
20
"github.com/dustin/go-humanize"
21
- "github.com/rwcarlsen/goexif/exif"
22
- "golang.org/x/image/draw"
21
+ _ "golang.org/x/image/webp" // 注册解码器
23
22
)
24
23
25
24
// SizeLimit 上传大小限制
26
25
var SizeLimit = humanize .MiByte * config .Config .GetInt64 ("oss.limit" )
27
26
27
+ var maxLongEdge = config .Config .GetInt ("oss.thumbnailLongEdge" )
28
+
28
29
var invalidCharRegex = regexp .MustCompile (`[:*?"<>|]` )
29
30
30
31
var genLocks sync.Map
@@ -53,16 +54,10 @@ func CleanLocation(location string) string {
53
54
54
55
// ConvertToWebP 将图片转换为 WebP 格式
55
56
func ConvertToWebP (reader io.Reader ) (* bytes.Reader , error ) {
56
- data , err := io .ReadAll (reader )
57
- if err != nil {
58
- return nil , err
59
- }
60
-
61
- img , _ , err := image .Decode (bytes .NewReader (data ))
57
+ img , err := imaging .Decode (reader , imaging .AutoOrientation (true ))
62
58
if err != nil {
63
59
return nil , err
64
60
}
65
- img , _ = fixOrientation (img , bytes .NewReader (data ))
66
61
67
62
buf , _ := bufferPool .Get ().(* bytes.Buffer )
68
63
buf .Reset ()
@@ -78,50 +73,6 @@ func ConvertToWebP(reader io.Reader) (*bytes.Reader, error) {
78
73
return bytes .NewReader (buf .Bytes ()), nil
79
74
}
80
75
81
- // fixOrientation 修复图片的旋转
82
- func fixOrientation (img image.Image , exifData io.Reader ) (image.Image , error ) {
83
- x , err := exif .Decode (exifData )
84
- if err != nil {
85
- return nil , err
86
- }
87
-
88
- tag , err := x .Get (exif .Orientation )
89
- if err != nil {
90
- return nil , err
91
- }
92
-
93
- orientation , err := tag .Int (0 )
94
- if err != nil {
95
- return nil , err
96
- }
97
-
98
- return applyOrientation (img , orientation ), nil
99
- }
100
-
101
- // applyOrientation 根据 EXIF Orientation 调整图像方向
102
- func applyOrientation (img image.Image , orientation int ) image.Image {
103
- switch orientation {
104
- case 1 : // 正常
105
- return img
106
- case 2 : // 水平翻转
107
- return imaging .FlipH (img )
108
- case 3 : // 旋转 180°
109
- return imaging .Rotate180 (img )
110
- case 4 : // 垂直翻转
111
- return imaging .FlipV (img )
112
- case 5 : // 顺时针 90° + 水平翻转
113
- return imaging .FlipH (imaging .Rotate270 (img ))
114
- case 6 : // 顺时针 90°
115
- return imaging .Rotate270 (img )
116
- case 7 : // 顺时针 90° + 垂直翻转
117
- return imaging .FlipV (imaging .Rotate270 (img ))
118
- case 8 : // 逆时针 90°
119
- return imaging .Rotate90 (img )
120
- default :
121
- return img
122
- }
123
- }
124
-
125
76
// GetThumbnail 获取缩略图
126
77
func GetThumbnail (bucket string , objectKey string ) (io.ReadCloser , int64 , error ) {
127
78
filename := bucket + "-" + objectKey
@@ -163,12 +114,12 @@ func GetThumbnail(bucket string, objectKey string) (io.ReadCloser, int64, error)
163
114
}()
164
115
165
116
// 解码图片
166
- img , err := decodeImg (object )
117
+ img , err := imaging . Decode (object , imaging . AutoOrientation ( true ) )
167
118
if err != nil {
168
119
return nil , 0 , err
169
120
}
170
121
img = removeAlpha (img )
171
- finalImg := resizeIfNeeded (img , config . Config . GetInt ( "oss.thumbnailLongEdge" ) )
122
+ finalImg := imaging . Fit (img , maxLongEdge , maxLongEdge , imaging . CatmullRom )
172
123
173
124
buf , _ := bufferPool .Get ().(* bytes.Buffer )
174
125
buf .Reset ()
@@ -189,29 +140,6 @@ func GetThumbnail(bucket string, objectKey string) (io.ReadCloser, int64, error)
189
140
return io .NopCloser (bytes .NewReader (buf .Bytes ())), int64 (buf .Len ()), nil
190
141
}
191
142
192
- func resizeIfNeeded (img image.Image , targetLongSide int ) image.Image {
193
- b := img .Bounds ()
194
- w , h := b .Dx (), b .Dy ()
195
- longSide , shortSide := max (w , h ), min (w , h )
196
-
197
- if longSide <= targetLongSide {
198
- return img
199
- }
200
- scale := float64 (targetLongSide ) / float64 (longSide )
201
- targetShort := int (float64 (shortSide ) * scale )
202
-
203
- var tw , th int
204
- if w > h {
205
- tw , th = targetLongSide , targetShort
206
- } else {
207
- tw , th = targetShort , targetLongSide
208
- }
209
-
210
- dst := image .NewRGBA (image .Rect (0 , 0 , tw , th ))
211
- draw .BiLinear .Scale (dst , dst .Rect , img , b , draw .Over , nil )
212
- return dst
213
- }
214
-
215
143
func waitForPath (p string ) (first bool , done func ()) {
216
144
ch := make (chan struct {})
217
145
actual , loaded := genLocks .LoadOrStore (p , ch )
@@ -229,11 +157,8 @@ func waitForPath(p string) (first bool, done func()) {
229
157
return false , func () {}
230
158
}
231
159
232
- func removeAlpha (img image.Image ) * image.RGBA {
160
+ func removeAlpha (img image.Image ) image.Image {
233
161
b := img .Bounds ()
234
- out := image .NewRGBA (b )
235
-
236
- draw .Draw (out , b , & image.Uniform {C : color .White }, image.Point {}, draw .Src )
237
- draw .Draw (out , b , img , b .Min , draw .Over )
238
- return out
162
+ bg := imaging .New (b .Dx (), b .Dy (), color .White )
163
+ return imaging .Overlay (bg , img , image .Pt (0 , 0 ), 1.0 )
239
164
}
0 commit comments