-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimageCompress.go
303 lines (287 loc) · 7.3 KB
/
imageCompress.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
package main
import (
//"encoding/json"
"fmt"
//"os"
//"io/ioutil"
"github.com/nfnt/resize"
"image/jpeg"
"io"
"log"
"os"
"path/filepath"
"strconv"
// "flag"
"bufio"
"image"
"image/png"
"strings"
"time"
)
func imageCompress(
getReadSizeFile func() (io.Reader, error),
getDecodeFile func() (*os.File, error),
to string,
Quality,
base int,
format string) bool {
/** 读取文件 */
fileOrigin, err := getDecodeFile()
if err != nil {
fmt.Println("os.Open(file)错误")
log.Fatal(err)
return false
}
defer func() {
if fileOrigin != nil {
_ = fileOrigin.Close()
}
}()
var origin image.Image
var config image.Config
var temp io.Reader
/** 读取尺寸 */
temp, err = getReadSizeFile()
if err != nil {
fmt.Println("os.Open(temp)")
log.Fatal(err)
return false
}
var typeImage int64
format = strings.ToLower(format)
/** jpg 格式 */
if format == "jpg" || format == "jpeg" {
typeImage = 1
origin, err = jpeg.Decode(fileOrigin)
if err != nil {
fmt.Println("jpeg.Decode(file_origin)")
log.Fatal(err)
return false
}
temp, err = getReadSizeFile()
if err != nil {
fmt.Println("os.Open(temp)")
log.Fatal(err)
return false
}
config, err = jpeg.DecodeConfig(temp)
if err != nil {
fmt.Println("jpeg.DecodeConfig(temp)")
return false
}
} else if format == "png" {
typeImage = 0
origin, err = png.Decode(fileOrigin)
if err != nil {
fmt.Println("png.Decode(file_origin)")
log.Fatal(err)
return false
}
temp, err = getReadSizeFile()
if err != nil {
fmt.Println("os.Open(temp)")
log.Fatal(err)
return false
}
config, err = png.DecodeConfig(temp)
if err != nil {
fmt.Println("png.DecodeConfig(temp)")
return false
}
}
/** 做等比缩放 */
width := uint(base) /** 基准 */
height := uint(base * config.Height / config.Width)
canvas := resize.Thumbnail(width, height, origin, resize.Lanczos3)
fileOut, err := os.Create(to)
if err != nil {
log.Fatal(err)
return false
}
defer func() {
if fileOut != nil {
_ = fileOut.Close()
}
}()
if typeImage == 0 {
err = png.Encode(fileOut, canvas)
if err != nil {
fmt.Println("压缩图片失败")
return false
}
} else {
err = jpeg.Encode(fileOut, canvas, &jpeg.Options{Quality})
if err != nil {
fmt.Println("压缩图片失败")
return false
}
}
return true
}
func getFilelist(path string) {
/** 创建输出目录 */
errC := os.MkdirAll(inputArgs.OutputPath, 0777)
if errC != nil {
fmt.Printf("%s", errC)
return
}
err := filepath.Walk(path, func(pathFound string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if f.IsDir() { /** 是否是目录 */
return nil
}
// println(pathFound)
/** 找到一个文件 */
/** 判断是不是图片 */
localPath, format, _ := isPictureFormat(pathFound)
oldfilename:=filepath.Base(localPath)
/** 随机数 */
//t := time.Now()
//millis := t.Nanosecond() /** 纳秒 */
outputPath := inputArgs.OutputPath + oldfilename // strconv.FormatInt(int64(millis), 10) + "." + format
if localPath != "" {
if !imageCompress(
func() (io.Reader, error) {
return os.Open(localPath)
},
func() (*os.File, error) {
return os.Open(localPath)
},
outputPath,
inputArgs.Quality,
inputArgs.Width,
format) {
fmt.Println("生成缩略图失败")
} else {
fmt.Println("生成缩略图成功 " + outputPath)
}
}
return nil
})
if err != nil {
fmt.Printf("输入的路径信息有误 %v\n", err)
}
}
/** 是否是图片 */
func isPictureFormat(path string) (string, string, string) {
temp := strings.Split(path, ".")
if len(temp) <= 1 {
return "", "", ""
}
mapRule := make(map[string]int64)
mapRule["jpg"] = 1
mapRule["png"] = 1
mapRule["jpeg"] = 1
// fmt.Println(temp[1]+"---")
/** 添加其他格式 */
if mapRule[temp[1]] == 1 {
//println(temp[1])
return path, temp[1], temp[0]
} else {
return "", "", ""
}
}
func execute() {
/** 获取输入 */
//str := ""
//fmt.Scanln (&str) /** 不要使用 scanf,它不会并以一个新行结束输入 */
reader := bufio.NewReader(os.Stdin)
data, _, _ := reader.ReadLine()
/** 分割 */
reg := regexp.MustCompile("\\s+")
inputstr:= reg.ReplaceAllString(string(data), " ") //多个空格替换为一个
strPice := strings.Split(inputstr, " ") /** 空格 */
if len(strPice) < 3 {
fmt.Printf("输入有误,参数数量不足,请重新输入或退出程序:")
execute()
return
}
inputArgs.LocalPath = strPice[0]
inputArgs.Quality, _ = strconv.Atoi(strPice[1])
inputArgs.Width, _ = strconv.Atoi(strPice[2])
pathTemp, format, top := isPictureFormat(inputArgs.LocalPath)
if pathTemp == "" {
/** 目录 */
/** 如果输入目录,那么是批量 */
fmt.Println("开始批量压缩...")
inputArgs.OutputPath = filepath.Dir(inputArgs.LocalPath) + string(os.PathSeparator) + "LghImageCompress" + string(os.PathSeparator)
/*
rs := []rune(inputArgs.LocalPath)
end := len(rs)
substr := string(rs[end-1 : end])
if substr == "/" {
// 有 /
rs := []rune(inputArgs.LocalPath)
end := len(rs)
substr := string(rs[0 : end-1])
endIndex := strings.LastIndex(substr, "/")
inputArgs.OutputPath = string(rs[0:endIndex]) + "/LghImageCompress/"
} else {
endIndex := strings.LastIndex(inputArgs.LocalPath, "/")
inputArgs.OutputPath = string(rs[0:endIndex]) + "/LghImageCompress/"
}*/
getFilelist(inputArgs.LocalPath)
fmt.Println("图片保存在文件夹 " + inputArgs.OutputPath)
} else {
/** 单个 */
/** 如果输入文件,那么是单个,允许自定义路径 */
fmt.Println("开始单张压缩...") //C:\Users\lzq\Desktop\Apk.jpg 75 200
inputArgs.OutputPath = top + "_compress." + format
if !imageCompress(
func() (io.Reader, error) {
return os.Open(inputArgs.LocalPath)
},
func() (*os.File, error) {
return os.Open(inputArgs.LocalPath)
},
inputArgs.OutputPath,
inputArgs.Quality,
inputArgs.Width,
format) {
fmt.Println("生成缩略图失败")
} else {
fmt.Println("生成缩略图成功 " + inputArgs.OutputPath)
finish()
}
}
time.Sleep(5 * time.Minute) /** 如果不是自己点击退出,延时5分钟 */
}
func finish() {
fmt.Printf("继续输入进行压缩或者退出程序:")
execute()
}
func showTips() {
tips := []string{
"请输入文件夹或图片路径:",
"如果输入文件夹,那么该目录的图片将会被批量压缩;",
"如果是图片路径,那么将会被单独压缩处理。",
"例如:",
"C:/Users/lzq/Desktop/headImages/ 75 200",
"指桌面 headImages 文件夹,里面的图片质量压缩到75%,宽分辨率为200,高是等比例计算",
"C:/Users/lzq/Desktop/headImages/1.jpg 75 200",
"指桌面的 headImages 文件夹里面的 1.jpg 图片,质量压缩到75%,宽分辨率为200,高是等比例计算 ",
"请输入:"}
itemLen := len(tips)
for i := 0; i < itemLen; i++ {
if i == itemLen-1 {
fmt.Printf(tips[i])
} else {
fmt.Println(tips[i])
}
}
}
type InputArgs struct {
OutputPath string /** 输出目录 */
LocalPath string /** 输入的目录或文件路径 */
Quality int /** 质量 */
Width int /** 宽度尺寸,像素单位 */
Format string /** 格式 */
}
var inputArgs InputArgs
func main() {
showTips()
execute()
time.Sleep(5 * time.Minute) /** 如果不是自己点击退出,延时5分钟 */
}