Featured image of post 相册优化小记

相册优化小记

使用 Squoosh-CLI 进行图片压缩

看过我相册的朋友都知道,我的相册其实优化的挺差的,代码写的基本上是依托答辩。加载一个页面要半天的时间,而且大部分图片基本上加载不出来。其实原因很简单。一个是使用了动态调整的瀑布流式布局,导致需要不停的计算样式,其次是外链的 CDN 不太行,我当初创建相册的时候并没有很多相关经验,直接就是用的 Github + JSDelivr 做的图床,导致访问速度在国内有些不尽人意。再加上我的图片都是相机拍摄的高分辨率大图,即使经过算法压缩,也没有改变图片分辨率大小,导致虽然只有 1MB 的图片,但是加载起来也要很久。

那么针对以上问题,分别提出以下对策:

  • 整体框架重构,优化布局算法
  • 减轻图片体积,降低分辨率
  • 更换外链 CDN,加快访问速度

优化框架

这里直接拿得 Github 上大佬的框架😅 我就不自己造轮子了(其实是不会)

public
Visual Portfolio Generator with no extra installation
JavaScript

项目也是采用类似的瀑布流式布局,但是明显代码更加精简,而且不会出现加载到底部再回滚又要再加载一次图片的愚蠢逻辑。相比之下虽然功能少了一些,但是换来的是整体效率的提升。

图片压缩

这段是本文的重点

首先介绍一下 Squoosh 这款黑科技图片压缩工具,基本上可以算是同类中数一数二的存在,强大的压缩效率,简单快捷的操作,还没有广告的烦恼!而且是免费开源的项目,代码大家都可以审核,安全性也是有保障的。特别的,甚至还支持自部署!(当然,压缩是在本地进行的,不会上传云端,所以自部署意义也不是很大…)当然唯一的遗憾就是不能批量压缩,要知道这一点其实是可以劝退很多用户的,大部分情况下需要压缩图片的人也不可能只压缩一张…这其中的逻辑不言自明。另外一个缺点是需要手动调节参数,这是需要大量压缩图片的用户所不希望看到的事情,没人想每次都手动点一下吧?

针对以上痛点,将使用 Squoosh-CLI 工具进行解决。

安装方法如下(建议全局安装)

npm i -g @squoosh/cli

获取指令

这里需要使用自己搭建的网页版来获取压缩图片的指令,官方现在已经不提供这项功能了(不知道为什么)。

GitHub 项目地址如下:

public
Visual Portfolio Generator with no extra installation
TypeScript

但是索性我们并不需要那么复杂的部署操作,依旧是是使用简单的docker部署方式,下面附上我自己的写的docker-compose.yml文件:

version: '3'
services:
  squoosh:
    image: dko0/squoosh:latest
    container_name: squoosh
    restart: unless-stopped
    ports:
      - 7701:8080

然后我们就可以在自部署的网页上看到复制按钮了。

这里要提示下,完事以后务必开启https,否则网页没有权限读取剪贴板,也就无法复制代码!

image-20230918231324669

可以看到我们复制好的指令如下,如果没有条件自部署的也可以根据我给出的代码自行调整,主要是调整一下图片压缩质量(默认为75%),即"quality":75

npx @squoosh/cli --mozjpeg '{"quality":75,"baseline":false,"arithmetic":false,"progressive":true,"optimize_coding":true,"smoothing":0,"color_space":3,"quant_table":3,"trellis_multipass":false,"trellis_opt_zero":false,"trellis_opt_table":false,"trellis_loops":1,"auto_subsample":true,"chroma_subsample":2,"separate_chroma_quality":false,"chroma_quality":75}'

将指令开头npx @squoosh/cli替换成squoosh/cli, 在 -d 参数后写上输出文件夹,后面再跟需要压缩的图片名称,可以使用通配符(Windows 不行),命令如下:

squoosh/cli --mozjpeg '{"quality":75,"baseline":false,"arithmetic":false,"progressive":true,"optimize_coding":true,"smoothing":0,"color_space":3,"quant_table":3,"trellis_multipass":false,"trellis_opt_zero":false,"trellis_opt_table":false,"trellis_loops":1,"auto_subsample":true,"chroma_subsample":2,"separate_chroma_quality":false,"chroma_quality":75}' -d "output" "filename.jpg"

该指令会将文件夹下的filename.jpg按照75%的质量压缩到output文件夹,并保持文件名称不变

批量压缩

当然,到这一步还是和网页版没有什么区别的,无非是从图形话操作转为命令行,依旧没有解决痛点问题:批量压缩。

既然我们得知了压缩单个图片的指令,那么在power shell中只需要使用循环条件遍历文件夹下所有图片循环进行压缩就可以了。

下面给出相关代码,新建一个 txt 文本文件,写入以下代码后将后缀改为 ps1 。注意后面这个是阿拉伯数字 1,不是英文字母 L

# 设置输入文件夹和输出文件夹路径
$inputFolder = "output-resized"
$outputFolder = "output-compressed"

# 获取输入文件夹中的所有图片文件
$images = Get-ChildItem -Path $inputFolder -Filter "*.jpg" -File

# 循环处理每个图片文件
foreach ($image in $images) {
    # 构建执行命令
    $squoosh = "squoosh-cli --mozjpeg '{""quality"":75,""baseline"":false,""arithmetic"":false,""progressive"":true,""optimize_coding"":true,""smoothing"":0,""color_space"":3,""quant_table"":3,""trellis_multipass"":false,""trellis_opt_zero"":false,""trellis_opt_table"":false,""trellis_loops"":1,""auto_subsample"":true,""chroma_subsample"":2,""separate_chroma_quality"":false,""chroma_quality"":75}' -d ""$outputFolder"" ""$($image.FullName)"""

    # 执行命令
    Invoke-Expression -Command $squoosh
}

执行时需要以管理员身份运行,不然会报错!

修改图片尺寸

我拍摄的照片默认是 4000x6000 分辨率的图片,这样的高解析力照片显然是有些用力过猛的,大概压缩成 25% ~ 50%的分辨率就够用了,能在保持清晰度的同时减少体积。

经过测试,Squoosh自带的分辨率调整功能速度较慢,而且效果一般,这里我用 Python 写了一个小脚本,速度实测非常快,一百多张图片几秒钟就好了。

# 作者:小骆同学
# 日期:2023年08月30日

import os

from PIL import Image


def resize_to_25_percent(input_path, output_path):
    # 打开图像
    img = Image.open(input_path)

    # 获取原始分辨率
    original_width, original_height = img.size

    # 计算新的宽度和高度(20%分辨率)
    new_width = int(original_width * 0.20)
    new_height = int(original_height * 0.20)

    # 调整分辨率
    resized_img = img.resize((new_width, new_height), Image.LANCZOS)

    # 保存调整后的图像
    resized_img.save(output_path)


# 输入文件夹和输出文件夹路径
input_folder = 'input'  # 替换为你的输入文件夹路径
output_folder = 'output-resize'  # 替换为你的输出文件夹路径

# 确保输出文件夹存在
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

# 遍历输入文件夹中的所有图片文件
for filename in os.listdir(input_folder):
    if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.gif')):
        input_path = os.path.join(input_folder, filename)
        output_path = os.path.join(output_folder, filename)

        # 调整图像分辨率为原始的20%
        resize_to_25_percent(input_path, output_path)
        print(f"resize:{input_path} => {output_path}")

print("success!")

产业链整合

首先调整图片大小,压缩至 20% 分辨率,然后使用Squoosh进行压缩。这个顺序不要搞错了,如果是先压缩再调整分辨率的话电脑需要压缩高分辨率,高体积的大图,CPU拉满,风扇直接起飞😅我第一次没经验就踩坑了。

目录下分别新建 inputinput-resizedinput-compressed 三个文件夹,在 input 文件夹下输入图片,然后依次运行 image-resize.pysquoosh.ps1,最后在 input-compressed 文件夹下查收结果

这里我还写了一个程序 clear-dir.bat 一键清空上述三个文件夹,当然在使用的时候一定要确保原图片已经备份,要不然会直接丢失数据!

@echo off

set "inputFolder=input"
set "outputFolder=output"

echo clear %inputFolder% ...
del /q "%inputFolder%\*.*" > nul 2>&1

echo clear %outputFolder% ...
del /q "%outputFolder%\*.*" > nul 2>&1

echo successfully cleared %inputFolder% and %outputFolder% folders.

pause

参考链接

🔗 Squoosh CLI使用教程

🔗 如何使用 Squoosh 命令行批量压缩图片

Licensed under CC BY-NC-SA 4.0