找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 23636|回复: 6

[其他] 数字盲水印工具dct.exe

[复制链接]
发表于 2017-11-10 15:03:03 | 显示全部楼层 |阅读模式
http://bcn.bathome.net/s/tool/index.html?key=dct
使用了DCT离散余弦变换,可以在图片中嵌入全盲数字水印,利用模拟量子态,成功解决信息的稳定性。图片即使被调色,被ps处理,其嵌入的数字水印依然可读取。本工具采取非开源策略。

使用说明:

  1. 加数字盲水印:
  2.     dct [输入图片] [输出图片] [水印字符串]
  3. 解数字盲水印:
  4.     dct [输入图片]
复制代码


核心函数
  1. // 离散余弦变换核心
  2. int DCT2D(double* cMatrix, double* pBmpMatrix, double* cMatrixT, int Nx, int Ny, int N, DCT2Mode mode, byte* insertData, int insertLen)
  3. {
  4.         // 如果在编码模式下
  5.         if(mode == DCT2_ENCODE_MODE)
  6.         {
  7.                 // 检测插入长度是否合法
  8.                 if
  9.                 (
  10.                     (insertLen <= 0)          ||
  11.                     (insertLen > Nx * Ny / 8) ||
  12.                     (Nx == 0)                 ||
  13.                     (Ny == 0)
  14.                 )
  15.                 {
  16.                         // 插入数据量过大,则退出
  17.                         fprintf(stdout, "You can't inserted bytes to the picture\n");
  18.                         exit(1);
  19.                 }
  20.         }

  21.         // 辅助数组
  22.         double* pTmp = (double*)malloc(N * N * sizeof(double));
  23.         int pBmpMatrixWith = Nx * N;

  24.         // 插入索引位
  25.         int insertIndex = 0;

  26.         // 分块DCT变换
  27.         for(int j = 0; j < Ny; j ++)
  28.         {
  29.                 for(int i = 0; i < Nx; i ++)
  30.                 {
  31.                         int xOffset = i * N;
  32.                         int yOffset = j * N * pBmpMatrixWith;

  33.                         // 正交化乘以系数矩阵
  34.                         for(int dy = 0; dy < N; dy ++)
  35.                         {
  36.                                 for(int dx = 0; dx < N; dx ++)
  37.                                 {
  38.                                         double sum = 0.0f;
  39.                                         for(int sn = 0; sn < N; sn ++)
  40.                                         {
  41.                                                 sum += (*(cMatrix + (dy * N + sn))) * (*(pBmpMatrix + (yOffset + sn * pBmpMatrixWith) + (xOffset+ dx)));
  42.                                         }

  43.                                         *(pTmp + (dy * N + dx)) = sum;
  44.                                 }
  45.                         }

  46.                         // 正交化乘以转置系数矩阵
  47.                         for(int dy = 0; dy < N; dy ++)
  48.                         {
  49.                                 for(int dx = 0; dx < N; dx ++)
  50.                                 {
  51.                                         double sum = 0.0f;
  52.                                         for(int sn = 0; sn < N; sn ++)
  53.                                         {
  54.                                                 sum += (*(pTmp + (dy * N + sn))) * (*(cMatrixT + (sn * N) + dx));
  55.                                         }

  56.                                         *(pBmpMatrix + (yOffset + dy * pBmpMatrixWith) + (xOffset+ dx)) = sum;
  57.                                 }
  58.                         }

  59.                         // 逆变换模式
  60.                         if(mode == DCT2_INVERSE_TRANSFORM)
  61.                         {
  62.                                 continue;
  63.                         }

  64.                         // 编码模式
  65.                         if(mode == DCT2_ENCODE_MODE)
  66.                         {
  67.                                 double* pA = pBmpMatrix + (yOffset + 5 * pBmpMatrixWith) + (xOffset+ 5);
  68.                                 double* pB = pBmpMatrix + (yOffset + 6 * pBmpMatrixWith) + (xOffset+ 6);

  69.                                 // 采集密文bit位
  70.                                 int insertV = ((int)(*(insertData + insertIndex / 8))) & ((int)(0x80 >> (insertIndex & 7)));

  71.                                 if(insertV == 0)
  72.                                 {
  73.                                         if(*pA > *pB)
  74.                                         {
  75.                                                 SWAP_DOUBLE(*pA, *pB);
  76.                                         }

  77.                                         *pB += 1.0f;
  78.                                 }
  79.                                 else
  80.                                 {
  81.                                         if(*pA < *pB)
  82.                                         {
  83.                                                 SWAP_DOUBLE(*pA, *pB);
  84.                                         }
  85.                                         *pB -= 1.0f;
  86.                                 }

  87.                                 // 插入计数器
  88.                                 insertIndex ++;
  89.                                 continue;
  90.                         }

  91.                         // 解码模式
  92.                         if(mode == DCT2_DECODE_MODE)
  93.                         {
  94.                                 double* pA = pBmpMatrix + (yOffset + 5 * pBmpMatrixWith) + (xOffset+ 5);
  95.                                 double* pB = pBmpMatrix + (yOffset + 6 * pBmpMatrixWith) + (xOffset+ 6);
  96.                                 byte* pInsertV = (byte*)(insertData + (insertIndex >> 3));

  97.                                 if(*pA > *pB)
  98.                                 {
  99.                                         *pInsertV |= (byte)(0x80 >> (insertIndex & 7));
  100.                                 }

  101.                                 // 插入计数器
  102.                                 insertIndex ++;
  103.                                 continue;
  104.                         }
  105.                 }
  106.         }

  107.         // 释放辅助数组
  108.         free(pTmp);
  109.         return 0;
  110. }
复制代码

评分

参与人数 4PB +22 技术 +4 收起 理由
CrLf + 10 + 1 大神
老刘1号 + 1 6x6x
freesoft00 + 1 +1
523066680 + 12 + 1 达人

查看全部评分

发表于 2017-11-12 02:04:27 | 显示全部楼层
研究了半天代码,看不懂...放弃
 楼主| 发表于 2017-11-12 09:44:39 | 显示全部楼层
回复 2# CrLf
离散余弦变换,就是把密文转化为图片频域能量添加到图片上,再逆变换成图片,参见这个帖子https://www.cnblogs.com/zkwarrior/p/5980191.html
说白了就是防止盗图用的,我的代码中只用了1.0f倍的能量,如果改成1000被,那么别人把图片压缩,调色,密文依然能还原,也就是密文不是嵌入到二进制数据里,而是嵌入到图片的灰度频率里。你通过ps软件对图片压缩、修改、调色、甚至直接拍照, 其解密的密文依然不变。 用于网站防盗图、信息隐藏等方面。
发表于 2017-11-12 13:17:25 | 显示全部楼层
66666,其实看过这篇(好像是知乎),但是还是很难理解
我原以为会在核心代码里看到 sin,然而并没有
 楼主| 发表于 2017-11-12 14:30:55 | 显示全部楼层
本帖最后由 happy886rr 于 2017-11-12 14:32 编辑

回复 4# CrLf
调用数学库函数慢,都提前求好,转化为整数。因为它是分块处理的,就是每次处理一个8*8的小格子,那些cos系数提前算出来并量化为整数比值,这样可以用整形替代浮点型。
说白了就是cos之类的,提前就算好,存在一个static const int 系数[8][8]的数组里。
发表于 2017-11-12 23:02:32 | 显示全部楼层
回复 5# happy886rr


    soga
发表于 2018-4-8 17:01:45 | 显示全部楼层
加入水印的文件再截图后,解密不了原水印
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 02:51 , Processed in 0.010638 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表