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

📄 wvlttrans.cpp

📁 一种图像水印加密算法 该算法抗攻击性强 安全性高 可以直接运行
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	//图像的属性参数
	int iWidth, iHeight, iWidth_H, iHeight_H;
	float fr = fRadius;
	//获得数据空间的指针
	pData = spOriginData;
	pTran0 = spTransData0;
	pTran1 = spTransData1;
	//图像属性参数赋值
	iWidth = nWidth;	
	iWidth_H = nWidth_H;
	iHeight = nHeight;	
	iHeight_H = nHeight_H;
	//利用循环完成两次小波变换
	for(i=1; i<=layer; i++)
	{
		DWT_Once(pData,pTran0,pTran1,iHeight,iHeight_H,iWidth,iWidth_H,i,fr);
		iHeight = iHeight>>1;//高度的一半	
		iWidth = iWidth>>1;//宽度的一半
		iHeight_H = iHeight/2;
		iWidth_H = iWidth/2;
	}

}



/********************************************************************************
*函数描述:	DWTi_Once完成一次图像小波变换的逆变换								*	
*函数参数:	short **spData		:二维指针,其数据空间存放小波逆变换后的图像数据*
*			short **spTransData0:小波变换系数,存放一次水平变换后的小波系数	*
*			short **spTransData1:小波变换系数,存放一次竖直变换后的小波系数	*
*			int   nHeight		:图像属性参数,数值为原始图像的高度值			*
*			int	  nHeight_H		:图像属性参数,数值为原始图像高度值的一半		*
*			int   nWidth		:图像属性参数,数值为原始图像的宽度值			*
*			int	  nWidth_H		:图像属性参数,数值为原始图像宽度值的一半		*
*			int   layer			:小波变换的层数,数值为3层						*
*			float fRadius		:小波变换因子,在调用时候已指定数值为1.414		*
********************************************************************************/

void CWvltTrans::DWTi_Once(float **spData, float **spTransData0, float **spTransData1, int nHeight, int nHeight_H, int nWidth, int nWidth_H, int layer, float fRadius)
{
	
	int Trans_W,				//图像扫描线控制:横坐标
		Trans_H,				//图像扫描线控制:纵坐标
		Trans_M,				//图像矩阵的横坐标
		Trans_N;				//图像矩阵的纵坐标
	int WvltCoeff0;			//小波变换系数
    signed int WvltCoeff1;

	for(Trans_N=0; Trans_N<nWidth; Trans_N++)
	{
		for(Trans_M=0; Trans_M<nHeight_H; Trans_M++)
		{
			spTransData1[Trans_M][Trans_N]/=fRadius;
			spTransData1[Trans_M+nHeight_H][Trans_N]*=fRadius;
		}
	}
	//逆变换是一个逆过程,所以先从竖直方向开始
	//竖直方向的逆变换(此时自然奇偶有序排列),Trans_N为图像矩阵的纵坐标
	for(Trans_N=0; Trans_N<nWidth_H; Trans_N++)
	{
		//偶数坐标的小波系数逆变换时的边界处理
		WvltCoeff0 = (int)((spTransData1[nHeight_H][Trans_N]+spTransData1[nHeight_H+1][Trans_N])/4);
		spTransData1[0][Trans_N] = spTransData1[0][Trans_N]-WvltCoeff0;
		WvltCoeff0 = (int)((spTransData1[nHeight_H][nWidth_H+Trans_N]+spTransData1[nHeight_H+1][nWidth_H+Trans_N])/4);
		spTransData1[0][nWidth_H+Trans_N] = spTransData1[0][nWidth_H+Trans_N]-WvltCoeff0;
		//竖直方向逆变换的第二次偶数坐标小波系数的逆变换
		for(Trans_M=1; Trans_M<nHeight_H; Trans_M++)
		{
			WvltCoeff0 = (int)((spTransData1[nHeight_H+Trans_M][Trans_N]+spTransData1[nHeight_H+Trans_M-1][Trans_N])/4);
			spTransData1[Trans_M][Trans_N] = spTransData1[Trans_M][Trans_N]-WvltCoeff0;
			WvltCoeff0 = (int)((spTransData1[nHeight_H+Trans_M][nWidth_H+Trans_N]+spTransData1[nHeight_H+Trans_M-1][nWidth_H+Trans_N])/4);
			spTransData1[Trans_M][nWidth_H+Trans_N] = spTransData1[Trans_M][nWidth_H+Trans_N]-WvltCoeff0;
		}
		//第二次奇数坐标小波系数的逆变换
		for(Trans_M=0; Trans_M<nHeight_H-1; Trans_M++)
		{
			WvltCoeff1 = (int)((spTransData1[Trans_M][Trans_N]+spTransData1[Trans_M+1][Trans_N])/2);
			WvltCoeff1=~WvltCoeff1+1;
			spTransData1[nHeight_H+Trans_M][Trans_N] = spTransData1[nHeight_H+Trans_M][Trans_N]-WvltCoeff1;
			WvltCoeff1 = (int)((spTransData1[Trans_M][nWidth_H+Trans_N]+spTransData1[Trans_M+1][nWidth_H+Trans_N])/2);
			WvltCoeff1=~WvltCoeff1+1;
			spTransData1[nHeight_H+Trans_M][nWidth_H+Trans_N] = spTransData1[nHeight_H+Trans_M][nWidth_H+Trans_N]-WvltCoeff1;
		}
		//奇数坐标小波系数逆变换时的边界处理
		WvltCoeff1 = ((spTransData1[nHeight_H-1][Trans_N]+spTransData1[nHeight_H-2][Trans_N])/2);
		WvltCoeff1=~WvltCoeff1+1;
		spTransData1[nHeight-1][Trans_N] = spTransData1[nHeight-1][Trans_N]-WvltCoeff1;
		WvltCoeff1 = (int)((spTransData1[nHeight_H-1][nWidth_H+Trans_N]+spTransData1[nHeight_H-2][nWidth_H+Trans_N])/2);
		WvltCoeff1=~WvltCoeff1+1;
		spTransData1[nHeight-1][nWidth_H+Trans_N] = spTransData1[nHeight-1][nWidth_H+Trans_N]-WvltCoeff1;
		//本模块完成变换系数的赋值采样的逆操作
		for(Trans_M=0; Trans_M<nHeight_H; Trans_M++)
		{
			Trans_H = Trans_M<<1;
			spTransData0[Trans_H][Trans_N] = spTransData1[Trans_M][Trans_N];
			spTransData0[Trans_H+1][Trans_N] = spTransData1[nHeight_H+Trans_M][Trans_N];
			spTransData0[Trans_H][nWidth_H+Trans_N] = spTransData1[Trans_M][nWidth_H+Trans_N];
			spTransData0[Trans_H+1][nWidth_H+Trans_N]= spTransData1[nHeight_H+Trans_M][nWidth_H+Trans_N];
		}
	}

	//去除小波变换中频带系数的滤波影响
	for(Trans_M=0; Trans_M<nHeight; Trans_M++)
	{
		for(Trans_N=0; Trans_N<nWidth_H; Trans_N++)
		{
			spTransData0[Trans_M][Trans_N]/=fRadius;
			spTransData0[Trans_M][Trans_N+nWidth_H]*=fRadius;
		}
	}
	//下面进行水平方向的逆变换
	//水平方向的逆变换
	for(Trans_H=0; Trans_H<nHeight; Trans_H++)
	{
		//偶数坐标小波系数逆变换时的边界处理
		WvltCoeff0 = (int)((spTransData0[Trans_H][nWidth_H]+spTransData0[Trans_H][nWidth_H+1])/4);
		spTransData0[Trans_H][0] = spTransData0[Trans_H][0]-WvltCoeff0;
		//第二次偶数坐标小波系数的逆变换
		for(Trans_N=1; Trans_N<nWidth_H; Trans_N++)
		{
			WvltCoeff0 = (int)((spTransData0[Trans_H][nWidth_H+Trans_N]+spTransData0[Trans_H][nWidth_H+Trans_N-1])/4);
			spTransData0[Trans_H][Trans_N] = spTransData0[Trans_H][Trans_N]-WvltCoeff0;
		}
		//第二次奇数坐标小波系数的逆变换
		for(Trans_N=0; Trans_N<nWidth_H-1; Trans_N++)
		{
			WvltCoeff1 = (int)((spTransData0[Trans_H][Trans_N]+spTransData0[Trans_H][Trans_N+1])/2);
			WvltCoeff1=~WvltCoeff1+1;
			spTransData0[Trans_H][nWidth_H+Trans_N] = spTransData0[Trans_H][nWidth_H+Trans_N]-WvltCoeff1;
		}
		//奇数坐标小波系数逆变换时的边界处理
		WvltCoeff1 = (int)((spTransData0[Trans_H][nWidth_H-1]+spTransData0[Trans_H][nWidth_H-2])/2);
		WvltCoeff1=~WvltCoeff1+1;
		spTransData0[Trans_H][nWidth-1] = spTransData0[Trans_H][nWidth-1]-WvltCoeff1;
		
		if(layer > 1)
		{
			for(Trans_N=0; Trans_N<nWidth_H; Trans_N++)
			{
			Trans_W =Trans_N<<1;
			spTransData1[Trans_H][Trans_W] = spTransData0[Trans_H][Trans_N];
			spTransData1[Trans_H][Trans_W+1] = spTransData0[Trans_H][nWidth_H+Trans_N];
			}
		}
		if(layer == 1)
		{
			for(Trans_N=0; Trans_N<nWidth_H; Trans_N++)
			{
				Trans_W =Trans_N<<1;
				if(fRadius!=2)
				{
					spTransData0[Trans_H][Trans_N]=spTransData0[Trans_H][Trans_N]+128;
					spTransData0[Trans_H][nWidth_H+Trans_N]=spTransData0[Trans_H][nWidth_H+Trans_N]+128;
				}
				if(spTransData0[Trans_H][Trans_N]>255) spTransData0[Trans_H][Trans_N]=255;
				if(spTransData0[Trans_H][Trans_N]<0)   spTransData0[Trans_H][Trans_N]=0;
				if(spTransData0[Trans_H][nWidth_H+Trans_N]>255) spTransData0[Trans_H][nWidth_H+Trans_N]=255;
				if(spTransData0[Trans_H][nWidth_H+Trans_N]<0)   spTransData0[Trans_H][nWidth_H+Trans_N]=0;
				
				spData[Trans_H][Trans_W] = spTransData0[Trans_H][Trans_N];
				
				spData[Trans_H][Trans_W+1] =spTransData0[Trans_H][nWidth_H+Trans_N];
			}
		}

	}

}




//add by fengshaohui
/********************************************************************************
*函数描述:	基于Logistic映射的二值水印生成								            *	
*
*			
********************************************************************************/

void CWvltTrans::LogisticWaterMark()
{	
	double* s = new double [MarkLength+1];//s用来存放混沌系统生成的实数
	double temp ;
	double T = 0.5;//(阈值)
	int* p = new int [MarkLength+1];//存放由序列s转化成的二值序列
	s[0] = 0.25;	
	int j = 0;
	for(int i = 0; i<MarkLength; i++ )
	{		
		temp = 3.93*s[i]*(1 - s[i]);
		j = i + 1;
		s[j] = temp; 
		//将生成的实数转化为二值整数
		if(s[i] < T )
		{
			s[i] = 0;
			p[i] = (int)s[i];
		}
		else
		{
			s[i] = 1;
			p[i] = (int)s[i];

		}
		//将原始二值水印信息与上面得到的二值序列异或得到水印信息		
        WaterMarkOrigin[i] = p[i] ^ WaterMarkOrigin[i];
	}
    
	if( s!=NULL)
	{
		delete[]  s;
		s = NULL;
	}
    if( p!=NULL)
	{
		delete[]  p;
		p = NULL;
	}

}

//改变水印序列的值域为{-1,1}
void CWvltTrans::changeMarkValue()
{
	
	for(int i=0; i<MarkLength; i++)
	{
		if(WaterMarkOrigin[i] == 0)
		{
			WaterMarkOrigin[i] = -1;
		}
	}

}
/**********************************************************************************************
功能:加载二值水印,调用此函数后CoeffChoosed[][]中为被水印信息修改完的选定系数,m_WvltCoeff[][]为加载水印信息后的全部系数
   CoeffChoosed[][]数组大小与原始图像像素数相同,WaterMarkOrigin[]中为-1与1序列
说明:用乘性规则嵌入,对单个图像加载水印
 **********************************************************************************************/
void CWvltTrans::LoadWaterMark()
{
	//changeMarkValue();//转换水印的值域([0,1]->[-1,1])	
	int i,j;
	int k=0;
	/*
	//将嵌入前的选定系数写到文件中
	char FilePathBuf[MAX_PATH];
	GetCurrentDirectory(100,FilePathBuf);
	CString strFilePath = FilePathBuf;
	strFilePath = strFilePath + "\\CoeffChoosedBeforeLoad.txt";
	WriteFile(strFilePath,CoeffChoosed,biHeight,biWidth);
    */
    float** TempCoeff = new float* [biHeight];
    for(i=0; i<biHeight; i++)//控制选定系数的行
	{
		TempCoeff[i] = new float[biWidth];
	}
	for(i=0; i<biHeight; i++)//控制选定系数的行
	{
		for(j=0; j<biWidth; j++)//控制选定系数的列
		{
			TempCoeff[i][j] = CoeffChoosed[i][j];
		}
	}

	for(i=0; i<biHeight; i++)//控制选定系数的行
	{
		for(j=0; j<biWidth; j++)//控制选定系数的列
		{
			CoeffAfterLoad[i][j] = m_WvltCoeff[i][j];//加载水印后的系数数组初值为小波变换后系数
			if(CoeffChoosed[i][j] != 0)//CoeffChoosed中不为0的个数刚好等于水印长度
			{
				//用水印信息修改选定系数
				TempCoeff[i][j] = CoeffChoosed[i][j] * (1.0 + strength*WaterMarkOrigin[k]);				
				 k++;//下一个水印信息
				 //用修改后的选定系数更新DWT变换后相应位置的系数
	             CoeffAfterLoad[i][j] = TempCoeff[i][j];
			}
			
		}

	}
    //删除临时空间
	for(i=0; i<biHeight; i++)//控制选定系数的行
	{
		delete []TempCoeff[i];
        TempCoeff[i] = NULL;
	}
	delete []TempCoeff;
	TempCoeff = NULL;
	/*
	//将被水印信息修改后的选定系数写到文件中
    strFilePath = FilePathBuf;
	strFilePath = strFilePath + "\\CoeffChoosedAfterLoad.txt";
	WriteFile(strFilePath,CoeffChoosed,biHeight,biWidth);
	//将水印加载前后的系数写入文件中	
	strFilePath = FilePathBuf;
	strFilePath = strFilePath + "\\CoeffAfterDWT.txt";
	WriteFile(strFilePath,m_WvltCoeff,biHeight,biWidth);
	strFilePath = FilePathBuf;
	strFilePath = strFilePath + "\\CoeffAfterLoad.txt";
	WriteFile(strFilePath,CoeffAfterLoad,biHeight,biWidth);
	*/

}

//对单个图像加载水印
void CWvltTrans::LoadWaterMarkOne(CString CurrentFile)
{ 
	    CString CoeffChoosedSavePath = "";
		int pos = CurrentFile.ReverseFind('\\');
		picName = CurrentFile.Mid(pos+1);//取到当前文件名
        CString Path = CurrentFile.Left(pos);//当前路径
	    SavePath =  Path +  "\\加水印后图像" + "\\" + picName;//保存加载水印后的图像路径
        int pos2 = picName.ReverseFind('.');	 
        CString picTitle = picName.Left(pos2);//不含扩展名的文件名
		CoeffChoosedSavePath = Path + "\\加水印后图像" + "\\选择的系数\\" + picTitle + ".txt";//待保存的选定系数文件路径
			
		if (!ReadBitmap(CurrentFile, m_pBitmap))
		{
			AfxMessageBox("读取原始文件" + CurrentFile + "错误!");
			exit(1);
		}
		
		//分配缓冲区
		pY = new float* [biHeight];
		pU = new float* [biHeight];
		pV = new float* [biHeight];
		
		for(int i = 0; i < biHeight; i ++)
		{
			pY[i] = new float [biWidth];
			pU[i] = new float [biWidth];
			pV[i] = new float [biWidth];
			
		}
		RGBToYUV(m_pBitmap,pY,pU, pV);//将原始图像数据分解成Y、U、V
		
		int x,y;	
		float **spTransData0, **spTransData1;
		
		//分配图像小波变换的数据内存空间		
		spTransData0 = new float* [biHeight];
		spTransData1 = new float* [biHeight];
		m_WvltCoeff	= new float * [biHeight];//存放小波变换后系数	
		
		for(i = 0; i < biHeight; i ++)
		{		
			spTransData0[i] = new float [biWidth];
			spTransData1[i] = new float [biWidth];
			m_WvltCoeff[i] = new float [biWidth];
			
		}
		
		//完成图像的三次小波变换
		DWT_nLayers(pY,spTransData0,spTransData1,biHeight,biHeight/2,biWidth,biWidth/2,3,(float)1.414);
		//得到小波系数
		for( y=0; y<biHeight; y++)
		{
			for( x=0; x<biWidth; x++)
			{				
				m_WvltCoeff[y][x] = spTransData1[y][x];//得到三次小波变换后的系数
			}
		}
		//为DWT各子带及选择的加载水印的系数、加载水印后的系数及小波逆变换后的系数分配缓冲区
		allocBuffers();
		ChooseCoeffByWholeThreshold();//选择要加载水印的系数,此函数中将小波变换后系数分成各子带
		//将当前图像的选定系数写到文件中以备检测水印时用		
		WriteFile(CoeffChoosedSavePath,CoeffChoosed,biHeight,biWidth);//此函数为何有错(已解决,目录必须存在)
		LoadWaterMark();//加载二值水印,加载过水印的小波系数保存在CoeffAfterLoad中
		//对加载过水印的系数进行小波逆变换
		DWT_Inverse(biHeight,biWidth,3,CoeffAfterLoad,CoeffIDWT);		
		
		unsigned char* RGBData = new BYTE [biHeight*biAlign];
		if(RGBData == NULL)
		{
			AfxMessageBox("分配存放合成Y、U、V后的RGB空间失败!");
			return;
		}
		YUVToRGB(CoeffIDWT,pU,pV,RGBData,biHeight,biWidth,biAlign);//恢复加载水印后图像为彩色图像
		FileSaveAs(SavePath,BFH,BIH,RGBData,bmSize);//将加载水印后的数据另存为bmp图像
		
		delete []RGBData;
		RGBData = NULL;			
		freeBuffers();//此函数中将选择的系数释放
		//释放空间
		for(i = 0; i < biHeight; i++)
		{
			delete []m_WvltCoeff[i];
			delete []spTransData0[i] ;
			delete []spTransData1[i] ;
			m_WvltCoeff[i] = NULL;
			spTransData0[i] = NULL;
			spTransData1[i] = NULL;
			
		}
		delete []m_WvltCoeff;
		delete []spTransData0;
		delete []spTransData1;		
		spTransData0 = NULL;
		spTransData1 = NULL;
		m_WvltCoeff = NULL;
       
		if( m_pBitmap != NULL)
		{
			delete []m_pBitmap;
			m_pBitmap = NULL;
		}		
		
		for(i=0; i<biHeight; i++)
		{			
			delete []pY[i];
			delete []pU[i];
			delete []pV[i];				
			pY[i] = NULL;
			pU[i] = NULL;
			pV[i] = NULL;
		}		
		delete []pY;
		delete []pU;
		delete []pV;		
		pY = NULL;
		pU = NULL;
		pV = NULL;	
	
	AfxMessageBox("所选图像加载水印完毕!");
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -