异想家博客图片批量压缩程序

为了方便给自己的博客配图,用Golang写了一个脚本处理,现分享出来,有需要的朋友也可以参考修改使用。

压缩规则

1、图片都等比例压缩,不破坏长宽比。

2、如果是横屏图片,压缩到宽度为1280,高度适应。

3、如果是竖屏图片,压缩到高度为1000,宽度适应。

4、如果分辨率小于这个,不压缩。

5、支持png、jpg、jpeg。

使用方法

go build jfzBlogPicCompress.go

原图放在当前目录下的raw目录中,压缩后的图片生成在thumb目录下,运行生成的二进制文件即可,压缩完5s后程序退出。

源码

文件名jfzBlogPicCompress.go:

package main



import (

	"fmt"

	"github.com/nfnt/resize"

	"image"

	"image/jpeg"

	"image/png"

	"io"

	"log"

	"os"

	"path/filepath"

	"strings"

	"time"

)



type InputArgs struct {

	OutputPath string /** 输出目录 */

	LocalPath  string /** 输入的目录或文件路径 */

	Quality    int    /** 质量 */

	Width      int    /** 宽度尺寸,像素单位 */

	Format     string /** 格式 */

}



var inputArgs InputArgs



func main() {

	execute()

	fmt.Printf("处理完成,5秒后自动退出……")

	time.Sleep(5 * time.Second) /** 如果不是自己点击退出,延时5s */

}



//  执行压缩

func execute() {

	fmt.Println("开始批量压缩...")



	inputArgs.LocalPath = "./raw/"

	inputArgs.OutputPath = "./thumb/"

	inputArgs.Quality = 90

	inputArgs.Width = 1280

	fmt.Println("压缩规则:宽度1280,如果是竖图,高度1000  压缩质量:", inputArgs.Quality)



	GetFilelist(inputArgs.LocalPath)

	fmt.Println("图片保存在:" + inputArgs.OutputPath)

}



// 遍历输入原图目录的图片

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

		}

		// 文件是否是图片

		localPath, format, _ := isPictureFormat(pathFound)

		outputPath := strings.Replace(localPath, "raw", "thumb", 1)

		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 imageCompress(

	getReadSizeFile func() (io.Reader, error),

	getDecodeFile func() (*os.File, error),

	to string,

	Quality,

	base int,

	format string) bool {

	// 读取文件

	file_origin, err := getDecodeFile()

	defer file_origin.Close()

	if err != nil {

		fmt.Println("os.Open(file)错误")

		log.Fatal(err)

		return false

	}

	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)

	if format == "jpg" || format == "jpeg" {

		// jpg 格式 1

		typeImage = 1

		origin, err = jpeg.Decode(file_origin)

		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" {

		// png 格式 0

		typeImage = 0

		origin, err = png.Decode(file_origin)

		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

		}

	}

	// 等比缩放(压缩到1280的宽,如果图片是竖着的,限定高最多1000)

	fixBase := base

	heightBase := fixBase * config.Height / config.Width

	if config.Height > config.Width {

		heightBase = 1000

		fixBase = heightBase * config.Width / config.Height

	}



	// 基准

	width := uint(fixBase)

	height := uint(heightBase)



	canvas := resize.Thumbnail(width, height, origin, resize.Lanczos3)

	file_out, err := os.Create(to)

	defer file_out.Close()

	if err != nil {

		log.Fatal(err)

		return false

	}

	if typeImage == 0 {

		err = png.Encode(file_out, canvas)

		if err != nil {

			fmt.Println("压缩图片失败")

			return false

		}

	} else {

		err = jpeg.Encode(file_out, canvas, &jpeg.Options{Quality})

		if err != nil {

			fmt.Println("压缩图片失败")

			return false

		}

	}



	return true

}



// 是否是图片

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["JPG"] = 1

	mapRule["png"] = 1

	mapRule["PNG"] = 1

	mapRule["jpeg"] = 1

	mapRule["JPEG"] = 1

	if mapRule[temp[1]] == 1 {

		println(temp[1])

		return path, temp[1], temp[0]

	} else {

		return "", "", ""

	}

}

参考

代码参考了golang_image_compress,改为了适合自己博客使用,源程序的代码更通用,更推荐在它基础上修改。