![Board logo](images/default/logo.gif)
标题: [其他] 数字盲水印工具dct.exe [打印本页]
作者: happy886rr 时间: 2017-11-10 15:03 标题: 数字盲水印工具dct.exe
http://bcn.bathome.net/s/tool/index.html?key=dct
使用了DCT离散余弦变换,可以在图片中嵌入全盲数字水印,利用模拟量子态,成功解决信息的稳定性。图片即使被调色,被ps处理,其嵌入的数字水印依然可读取。本工具采取非开源策略。
使用说明:- 加数字盲水印:
- dct [输入图片] [输出图片] [水印字符串]
- 解数字盲水印:
- dct [输入图片]
复制代码
核心函数- // 离散余弦变换核心
- int DCT2D(double* cMatrix, double* pBmpMatrix, double* cMatrixT, int Nx, int Ny, int N, DCT2Mode mode, byte* insertData, int insertLen)
- {
- // 如果在编码模式下
- if(mode == DCT2_ENCODE_MODE)
- {
- // 检测插入长度是否合法
- if
- (
- (insertLen <= 0) ||
- (insertLen > Nx * Ny / 8) ||
- (Nx == 0) ||
- (Ny == 0)
- )
- {
- // 插入数据量过大,则退出
- fprintf(stdout, "You can't inserted bytes to the picture\n");
- exit(1);
- }
- }
-
- // 辅助数组
- double* pTmp = (double*)malloc(N * N * sizeof(double));
- int pBmpMatrixWith = Nx * N;
-
- // 插入索引位
- int insertIndex = 0;
-
- // 分块DCT变换
- for(int j = 0; j < Ny; j ++)
- {
- for(int i = 0; i < Nx; i ++)
- {
- int xOffset = i * N;
- int yOffset = j * N * pBmpMatrixWith;
-
- // 正交化乘以系数矩阵
- for(int dy = 0; dy < N; dy ++)
- {
- for(int dx = 0; dx < N; dx ++)
- {
- double sum = 0.0f;
- for(int sn = 0; sn < N; sn ++)
- {
- sum += (*(cMatrix + (dy * N + sn))) * (*(pBmpMatrix + (yOffset + sn * pBmpMatrixWith) + (xOffset+ dx)));
- }
-
- *(pTmp + (dy * N + dx)) = sum;
- }
- }
-
- // 正交化乘以转置系数矩阵
- for(int dy = 0; dy < N; dy ++)
- {
- for(int dx = 0; dx < N; dx ++)
- {
- double sum = 0.0f;
- for(int sn = 0; sn < N; sn ++)
- {
- sum += (*(pTmp + (dy * N + sn))) * (*(cMatrixT + (sn * N) + dx));
- }
-
- *(pBmpMatrix + (yOffset + dy * pBmpMatrixWith) + (xOffset+ dx)) = sum;
- }
- }
-
- // 逆变换模式
- if(mode == DCT2_INVERSE_TRANSFORM)
- {
- continue;
- }
-
- // 编码模式
- if(mode == DCT2_ENCODE_MODE)
- {
- double* pA = pBmpMatrix + (yOffset + 5 * pBmpMatrixWith) + (xOffset+ 5);
- double* pB = pBmpMatrix + (yOffset + 6 * pBmpMatrixWith) + (xOffset+ 6);
-
- // 采集密文bit位
- int insertV = ((int)(*(insertData + insertIndex / 8))) & ((int)(0x80 >> (insertIndex & 7)));
-
- if(insertV == 0)
- {
- if(*pA > *pB)
- {
- SWAP_DOUBLE(*pA, *pB);
- }
-
- *pB += 1.0f;
- }
- else
- {
- if(*pA < *pB)
- {
- SWAP_DOUBLE(*pA, *pB);
- }
- *pB -= 1.0f;
- }
-
- // 插入计数器
- insertIndex ++;
- continue;
- }
-
- // 解码模式
- if(mode == DCT2_DECODE_MODE)
- {
- double* pA = pBmpMatrix + (yOffset + 5 * pBmpMatrixWith) + (xOffset+ 5);
- double* pB = pBmpMatrix + (yOffset + 6 * pBmpMatrixWith) + (xOffset+ 6);
- byte* pInsertV = (byte*)(insertData + (insertIndex >> 3));
-
- if(*pA > *pB)
- {
- *pInsertV |= (byte)(0x80 >> (insertIndex & 7));
- }
-
- // 插入计数器
- insertIndex ++;
- continue;
- }
- }
- }
-
- // 释放辅助数组
- free(pTmp);
- return 0;
- }
复制代码
作者: CrLf 时间: 2017-11-12 02:04
研究了半天代码,看不懂...放弃
作者: happy886rr 时间: 2017-11-12 09:44
回复 2# CrLf
离散余弦变换,就是把密文转化为图片频域能量添加到图片上,再逆变换成图片,参见这个帖子https://www.cnblogs.com/zkwarrior/p/5980191.html
说白了就是防止盗图用的,我的代码中只用了1.0f倍的能量,如果改成1000被,那么别人把图片压缩,调色,密文依然能还原,也就是密文不是嵌入到二进制数据里,而是嵌入到图片的灰度频率里。你通过ps软件对图片压缩、修改、调色、甚至直接拍照, 其解密的密文依然不变。 用于网站防盗图、信息隐藏等方面。
作者: CrLf 时间: 2017-11-12 13:17
66666,其实看过这篇(好像是知乎),但是还是很难理解
我原以为会在核心代码里看到 sin,然而并没有
作者: happy886rr 时间: 2017-11-12 14:30
本帖最后由 happy886rr 于 2017-11-12 14:32 编辑
回复 4# CrLf
调用数学库函数慢,都提前求好,转化为整数。因为它是分块处理的,就是每次处理一个8*8的小格子,那些cos系数提前算出来并量化为整数比值,这样可以用整形替代浮点型。
说白了就是cos之类的,提前就算好,存在一个static const int 系数[8][8]的数组里。
作者: CrLf 时间: 2017-11-12 23:02
回复 5# happy886rr
soga
作者: zgzxp 时间: 2018-4-8 17:01
加入水印的文件再截图后,解密不了原水印
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |