📄 geometrytrans.cpp
字号:
}
}
/*************************************************************************
*
* 函数名称:
* 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 + -