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
}

  

posted @ 2023-06-13 16:45  wsh3166Sir  阅读(331)  评论(0编辑  收藏  举报