写一个可以批量修改图片分辨率的工具

说在前面

🎈在视觉内容至关重要的今天,图片尺寸的调整对于网站加载速度和用户体验有着直接影响。本文介绍的Node.js工具,通过简单的命令行操作,允许用户批量调整图片尺寸,支持单张图片和整个目录的操作,提供了按比例缩放和自定义宽高的灵活选项。这不仅提高了工作效率,也使得图片管理变得更加简单。

代码实现

1.依赖引入

(1)@jyeontu/j-inquirer

@jyeontu/j-inquirer 是一个 Node.js 的命令行交互模块,它可以方便地创建一个交互式命令行界面,用于与用户进行交互。它提供了多种常见的输入方式,如单选、多选、输入框、文件选择、目录选择等等,并且可以自定义提示信息、选项等。

(2)@jyeontu/progress-bar

@jyeontu/progress-bar 是一个 Node.js 的进度条模块,它可以在命令行中展示一个进度条,用于显示正在进行的操作的进度。它支持多种样式和配置选项,可以根据需要调整进度条的样式、长度、颜色等等。

(3)fs-extra

扩展了Node.js的fs模块,它提供了多种操作文件和目录的方法,如读取文件、写入文件、创建目录、删除文件等等。在 Node.js 中,我们可以使用 fs-extra 模块来读取和处理本地的文件。

(4)jimp

jimp 是一个纯 JavaScript 的图像处理库,它可以用于处理各种类型的图片,如 PNG、JPEG、BMP 等等。它提供了多种图像处理方法,如调整大小、裁剪、旋转、添加水印等等,可以轻松地实现各种图像处理需求。在 Node.js 中,我们可以使用 jimp 来读取和处理本地的图片文件。

2.命令行交互获取处理参数

(1)单张图片或批量

询问用户是要处理单个图片还是一个图片文件夹

async function askForSingleOrBatch() {
  const options = [
    {
      type: "list",
      message: "选择文件夹还是单张图片",
      name: "imgType",
      default: "单张图片",
      choices: ["文件夹", "单张图片"],
    },
  ];
  const answers = await new inquirer(options).prompt();
  const { imgType } = answers;
  return imgType;
}
(2)获取图片路径

根据用户选择的类型(单个图片或文件夹),询问用户选择图片或文件夹的路径,并询问调整尺寸的方式。

async function askForParams(imgType) {
  const options = [];
  if (imgType === "文件夹") {
    options.push({
      type: "folder",
      message: "请选择图片目录",
      name: "imgFolder",
      default: "",
      dirname: baseDir,
    });
  } else {
    options.push({
      type: "file",
      message: "请选择图片",
      name: "img",
      default: "",
      dirname: baseDir,
    });
  }
  options.push({
    type: "list",
    message: "调整类型",
    name: "adjustType",
    default: "按比例",
    choices: ["按比例", "自定义宽高"],
  });
  const answers = await new inquirer(options).prompt();
  return answers;
}
(3)获取具体调整参数

根据用户选择的调整方式,询问用户具体的调整参数。

async function askForImgParams(adjustType) {
  const options = [];
  if (adjustType === "按比例") {
    options.push(
      {
        type: "list",
        message: "请选择基准边",
        name: "referenceEdge",
        default: "宽",
        choices: ["宽", "高"],
      },
      {
        type: "input",
        message: "请输入基准边长度",
        name: "referenceEdgeLength",
        default: "800",
        validate: function (input) {
          const isNumber = !isNaN(input) && !isNaN(parseFloat(input));
          if (isNumber) {
            return true; // 输入有效
          } else {
            return "请输入一个有效的数字"; // 输入无效
          }
        },
      }
    );
  } else {
    options.push(
      {
        type: "input",
        message: "请输入宽度",
        name: "width",
        default: "1280",
        validate: function (input) {
          const isNumber = !isNaN(input) && !isNaN(parseFloat(input));
          if (isNumber) {
            return true; // 输入有效
          } else {
            return "请输入一个有效的数字"; // 输入无效
          }
        },
      },
      {
        type: "input",
        message: "请输入高度",
        name: "height",
        default: "720",
        validate: function (input) {
          const isNumber = !isNaN(input) && !isNaN(parseFloat(input));
          if (isNumber) {
            return true; // 输入有效
          } else {
            return "请输入一个有效的数字"; // 输入无效
          }
        },
      }
    );
  }
  const answers = await new inquirer(options).prompt();
  return answers;
}

3.计算调整后图片分辨率

根据用户输入的参数,计算出调整后的图片宽度和高度。

function getWidthAndHeight(bitmap, params) {
  let { width, height } = bitmap;
  if (params.adjustType === "按比例") {
    if (params.referenceEdge === "宽") {
      const rate = params.referenceEdgeLength / width;
      width = params.referenceEdgeLength;
      height = height * rate;
    } else {
      const rate = params.referenceEdgeLength / height;
      height = params.referenceEdgeLength;
      width = width * rate;
    }
  } else {
    width = params.width;
    height = params.height;
  }
  width -= 0;
  height -= 0;
  return { width, height };
}
参数解释:
  • bitmap:这是一个Jimp对象,代表了加载的图片,包含了图片的原始宽度和高度信息。
  • params:这是一个对象,包含了用户通过命令行交互指定的调整参数,主要有:
    • adjustType:用户选择的调整类型,可以是"按比例"或"自定义宽高"。
    • referenceEdge:如果用户选择按比例调整,这个属性指定了参考边是"宽"还是"高"。
    • referenceEdgeLength:用户输入的基准边长度。
    • widthheight:如果用户选择自定义宽高,这两个属性会包含用户输入的宽度和高度值。
函数逻辑:
  1. 函数首先从bitmap对象中解构出原始的width(宽度)和height(高度)。

  2. 接下来,根据params.adjustType的值来判断用户选择的调整类型:

    • 如果是"按比例"("按比例"),则进一步检查params.referenceEdge的值:
      • 如果参考边是"宽"("宽"),则计算新的宽度为用户指定的基准边长度params.referenceEdgeLength,然后根据原始高度和新宽度的比例计算新的height
      • 如果参考边是"高"("高"),则计算新的height为用户指定的基准边长度,然后计算新的width
    • 如果用户选择的是"自定义宽高"(非"按比例"),则直接将用户指定的params.widthparams.height作为新的宽度和高度。
  3. 在计算出新的宽度和高度后,函数通过width -= 0;height -= 0;将数值转换为数字类型,以确保它们是数字而不是字符串。这是因为用户输入可能会被当作字符串处理,而在进行数学计算时需要确保它们是数字类型。

  4. 最后,函数返回一个包含新widthheight的对象。

注意:
  • 这个函数中的width -= 0;height -= 0;是一种类型转换的技巧,它利用了JavaScript的类型转换规则,将变量转换为数字类型。这种转换通常不是必须的,因为从bitmap对象中直接解构出来的widthheight应该已经是数字类型了。如果params.widthparams.height是从用户输入解析得到的,并且确定用户输入的是有效的数字,这两个转换语句可以省略。

4.获取修改后图片输出路径

根据用户选择的图片或文件夹路径,生成输出目录的路径,如果路径不存在则创建该目录。

async function getOutPutDir(img) {
  const pathName = img.split("\\");
  const name = pathName.pop();
  pathName.push("resizeImgOutPut");
  const outputPath = pathName.join("\\");
  if (!fs.existsSync(outputPath)) {
    fs.mkdirSync(outputPath);
  }
  pathName.push(name);
  return pathName.join("\\");
}

5.定义图片处理函数

(1)单张图片
async function resizeImg(params) {
  const outputPath = await getOutPutDir(params.img);
  const image = await Jimp.read(params.img);
  const { width, height } = getWidthAndHeight(image.bitmap, params);
  const newSizeImage = image.resize(width, height);
  newSizeImage.write(outputPath);
}
(2)图片目录
async function resizeDir(params) {
  const imgList = fs.readdirSync(params.imgFolder);
  for (let i = 0; i < imgList.length; i++) {
    if (imgList[i].match(/\.(jpg|jpeg|png|bmp|tiff|gif)$/i)) {
      await resizeImg({
        ...params,
        img: params.imgFolder + "\\" + imgList[i],
      });
    }
  }
}

快速使用

安装

该工具已经发布到npm上,可以在命令行快速安装:

npm install -g jyeontu

功能选择

jyeontu img

选择调整图片尺寸,然后按提示输入或选择即可。

源码

Gitee

该工具的源码也已经开源,有兴趣的同学可以到Gitee上查看:

https://gitee.com/changkong1009/node-scripting-tool/tree/master/src/jyeontu/script/img/resize

欢迎star~

欢迎pr~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JYeontu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值