如何将项目中的图片转换成webp格式

webp 是谷歌最早在 2010 年推出的一种全新的图片格式,它的主要特点是跟 JPEG、PNG 图片相比,在同等质量下 webp 格式的图片大小要少 26%~35%,在有损压缩下甚至能减少 80%左右, 虽然说是有损压缩,但肉眼几乎很难看出区别来,目前已经有 94%的浏览器支持 webp 格式,所以大胆的在项目中采用吧😄

安装

要将图片转换成 webp 格式首先要在系统中安装一个 libwebp 的命令行工具,去官网下载, 下载下来后解压到任意目录下,然后将此目录下的 bin 目录添加到系统环境变量,打开 cmd 命令窗口,输入cwebp -version查看是否设置成功

cwebp 使用介绍

cwebp 是将普通图片压缩成 webp 格式的命令行工具,下载的包 的 bin 目录下有很多工具,一般只需要使用 cwebp 即可, 如果需要将 gif 图片转换成 webp,请使用 gif2webp 工具,另外 img2webp 用来转换动态 webp 图片, dwebp 是 cwebp 的逆向过程,将 webp 转换成 png、jpg 格式图片,这些工具我们都不常用就不在此介绍了,重点介绍 cwebp 的使用。

cwebp 语法

cwebp [options] input_file -o output_file.webp

cwebp 选项

cwebp 的参数选项有很多,这里挑几个常用的介绍,如果需要查看更多选项的用法可以输入命令cwebp -longhelp

-o string 指定输出的文件名

-lossless 使用无损压缩模式

-near_lossless int 接近无损压缩的级别,范围是 0 到 100(无预处理,默认值),一般设为60。 请注意,使用有损压缩-q 100 有时会产生更好的结果。

-q float 有损压缩模式(默认模式),指定 RGB 通道的压缩系数,范围从 0 到 100, 默认值为 75,值越大质量越好文件也越大,当和-lossless选项一起使用时,较小的值会提高压缩速度, 但产生较大的文件

-resize width height 将原图调整为width * height尺寸大小的图片

-crop x y width height 从图片左上角坐标 x, y 开始裁剪为尺寸大小是width * height的图片,如果和-resize一起使用,会先进行裁剪处理

-size int 指定输出图片的大小, 以字节为单位,只在有损压缩模式下才生效

例子

使用默认压缩

cwebp images/flower.jpg -o images/flower.webp

使用质量级别为50转换文件

cwebp -q 50 images/flower.jpg -o images/flower.webp

调整图片分辨率为 1920 * 1080

cwebp -resize 1920 1080 images/flower.jpg -o images/flower.webp

图片批处理

项目中会用到很多图片,如果通过命令行一张张的手动去转换不现实,我们可以通过写一个 nodejs 程序进行批处理

const { execFile } = require("node:child_process");
const fs = require("fs");
const util = require("util");
const stat = util.promisify(fs.stat);
const path = require("path");
const imgDir = path.resolve(__dirname, "src/assets/img");

// 将图片转换成webp格式并输出到源文件同级目录
const readFile = (dir) => {
  fs.readdir(dir, (error, files) => {
    files
      .filter((file) => !file.endsWith(".webp"))
      .forEach((file) => {
        const filePath = path.join(dir, file);
        stat(filePath).then((stats) => {
          const isDirectory = stats.isDirectory(filePath);
          if (isDirectory) {
            readFile(filePath);
          } else {
            const newFile = path.join(dir, getFileName(filePath) + ".webp");
            // png格式图片使用无损压缩
            if (filePath.endsWith(".png")) {
              convert(filePath, newFile, "-lossless");
            } else {
              convert(filePath, newFile);
            }
          }
        });
      });
  });
};

const convert = (inputFile, outputFile, ...args) => {
  execFile("cwebp", [...args, inputFile, "-o", outputFile], (err) => {
    if (err) {
      throw err;
    }
    console.log("图片转换成功!");
  });
};

const getFileName = (filePath, keepSuffix = false) => {
  const begin = filePath.lastIndexOf(path.sep),
    end = filePath.lastIndexOf(".");
  return filePath.substr(
    begin + 1,
    keepSuffix ? filePath.length : end - begin - 1
  );
};

readFile(imgDir);

我们可以把这个批处理文件放到项目中,然后在package.json的scripts字段中配置一下脚本命令,如:

{
  "scripts": {
    "webp": "node ./toWebp.js"
  },
}

需要转换的时候就执行一下npm run webp命令即可,是不是很方便呢👏

说了这么多来看下效果图

转换前: 格式.jpg, 分辨率1920 * 1362,大小161kb

转换前

转换后: 格式.webp,分辨率1920 * 1362,大小47.2kb

转换后

其他方案

如果批处理程序无法满足你的需求,或者你需要集成到你的打包工具中,如webpackvitegulp,你可以使用imagemin-webp插件,这是一个npm包。

小结

本文介绍了cwebp命令常用选项的用途和在命令行中的使用,以及如何通过脚本程序将普通图片批量转换成webp格式,各种参数选项的设置可以影响输出图片的大小和质量,如何在两者之间找到一个平衡,需要你反复的尝试。

评论