请教vc++高手讲解一下下面的图像处理程序

图像处理算法

.旋转图像(含对话框 这里对话框需要自己建立)
void CCimageProcessingView::OnGeomRota()
{
//获取指向文档的指针
CCimageProcessingDoc* pDoc = GetDocument();

//指向DIB的指针
LPSTR lpDIB;

//锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());

// 缩放比率
int iRotaAngle;

// 创建对话框
CDlgGeoRota dlgPara;

// 初始化变量值
dlgPara.m_iRotaAngle = 90;

// 显示对话框,提示用户设定旋转角度
if (dlgPara.DoModal() != IDOK)
{
// 返回
return;
}

// 获取用户设定的平移量
iRotaAngle = dlgPara.m_iRotaAngle;

// 删除对话框
delete dlgPara;
//创建新DIB
HDIB hNewDIB=NULL;

//设置光标状态为等待状态
BeginWaitCursor();

//调用RotateDIB函数旋转DIB图象
hNewDIB=(HDIB)::RotateDIB(lpDIB,iRotaAngle);

//旋转成功
if (hNewDIB)
{
//替换原来的DIB图象为新的DIB
pDoc->ReplaceHDIB(hNewDIB);

//更新DIB图象的大小和调色板
pDoc->InitDIBData();

//设置文档修改标记
pDoc->SetModifiedFlag(TRUE);

//调节滚动视图大小
SetScrollSizes(MM_TEXT,pDoc->GetDocSize());

//更新所有视图
pDoc->UpdateAllViews(NULL);
}
else
{
//提示信息
MessageBox("实现图象旋转失败!");
}

//解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

//结束光标等待状态
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
*
* RotateDIB ()
*
* 参数:
*
* LPSTR lpDIB //指向源DIB图像指针
*
* int iAngle
* 说明:
*
* 该函数用来实现DIB图像的旋转。
*
************************************************************************/
HGLOBAL WINAPI RotateDIB(LPSTR lpDIB,int iAngle)
{
//原图象宽度
LONG lWidth;

//原图象高度
LONG lHeight;

//旋转后图象宽度
LONG lNewWidth;

//旋转后图象高度
LONG lNewHeight;

//原图象的颜色数
WORD wNumColors;

//原图象的信息头结构指针
LPBITMAPINFOHEADER lpbmi,lpbmi0;

//指向原图象和目的图象的像素的指针
LPBYTE lpSrc,lpDst;

//指向原图像像素的指针
LPBYTE lpDIBBits;

//指向旋转后图像(像素)的指针
LPBYTE lpNewDIBBits;
LPSTR lpNewDIB;

//旋转后新的DIB句柄
HDIB hDIB;

//循环变量
LONG i,j,i0,j0;

//原图像每行的字节数
LONG lLineBytes;

//旋转后图像每行的字节数
LONG lNewLineBytes;

//旋转角度的弧度
double fArcAngle;

//旋转角度的正弦和余弦
float fSin,fCos;

//旋转前图象四个角的坐标(以图象中心为坐标系原点)
float fSrcX1,fSrcY1,fSrcX2,fSrcY2;
float fSrcX3,fSrcY3,fSrcX4,fSrcY4;

//旋转后图象四个角的坐标(以图象中心为坐标系原点)
float fDstX1,fDstY1,fDstX2,fDstY2;
float fDstX3,fDstY3,fDstX4,fDstY4;

//两个中间量
float f1,f2;

//找到图象的像素位置
lpDIBBits=(LPBYTE)::FindDIBBits(lpDIB);

//获取图象的宽度
lWidth=::DIBWidth(lpDIB);

//获取图象的高度
lHeight=::DIBHeight(lpDIB);

//获取图象的颜色数
wNumColors=::DIBNumColors(lpDIB);

//获取指向原位图信息头结构的指针
lpbmi0=(LPBITMAPINFOHEADER)lpDIB;

//计算原图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth *(lpbmi0->biBitCount));

//将旋转角度从度转换到弧度
fArcAngle =(iAngle*PI)/180.0;

//计算旋转角度的正弦
fSin = (float) sin(fArcAngle);

//计算旋转角度的余弦
fCos = (float) cos(fArcAngle);

//计算原图的四个角的坐标(以图像中心为坐标系原点)
fSrcX1 = (float) (- (lWidth - 1) / 2);
fSrcY1 = (float) ( (lHeight - 1) / 2);
fSrcX2 = (float) ( (lWidth - 1) / 2);
fSrcY2 = (float) ( (lHeight - 1) / 2);
fSrcX3 = (float) (- (lWidth - 1) / 2);
fSrcY3 = (float) (- (lHeight - 1) / 2);
fSrcX4 = (float) ( (lWidth - 1) / 2);
fSrcY4 = (float) (- (lHeight - 1) / 2);

//计算新图四个角的坐标(以图像中心为坐标系原点)
fDstX1 = fCos * fSrcX1 + fSin * fSrcY1;
fDstY1 = -fSin * fSrcX1 + fCos * fSrcY1;
fDstX2 = fCos * fSrcX2 + fSin * fSrcY2;
fDstY2 = -fSin * fSrcX2 + fCos * fSrcY2;
fDstX3 = fCos * fSrcX3 + fSin * fSrcY3;
fDstY3 = -fSin * fSrcX3 + fCos * fSrcY3;
fDstX4 = fCos * fSrcX4 + fSin * fSrcY4;
fDstY4 = -fSin * fSrcX4 + fCos * fSrcY4;

//计算旋转后的图像实际宽度
lNewWidth = (LONG) ( max( fabs(fDstX4 - fDstX1),
fabs(fDstX3 - fDstX2) ) + 0.5);

//计算旋转后的图像高度
lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1),
fabs(fDstY3 - fDstY2) ) + 0.5);

//计算旋转后图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * lpbmi0->biBitCount);

//计算两个常数
f1 = (float) (-0.5 * (lNewWidth - 1) * fCos - 0.5 * (lNewHeight - 1) * fSin
+ 0.5 * (lWidth - 1));
f2 = (float) ( 0.5 * (lNewWidth - 1) * fSin - 0.5 * (lNewHeight - 1) * fCos
+ 0.5 * (lHeight - 1));

//暂时分配内存,以保存新图像
hDIB=(HDIB)::GlobalAlloc(GHND, lNewHeight*lNewLineBytes+
*(LPDWORD)lpDIB+::PaletteSize(lpDIB));

//分配内存失败,直接返回
if (!hDIB)
return NULL;

//锁定内存
lpNewDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB);

//复制DIB信息头和调色板
memcpy(lpNewDIB,lpDIB,*(LPDWORD)lpDIB+::PaletteSize(lpDIB));

//获取图象的信息头结构的指针
lpbmi=(LPBITMAPINFOHEADER)lpNewDIB;

//更新DIB图象的高度和宽度
lpbmi->biWidth=lNewWidth;
lpbmi->biHeight=lNewHeight;

//找到新DIB像素的起始位置
lpNewDIBBits=(LPBYTE)::FindDIBBits(lpNewDIB);

//如果是256色位图
if(wNumColors==256)
{
//旋转后图像每行
for(i = 0; i<lNewHeight; i++)
{
//旋转后图象每列
for(j=0;j<lNewWidth;j++)
{
//指向图象第i行第j个像素的指针
lpDst =(LPBYTE)lpNewDIBBits + lNewLineBytes * (lNewHeight-1-i)+j;

//计算每个像素点在原图象中的坐标
i0 = (LONG) (-((float) j) * fSin + ((float) i) * fCos + f2 + 0.5);
j0 = (LONG) ( ((float) j) * fCos + ((float) i) * fSin + f1 + 0.5);

// 判断是否在源图象范围之内
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB图象第i0行,第j0个象素的指针
lpSrc = (LPBYTE)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;

// 复制象素
*lpDst = *lpSrc;
}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((LPBYTE)lpDst) = 255;
}
}
}
}

//如果是24位真彩色位图
else if(wNumColors==0)
{
//旋转后图像每行
for(i = 0; i<lNewHeight; i++)
{
//旋转后图象每列
for(j=0;j<lNewWidth;j++)
{
//指向图象第i行第j个像素的指针
lpDst =(LPBYTE)lpNewDIBBits + lNewLineBytes * (lNewHeight-1-i)+3*j;

//计算每个像素点在原图象中的坐标
i0 = (LONG) (-((float) j) * fSin + ((float) i) * fCos + f2 + 0.5);
j0 = (LONG) ( ((float) j) * fCos + ((float) i) * fSin + f1 + 0.5);

// 判断是否在源图象范围之内
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB图象第i0行,第j0个象素的指针
lpSrc = (LPBYTE)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + 3*j0;

// 复制象素
memcpy(lpDst,lpSrc,3);
}
else
{
// 对于源图中没有的象素,直接赋值为255
memset(lpDst,255,3);
}
}
}
}

else
{
AfxMessageBox("只支持256色和真彩色位图");

// 释放内存
GlobalUnlock(hDIB);
GlobalFree(hDIB);
return NULL;
}

// 返回
return hDIB;
}

参考资料:http://blog.vbgood.com/index.php/1834/action_viewspace_itemid_174.html

温馨提示:答案为网友推荐,仅供参考
相似回答