📄 geometrytrans.cpp
字号:
* interpolationDblLinear()
*
* 参数:
* array,2*2数组,存放图像待插值位置周围四个像素灰度值
* xpos,ypos为相对于数组四个像素的插值位置坐标,取小数
*
* 返回值:
* 插值结果。
*
* 说明:
* 该函数将原图像待插值位置的四个像素数据拷贝到数组array中,根据插值位置坐标对
* 应到array的位置,对数组array的四个元素进行双线性插值,返回值为插值的结果。
************************************************************************/
unsigned char GeometryTrans::interpolationDblLinear(unsigned char array[2][2],
float xpos, float ypos)
{
//两个中间变量
int t1, t2;
//先垂直方向线性插值
t1 = (1-ypos)*array[0][0] + ypos*array[1][0];
t2 = (1-ypos)*array[0][1] + ypos*array[1][1];
//再水平方向线性插值
float t=(int)((1-xpos)*t1 + xpos*t2);
//若插值结果小于0,则输出0
if(t<0)
t=0;
//若插值结果大于255,则输出255
if(t>255)
t=255;
//插值结果返回
return (unsigned char)t;
}
/*************************************************************************
*
* 函数名称:
* interpolationCube()
*
* 参数:
* array,4x4数组,存放图像待插值位置周围16个像素灰度值
* xpos,ypos对应于4x4数组16个元素的插值坐标
*
* 返回值:
* 插值结果。
*
* 说明:
* 该函数将原图像待插值位置周围16个像素数据拷贝到数组array中,根据插值位置坐标对
* 应到array的位置,对数组array的16个元素进行立方卷积插值,返回值为插值的结果。
*
************************************************************************/
unsigned char GeometryTrans::interpolationCube(unsigned char array[4][4], float xpos, float ypos)
{
//申请数组,计算插值所需要的系数
float col[4], row[4];
//准备插值的x方向数据源
col[0]=xpos+1;
col[1]=xpos;
col[2]=1-xpos;
col[3]=2-xpos;
//准备插值的y方向数据源
row[0]=ypos+1;
row[1]=ypos;
row[2]=1-ypos;
row[3]=2-ypos;
//循环变量
int i;
//临时变量
float t;
//对水平方向系数数组进行计算
for(i=0;i<4;i++){
t=fabs(col[i]);
if (t>=0&&t<1)
col[i]=pow(t,3)-2*pow(t,2)+1;
else if (t>=1&&t<2)
col[i]=-pow(t,3)+5*pow(t,2)-8*t+4;
else
col[i]=0;
}
//对垂直方向系数数组进行计算
for(i=0;i<4;i++){
t=fabs(row[i]);
if (t>=0&&t<1)
row[i]=pow(t,3)-2*pow(t,2)+1;
else if (t>=1&&t<2)
row[i]=-pow(t,3)+5*pow(t,2)-8*t+4;
else
row[i]=0;
}
//将计算好的系数与对应图像数据数组作卷积
float tempArray[4], temp;
//先x方向卷积
for(i=0;i<4;i++)
tempArray[i]=row[0]*array[0][i]+row[1]*array[1][i]+row[2]*array[2][i]+row[3]*array[3][i];
//再y方向卷积
temp=0;
for (i=0;i<4;i++)
temp+=tempArray[i]*col[i];
//将插值结果在图像灰度级范围内输出
if (temp>255)
temp=255;
if (temp<0)
temp=0;
//函数返回值,插值结果
return (unsigned char)temp;
}
/*************************************************************************
*
* 函数名称:
* Zoom()
*
* 参数:
* int zoomWidthPixel -输出图像的宽,像素为单位
* int zoomHeightPixel -输出图像的高,像素为单位
* int interpolationflag -插值方式,0为近邻插值,1为双线性插值,2为立方卷积插值
*
* 返回值:
* 无
*
* 说明:
* 根据指定的大小和指定的插值方式,对原图像进行缩放,缩放后的结果存放
* 在m_pImgDataOut缓冲区中,该函数同时适合于彩色和灰度图像
*
************************************************************************/
void GeometryTrans::Zoom(int zoomWidthPixel, int zoomHeightPixel, int interpolationflag)
{
//释放旧的输出图像缓冲区
if(m_pImgDataOut!=NULL){
delete []m_pImgDataOut;
m_pImgDataOut=NULL;
}
//输出图像的宽和高
m_imgWidthOut=zoomWidthPixel;
m_imgHeightOut=zoomHeightPixel;
//输出图像每行像素字节数
int lineByteOut=(m_imgWidthOut*m_nBitCountOut/8+3)/4*4;
//申请缓冲区,存放输出结果
m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];
//近邻插值缩放
if(interpolationflag==0)
ZoomNeighbor(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
//双线性插值缩放
else if(interpolationflag==1)
ZoomDblLinear(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
//立方卷积插值
else
ZoomCube(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
}
/*************************************************************************
*
* 函数名称:
* ZoomNeighbor()
*
* 参数:
* unsigned char *pImgIn -输入图像缓冲区指针
* int widthIn -输入图像的宽
* int heightIn -输入图像的高
* int biBitCount -图像每像素位数,输入图像与输出图像相同
* unsigned char *pImgOut -输出图像缓冲区指针,该存储区已经存在
* int widthOut -输出图像的宽
* int heightOut -输出图像的高
* 返回值:
* 无
*
* 说明:
* 将pImgIn所指向的数据由widthIn*heightIn最近邻缩放至widthOut*heightOut的大小,
* 结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
*
************************************************************************/
void GeometryTrans::ZoomNeighbor(unsigned char *pImgIn, int widthIn, int heightIn,
int biBitCount, unsigned char *pImgOut, int widthOut, int heightOut)
{
//水平方向缩放比例
float ratioX=(float)widthOut/widthIn;
//垂直方向缩放比例
float ratioY=(float)heightOut/heightIn;
//每像素字节数,输入图像与输出图像相同
int pixelByte=biBitCount/8;
//输出图像在输入图像中待插值的位置坐标
int coordinateX, coordinateY;
//输入图像每行像素字节数
int lineByteIn=(widthIn*pixelByte+3)/4*4;
//输出图像每行像素字节数
int lineByteOut=(widthOut*pixelByte+3)/4*4;
//循环变量,输出图像的坐标
int i, j;
//循环变量,像素的每个通道
int k;
//近邻插值
for(i=0; i< heightOut; i++){
for(j=0; j< widthOut ; j++){
//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
coordinateX=j/ratioX+0.5;
coordinateY=i/ratioY+0.5;
//若插值位置在输入图像范围内,则近邻插值
if(0<=coordinateX&&coordinateX<widthIn
&& coordinateY>=0&&coordinateY<heightIn){
for(k=0;k<pixelByte;k++)
*(pImgOut + i * lineByteOut + j*pixelByte + k)
=*(pImgIn+ coordinateY*lineByteIn+ coordinateX*pixelByte + k) ;
}
else //若不在输入图像范围内,则置255
{
for(k=0;k<pixelByte;k++)
*(pImgOut + i * lineByteOut + j*pixelByte+k) = 255;
}
}
}
}
/*************************************************************************
*
* 函数名称:
* ZoomDblLinear()
*
* 参数:
* unsigned char *pImgIn -输入图像缓冲区指针
* int widthIn -输入图像的宽
* int heightIn -输入图像的高
* int biBitCount -图像每像素位数,输入图像与输出图像相同
* unsigned char *pImgOut -输出图像缓冲区指针,该存储区已经存在
* int widthOut -输出图像的宽
* int heightOut -输出图像的高
* 返回值:
* 无
*
* 说明:
* 将pImgIn所指向的数据由widthIn*heightIn双线性缩放至widthOut*heightOut的大小,
* 结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
*
************************************************************************/
void GeometryTrans::ZoomDblLinear(unsigned char *pImgIn, int widthIn, int heightIn,
int biBitCount,unsigned char *pImgOut, int widthOut, int heightOut)
{
//水平方向缩放比例
float ratioX=(float)widthOut/widthIn;
//垂直方向缩放比例
float ratioY=(float)heightOut/heightIn;
//每像素字节数,输入图像与输出图像相同
int pixelByte=biBitCount/8;
//输出图像在输入图像中待插值的位置坐标,必须浮点型
float coordinateX, coordinateY;
//输入图像每行像素字节数
int lineByteIn=(widthIn*pixelByte+3)/4*4;
//输出图像每行像素字节数
int lineByteOut=(widthOut*pixelByte+3)/4*4;
//循环变量,输出图像的坐标
int i, j;
//循环变量,像素的每个通道
int k;
//临时变量,待插值位置向下取整的坐标
int Iu, Iv;
//数组,存放插值位置周围的4个像素
unsigned char array[2][2];
//双线性插值
for(i=0; i< heightOut; i++){
for(j=0; j< widthOut ; j++){
//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
coordinateX=j/ratioX;
coordinateY=i/ratioY;
//对插值位置坐标取整
Iu=(int)coordinateX;
Iv=(int)coordinateY;
//若插值位置在输入图像范围内,则双线性插值
if(0<=coordinateX&&coordinateX<widthIn
&& coordinateY>=0&&coordinateY<heightIn){
//将图像每个像素通道的数据进行分别插值,
//彩图pixelByte为3,灰度图像pixelByte为1
for(k=0;k<pixelByte;k++){
//将第k个通道的四个像素数据拷贝至array数组中
array[0][0]=*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
array[0][1]=*(pImgIn+ Iv*lineByteIn+ (Iu+1)*pixelByte+k);
array[1][0]=*(pImgIn+ (Iv+1)*lineByteIn+ Iu*pixelByte+k);
array[1][1]=*(pImgIn+ (Iv+1)*lineByteIn+ (Iu+1)*pixelByte+k);
//调用双线性插值函数插值并输出到pImgOut中
*(pImgOut + i * lineByteOut + j*pixelByte+k)
=interpolationDblLinear(array, coordinateX-Iu, coordinateY-Iv);
}
}
else{//边缘像素采用近邻插值
for(k=0;k<pixelByte;k++)
*(pImgOut + i * lineByteOut + j*pixelByte + k) =
*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
}
}
}
}
/*************************************************************************
*
* 函数名称:
* ZoomCube()
*
* 参数:
* unsigned char *pImgIn -输入图像缓冲区指针
* int widthIn -输入图像的宽
* int heightIn -输入图像的高
* int biBitCount -图像每像素位数,输入图像与输出图像相同
* unsigned char *pImgOut -输出图像缓冲区指针,该存储区已经存在
* int widthOut -输出图像的宽
* int heightOut -输出图像的高
* 返回值:
* 无
*
* 说明:
* 将pImgIn所指向的数据由widthIn*heightIn立方卷积缩放至widthOut*heightOut的大小,
* 结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
*
************************************************************************/
void GeometryTrans::ZoomCube(unsigned char *pImgIn, int widthIn, int heightIn,
int biBitCount, unsigned char *pImgOut, int widthOut, int heightOut)
{
//水平方向缩放比例
float ratioX=(float)widthOut/widthIn;
//垂直方向缩放比例
float ratioY=(float)heightOut/heightIn;
//每像素字节数,输入图像与输出图像相同
int pixelByte=biBitCount/8;
//输出图像在输入图像中待插值的位置坐标,必须浮点型
float coordinateX, coordinateY;
//输入图像每行像素字节数
int lineByteIn=(widthIn*pixelByte+3)/4*4;
//输出图像每行像素字节数
int lineByteOut=(widthOut*pixelByte+3)/4*4;
//循环变量,输出图像的坐标
int i, j;
//循环变量,像素的每个通道
int k;
//临时变量,待插值位置向下取整的坐标
int Iu, Iv;
//数组,存放插值位置周围16个像素
unsigned char array[4][4];
//循环变量,遍历待插值位置4x4的图像数据
int x, y;
//立方卷积插值
for(i=0; i< heightOut; i++){
for(j=0; j< widthOut ; j++){
//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
coordinateX=j/ratioX;
coordinateY=i/ratioY;
//对插值位置坐标取整
Iu=(int)coordinateX;
Iv=(int)coordinateY;
//若插值位置在输入图像范围内,则立方卷积插值
if(1<=coordinateX&&coordinateX<widthIn-2
&& coordinateY>=1&&coordinateY<heightIn-2){
//将图像每个像素通道的数据进行分别插值,
//彩图pixelByte为3,灰度图像pixelByte为1
for(k=0;k<pixelByte;k++){
//将第k个通道的4x4个像素数据拷贝至array数组中
for(y=Iv-1;y<Iv+3;y++)
{
for (x=Iu-1;x<Iu+3;x++)
{
array[y-Iv+1][x-Iu+1]=
*(pImgIn+y*lineByteIn+x*pixelByte+k);
}
}
//调用立方卷积插值函数插值并输出到pImgOut中
*(pImgOut + i * lineByteOut + j*pixelByte+k)
=interpolationCube(array, coordinateX-Iu, coordinateY-Iv);
}
}
else{//边缘像素采用近邻插值
for(k=0;k<pixelByte;k++)
*(pImgOut + i * lineByteOut + j*pixelByte + k) =
*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -