zoukankan      html  css  js  c++  java
  • 【图像算法】常见的数字图像处理程序大全

    图像算法:数字图像处理程序大全

     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) 函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   PaintDIB()
     * 参数:
     *   HDC hDC            - 输出设备DC
     *   LPRECT lpDCRect    - 绘制矩形区域
     *   HDIB hDIB          - 指向DIB对象的指针
     *   LPRECT lpDIBRect   - 要输出的DIB区域
     *   CPalette* pPal     - 指向DIB对象调色板的指针
     * 返回值:
     *   BOOL               - 绘制成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者
     * SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指
     * 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数
     * lpDIBRect指定。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   CreateDIBPalette()
     * 参数:
     *   HDIB hDIB          - 指向DIB对象的指针
     *   CPalette* pPal     - 指向DIB对象调色板的指针
     * 返回值:
     *   BOOL               - 创建成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中,
     * 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样
     * 可以用最好的颜色来显示DIB图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   FindDIBBits()
     * 参数:
     *   LPSTR lpbi         - 指向DIB对象的指针
     * 返回值:
     *   LPSTR              - 指向DIB图像象素起始位置
     * 说明:
     *   该函数计算DIB中图像象素的起始位置,并返回指向它的指针。
     ************************************************************************/
    LPSTR CDibImage::FindDIBBits(LPSTR lpbi)
    {
    	return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBWidth()
     * 参数:
     *   LPSTR lpbi         - 指向DIB对象的指针
     * 返回值:
     *   DWORD              - DIB中图像的宽度
     * 说明:
     *   该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER
     * 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。
     ************************************************************************/
    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
    	}
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBHeight()
     * 参数:
     *   LPSTR lpDIB        - 指向DIB对象的指针
     * 返回值:
     *   DWORD              - DIB中图像的高度
     * 说明:
     *   该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER
     * 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。
     ************************************************************************/
    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
    	}
    }
    
    /*************************************************************************
     * 函数名称:
     *   PaletteSize()
     * 参数:
     *   LPSTR lpbi         - 指向DIB对象的指针
     * 返回值:
     *   WORD               - DIB中调色板的大小
     * 说明:
     *   该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目×
     * RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。
     ************************************************************************/
    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));
    	}
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBNumColors()
     * 参数:
     *   LPSTR lpbi         - 指向DIB对象的指针
     * 返回值:
     *   WORD               - 返回调色板中颜色的种数
     * 说明:
     *   该函数返回DIB中调色板的颜色的种数。对于单色位图,返回2,
     * 对于16色位图,返回16,对于256色位图,返回256;对于真彩色
     * 位图(24位),没有调色板,返回0。
     ************************************************************************/
    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;
    	}
    }
    
    /*************************************************************************
     * 函数名称:
     *   CopyHandle()
     * 参数:
     *   HGLOBAL h          - 要复制的内存区域
     * 返回值:
     *   HGLOBAL            - 复制后的新内存区域
     * 说明:
     *   该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   SaveDIB()
     * 参数:
     *   HDIB hDib          - 要保存的DIB
     *   CFile& file        - 保存文件CFile
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE或者CFileException
     * 说明:
     *   该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
     *************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ReadDIBFile()
     * 参数:
     *   CFile& file        - 要读取得文件文件CFile
     * 返回值:
     *   HDIB               - 成功返回DIB的句柄,否则返回NULL。
     * 说明:
     *   该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER
     * 外的内容都将被读入内存。
     *************************************************************************/
    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;
    }
    
    //////////////////////////////////////////////////////////////////////
    // 图像点运算函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   LinerTrans()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   FLOAT fA		    - 线性变换的斜率
     *   FLOAT fB           - 线性变换的截距
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行灰度的线性变换操作。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ThresholdTrans()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   BYTE  bThre	    - 阈值
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置
     * 灰度值为0;灰度值大于阈值的象素直接设置为255。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   WindowTrans()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   BYTE  bLow		    - 窗口下限
     *   BYTE  bUp          - 窗口上限
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行窗口变换。只有在窗口范围内的灰度保持不变,
     * 小于下限的象素直接设置灰度值为0;大于上限的象素直接设置灰度值为255。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   GrayStretch()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   BYTE bX1			- 灰度拉伸第一个点的X坐标
     *   BYTE bY1			- 灰度拉伸第一个点的Y坐标
     *   BYTE bX2			- 灰度拉伸第二个点的X坐标
     *   BYTE bY2			- 灰度拉伸第二个点的Y坐标
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行灰度拉伸。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   InteEqualize()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行直方图均衡。
     ************************************************************************/
    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;
    }
    
    //////////////////////////////////////////////////////////////////////
    // 图像几何变换函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   TranslationDIB1()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   LONG  lXOffset     - X轴平移量(象素数)
     *   LONG  lYOffset     - Y轴平移量(象素数)
     * 返回值:
     *   BOOL               - 平移成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像
     * 将截去,空白部分用白色填充。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   TranslationDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   LONG  lXOffset     - X轴平移量(象素数)
     *   LONG  lYOffset     - Y轴平移量(象素数)
     * 返回值:
     *   BOOL               - 平移成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像
     * 将截去,空白部分用白色填充。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   MirrorDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   BOOL  bDirection   - 镜像的方向,TRUE表示水平镜像,FALSE表示垂直镜像
     * 返回值:
     *   BOOL               - 镜像成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来镜像DIB图像。可以指定镜像的方式是水平还是垂直。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   TransposeDIB()
     * 参数:
     *   LPSTR lpDIB		- 指向源DIB的指针
     * 返回值:
     *   BOOL               - 转置成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来转置DIB图像,即图像x、y坐标互换。函数将不会改变图像的大小,
     * 但是图像的高宽将互换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ZoomDIB()
     * 参数:
     *   LPSTR lpDIB		- 指向源DIB的指针
     *   float fXZoomRatio	- X轴方向缩放比率
     *   float fYZoomRatio	- Y轴方向缩放比率
     * 返回值:
     *   HGLOBAL            - 缩放成功返回新DIB句柄,否则返回NULL。
     * 说明:
     *   该函数用来缩放DIB图像,返回新生成DIB的句柄。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   RotateDIB()
     * 参数:
     *   LPSTR lpDIB		- 指向源DIB的指针
     *   int iRotateAngle	- 旋转的角度(0-360度)
     * 返回值:
     *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。
     * 说明:
     *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
     * 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
     * 值算法进行插值。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   RotateDIB2()
     * 参数:
     *   LPSTR lpDIB		- 指向源DIB的指针
     *   int iRotateAngle	- 旋转的角度(0-360度)
     * 返回值:
     *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。
     * 说明:
     *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
     * 调用该函数会自动扩大图像以显示所有的象素。函数中采用双线性插
     * 值算法进行插值。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   Interpolation()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   FLOAT x			- 插值元素的x坐标
     *   FLOAT y		    - 插值元素的y坐标
     * 返回值:
     *   unsigned char      - 返回插值计算结果。
     * 说明:
     *   该函数利用双线性插值算法来估算象素值。对于超出图像范围的象素,
     * 直接返回255。
     ************************************************************************/
    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)));
    		}
    	}
    }
    
    //////////////////////////////////////////////////////////////////////
    //  图像正交变换函数
    //////////////////////////////////////////////////////////////////////
    /*************************************************************************
     * 函数名称:
     *   FFT()
     * 参数:
     *   complex<double> * TD	- 指向时域数组的指针
     *   complex<double> * FD	- 指向频域数组的指针
     *   r						-2的幂数,即迭代次数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速付立叶变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   IFFT()
     * 参数:
     *   complex<double> * FD	- 指向频域值的指针
     *   complex<double> * TD	- 指向时域值的指针
     *   r						-2的幂数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速付立叶反变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   Fourier()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行付立叶变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   DCT()
     * 参数:
     *   double * f				- 指向时域值的指针
     *   double * F				- 指向频域值的指针
     *   r						-2的幂数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速离散余弦变换。该函数利用2N点的快速付立叶变换
     * 来实现离散余弦变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   IDCT()
     * 参数:
     *   double * F				- 指向频域值的指针
     *   double * f				- 指向时域值的指针
     *   r						-2的幂数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速离散余弦反变换。该函数也利用2N点的快速付立叶变换
     * 来实现离散余弦反变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBDct()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行离散余弦变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   WALSH()
     * 参数:
     *   double * f				- 指向时域值的指针
     *   double * F				- 指向频域值的指针
     *   r						-2的幂数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速沃尔什-哈达玛变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   IWALSH()
     * 参数:
     *   double * F				- 指向频域值的指针
     *   double * f				- 指向时域值的指针
     *   r						-2的幂数
     * 返回值:
     *   无。
     * 说明:
     *   该函数用来实现快速沃尔什-哈达玛反变换。
     ************************************************************************/
    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;
    	}
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBWalsh()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行沃尔什-哈达玛变换。函数首先对图像每列进行一维
     * 沃尔什-哈达玛变换,然后对变换结果的每行进行一维沃尔什-哈达玛变换。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   DIBWalsh1()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行沃尔什-哈达玛变换。于上面不同的是,此处是将二维
     * 矩阵转换成一个列向量,然后对该列向量进行一次一维沃尔什-哈达玛变换。
     ************************************************************************/
    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;
    }
    
    //////////////////////////////////////////////////////////////////////
    //	图像模板变换函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   Template()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   int   iTempH		- 模板的高度
     *   int   iTempW		- 模板的宽度
     *   int   iTempMX		- 模板的中心元素X坐标 ( < iTempW - 1)
     *   int   iTempMY		- 模板的中心元素Y坐标 ( < iTempH - 1)
     *	 FLOAT * fpArray	- 指向模板数组的指针
     *	 FLOAT fCoef		- 模板系数
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用指定的模板(任意大小)来对图像进行操作,参数iTempH指定模板
     * 的高度,参数iTempW指定模板的宽度,参数iTempMX和iTempMY指定模板的中心
     * 元素坐标,参数fpArray指定模板元素,fCoef指定系数。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   MedianFilter()
     * 参数:
     *   LPSTR lpDIBBits		- 指向源DIB图像指针
     *   LONG  lWidth			- 源图像宽度(象素数)
     *   LONG  lHeight			- 源图像高度(象素数)
     *   int   iFilterH			- 滤波器的高度
     *   int   iFilterW			- 滤波器的宽度
     *   int   iFilterMX		- 滤波器的中心元素X坐标
     *   int   iFilterMY		- 滤波器的中心元素Y坐标
     * 返回值:
     *   BOOL					- 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数对DIB图像进行中值滤波。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   GetMedianNum()
     * 参数:
     *   unsigned char * bpArray	- 指向要获取中值的数组指针
     *   int   iFilterLen			- 数组长度
     * 返回值:
     *   unsigned char      - 返回指定数组的中值。
     * 说明:
     *   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   GradSharp()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   BYTE  bThre		- 阈值
     * 返回值:
     *   BOOL               - 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用来对图像进行梯度锐化。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ReplaceColorPal()
     * 参数:
     *   LPSTR lpDIB			- 指向源DIB图像指针
     *   BYTE * bpColorsTable	- 伪彩色编码表
     * 返回值:
     *   BOOL					- 成功返回TRUE,否则返回FALSE。
     * 说明:
     *   该函数用指定的伪彩色编码表来替换图像的调试板,参数bpColorsTable
     * 指向要替换的伪彩色编码表。
     ************************************************************************/
    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;	
    }
    
    //////////////////////////////////////////////////////////////////////
    //  图像形态学变换函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   ErosiontionDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   int   nMode		- 腐蚀方式:0表示水平方向,1垂直方向,2自定义结构元素。
     *	 int   structure[3][3]	- 自定义的3×3结构元素。
     * 返回值:
     *   BOOL               - 腐蚀成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行腐蚀运算。结构元素为水平方向或垂直方向的三个点,
     * 中间点位于原点;或者由用户自己定义3×3的结构元素。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   DilationDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   int   nMode		- 膨胀方式:0表示水平方向,1垂直方向,2自定义结构元素。
     *	 int   structure[3][3]	- 自定义的3×3结构元素。
     * 返回值:
     *   BOOL               - 膨胀成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行膨胀运算。结构元素为水平方向或垂直方向的三个点,
     * 中间点位于原点;或者由用户自己定义3×3的结构元素。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   OpenDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   int   nMode		- 开运算方式:0表示水平方向,1垂直方向,2自定义结构元素。
     *	 int   structure[3][3]	- 自定义的3×3结构元素。
     * 返回值:
     *   BOOL               - 开运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,
     * 中间点位于原点;或者由用户自己定义3×3的结构元素。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   CloseDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     *   int   nMode		- 闭运算方式:0表示水平方向,1垂直方向,2自定义结构元素。
     *	 int   structure[3][3]	- 自定义的3×3结构元素。
     * 返回值:
     *   BOOL               - 闭运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行开运算。结构元素为水平方向或垂直方向的三个点,
     * 中间点位于原点;或者由用户自己定义3×3的结构元素。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ThinDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 闭运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行细化运算。要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    //////////////////////////////////////////////////////////////////////
    // 图像边缘与轮廓运算函数
    //////////////////////////////////////////////////////////////////////
    
    /*************************************************************************
     * 函数名称:
     *   RobertDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用Robert边缘检测算子对图像进行边缘检测运算。
     * 要求目标图像为灰度图像。
     ************************************************************************/
    BOOL CDibImage::RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
    {	
    
      WatershedSegment(lpDIBBits,lWidth,lHeight);
    
    
    
    
    
    
    
    //ju_lei(lpDIBBits,lWidth,lHeight);     
    return TRUE;
    
    }
    
    /*************************************************************************
     * 函数名称:
     *   SobelDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用Sobel边缘检测算子对图像进行边缘检测运算。
     * 要求目标图像为灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   PrewittDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用Prewitt边缘检测算子对图像进行边缘检测运算。
     * 要求目标图像为灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   KirschDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用kirsch边缘检测算子对图像进行边缘检测运算。
     * 要求目标图像为灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *  GaussDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用高斯拉普拉斯边缘检测算子对图像进行边缘检测运算。 
     * 要求目标图像为灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   HoughDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,
     * 则将这两条平行直线提取出来。 
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   Fill2DIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行种子填充运算。 
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   FillDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行种子填充运算。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   ContourDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行轮廓提取运算。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
    /*************************************************************************
     * 函数名称:
     *   TraceDIB()
     * 参数:
     *   LPSTR lpDIBBits    - 指向源DIB图像指针
     *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
     *   LONG  lHeight      - 源图像高度(象素数)
     * 返回值:
     *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
     * 说明:
     * 该函数用于对图像进行轮廓跟踪运算。
     * 要求目标图像为只有0和255两个灰度值的灰度图像。
     ************************************************************************/
    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;
    }
    
     
     

    Author:         SKySeraph

    Email/GTalk: zgzhaobo@gmail.com    QQ:452728574

    From:         http://www.cnblogs.com/skyseraph/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的

  • 相关阅读:
    终端提示“ timed out waiting for input: auto-logout”
    shell-日志统计
    spring-file-upload-exceeds its maximum permitted size of 1048576 bytes
    全面质量管理 TQM、六西格玛、CMMI、ISO9000 关系
    GitLab: You are not allowed to force push code to a protected branch on this project.
    go 多版本管理
    glide install error
    js tab栏切换
    ES6 class命令浅识
    ES6 const命令
  • 原文地址:https://www.cnblogs.com/skyseraph/p/2024657.html
Copyright © 2011-2022 走看看