- 上传时加水印
- 用户上传原始图片 => 服务器保留原始图片以及水印图片
- 动态水印
- 用户上传原始图片 => 服务器只保留原始图片,
- 请求图片的时候,服务器动态添加水印
插件:jimp
官网:https://github.com/oliver-moran/jimp/tree/master/packages/jimp
安装jimp
npm i jimp@0.10.3
封装添加水印的方法
// 给一张图片加水印
async function mark(
waterFile,
originFile,
targetFile,
proportion = 5,
marginProportion = 0.01
) {
const [water, origin] = await Promise.all([
jimp.read(waterFile),
jimp.read(originFile),
]);
// 对水印图片进行缩放
const curProportion = origin.bitmap.width / water.bitmap.width;
water.scale(curProportion / proportion);
// 计算位置
const right = origin.bitmap.width * marginProportion;
const bottom = origin.bitmap.height * marginProportion;
const x = origin.bitmap.width - right - water.bitmap.width;
const y = origin.bitmap.height - bottom - water.bitmap.height;
// 写入水印
origin.composite(water, x, y, {
mode: jimp.BLEND_SOURCE_OVER,
opacitySource: 0.3,
});
await origin.write(targetFile);
}
- 参数
- waterFile : 水印图片的地址
- originFile: 源图片的地址,
- targetFile: 添加好图片以后,图片存放的地址
- proportion: 比例,原始图片的宽度/水印图片的宽度
- marginProportion: 水印图片距离边框的距离,是一个比例,原始图片宽度和高度的比例
- 对水印图片进行缩放
// 对水印图片进行缩放
const curProportion = origin.bitmap.width / water.bitmap.width;
water.scale(curProportion / proportion);
- 位图:
origin.bitmap
一个一个的像素点
计算图片水印的位置
// 计算位置
const right = origin.bitmap.width * marginProportion;
const bottom = origin.bitmap.height * marginProportion;
const x = origin.bitmap.width - right - water.bitmap.width;
const y = origin.bitmap.height - bottom - water.bitmap.height;
写入水印
origin.composite(water, x, y, {
mode: jimp.BLEND_SOURCE_OVER,
opacitySource: 0.3,
});
await origin.write(targetFile);
- mode: 水印的模式,水印图片在原图片之上
- opacitySource: 水印透明度
- 更多参数详见官网:https://github.com/oliver-moran/jimp/tree/master/packages/jimp
使用水印方法
在图片上传的时候,调用水印方法,可以利用缩放water.scale(比例)
,做成不同尺寸(大小)的图片
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const jimp = require('jimp');
// 给一张图片加水印
async function mark(
waterFile,
originFile,
targetFile,
proportion = 5,
marginProportion = 0.01
) {
const [water, origin] = await Promise.all([
jimp.read(waterFile),
jimp.read(originFile),
]);
// 对水印图片进行缩放
const curProportion = origin.bitmap.width / water.bitmap.width;
water.scale(curProportion / proportion);
// 计算位置
const right = origin.bitmap.width * marginProportion;
const bottom = origin.bitmap.height * marginProportion;
const x = origin.bitmap.width - right - water.bitmap.width;
const y = origin.bitmap.height - bottom - water.bitmap.height;
// 写入水印
origin.composite(water, x, y, {
mode: jimp.BLEND_SOURCE_OVER,
opacitySource: 0.3,
});
await origin.write(targetFile);
}
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.resolve(__dirname, '../../public/upload'))
},
filename: function (req, file, cb) {
// 时间戳 - 6位随机字符.文件后缀
const timeStamp = Date.now();
const ramdomStr = Math.random().toString(36).slice(-6);
const ext = path.extname(file.originalname);
const filename = `${timeStamp}-${ramdomStr}${ext}`;
cb(null, filename);
}
})
const upload = multer({
storage,
limits: {
fileSize: 1024 * 2014 * 10
},
fileFilter(req, file, cb) {
// 文件名
const extname = path.extname(file.originalname);
const whiteList = ['.jpg', '.gif', '.png', '.jpeg'];
if (whiteList.includes(extname)) {
cb(null, true);
} else {
cb(new Error(`you ext name of ${extname} is not support`));
}
}
});
const waterImg = path.resolve(__dirname, '../../public/img/sy.jpeg')
router.post('/', upload.single('avatar'), function (req, res, next) {
const url = `http://localhost:12306/upload/${req.file.filename}`;
const targetPath = path.resolve(__dirname, `../../public/upload/sy_${req.file.filename}`);
mark(waterImg, req.file.path, targetPath)
res.send({
success: true,
uid: "0",
name: "IMG.png",
state: "done",
url: url,
downloadURL: url,
imgURL: url,
size: 2000
})
})
module.exports = router;
这里在同一个文件夹下面,添加了一个增加前缀sy_的同名图片