8种常用图像处理算法
生活随笔
收集整理的這篇文章主要介紹了
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<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;
}
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种常用图像处理算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从对话框中传递参数到视图类
- 下一篇: MFC文件操作