zoukankan      html  css  js  c++  java
  • 异想家博客图片批量压缩程序

    为了方便给自己的博客配图,用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
    ", 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,改为了适合自己博客使用,源程序的代码更通用,更推荐在它基础上修改。

  • 相关阅读:
    统计nginx日志里访问次数最多的前十个IP
    while 格式化输出 运算符 字符编码
    Python 软件安装
    Python 基础
    Typora 基础的使用方法
    Django ORM (四) annotate,F,Q 查询
    Django 惰性机制
    Django ORM (三) 查询,删除,更新操作
    Django ORM (二) 增加操作
    Django ORM (一) 创建数据库和模型常用的字段类型参数及Field 重要参数介绍
  • 原文地址:https://www.cnblogs.com/sandeepin/p/jfz-blog-pic-compress.html
Copyright © 2011-2022 走看看