⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 watermarking.cpp

📁 电子书《数字图像处理学》Visual C++实现 郎锐编写 所附源码
💻 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 + -