使用 Node.js 插件给指定目录下的所有图片添加上文字水印

说在前面

加水印是为了保护图片的版权和安全。在互联网上,很容易将图片下载或者截屏保存下来,然后进行二次使用,这就侵犯了原作者的版权。而加上水印可以使得图片更难被盗用,因为盗用者需要花费时间和精力去处理水印,而这个过程可能会破坏原始图片的质量。
此外,水印也可以帮助识别图片的来源和所有者。如果一张图片被恶意使用或者未经授权的使用,通过水印可以追踪到图片的来源和版权所有人,从而维护原作者的权益。
因此,加水印对于保护图片的版权和安全具有重要意义。

代码实现

1、依赖引入

(1)@jyeontu/j-inquirer

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

(2)@jyeontu/progress-bar

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

(3)fs

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

(4)jimp

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

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

javascript 复制代码
const textWaterMarkOptions = [
  {
    type: "folder",
    message: "请选择需要添加水印的图片目录",
    name: "inputFolder",
    default: "",
    dirname: baseDir,
  },
  {
    type: "input",
    message: "请输入水印文字",
    name: "watermarkText",
    default: "",
  },
  {
    type: "list",
    message: "请选择水印位置",
    name: "watermarkPos",
    default: "center",
    choices: [
      "上左",
      "上中",
      "上右",
      "中左",
      "正中",
      "中右",
      "下左",
      "下中",
      "下右",
    ],
  },
];
async function ask(options) {
  const answers = await new inquirer(options).prompt();
  return answers;
}
async function textWaterMark(inputFolder, outputFolder) {
  const { watermarkText, watermarkPos } = await ask(textWaterMarkOptions);
  ............
}

获取用户需要添加水印的目录、水印文字内容及水印添加位置。

3、图片添加水印

(1)获取目录下的所有图片

javascript 复制代码
const IMG_TYPE = ["jpg", "png", "jpeg"];
function checkImgType(file) {
  const tmp = file.split(".");
  return IMG_TYPE.includes(tmp[tmp.length - 1].toLocaleLowerCase());
}

const imageFiles = fs
.readdirSync(inputFolder)
.filter((file) => checkImgType(file));

目前支持处理"jpg", "png", "jpeg"类型的图片文件,获取指定目录下的符合类型的所有图片文件。

(2)水印位置计算

javascript 复制代码
function getPosition(img, waterMark, pos) {
  const imageWidth = img.width;
  const imageHeight = img.height;
  const watermarkWidth = waterMark.width;
  const watermarkHeight = waterMark.height;
  let x = (imageWidth - watermarkWidth) / 2; // 水印横坐标
  let y = (imageHeight - watermarkHeight) / 2; // 水印纵坐标

  switch (pos) {
    case "上左":
      x = 10; // 水印横坐标
      y = 10; // 水印纵坐标
      break;
    case "上中":
      x = (imageWidth - watermarkWidth) / 2; // 水印横坐标
      y = 10; // 水印纵坐标
      break;
    case "上右":
      x = imageWidth - watermarkWidth - 20; // 水印横坐标
      y = 10; // 水印纵坐标
      break;
    case "中左":
      x = 10; // 水印横坐标
      y = (imageHeight - watermarkHeight) / 2; // 水印纵坐标
      break;
    case "正中":
      x = (imageWidth - watermarkWidth) / 2; // 水印横坐标
      y = (imageHeight - watermarkHeight) / 2; // 水印纵坐标
      break;
    case "中右":
      x = imageWidth - watermarkWidth - 20; // 水印横坐标
      y = (imageHeight - watermarkHeight) / 2; // 水印纵坐标
      break;
    case "下左":
      x = 10; // 水印横坐标
      y = imageHeight - watermarkHeight - 20; // 水印纵坐标
      break;
    case "下中":
      x = (imageWidth - watermarkWidth) / 2; // 水印横坐标
      y = imageHeight - watermarkHeight - 20; // 水印纵坐标
      break;
    case "下右":
      x = imageWidth - watermarkWidth - 20; // 水印横坐标
      y = imageHeight - watermarkHeight - 20; // 水印纵坐标
      break;
  }
  return {
    x,
    y,
  };
}

(3)添加文字水印

使用 jimp 模块读取输入图片,根据水印文字和位置参数创建水印图层,并与原始图片进行合成,最后保存处理后的图片到输出路径。具体说明已在下面代码中注释。

javascript 复制代码
async function addWaterMark(
  inputFilePath,
  outputFilePath,
  watermarkText,
  watermarkPos,
  textconfig = {}
) {
//接收五个参数:`inputFilePath`(输入图片文件路径)、`outputFilePath`(输出图片文件路径)、`watermarkText`(水印文字内容)、`watermarkPos`(水印位置)、`textconfig`(文本配置,可选)。
  textOptions.text = watermarkText;
  for (const k in textconfig) {
    textOptions[k] = textconfig[k];
  }
  // 使用 `Jimp.read` 方法读取输入图片文件,并使用 `Jimp.loadFont` 方法加载字体文件
  const image = await Jimp.read(inputFilePath);
  const font = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE);

  // 获取输入图片和水印的宽度和高度,使用 `Jimp.measureText` 方法测量水印文字的宽度,使用 `Jimp.measureTextHeight` 方法测量水印文字的高度。
  const imageWidth = image.getWidth();
  const imageHeight = image.getHeight();
  const watermarkWidth = Jimp.measureText(font, watermarkText);
  const watermarkHeight = Jimp.measureTextHeight(
    font,
    watermarkText,
    watermarkWidth
  );

  // 调用 `getPosition` 函数计算水印放置的位置,根据输入图片和水印的尺寸以及水印位置参数 `watermarkPos`。
  const { x, y } = getPosition(
    {
      height: imageHeight,
      width: imageWidth,
    },
    { height: watermarkHeight, width: watermarkWidth },
    watermarkPos
  );

  // 创建一个新的 `Jimp` 对象作为背景图层,宽度为水印宽度加上 20 像素,高度为水印高度加上 20 像素,并设置背景颜色为半透明黑色(0x00000030)
  const background = new Jimp(
    watermarkWidth + 20,
    watermarkHeight + 20,
    0x00000030
  ); // 0x00000080 表示半透明黑色背景

  // 将水印文字打印到背景图层上,使用指定的字体、起始坐标(10, 10)、文本配置 `textOptions`,并指定水印文字的宽度和高度。
  background.print(font, 10, 10, textOptions, watermarkWidth, watermarkHeight);

  // 将背景图层与原始图片进行合成,使用指定的合成模式 `Jimp.BLEND_SOURCE_OVER`。
  image.composite(background, x, y, { mode: Jimp.BLEND_SOURCE_OVER });

  // 将处理后的图片保存到输出图片文件路径 `outputFilePath`。
  await image.writeAsync(outputFilePath);
}

插件体验

安装

shell 复制代码
npm install -g jyeontu

使用

shell 复制代码
jyeontu img

按交互提示进行选择操作即可。

源码

gitee

gitee.com/zheng_yongt...

公众号

关注公众号『前端也能这么有趣』,发送jyeontu获取源码。

获取更多有趣内容

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

说在后面

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

相关推荐
YHHLAI几秒前
从 SPA 到 Next.js 全栈:一个大前端的 SEO 突围笔记
javascript
IMPYLH2 分钟前
HTML 的 <small> 元素
前端·网络·html
IT_陈寒3 分钟前
Vue的响应式让我加班到凌晨,问题竟出在这个不起眼的地方
前端·人工智能·后端
AlienZHOU9 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc12 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师13 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen14 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒14 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
65岁退休Coder14 小时前
PI Agent 开发一个生产级 Harness
后端·node.js·agent
前端snow14 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端