龙空技术网

编写一个图片去水印的小工具

xue5hen 359

前言:

此时姐妹们对“图像水印算法代码”可能比较讲究,小伙伴们都想要分析一些“图像水印算法代码”的相关内容。那么小编同时在网上收集了一些有关“图像水印算法代码””的相关内容,希望小伙伴们能喜欢,朋友们一起来了解一下吧!

原理分析

为了便于分析原理,我写了一个简单的Demo,如下图所示,在Demo页面中有三张单色图片,第一张原始图是颜色为#999的灰色图片,第二张水印图是颜色为#fff透明度为0.7的图片,第三张结果图是前两张图片合成以后得到的图片。

demo

在右侧的控制台打印出了这三张图片的数据(数据是通过canvas画布中的getImageData方法获取到的),从数据中可以看到,三张图片的宽高均为100像素,数据长度均为40000。可以看出,每张图片有100*100个像素点,每个像素点用4个长度来表示,分别是R(红)、G(绿)、B(蓝)、A(透明度)。

接下来,对比下三张图片数据有何不同,原图片和水印图的数据是怎么得到结果图的数据的?

稍微想一下,应该可以得出一个思路:水印图的透明度为0.7,意味着它的色值在结果图中占的比重是70%,原始图因为被水印图遮挡,所以占的比重是剩余的30%。于是,153 × 0.3 + 255 × 0.7 = 224.4,向上取整后为225,正好与结果图中数据相等。

功能实现

实践是检验理论的唯一手段。根据上述猜测的计算方式,如果已知结果图和水印图,那么应该就可以推算出来原始图。不过需要准备好与待处理图片相对应的水印图片,确保它们的尺寸大小和水印位置是一致的,否则靠程序自己去猜测水印位置的话,需要额外复杂的算法和很大的计算量支撑。

这里我设计的程序界面如下:

程序界面

程序上方是参数配置,可以设置水印图片和下载目录,左侧区域是待处理图片列表区,可以将待处理的图片拖拽进来,右侧区域是图片预览区域,点选左侧某一条数据可以对其进行预览。

程序去水印的关键代码如下:

// 获取imgDatagetImgData (imgObj) {    let canvasObj = document.createElement('canvas')    canvasObj.width = imgObj.width    canvasObj.height = imgObj.height    let ctx = canvasObj.getContext('2d')    ctx.drawImage(imgObj, 0, 0, canvasObj.width, canvasObj.height)    let imgData = ctx.getImageData(0, 0, canvasObj.width, canvasObj.height)    return imgData.data}
let imgData = this.imagesList[index].imgDatalet imgData_sy = this.watermarkInfo.imgDataif (imgData.length !== imgData_sy.length) {    this.$toast('待处理图片与水印图片大小不一致')    return reject('待处理图片与水印图片大小不一致')}let bakColor = nullfor (let i = imgData.length - 4; i > -1; i -= 4) {    if (!imgData_sy[i + 3]) {        bakColor = [imgData[i + 0], imgData[i + 1], imgData[i + 2], imgData[i + 3]]        continue    } else if (imgData_sy[i + 3] === 255 && bakColor) {        imgData[i + 0] = bakColor[0]        imgData[i + 1] = bakColor[1]        imgData[i + 2] = bakColor[2]        imgData[i + 3] = bakColor[3]        continue    }    let opacity_sy = imgData_sy[i + 3] / 255    let opacity_raw = (255 - imgData_sy[i + 3]) / 255    imgData[i + 0] = (imgData[i + 0] - imgData_sy[i + 0] * opacity_sy) / opacity_raw    imgData[i + 1] = (imgData[i + 1] - imgData_sy[i + 1] * opacity_sy) / opacity_raw    imgData[i + 2] = (imgData[i + 2] - imgData_sy[i + 2] * opacity_sy) / opacity_raw    if (imgData[i + 3] > 0 && imgData[i + 3] < 255) {        imgData[i + 3] = (imgData[i + 3] - imgData_sy[i + 3]) / opacity_raw    }}this.imagesList[index].imgData = imgData// imgData2dataUrllet canvasObj = document.createElement('canvas')canvasObj.width = item.imgObj.widthcanvasObj.height = item.imgObj.heightlet ctx = canvasObj.getContext('2d')let imageData = new ImageData(imgData, canvasObj.width, canvasObj.height)ctx.putImageData(imageData, 0, 0)

经测,常见的水印可以正常去除;对于不透明的水印,这里采用的是使用附近的图片色值来替代;假设原始图片本身也是半透明,这种情况下,透明度好计算,但色值计算存在些许误差,不过好在这种情况在现实中相对较少。

标签: #图像水印算法代码