golang 遍历并批量压缩图片
package main import ( "bytes" "fmt" "image" "io/ioutil" "mylog" "os" "path" "github.com/nfnt/resize" _ "image/gif" "image/jpeg" _ "image/png" ) func main() { // GetFiles(".") pathslist := GetFiles2(".") mapRule := make(map[string]int) mapRule[".jpg"] = 1 mapRule[".png"] = 1 mapRule[".jpeg"] = 1 for i, m := range pathslist { mylog.Println(i, "===>", m) ext := path.Ext(m) // fmt.Println(ext) if mapRule[ext] == 1 { fmt.Println(m) old, err := os.ReadFile(m) if err != nil { fmt.Println(err) } new_pic := CompressImageResource(old) ioutil.WriteFile(m, new_pic, 0666) } } } // 默认最大高度 const MaxHeight uint = 1080 // 文件小于 200KB 或者不是jpeg/png格式,不再压缩 func CompressImageResource(data []byte) []byte { if len(data) < 1024*200 { return data } img, _, err := image.Decode(bytes.NewReader(data)) if err != nil { mylog.Printf("jpeg png compress failed,err:%v", err) return data } // 修改图片的大小 m := resize.Resize(0, MaxHeight, img, resize.Lanczos3) buf := bytes.Buffer{} // 修改图片的质量 err = jpeg.Encode(&buf, m, &jpeg.Options{Quality: 85}) if err != nil { mylog.Printf("jpeg compress failed,err:%v", err) return data } if buf.Len() > len(data) { return data } return buf.Bytes() } func GetFiles(folder string) { files, _ := ioutil.ReadDir(folder) for _, file := range files { if file.IsDir() { GetFiles(folder + "/" + file.Name()) } else { fmt.Println(folder + "/" + file.Name() + ",扩展名:" + path.Ext(file.Name())) } } } func GetFiles2(folder string) []string { res := []string{} files, _ := ioutil.ReadDir(folder) for _, file := range files { if file.IsDir() { temp2 := GetFiles2(folder + "/" + file.Name()) res = append(res, temp2...) } else { res = append(res, folder+"/"+file.Name()) // fmt.Println(folder + "/" + file.Name() + ",扩展名:" + path.Ext(file.Name())) } } return res }
效果:遍历当前根目录,批量压缩图片
mylog是自定义的日志包
在压缩那步增加并发代码跑,可以大幅提高效率。
并发:
package main import ( "errors" "fmt" "image" "io/ioutil" "mylog" "os" "path" "strings" "sync" "time" "image/gif" "image/jpeg" "image/png" "github.com/nfnt/resize" _ "golang.org/x/image/bmp" ) type Glimit struct { n int c chan struct{} } // initialization Glimit struct func New(n int) *Glimit { return &Glimit{ n: n, c: make(chan struct{}, n), } } // Run f in a new goroutine but with limit. func (g *Glimit) Run(f func()) { g.c <- struct{}{} go func() { f() <-g.c }() } var wg = sync.WaitGroup{} var mu sync.Mutex var count int func main() { since := time.Now() pathslist := GetFiles2(".") mapRule := make(map[string]int) mapRule[".jpg"] = 1 mapRule[".png"] = 1 mapRule[".jpeg"] = 1 mapRule[".gif"] = 1 mapRule[".bmp"] = 1 g := New(20) for i, m := range pathslist { ext := strings.ToLower(path.Ext(m)) that_m := m //并发时 很重要 // fmt.Println(ext) if mapRule[ext] == 1 { mylog.Println(i, "===>", m) wg.Add(1) fmt.Println(m) goFunc := func() { compressImage_with_path(that_m, that_m) mu.Lock() count++ mu.Unlock() wg.Done() } g.Run(goFunc) } } wg.Wait() fmt.Println(time.Since(since), ",执行次数:", count) time.Sleep(10 * time.Second) } //压缩图片 func compressImage_with_path(imagePath, savePath string) error { mylog.Println("文件路径是:", imagePath) file, _ := os.Open(imagePath) defer file.Close() w := 500 h := 0 img, layout, err := image.Decode(file) if err != nil { mylog.Println("解码错误:<<<", imagePath, ">>>==>", err) return err } else { mylog.Println("格式:", imagePath, "==>", layout) } fmt.Println(img.Bounds().Dx()) if w >= img.Bounds().Dx() && w >= img.Bounds().Dy() { return nil } if img.Bounds().Dx() < img.Bounds().Dy() { //考虑翻转的图片 w, h = h, w } // 调用resize库进行图片缩放 m := resize.Resize(uint(w), uint(h), img, resize.Lanczos3) // 需要保存的文件 imgfile, _ := os.Create(savePath) defer imgfile.Close() switch layout { case "png": err = png.Encode(imgfile, m) case "jpeg", "jpg", "bmp": err = jpeg.Encode(imgfile, m, &jpeg.Options{Quality: 85}) case "gif": err = gif.Encode(imgfile, m, &gif.Options{NumColors: 32}) default: return errors.New("该图片格式不支持压缩") } if err != nil { return err } return nil } func GetFiles2(folder string) []string { res := []string{} files, _ := ioutil.ReadDir(folder) for _, file := range files { if file.IsDir() { temp2 := GetFiles2(folder + "/" + file.Name()) res = append(res, temp2...) } else { res = append(res, folder+"/"+file.Name()) // fmt.Println(folder + "/" + file.Name() + ",扩展名:" + path.Ext(file.Name())) } } return res }