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
}
浙公网安备 33010602011771号