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

📄 geometrytrans.cpp

📁 将数字图像处理的一般算法都集中在一个MFC的框架中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}


}

/*************************************************************************
 *
 * 函数名称:
 *   Rotate()
 *
 * 参数:
 *   int angle  -旋转角度
 *   int interpolationflag -插值方式,0为近邻,1为双线性,2为立方卷积

 * 返回值:
 *   无
 *
 * 说明:
 *   根据指定旋转角度和插值方式,调用相应的插值旋转函数对原图像进行旋转,
 *   旋转结果输出至m_pImgDataOut缓冲区中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::Rotate(int angle, int interpolationflag)
{
	if(interpolationflag==0)//近邻插值缩放
		RotateNeighbor(angle);

	else if(interpolationflag==1)//双线性插值缩放
		RotateDblLinear(angle);

	else//立方卷积插值缩放
	    RotateCube(angle);
}


/*************************************************************************
 *
 * 函数名称:
 *   RotateNeighbor(),近邻插值旋转
 *
 * 参数:
 *   int angle	- 旋转的角度(0-360度)
 *
 * 返回值:
 *   无。
 *
 * 说明:
 *    采用最近邻插值方式,以输入图像中心为原点,将图像旋转angle,旋转结果
 *    存放在m_pImgDataOut中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::RotateNeighbor(int angle)
{
	//释放旧的输出图像缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}

	//每像素所占字节数,输入图像与输出图像相同
	int pixelByte=m_nBitCount/8;

	// 输入图像每行像素所占字节数
	int lineByte=(m_imgWidth*pixelByte+3)/4*4;

	// 旋转角度(弧度), 将旋转角度从度转换到弧度
	float	fRotateAngle= 2*3.1415926*angle/360;
	
	// 输入图像四个角的坐标,以图像中心为坐标系原点
	float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
	
	// 旋转后四个角的坐标,以图像中心为坐标系原点
	float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
	
	// 计算旋转角度的正弦
	float fSina = (float) sin((double)fRotateAngle);
	
	// 计算旋转角度的余弦
	float fCosa = (float) cos((double)fRotateAngle);
	
	// 计算原图的四个角的坐标,以图像中心为坐标系原点
	fSrcX1 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY1 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX2 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY2 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX3 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY3 = (float) (- (m_imgHeight - 1) / 2);
	fSrcX4 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY4 = (float) (- (m_imgHeight - 1) / 2);
	
	// 计算新图四个角的坐标,以图像中心为坐标系原点
	fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
	fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
	fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
	fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
	fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
	fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
	fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
	fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
	
	// 旋转后输出图像宽度
	m_imgWidthOut  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
	
	// 旋转后输出图像高度
	m_imgHeightOut = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);

	// 旋转后输出图像每行的字节数
	int lineByteOut=(m_imgWidthOut*pixelByte+3)/4*4;
	
	//分配缓冲区,存放旋转结果
	m_pImgDataOut = new unsigned char[lineByteOut*m_imgHeightOut];

	// 两个常数,这样不用以后每次都计算了
	float f1 = (float) (-0.5 * (m_imgWidthOut - 1) * fCosa 
		                + 0.5 * (m_imgHeightOut - 1) * fSina + 0.5 * (m_imgWidth  - 1));
	float f2 = (float) (-0.5 * (m_imgWidthOut - 1) * fSina 
		                - 0.5 * (m_imgHeightOut - 1) * fCosa + 0.5 * (m_imgHeight - 1));

	// 循环变量,输出图像坐标
	int	i, j;

	//循环变量,像素的每个通道
	int k;
	
	//输出图像在输入图像中待插值的位置坐标,必须浮点型
	int	coordinateX, coordinateY;

	// 最近邻插值旋转
	for(i = 0; i < m_imgHeightOut; i++)
	{
		for(j = 0; j < m_imgWidthOut; j++)
		{
			
			// 输出图像像素(j,i)映射到输入图像的坐标,近邻插值取整数
			coordinateX = (int)(j * fCosa - i * fSina + f1 + 0.5);
			coordinateY = (int)(j * fSina + i * fCosa + f2 + 0.5);
			
			// 判断是否在输入图像范围内
			if( (coordinateX >= 0) && (coordinateX < m_imgWidth) && (coordinateY >= 0) 
				&& (coordinateY < m_imgHeight))
			{
				//将图像每个通道的数据进行分别插值,彩色图像pixelByte为3,
				//灰度图像pixelByte为1
				for(k=0; k<pixelByte; k++)
					*(m_pImgDataOut+i*lineByteOut+j*pixelByte+k)
					=*(m_pImgData+coordinateY*lineByte+coordinateX*pixelByte+k);
			}
			else
			{
				// 对于不在原图中的像素,赋值为255
				for(k=0; k<pixelByte; k++)
		    		*(m_pImgDataOut+i*lineByteOut+j*pixelByte+k) = 255;
			}
			
		}
		
	}
	
}

/*************************************************************************
 *
 * 函数名称:
 *   RotateDblLinear()
 *
 * 参数:
 *   int angle	- 旋转的角度(0-360度)
 *
 * 返回值:
 *   无。
 *
 * 说明:
 *    采用双线性插值方式,以输入图像中心为原点,将图像旋转angle,旋转结果
 *    存放在m_pImgDataOut中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::RotateDblLinear(int angle)
{
	//释放旧的输出图像缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}

	//每像素所占字节数,输入图像与输出图像相同
	int pixelByte=m_nBitCount/8;

	// 输入图像每行像素所占字节数
	int lineByte=(m_imgWidth*pixelByte+3)/4*4;

	// 旋转角度(弧度), 将旋转角度从度转换到弧度
	float	fRotateAngle= 2*3.1415926*angle/360;
	
	// 输入图像四个角的坐标,以图像中心为坐标系原点
	float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
	
	// 旋转后四个角的坐标,以图像中心为坐标系原点
	float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
	
	// 计算旋转角度的正弦
	float fSina = (float) sin((double)fRotateAngle);
	
	// 计算旋转角度的余弦
	float fCosa = (float) cos((double)fRotateAngle);
	
	// 计算原图的四个角的坐标,以图像中心为坐标系原点
	fSrcX1 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY1 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX2 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY2 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX3 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY3 = (float) (- (m_imgHeight - 1) / 2);
	fSrcX4 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY4 = (float) (- (m_imgHeight - 1) / 2);
	
	// 计算新图四个角的坐标,以图像中心为坐标系原点
	fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
	fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
	fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
	fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
	fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
	fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
	fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
	fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
	
	// 旋转后输出图像宽度
	m_imgWidthOut  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
	
	// 旋转后输出图像高度
	m_imgHeightOut = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);

	// 旋转后输出图像每行的字节数
	int lineByteOut=(m_imgWidthOut*pixelByte+3)/4*4;
	
	//分配缓冲区,存放旋转结果
	m_pImgDataOut = new unsigned char[lineByteOut*m_imgHeightOut];

	// 两个常数,这样不用以后每次都计算了
	float f1 = (float) (-0.5 * (m_imgWidthOut - 1) * fCosa 
		                + 0.5 * (m_imgHeightOut - 1) * fSina + 0.5 * (m_imgWidth  - 1));
	float f2 = (float) (-0.5 * (m_imgWidthOut - 1) * fSina 
		                - 0.5 * (m_imgHeightOut - 1) * fCosa + 0.5 * (m_imgHeight - 1));

	// 循环变量,输出图像坐标
	int	i, j;

	//循环变量,像素的每个通道
	int k;
	
	//输出图像在输入图像中待插值的位置坐标,必须浮点型
	int	coordinateX, coordinateY;

	//存放待插值的4个像素的数组
	unsigned char array[2][2];

	//两个中间变量
	int Iu, Iv;

	//双线性插值旋转
	for(i = 0; i < m_imgHeightOut; i++)
	{
		for(j = 0; j < m_imgWidthOut; j++)
		{		
			// 输出图像像素(j,i)映射到输入图像的坐标
			coordinateX = j * fCosa - i * fSina + f1;
			coordinateY = j * fSina + i * fCosa + f2;

			//对坐标取整
			Iu=(int)coordinateX;
			Iv=(int)coordinateY;

			// 判断是否在原图范围内
			if( (coordinateX >= 0) && (coordinateX < m_imgWidth-1) && (coordinateY >= 0) 
				&& (coordinateY < m_imgHeight-1))
			{
				//将图像每个通道的数据进行分别插值,彩色图像pixelByte为3,
				//灰度图像pixelByte为1
				for(k=0;k<pixelByte;k++){
					//将当前处理像素周围2*2邻域像素拷贝至数组array
					array[0][0]=*(m_pImgData+ Iv*lineByte+ Iu*pixelByte+k);
					array[0][1]=*(m_pImgData+ Iv*lineByte+ (Iu+1)*pixelByte+k);
					array[1][0]=*(m_pImgData+ (Iv+1)*lineByte+ Iu*pixelByte+k);
					array[1][1]=*(m_pImgData+ (Iv+1)*lineByte+ (Iu+1)*pixelByte+k);
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte+k)
						=interpolationDblLinear(array, coordinateX-Iu, coordinateY-Iv);
				}
			}
			else
			{
				// 对于不在原图范围内的像象素,赋值为255
				for(k=0;k<pixelByte;k++)
	     			*(m_pImgDataOut+i*lineByteOut+j*pixelByte+k) = 255;
			}
			
		}
		
	}
	
}


/*************************************************************************
 *
 * 函数名称:
 *   RotateCube()
 *
 * 参数:
 *   int angle	- 旋转的角度(0-360度)
 *
 * 返回值:
 *   无
 *
 * 说明:
 *    采用立方卷积插值方式,以输入图像中心为原点,将图像旋转angle,旋转结果
 *    存放在m_pImgDataOut中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::RotateCube(int angle)
{
	//释放旧的输出图像缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}

	//每像素所占字节数,输入图像与输出图像相同
	int pixelByte=m_nBitCount/8;

	// 输入图像每行像素所占字节数
	int lineByte=(m_imgWidth*pixelByte+3)/4*4;

	// 旋转角度(弧度), 将旋转角度从度转换到弧度
	float	fRotateAngle= 2*3.1415926*angle/360;
	
	// 输入图像四个角的坐标,以图像中心为坐标系原点
	float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
	
	// 旋转后四个角的坐标,以图像中心为坐标系原点
	float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
	
	// 计算旋转角度的正弦
	float fSina = (float) sin((double)fRotateAngle);
	
	// 计算旋转角度的余弦
	float fCosa = (float) cos((double)fRotateAngle);
	
	// 计算原图的四个角的坐标,以图像中心为坐标系原点
	fSrcX1 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY1 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX2 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY2 = (float) (  (m_imgHeight - 1) / 2);
	fSrcX3 = (float) (- (m_imgWidth  - 1) / 2);
	fSrcY3 = (float) (- (m_imgHeight - 1) / 2);
	fSrcX4 = (float) (  (m_imgWidth  - 1) / 2);
	fSrcY4 = (float) (- (m_imgHeight - 1) / 2);
	
	// 计算新图四个角的坐标,以图像中心为坐标系原点
	fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
	fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
	fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
	fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
	fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
	fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
	fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
	fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
	
	// 旋转后输出图像宽度
	m_imgWidthOut  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
	
	// 旋转后输出图像高度
	m_imgHeightOut = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);

	// 旋转后输出图像每行的字节数
	int lineByteOut=(m_imgWidthOut*pixelByte+3)/4*4;
	
	//分配缓冲区,存放旋转结果
	m_pImgDataOut = new unsigned char[lineByteOut*m_imgHeightOut];

	// 两个常数,这样不用以后每次都计算了
	float f1 = (float) (-0.5 * (m_imgWidthOut - 1) * fCosa 
		                + 0.5 * (m_imgHeightOut - 1) * fSina + 0.5 * (m_imgWidth  - 1));
	float f2 = (float) (-0.5 * (m_imgWidthOut - 1) * fSina 
		                - 0.5 * (m_imgHeightOut - 1) * fCosa + 0.5 * (m_imgHeight - 1));

	// 循环变量,输出图像坐标
	int	i, j;

	//循环变量,像素的每个通道
	int k;
	
	//输出图像在输入图像中待插值的位置坐标,必须浮点型
	int	coordinateX, coordinateY;

	//存放待插值的16个像素的数组
	unsigned char array[4][4];

	//两个中间变量
	int Iu, Iv;

	//循环变量,对确定要插值的位置取4x4邻域用
	int x, y;

	// 立方卷积插值
	for(i = 0; i < m_imgHeightOut; i++)
	{
		for(j = 0; j < m_imgWidthOut; j++)
		{		
			// 输出图像像素(j,i)映射到输入图像的坐标
			coordinateX = j * fCosa - i * fSina + f1;
			coordinateY = j * fSina + i * fCosa + f2;

			//对坐标取整
			Iu=(int)coordinateX;
			Iv=(int)coordinateY;

			// 判断是否在原图范围内
			if( (coordinateX >= 1) && (coordinateX < m_imgWidth-3) && (coordinateY >= 1) 
				&& (coordinateY < m_imgHeight-3))
			{
				//将图像每个通道的数据进行分别插值,彩色图像pixelByte为3,
				//灰度图像pixelByte为1
				for(k=0;k<pixelByte;k++){
					//将当前处理像素周围4*4邻域像素拷贝至数组array
					for(y=Iv-1;y<Iv+3;y++){
						for (x=Iu-1;x<Iu+3;x++){
							array[y-Iv+1][x-Iu+1]=*(m_pImgData+y*lineByte+x*pixelByte+k);
						}
					}
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte+k)
						=interpolationCube(array, coordinateX-Iu, coordinateY-Iv);
				}
			}
			else
			{
				// 对于不在原图内的像素,赋值为255
				for(k=0;k<pixelByte;k++)
    	 			*(m_pImgDataOut+i*lineByteOut+j*pixelByte+k) = 255;
			}
			
		}
		
	}
	
}

⌨️ 快捷键说明

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