📄 watermarking.cpp
字号:
// ************************************************************************
// 文件名:WaterMarking.cpp
//
// 水印添加函数库:
//
// Set() - 水印嵌入函数
// Get() - 水印检测函数
//
// ************************************************************************
#include "stdafx.h"
#include "dip_system.h"
#include "WaterMarking.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WIDTH 100
#define HEIGHT 100
/////////////////////////////////////////////////////////////////////////////
// CWaterMarking
CWaterMarking::CWaterMarking()
{
}
CWaterMarking::~CWaterMarking()
{
}
BEGIN_MESSAGE_MAP(CWaterMarking, CWnd)
//{{AFX_MSG_MAP(CWaterMarking)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWaterMarking message handlers
/*************************************************************************
*
* 函数名称:
* Set()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数为DIB图象添加水印
*
************************************************************************/
void CWaterMarking::Set(HDIB hDIB)
{
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 从水印文件获取相关信息
char exeFullPath[MAX_PATH];
CString strPath;
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
strPath = CString(exeFullPath);
strPath = strPath.Left(strPath.ReverseFind('\\'));
strPath += "\\水印.bmp";
CFile file;
file.Open(strPath, CFile::modeReadWrite);
int nFileLen = file.GetLength();
unsigned char* lpBuf;
lpBuf = new unsigned char[nFileLen];
nFileLen = file.Read(lpBuf, nFileLen);
file.Close();
if (lLineBytes * lHeight < 4 * nFileLen)
{
// 提示用户
MessageBox("载体位图太小,不能容纳水印!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 释放内存
delete lpBuf;
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 填冗余位时的移位序列
int move1[13] = {6, 5, 2, 0, 7, 4, 2, 1, -2, 6, 4, 3, 0};
// 待隐藏文件的字节掩码序列
unsigned char mask1[13]={192, 32, 28, 3, 128, 112, 12, 2, 1, 192, 48, 8, 7};
// 位图文件的字节掩码序列
unsigned char mask2[13]={252, 254, 248, 252, 254, 248, 252, 254, 251, 252, 252, 254, 248};
// 为1时pointer1指针加一
int add1[13]={0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1};
// 为1时pointer2指针加一
int add2[13]={1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1};
// 临时指针
int pointer1 = 0;
int pointer2 = 0;
int pointer3 = 0;
while(pointer1 <= nFileLen)
{
// 将水印比特流嵌入到载体位图
if (move1[pointer3] > 0)
*(lpDIBBits + pointer2) = (*(lpDIBBits + pointer2) & mask2[pointer3])|((lpBuf[pointer1] & mask1[pointer3]) >> move1[pointer3]);
else
*(lpDIBBits + pointer2) = (*(lpDIBBits + pointer2) & mask2[pointer3])|((lpBuf[pointer1] & mask1[pointer3]) << move1[pointer3] * (-1));
//修正指针
if (add1[pointer3] == 1)
pointer1++;
if (add2[pointer3] == 1)
pointer2++;
pointer3++;
pointer3 %= 13;
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
delete lpBuf;//释放缓存
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* Get()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* CFile& file - 水印文件
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数从DIB图象提取出水印
*
************************************************************************/
void CWaterMarking::Get(HDIB hDIB, CFile &file)
{
// 嵌入水印的长度
int nFileLen = 54 + 3 * WIDTH * HEIGHT;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 分配并初始化内存
unsigned char* lpBuf1;
unsigned char* lpBuf2;
lpBuf1 = new unsigned char [lLineBytes * lHeight];
lpBuf2 = new unsigned char [lLineBytes * lHeight];
memset(lpBuf1, 0, lLineBytes * lHeight);
memset(lpBuf2, 0, lLineBytes * lHeight);
//拼合文件信息字节时的移位序列
int move2[13] = {6, 5, 2, 0, 7, 4, 2, 1, -2, 6, 4, 3, 0};
//位图文件字节的掩码序列
unsigned char mask2[13]={3, 1, 7, 3, 1, 7, 3, 1, 4, 3, 3, 1, 7};
// 为1时pointer1指针加一
int add1[13]={0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1};
// 为1时pointer2指针加一
int add2[13]={1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1};
// 临时指针
int pointer1 = 0;
int pointer2 = 0;
int pointer3 = 0;
int pointer4 = 0;
// 提取水印数据
while(true)
{
// 从DIB字节流中提取出水印数据
if(move2[pointer3] > 0)
lpBuf2[pointer1] |= (*(lpDIBBits + pointer2) & mask2[pointer3]) << move2[pointer3];
else
lpBuf2[pointer1] |= (*(lpDIBBits + pointer2) & mask2[pointer3]) >> (move2[pointer3] * (-1));
if(add1[pointer3] == 1)
{
lpBuf1[pointer4] = lpBuf2[pointer1];
pointer4++;
// 水印提取完毕,跳出循环
if(pointer4 > nFileLen)
break;
//修正指针
pointer1++;
}
//修正指针
if(add2[pointer3] == 1)
pointer2++;
pointer3++;
pointer3 %= 13;
}
file.Write(lpBuf1, nFileLen);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
//释放缓存
delete lpBuf1;
delete lpBuf2;
// 恢复光标
EndWaitCursor();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -