记录笔记或者写博客的时候经常会直接复制mac截图插入图片,默认复制得到的是无损png图片,图片体积比较大,占空间带宽,就基于go实现了个命令行批量压缩工具。

基于图片尺寸压缩

主要是用到了github.com/nfnt/resize

func (j *JPG) Resizer(filePath string, dstPath string, compressFactor float64) error {
    // 打开图片文件
    file, err := os.Open(filePath)
    if err != nil {
        return err
    }
    defer file.Close()

    // 解码图片
    img, _, err := image.Decode(file)
    if err != nil {
        return err
    }

    // 计算新的宽高
    width := uint(float64(img.Bounds().Dx()) * compressFactor)
    height := uint(float64(img.Bounds().Dy()) * compressFactor)

    // 缩放图片
    resizedImg := resize.Resize(width, height, img, resize.Lanczos3)
    // 创建输出文件
    outputFile, err := os.Create(dstPath)
    if err != nil {
        return err
    }
    defer outputFile.Close()

    // 保存压缩后的图片
    err = jpeg.Encode(outputFile, resizedImg, nil)
    if err != nil {
        return err
    }
    return nil
}

基于质量的压缩

直接使用的Go image标准库

func (j *JPG) QualityLower(filePath string, dstPath string, quality int) error {
    if quality < 0 {
        return nil
    }
    if quality < 10 {
        quality = quality * 10
    }
    if quality > 100 {
        return nil
    }
    // 打开图片文件
    file, err := os.Open(filePath)
    if err != nil {
        return err
    }
    defer file.Close()

    // 解码图片
    img, _, err := image.Decode(file)
    if err != nil {
        return err
    }

    // 创建输出文件
    outputFile, err := os.Create(dstPath)
    if err != nil {
        return err
    }
    defer outputFile.Close()

    // 设置JPEG编码参数
    options := &jpeg.Options{
        Quality: int(quality),
    }
    // 保存压缩后的图片
    err = jpeg.Encode(outputFile, img, options)
    if err != nil {
        return err
    }

    return nil
}

png属于无损格式,go默认库无法进行有效压缩,就算用png.BestCompression 参数压缩效果也不理想,如果不是很在乎质量,可以转成jpg图片,再压缩

// QualityLower png 压缩
func (p *PNG) QualityLower(filePath string, dstPath string) error {
    // 打开PNG图片文件
    file, err := os.Open(filePath)
    if err != nil {
        return err
    }
    defer file.Close()

    // 解码PNG图片
    img, _, err := image.Decode(file)
    if err != nil {
        return err
    }

    // 创建输出文件
    outputFile, err := os.Create(dstPath)
    if err != nil {
        return err
    }
    defer outputFile.Close()

    encoder := png.Encoder{
        CompressionLevel: png.BestCompression,
    }

    // 保存为PNG格式
    err = encoder.Encode(outputFile, img)
    if err != nil {
        return err
    }

    return nil
}

png转jpg再压缩

func (i *ImageConvert) ToJPEG(filePath string, dstPath string, quality int) error {
    file, err := os.Open(filePath)
    if err != nil {
        return err
    }
    defer file.Close()

    img, _, err := image.Decode(file)
    if err != nil {
        return err
    }

    // 创建输出文件
    outputFile, err := os.Create(dstPath)
    if err != nil {
        return err
    }
    defer outputFile.Close()

    // 设置JPEG编码参数
    jpegOptions := &jpeg.Options{
        Quality: quality,
    }

    // 将PNG转为JPEG并进行压缩
    err = jpeg.Encode(outputFile, img, jpegOptions)
    if err != nil {
        return err
    }

    return nil
}

完整代码在github,直接用go安装go install github.com/mengboy/img@latest使用示例:

# 将image下的png图片批量转换为jpeg图片并压缩质量到80
img convert -s /images -d /imagesjpeg -c jpeg -q 80

# 将image下的test.png转换为test.jpeg并压缩质量到80 
img convert -s /images/test.png -d /images/test.jpeg -c jpeg -q 80

# 将image下的图片批量压缩质量到80
img resize -s /images -d /images8 -q 80

# 将image下的test.jpeg压缩质量到80 
img resize -s /images/test.jpeg -d /images/test8.jpeg - 80

# 将image下的png图片尺寸批量缩小至原来的80%
img resize -s /images -d /images8 -f 0.8

# 将image下的test.png图片尺寸缩小至原来的80% 
img resize -s /images/test.png -d /images/test8.png -f 0.8