為了方便給自己的博客配圖,用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,改為了適合自己博客使用,源程序的代碼更通用,更推薦在它基礎上修改。
