8种常用图像处理算法

1.图像镜像
void CCimageProcessingView::OnGeomTrpo() 
{
 //获取指向文档的指针
 CCimageProcessingDoc* pDoc = GetDocument();
 
 //指向DIB的指针
 LPSTR lpDIB;
 
 //锁定DIB
 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
 
 //设置光标状态为等待状态
 BeginWaitCursor();
 
 //调用VertMirror函数镜像图象
 if (VertMirror(lpDIB))
 { 
 //设置文档修改标记
 pDoc->SetModifiedFlag(TRUE);

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

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

 //结束光标等待状态
 EndWaitCursor(); 
}
/*************************************************************************
*
* 函数名称:
*
* VertMirror()
*
* 参数:
*
* LPSTR lpDIB //指向源DIB图像指针

* 返回值:
*
* BOOL //镜像成功返回TRUE,否则返回FALSE。
*
* 说明:
*
* 该函数用来实现DIB图像的垂直镜像。
*
************************************************************************/

BOOL WINAPI VertMirror(LPSTR lpDIB)
{
 //原图象宽度
 LONG lWidth;

 //原图象高度
 LONG lHeight;

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

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

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

 //平移后剩余图像在源图像中的位置(矩形区域)
 CRect rectSrc;
 
 //指向原图像像素的指针
 LPBYTE lpDIBBits;

 //指向复制图像像素的指针
 LPBYTE lpNewDIBBits;
 
 //内存句柄
 HLOCAL h;
 
 //循环变量
 LONG i;
 
 //图像每行的字节数
 LONG lLineBytes;

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

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

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

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

 //获取图象的颜色数
 wNumColors=::DIBNumColors(lpDIB);
 
 //计算图像每行的字节数
 lLineBytes = WIDTHBYTES(lWidth *(lpbmi->biBitCount));
 
 // 暂时分配内存,以保存新图像
 h= LocalAlloc(LHND, lLineBytes);
 
 // 分配内存失败,直接返回
 if (!h) 
 return FALSE;
 
 // 锁定内存
 lpNewDIBBits = (LPBYTE)LocalLock(h);
 
 //如果是256色位图或真彩色位图
 if(wNumColors==256||wNumColors==0)
 {
 //平移图像,每次移动一行
 for(i = 0; i  {
 //指向原图象倒数第i行像素起点的指针 
 lpSrc =(LPBYTE)lpDIBBits + lLineBytes * i;
 
 //目标区域同样要注意上下倒置的问题
 lpDst =(LPBYTE)lpDIBBits+lLineBytes * (lHeight-i-1) ;
 
 //备份一行
 memcpy(lpNewDIBBits, lpDst, lLineBytes);

 //将倒数第i行像素复制到第i行
 memcpy(lpDst, lpSrc, lLineBytes);
 
 //将第i行像素复制到第i行
 memcpy(lpSrc, lpNewDIBBits, lLineBytes);
 }
 }

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

 // 释放内存
 LocalUnlock(h);
 LocalFree(h);
 return false;
 }

 // 释放内存
 LocalUnlock(h);
 LocalFree(h);
 
 // 返回
 return TRUE;
}

2.旋转图像(含对话框 这里对话框需要自己建立)
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  {
 //旋转后图象每列
 for(j=0;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  {
 //旋转后图象每列
 for(j=0;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;
}

3.图像缩放(对话框自己建立)
void CCimageProcessingView::OnGeomZoom() 
{
 // TODO: Add your command handler code here
 // 图像缩放

 // 获取文档
 CCimageProcessingDoc* pDoc = GetDocument();
 
 // 指向DIB的指针
 LPSTR lpDIB;
 
 // 锁定DIB
 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
 

 
 // 缩放比率
 float fXZoomRatio;
 float fYZoomRatio;
 
 // 创建对话框
 CDlgGeoZoom dlgPara;
 
 // 初始化变量值
 dlgPara.m_XZoom = 0.5;
 dlgPara.m_YZoom = 0.5;
 
 // 显示对话框,提示用户设定平移量
 if (dlgPara.DoModal() != IDOK)
 {
 // 返回
 return;
 }
 
 // 获取用户设定的平移量
 fXZoomRatio = dlgPara.m_XZoom;
 fYZoomRatio = dlgPara.m_YZoom;
 
 // 删除对话框
 delete dlgPara; 
 
 // 创建新DIB
 HDIB hNewDIB = NULL;
 
 // 更改光标形状
 BeginWaitCursor();
 
 // 调用ZoomDIB()函数转置DIB
 hNewDIB = (HDIB) ZoomDIB(lpDIB, fXZoomRatio, fYZoomRatio);
 
 // 判断缩放是否成功
 if (hNewDIB != NULL)
 {
 
 // 替换DIB,同时释放旧DIB对象
 pDoc->ReplaceHDIB(hNewDIB);

 // 更新DIB大小和调色板
 pDoc->InitDIBData();
 
 // 设置脏标记
 pDoc->SetModifiedFlag(TRUE);
 
 // 重新设置滚动视图大小
 SetScrollSizes(MM_TEXT, pDoc->GetDocSize());

 // 更新视图
 pDoc->UpdateAllViews(NULL);
 }
 else
 {
 // 提示用户
 MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
 }
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

 // 恢复光标
 EndWaitCursor(); 
}
/*************************************************************************
*
* 函数名称:
* ZoomDIB()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* float fXZoomRatio - X轴方向缩放比率
* float fYZoomRatio - Y轴方向缩放比率
*
* 返回值:
* HGLOBAL - 缩放成功返回新DIB句柄,否则返回NULL。
*
* 说明:
* 该函数用来缩放DIB图像,返回新生成DIB的句柄。
*
************************************************************************/

HGLOBAL WINAPI ZoomDIB(LPSTR lpDIB, float fXZoomRatio, float fYZoomRatio)
{
 
 // 源图像的宽度和高度
 LONG lWidth;
 LONG lHeight;
 
 // 缩放后图像的宽度和高度
 LONG lNewWidth;
 LONG lNewHeight;
 WORD wNumColors;
 
 // 缩放后图像的宽度(lNewWidth',必须是4的倍数)
 LONG lNewLineBytes;
 
 // 指向源图像的指针
 LPBYTE lpDIBBits;
 
 // 指向源象素的指针
 LPBYTE lpSrc;
 
 // 缩放后新DIB句柄
 HDIB hDIB;
 
 // 指向缩放图像对应象素的指针
 LPBYTE lpDst;
 
 // 指向缩放图像的指针
 LPSTR lpNewDIB;
 LPBYTE lpNewDIBBits;
 
 // 指向BITMAPINFO结构的指针(Win3.0)
 LPBITMAPINFOHEADER lpbmi,lpbmi0;
 
 // 指向BITMAPCOREINFO结构的指针
 LPBITMAPCOREHEADER lpbmc;
 
 // 循环变量(象素在新DIB中的坐标)
 LONG i;
 LONG j;
 
 // 象素在源DIB中的坐标
 LONG i0;
 LONG j0;
 
 // 图像每行的字节数
 LONG lLineBytes;
 
 // 找到源DIB图像象素起始位置
 lpDIBBits = (LPBYTE)::FindDIBBits(lpDIB);
 
 // 获取图像的宽度
 lWidth = ::DIBWidth(lpDIB);
 
 // 获取图像的高度
 lHeight = ::DIBHeight(lpDIB);
 wNumColors= ::DIBNumColors(lpDIB);
 lpbmi0=(LPBITMAPINFOHEADER)lpDIB;
 
 // 计算图像每行的字节数
 lLineBytes = WIDTHBYTES(lWidth * (lpbmi0->biBitCount));
 
 // 计算缩放后的图像实际宽度
 // 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
 lNewWidth = (LONG) (lWidth* fXZoomRatio + 0.5);
 
 // 计算新图像每行的字节数
 lNewLineBytes = WIDTHBYTES(lNewWidth * (lpbmi0->biBitCount));
 
 // 计算缩放后的图像高度
 lNewHeight = (LONG) (lHeight * fYZoomRatio + 0.5);
 
 // 分配内存,以保存新DIB
 hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
 
 // 判断是否内存分配失败
 if (hDIB == NULL)
 {
 // 分配内存失败
 return NULL;
 }
 
 // 锁定内存
 lpNewDIB = (LPSTR)::GlobalLock((HGLOBAL) hDIB);
 
 // 复制DIB信息头和调色板
 memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
 
 // 找到新DIB象素起始位置
 lpNewDIBBits = (LPBYTE)::FindDIBBits(lpNewDIB);
 
 // 获取指针
 lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
 lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
 
 // 更新DIB中图像的高度和宽度
 if (IS_WIN30_DIB(lpNewDIB))
 {
 // 对于Windows 3.0 DIB
 lpbmi->biWidth = lNewWidth;
 lpbmi->biHeight = lNewHeight;
 }
 else
 {
 // 对于其它格式的DIB
 lpbmc->bcWidth = (unsigned short) lNewWidth;
 lpbmc->bcHeight = (unsigned short) lNewHeight;
 }
 if(wNumColors==256)
 {
 // 针对图像每行进行操作
 for(i = 0; i < lNewHeight; i++)
 {
 // 针对图像每列进行操作
 for(j = 0; j < lNewWidth; j++)
 {
 
 // 指向新DIB第i行,第j个象素的指针
 // 注意此处宽度和高度是新DIB的宽度和高度
 lpDst = (LPBYTE)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
 
 // 计算该象素在源DIB中的坐标
 i0 = (LONG) (i / fYZoomRatio + 0.5);
 j0 = (LONG) (j / fXZoomRatio + 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;
 }
 
 }
 } 
 }
 else if(wNumColors==0)
 {for(i = 0; i < lNewHeight; i++)
 {
 // 针对图像每列进行操作
 for(j = 0; j < lNewWidth; j++)
 {
 // 指向新DIB第i行,第j个象素的指针
 // 注意此处宽度和高度是新DIB的宽度和高度
 lpDst = (LPBYTE)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + 3*j;
 
 // 计算该象素在源DIB中的坐标
 i0 = (LONG) (i / fYZoomRatio + 0.5);
 j0 = (LONG) (j / fXZoomRatio + 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);
 }
 }
 }
 }
 // 返回
 return hDIB;
}

4. 256位图=》灰度图
/*************************************************************************
*
* 函数名称:
* On256tograyscale ()
*
* 说明:
* 该算法函数用来把256图像转化成灰度图像。
*
************************************************************************/
void CCimageProcessingView::On256tograyscale() 
{
 // TODO: Add your command handler code here
 // 获取文档指针
 CCimageProcessingDoc* pDoc = GetDocument();
 
 // 指向DIB的指针
 LPSTR lpDIB;
 
 // 指向DIB象素指针
 LPSTR lpDIBBits;
 
 // 指向DIB的一个象素的指针
 BYTE * lpSrc;
 
 // 颜色表中的颜色数目
 WORD wNumColors;
 // 灰度映射表
 BYTE bGrayMap[256];

 //调色板索应循环变量
 LONG i;

 // 图象高度循环变量
 LONG ih;
 //图象宽度循环变量
 LONG iw;
 
 // 图像宽度
 LONG lWidth;
 
 // 图像高度
 LONG lHeight;
 
 // 图像每行的字节数
 LONG OneLineBytes;
 
 // 指向BITMAPINFO结构的指针(Win3.0)
 LPBITMAPINFO lpbmi;
 
 // 指向BITMAPCOREINFO结构的指针(OS/2)
 LPBITMAPCOREINFO lpbmc;
 
 // 表明是否是Win3.0 DIB的标记
 BOOL bWin30DIB;

 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
 
 // 获取指向BITMAPINFO结构的指针(Win3.0)
 lpbmi = (LPBITMAPINFO)lpDIB;
 
 // 获取指向BITMAPCOREINFO结构的指针(OS/2)
 lpbmc = (LPBITMAPCOREINFO)lpDIB;
 
 
 // 锁定DIB
 
 
 // 获取DIB中颜色表中的颜色数目
 wNumColors = ::DIBNumColors(lpDIB);
 
 // 判断是否是256色位图
 if (wNumColors != 256)
 {
 
 MessageBox("不是256色位图!");
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
 
 // 返回
 return;
 }
 
 // 更改光标形状
 BeginWaitCursor();
 
 
 // 判断是否是WIN3.0的DIB
 bWin30DIB = IS_WIN30_DIB(lpDIB);
 
 //将原图象的调色板转化为灰度调色板
//建立原调色板索引与灰度调色板索引的映射关系
 for (i = 0; i < 256; i ++)
 {
 if (bWin30DIB)
 {
 //对原256色调色板的每一表项计算对应的灰度值
 bGrayMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed +
 0.587 * lpbmi->bmiColors[i].rgbGreen +
 0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);
 
 // 建立灰度调色板

 //红色分量
 lpbmi->bmiColors[i].rgbRed = i;
 
 // 绿色分量
 lpbmi->bmiColors[i].rgbGreen = i;
 
 // 蓝色分量
 lpbmi->bmiColors[i].rgbBlue = i;
 
 // 保留位
 lpbmi->bmiColors[i].rgbReserved = 0;
 }

 else
 {
 //对原256色调色板的每一表项计算对应的灰度值
 bGrayMap[i] = (BYTE)(0.299 * lpbmc->bmciColors[i].rgbtRed +
 0.587 * lpbmc->bmciColors[i].rgbtGreen +
 0.114 * lpbmc->bmciColors[i].rgbtBlue + 0.5);
 
 //建立灰度调色板

 // 红色分量
 lpbmc->bmciColors[i].rgbtRed = i;
 
 // 绿色分量
 lpbmc->bmciColors[i].rgbtGreen = i;
 
 // 蓝色分量
 lpbmc->bmciColors[i].rgbtBlue = i;
 }
 }

 // 找到DIB图像象素起始位置
 lpDIBBits = ::FindDIBBits(lpDIB); 
 
 // 获取图像宽度
 lWidth = ::DIBWidth(lpDIB);
 
 // 获取图像高度
 lHeight = ::DIBHeight(lpDIB);
 
 // 计算图像每行的字节数
 OneLineBytes = WIDTHBYTES(lWidth * 8);
 
 // 更换原256色位图的每个象素的颜色索引

 // 每行
 for(ih = 0; ih < lHeight; ih++)
 {
 // 每列
 for(iw= 0; iw < lWidth; iw++)
 {
 // 指向DIB第ih行,第iw列的象素的指针
 lpSrc = (BYTE*)lpDIBBits + OneLineBytes * (lHeight - 1 - ih) +iw;
 
 //对256色位图,其像素值是调色板索引值
 //对灰度图,索引值就等于其灰度值
 
 //映射调色板索引
 *lpSrc = bGrayMap[*lpSrc];
 }
 }
 
 // 替换当前调色板为灰度调色板
 pDoc->GetDocPalette()->SetPaletteEntries(0,256,
 (LPPALETTEENTRY)lpbmi->bmiColors);

 // 设置脏标记
 pDoc->SetModifiedFlag(TRUE);
 
 // 实现新的调色板
 OnDoRealize((WPARAM)m_hWnd,0);
 
 // 更新视图
 pDoc->UpdateAllViews(NULL);
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

 // 恢复光标
 EndWaitCursor(); 
}

5. 随机噪声
void CCimageProcessingView::OnRestoreRandomnoise() 
{
 // TODO: Add your command handler code here
 // 获取文档指针
 CCimageProcessingDoc* pDoc = GetDocument();
 
 // 指向DIB的指针
 LPSTR lpDIB;
 
 // 获取DIB图像并锁定
 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB()); 
 
 // 更改光标形状
 BeginWaitCursor();
 
 // 调用RandomNoise函数对DIB进行加噪处理
 if (::RandomNoise(lpDIB))
 { 
 // 设置脏标记
 pDoc->SetModifiedFlag(TRUE);

 // 更新视图
 pDoc->UpdateAllViews(NULL);
 }
 else
 {
 // 提示用户
 MessageBox("分配内存失败!");
 }
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());

 // 恢复光标
 EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
*
* RandomNoise()
*
* 参数:
*
* LPSTR lpDIB // 指向源DIB图像指针
*
* 返回值:
*
* BOOL // 加入随机噪声操作成功返回TRUE,否则返回FALSE。
*
* 说明:
*
* 该函数用来对256色位图和24位真彩色位图进行加入随即噪声操作。
*
************************************************************************/

BOOL WINAPI RandomNoise (LPSTR lpDIB)
{
 // 图像宽度和高度
 LONG lWidth,lHeight;

 // 指向图像像素的指针
 LPSTR lpDIBBits;

 // 指向源图像的指针
 LPSTR lpSrc;
 
 //循环变量
 long i;
 long j;

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

 //指向图像信息头结构的指针
 LPBITMAPINFOHEADER lpbmi;
 
 //图像的颜色数
 WORD wNumColors; 

 //噪声
 BYTE NoiseValue;

 // 计算图像每行的字节数
 lpbmi=(LPBITMAPINFOHEADER)lpDIB;
 
 //计算图像的高度和宽度
 lWidth=::DIBWidth(lpDIB);
 lHeight=::DIBHeight(lpDIB);

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

 //计算图像的颜色数
 wNumColors=::DIBNumColors(lpDIB);

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

 //生成伪随机种子
 srand((unsigned)time(NULL));

 //在图像中加噪

 //如果是256色位图
 if(wNumColors==256)
 { 
 for (j = 0;j < lHeight ;j++)
 {
 for(i = 0;i < lWidth ;i++)
 {
 //随机的噪声值
 NoiseValue=rand()/1024;

 // 指向源图像倒数第j行,第i个象素的指针 
 lpSrc = (char *)lpDIBBits + lLineBytes * j + i; 

 //在像素值中加入噪声值
 *lpSrc = (BYTE)(((BYTE)*(lpSrc))*224/256 + NoiseValue);
 }
 }
 }

 //如果是24位真彩色位图
 else if(wNumColors==0)
 {
 for (j = 0;j < lHeight ;j++)
 {
 for(i = 0;i < lWidth ;i++)
 {
 NoiseValue=rand()/1024;

 // 指向源图像倒数第j行,第i个象素的指针 
 lpSrc = (char *)lpDIBBits + lLineBytes * j + 3*i; 

 //在每个像素的RGB分量中加入随机的噪声值
 *lpSrc++ = (BYTE)(((BYTE)*(lpSrc++))*224/256 + NoiseValue);
 *lpSrc++ = (BYTE)(((BYTE)*(lpSrc++))*224/256 + NoiseValue);
 *lpSrc++ = (BYTE)(((BYTE)*(lpSrc++))*224/256 + NoiseValue);
 }
 }
 }

 //如果既不是256色位图也不是24 位真彩色位图,直接返回
 else
 {
 AfxMessageBox("只支持256色位图和24位真彩色位图");
 return false;
 }

 // 返回
 return true;
}

6.亮度调节
void CCimageProcessingView::OnEXPBright() 
{
 // TODO: Add your command handler code here
 CCimageProcessingDoc* pDoc=GetDocument();
 LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB());
 AdjustBrightness(lpDIB,-80);
 pDoc->SetModifiedFlag(true);
 OnDoRealize((WPARAM)m_hWnd,0);
 pDoc->UpdateAllViews(NULL); 
}
/*************************************************************************
*
* 函数名称:
*
* AdjustBrightness ()
*
* 参数:
*
* LPSTR lpDIB // 指向源DIB图像指针
*
* int db 
*
* BOOL //操作成功返回TRUE,否则返回FALSE。
*
* 说明:
*
* 该算法函数用来对256色位图和24位真彩色位图进行亮度调整操作。
*
************************************************************************/
BOOL WINAPI AdjustBrightness(LPSTR lpDIB, int db)
{
 BYTE r, g, b;

 
 BITMAPINFO *pbmi;
 WORD wNumColors;
 LONG i;
 LPSTR lpDIBBits;
 int nDelta; 
 int iWidth, iHeight;

 if (lpDIB == NULL)
 return FALSE;
 pbmi = (BITMAPINFO *)lpDIB;
 if (! pbmi)
 return FALSE;

 
 wNumColors =::DIBNumColors(lpDIB);

 if (wNumColors==256) 
 {
 
 for (i=0; i  {
 pbmi->bmiColors[i].rgbRed = BOUND(pbmi->bmiColors[i].rgbRed+db, 0, 255);
 pbmi->bmiColors[i].rgbGreen = BOUND(pbmi->bmiColors[i].rgbGreen+db, 0, 255);
 pbmi->bmiColors[i].rgbBlue = BOUND(pbmi->bmiColors[i].rgbBlue+db, 0, 255);
 }
 
 }
 else if(wNumColors==0) 
 {
 
 lpDIBBits= ::FindDIBBits(lpDIB);
 nDelta = WIDTHBYTES((pbmi->bmiHeader.biBitCount)*(pbmi->bmiHeader.biWidth))
 - ((pbmi->bmiHeader.biWidth)*(pbmi->bmiHeader.biBitCount)+7)/8;
 
 for (iHeight=0; iHeightbmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidthbmiHeader.biWidth; iWidth++)
 {
 b = (BYTE)*(lpDIBBits);
 g = (BYTE)*(lpDIBBits+1);
 r = (BYTE)*(lpDIBBits+2);
 *lpDIBBits++= BOUND(b+db, 0, 255);
 *lpDIBBits++= BOUND(g+db, 0, 255);
 *lpDIBBits++= BOUND(r+db, 0, 255);
 }
 lpDIBBits += nDelta; 
 }
 
 }
 
 else
 {
 AfxMessageBox("只处理256色和24位位图");

 return false;

 }
 return TRUE;
}

7.色调调节
void CCimageProcessingView::OnExpColor() 
{
 // TODO: Add your command handler code here
 CCimageProcessingDoc* pDoc=GetDocument();
 LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB());
 AdjustColor(lpDIB,26,120,-30);
 pDoc->SetModifiedFlag(true);
 OnDoRealize((WPARAM)m_hWnd,0);
 pDoc->UpdateAllViews(NULL); 
}
/*************************************************************************
*
* 函数名称:
*
* AdjustColor ()
*
* 参数:
*
* LPSTR lpDIB // 指向源DIB图像指针
*
* int dr dg db 
*
* BOOL //操作成功返回TRUE,否则返回FALSE。
*
* 说明:
*
* 该算法函数用来对256色位图和24位真彩色位图进行色调调整操作。
*
************************************************************************/

BOOL WINAPI AdjustColor(LPSTR lpDIB, int dr, int dg, int db)
{
 BYTE r, g, b;

 
 BITMAPINFO *pbmi;
 WORD wNumColors;
 LONG i;
 LPSTR lpDIBBits;
 int nDelta; 
 int iWidth, iHeight;

 if (lpDIB == NULL)
 return FALSE;
 pbmi = (BITMAPINFO *)lpDIB;
 if (! pbmi)
 return FALSE;

 
 wNumColors =::DIBNumColors(lpDIB);

 if (wNumColors==256) 
 {
 
 for (i=0; i  {
 pbmi->bmiColors[i].rgbRed = BOUND(pbmi->bmiColors[i].rgbRed+dr, 0, 255);
 pbmi->bmiColors[i].rgbGreen = BOUND(pbmi->bmiColors[i].rgbGreen+dg, 0, 255);
 pbmi->bmiColors[i].rgbBlue = BOUND(pbmi->bmiColors[i].rgbBlue+db, 0, 255);
 }
 
 }
 else if(wNumColors==0) 
 {
 
 lpDIBBits= ::FindDIBBits(lpDIB);
 nDelta = WIDTHBYTES((pbmi->bmiHeader.biBitCount)*(pbmi->bmiHeader.biWidth))
 - ((pbmi->bmiHeader.biWidth)*(pbmi->bmiHeader.biBitCount)+7)/8;
 
 for (iHeight=0; iHeightbmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidthbmiHeader.biWidth; iWidth++)
 {
 b = (BYTE)*(lpDIBBits);
 g = (BYTE)*(lpDIBBits+1);
 r = (BYTE)*(lpDIBBits+2);
 *lpDIBBits++= BOUND(b+db, 0, 255);
 *lpDIBBits++= BOUND(g+dg, 0, 255);
 *lpDIBBits++= BOUND(r+dr, 0, 255);
 }
 lpDIBBits += nDelta; 
 }
 
 }
 
 else
 {
 AfxMessageBox("只处理256色和24位位图");

 return false;

 }
 return TRUE;
}

8.对比度调节
void CCimageProcessingView::OnExpComp() 
{
 // TODO: Add your command handler code here
 CCimageProcessingDoc* pDoc=GetDocument();
 LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB());
 AdjustCotrast(lpDIB,80);
 pDoc->SetModifiedFlag(true);
 OnDoRealize((WPARAM)m_hWnd,0);
 pDoc->UpdateAllViews(NULL); 
}
/*************************************************************************
*
* 函数名称:
*
* AdjustCotrast ()
*
* 参数:
*
* LPSTR lpDIB // 指向源DIB图像指针
*
* int dc 
*
* BOOL //操作成功返回TRUE,否则返回FALSE。
*
* 说明:
*
* 该算法函数用来对256色位图和24位真彩色位图进行对比度调整操作。
*
************************************************************************/

BOOL WINAPI AdjustCotrast(LPSTR lpDIB, int dc)
{
 BYTE r, g, b;

 
 BITMAPINFO *pbmi;
 WORD wNumColors;
 LONG i;
 LPSTR lpDIBBits;
 int nDelta; 
 int iWidth, iHeight;

 if (lpDIB == NULL)
 return FALSE;
 pbmi = (BITMAPINFO *)lpDIB;
 if (! pbmi)
 return FALSE;

 
 wNumColors =::DIBNumColors(lpDIB);

 if (wNumColors==256) 
 {
 
 for (i=0; i  {
 if(dc>=0)
 {
 int vMin=dc;
 int vMax=255-dc;
 float Grad=((float)(vMax-vMin))/255;
 IncreaseContrast(&(pbmi->bmiColors[i].rgbRed),vMin,vMax,Grad);
 IncreaseContrast(&(pbmi->bmiColors[i].rgbGreen),vMin,vMax,Grad);
 IncreaseContrast(&(pbmi->bmiColors[i].rgbBlue),vMin,vMax,Grad);
 }
 else
 {
 float Grad=255/(255+2*(float)dc);
 DecreaseContrast(&(pbmi->bmiColors[i].rgbRed),dc,Grad);
 DecreaseContrast(&(pbmi->bmiColors[i].rgbGreen),dc,Grad);
 DecreaseContrast(&(pbmi->bmiColors[i].rgbBlue),dc,Grad);

 }
 
 }
 
 }

 else if(wNumColors==0) 
 {
 
 lpDIBBits= ::FindDIBBits(lpDIB);
 nDelta = WIDTHBYTES((pbmi->bmiHeader.biBitCount)*(pbmi->bmiHeader.biWidth))
 - ((pbmi->bmiHeader.biWidth)*(pbmi->bmiHeader.biBitCount)+7)/8;
 
 for (iHeight=0; iHeightbmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidthbmiHeader.biWidth; iWidth++)
 {
 b = (BYTE)*(lpDIBBits);
 g = (BYTE)*(lpDIBBits+1);
 r = (BYTE)*(lpDIBBits+2);
 
 if(dc>=0)
 {
 int vMin=dc;
 int vMax=255-dc;
 float Grad=((float)(vMax-vMin))/255;
 IncreaseContrast(&b,vMin,vMax,Grad);
 IncreaseContrast(&g,vMin,vMax,Grad);
 IncreaseContrast(&r,vMin,vMax,Grad);
 }
 else
 {
 float Grad=255/(255+2*(float)dc);
 DecreaseContrast(&b,dc,Grad);
 DecreaseContrast(&g,dc,Grad);
 DecreaseContrast(&r,dc,Grad);

 }
 

 *lpDIBBits++= b;
 *lpDIBBits++= g;
 *lpDIBBits++= r;
 }
 lpDIBBits += nDelta; 
 }
 
 }

 else
 {
 AfxMessageBox("只处理256色和24位位图");
 return false;
 }

 
 return TRUE;
}

你可能感兴趣的:(转来学习)