?? globalapi.cpp
字號:
ReleaseDC( NULL, hDC );
return FALSE;
}
// 將指針保存在CDib對象的數據成員中
pDibDest->m_lpBMIH = lpBMIH;
pDibDest->m_lpImage = lpImage;
pDibDest->m_nBmihAlloc = pDibDest->m_nImageAlloc = pDibDest->crtAlloc;
// 刪除臨時變量
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* CopyDIB()
*
* \輸入參數:
* CDib* pDibSrc - 指向源數據的CDib對象指針
* CDib* pDibDst - 指向拷貝目標的CDib對象指針
*
* \返回值:
* BOOL - 如果操作成功,則返回TRUE
*
* \說明:
* 該函數將源CDib類pDibSrc中的數據拷貝到pDibDst中,并對相應的數據成員賦值
*
*************************************************************************
*/
BOOL CopyDIB(CDib* pDibSrc, CDib* pDibDst)
{
// 將目的CDib對象清空
pDibDst->Empty();
// 計算信息頭加上調色板的大小,并分配相應的內存
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pDibSrc->m_nColorTableEntries;
pDibDst->m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSizeHdr];
pDibDst->m_nBmihAlloc = pDibDst->m_nImageAlloc = pDibDst->crtAlloc;
try{
// 拷貝信息頭和調色板
memcpy(pDibDst->m_lpBMIH,pDibSrc->m_lpBMIH,nSizeHdr);
// 如果結構的長度不對,則進行錯誤處理
if(pDibDst->m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
throw new CException;
}
// 保存圖象數據內存大小到CDib對象的數據成員中
pDibDst->m_dwSizeImage = pDibDst->m_lpBMIH->biSizeImage;
// 如果圖象數據內存大小為0,則重新計算
if(pDibDst->m_dwSizeImage == 0) {
DWORD dwBytes = ((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) / 32;
if(((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
pDibDst->m_dwSizeImage = dwBytes * pDibDst->m_lpBMIH->biHeight;
}
// 設置DIB中的調色板指針
pDibDst->m_lpvColorTable = (LPBYTE) pDibDst->m_lpBMIH + sizeof(BITMAPINFOHEADER);
// 計算調色板的表項數
pDibDst->ComputePaletteSize(pDibDst->m_lpBMIH->biBitCount);
// 如果DIB中存在調色板,則創建一個Windows調色板
pDibDst->MakePalette();
// 分配圖象數據內存,并拷貝圖象數據
pDibDst->m_lpImage = (LPBYTE) new char[pDibDst->m_dwSizeImage];
memcpy(pDibDst->m_lpImage, pDibSrc->m_lpImage,pDibDst->m_dwSizeImage);
}
catch(CException* pe)
{
AfxMessageBox("Copy DIB error");
pDibDst->Empty();
pe->Delete();
return FALSE;
}
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* CopyScreenToDIB
*
* \輸入參數:
* LPRECT lpRect - 需要拷貝的屏幕區域
* CDib* pDibDest - 指向目標CDib對象的指針
*
* \返回值:
* BOOL - 如果操作成功,則返回TRUE
*
* \說明:
* 該函數將指定矩形位置內的屏幕內容拷貝到DIB中源CDib類pDibSrc中的數據拷貝到pDibDst中
*
*************************************************************************
*/
BOOL CopyScreenToDIB(LPRECT lpRect, CDib* pDibDest)
{
// 屏幕設備上下文和內存設備上下文句柄
HDC hScrDC, hMemDC;
// 聲明BITMAP臨時句柄和以前的BITMAP句柄
HBITMAP hBitmap, hOldBitmap;
// 調色板句柄
HPALETTE hPalette;
// 獲取矩形區域的坐標
int nX, nY, nX2, nY2;
// DIB圖象的高度和寬度
int nWidth, nHeight;
// 屏幕分辨率
int xScrn, yScrn;
// 如果給定的矩形區域為空,則不進行進一步的處理
if (IsRectEmpty(lpRect))
return FALSE;
// 得到一個屏幕設備上下文
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
// 創建與屏幕設備兼容的內存設備上下文
hMemDC = CreateCompatibleDC(hScrDC);
// 得到矩形的區域坐標
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 得到屏幕的分辨率,以便后面的判斷處理
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
// 判斷矩形區域是否超出屏幕
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;
// 計算DIB圖象的高度和寬度
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 創建一個與屏幕設備上下文兼容的DDB位圖
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
// 將DDB位圖選入內存設備上下文
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 將屏幕中指定區域的圖象傳輸到內存設備上下文中
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
// 然后將以前的圖象選入,并得到屏幕區域的DDB圖象句柄
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
// 將臨時的設備上下文刪除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 得到當前系統調色板
hPalette = GetSystemPalette();
// 將DDB圖象轉換為DIB圖象
pDibDest->ConvertFromDDB(hBitmap,hPalette);
// 刪除臨時對象
DeleteObject(hPalette);
DeleteObject(hBitmap);
return TRUE;
}
void Laplacian(LPBYTE lpImage, int nWidth, int nHeight, int nSaveWidth, double* pdGrad)
{
int x, y;
// 初始化
for(y=0; y<nHeight ; y++ )
for(x=0 ; x<nWidth ; x++ )
{
*(pdGrad+y*nWidth+x)=0;
}
// 設置模板系數
static int nWeight[3][3] ;
nWeight[0][0] = -1 ;
nWeight[0][1] = -1 ;
nWeight[0][2] = -1 ;
nWeight[1][0] = -1 ;
nWeight[1][1] = 8 ;
nWeight[1][2] = -1 ;
nWeight[2][0] = -1 ;
nWeight[2][1] = -1 ;
nWeight[2][2] = -1 ;
//這個變量用來表示Laplacian算子象素值
int nTmp[3][3];
// 臨時變量
double dGrad;
// 模板循環控制變量
int yy ;
int xx ;
// 下面開始利用Laplacian算子進行計算,為了保證計算所需要的
// 的數據位于圖像數據的內部,下面的兩重循環的條件是
// y<nHeight-2 而不是y<nHeight,相應的x方向也是x<nWidth-2
// 而不是x<nWidth
for(y=1; y<nHeight-2 ; y++ )
for(x=1 ; x<nWidth-2 ; x++ )
{
dGrad = 0 ;
// Laplacian算子需要的各點象素值
// 模板第一行
nTmp[0][0] = lpImage[(y-1)*nSaveWidth + x - 1 ] ;
nTmp[0][1] = lpImage[(y-1)*nSaveWidth + x ] ;
nTmp[0][2] = lpImage[(y-1)*nSaveWidth + x + 1 ] ;
// 模板第二行
nTmp[1][0] = lpImage[y*nSaveWidth + x - 1 ] ;
nTmp[1][1] = lpImage[y*nSaveWidth + x ] ;
nTmp[1][2] = lpImage[y*nSaveWidth + x + 1 ] ;
// 模板第三行
nTmp[2][0] = lpImage[(y+1)*nSaveWidth + x - 1 ] ;
nTmp[2][1] = lpImage[(y+1)*nSaveWidth + x ] ;
nTmp[2][2] = lpImage[(y+1)*nSaveWidth + x + 1 ] ;
// 計算梯度
for(yy=0; yy<3; yy++)
for(xx=0; xx<3; xx++)
{
dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;
}
// 梯度值寫入內存
*(pdGrad+y*nWidth+x)=dGrad;
}
}
void MakeGauss(double sigma, double **pdKernel, int *pnWindowSize)
{
// 循環控制變量
int i ;
// 數組的中心點
int nCenter;
// 數組的某一點到中心點的距離
double dDis ;
double PI = 3.14159;
// 中間變量
double dValue;
double dSum ;
dSum = 0 ;
// 數組長度,根據概率論的知識,選取[-3*sigma, 3*sigma]以內的數據。
// 這些數據會覆蓋絕大部分的濾波系數
*pnWindowSize = 1 + 2 * ceil(3 * sigma);
// 中心
nCenter = (*pnWindowSize) / 2;
// 分配內存
*pdKernel = new double[*pnWindowSize] ;
for(i=0; i< (*pnWindowSize); i++)
{
dDis = (double)(i - nCenter);
dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma)) / (sqrt(2 * PI) * sigma );
(*pdKernel)[i] = dValue ;
dSum += dValue;
}
// 歸一化
for(i=0; i<(*pnWindowSize) ; i++)
{
(*pdKernel)[i] /= dSum;
}
}
/*************************************************************************
*
* \函數名稱:
* GaussianSmooth()
*
* \輸入參數:
* unsigned char * pUnchImg - 指向圖象數據的指針
* int nWidth - 圖象數據寬度
* int nHeight - 圖象數據高度
* double dSigma - 高斯函數的標準差
* unsigned char * pUnchSmthdImg - 指向經過平滑之后的圖象數據
*
* \返回值:
* 無
*
* \說明:
* 為了抑止噪聲,采用高斯濾波對圖象進行濾波,濾波先對x方向進行,然后對
* y方向進行。
*
*************************************************************************
*/
void GaussianSmooth(unsigned char *pUnchImg, int nWidth, int nHeight,
double sigma, unsigned char * pUnchSmthdImg)
{
// 循環控制變量
int y;
int x;
int i;
// 高斯濾波器的數組長度
int nWindowSize;
// 窗口長度的1/2
int nHalfLen;
// 一維高斯數據濾波器
double *pdKernel ;
// 高斯系數與圖象數據的點乘
double dDotMul ;
// 高斯濾波系數的總和
double dWeightSum ;
// 中間變量
double * pdTmp ;
// 分配內存
pdTmp = new double[nWidth*nHeight];
// 產生一維高斯數據濾波器
// MakeGauss(sigma, &dKernel, &nWindowSize);
MakeGauss(sigma, &pdKernel, &nWindowSize) ;
// MakeGauss返回窗口的長度,利用此變量計算窗口的半長
nHalfLen = nWindowSize / 2;
// x方向進行濾波
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判斷是否在圖象內部
if( (i+x) >= 0 && (i+x) < nWidth )
{
dDotMul += (double)pUnchImg[y*nWidth + (i+x)] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pdTmp[y*nWidth + x] = dDotMul/dWeightSum ;
}
}
// y方向進行濾波
for(x=0; x<nWidth; x++)
{
for(y=0; y<nHeight; y++)
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判斷是否在圖象內部
if( (i+y) >= 0 && (i+y) < nHeight )
{
dDotMul += (double)pdTmp[(y+i)*nWidth + x] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pUnchSmthdImg[y*nWidth + x] = (unsigned char)(int)dDotMul/dWeightSum ;
}
}
// 釋放內存
delete []pdKernel;
pdKernel = NULL ;
delete []pdTmp;
pdTmp = NULL;
}
/*************************************************************************
*
* \函數名稱:
* DirGrad()
*
* \輸入參數:
* unsigned char *pUnchSmthdImg - 經過高斯濾波后的圖象
* int nWidht - 圖象寬度
* int nHeight - 圖象高度
* int *pnGradX - x方向的方向導數
* int *pnGradY - y方向的方向導數
* \返回值:
* 無
*
* \說明:
* 這個函數計算方向倒數,采用的微分算子是(-1 0 1) 和 (-1 0 1)'(轉置)
* 計算的時候對邊界象素采用了特殊處理
*
*
*************************************************************************
*/
void DirGrad(unsigned char *pUnchSmthdImg, int nWidth, int nHeight,
int *pnGradX , int *pnGradY)
{
// 循環控制變量
int y ;
int x ;
// 計算x方向的方向導數,在邊界出進行了處理,防止要訪問的象素出界
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
pnGradX[y*nWidth+x] = (int) ( pUnchSmthdImg[y*nWidth+min(nWidth-1,x+1)]
- pUnchSmthdImg[y*nWidth+max(0,x-1)] );
}
}
// 計算y方向的方向導數,在邊界出進行了處理,防止要訪問的象素出界
for(x=0; x<nWidth; x++)
{
for(y=0; y<nHeight; y++)
{
pnGradY[y*nWidth+x] = (int) ( pUnchSmthdImg[min(nHeight-1,y+1)*nWidth + x]
- pUnchSmthdImg[max(0,y-1)*nWidth+ x ] );
}
}
}
/*************************************************************************
*
* \函數名稱:
* GradMagnitude()
*
* \輸入參數:
* int *pnGradX - x方向的方向導數
* int *pnGradY - y方向的方向導數
* int nWidht - 圖象寬度
* int nHeight - 圖象高度
* int *pnMag - 梯度幅度
*
* \返回值:
* 無
*
* \說明:
* 這個函數利用方向倒數計算梯度幅度,方向倒數是DirGrad函數計算的結果
*
*************************************************************************
*/
void GradMagnitude(int *pnGradX, int *pnGradY, int nWidth, int nHeight, int *pnMag)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -