数字图像处理程序大全

SkySeraph Apr 22nd 2011  HQU

Email:zgzhaobo@gmail.com    QQ:452728574

Latest Modified Date:Apr 22nd 2011 HQU

说明:几乎包括所有常用的图像处理算法,发于博客,以备查询之用...

Dib头文件

class CDibImage  
{
 // Constructor and Destructor ///////////////////////////////
public:
 CDibImage();
 virtual ~CDibImage();

 // function /////////////////////////////////////////////////
public:
 //  DIB(Independent Bitmap) 函数
 BOOL    PaintDIB (HDC, LPRECT, HDIB, LPRECT, CPalette* pPal);
 BOOL    CreateDIBPalette(HDIB hDIB, CPalette* cPal);
 LPSTR   FindDIBBits (LPSTR lpbi);
 DWORD   DIBWidth (LPSTR lpDIB);
 DWORD   DIBHeight (LPSTR lpDIB);
 WORD    PaletteSize (LPSTR lpbi);
 WORD    DIBNumColors (LPSTR lpbi);
 HGLOBAL CopyHandle (HGLOBAL h);
 BOOL    SaveDIB (HDIB hDib, CFile& file);
 HDIB    ReadDIBFile(CFile& file);

 //  图像点运算函数
 BOOL LinerTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, FLOAT fA, FLOAT fB);
 BOOL ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre);
 BOOL WindowTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bLow, BYTE bUp);
 BOOL GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2);
 BOOL InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);

 // 图像几何变换函数
 BOOL TranslationDIB1 (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset);
 BOOL TranslationDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset);
 BOOL MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bDirection);
 BOOL TransposeDIB(LPSTR lpbi);
 HGLOBAL ZoomDIB(LPSTR lpbi, float fXZoomRatio, float fYZoomRatio);
 HGLOBAL RotateDIB(LPSTR lpbi, int iRotateAngle);
 HGLOBAL RotateDIB2(LPSTR lpbi, int iRotateAngle);
 unsigned char Interpolation (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, FLOAT x, FLOAT y);

 // 图像正交变换函数
 VOID FFT(complex<double> * TD, complex<double> * FD, int r);
 VOID IFFT(complex<double> * FD, complex<double> * TD, int r);
 VOID DCT(double *f, double *F, int power);
 VOID IDCT(double *F, double *f, int power);
 VOID WALSH(double *f, double *F, int r);
 VOID IWALSH(double *F, double *f, int r);
 
 BOOL Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL DIBDct(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL DIBWalsh(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL DIBWalsh1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);

 // 图像模板变换函数
 BOOL Template(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,   int iTempH, int iTempW,  int iTempMX, int iTempMY, FLOAT * fpArray, FLOAT fCoef);
 BOOL MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  int iFilterH, int iFilterW,   int iFilterMX, int iFilterMY);
 unsigned char GetMedianNum(unsigned char * bArray, int iFilterLen);
 BOOL GradSharp(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre);
 BOOL ReplaceColorPal(LPSTR lpDIB, BYTE * bpColorsTable);

 //  图像形态学变换函数
 BOOL ErosionDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori ,   int structure[3][3]);
 BOOL DilationDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori ,   int structure[3][3]);
 BOOL OpenDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori ,   int structure[3][3]);
 BOOL CloseDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bHori ,   int structure[3][3]);
 BOOL ThiningDIB (LPSTR lpDIBBits, LONG lWidth, LONG lHeight);

 //  图像边缘与轮廓运算函数
 BOOL RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL SobelDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL PrewittDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL KirschDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL GaussDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
 BOOL TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
};


Dib类/实现


CDibImage::CDibImage() 


CDibImage::~CDibImage() 


////////////////////////////////////////////////////////////////////// 
// DIB(Independent Bitmap) 函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::PaintDIB(HDC hDC, 
LPRECT lpDCRect, 
HDIB hDIB, 
LPRECT lpDIBRect, 
CPalette* pPal) 
LPSTR lpDIBHdr; // BITMAPINFOHEADER指针 
LPSTR lpDIBBits; // DIB象素指针 
BOOL bSuccess=FALSE; // 成功标志 
HPALETTE hPal=NULL; // DIB调色板 
HPALETTE hOldPal=NULL; // 以前的调色板 

if (hDIB == NULL) 
return FALSE; 

lpDIBHdr = (LPSTR)::GlobalLock((HGLOBAL) hDIB);// 锁定DIB
lpDIBBits = FindDIBBits(lpDIBHdr); // 找到DIB图像象素起始位置 

if (pPal != NULL) // 获取DIB调色板,并选中它 
hPal = (HPALETTE) pPal->m_hObject;
hOldPal = ::SelectPalette(hDC, hPal, TRUE); // 选中调色板 

::SetStretchBltMode(hDC, COLORONCOLOR); // 设置显示模式 

// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象 
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && 
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 
// 原始大小,不用拉伸。 
bSuccess = ::SetDIBitsToDevice(hDC, // hDC 
lpDCRect->left, // DestX 
lpDCRect->top, // DestY 
RECTWIDTH(lpDCRect), // nDestWidth 
RECTHEIGHT(lpDCRect), // nDestHeight 
lpDIBRect->left, // SrcX 
(int)DIBHeight(lpDIBHdr) - 
lpDIBRect->top - 
RECTHEIGHT(lpDIBRect), // SrcY 
0, // nStartScan 
(WORD)DIBHeight(lpDIBHdr), // nNumScans 
lpDIBBits, // lpBits 
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo 
DIB_RGB_COLORS); // wUsage 
else 
// 非原始大小,拉伸。 
bSuccess = ::StretchDIBits(hDC, // hDC 
lpDCRect->left, // DestX 
lpDCRect->top, // DestY 
RECTWIDTH(lpDCRect), // nDestWidth 
RECTHEIGHT(lpDCRect), // nDestHeight 
lpDIBRect->left, // SrcX 
lpDIBRect->top, // SrcY 
RECTWIDTH(lpDIBRect), // wSrcWidth 
RECTHEIGHT(lpDIBRect), // wSrcHeight 
lpDIBBits, // lpBits 
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo 
DIB_RGB_COLORS, // wUsage 
SRCCOPY); // dwROP 

::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定
if (hOldPal != NULL) 
::SelectPalette(hDC, hOldPal, TRUE); // 恢复以前的调色板 
}
return bSuccess; 

 
BOOL CDibImage::CreateDIBPalette(HDIB hDIB, CPalette* pPal) 

LPLOGPALETTE lpPal; // 指向逻辑调色板的指针 
HANDLE hLogPal; // 逻辑调色板的句柄 
HPALETTE hPal = NULL; // 调色板的句柄 
int i; // 循环变量
WORD wNumColors; // 颜色表中的颜色数目
LPSTR lpbi; // 指向DIB的指针
LPBITMAPINFO lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO结构的指针
BOOL bWinStyleDIB; // 表明是否是Win3.0 DIB的标记
BOOL bResult = FALSE; // 创建结果 

if (hDIB == NULL) 
return FALSE; 

lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 锁定DIB 
lpbmi = (LPBITMAPINFO)lpbi; // 获取指向BITMAPINFO结构的指针(Win3.0) 
lpbmc = (LPBITMAPCOREINFO)lpbi; // 获取指向BITMAPCOREINFO结构的指针 
wNumColors = DIBNumColors(lpbi);// 获取DIB中颜色表中的颜色数目 

if (wNumColors != 0) 
// 分配为逻辑调色板内存 
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
+ sizeof(PALETTEENTRY) 
* wNumColors);
// 如果内存不足,退出 
if (hLogPal == 0) 
{
::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定 
return FALSE; 

lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
lpPal->palVersion = PALVERSION; // 设置版本号 
lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目 
bWinStyleDIB = IS_WIN30_DIB(lpbi); // 判断是否是WIN3.0的DIB 

// 读取调色板 
for (i = 0; i < (int)wNumColors; i++) 
if (bWinStyleDIB) 
// 读取红色绿色蓝色分量 
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
// 保留位 
lpPal->palPalEntry[i].peFlags = 0; 
else 
// 读取红色绿色蓝色分量 
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
// 保留位 
lpPal->palPalEntry[i].peFlags = 0; 

bResult = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针 
::GlobalUnlock((HGLOBAL) hLogPal); // 解除锁定 
::GlobalFree((HGLOBAL) hLogPal); // 释放逻辑调色板 

::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定 
return bResult; 

 
LPSTR CDibImage::FindDIBBits(LPSTR lpbi) 
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi)); 

 
DWORD CDibImage::DIBWidth(LPSTR lpDIB) 
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) 
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 
lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
lpbmc = (LPBITMAPCOREHEADER)lpDIB; 

// 返回DIB中图像的宽度 
if (IS_WIN30_DIB(lpDIB)) 
{
DWORD c; 
c=lpbmi->biWidth; 
return lpbmi->biWidth; // 对于Windows 3.0 DIB,返回lpbmi->biWidth 
else 
{
return (DWORD)lpbmc->bcWidth; // 对于其它格式的DIB,返回lpbmc->bcWidth 

 
DWORD CDibImage::DIBHeight(LPSTR lpDIB) 
{
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) 
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 
lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
lpbmc = (LPBITMAPCOREHEADER)lpDIB; 

// 返回DIB中图像的宽度 
if (IS_WIN30_DIB(lpDIB)) 
{
return lpbmi->biHeight; // 对于Windows 3.0 DIB,返回lpbmi->biHeight 
else 
{
return (DWORD)lpbmc->bcHeight; // 对于其它格式的DIB,返回lpbmc->bcHeight 

 
WORD CDibImage::PaletteSize(LPSTR lpbi) 
// 计算DIB中调色板的大小 
if (IS_WIN30_DIB (lpbi)) 
//返回颜色数目×RGBQUAD的大小 
return (WORD)(DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
else 
//返回颜色数目×RGBTRIPLE的大小 
return (WORD)(DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 

 
WORD CDibImage::DIBNumColors(LPSTR lpbi) 
WORD wBitCount; 

// 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。 
// 对于这种情况,则返回一个近似的数值。 

// 判断是否是WIN3.0 DIB 
if (IS_WIN30_DIB(lpbi)) 
DWORD dwClrUsed; 
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; // 读取dwClrUsed值 

if (dwClrUsed != 0) 
// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值 
return (WORD)dwClrUsed; 

// 读取象素的位数 
if (IS_WIN30_DIB(lpbi)) 
{
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; // 读取biBitCount值 
else 
{
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; // 读取biBitCount值 

// 按照象素的位数计算颜色数目 
switch (wBitCount) 
case 1: 
return 2; 
break; 
case 4: 
return 16; 
break; 
case 8: 
return 256; 
break; 
default: 
return 0; 
break; 

 
HGLOBAL CDibImage::CopyHandle (HGLOBAL h) 
if (h == NULL) 
return NULL; 

DWORD dwLen = ::GlobalSize((HGLOBAL) h); // 获取指定内存区域大小 
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 分配新内存空间
if (hCopy != NULL) // 判断分配是否成功 
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
void* lp = ::GlobalLock((HGLOBAL) h); 

memcpy(lpCopy, lp, dwLen); 

::GlobalUnlock(hCopy); 
::GlobalUnlock(h); 

return hCopy; 

 
BOOL CDibImage::SaveDIB(HDIB hDib, CFile& file) 
{
BITMAPFILEHEADER bmfHdr; // Bitmap文件头
LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指针 
DWORD dwDIBSize; // DIB大小 

if (hDib == NULL) 
return FALSE; 

// 读取BITMAPINFO结构,并锁定 
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL) 
return FALSE; 

// 判断是否是WIN3.0 DIB 
if (!IS_WIN30_DIB(lpBI)) 
// 不支持其它类型的DIB保存 
::GlobalUnlock((HGLOBAL) hDib); 
return FALSE; 

//////////////////////////////////////////////////////////////////////// 
// 填充文件头///////////////////////////////////////////////////////////
bmfHdr.bfType = DIB_HEADER_MARKER; // 文件类型"BM" 

// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并 
// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。 

// 文件头大小+颜色表大小 
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小) 
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); 

// 计算图像大小 
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值 
dwDIBSize += lpBI->biSizeImage; 
else 
{
DWORD dwBmBitsSize; // 象素的大小 
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) 
* lpBI->biHeight; // 大小为Width * Height 
dwDIBSize += dwBmBitsSize; // 计算出DIB真正的大小 

// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的) 
lpBI->biSizeImage = dwBmBitsSize; 

// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小 
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 

// 两个保留字 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 

// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
+ PaletteSize((LPSTR)lpBI); 

///////////////////////////////////////////////////////////////////////// 
// 尝试写文件//////////////////////////////////////////////////////////// 
TRY 
{
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 写文件头 
file.WriteHuge(lpBI, dwDIBSize); // 写DIB头和象素 
CATCH (CFileException, e) 
::GlobalUnlock((HGLOBAL) hDib); 
THROW_LAST(); 
END_CATCH 

::GlobalUnlock((HGLOBAL) hDib); 
return TRUE; 

 
HDIB CDibImage::ReadDIBFile(CFile& file) 
BITMAPFILEHEADER bmfHeader; 
HDIB hDIB; 
LPSTR pDIB; 
DWORD dwBitsSize; 

dwBitsSize = file.GetLength(); // 获取DIB(文件)长度(字节) 

// 尝试读取DIB文件头 
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
return NULL; 
// 判断是否是DIB对象,检查头两个字节是否是"BM" 
if (bmfHeader.bfType != DIB_HEADER_MARKER) 
return NULL; 
// 为DIB分配内存 
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
if (hDIB == 0) 
return NULL; 

pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 读象素 
::GlobalUnlock((HGLOBAL) hDIB); 
::GlobalFree((HGLOBAL) hDIB); 
return NULL; 

::GlobalUnlock((HGLOBAL) hDIB); 
return hDIB; 

////////////////////////////////////////////////////////////////////// 
// 图像点运算函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::LinerTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
FLOAT fA, FLOAT fB) 
{
unsigned char* lpSrc; // 指向源图像的指针 
LONG i; // 循环变量 
LONG j;
LONG lLineBytes; // 图像每行的字节数
FLOAT fTemp; // 中间变量

lLineBytes = WIDTHBYTES(lWidth * 8); // 计算图像每行的字节数 

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fTemp = fA * (*lpSrc) + fB; // 线性变换

if (fTemp > 255) // 判断是否超出范围 
*lpSrc = 255; 
else if (fTemp < 0) 
*lpSrc = 0; 
else 
{
*lpSrc = (unsigned char) (fTemp + 0.5); // 四舍五入 

return TRUE; 

 
BOOL CDibImage::ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre) 
{
unsigned char* lpSrc; // 指向源图像的指针
LONG i; // 循环变量 
LONG j;
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;

if ((*lpSrc) < bThre) // 判断是否小于阈值 
*lpSrc = 0; 
else 
*lpSrc = 255; 

return TRUE; 

 
BOOL CDibImage::WindowTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
BYTE bLow, BYTE bUp) 
{
unsigned char* lpSrc; // 指向源图像的指针
LONG i; // 循环变量 
LONG j; 
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
if ((*lpSrc) < bLow) // 判断是否超出范围 
*lpSrc = 0; 
else if ((*lpSrc) > bUp) 
*lpSrc = 255; 

return TRUE; 

 
BOOL CDibImage::GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2) 
{
unsigned char* lpSrc; // 指向源图像的指针 
LONG i; // 循环变量 
LONG j;
BYTE bMap[256]; // 灰度映射表
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 

// 计算灰度映射表 
for (i = 0; i <= bX1; i++) 
{
if (bX1 > 0) // 判断bX1是否大于0(防止分母为0) 
bMap[i] = (BYTE) bY1 * i / bX1; 
else 
bMap[i] = 0; 
for (; i <= bX2; i++) 
if (bX2 != bX1) // 判断bX1是否等于bX2(防止分母为0) 
bMap[i] = bY1 + (BYTE) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1)); 
else 
bMap[i] = bY1; 
for (; i < 256; i++) 
{
if (bX2 != 255) // 判断bX2是否等于255(防止分母为0) 
bMap[i] = bY2 + (BYTE) ((255 - bY2) * (i - bX2) / (255 - bX2)); 
else 
bMap[i] = 255; 

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值 
*lpSrc = bMap[*lpSrc]; 

return TRUE; 

 
BOOL CDibImage::InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
unsigned char* lpSrc; // 指向源图像的指针
LONG lTemp; // 临时变量
LONG i; // 循环变量 
LONG j;
BYTE bMap[256]; // 灰度映射表
LONG lCount[256]; // 灰度映射表 
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 

for (i = 0; i < 256; i ++) // 重置计数为0 
lCount[i] = 0; 

// 计算各个灰度值的计数 
for (i = 0; i < lHeight; i ++) 
for (j = 0; j < lWidth; j ++) 
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j; 
lCount[*(lpSrc)]++; 

// 计算灰度映射表 
for (i = 0; i < 256; i++) 
lTemp = 0;
for (j = 0; j <= i ; j++) 
lTemp += lCount[j]; 

// 计算对应的新灰度值 
bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth); 

for(i = 0; i < lHeight; i++) // 每行 
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值 
*lpSrc = bMap[*lpSrc]; 

return TRUE; 

////////////////////////////////////////////////////////////////////// 
// 图像几何变换函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::TranslationDIB1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
LONG lXOffset, LONG lYOffset) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向要复制区域的指针 
LPSTR lpNewDIBBits; // 指向复制图像的指针 
HLOCAL hNewDIBBits; 
LONG i; // 象素在新DIB中的坐标 
LONG j;
LONG i0; // 象素在源DIB中的坐标 
LONG j0;
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向新DIB第i行,第j个象素的指针 
// 注意由于DIB中图像第一行其实保存在最后一行的位置,因此lpDst 
// 值不是(char *)lpNewDIBBits + lLineBytes * i + j,而是 
// (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j 
lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 计算该象素在源DIB中的坐标 
i0 = i - lXOffset; 
j0 = j - lYOffset; 

// 判断是否在源图范围内 
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
// 指向源DIB第i0行,第j0个象素的指针 
// 同样要注意DIB上下倒置的问题 
lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
*lpDst = *lpSrc; // 复制象素 
else 
// 对于源图中没有的象素,直接赋值为255 
* ((unsigned char*)lpDst) = 255; 

// 复制平移后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 
return TRUE; 

 
BOOL CDibImage::TranslationDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
LONG lXOffset, LONG lYOffset) 
{
CRect rectSrc; // 平移后剩余图像在源图像中的位置(矩形区域)
CRect rectDst; // 平移后剩余图像在新图像中的位置(矩形区域)
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向要复制区域的指针
LPSTR lpNewDIBBits; // 指向复制图像的指针 
HLOCAL hNewDIBBits; 
BOOL bVisible; // 指明图像是否全部移去可视区间
LONG i; // 循环变量
LONG lLineBytes; // 图像每行的字节数 

lLineBytes = WIDTHBYTES(lWidth * 8); // 计算图像每行的字节数
bVisible = TRUE; // 赋初值 

// 计算rectSrc和rectDst的X坐标 
if (lXOffset <= -lWidth) 
{
bVisible = FALSE; // X轴方向全部移出可视区域 
else if (lXOffset <= 0) 
{
rectDst.left = 0; // 移动后,有图区域左上角X坐标为0 

// 移动后,有图区域右下角X坐标为lWidth - |lXOffset| = lWidth + lXOffset 
rectDst.right = lWidth + lXOffset; 
else if (lXOffset < lWidth) 
{
rectDst.left = lXOffset; // 移动后,有图区域左上角X坐标为lXOffset
rectDst.right = lWidth; // 移动后,有图区域右下角X坐标为lWidth 
else 
{
bVisible = FALSE; // X轴方向全部移出可视区域 

// 平移后剩余图像在源图像中的X坐标 
rectSrc.left = rectDst.left - lXOffset; 
rectSrc.right = rectDst.right - lXOffset; 

// 计算rectSrc和rectDst的Y坐标 
if (lYOffset <= -lHeight) 
{
bVisible = FALSE; // Y轴方向全部移出可视区域 
else if (lYOffset <= 0) 
{
rectDst.top = 0; // 移动后,有图区域左上角Y坐标为0 

// 移动后,有图区域右下角Y坐标为lHeight - |lYOffset| = lHeight + lYOffset 
rectDst.bottom = lHeight + lYOffset; 
else if (lYOffset < lHeight) 
{
rectDst.top = lYOffset; // 移动后,有图区域左上角Y坐标为lYOffset
rectDst.bottom = lHeight; // 移动后,有图区域右下角Y坐标为lHeight 
else 
{
bVisible = FALSE; // X轴方向全部移出可视区域 

// 平移后剩余图像在源图像中的Y坐标 
rectSrc.top = rectDst.top - lYOffset; 
rectSrc.bottom = rectDst.bottom - lYOffset; 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lLineBytes * lHeight); 

if (bVisible) // 如果有部分图像可见 
// 平移图像 
for(i = 0; i < (rectSrc.bottom - rectSrc.top); i++) 
// 要复制区域的起点,注意由于DIB图像内容是上下倒置的,第一行内容是保存 
// 在最后一行,因此复制区域的起点不是lpDIBBits + lLineBytes * (i + 
// rectSrc.top) + rectSrc.left,而是 lpDIBBits + lLineBytes * 
// (lHeight - i - rectSrc.top - 1) + rectSrc.left。 

lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - i - rectSrc.top 
- 1) + rectSrc.left; 

// 要目标区域的起点,同样注意上下倒置的问题。 
lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - i - rectDst.top 
- 1) + rectDst.left; 

// 拷贝每一行,宽度为rectSrc.right - rectSrc.left 
memcpy(lpDst, lpSrc, rectSrc.right - rectSrc.left); 


// 复制平移后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 
return TRUE; 

 
BOOL CDibImage::MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
BOOL bDirection) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向要复制区域的指针
LPSTR lpBits; // 指向复制图像的指针 
HLOCAL hBits;
LONG i; // 循环变量 
LONG j;
LONG lLineBytes; // 图像每行的字节数

lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数
hBits = LocalAlloc(LHND, lLineBytes); // 暂时分配内存,以保存一行图像 
if (hBits == NULL) 
return FALSE; 

lpBits = (char * )LocalLock(hBits); 

// 判断镜像方式 
if (bDirection) // 水平镜像 
{
// 针对图像每行进行操作 
for(i = 0; i < lHeight; i++) 
// 针对每行图像左半部分进行操作 
for(j = 0; j < lWidth / 2; j++) 
{
// 指向倒数第i行,第j个象素的指针 
lpSrc = (char *)lpDIBBits + lLineBytes * i + j;
// 指向倒数第i行,倒数第j个象素的指针 
lpDst = (char *)lpDIBBits + lLineBytes * (i + 1) - j; 

// 备份一个象素 
*lpBits = *lpDst; 

// 将倒数第i行,第j个象素复制到倒数第i行,倒数第j个象素 
*lpDst = *lpSrc;
// 将倒数第i行,倒数第j个象素复制到倒数第i行,第j个象素 
*lpSrc = *lpBits; 
}
else // 垂直镜像 
// 针对上半图像进行操作 
for(i = 0; i < lHeight / 2; i++) 
{
// 指向倒数第i行象素起点的指针 
lpSrc = (char *)lpDIBBits + lLineBytes * i;
// 指向第i行象素起点的指针 
lpDst = (char *)lpDIBBits + lLineBytes * (lHeight - i - 1); 

// 备份一行,宽度为lWidth 
memcpy(lpBits, lpDst, lLineBytes); 

// 将倒数第i行象素复制到第i行 
memcpy(lpDst, lpSrc, lLineBytes);
// 将第i行象素复制到倒数第i行 
memcpy(lpSrc, lpBits, lLineBytes);

LocalUnlock(hBits); 
LocalFree(hBits); 
return TRUE; 

 
BOOL CDibImage::TransposeDIB(LPSTR lpDIB) 
{
LONG lWidth; // 图像的宽度 
LONG lHeight; // 图像的高度
LPSTR lpDIBBits; // 指向源图像的指针
LPSTR lpSrc; // 指向源象素的指针
LPSTR lpDst; // 指向转置图像对应象素的指针
LPSTR lpNewDIBBits; // 指向转置图像的指针 
HLOCAL hNewDIBBits; 
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) 
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 
LONG i;
LONG j;
LONG lLineBytes; // 图像每行的字节数 
LONG lNewLineBytes; // 新图像每行的字节数 

lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
lpbmc = (LPBITMAPCOREHEADER)lpDIB; 


lpDIBBits = FindDIBBits(lpDIB); // 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB); // 获取图像的"宽度"(4的倍数) 
lHeight = DIBHeight(lpDIB); // 获取图像的高度 
lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 
lNewLineBytes = WIDTHBYTES(lHeight * 8); // 计算新图像每行的字节数 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lNewLineBytes); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

for(i = 0; i < lHeight; i++) // 针对图像每行进行操作 
{
for(j = 0; j < lWidth; j++) // 针对每行图像每列进行操作 
{
// 指向源DIB第i行,第j个象素的指针 
lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;

// 指向转置DIB第j行,第i个象素的指针 
// 注意此处lWidth和lHeight是源DIB的宽度和高度,应该互换 
lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lWidth - 1 - j) + i; 

// 复制象素 
*lpDst = *lpSrc;
}

// 复制转置后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lNewLineBytes); 

// 互换DIB中图像的高宽 
if (IS_WIN30_DIB(lpDIB)) 
// 对于Windows 3.0 DIB 
lpbmi->biWidth = lHeight;
lpbmi->biHeight = lWidth; 
else 
// 对于其它格式的DIB 
lpbmc->bcWidth = (unsigned short) lHeight; 
lpbmc->bcHeight = (unsigned short) lWidth; 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 
return TRUE; 

 
HGLOBAL CDibImage::ZoomDIB(LPSTR lpDIB, float fXZoomRatio, float fYZoomRatio) 
LONG lWidth; // 源图像的宽度 
LONG lHeight; // 源图像的高度
LONG lNewWidth; // 缩放后图像的宽度 
LONG lNewHeight; // 缩放后图像的高度
LONG lNewLineBytes; // 缩放后图像的宽度(lNewWidth",必须是4的倍数)
LPSTR lpDIBBits; // 指向源图像的指针
LPSTR lpSrc; // 指向源象素的指针
HDIB hDIB; // 缩放后新DIB句柄
LPSTR lpDst; // 指向缩放图像对应象素的指针
LPSTR lpNewDIB; // 指向缩放图像的指针 
LPSTR lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针

LONG i; // 循环变量(象素在新DIB中的坐标) 
LONG j;
LONG i0; // 象素在源DIB中的坐标 
LONG j0; 


LONG lLineBytes; // 图像每行的字节数
lpDIBBits = FindDIBBits(lpDIB); // 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB); // 获取图像的宽度 
lLineBytes = WIDTHBYTES(lWidth * 8); // 计算图像每行的字节数 
lHeight = DIBHeight(lpDIB); // 获取图像的高度 

// 计算缩放后的图像实际宽度 
// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分 
lNewWidth = (LONG) (DIBWidth(lpDIB) * fXZoomRatio + 0.5); 

// 计算新图像每行的字节数 
lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 

// 计算缩放后的图像高度 
lNewHeight = (LONG) (lHeight * fYZoomRatio + 0.5); 

// 分配内存,以保存新DIB 
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + 
*(LPDWORD)lpDIB + PaletteSize(lpDIB));
if (hDIB == NULL) 
return NULL; 

lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB); 

// 复制DIB信息头和调色板 
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 

// 找到新DIB象素起始位置 
lpNewDIBBits = 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; 

for(i = 0; i < lNewHeight; i++) // 针对图像每行进行操作 
{
for(j = 0; j < lNewWidth; j++) // 针对图像每列进行操作 
{
// 指向新DIB第i行,第j个象素的指针 
// 注意此处宽度和高度是新DIB的宽度和高度 
lpDst = (char *)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 = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
// 复制象素 
*lpDst = *lpSrc; 
else 
// 对于源图中没有的象素,直接赋值为255 
* ((unsigned char*)lpDst) = 255; 
}
}

return hDIB; 

 
HGLOBAL CDibImage::RotateDIB(LPSTR lpDIB, int iRotateAngle) 
{
LONG lWidth; // 源图像的宽度 
LONG lHeight; // 源图像的高度
LONG lNewWidth; // 旋转后图像的宽度 
LONG lNewHeight; // 旋转后图像的高度
LONG lLineBytes; // 图像每行的字节数
LONG lNewLineBytes; // 旋转后图像的宽度(lNewWidth",必须是4的倍数)
LPSTR lpDIBBits; // 指向源图像的指针
LPSTR lpSrc; // 指向源象素的指针
HDIB hDIB; // 旋转后新DIB句柄
LPSTR lpDst; // 指向旋转图像对应象素的指针
LPSTR lpNewDIB; // 指向旋转图像的指针 
LPSTR lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 

LONG i; // 循环变量(象素在新DIB中的坐标) 
LONG j;
LONG i0; // 象素在源DIB中的坐标 
LONG j0;

float fRotateAngle; // 旋转角度(弧度)
float fSina, fCosa; // 旋转角度的正弦和余弦
// 源图四个角的坐标(以图像中心为坐标系原点) 
float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点) 
float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4; 
float f1,f2; 

lpDIBBits = FindDIBBits(lpDIB); // 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB); // 获取图像的"宽度"(4的倍数)
lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数
lHeight = DIBHeight(lpDIB); // 获取图像的高度 

// 将旋转角度从度转换到弧度 
fRotateAngle = (float) RADIAN(iRotateAngle);
fSina = (float) sin((double)fRotateAngle); // 计算旋转角度的正弦 
fCosa = (float) cos((double)fRotateAngle); // 计算旋转角度的余弦 

// 计算原图的四个角的坐标(以图像中心为坐标系原点) 
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 = fCosa * fSrcX1 + fSina * fSrcY1; 
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1; 
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2; 
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2; 
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3; 
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3; 
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4; 
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4; 

// 计算旋转后的图像实际宽度 
lNewWidth = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5); 

// 计算新图像每行的字节数 
lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 

// 计算旋转后的图像高度 
lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5); 

// 两个常数,这样不用以后每次都计算了 
f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina 
+ 0.5 * (lWidth - 1)); 
f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa 
+ 0.5 * (lHeight - 1)); 

// 分配内存,以保存新DIB 
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + 
*(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
if (hDIB == NULL) 
return NULL; 

lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB); 

// 复制DIB信息头和调色板 
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 

// 找到新DIB象素起始位置 
lpNewDIBBits = 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; 

for(i = 0; i < lNewHeight; i++) // 针对图像每行进行操作 
{
for(j = 0; j < lNewWidth; j++) // 针对图像每列进行操作 
// 指向新DIB第i行,第j个象素的指针 
// 注意此处宽度和高度是新DIB的宽度和高度 
lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; 

// 计算该象素在源DIB中的坐标 
i0 = (LONG) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5); 
j0 = (LONG) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5); 

// 判断是否在源图范围内 
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
// 指向源DIB第i0行,第j0个象素的指针 
lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0; 

// 复制象素 
*lpDst = *lpSrc; 
else 
// 对于源图中没有的象素,直接赋值为255 
* ((unsigned char*)lpDst) = 255; 
}
}

return hDIB; 

 
HGLOBAL CDibImage::RotateDIB2(LPSTR lpDIB, int iRotateAngle) 
{
LONG lWidth; // 源图像的宽度 
LONG lHeight; // 源图像的高度
LONG lNewWidth; // 旋转后图像的宽度 
LONG lNewHeight; // 旋转后图像的高度 
LONG lNewLineBytes; // 旋转后图像的宽度(lNewWidth",必须是4的倍数)
LPSTR lpDIBBits; // 指向源图像的指针
HDIB hDIB; // 旋转后新DIB句柄
LPSTR lpDst; // 指向旋转图像对应象素的指针
LPSTR lpNewDIB; // 指向旋转图像的指针 
LPSTR lpNewDIBBits;
LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 

LONG i; // 循环变量(象素在新DIB中的坐标) 
LONG j;
FLOAT i0; // 象素在源DIB中的坐标 
FLOAT j0;

float fRotateAngle; // 旋转角度(弧度)
float fSina, fCosa; // 旋转角度的正弦和余弦
// 源图四个角的坐标(以图像中心为坐标系原点) 
float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点) 
float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4; 
float f1,f2; 


lpDIBBits = FindDIBBits(lpDIB); // 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB); // 获取图像的宽度 
lHeight = DIBHeight(lpDIB); // 获取图像的高度 

// 将旋转角度从度转换到弧度 
fRotateAngle = (float) RADIAN(iRotateAngle); 

fSina = (float) sin((double)fRotateAngle); // 计算旋转角度的正弦 
fCosa = (float) cos((double)fRotateAngle); // 计算旋转角度的余弦 

// 计算原图的四个角的坐标(以图像中心为坐标系原点) 
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 = fCosa * fSrcX1 + fSina * fSrcY1; 
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1; 
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2; 
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2; 
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3; 
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3; 
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4; 
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4; 

// 计算旋转后的图像实际宽度 
lNewWidth = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5); 
lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 

// 计算旋转后的图像高度 
lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5); 

f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina 
+ 0.5 * (lWidth - 1)); 
f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa 
+ 0.5 * (lHeight - 1)); 

// 分配内存,以保存新DIB 
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + 
*(LPDWORD)lpDIB + PaletteSize(lpDIB));
if (hDIB == NULL) 
return NULL; 

lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB); 

// 复制DIB信息头和调色板 
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 

// 找到新DIB象素起始位置 
lpNewDIBBits = 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; 

for(i = 0; i < lNewHeight; i++) // 针对图像每行进行操作 
{
for(j = 0; j < lNewWidth; j++) // 针对图像每列进行操作 
// 指向新DIB第i行,第j个象素的指针 
// 注意此处宽度和高度是新DIB的宽度和高度 
lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; 

// 计算该象素在源DIB中的坐标 
i0 = -((float) j) * fSina + ((float) i) * fCosa + f2; 
j0 = ((float) j) * fCosa + ((float) i) * fSina + f1; 

// 利用双线性插值算法来估算象素值 
*lpDst = Interpolation (lpDIBBits, lWidth, lHeight, j0, i0);
}

return hDIB; 

 
unsigned char CDibImage::Interpolation (LPSTR lpDIBBits, LONG lWidth, 
LONG lHeight, FLOAT x, FLOAT y) 
// 四个最临近象素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2) 
LONG i1, i2; 
LONG j1, j2; 

unsigned char f1, f2, f3, f4; // 四个最临近象素值
unsigned char f12, f34; // 二个插值中间值

// 定义一个值,当象素坐标相差小于改值时认为坐标相同 
FLOAT EXP;

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

EXP = (FLOAT) 0.0001; 

// 计算四个最临近象素的坐标 
i1 = (LONG) x; 
i2 = i1 + 1; 
j1 = (LONG) y; 
j2 = j1 + 1; 

// 根据不同情况分别处理 
if( (x < 0) || (x > lWidth - 1) || (y < 0) || (y > lHeight - 1)) 
{
return 255; // 要计算的点不在源图范围内,直接返回255。 
else 
if (fabs(x - lWidth + 1) <= EXP) 
// 要计算的点在图像右边缘上 
if (fabs(y - lHeight + 1) <= EXP) 
// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值 
f1 = *((unsigned char *)lpDIBBits + lLineBytes * 
(lHeight - 1 - j1) + i1); 
return f1; 
else 
// 在图像右边缘上且不是最后一点,直接一次插值即可 
f1 = *((unsigned char *)lpDIBBits + lLineBytes * 
(lHeight - 1 - j1) + i1); 
f3 = *((unsigned char *)lpDIBBits + lLineBytes * 
(lHeight - 1 - j1) + i2); 

// 返回插值结果 
return ((unsigned char) (f1 + (y -j1) * (f3 - f1))); 
else if (fabs(y - lHeight + 1) <= EXP) 
// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可 
f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1); 
f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1); 

// 返回插值结果 
return ((unsigned char) (f1 + (x -i1) * (f2 - f1))); 
else 
// 计算四个最临近象素值 
f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1); 
f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1); 
f3 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i2); 
f4 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i2); 

// 插值1 
f12 = (unsigned char) (f1 + (x - i1) * (f2 - f1));
// 插值2 
f34 = (unsigned char) (f3 + (x - i1) * (f4 - f3));
// 插值3 
return ((unsigned char) (f12 + (y -j1) * (f34 - f12))); 

////////////////////////////////////////////////////////////////////// 
// 图像正交变换函数 
////////////////////////////////////////////////////////////////////// 
 
VOID CDibImage::FFT(complex<double> * TD, complex<double> * FD, int r) 
{
LONG count; // 付立叶变换点数
int i,j,k; // 循环变量 
int bfsize,p;
double angle; // 角度
complex<double> *W,*X1,*X2,*X; 

count = 1 << r; // 计算付立叶变换点数 

// 分配运算所需存储器 
W = new complex<double>[count / 2]; 
X1 = new complex<double>[count]; 
X2 = new complex<double>[count]; 

// 计算加权系数 
for(i = 0; i < count / 2; i++) 
angle = -i * PI * 2 / count; 
W[i] = complex<double> (cos(angle), sin(angle)); 

// 将时域点写入X1 
memcpy(X1, TD, sizeof(complex<double>) * count); 

// 采用蝶形算法进行快速付立叶变换 
for(k = 0; k < r; k++) 
for(j = 0; j < 1 << k; j++) 
bfsize = 1 << (r-k); 
for(i = 0; i < bfsize / 2; i++) 
p = j * bfsize; 
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2]; 
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) 
* W[i * (1<<k)]; 
X = X1; 
X1 = X2; 
X2 = X; 

// 重新排序 
for(j = 0; j < count; j++) 
p = 0; 
for(i = 0; i < r; i++) 
if (j&(1<<i)) 
p+=1<<(r-i-1); 
FD[j]=X1[p]; 

delete W; 
delete X1; 
delete X2; 

 
VOID CDibImage::IFFT(complex<double> * FD, complex<double> * TD, int r) 
{
LONG count; // 付立叶变换点数
int i; // 循环变量
complex<double> *X;

count = 1 << r; // 计算付立叶变换点数 
X = new complex<double>[count]; // 分配运算所需存储器 
memcpy(X, FD, sizeof(complex<double>) * count); // 将频域点写入X 

// 求共轭 
for(i = 0; i < count; i++) 
X[i] = complex<double> (X[i].real(), -X[i].imag()); 

FFT(X, TD, r); // 调用快速付立叶变换 

// 求时域点的共轭 
for(i = 0; i < count; i++) 
TD[i] = complex<double> (TD[i].real() / count, -TD[i].imag() / count); 

delete X; 

 
BOOL CDibImage::Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
unsigned char* lpSrc; // 指向源图像的指针 
double dTemp;
LONG i; // 循环变量 
LONG j;
LONG w; // 进行付立叶变换的宽度(2的整数次方) 
LONG h; // 进行付立叶变换的高度(2的整数次方)
int wp; 
int hp; 

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); // 计算图像每行的字节数 

// 赋初值 
w = 1; 
h = 1; 
wp = 0; 
hp = 0; 

// 计算进行付立叶变换的宽度和高度(2的整数次方) 
while(w * 2 <= lWidth) 
w *= 2; 
wp++; 

while(h * 2 <= lHeight) 
h *= 2; 
hp++; 

complex<double> *TD = new complex<double>[w * h]; 
complex<double> *FD = new complex<double>[w * h]; 

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 给时域赋值 
TD[j + w * i] = complex<double>(*(lpSrc), 0); 

for(i = 0; i < h; i++) 
// 对y方向进行快速付立叶变换 
FFT(&TD[w * i], &FD[w * i], wp); 

// 保存变换结果 
for(i = 0; i < h; i++) 
for(j = 0; j < w; j++) 
TD[i + h * j] = FD[j + w * i]; 

for(i = 0; i < w; i++) 
// 对x方向进行快速付立叶变换 
FFT(&TD[i * h], &FD[i * h], hp); 

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
// 计算频谱 
dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() + 
FD[j * h + i].imag() * FD[j * h + i].imag()) / 100; 
if (dTemp > 255) 
dTemp = 255; 

// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个 
// 象素的指针,此处不直接取i和j,是为了将变换后的原点移到中心 
// lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight-1-i) + j; 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * 
(lHeight - 1 - (i<h/2 ? i+h/2 : i-h/2)) + (j<w/2 ? j+w/2 : j-w/2); 

// 更新源图像 
* (lpSrc) = (BYTE)(dTemp); 

delete TD; 
delete FD; 
return TRUE; 

 
VOID CDibImage::DCT(double *f, double *F, int r) 
{
LONG count; // 离散余弦变换点数
int i; // 循环变量
double dTemp;
complex<double> *X; 

count = 1<<r; // 计算离散余弦变换点数

X = new complex<double>[count*2];
memset(X, 0, sizeof(complex<double>) * count * 2); // 赋初值为0 

// 将时域点写入数组X 
for(i=0;i<count;i++) 
X[i] = complex<double> (f[i], 0); 

FFT(X,X,r+1); // 调用快速付立叶变换
dTemp = 1/sqrt(count); // 调整系数
F[0] = X[0].real() * dTemp; // 求F[0]
dTemp *= sqrt(2); 

// 求F[u]
for(i = 1; i < count; i++) 
F[i]=(X[i].real() * cos(i*PI/(count*2)) + X[i].imag() * 
sin(i*PI/(count*2))) * dTemp; 

delete X; 

 
VOID CDibImage::IDCT(double *F, double *f, int r) 
LONG count; // 离散余弦反变换点数 
int i; // 循环变量 
double dTemp, d0;
complex<double> *X; 

count = 1<<r; // 计算离散余弦变换点数 

X = new complex<double>[count*2];
memset(X, 0, sizeof(complex<double>) * count * 2); // 赋初值为0 

// 将频域变换后点写入数组X 
for(i=0;i<count;i++) 
X[i] = complex<double> (F[i] * cos(i*PI/(count*2)), F[i] * 
sin(i*PI/(count*2))); 

IFFT(X,X,r+1); // 调用快速付立叶反变换 

// 调整系数 
dTemp = sqrt(2.0/count); 
d0 = (sqrt(1.0/count) - dTemp) * F[0]; 

for(i = 0; i < count; i++) 
f[i] = d0 + X[i].real()* dTemp * 2 * count; 

delete X; 

 
BOOL CDibImage::DIBDct(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
unsigned char* lpSrc; // 指向源图像的指针
LONG i; // 循环变量 
LONG j;
LONG w; // 进行付立叶变换的宽度(2的整数次方) 
LONG h; // 进行付立叶变换的高度(2的整数次方) 
double dTemp;
int wp; 
int hp; 

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 赋初值 
w = 1; 
h = 1; 
wp = 0; 
hp = 0; 

// 计算进行离散余弦变换的宽度和高度(2的整数次方) 
while(w * 2 <= lWidth) 
w *= 2; 
wp++; 

while(h * 2 <= lHeight) 
h *= 2; 
hp++; 

double *f = new double[w * h]; 
double *F = new double[w * h]; 

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 给时域赋值 
f[j + i * w] = *(lpSrc); 

for(i = 0; i < h; i++) 
// 对y方向进行离散余弦变换 
DCT(&f[w * i], &F[w * i], wp); 

// 保存计算结果 
for(i = 0; i < h; i++) 
for(j = 0; j < w; j++) 
f[j * h + i] = F[j + w * i]; 

for(j = 0; j < w; j++) 
// 对x方向进行离散余弦变换 
DCT(&f[j * h], &F[j * h], hp); 
}

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
dTemp = fabs(F[j*h+i]); // 计算频谱 

// 判断是否超过255 
if (dTemp > 255) 
dTemp = 255; 

// 指向DIB第y行,第x个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 更新源图像 
* (lpSrc) = (BYTE)(dTemp); 

delete f; 
delete F; 

return TRUE; 

 
VOID CDibImage::WALSH(double *f, double *F, int r) 
{
LONG count; // 沃尔什-哈达玛变换点数
int i,j,k; // 循环变量 
int bfsize,p;
double *X1,*X2,*X; 

count = 1 << r; // 计算快速沃尔什变换点数
X1 = new double[count]; // 分配运算所需的数组 
X2 = new double[count]; // 分配运算所需的数组 

memcpy(X1, f, sizeof(double) * count); // 将时域点写入数组X1 

// 蝶形运算 
for(k = 0; k < r; k++) 
for(j = 0; j < 1<<k; j++) 
bfsize = 1 << (r-k); 
for(i = 0; i < bfsize / 2; i++) 
p = j * bfsize; 
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2]; 
X2[i + p + bfsize / 2] = X1[i + p] - X1[i + p + bfsize / 2]; 

// 互换X1和X2 
X = X1; 
X1 = X2; 
X2 = X; 

// 调整系数 
for(j = 0; j < count; j++) 
p = 0; 
for(i = 0; i < r; i++) 
if (j & (1<<i)) 
p += 1 << (r-i-1); 

F[j] = X1[p] / count; 

delete X1; 
delete X2; 

 
VOID CDibImage::IWALSH(double *F, double *f, int r) 
{
LONG count; // 变换点数
int i; // 循环变量 

count = 1 << r; // 计算变换点数
WALSH(F, f, r); // 调用快速沃尔什-哈达玛变换进行反变换 

for(i = 0; i < count; i++) // 调整系数 
f[i] *= count; 

 
BOOL CDibImage::DIBWalsh(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
unsigned char* lpSrc; // 指向源图像的指针
LONG i,j; // 循环变量 
LONG w; // 进行付立叶变换的宽度(2的整数次方) 
LONG h; // 进行付立叶变换的高度(2的整数次方) 
double dTemp;
int wp; 
int hp; 

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 赋初值 
w = 1; 
h = 1; 
wp = 0; 
hp = 0; 

// 计算进行离散余弦变换的宽度和高度(2的整数次方) 
while(w * 2 <= lWidth) 
w *= 2; 
wp++; 
}
while(h * 2 <= lHeight) 
h *= 2; 
hp++; 

double *f = new double[w * h]; 
double *F = new double[w * h]; 

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 给时域赋值 
f[j + i * w] = *(lpSrc); 

for(i = 0; i < h; i++) 
// 对y方向进行沃尔什-哈达玛变换 
WALSH(f + w * i, F + w * i, wp); 

// 保存计算结果 
for(i = 0; i < h; i++) 
for(j = 0; j < w; j++) 
f[j * h + i] = F[j + w * i]; 

for(j = 0; j < w; j++) 
// 对x方向进行沃尔什-哈达玛变换 
WALSH(f + j * h, F + j * h, hp); 

for(i = 0; i < h; i++) // 行 
{
for(j = 0; j < w; j++) // 列 
{
dTemp = fabs(F[j * h + i] * 1000); // 计算频谱
if (dTemp > 255)
{
dTemp = 255;

// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 更新源图像 
* (lpSrc) = (BYTE)(dTemp); 

delete f; 
delete F; 

return TRUE; 

 
BOOL CDibImage::DIBWalsh1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
unsigned char* lpSrc; // 指向源图像的指针 
LONG i,j; // 循环变量
LONG w; // 进行付立叶变换的宽度(2的整数次方) 
LONG h; // 进行付立叶变换的高度(2的整数次方) 
double dTemp;
int wp; 
int hp; 

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 赋初值 
w = 1; 
h = 1; 
wp = 0; 
hp = 0; 

// 计算进行离散余弦变换的宽度和高度(2的整数次方) 
while(w * 2 <= lWidth) 
w *= 2; 
wp++; 
}
while(h * 2 <= lHeight) 
h *= 2; 
hp++; 

double *f = new double[w * h]; 
double *F = new double[w * h]; 

for(i = 0; i < w; i++) // 列 
for(j = 0; j < h; j++) // 行 
// 指向DIB第j行,第i个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i; 

// 给时域赋值 
f[j + i * w] = *(lpSrc); 

// 调用快速沃尔什-哈达玛变换 
WALSH(f, F, wp + hp); 

for(i = 0; i < w; i++) // 列 
{
for(j = 0; j < h; j++) // 行 
{
dTemp = fabs(F[i * w + j] * 1000); // 计算频谱 
if (dTemp > 255) 
dTemp = 255; 

// 指向DIB第j行,第i个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i; 

// 更新源图像 
* (lpSrc) = (BYTE)(dTemp); 

delete f; 
delete F; 

return TRUE; 

////////////////////////////////////////////////////////////////////// 
// 图像模板变换函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::Template(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
int iTempH, int iTempW, int iTempMX, int iTempMY, 
FLOAT * fpArray, FLOAT fCoef) 
{
LPSTR lpNewDIBBits; // 指向复制图像的指针 
HLOCAL hNewDIBBits;
unsigned char* lpSrc; // 指向源图像的指针
unsigned char* lpDst; // 指向要复制区域的指针
LONG i,j,k,l; // 循环变量
FLOAT fResult; // 计算结果 

LONG lLineBytes; // 图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化图像为原始图像 
memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight); 

for(i = iTempMY; i < lHeight - iTempH + iTempMY + 1; i++) // 行(除去边缘几行) 
{
for(j = iTempMX; j < lWidth - iTempW + iTempMX + 1; j++)// 列(除去边缘几列) 
// 指向新DIB第i行,第j个象素的指针 
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

fResult = 0; 

for (k = 0; k < iTempH; k++) 
for (l = 0; l < iTempW; l++) 
// 指向DIB第i - iTempMY + k行,第j - iTempMX + l个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 
- i + iTempMY - k) + j - iTempMX + l; 

// 保存象素值 
fResult += (* lpSrc) * fpArray[k * iTempW + l]; 

fResult *= fCoef; // 乘上系数
fResult = (FLOAT ) fabs(fResult); // 取绝对值 
if(fResult > 255) 
* lpDst = 255; 
else 
* lpDst = (unsigned char) (fResult + 0.5); 
}

// 复制变换后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

 
BOOL CDibImage::MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
int iFilterH, int iFilterW, int iFilterMX, int iFilterMY) 
{
unsigned char* lpSrc; // 指向源图像的指针
unsigned char* lpDst; // 指向要复制区域的指针
LPSTR lpNewDIBBits; // 指向复制图像的指针 
HLOCAL hNewDIBBits;
unsigned char * aValue; // 指向滤波器数组的指针 
HLOCAL hArray;
LONG i,j,k,l; // 循环变量

LONG lLineBytes; // 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化图像为原始图像 
memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight); 

// 暂时分配内存,以保存滤波器数组 
hArray = LocalAlloc(LHND, iFilterH * iFilterW); 
if (hArray == NULL) 
LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return FALSE; 

aValue = (unsigned char * )LocalLock(hArray); 

// 开始中值滤波 
// 行(除去边缘几行) 
for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++) 
// 列(除去边缘几列) 
for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++) 
// 指向新DIB第i行,第j个象素的指针 
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; 

// 读取滤波器数组 
for (k = 0; k < iFilterH; k++) 
for (l = 0; l < iFilterW; l++) 
// 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 
- i + iFilterMY - k) + j - iFilterMX + l; 

// 保存象素值 
aValue[k * iFilterW + l] = *lpSrc; 

// 获取中值 
* lpDst = GetMedianNum(aValue, iFilterH * iFilterW); 

// 复制变换后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 
LocalUnlock(hArray); 
LocalFree(hArray); 

return TRUE; 

 
unsigned char CDibImage::GetMedianNum(unsigned char * bArray, int iFilterLen) 
int i,j; // 循环变量 
unsigned char bTemp; 

// 用冒泡法对数组进行排序 
for (j = 0; j < iFilterLen - 1; j ++) 
for (i = 0; i < iFilterLen - j - 1; i ++) 
if (bArray[i] > bArray[i + 1]) 
// 互换 
bTemp = bArray[i]; 
bArray[i] = bArray[i + 1]; 
bArray[i + 1] = bTemp; 

// 计算中值 
if ((iFilterLen & 1) > 0) 
// 数组有奇数个元素,返回中间一个元素 
bTemp = bArray[(iFilterLen + 1) / 2]; 
else 
// 数组有偶数个元素,返回中间两个元素平均值 
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; 

return bTemp; 

 
BOOL CDibImage::GradSharp(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre) 
{

unsigned char* lpSrc; // 指向源图像的指针 
unsigned char* lpSrc1; 
unsigned char* lpSrc2;
LONG i,j; // 循环变量 
LONG lLineBytes; // 图像每行的字节数 
BYTE bTemp; 

lLineBytes = WIDTHBYTES(lWidth * 8); 

for(i = 0; i < lHeight; i++) // 每行 
{
for(j = 0; j < lWidth; j++) // 每列 
// 指向DIB第i行,第j个象素的指针 
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 指向DIB第i+1行,第j个象素的指针 
lpSrc1 = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 2 - i) + j;
// 指向DIB第i行,第j+1个象素的指针 
lpSrc2 = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) 
+ j + 1; 

bTemp = abs((*lpSrc)-(*lpSrc1)) + abs((*lpSrc)-(*lpSrc2)); 

// 判断是否小于阈值 
if (bTemp < 255) 
// 判断是否大于阈值,对于小于情况,灰度值不变。 
if (bTemp >= bThre) 
*lpSrc = bTemp; 
else 
*lpSrc = 255; 

return TRUE; 

 
BOOL CDibImage::ReplaceColorPal(LPSTR lpDIB, BYTE * bpColorsTable) 
{
int i; // 循环变量
WORD wNumColors; // 颜色表中的颜色数目
LPBITMAPINFO lpbmi; // 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO结构的指针 
BOOL bWinStyleDIB; // 表明是否是Win3.0 DIB的标记
BOOL bResult = FALSE; // 创建结果

lpbmi = (LPBITMAPINFO)lpDIB; // 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmc = (LPBITMAPCOREINFO)lpDIB; // 获取指向BITMAPCOREINFO结构的指针 
wNumColors = DIBNumColors(lpDIB); // 获取DIB中颜色表中的颜色数目 

if (wNumColors == 256) // 判断颜色数目是否是256色 
{
bWinStyleDIB = IS_WIN30_DIB(lpDIB); // 判断是否是WIN3.0的DIB 

// 读取伪彩色编码,更新DIB调色板 
for (i = 0; i < (int)wNumColors; i++) 
if (bWinStyleDIB) 
// 更新DIB调色板红色绿色蓝色分量 
lpbmi->bmiColors[i].rgbRed = bpColorsTable[i * 4]; 
lpbmi->bmiColors[i].rgbGreen = bpColorsTable[i * 4 + 1]; 
lpbmi->bmiColors[i].rgbBlue = bpColorsTable[i * 4 + 2]; 

// 更新DIB调色板保留位 
lpbmi->bmiColors[i].rgbReserved = 0; 
else 
// 更新DIB调色板红色绿色蓝色分量 
lpbmc->bmciColors[i].rgbtRed = bpColorsTable[i * 4]; 
lpbmc->bmciColors[i].rgbtGreen = bpColorsTable[i * 4 + 1]; 
lpbmc->bmciColors[i].rgbtBlue = bpColorsTable[i * 4 + 2]; 

return bResult;

////////////////////////////////////////////////////////////////////// 
// 图像形态学变换函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::ErosionDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, 
int nMode , int structure[3][3]) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits;
long i,j,n,m; //循环变量 
unsigned char pixel; //像素值 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

if(nMode == 0) 
//使用水平方向的结构元素进行腐蚀 
for(j = 0; j <lHeight; j++) 
for(i = 1;i <lWidth-1; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果源图像中当前点自身或者左右有一个点不是黑色, 
//则将目标图像中的当前点赋成白色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+n-1); 
if (pixel == 255 ) 
*lpDst = (unsigned char)255; 
break; 
}
else if(nMode == 1) 
//使用垂直方向的结构元素进行腐蚀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果源图像中当前点自身或者上下有一个点不是黑色, 
//则将目标图像中的当前点赋成白色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+(n-1)*lWidth); 
if (pixel == 255 ) 
*lpDst = (unsigned char)255; 
break; 
}
else 
//使用自定义的结构元素进行腐蚀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素和最上边和最下边的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色, 
//则将目标图像中的当前点赋成白色 
//注意在DIB图像中内容是上下倒置的 
for (m = 0;m < 3;m++ ) 
for (n = 0;n < 3;n++) 
if( structure[m][n] == -1) 
continue; 
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1)); 
if (pixel == 255 ) 
{
*lpDst = (unsigned char)255; 
break; 
}
// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

 
BOOL CDibImage::DilationDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode, 
int structure[3][3]) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits;
long i,j,m,n; //循环变量
unsigned char pixel; //像素值 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

if(nMode == 0) 
//使用水平方向的结构元素进行膨胀 
for(j = 0; j <lHeight; j++) 
for(i = 1;i <lWidth-1; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//源图像中当前点自身或者左右只要有一个点是黑色, 
//则将目标图像中的当前点赋成黑色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+n-1); 
if (pixel == 0 ) 
*lpDst = (unsigned char)0; 
break; 
}
else if(nMode == 1) 
//使用垂直方向的结构元素进行膨胀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//源图像中当前点自身或者上下只要有一个点是黑色, 
//则将目标图像中的当前点赋成黑色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+(n-1)*lWidth); 
if (pixel == 0 ) 
*lpDst = (unsigned char)0; 
break; 
}
else 
//使用自定义的结构元素进行膨胀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素和最上边和最下边的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//原图像中对应结构元素中为黑色的那些点中只要有一个是黑色, 
//则将目标图像中的当前点赋成黑色 
//注意在DIB图像中内容是上下倒置的 
for (m = 0;m < 3;m++ ) 
for (n = 0;n < 3;n++) 
if( structure[m][n] == -1) 
continue; 
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1)); 
if (pixel == 0 ) 
{
*lpDst = (unsigned char)0; 
break; 
}
// 复制膨胀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

 
BOOL CDibImage::OpenDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , 
int structure[3][3]) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits; 
long i,j,m,n; //循环变量
unsigned char pixel; //像素值 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

if(nMode == 0) 
//使用水平方向的结构元素进行腐蚀 
for(j = 0; j <lHeight; j++) 
for(i = 1;i <lWidth-1; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果源图像中当前点自身或者左右有一个点不是黑色, 
//则将目标图像中的当前点赋成白色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+n-1); 
if (pixel == 255 ) 
*lpDst = (unsigned char)255; 
break; 
}
else if(nMode == 1) 
//使用垂直方向的结构元素进行腐蚀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果源图像中当前点自身或者上下有一个点不是黑色, 
//则将目标图像中的当前点赋成白色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+(n-1)*lWidth); 
if (pixel == 255 ) 
*lpDst = (unsigned char)255; 
break; 
}
else 
//使用自定义的结构元素进行腐蚀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素和最上边和最下边的两列像素 
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成黑色 
*lpDst = (unsigned char)0; 

//如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色, 
//则将目标图像中的当前点赋成白色 
//注意在DIB图像中内容是上下倒置的 
for (m = 0;m < 3;m++ ) 
for (n = 0;n < 3;n++) 
if( structure[m][n] == -1) 
continue; 
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1)); 
if (pixel == 255 ) 
{
*lpDst = (unsigned char)255; 
break; 
}
// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

// 重新初始化新分配的内存,设定初始值为255 
//lpDst = (char *)lpNewDIBBits; 
//memset(lpDst, (BYTE)255, lWidth * lHeight); 

if(nMode == 0) 
//使用水平方向的结构元素进行膨胀 
for(j = 0; j <lHeight; j++) 
for(i = 1;i <lWidth-1; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//源图像中当前点自身或者左右只要有一个点是黑色, 
//则将目标图像中的当前点赋成黑色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+n-1); 
if (pixel == 0 ) 
*lpDst = (unsigned char)0; 
break; 
}
else if(nMode == 1) 
//使用垂直方向的结构元素进行膨胀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边 
// 的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//源图像中当前点自身或者上下只要有一个点是黑色, 
//则将目标图像中的当前点赋成黑色 
for (n = 0;n < 3;n++ ) 
pixel = *(lpSrc+(n-1)*lWidth); 
if (pixel == 0 ) 
*lpDst = (unsigned char)0; 
break; 
}
else 
//使用自定义的结构元素进行膨胀 
for(j = 1; j <lHeight-1; j++) 
for(i = 0;i <lWidth; i++) 
// 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边 
// 的两列像素和最上边和最下边的两列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//目标图像中的当前点先赋成白色 
*lpDst = (unsigned char)255; 

//原图像中对应结构元素中为黑色的那些点中只要有一个是黑色, 
//则将目标图像中的当前点赋成黑色 
//注意在DIB图像中内容是上下倒置的 
for (m = 0;m < 3;m++ ) 
for (n = 0;n < 3;n++) 
if( structure[m][n] == -1) 
continue; 
pixel = *(lpSrc + ((2-m)-1)*lWidth + (n-1)); 
if (pixel == 0 ) 
{
*lpDst = (unsigned char)0; 
break; 
}
// 复制膨胀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

 
BOOL CDibImage::CloseDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int nMode , 
int structure[3][3]) 
if (DilationDIB(lpDIBBits, lWidth, lHeight, nMode , structure)) 
if (ErosionDIB(lpDIBBits, lWidth, lHeight, nMode , structure)) 
return TRUE; 
return FALSE; 

 
BOOL CDibImage::ThiningDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits;
BOOL bModified; //脏标记
long i,j,m,n; //循环变量 

//四个条件 
BOOL bCondition1; 
BOOL bCondition2; 
BOOL bCondition3; 
BOOL bCondition4; 

unsigned char nCount; //计数器
unsigned char pixel; //像素值
unsigned char neighbour[5][5]; //5×5相邻区域像素值 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

bModified = TRUE; 
while(bModified) 
bModified = FALSE; 
// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

for(j = 2; j <lHeight-2; j++) 
for(i = 2;i <lWidth-2; i++) 
bCondition1 = FALSE; 
bCondition2 = FALSE; 
bCondition3 = FALSE; 
bCondition4 = FALSE; 

//由于使用5×5的结构元素,为防止越界,所以不处理外围的几行和几列像素 

// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i; 
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
continue; 
//如果源图像中当前点为白色,则跳过 
else if(pixel == 255) 
continue; 

//获得当前点相邻的5×5区域内像素值,白色用0代表,黑色用1代表 
for (m = 0;m < 5;m++ ) 
for (n = 0;n < 5;n++) 
neighbour[m][n] =(255 - (unsigned char)*(lpSrc + 
((4 - m) - 2)*lWidth + n - 2 )) / 255; 

//逐个判断条件。 
//判断2<=NZ(P1)<=6 
nCount = neighbour[1][1] + neighbour[1][2] + neighbour[1][3] + neighbour[2][1] + neighbour[2][3] + + neighbour[3][1] + neighbour[3][2] + neighbour[3][3]; 
if ( nCount >= 2 && nCount <=6) 
bCondition1 = TRUE; 

//判断Z0(P1)=1 
nCount = 0; 
if (neighbour[1][2] == 0 && neighbour[1][1] == 1) 
nCount++; 
if (neighbour[1][1] == 0 && neighbour[2][1] == 1) 
nCount++; 
if (neighbour[2][1] == 0 && neighbour[3][1] == 1) 
nCount++; 
if (neighbour[3][1] == 0 && neighbour[3][2] == 1) 
nCount++; 
if (neighbour[3][2] == 0 && neighbour[3][3] == 1) 
nCount++; 
if (neighbour[3][3] == 0 && neighbour[2][3] == 1) 
nCount++; 
if (neighbour[2][3] == 0 && neighbour[1][3] == 1) 
nCount++; 
if (neighbour[1][3] == 0 && neighbour[1][2] == 1) 
nCount++; 
if (nCount == 1) 
bCondition2 = TRUE; 

//判断P2*P4*P8=0 or Z0(p2)!=1 
if (neighbour[1][2]*neighbour[2][1]*neighbour[2][3] == 0) 
bCondition3 = TRUE; 
else 
nCount = 0; 
if (neighbour[0][2] == 0 && neighbour[0][1] == 1) 
nCount++; 
if (neighbour[0][1] == 0 && neighbour[1][1] == 1) 
nCount++; 
if (neighbour[1][1] == 0 && neighbour[2][1] == 1) 
nCount++; 
if (neighbour[2][1] == 0 && neighbour[2][2] == 1) 
nCount++; 
if (neighbour[2][2] == 0 && neighbour[2][3] == 1) 
nCount++; 
if (neighbour[2][3] == 0 && neighbour[1][3] == 1) 
nCount++; 
if (neighbour[1][3] == 0 && neighbour[0][3] == 1) 
nCount++; 
if (neighbour[0][3] == 0 && neighbour[0][2] == 1) 
nCount++; 
if (nCount != 1) 
bCondition3 = TRUE; 

//判断P2*P4*P6=0 or Z0(p4)!=1 
if (neighbour[1][2]*neighbour[2][1]*neighbour[3][2] == 0) 
bCondition4 = TRUE; 
else 
nCount = 0; 
if (neighbour[1][1] == 0 && neighbour[1][0] == 1) 
nCount++; 
if (neighbour[1][0] == 0 && neighbour[2][0] == 1) 
nCount++; 
if (neighbour[2][0] == 0 && neighbour[3][0] == 1) 
nCount++; 
if (neighbour[3][0] == 0 && neighbour[3][1] == 1) 
nCount++; 
if (neighbour[3][1] == 0 && neighbour[3][2] == 1) 
nCount++; 
if (neighbour[3][2] == 0 && neighbour[2][2] == 1) 
nCount++; 
if (neighbour[2][2] == 0 && neighbour[1][2] == 1) 
nCount++; 
if (neighbour[1][2] == 0 && neighbour[1][1] == 1) 
nCount++; 
if (nCount != 1) 
bCondition4 = TRUE; 
if(bCondition1 && bCondition2 && bCondition3 && bCondition4) 
*lpDst = (unsigned char)255; 
bModified = TRUE; 
else 
*lpDst = (unsigned char)0; 
// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 
// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

////////////////////////////////////////////////////////////////////// 
// 图像边缘与轮廓运算函数 
////////////////////////////////////////////////////////////////////// 

 
BOOL CDibImage::RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{

WatershedSegment(lpDIBBits,lWidth,lHeight); 







//ju_lei(lpDIBBits,lWidth,lHeight); 
return TRUE; 


 
BOOL CDibImage::SobelDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpDst1; // 指向缓存图像的指针 
LPSTR lpDst2;
LPSTR lpNewDIBBits1; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits1; 
LPSTR lpNewDIBBits2; 
HLOCAL hNewDIBBits2; 

long i,j; // 循环变量
int iTempH; // 模板高度
int iTempW; // 模板宽度
FLOAT fTempC; // 模板系数
int iTempMX; // 模板中心元素X坐标
int iTempMY; // 模板中心元素Y坐标
FLOAT aTemplate[9]; // 模板数组 

// 暂时分配内存,以保存新图像 
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits1 == NULL) 
return FALSE; 

lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1); 

// 暂时分配内存,以保存新图像 
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits2 == NULL) 
return FALSE; 

lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2); 

// 拷贝源图像到缓存图像中 
lpDst1 = (char *)lpNewDIBBits1; 
memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight); 
lpDst2 = (char *)lpNewDIBBits2; 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Sobel模板参数 
iTempW = 3; 
iTempH = 3; 
fTempC = 1.0; 
iTempMX = 1; 
iTempMY = 1; 
aTemplate[0] = -1.0; 
aTemplate[1] = -2.0; 
aTemplate[2] = -1.0; 
aTemplate[3] = 0.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 0.0; 
aTemplate[6] = 1.0; 
aTemplate[7] = 2.0; 
aTemplate[8] = 1.0; 

if (!Template(lpNewDIBBits1, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

// 设置Sobel模板参数 
aTemplate[0] = -1.0; 
aTemplate[1] = 0.0; 
aTemplate[2] = 1.0; 
aTemplate[3] = -2.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 2.0; 
aTemplate[6] = -1.0; 
aTemplate[7] = 0.0; 
aTemplate[8] = 1.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 复制经过模板运算后的图像到源图像 
memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight); 

LocalUnlock(hNewDIBBits1); 
LocalFree(hNewDIBBits1); 
LocalUnlock(hNewDIBBits2); 
LocalFree(hNewDIBBits2); 

return TRUE; 

 
BOOL CDibImage::PrewittDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpDst1; // 指向缓存图像的指针 
LPSTR lpDst2;
LPSTR lpNewDIBBits1; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits1; 
LPSTR lpNewDIBBits2; 
HLOCAL hNewDIBBits2; 

long i,j; // 循环变量
int iTempH; // 模板高度
int iTempW; // 模板宽度
FLOAT fTempC; // 模板系数
int iTempMX; // 模板中心元素X坐标 
int iTempMY; // 模板中心元素Y坐标 
FLOAT aTemplate[9]; // 模板数组 

// 暂时分配内存,以保存新图像 
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits1 == NULL) 
return FALSE; 

lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1); 

// 暂时分配内存,以保存新图像 
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits2 == NULL) 
return FALSE; 

lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2); 

// 拷贝源图像到缓存图像中 
lpDst1 = (char *)lpNewDIBBits1; 
memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight); 
lpDst2 = (char *)lpNewDIBBits2; 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 


// 设置Prewitt模板参数 
iTempW = 3; 
iTempH = 3; 
fTempC = 1.0; 
iTempMX = 1; 
iTempMY = 1; 
aTemplate[0] = -1.0; 
aTemplate[1] = -1.0; 
aTemplate[2] = -1.0; 
aTemplate[3] = 0.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 0.0; 
aTemplate[6] = 1.0; 
aTemplate[7] = 1.0; 
aTemplate[8] = 1.0; 

if (!Template(lpNewDIBBits1, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

// 设置Prewitt模板参数 
aTemplate[0] = 1.0; 
aTemplate[1] = 0.0; 
aTemplate[2] = -1.0; 
aTemplate[3] = 1.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -1.0; 
aTemplate[6] = 1.0; 
aTemplate[7] = 0.0; 
aTemplate[8] = -1.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 复制经过模板运算后的图像到源图像 
memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight); 

LocalUnlock(hNewDIBBits1); 
LocalFree(hNewDIBBits1); 
LocalUnlock(hNewDIBBits2); 
LocalFree(hNewDIBBits2); 

return TRUE; 

 
BOOL CDibImage::KirschDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpDst1; // 指向缓存图像的指针 
LPSTR lpDst2; 
LPSTR lpNewDIBBits1; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits1; 
LPSTR lpNewDIBBits2; 
HLOCAL hNewDIBBits2; 

long i,j; // 循环变量
int iTempH; // 模板高度
int iTempW; // 模板宽度
FLOAT fTempC; // 模板系数
int iTempMX; // 模板中心元素X坐标
int iTempMY; // 模板中心元素Y坐标
FLOAT aTemplate[9]; // 模板数组 

// 暂时分配内存,以保存新图像 
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits1 == NULL) 
return FALSE; 

lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1); 

// 暂时分配内存,以保存新图像 
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits2 == NULL) 
return FALSE; 

lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2); 

// 拷贝源图像到缓存图像中 
lpDst1 = (char *)lpNewDIBBits1; 
memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight); 
lpDst2 = (char *)lpNewDIBBits2; 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板1参数 
iTempW = 3; 
iTempH = 3; 
fTempC = 1.0; 
iTempMX = 1; 
iTempMY = 1; 
aTemplate[0] = 5.0; 
aTemplate[1] = 5.0; 
aTemplate[2] = 5.0; 
aTemplate[3] = -3.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -3.0; 
aTemplate[6] = -3.0; 
aTemplate[7] = -3.0; 
aTemplate[8] = -3.0; 

if (!Template(lpNewDIBBits1, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

// 设置Kirsch模板2参数 
aTemplate[0] = -3.0; 
aTemplate[1] = 5.0; 
aTemplate[2] = 5.0; 
aTemplate[3] = -3.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 5.0; 
aTemplate[6] = -3.0; 
aTemplate[7] = -3.0; 
aTemplate[8] = -3.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板3参数 
aTemplate[0] = -3.0; 
aTemplate[1] = -3.0; 
aTemplate[2] = 5.0; 
aTemplate[3] = -3.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 5.0; 
aTemplate[6] = -3.0; 
aTemplate[7] = -3.0; 
aTemplate[8] = 5.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板4参数 
aTemplate[0] = -3.0; 
aTemplate[1] = -3.0; 
aTemplate[2] = -3.0; 
aTemplate[3] = -3.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = 5.0; 
aTemplate[6] = -3.0; 
aTemplate[7] = 5.0; 
aTemplate[8] = 5.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板5参数 
aTemplate[0] = -3.0; 
aTemplate[1] = -3.0; 
aTemplate[2] = -3.0; 
aTemplate[3] = -3.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -3.0; 
aTemplate[6] = 5.0; 
aTemplate[7] = 5.0; 
aTemplate[8] = 5.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板6参数 
aTemplate[0] = -3.0; 
aTemplate[1] = -3.0; 
aTemplate[2] = -3.0; 
aTemplate[3] = 5.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -3.0; 
aTemplate[6] = 5.0; 
aTemplate[7] = 5.0; 
aTemplate[8] = -3.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板7参数 
aTemplate[0] = 5.0; 
aTemplate[1] = -3.0; 
aTemplate[2] = -3.0; 
aTemplate[3] = 5.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -3.0; 
aTemplate[6] = 5.0; 
aTemplate[7] = -3.0; 
aTemplate[8] = -3.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 拷贝源图像到缓存图像中 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Kirsch模板8参数 
aTemplate[0] = 5.0; 
aTemplate[1] = 5.0; 
aTemplate[2] = -3.0; 
aTemplate[3] = 5.0; 
aTemplate[4] = 0.0; 
aTemplate[5] = -3.0; 
aTemplate[6] = -3.0; 
aTemplate[7] = -3.0; 
aTemplate[8] = -3.0; 

if (!Template(lpNewDIBBits2, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

//求两幅缓存图像的最大值 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth-1; i++) 
// 指向缓存图像1倒数第j行,第i个象素的指针
lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i; 
// 指向缓存图像2倒数第j行,第i个象素的指针
lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i; 

if(*lpDst2 > *lpDst1) 
*lpDst1 = *lpDst2; 

// 复制经过模板运算后的图像到源图像 
memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight); 

LocalUnlock(hNewDIBBits1); 
LocalFree(hNewDIBBits1); 
LocalUnlock(hNewDIBBits2); 
LocalFree(hNewDIBBits2); 

return TRUE; 

 
BOOL CDibImage::GaussDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpDst1; // 指向缓存图像的指针 
LPSTR lpDst2;
LPSTR lpNewDIBBits1; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits1; 
LPSTR lpNewDIBBits2; 
HLOCAL hNewDIBBits2; 

int iTempH; // 模板高度
int iTempW; // 模板宽度
FLOAT fTempC; // 模板系数
int iTempMX; // 模板中心元素X坐标
int iTempMY; // 模板中心元素Y坐标 
FLOAT aTemplate[25]; //模板数组 

// 暂时分配内存,以保存新图像 
hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits1 == NULL) 
return FALSE; 

lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1); 

// 暂时分配内存,以保存新图像 
hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits2 == NULL) 
return FALSE; 

lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2); 

// 拷贝源图像到缓存图像中 
lpDst1 = (char *)lpNewDIBBits1; 
memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight); 
lpDst2 = (char *)lpNewDIBBits2; 
memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight); 

// 设置Gauss模板参数 
iTempW = 5; 
iTempH = 5; 
fTempC = 1.0; 
iTempMX = 3; 
iTempMY = 3; 
aTemplate[0] = -2.0; 
aTemplate[1] = -4.0; 
aTemplate[2] = -4.0; 
aTemplate[3] = -4.0; 
aTemplate[4] = -2.0; 
aTemplate[5] = -4.0; 
aTemplate[6] = 0.0; 
aTemplate[7] = 8.0; 
aTemplate[8] = 0.0; 
aTemplate[9] = -4.0; 
aTemplate[10] = -4.0; 
aTemplate[11] = 8.0; 
aTemplate[12] = 24.0; 
aTemplate[13] = 8.0; 
aTemplate[14] = -4.0; 
aTemplate[15] = -4.0; 
aTemplate[16] = 0.0; 
aTemplate[17] = 8.0; 
aTemplate[18] = 0.0; 
aTemplate[19] = -4.0; 
aTemplate[20] = -2.0; 
aTemplate[21] = -4.0; 
aTemplate[22] = -4.0; 
aTemplate[23] = -4.0; 
aTemplate[24] = -2.0; 

if (!Template(lpNewDIBBits1, lWidth, lHeight, 
iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC)) 
return FALSE; 

// 复制经过模板运算后的图像到源图像 
memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight); 

LocalUnlock(hNewDIBBits1); 
LocalFree(hNewDIBBits1); 
LocalUnlock(hNewDIBBits2); 
LocalFree(hNewDIBBits2); 

return TRUE; 

 
BOOL CDibImage::HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpTrans; // 指向变换域的指针
LONG lLineBytes; // 图像每行的字节数
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits;
LPSTR lpTransArea; // 指向变换域的指针 
HLOCAL hTransArea; 

int iMaxDist; // 变换域的尺寸 
int iMaxAngleNumber;
int iDist; // 变换域的坐标 
int iAngleNumber;
long i,j; // 循环变量
unsigned char pixel; // 像素值 
MaxValue MaxValue1; // 存储变换域中的两个最大值 
MaxValue MaxValue2; 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 

//计算变换域的尺寸 最大距离 
iMaxDist = (int) sqrt(lWidth*lWidth + lHeight*lHeight);
//角度从0-180,每格2度 
iMaxAngleNumber = 90;

//为变换域分配内存 
hTransArea = LocalAlloc(LHND, lWidth * lHeight * sizeof(int)); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpTransArea = (char * )LocalLock(hTransArea); 

// 初始化新分配的内存,设定初始值为0 
lpTrans = (char *)lpTransArea; 
memset(lpTrans, 0, lWidth * lHeight * sizeof(int)); 

// 计算图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

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

//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 
//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && *lpSrc != 0) 
return FALSE; 

//如果是黑点,则在变换域的对应各点上加1 
if(pixel == 0) 
//注意步长是2度 
for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++) 
iDist = (int) fabs(i*cos(iAngleNumber*2*PI/180.0) + j*sin(iAngleNumber*2*PI/180.0)); 

//变换域的对应点上加1 
*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) = *(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) +1; 
}

//找到变换域中的两个最大值点 
MaxValue1.Value=0; 
MaxValue2.Value=0; 

//找到第一个最大值点 
for (iDist=0; iDist<iMaxDist;iDist++) 
for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++) 
if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue1.Value) 
MaxValue1.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber 
+iAngleNumber); 
MaxValue1.Dist = iDist; 
MaxValue1.AngleNumber = iAngleNumber; 

//将第一个最大值点附近清零 
for (iDist = -9;iDist < 10;iDist++) 
for(iAngleNumber=-1; iAngleNumber<2; iAngleNumber++) 
if(iDist+MaxValue1.Dist>=0 && iDist+MaxValue1.Dist<iMaxDist && iAngleNumber+MaxValue1.AngleNumber>=0 && iAngleNumber 
+MaxValue1.AngleNumber<=iMaxAngleNumber) 
*(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+ (iAngleNumber+MaxValue1.AngleNumber))=0; 

//找到第二个最大值点 
for (iDist=0; iDist<iMaxDist;iDist++) 
for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++) 
if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue2.Value) 
MaxValue2.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber 
+iAngleNumber); 
MaxValue2.Dist = iDist; 
MaxValue2.AngleNumber = iAngleNumber; 

//判断两直线是否平行 
if(abs(MaxValue1.AngleNumber-MaxValue2.AngleNumber)<=2) 
//两直线平行,在缓存图像中重绘这两条直线 
for(j = 0; j <lHeight; j++) 
for(i = 0;i <lWidth; i++) 
{
// 指向缓存图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;

//如果该点在某一条平行直线上,则在缓存图像上将该点赋为黑 

//在第一条直线上 
iDist = (int) fabs(i*cos(MaxValue1.AngleNumber*2*PI/180.0) + j*sin(MaxValue1.AngleNumber*2*PI/180.0)); 
if (iDist == MaxValue1.Dist) 
*lpDst = (unsigned char)0; 
//在第二条直线上 
iDist = (int) fabs(i*cos(MaxValue2.AngleNumber*2*PI/180.0) + j*sin(MaxValue2.AngleNumber*2*PI/180.0)); 
if (iDist == MaxValue2.Dist) 
*lpDst = (unsigned char)0; 

// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 
LocalUnlock(hTransArea); 
LocalFree(hTransArea); 

return TRUE; 

 
BOOL CDibImage::Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
long i; // 循环变量
unsigned char pixel; // 像素值
int xl,xr; // 左右边界像素位置 
BOOL bFilll,bFillr; // 是否已填充至边界
Seed Seeds[10]; // 种子堆栈及指针 
int StackPoint;
int iCurrentPixelx,iCurrentPixely; // 当前像素位置 
int iBufferPixelx,iBufferPixely; 

Seeds[1].Height = lHeight / 2; // 初始化种子 
Seeds[1].Width = lWidth / 2; 
StackPoint = 1; 

while( StackPoint != 0) 
//取出种子 
iCurrentPixelx = Seeds[StackPoint].Width; 
iCurrentPixely = Seeds[StackPoint].Height; 
StackPoint--; 
// if(Seed2.Height== 75) 
// { 
// return true; 
// i++; 
// } 
bFilll = true; 
bFillr = true; 
//填充种子所在的行,保存种子像素的位置 
iBufferPixelx = iCurrentPixelx; 
iBufferPixely = iCurrentPixely; 
//先向左填充 
while(bFilll) 
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 
//遇到边界 
if(pixel == 0) 
bFilll = false; 
xl=iCurrentPixelx+1; 
else 
*lpSrc = (unsigned char)0; 
iCurrentPixelx--; 
//防止越界 
if(iCurrentPixelx<0) 
{
bFilll = false; 
iCurrentPixelx = 0; 
xl = 0; 
}
//再向右填充,取回种子像素的位置 
iCurrentPixelx = iBufferPixelx+1; 
if(iCurrentPixelx>lWidth) 
{
bFillr = false; 
iCurrentPixelx = lWidth; 
xr = lWidth; 
iCurrentPixely = iBufferPixely; 
while(bFillr) 
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 
//遇到边界 
if(pixel == 0) 
bFillr = false; 
xr=iCurrentPixelx-1; 
else 
*lpSrc = (unsigned char)0; 
iCurrentPixelx++; 
//防止越界 
if(iCurrentPixelx>lWidth) 
{
bFillr = false; 
iCurrentPixelx = lWidth; 
xr = lWidth; 
}
//上、下两条扫描线是否全为边界象素或已填充过 
//先看上面的扫描线 
iCurrentPixely--; 
if(iCurrentPixely < 0) 
iCurrentPixely = 0; 
for (i = xr; i>= xl;i--) 
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//有未填充的像素,将新的种子压入堆栈 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely; 
Seeds[StackPoint].Width = i; 
break; 
}
//再看下面的扫描线 
iCurrentPixely+=2; 
if(iCurrentPixely > lHeight) 
iCurrentPixely = lHeight; 
for (i = xr; i>= xl;i--) 
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//有未填充的像素,将新的种子压入堆栈 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely; 
Seeds[StackPoint].Width = i; 
break; 
}

return TRUE; 

 
BOOL CDibImage::FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
unsigned char pixel; // 像素值
Seed *Seeds; // 种子堆栈及指针 
int StackPoint; 
int iCurrentPixelx,iCurrentPixely; // 当前像素位置 

Seeds = new Seed[lWidth*lHeight]; // 初始化种子 
Seeds[1].Height = lHeight / 2; 
Seeds[1].Width = lWidth / 2; 
StackPoint = 1; 

while( StackPoint != 0) 
//取出种子 
iCurrentPixelx = Seeds[StackPoint].Width; 
iCurrentPixely = Seeds[StackPoint].Height; 
StackPoint--; 

lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

//将当前点涂黑 
*lpSrc = (unsigned char)0; 

//判断左面的点,如果为白,则压入堆栈,注意防止越界 
if(iCurrentPixelx > 0) 
lpSrc = (char *)lpDIBBits+lWidth*iCurrentPixely+iCurrentPixelx-1; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely; 
Seeds[StackPoint].Width = iCurrentPixelx - 1; 
//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

//判断上面的点,如果为白,则压入堆栈,注意防止越界 
if(iCurrentPixely < lHeight - 1) 
lpSrc = (char *)lpDIBBits+lWidth*(iCurrentPixely+1)+iCurrentPixelx; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely + 1; 
Seeds[StackPoint].Width = iCurrentPixelx; 
//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

//判断右面的点,如果为白,则压入堆栈,注意防止越界 
if(iCurrentPixelx < lWidth - 1) 
lpSrc = (char *)lpDIBBits+lWidth*iCurrentPixely+iCurrentPixelx+1; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely; 
Seeds[StackPoint].Width = iCurrentPixelx + 1; 
//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

//判断下面的点,如果为白,则压入堆栈,注意防止越界 
if(iCurrentPixely > 0) 
lpSrc = (char *)lpDIBBits+lWidth*(iCurrentPixely-1)+iCurrentPixelx; 
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 
if (pixel == 255) 
StackPoint++; 
Seeds[StackPoint].Height = iCurrentPixely - 1; 
Seeds[StackPoint].Width = iCurrentPixelx; 
//目标图像中含有0和255外的其它灰度值 
if(pixel != 255 && pixel != 0) 
return FALSE; 

delete Seeds; 

return TRUE; 

 
BOOL CDibImage::ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits; 
long i,j; //循环变量 
unsigned char n,e,s,w,ne,se,nw,sw; 
unsigned char pixel; //像素值 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lWidth * lHeight); 
for(j = 1; j <lHeight-1; j++) 
for(i = 1;i <lWidth-1; i++) 
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

//目标图像中含有0和255外的其它灰度值 
// if(pixel != 255 && pixel != 0) 
// return FALSE; 
if(pixel == 0) 
*lpDst = (unsigned char)0; 
nw = (unsigned char)*(lpSrc + lWidth -1); 
n = (unsigned char)*(lpSrc + lWidth ); 
ne = (unsigned char)*(lpSrc + lWidth +1); 
w = (unsigned char)*(lpSrc -1); 
e = (unsigned char)*(lpSrc +1); 
sw = (unsigned char)*(lpSrc - lWidth -1); 
s = (unsigned char)*(lpSrc - lWidth ); 
se = (unsigned char)*(lpSrc - lWidth +1); 
//如果相邻的八个点都是黑点 
if(nw+n+ne+w+e+sw+s+se==0) 
*lpDst = (unsigned char)255; 

// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 

 
BOOL CDibImage::TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{
LPSTR lpSrc; // 指向源图像的指针
LPSTR lpDst; // 指向缓存图像的指针
LPSTR lpNewDIBBits; // 指向缓存DIB图像的指针 
HLOCAL hNewDIBBits; 
LONG lLineBytes; // 图像每行的字节数 
long i,j; // 循环变量 
unsigned char pixel; // 像素值 
bool bFindStartPoint; // 是否找到起始点及回到起始点 
bool bFindPoint; // 是否扫描到一个边界点
Point StartPoint,CurrentPoint; // 起始边界点与当前边界点 

//八个方向和起始扫描方向 
int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}}; 
int BeginDirect; 

// 计算图像每行的字节数 
lLineBytes = WIDTHBYTES(lWidth * 8); 

// 暂时分配内存,以保存新图像 
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
if (hNewDIBBits == NULL) 
return FALSE; 

lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 

// 初始化新分配的内存,设定初始值为255 
lpDst = (char *)lpNewDIBBits; 
memset(lpDst, (BYTE)255, lLineBytes * lHeight); 

//先找到最左上方的边界点 
bFindStartPoint = false; 
for (j = 0;j < lHeight && !bFindStartPoint;j++) 
for(i = 0;i < lWidth && !bFindStartPoint;i++) 
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型 
pixel = (unsigned char)*lpSrc; 

if(pixel == 0) 
bFindStartPoint = true; 
StartPoint.Height = j; 
StartPoint.Width = i; 

// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
*lpDst = (unsigned char)0; 
}

//由于起始点是在左下方,故起始扫描沿左上方向 
BeginDirect = 0; 
//跟踪边界 
bFindStartPoint = false; 
//从初始点开始扫描 
CurrentPoint.Height = StartPoint.Height; 
CurrentPoint.Width = StartPoint.Width; 
while(!bFindStartPoint) 
bFindPoint = false; 
while(!bFindPoint) 
//沿扫描方向查看一个像素 
lpSrc = (char *)lpDIBBits + lLineBytes * ( CurrentPoint.Height + 
Direction[BeginDirect][1]) + (CurrentPoint.Width + 
Direction[BeginDirect][0]); 
pixel = (unsigned char)*lpSrc; 
if(pixel == 0) 
bFindPoint = true; 
CurrentPoint.Height = CurrentPoint.Height+Direction[BeginDirect][1]; 
CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0]; 
if(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width 
== StartPoint.Width) 
bFindStartPoint = true; 
lpDst = (char *)lpNewDIBBits + lLineBytes * CurrentPoint.Height 
+ CurrentPoint.Width; 
*lpDst = (unsigned char)0; 
//扫描的方向逆时针旋转两格 
BeginDirect--; 
if(BeginDirect == -1) 
BeginDirect = 7; 
BeginDirect--; 
if(BeginDirect == -1) 
BeginDirect = 7; 
else 
//扫描方向顺时针旋转一格 
BeginDirect++; 
if(BeginDirect == 8) 
BeginDirect = 0; 

// 复制腐蚀后的图像 
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 

LocalUnlock(hNewDIBBits); 
LocalFree(hNewDIBBits); 

return TRUE; 


posted on 2012-06-05 16:56  龙猫先生  阅读(472)  评论(0编辑  收藏  举报

导航