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;
}