[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

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

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. }
复制代码
4

评分人数

研究了半天代码,看不懂...放弃

TOP

回复 2# CrLf
离散余弦变换,就是把密文转化为图片频域能量添加到图片上,再逆变换成图片,参见这个帖子https://www.cnblogs.com/zkwarrior/p/5980191.html
说白了就是防止盗图用的,我的代码中只用了1.0f倍的能量,如果改成1000被,那么别人把图片压缩,调色,密文依然能还原,也就是密文不是嵌入到二进制数据里,而是嵌入到图片的灰度频率里。你通过ps软件对图片压缩、修改、调色、甚至直接拍照, 其解密的密文依然不变。 用于网站防盗图、信息隐藏等方面。

TOP

66666,其实看过这篇(好像是知乎),但是还是很难理解
我原以为会在核心代码里看到 sin,然而并没有

TOP

本帖最后由 happy886rr 于 2017-11-12 14:32 编辑

回复 4# CrLf
调用数学库函数慢,都提前求好,转化为整数。因为它是分块处理的,就是每次处理一个8*8的小格子,那些cos系数提前算出来并量化为整数比值,这样可以用整形替代浮点型。
说白了就是cos之类的,提前就算好,存在一个static const int 系数[8][8]的数组里。

TOP

回复 5# happy886rr


    soga

TOP

加入水印的文件再截图后,解密不了原水印

TOP

返回列表