用 idea 打开 first.html,也就是起一个前端项目,直接打开会报跨域错误。
打开后,选择自己想查看的图片。这里以第二张图片甘雨为例,打开后会到达二级页面,二级页面包括了四张图片:
这四张图片以此表示了:原图、带明水印的图、数字水印、带暗水印的图。
点击最后一张图,会解析出明水印。
二级界面文件夹下,有各个 html文件,一个css文件,一个 js 文件。
每个 html中都会链接到 css和 js 文件,html 中原本都只有一个 img 标签。css 文件没什么,就是规约了图片的大小。重点在 js 文件中。
waterMark.js 中的主体部分规定了两个全局变量,并执行了 run 方法。
var darkCanvas;
var created=0;
run();
接下来请看 run 方法。
async function run() {
const url = document.getElementsByClassName("img")[0].src;
const img = document.createElement("img");
img.src = url;
img.crossOrigin='Anonymous';
await new Promise((resolve) => (img.onload = resolve));
let canvas = document.createElement("canvas");
canvas.width = img.width * 400 / img.height;
canvas.height = 400;
//可见水印
bright(canvas,img);
document.body.appendChild(document.createElement("br"));
//黑底白字展示水印
let waterMarkCanvas=waterMark(canvas);
//展示不可见水印
dark(canvas,img,waterMarkCanvas);
}
接下来请看 bright 方法:
function bright(canvas,img) {
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#FFF";
ctx.font = "24px 黑体";
ctx.fillText("191250025丁笑宇", 20, 350);
draw(canvas);
}
bright 方法将图片画在画布上,并给画布的上下文加上了一些设置,然后调用 draw 方法,把画布当做图片输出。
接下来请看 draw 方法:
function draw(canvas) {
let img = new Image();
img.src = canvas.toDataURL("image/png");
document.body.appendChild(img);
}
draw 方法很简单,把画布当做图片输出,并放在当前 body 最后一个元素后面。
接下来请看 waterMark 方法:
function waterMark(canvas) {
let ctx=canvas.getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "#FFF";
ctx.font = "24px 黑体";
ctx.fillText("191250025丁笑宇", 20, 350);
draw(canvas);
return canvas;
}
和 bright 方法差不多,直接将画布设置成全黑,然后在上面绘制水印即可。
接下来请看 dark 方法:
function dark(canvas,img,waterMarkCanvas) {
let
temp=waterMarkCanvas.getContext("2d").getImageData(0,0,canvas.width,canvas.heigh t).data;
canvas.getContext("2d").drawImage(img, 0, 0, canvas.width, canvas.height);
let
digits=canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height);
for (let i=0; i
首先获得了水印画布和图片画布的 image 信息。我们注意到,图片中一个像素点对应了数组中四个数, 在水印画布中,如果某个点不属于水印,则这个点就是(0,0,0,255)。考虑到两张画布的大小一致,我 们可以做这样的记录: 倘若水印画布某个点的第一个值是 0,则将图片画布上对应位置的那个点的第一个 值置为偶数,否则将那个对应位置的那个点的第一个值置为奇数。 这样处理过后,我们判断图片画布上 的每一个点对应的第一个值的奇偶性,奇数表示是水印位置,偶数表示不是水印位置。
然后把处理过的数据画出来,并且给这张图片加上点击的监听器,绑定了 unload 这个方法,然后记录下 当前的这个画布。
接下来请看 unload 方法:
function unload() {
if (created===1) {
return;
}
let ctx=darkCanvas.getContext("2d");
let digits=ctx.getImageData(0,0,darkCanvas.width,darkCanvas.height);
for (let i=0; i
首先判断如果已经解码过了,就不会再解码。
然后我们对于 image 信息,判断每一个像素点的第一个数的奇偶性。如果是奇数,表示是水印位,就把这个像素点的四个值全部变成 255。