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

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类/实现

+ View Code ?
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/

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

作者:skyseraph
出处:http://www.cnblogs.com/skyseraph/
Email/GTalk: zgzhaobo@gmail.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类: 【31】DIP
标签: 图像算法
绿色通道: 好文要顶 关注我 收藏该文 与我联系

SkySeraph
关注 - 8
粉丝 - 457

+加关注

0
0
(请您对文章做出评价)

« 上一篇: 【收藏】国企央企
» 下一篇: 【面试笔试】图像处理工程师 笔试面试经历

posted @ 2011-04-22 21:50 SkySeraph 阅读( 2758) 评论( 0) 编辑 收藏

刷新评论 刷新页面 返回顶部
style="DISPLAY: none; VISIBILITY: hidden" src="http://tpc.googlesyndication.com/safeframe/1-0-2/html/container.html">

最新IT新闻:
· 大众点评完成新轮8.5亿美元融资 小米腾讯参投
· 让人悚然心惊的节奏 听一听北京雾霾唱歌
· NASA推出灶神星探索网页工具
· 谷歌大开杀戒? 移除近200个Chrome恶意扩展
· 阿里的网商银行已提交验收申请 进入开业准备
» 更多新闻...
最新知识库文章:

· 我们为什么要思考算法
· 事件流如何提高应用程序的扩展性、可靠性和可维护性
· Web动效研究与实践
· 关于工作效率的心得分享
· 编码之道:取个好名字很重要

» 更多知识库文章...

style="WIDTH: 0px; DISPLAY: none; HEIGHT: 0px" id="google_osd_static_frame_7523488917363" name="google_osd_static_frame">

图像算法:数字图像处理程序大全相关推荐

  1. 中南民族大学计算机图像处理实验报告,中南民族大学数字图像处理程序及图像...

    数字图像处理实验课 matlab实验程序 以及图像结果 附带有命名图 仅供参考 定有错误 木有绝对正确 实验1 1-1 close all; clear; f=zeros(40,40);% f(10: ...

  2. 基于matlab的霍夫变换,基于matlab的霍夫变换

    MATLAB 三维绘图功能 Plot3函数(三维曲线图) Mesh函数(网格图) Surf函数(曲面...步骤: 1.利用hough()函数执行霍夫变换,得到霍夫矩阵; 2.利用houghpeaks( ...

  3. Matlab 图像处理的一些杂记

    图像直方图均衡- - Tag: matlab    图像处理    直方图均衡 %  数字图像处理程序作业 %  本程序能将JPG格式的彩色图像文件灰度化并进行直方图均衡 %  %  输入文件:Pic ...

  4. 基于opencv第三方视觉库,通过内网IP调用手机摄像头,实现人脸识别与图形监测

    1. 安装opencv视觉库 OpenCV 是一个开源的计算机视觉库,OpenCV 库用C语言和 C++ 语言编写,可以在 Windows.Linux.Mac OS X 等系统运行.同时也在积极开发 ...

  5. 基于opencv视觉库,通过numpy进行像素矩阵处理,压缩图片、做像素图

    1. numpy库基本介绍 NumPy 是一个Python包(Numeric Python)它是一个由多维数组对象和用于处理数组的例程集合组成的库,其支持大量高维度数组与矩阵运算.NumPy 也针对数 ...

  6. python手绘效果图_Python实现手绘图

    利用python的Numpy及PIL第三方库实现图片的手绘效果.PIL第三方库是一个具有强大图像处理能力的第三方库. 数字图像数据可以用矩阵来表示,因此可以采用矩阵理论和矩阵算法对数字图像进行分析和处 ...

  7. C语言库函数大全及应用实例二

                                                 [编程资料]C语言库函数大全及应用实例二 函数名: bioskey 功 能: 直接使用BIOS服务的键盘接口 ...

  8. 艰难就业季,2020 AI算法岗春招汇总 面经大全来了!!!

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 受疫情影响,很多家企业纷纷推迟复工.但是,今年的春招并没有因此耽搁,很多企业纷纷发 ...

  9. cmos 和 bios中断大全

    1,cmos简介.    cmos是主板上一块可读写的RAM芯片.用途:主要用来保存当前系统的硬件配置和操作人员对某些参数的设定.cmos芯片是由一块纽扣电池供电.因此在关机状态内部信息也不会丢失. ...

最新文章

  1. malloc为什么会报错:memory corruption
  2. GitHub 标星 17 万:打破程序员“中年危机”的「编程面试大学」!
  3. 百度超级链XChain(2)p2p网络
  4. 假设以带头结点的循环链表表示队列_[leetcode链表系列]2 删除链表中的节点
  5. 深度学习 点积的概念
  6. chromium 源码下载地址
  7. 【转】怎样判断自己掌握了学到的新知识
  8. 案例|自建or现成工具?小型创业团队敏捷研发探索
  9. mjorm java_MongoDB 的 ORM框架 MJORM
  10. Zoom创始人袁征转让约1800万股股票 价值超过60亿美元
  11. redis允许其他机器远程连接
  12. 苹果原生文字转语音播报
  13. 判断当前用户与审批人是否属于同一个部门
  14. ER图(实体关系图)怎么画?
  15. 西安省某小学能耗监测及电力监控系统的研究与应用
  16. android gpu平板 推荐,性能强的不像话,最强安卓平板华为平板M6上手
  17. 英语时态:一般、否定疑问句、现表将来(中文练到无停顿)
  18. oracle 初级学习(王二暖 视频 笔记)
  19. 复旦发布报告!70后度过中年危机?80后珍惜家庭?90后高压期来临?
  20. Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask

热门文章

  1. cmd中到指定目录去的操作
  2. Python打印佛祖
  3. win8 计算机没了怎么办,win8没有介质怎么重置电脑
  4. Linux time时间概述
  5. POJ3258 River Hopscotch(二分)
  6. java下拉菜单选择前弹提示框_javascript实现下拉提示选择框
  7. 计算机房承重载荷,机房楼面承重荷载检测收费标准
  8. iOS邓白码和开发者账号申请
  9. 2020电工(中级)模拟考试系统及电工(中级)考试软件
  10. 数据库工程师考试自学(6)---多值依赖与4NF