# 图像盲水印

图像盲水印将水印信息以不可见的形式添加到原图信息中,您可对疑似被盗取的资源进行盲水印提取,验证图片归属。

# 功能特性

开通后,每个账户拥有三千次免费额度,超出后进行计费。为您提供半盲、全盲和文字盲水印三种类型,您可根据需要进行选择:

水印类型 特性 适用场景
半盲水印(type1) 抗攻击性强,但提取水印需原图 小图(640x640以下)使用
全盲水印(type2) 提取方便,提取水印仅需水印图 无需对比原图 批量添加,批量校验
文字水印(type3) 可直接将文字信息添加至图片中 终端信息添加

# 适用场景

# 鉴权追责

您可对图片资源增加半盲水印,在发现恶意攻击方盗取您的资源后将疑似被盗取图取回,并与相应原图进行盲水印提取操作,若能够得到有效水印图即可证明资源归属。

# 上传查重

为解决部分用户使用其他用户资源重复上传相同信息的问题(如房产图、汽车图、商品图等),您可在用户上传图片资源前先进行全盲水印提取,若提取到水印图信息则证明该图片来自之前已有资源,并进行相应操作(如提醒用户请勿重复上传资源);若不存在全盲水印则添加全盲水印,保护图片资源不被其他用户下载后重复上传。

# 资源防泄露

对于内部分享的图片资源,您可通过文字盲水印将访问方的信息在请求图片时添加至图片中,当资源泄露后可通过流传出的资源图提取出盲水印,进而得到泄露方信息。

  • 注意:您不仅在云函数中可以使用该扩展能力,也可以在客户端使用,文件读写权限策略与云存储一致,减去您额外的权限管理工作。

# 前置要求

  1. 已经开通云开发。
  2. 云环境已安装图像安全审核扩展,点击此处查看安装情况

# 使用说明

# 1.下载时添加水印

图片下载时添加盲水印与添加普通水印操作相同,只需在图片访问链接后使用 watermark 参数即可。相关内容如下:

watermark/3/type/<type>/image/<imageUrl>/text/<text>
// 例如:http://xxxxx.tcb.qcloud.la/demo.jpeg?watermark/3/type/3/text/dGVuY2VudCBjbG91ZA==
1
2

水印参数取值如:

参数 类型 必选 描述
type Int 盲水印类型,有效值:1 半盲;2 全盲;3 文字
image String 水印图片地址,需要经过 URL 安全的 Base64 编码。 当 type 为1或2时必填,type 为3时无效。 须同时满足 3 个条件:
1. 水印图片存储在当前环境的云存储中
2. 将您的文件访问域名中 tcb.qcloud.la 替换为 picsh.myqcloud.com 即可,如:examplebucket-1250000000.picsh.myqcloud.com
3. URL 必须以 http:// 开始。
text String 盲水印文字,需要经过 URL 安全的 Base64 编码。当 type 为3时必填,type 为1或2时无效。
# 2.上传图片并添加水印及提取水印
# 1. 安装扩展 SDK 到项目
npm install --save @cloudbase/extension-ci@latest
1
# 2. 注册扩展到Cloud对象

小程序中

const extCI = require('@cloudbase/extension-ci');

// 初始化环境
qq.cloud.init({
    env:"test-x1dzi"
})

// 注册云开发扩展
qq.cloud.registerExtension(extCI);
1
2
3
4
5
6
7
8
9

云函数中

const cloud = require('qq-server-sdk');
const extCI = require('@cloudbase/extension-ci');
// 初始化环境
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
// 注册云开发扩展
cloud.registerExtension(extCI);
1
2
3
4
5
6
7
8
# 3. 调用扩展 SDK
Cloud.invokeExtension(extensionName: String, options: Object): Promise
1

参数说明

参数 类型 是否必须 说明
extensionName String 扩展名,传CloudInfinite
options Object 扩展参数,说明见下方

options参数

名称 类型 是否必须 说明
action String 操作类型,传:WaterMark
cloudPath String 文件的绝对路径,与 cloud.uploadFile 中一致
fileContent ArrayBuffer或Buffer 文件内容, 有值,表示上传时处理图像;为空,则处理已经上传的图像
operations Object 盲水印处理参数

operations节点内容

名称 类型 是否必须 说明
rules Array.<Rule对象> 处理样式

Rule节点内容

名称 类型 是否必须 说明
fileid String 处理结果的文件路径,如以’/’开头,则存入指定文件夹中,否则,存入原图文件存储的同目录
rule String 处理参数

添加水印处理参数(rule)取值如下:

参数 类型 必选 描述
mode Int 操作类型,固定为3,添加水印
type Int 盲水印类型,有效值:1 半盲;2 全盲;3 文字,必须跟添加盲水印时的 type 类型一致
image String 盲水印图片地址,当前环境云存储中的路径
text String 盲水印文字,当 type 为3时必填,type 为1或2时无效。

提取水印处理参数(rule)取值如下:

参数 类型 必选 描述
mode Int 操作类型,固定为4,提取水印
type Int 盲水印类型,有效值:1 半盲;2 全盲;3 文字,必须跟添加盲水印时的 type 类型一致
image String 图片地址,当 type 为1或2时必填,type为3时无效。 type 为1时,为未带盲水印的原图图片地址;type 为2时,为已经添加盲水印的图地址
text String 盲水印文字,当 type 为3时必填,type 为1或2时无效

返回内容 返回内容

参数名称 类型 描述
UploadResult Object 原图信息

UploadResult 节点内容:

参数名称 类型 描述
ProcessResults Object 图片处理结果

ProcessResults 节点内容:

节点名称 类型 描述
Object Object 每一个图片处理结果

Object 节点内容:

节点名称 类型 描述
Key String 文件名
Location String 图片路径
Format String 图片格式
Width Int 图片宽度
Height Int 图片高度
Size Int 图片大小
Quality Int 图片质量
WatermarkStatus Int 提取盲水印且当 type 为2时返回该字段,表示提取到全盲水印的可信度。具体为0-100的数字,75分以上表示确定有盲水印,60-75表示疑似有盲水印,60以下可认为未提取到盲水印

# 调用示例

在小程序中使用

const extCI = require('@cloudbase/extension-ci');

// 初始化环境
qq.cloud.init({
    env:"test-x1dzi"
})

// 注册云开发扩展
qq.cloud.registerExtension(extCI);

// 用户选择图片
qq.chooseImage({
  success:res=>{
    // 使用文件管理读取文件内容
    const fsm = qq.getFileSystemManager();
    const filePath = res.tempFilePaths[0];
    const cloudPath = `demo.jpeg`;

    fsm.readFile({
      filePath:filePath,
      success:res2=>{
        const fileContent = res2.data; // 格式为ArrayBuffer
      }
    })
  }
})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

云函数中使用:

const cloud = require('qq-server-sdk');
const extCI = require('@cloudbase/extension-ci');
// 初始化环境
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

// 注册云开发扩展
cloud.registerExtension(extCI);

let fileContent = imageBuffer; // Buffer格式图像内容

1
2
3
4
5
6
7
8
9
10
11
12

您可以根据需要选择在【客户端】或【云函数】中使用,再按照如下代码调用:

async function addWaterMark() {
  try {
    const opts = {
      rules:
      [
        {
          // 处理结果的文件路径,如以’/’开头,则存入指定文件夹中,否则,存入原图文件存储的同目录
          fileid: "/watermark/demo.jpeg",
          rule: { // 添加水印处理规则
            mode: 3,
            type: 3,
            text: 'tcb' // 支持数字[0 - 9]及英文大小写[A - Z,a - z]
          }
        }
      ]
    }
    const res = await cloud.invokeExtension("CloudInfinite", { // 小程序里使用qq.cloud.invokeExtension
      action:'WaterMark',
      cloudPath: "demo.jpeg", // 存储图像的绝对路径,与cloud.uploadFile中一致
      fileContent, // 该字段可选,文件内容:ArrayBuffer|Buffer。有值,表示上传时处理图像;为空,则处理已经上传的图像
      operations:opts
    });
    console.log(JSON.stringify(res.data, null, 4));
  } catch (err) {
    console.log(JSON.stringify(err, null, 4));
  }
}

async function getWaterMark() {
  try {
    const opts = {rules: [
      {
        fileid: "/watermark/demo.jpeg",
        rule: { // 提取水印处理规则
          mode: 4,
          type: 1,
          image: '/tcb.jpeg'
        }
      }
    ]}
    const res = await cloud.invokeExtension("CloudInfinite", { // 小程序里使用qq.cloud.invokeExtension
      action:'WaterMark',
      cloudPath: "demo.jpeg", // 存储图像的绝对路径,与cloud.uploadFile中一致
      operations:opts
    });
    console.log(JSON.stringify(res.data, null, 4));
  } catch (err) {
    console.log(JSON.stringify(err, null, 4));
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51