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<lHeight/2; 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<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;
}

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<wNumColors; 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; iHeight<pbmi->bmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidth<pbmi->bmiHeader.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<wNumColors; 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; iHeight<pbmi->bmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidth<pbmi->bmiHeader.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<wNumColors; 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; iHeight<pbmi->bmiHeader.biHeight; iHeight++)
 {
 for (iWidth=0; iWidth<pbmi->bmiHeader.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;
}

8种常用图像处理算法相关推荐

  1. 一文概括常用图像处理算法

    本文总结了11种常用的图像处理算法,包含了预处理算法以及检测算法,并介绍了一些常用的开发库. 一.算法(预处理算法.检测算法) 在采集完图像后,首先会对图像进行预处理操作.保证图像的对比度清晰,水平. ...

  2. [转载] java实现四种常用排序算法

    参考链接: 用Java排序 四种常用排序算法 ##注:从小到大排 ##冒泡排序## 特点:效率低,实现简单 思想:每一趟将待排序序列中最大元素移到最后,剩下的为新的待排序序列,重复上述步骤直到排完所有 ...

  3. 数字图像处理——12种常用图像处理方法对比

    数字图像处理--12种常用图像处理方法对比 1.图像反转 2.对数变换 3.幂次变换 4.分段函数 5.直方图均衡化 6.直方图规定化 7.直方图匹配 8.线性滤波 9.中值滤波与均值滤波 10.拉普 ...

  4. 几种常用回归算法——线性回归、支持向量机回归和KNN回归

    欢迎关注,敬请点赞! 台湾何时归--几种常用回归算法 线性回归LR(Linear Regression) 代码展示(加噪声的正旋函数,狭义线性回归) 支持向量机回归SVR(Support Vector ...

  5. 几种常用图像处理开源库简介及使用总结

    1.OpenCV,主要以算法形式,展示其实现:也就是说,它实际提供的是各种图像处理算法.若需具体应用,需要组合其算法以实现某个功能. OpenCV 的全称 Open Source Computer V ...

  6. 视觉直观感受7种常用排序算法

    视觉直观感受若干常用排序算法 1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状 ...

  7. 五种常用排序算法总结

    本篇文章讲的是以下五种常用的排序算法: 一.冒泡排序 1.原理 每次从前往后遍历整个数组,每一项与其后一项进行对比,若符合要求(从大到小或从小到大),就交换位置. 一遍循环结束后,最大(小)的值就会被 ...

  8. 8种常用排序算法稳定性分析

    选择排序.快速排序.希尔排序.堆排序不是稳定的排序算法 冒泡排序.插入排序.归并排序和基数排序都是稳定的排序算法. [1]为什么要区分排序算法的稳定性? 排序算法的稳定性通俗地讲就是能保证排序前两个相 ...

  9. 10种常用排序算法实现

    在使用VBA进行写程序时,经常会做排序,下面将会给出一些常用的排序算法的实现,方便大家写程序参考,若代码中出现了错误,欢迎高手指正. 主要算法有: 1.(冒泡排序)Bubble sort 2.(选择排 ...

最新文章

  1. R语言导入、读取网络CSV数据(Read a CSV from a URL)实战:R原生read_csv、readr包、data.table
  2. threadlocal存连接对象的目的_面试官:知道ThreadLocal嘛?谈谈你对它的理解?
  3. golang中的http服务器
  4. SpringBoot整合MongoDB(实现一个简单缓存)
  5. linux无线网卡的安装
  6. SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?
  7. 为对象分配内存TLAB
  8. 打开服务器文件提示内存不够,打开服务器文件提示内存不够
  9. webbrowser中localhost和发布的地址_004、Spring Boot中的项目属性配置
  10. maven netty 配置_进阿里、腾讯、字节跳动、美团必掌握的Netty
  11. 简单的客户机服务器投射模拟
  12. 专科python应届生工资多少-应届毕业生自述面试15K月薪的Python后端开发经历,希望对你有用...
  13. 腾讯云 python接口_python调用腾讯云短信接口
  14. 三维模型等大长方体剖分算法实现
  15. 关于Scala和面向对象的函数式编程
  16. Advertising on Instagram 如何在Instagram上发布广告 Lynda课程中文字幕
  17. java实现马尔科夫链,马尔科夫链算法的JAVA实现
  18. 自考招生工商学院类网站织梦模板
  19. qpython3l表白编程_沫琼的喜欢 | LOFTER(乐乎) - 让兴趣,更有趣
  20. excel生成动态进度条

热门文章

  1. 【Tools】CMAKE的使用
  2. Python-OpenCV 处理图像(二):滤镜和图像运算
  3. JQuery 总结(6) 锋利的jQuery
  4. 一台电脑上同启动两个Tomcat的方式,windows/Linux配置
  5. 2016年计算机视觉和图像处理相关的国际会议一览表
  6. 用初次训练的SVM+HOG分类器在负样本原图上检测HardExample
  7. 程序员面试题精选100题(27)-二元树的深度[数据结构]
  8. 程序员面试题精选100题(11)-求二元查找树的镜像[数据结构]
  9. 图形处理(三)简单拉普拉斯网格变形-Siggraph 2004
  10. 鸟哥的Linux私房菜(基础篇)-第三章、主机规划与磁盘分区(三.1. Linux与硬件的搭配)