DIB补充库

// dibapi.h
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.


#ifndef _INC_DIBAPI
#define _INC_DIBAPI

/* Handle to a DIB */
DECLARE_HANDLE(HDIB);

/* DIB constants */
#define PALVERSION   0x300

/* DIB Macros*/

#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
#define RECTWIDTH(lpRect)     ((lpRect)->right - (lpRect)->left)
#define RECTHEIGHT(lpRect)    ((lpRect)->bottom - (lpRect)->top)

// WIDTHBYTES performs DWORD-aligning of DIB scanlines.  The "bits"
// parameter is the bit count for the scanline (biWidth * biBitCount),
// and this macro returns the number of DWORD-aligned bytes needed
// to hold those bits.

#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

/* Function prototypes */
BOOL      WINAPI  PaintDIB (HDC, LPRECT, HDIB, LPRECT, CPalette* pPal);
BOOL      WINAPI  CreateDIBPalette(HDIB hDIB, CPalette* cPal);
LPSTR     WINAPI  FindDIBBits (LPSTR lpbi);
DWORD     WINAPI  DIBWidth (LPSTR lpDIB);
DWORD     WINAPI  DIBHeight (LPSTR lpDIB);
WORD      WINAPI  PaletteSize (LPSTR lpbi);
WORD      WINAPI  DIBNumColors (LPSTR lpbi);
HGLOBAL   WINAPI  CopyHandle (HGLOBAL h);

BOOL      WINAPI  SaveDIB (HDIB hDib, CFile& file);
HDIB      WINAPI  ReadDIBFile(CFile& file);

HDIB      WINAPI NewDIB(long width, long height, unsigned short biBitCount= 0); //add
void      WINAPI ConvertShort(unsigned short *array, long length);
void   WINAPI ConvertLong(unsigned long *array, long length);
BOOL      WINAPI EdgeDetect(LPSTR lpDIBBits,long lWidth,long lHeight);
BOOL      WINAPI ContourTrace(LPSTR lpDIBBits,long lWidth,long lHeight);
BOOL     MaxImg(LPSTR img,long lWidth,long lHeight);
BOOL     MinImg(LPSTR img,long lWidth,long lHeight);
BOOL     MiddleImg(LPSTR img,long lWidth,long lHeight);
BOOL Erosion(LPSTR lpDIBBits,long lWidth,long lHeight,int ErosionType);
BOOL Dialation(LPSTR lpDIBBits,long lWidth,long lHeight,int DialationType);
BOOL MirrorImg(LPSTR lpDIBBits,long lWidth,long lHeight,int mirrorType);
HGLOBAL WINAPI RotateImg(LPSTR lpDIB,float angle);
BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight);
BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL WINAPI Template(LPSTR lpDIBBits,long lWidth,long lHeight,float *temp,int temp_w,int temp_h,float xishu);
#endif //!_INC_DIBAPI

 

//  dibapi.cpp
//
//  Source file for Device-Independent Bitmap (DIB) API.  Provides
//  the following functions:
//
//  PaintDIB()          - Painting routine for a DIB
//  CreateDIBPalette()  - Creates a palette from a DIB
//  FindDIBBits()       - Returns a pointer to the DIB bits
//  DIBWidth()          - Gets the width of the DIB
//  DIBHeight()         - Gets the height of the DIB
//  PaletteSize()       - Gets the size required to store the DIB's palette
//  DIBNumColors()      - Calculates the number of colors
//                        in the DIB's color table
//  CopyHandle()        - Makes a copy of the given global memory block
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "dibapi.h"
#include "math.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#define  PI  3.1415926
//角度到弧度转化的宏
#define RADIAN(angle) ((angle)*PI/180.0)
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

#ifdef _MAC
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader);
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header);
#endif

/*************************************************************************
 *
 * PaintDIB()
 *
 * Parameters:
 *
 * HDC hDC          - DC to do output to
 *
 * LPRECT lpDCRect  - rectangle on DC to do output to
 *
 * HDIB hDIB        - handle to global memory with a DIB spec
 *                    in it followed by the DIB bits
 *
 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
 *
 * CPalette* pPal   - pointer to CPalette containing DIB's palette
 *
 * Return Value:
 *
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise
 *
 * Description:
 *   Painting routine for a DIB.  Calls StretchDIBits() or
 *   SetDIBitsToDevice() to paint the DIB.  The DIB is
 *   output to the specified DC, at the coordinates given
 *   in lpDCRect.  The area of the DIB to be output is
 *   given by lpDIBRect.
 *
 ************************************************************************/

BOOL WINAPI PaintDIB(HDC     hDC,
     LPRECT  lpDCRect,
     HDIB    hDIB,
     LPRECT  lpDIBRect,
     CPalette* pPal)
{
 LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
 LPSTR    lpDIBBits;           // Pointer to DIB bits
 BOOL     bSuccess=FALSE;      // Success/fail flag
 HPALETTE hPal=NULL;           // Our DIB's palette
 HPALETTE hOldPal=NULL;        // Previous palette

 /* Check for valid DIB handle */
 if (hDIB == NULL)
  return FALSE;

 /* Lock down the DIB, and get a pointer to the beginning of the bit
  *  buffer
  */
 lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
 lpDIBBits = ::FindDIBBits(lpDIBHdr);

 // Get the DIB's palette, then select it into DC
 if (pPal != NULL)
 {
  hPal = (HPALETTE) pPal->m_hObject;

  // Select as background since we have
  // already realized in forground if needed
  hOldPal = ::SelectPalette(hDC, hPal, TRUE);
 }

 /* Make sure to use the stretching mode best for color pictures */
 ::SetStretchBltMode(hDC, COLORONCOLOR);

 /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
 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);

 /* Reselect old palette */
 if (hOldPal != NULL)
 {
  ::SelectPalette(hDC, hOldPal, TRUE);
 }

   return bSuccess;
}

/*************************************************************************
 *
 * CreateDIBPalette()
 *
 * Parameter:
 *
 * HDIB hDIB        - specifies the DIB
 *
 * Return Value:
 *
 * HPALETTE         - specifies the palette
 *
 * Description:
 *
 * This function creates a palette from a DIB by allocating memory for the
 * logical palette, reading and storing the colors from the DIB's color table
 * into the logical palette, creating a palette from this logical palette,
 * and then returning the palette's handle. This allows the DIB to be
 * displayed using the best possible colors (important for DIBs with 256 or
 * more colors).
 *
 ************************************************************************/


BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
{
 LPLOGPALETTE lpPal;      // pointer to a logical palette
 HANDLE hLogPal;          // handle to a logical palette
 HPALETTE hPal = NULL;    // handle to a palette
 int i;                   // loop index
 WORD wNumColors;         // number of colors in color table
 LPSTR lpbi;              // pointer to packed-DIB
 LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
 LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
 BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
 BOOL bResult = FALSE;

 /* if handle to DIB is invalid, return FALSE */

 if (hDIB == NULL)
   return FALSE;

   lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

   /* get pointer to BITMAPINFO (Win 3.0) */
   lpbmi = (LPBITMAPINFO)lpbi;

   /* get pointer to BITMAPCOREINFO (old 1.x) */
   lpbmc = (LPBITMAPCOREINFO)lpbi;

   /* get the number of colors in the DIB */
   wNumColors = ::DIBNumColors(lpbi);

   if (wNumColors != 0)
   {
  /* allocate memory block for logical palette */
  hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
         + sizeof(PALETTEENTRY)
         * wNumColors);

  /* if not enough memory, clean up and return NULL */
  if (hLogPal == 0)
  {
   ::GlobalUnlock((HGLOBAL) hDIB);
   return FALSE;
  }

  lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);

  /* set version and number of palette entries */
  lpPal->palVersion = PALVERSION;
  lpPal->palNumEntries = (WORD)wNumColors;

  /* is this a Win 3.0 DIB? */
  bWinStyleDIB = IS_WIN30_DIB(lpbi);
  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;
   }
  }

  /* create the palette and get handle to it */
  bResult = pPal->CreatePalette(lpPal);
  ::GlobalUnlock((HGLOBAL) hLogPal);
  ::GlobalFree((HGLOBAL) hLogPal);
 }

 ::GlobalUnlock((HGLOBAL) hDIB);

 return bResult;
}

/*************************************************************************
 *
 * FindDIBBits()
 *
 * Parameter:
 *
 * LPSTR lpbi       - pointer to packed-DIB memory block
 *
 * Return Value:
 *
 * LPSTR            - pointer to the DIB bits
 *
 * Description:
 *
 * This function calculates the address of the DIB's bits and returns a
 * pointer to the DIB bits.
 *
 ************************************************************************/


LPSTR WINAPI FindDIBBits(LPSTR lpbi)
{
 return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
}


/*************************************************************************
 *
 * DIBWidth()
 *
 * Parameter:
 *
 * LPSTR lpbi       - pointer to packed-DIB memory block
 *
 * Return Value:
 *
 * DWORD            - width of the DIB
 *
 * Description:
 *
 * This function gets the width of the DIB from the BITMAPINFOHEADER
 * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
 * width field if it is an other-style DIB.
 *
 ************************************************************************/


DWORD WINAPI DIBWidth(LPSTR lpDIB)
{
 LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
 LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB

 /* point to the header (whether Win 3.0 and old) */

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

 /* return the DIB width if it is a Win 3.0 DIB */
 if (IS_WIN30_DIB(lpDIB))
  return lpbmi->biWidth;
 else  /* it is an other-style DIB, so return its width */
  return (DWORD)lpbmc->bcWidth;
}


/*************************************************************************
 *
 * DIBHeight()
 *
 * Parameter:
 *
 * LPSTR lpbi       - pointer to packed-DIB memory block
 *
 * Return Value:
 *
 * DWORD            - height of the DIB
 *
 * Description:
 *
 * This function gets the height of the DIB from the BITMAPINFOHEADER
 * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
 * height field if it is an other-style DIB.
 *
 ************************************************************************/


DWORD WINAPI DIBHeight(LPSTR lpDIB)
{
 LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
 LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB

 /* point to the header (whether old or Win 3.0 */

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

 /* return the DIB height if it is a Win 3.0 DIB */
 if (IS_WIN30_DIB(lpDIB))
  return lpbmi->biHeight;
 else  /* it is an other-style DIB, so return its height */
  return (DWORD)lpbmc->bcHeight;
}


/*************************************************************************
 *
 * PaletteSize()
 *
 * Parameter:
 *
 * LPSTR lpbi       - pointer to packed-DIB memory block
 *
 * Return Value:
 *
 * WORD             - size of the color palette of the DIB
 *
 * Description:
 *
 * This function gets the size required to store the DIB's palette by
 * multiplying the number of colors by the size of an RGBQUAD (for a
 * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
 * style DIB).
 *
 ************************************************************************/


WORD WINAPI PaletteSize(LPSTR lpbi)
{
   /* calculate the size required by the palette */
   if (IS_WIN30_DIB (lpbi))
   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
   else
   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}


/*************************************************************************
 *
 * DIBNumColors()
 *
 * Parameter:
 *
 * LPSTR lpbi       - pointer to packed-DIB memory block
 *
 * Return Value:
 *
 * WORD             - number of colors in the color table
 *
 * Description:
 *
 * This function calculates the number of colors in the DIB's color table
 * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
 * if 24, no colors in color table.
 *
 ************************************************************************/


WORD WINAPI DIBNumColors(LPSTR lpbi)
{
 WORD wBitCount;  // DIB bit count

 /*  If this is a Windows-style DIB, the number of colors in the
  *  color table can be less than the number of bits per pixel
  *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  *  If this is the case, return the appropriate value.
  */

 if (IS_WIN30_DIB(lpbi))
 {
  DWORD dwClrUsed;

  dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  if (dwClrUsed != 0)
   return (WORD)dwClrUsed;
 }

 /*  Calculate the number of colors in the color table based on
  *  the number of bits per pixel for the DIB.
  */
 if (IS_WIN30_DIB(lpbi))
  wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
 else
  wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;

 /* return number of colors based on bits per pixel */
 switch (wBitCount)
 {
  case 1:
   return 2;

  case 4:
   return 16;

  case 8:
   return 256;

  default:
   return 0;
 }
}

/*************************************************************************
 *
 * SaveDIB()
 *
 * Saves the specified DIB into the specified CFile.  The CFile
 * is opened and closed by the caller.
 *
 * Parameters:
 *
 * HDIB hDib - Handle to the dib to save
 *
 * CFile& file - open CFile used to save DIB
 *
 * Return value: TRUE if successful, else FALSE or CFileException
 *
 *************************************************************************/


BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
{
 BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
 LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure
 DWORD dwDIBSize;

 if (hDib == NULL)
  return FALSE;

 /*
  * Get a pointer to the DIB memory, the first of which contains
  * a BITMAPINFO structure
  */
 lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
 if (lpBI == NULL)
  return FALSE;

 if (!IS_WIN30_DIB(lpBI))
 {
  ::GlobalUnlock((HGLOBAL) hDib);
  return FALSE;       // It's an other-style DIB (save not supported)
 }

 /*
  * Fill in the fields of the file header
  */

 /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
 bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"

 // Calculating the size of the DIB is a bit tricky (if we want to
 // do it right).  The easiest way to do this is to call GlobalSize()
 // on our global handle, but since the size of our global memory may have
 // been padded a few bytes, we may end up writing out a few too
 // many bytes to the file (which may cause problems with some apps).
 //
 // So, instead let's calculate the size manually (if we can)
 //
 // First, find size of header plus size of color table.  Since the
 // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
 // the size of the structure, let's use this.

 dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation

 // Now calculate the size of the image

 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
 {
  // It's an RLE bitmap, we can't calculate size, so trust the
  // biSizeImage field

  dwDIBSize += lpBI->biSizeImage;
 }
 else
 {
  DWORD dwBmBitsSize;  // Size of Bitmap Bits only

  // It's not RLE, so size is Width (DWORD aligned) * Height

  dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;

  dwDIBSize += dwBmBitsSize;

  // Now, since we have calculated the correct size, why don't we
  // fill in the biSizeImage field (this will fix any .BMP files which
  // have this field incorrect).

  lpBI->biSizeImage = dwBmBitsSize;
 }


 // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)

 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
 bmfHdr.bfReserved1 = 0;
 bmfHdr.bfReserved2 = 0;

 /*
  * Now, calculate the offset the actual bitmap bits will be in
  * the file -- It's the Bitmap file header plus the DIB header,
  * plus the size of the color table.
  */
 bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
             + PaletteSize((LPSTR)lpBI);
#ifdef _MAC
 ByteSwapHeader(&bmfHdr);

 // First swap the size field
 *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));

 // Now swap the rest of the structure (we don't save < Win30 files)
 ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif

 TRY
 {
  // Write the file header
  file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  //
  // Write the DIB header and the bits
  //
  file.WriteHuge(lpBI, dwDIBSize);
 }
 CATCH (CFileException, e)
 {
#ifdef _MAC
  // Swap everything back
  *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
  ::GlobalUnlock((HGLOBAL) hDib);
  THROW_LAST();
 }
 END_CATCH

#ifdef _MAC
 // Swap everything back
 *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
 ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif

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


/*************************************************************************

  Function:  ReadDIBFile (CFile&)

   Purpose:  Reads in the specified DIB file into a global chunk of
    memory.

   Returns:  A handle to a dib (hDIB) if successful.
    NULL if an error occurs.

  Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
    from the end of the BITMAPFILEHEADER structure on is
    returned in the global memory handle.

*************************************************************************/


HDIB WINAPI ReadDIBFile(CFile& file)
{
 BITMAPFILEHEADER bmfHeader;
 DWORD dwBitsSize;
 HDIB hDIB;
 LPSTR pDIB;

 /*
  * get length of DIB in bytes for use when reading
  */

 dwBitsSize = file.GetLength();

 /*
  * Go read the DIB file header and check if it's valid.
  */
 if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  return NULL;

#ifdef _MAC
 ByteSwapHeader(&bmfHeader);
#endif
 if (bmfHeader.bfType != DIB_HEADER_MARKER)
  return NULL;

 /*
  * Allocate memory for DIB
  */
 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
 if (hDIB == 0)
 {
  return NULL;
 }
 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

 /*
  * Go read the bits.
  */
 if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
  dwBitsSize - sizeof(BITMAPFILEHEADER) )
 {
  ::GlobalUnlock((HGLOBAL) hDIB);
  ::GlobalFree((HGLOBAL) hDIB);
  return NULL;
 }
#ifdef _MAC
 // First swap the size field
 *((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB));

 // Now swap the rest of the structure
 ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB));
#endif
 ::GlobalUnlock((HGLOBAL) hDIB);
 return hDIB;
}
//  add Nov.27,1999
HDIB WINAPI NewDIB(long width, long height,unsigned short biBitCount) // add "biBitCount" by hchen Jan 25,00
{
 long dwindth = (width*biBitCount/8+3)/4*4; // align 4 bytes
 WORD color_num;
 switch(biBitCount)
 {
  case 1:
   color_num=2;
   break;

  case 4:
   color_num=16;
   break;
  case 8:
   color_num=256;
   break;
  default:
   color_num=0;
   break;
 }

 long dwBitsSize = dwindth *height + 40 + color_num*4;// 40 LPBIMHEAD

 LPSTR pDIB;
 HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
 if (hDIB == 0)
 {
  return NULL;
 }
 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
 
 LPBITMAPINFO lpmf = (LPBITMAPINFO)pDIB;
 lpmf->bmiHeader.biSize = 40;//40
 lpmf->bmiHeader.biWidth = width; //i_info.width;
    lpmf->bmiHeader.biHeight = height;
    lpmf->bmiHeader.biPlanes = 1;
 lpmf->bmiHeader.biBitCount = biBitCount;// 24
 lpmf->bmiHeader.biCompression = 0;
    lpmf->bmiHeader.biSizeImage = dwindth *height;
 lpmf->bmiHeader.biXPelsPerMeter = 2925;
    lpmf->bmiHeader.biYPelsPerMeter = 2925;
    lpmf->bmiHeader.biClrUsed = 0;
 lpmf->bmiHeader.biClrImportant= 0;  

 if(color_num!=0)
 {
  for(int i=0;i<color_num;i++)
  {
   lpmf->bmiColors[i].rgbRed =(BYTE)i;
   lpmf->bmiColors[i].rgbGreen =(BYTE)i;
   lpmf->bmiColors[i].rgbBlue =(BYTE)i;
  }
 }

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

#ifdef _MAC
void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader)
{
 bmfHeader->bfType = SWAPWORD(bmfHeader->bfType);
 bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize);
 bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits);
}


void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header)
{
 // Note this doesn't swap the bcSize/biSize field.  It assumes that the
 // size field was swapped during read or while setting the fWin30Header
 // flag.

 if (fWin30Header)
 {
  LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader);

  //lpBMIH->biSize = SWAPLONG(lpBMIH->biSize);
  lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth);
  lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight);
  lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes);
  lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount);
  lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression);
  lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage);
  lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter);
  lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter);
  lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed);
  lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant);
 }
 else
 {
  LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader);

  lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth);
  lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight);
  lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes);
  lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount);
 }
}

#endif
/*************************************************************************
 *
 * 函数名称:
 *   EdgeDetect()
 *
 * 参数:
 *   LPSTR lpDIBBits - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *  
 * 返回值:
 *   BOOL            - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来对图象进行轮廓提取,前提是图象数据必须是只有0和255的二值图象
 *   0表示物体,255为背景,采用掏空内部点的原理
 *
 ************************************************************************/
BOOL  WINAPI EdgeDetect(LPSTR lpDIBBits,long lWidth,long lHeight)
{  
 LPSTR  lpsrc;
 LPSTR  lpDst;
 BYTE   pixel;
 long   lLineBytes=WIDTHBYTES(lWidth*8);
 LPSTR  lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
    return FALSE;
 
 int i,j;
 BYTE w,e,s,n,sw,nw,ne,se;
 
/* for(i=0;i<lHeight;i++)
  for(j=0;j<lWidth;j++)
  {
   lpsrc=lpDIBBits+lLineBytes*i+j;
   pixel=(BYTE)*lpsrc;
   if(pixel>=120)
    *lpsrc=(BYTE)255;
   else
    *lpsrc=(BYTE)0;
  }*/
  
 memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
 
 for(i=1;i<lHeight-1;i++)
  for(j=1;j<lWidth-1;j++)
  {
   lpsrc=lpDIBBits+lLineBytes*i+j;
   lpDst=lpbuff+lLineBytes*i+j;
   pixel=(BYTE)*lpDst;
   if(pixel!=255 && pixel!=0)
   {
     return FALSE;
   }
   if((*lpDst)==0)
   {
    w=(BYTE)*(lpDst-1);
    e=(BYTE)*(lpDst+1);
    nw=(BYTE)*(lpDst+lLineBytes-1);
    n=(BYTE)*(lpDst+lLineBytes);
    ne=(BYTE)*(lpDst+lLineBytes+1);
    se=(BYTE)*(lpDst-lLineBytes+1);
    s=(BYTE)*(lpDst-lLineBytes);
    sw=(BYTE)*(lpDst-lLineBytes-1);
    if(w+e+nw+n+ne+se+s+sw==0)
     (*lpsrc)=(BYTE)255;
   }
  }
   
 delete[] lpbuff;
 return TRUE;
 
}
/*************************************************************************
 *
 * 函数名称:
 *   ContourTrace()
 *
 * 参数:
 *   LPSTR lpDIBBits - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *  
 * 返回值:
 *   BOOL            - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来对图象进行轮廓跟踪,前提是图象数据必须是只有0和255的二值图象
 *   0表示物体,255为背景
 *
 ************************************************************************/
BOOL WINAPI ContourTrace(LPSTR lpDIBBits,long lWidth,long lHeight)
{
 LPSTR  lpsrc;
 LPSTR  lpDst;
 BYTE   pixel;
 long   lLineBytes=WIDTHBYTES(lWidth*8);
 LPSTR  lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE;
    memset(lpbuff,(BYTE)255,lLineBytes*lHeight);
 int    i,j;
 bool   IsStartPoint;
 bool   PointFind;
 CPoint StartPoint;
 CPoint CurrentPoint;
 int    Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
 int    BeginDirect;
 IsStartPoint=false;
 for(i=1;i<lHeight-1 && !IsStartPoint;i++)
   for(j=1;j<lWidth-1 && !IsStartPoint;j++)
   {
    lpsrc=lpDIBBits+lLineBytes*i+j;
          pixel=(BYTE)*lpsrc;
          if(pixel!=255 && pixel!=0)
    {
     return FALSE;
    }
    if(pixel==0)
    {
     StartPoint.x=j;
     StartPoint.y=i;
     IsStartPoint=true;
     lpDst=lpbuff+lLineBytes*i+j;
     *lpDst=(BYTE)0;
    }
   }
    
 BeginDirect=0;
 IsStartPoint=false;
 CurrentPoint.x=StartPoint.x;
 CurrentPoint.y=StartPoint.y;
 while (!IsStartPoint)
 {
  PointFind=false;
  while (!PointFind)
  {
    lpsrc=lpDIBBits+lLineBytes*(CurrentPoint.y+Direction[BeginDirect][1])+
       (CurrentPoint.x+Direction[BeginDirect][0]);
    pixel=(BYTE)*lpsrc;
    if (pixel==0)
    {
     PointFind=true;
     CurrentPoint.x=CurrentPoint.x+Direction[BeginDirect][0];
     CurrentPoint.y=CurrentPoint.y+Direction[BeginDirect][1];
     if(CurrentPoint.x==StartPoint.x && CurrentPoint.y==StartPoint.y)
     {
      IsStartPoint=true;
     }
     lpDst=lpbuff+lLineBytes*CurrentPoint.y+CurrentPoint.x;
     *lpDst=(BYTE)0;

     BeginDirect--;
     if(BeginDirect==-1)
      BeginDirect=7;
     if(BeginDirect==-1)
      BeginDirect=7;
       
    }
          else
    {
     BeginDirect++;
     if(BeginDirect==8)
     {
      BeginDirect=0;
     }
    }
  }
 }
    memcpy(lpDIBBits,lpbuff,lLineBytes*lHeight);
 delete[] lpbuff;
 return TRUE;
 
}

/*************************************************************************
 *
 * 函数名称:
 *   Template()
 *
 * 参数:
 *   LPSTR lpDIBBits  - 指向源DIB的指针
 *   long lWidth         - 图象的宽度
 *   long lHeight           - 图象的高度
 *   float *temp            - 指向模板地址的指针
 *   int temp_w             - 模板宽
 *   int temp_h             - 模板高
 *   float xishu            - 模板系数
 * 返回值:
 *   BOOL           - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现模板操作(卷积运算)。
 *
 ************************************************************************/
BOOL WINAPI Template(LPSTR lpDIBBits,long lWidth,long lHeight,float *temp,int temp_w,int temp_h,float xishu)
{
 LPSTR  lpsrc;
 LPSTR  lpDst;
 BYTE   pixel;
 long   lLineBytes=WIDTHBYTES(lWidth*8);
 LPSTR  lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
    return FALSE;
    memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
 int    i,j,m,n;
 double sum=0.0;
 for(i=(temp_h-1)/2;i<lHeight-(temp_h-1)/2;i++)
   for(j=temp_w/2;j<lWidth-temp_w/2;j++)
   {  
    sum=0.0;
    lpsrc=lpDIBBits+lLineBytes*i+j;
    for(m=-(temp_h-1)/2;m<=(temp_h-1)/2;m++)
   for(n=-(temp_w-1)/2;n<=(temp_w-1)/2;n++)
   {
    lpDst=lpbuff+lLineBytes*(m+i)+n+j;
    pixel=(BYTE)*lpDst;
    sum+=pixel*temp[(m+temp_h/2)*temp_w+(n+temp_w/2)];
   }
          sum=(int)(sum*xishu);
    if(sum<0)
     sum=0;
    if(sum>255)
     sum=255;
    *lpsrc=(BYTE)sum;
   
   }
 delete[] lpbuff;
 return TRUE;
 
}
/*************************************************************************
 *
 * 函数名称:
 *   MaxImg()
 *
 * 参数:
 *   LPSTR img  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *  
 * 返回值:
 *   BOOL             - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现对图象的最大值滤波。
 *
 ************************************************************************/
BOOL MaxImg(LPSTR img,long lWidth,long lHeight)
{
    LPSTR lpsrc;
 LPSTR lpbuff;
 LPSTR lpDst;
 BYTE  pixel;
 long lLineBytes=(lWidth*8+31)/32*4;
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE; 
 memcpy(lpbuff,img,lLineBytes*lHeight);
 int i,j,m,n;
    for(i=1;i<lHeight-1;i++)
  for(j=1;j<lWidth-1;j++)
  { 
   lpsrc=img+i*lLineBytes+j;
   for(m=-1;m<=1;m++)
    for(n=-1;n<=1;n++)
    {
     lpDst=lpbuff+(i+m)*lLineBytes+(j+n);
     pixel=(BYTE)*lpDst;
     if(*lpsrc<pixel)
      *lpsrc=*lpDst;
    }
  }
 delete[] lpbuff;
 return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   MinImg()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 * 返回值:
 *   BOOL             - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现3*3模板的中值滤波
 *
 ************************************************************************/
BOOL MinImg(LPSTR img,long lWidth,long lHeight)
{
    LPSTR lpsrc;
 LPSTR lpbuff;
 LPSTR lpDst;
 BYTE  pixel;
 long lLineBytes=(lWidth*8+31)/32*4;
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return NULL;
 memcpy(lpbuff,img,lLineBytes*lHeight);
 int i,j,m,n;
    for(i=1;i<lHeight-1;i++)
  for(j=1;j<lWidth-1;j++)
  { 
   lpsrc=img+i*lLineBytes+j;
   for(m=-1;m<=1;m++)
    for(n=-1;n<=1;n++)
    {
     lpDst=lpbuff+(i+m)*lLineBytes+(j+n);
     pixel=(BYTE)*lpDst;
     if(*lpsrc>pixel)
      *lpsrc=*lpDst;
    }
  }
  delete[] lpbuff;
  return TRUE;
}
/*************************************************************************
 *
 * 函数名称:
 *   MiddleImg()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 * 返回值:
 *   BOOL              - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现3*3模板的中值滤波
 *
 ************************************************************************/

BOOL  MiddleImg(LPSTR img,long lWidth,long lHeight)
{
    LPSTR lpsrc;
 LPSTR lpbuff;

 long lLineBytes=(lWidth*8+31)/32*4;
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE;
 memcpy(lpbuff,img,lLineBytes*lHeight);
 BYTE *temp=new BYTE[9];
    BYTE mid;
 int i,j,m,n;
    for(i=1;i<lHeight-1;i++)
  for(j=1;j<lWidth-1;j++)
  { 
   lpsrc=img+i*lLineBytes+j;
   for(m=-1;m<=1;m++)
    for(n=-1;n<=1;n++)
    {
     temp[(m+1)*3+(n+1)]=(BYTE)*(lpbuff+(i+m)*lLineBytes+(j+n));
    }
    for(m=0;m<5;m++)
    {
     
     for(n=0;n<8-m;n++)
     {
      if(temp[n]>temp[n+1])
      {
        mid=temp[n];
        temp[n]=temp[n+1];
           temp[n+1]=mid;
      }
     }
    }
    *lpsrc=temp[4];
  }
   delete[] lpbuff;
   return TRUE;
}
/*************************************************************************
 *
 * 函数名称:
 *   Erosion()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *   int ErosionType    - 腐蚀的类型
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现对图象的腐蚀处理
 *
 ************************************************************************/
BOOL Erosion(LPSTR lpDIBBits,long lWidth,long lHeight,int ErosionType)
{
    LPSTR lpsrc;
 LPSTR lpbuff;
 LPSTR lpDst;
 BYTE  pixel;
 long lLineBytes=WIDTHBYTES(lWidth*8);
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE;
 memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
 int i,j,m,n; 
 if(ErosionType==0)
 {
       for(i=0;i<lHeight;i++)
  for(j=1;j<lWidth-1;j++)
  {
   lpsrc=lpDIBBits+lLineBytes*i+j;
   lpDst=lpbuff+lLineBytes*i+j;
   pixel=(BYTE)*lpDst;
   if(pixel==0)
   {
    if(*(lpDst-1)!=0 || *(lpDst+1)!=0)
                   *lpsrc=(BYTE)255;
   }
  }
 }
 else if (ErosionType==1)
 {
  for(i=1;i<lHeight-1;i++)
   for(j=0;j<lWidth;j++)
   {
   lpsrc=lpDIBBits+lLineBytes*i+j;
   lpDst=lpbuff+lLineBytes*i+j;
      pixel=(BYTE)*lpDst;
   if(pixel==0)
    {
     if(*(lpDst-lLineBytes)!=0 || *(lpDst+lLineBytes)!=0)
      *lpsrc=(BYTE)255;
    }
   }

 }
    else if (ErosionType==2)
 {
     for(i=1;i<lHeight-1;i++)
   for(j=1;j<lWidth-1;j++)
   {
   lpsrc=lpDIBBits+lLineBytes*i+j;
   pixel=(BYTE)*lpsrc;
   if(pixel==0)
   {  
    for(m=-1;m<=1;m++)
    {
      for(n=-1;n<=1;n++)
     {
      lpDst=lpbuff+lLineBytes*(m+i)+n+j;
      if(*lpDst!=0)
      { 
       *lpsrc=(BYTE)255;
       break;
      }
     }
      if(*lpsrc==255)
          break;
    }
   }
   }
    }
 
 delete[] lpbuff;
    return TRUE;
 
}
/*************************************************************************
 *
 * 函数名称:
 *   Dialation()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *   int DialationType  - 膨胀的类型
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现对图象的膨胀处理
 *
 ************************************************************************/
BOOL Dialation(LPSTR lpDIBBits,long lWidth,long lHeight,int DialationType)
{
    LPSTR lpsrc;
 LPSTR lpbuff;
 LPSTR lpDst;
 BYTE  pixel;
 long lLineBytes=WIDTHBYTES(lWidth*8);
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE;
 memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
 int i,j,m,n; 
 if(DialationType==0)
 {
  for(i=0;i<lHeight;i++)
   for(j=1;j<lWidth-1;j++)
   {
    lpsrc=lpDIBBits+lLineBytes*i+j;
    lpDst=lpbuff+lLineBytes*i+j;
    pixel=(BYTE)*lpDst;
    if(pixel==255)
    {
     if(*(lpDst-1)==0 || *(lpDst+1)==0)
      *lpsrc=(BYTE)0;
    }
   }
 }
 else if (DialationType==1)
 {
  for(i=1;i<lHeight-1;i++)
   for(j=0;j<lWidth;j++)
   {
    lpsrc=lpDIBBits+lLineBytes*i+j;
    lpDst=lpbuff+lLineBytes*i+j;
    pixel=(BYTE)*lpDst;
    if(pixel==255)
    {
     if(*(lpDst-lLineBytes)==0 || *(lpDst+lLineBytes)==0)
      *lpsrc=(BYTE)0;
    }
   }
   
 }
    else if (DialationType==2)
 {
  for(i=1;i<lHeight-1;i++)
   for(j=1;j<lWidth-1;j++)
   {
    lpsrc=lpDIBBits+lLineBytes*i+j;
    pixel=(BYTE)*lpsrc;
    if(pixel==255)
    {  
     for(m=-1;m<=1;m++)
     {
      for(n=-1;n<=1;n++)
      {
       lpDst=lpbuff+lLineBytes*(m+i)+n+j;
       if(*lpDst==0)
       { 
        *lpsrc=(BYTE)0;
        break;
       }
      }
      break;
     }
    }
   }
    }
 
 delete[] lpbuff;
    return TRUE;
}
/*************************************************************************
 *
 * 函数名称:
 *   MirrorImg()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   long lWidth     - 图象的宽度
 *   long lHeight       - 图象的高度
 *   int mirrorType     - 镜像的类型
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来实现对图象的水平镜像处理
 *
 ************************************************************************/
BOOL MirrorImg(LPSTR lpDIBBits,long lWidth,long lHeight,int mirrorType)
{
 LPSTR lpsrc;
 LPSTR lpbuff;
 LPSTR lpDst;
 long lLineBytes=WIDTHBYTES(lWidth*8);
 lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
 if(lpbuff==NULL)
  return FALSE;
 memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
 int i,j; 
 if(mirrorType==0)
 {
    for(i=0;i<lHeight;i++)
     for(j=0;j<lWidth;j++)
  {
    lpsrc=lpDIBBits+lLineBytes*i+j;
    lpDst=lpbuff+lLineBytes*i+(lWidth-1-j);
    *lpsrc=*lpDst;
  }
 }
   else if (mirrorType==1)
   {
    for(i=0;i<lHeight;i++)
     for(j=0;j<lWidth;j++)
     {
      lpsrc=lpDIBBits+lLineBytes*i+j;
      lpDst=lpbuff+lLineBytes*(lHeight-i-1)+j;
      *lpsrc=*lpDst;
     }
   }
  return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   RotateDIB()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   int iRotateAngle - 旋转的角度(0-360度)
 *
 * 返回值:
 *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。
 *
 * 说明:
 *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
 * 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
 * 值算法进行插值。
 *
 ************************************************************************/

HGLOBAL WINAPI RotateImg(LPSTR lpDIB, float iRotateAngle)
{
 
 // 源图像的宽度和高度
 LONG lWidth;
 LONG lHeight;
 
 // 旋转后图像的宽度和高度
 LONG lNewWidth;
 LONG lNewHeight;
 
 // 图像每行的字节数
 LONG lLineBytes;
 
 // 旋转后图像的宽度(lNewWidth',必须是4的倍数)
 LONG lNewLineBytes;
 
 // 指向源图像的指针
 LPSTR lpDIBBits;
 
 // 指向源象素的指针
 LPSTR lpSrc;
 
 // 旋转后新DIB句柄
 HDIB hDIB;
 
 // 指向旋转图像对应象素的指针
 LPSTR lpDst;
 
 // 指向旋转图像的指针
 LPSTR lpNewDIB;
 LPSTR lpNewDIBBits;
 
 // 指向BITMAPINFO结构的指针(Win3.0)
 LPBITMAPINFOHEADER lpbmi;
 
 // 指向BITMAPCOREINFO结构的指针
 LPBITMAPCOREHEADER lpbmc;
 
 // 循环变量(象素在新DIB中的坐标)
 LONG i;
 LONG j;
 
 // 象素在源DIB中的坐标
 LONG i0;
 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;
 
 // 找到源DIB图像象素起始位置
 lpDIBBits = ::FindDIBBits(lpDIB);
 
 // 获取图像的"宽度"(4的倍数)
 lWidth = ::DIBWidth(lpDIB);
 
 // 计算图像每行的字节数
 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;
}

/*************************************************************************
 *
 * 函数名称:
 *   ThresholdDIB()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数)
 *   LONG  lHeight      - 源图像高度(象素数)
 *
 * 返回值:
 *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 * 该函数用于对图像进行阈值分割运算。
 *
 ************************************************************************/

BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
 
 // 指向源图像的指针
 LPSTR lpSrc;
 
 // 指向缓存图像的指针
 LPSTR lpDst;
 
 // 指向缓存DIB图像的指针
 LPSTR lpNewDIBBits;
 HLOCAL hNewDIBBits;

 //循环变量
 long i;
 long j;

 //像素值
 unsigned char pixel;

 //直方图数组
 long lHistogram[256];

 //阈值,最大灰度值与最小灰度值,两个区域的平均灰度值
 unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;

 //用于计算区域灰度平均值的中间变量
 long lP1,lP2,lS1,lS2;

 //迭代次数
 int iIterationTimes;

 // 图像每行的字节数
 LONG lLineBytes;

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

 if (hNewDIBBits == NULL)
 {
  // 分配内存失败
  return FALSE;
 }
 
 // 锁定内存
 lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

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

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

 for (i = 0; i < 256;i++)
 {
  lHistogram[i]=0;
 }

 //获得直方图
 iMaxGrayValue = 0;
 iMinGrayValue = 255;
 for (i = 0;i < lWidth ;i++)
 {
  for(j = 0;j < lHeight ;j++)
  {
   // 指向源图像倒数第j行,第i个象素的指针   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
 
   pixel = (unsigned char)*lpSrc;
   
   lHistogram[pixel]++;
   //修改最大,最小灰度值
   if(iMinGrayValue > pixel)
   {
    iMinGrayValue = pixel;
   }
   if(iMaxGrayValue < pixel)
   {
    iMaxGrayValue = pixel;
   }
  }
 }

 //迭代求最佳阈值
 iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
 iThreshold = 0;
 
 for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
 {
  iThreshold = iNewThreshold;
  lP1 =0;
  lP2 =0;
  lS1 = 0;
  lS2 = 0;
  //求两个区域的灰度平均值
  for (i = iMinGrayValue;i < iThreshold;i++)
  {
   lP1 += lHistogram[i]*i;
   lS1 += lHistogram[i];
  }
  iMean1GrayValue = (unsigned char)(lP1 / lS1);
  for (i = iThreshold+1;i < iMaxGrayValue;i++)
  {
   lP2 += lHistogram[i]*i;
   lS2 += lHistogram[i];
  }
  iMean2GrayValue = (unsigned char)(lP2 / lS2);
  iNewThreshold =  (iMean1GrayValue + iMean2GrayValue)/2;
 }

 //根据阈值将图像二值化
 for (i = 0;i < lWidth ;i++)
 {
  for(j = 0;j < lHeight ;j++)
  {
   // 指向源图像倒数第j行,第i个象素的指针   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
 
   // 指向目标图像倒数第j行,第i个象素的指针   
   lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;

   pixel = (unsigned char)*lpSrc;
   
   if(pixel >= iThreshold)
   {
    *lpDst = (unsigned char)255;
   }
   else
   {
    *lpDst = (unsigned char)0;
   }
  }
 }

 // 复制图像
 memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

 // 释放内存
 LocalUnlock(hNewDIBBits);
 LocalFree(hNewDIBBits);

 // 返回
 return TRUE;
}

/*************************************************************************
直方图均衡子函数
************************************************************************/
BOOL WINAPI 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);
 
 // 重置计数为0
 for (i = 0; i < 256; i ++)
 {
  // 清零
  lCount[i] = 0;
 }
 
 // 计算各个灰度值的计数
 for (i = 0; i < lHeight; i ++)
 {
  for (j = 0; j < lWidth; j ++)
  {
   lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
   
   // 计数加1
   lCount[*(lpSrc)]++;
  }
 }
 
 // 计算灰度映射表
 for (i = 0; i < 256; i++)
 {
  // 初始为0
  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;
}

/******************************************************************************** * DIBAPI.H * * Header file for Device-Independent Bitmap (DIB) API. Provides * function prototypes and constants for DIB functions ********************************************************************************/ #ifndef __DIBAPI_H_ #define __DIBAPI_H_ ////////////////////////////////////////////////////////// /* Handle to a DIB */ #define HDIB HANDLE // Dib Header Marker - used in writing DIBs to files #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') /* DIB constants */ #define PALVERSION 0x300 /* DIB copy constants */ #define PW_WINDOW 1 #define PW_CLIENT 2 // Image position in Canvas #define LEFT_UP 1 #define CENTER_UP 2 #define RIGHT_UP 3 #define LEFT_CENTER 4 #define CENTER_CENTER 5 #define CENTER_RIGHT 6 #define LEFT_DOWN 7 #define CENTER_DOWN 8 #define RIGHT_DOWN 9 /* Gray Method */ #define MEAN_GRAY 0 #define MAXIMUM_GRAY 1 #define WEIGHT_GRAY 2 /* Color Model */ #define RGB_COLOR 0 #define CMYK_COLOR 1 #define HSI_COLOR 2 #define HLS_COLOR 3 #define UNDEFINED (-1.0) // Separate color #define SEPARATE_RED 1 #define SEPARATE_GREEN 2 #define SEPARATE_BLUE 3 // Filte color #define FILTE_RED 1 #define FILTE_GREEN 2 #define FILTE_BLUE 3 // Filter algorithm #define FILTER1 1 #define FILTER2 2 #define FILTER3 3 // Edge enhancement algorithm #define VERT 1 #define HORZ 2 #define VERTHORZ 3 #define NORTH 4 #define NORTHEAST 5 #define EAST 6 #define SOUTH 7 #define SOUTHEAST 8 #define SOUTHWEST 9 #define WEST 10 #define NORTHWEST 11 #define LAP1 12 #define LAP2 13 #define LAP3 14 #define LAP4 15 #define SOBEL 16 #define HOUGH 17 /* DIB Macros*/ // WIDTHBYTES performs DWORD-aligning of DIB scanlines. The "bits" // parameter is the bit count for the scanline (biWidth * biBitCount), // and this macro returns the number of DWORD-aligned bytes needed // to hold those bits. #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) #define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER)) #define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left) #define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top) #define BOUND(x, mn, mx) ((x) < (mn) ? (mn) : ((x) > (mx) ? (mx) : (x))) #define WaitCursorBegin() HCURSOR hcURSOR = SetCursor(LoadCursor(NULL, IDC_WAIT)) #define WaitCursorEnd() SetCursor(hcURSOR) /* function prototypes */ // DIB initialization HDIB CreateDIB(DWORD, DWORD, WORD); HDIB CreateDefaultDIB(DWORD dwWidth, DWORD dwHeight); void DestroyDIB(HDIB); HDIB LoadDIB (LPTSTR); BOOL SaveDIB (HDIB, LPTSTR); HDIB ReadDIBFile(HANDLE); BOOL WriteDIBFile(HDIB hDib, HANDLE hFile); // DIB attributes DWORD BytesPerLine(LPBYTE lpDIB); DWORD BytesPerLine(HDIB hDIB); DWORD DIBlockSize(HDIB hDIB); DWORD DIBlockSize(LPBYTE lpDIB); DWORD DIBHeight (LPBYTE lpDIB); DWORD DIBHeight (HDIB hDIB); DWORD DIBWidth (LPBYTE lpDIB); DWORD DIBWidth (HDIB hDIB); WORD DIBNumColors (LPBYTE lpDIB); WORD DIBNumColors (HDIB hDIB); WORD DIBBitCount (LPBYTE lpDIB); WORD DIBBitCount (HDIB hDIB); LPBYTE FindDIBBits (LPBYTE lpDIB); WORD PaletteSize (LPBYTE lpDIB); WORD PaletteSize (HDIB hDIB); // DIB display BOOL PaintBitmap(HDC, LPRECT, HBITMAP, LPRECT, HPALETTE, DWORD); BOOL PaintDIB(HDC, LPRECT, HDIB, LPRECT, HPALETTE, DWORD); BOOL DitherDisplayDIB(HDC, LPRECT, HDIB, LPRECT, DWORD); // DIB operations HBITMAP DIBToDIBSection(LPBYTE lpDIB); HBITMAP DIBToDIBSection(HDIB hDIB); HDIB DIBSectionToDIB(HBITMAP hBitmap); HDIB ConvertDIBFormat(LPBYTE lpSrcDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc); HDIB ConvertDIBFormat(HDIB hDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc); HDIB ConvertDIBFormat(LPBYTE lpSrcDIB, UINT nbpp, HPALETTE hPalSrc); HDIB ConvertDIBFormat(HDIB hDIB, UINT nbpp, HPALETTE hPalSrc); HDIB BitmapToDIB (HBITMAP, HPALETTE); HDIB BitmapToDIB (HBITMAP, HPALETTE, WORD); HDIB ChangeBitmapFormat (HBITMAP, WORD, DWORD, HPALETTE); HBITMAP DIBToBitmap (HDIB hDIB, HPALETTE hPal); HDIB ChangeDIBFormat (HDIB, WORD, DWORD); // DIB palette HPALETTE CreateDIBPalette(LPBYTE lpDIB); HPALETTE CreateDIBPalette(HDIB hDIB); BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal); HPALETTE CopyPalette(HPALETTE hPalSrc); HPALETTE GetSystemPalette(void); int PalEntriesOnDevice (HDC hDC); HPALETTE CreateIdentifyPalette(HPALETTE hPalSrc); BOOL MapDIBColorsToPalette(HDIB hDIB, HPALETTE hPalette); HPALETTE CreateDitherPalette(); HDIB CreateDither8BppDIB(HDIB hDIB); // DIB capture HBITMAP CopyScreenToBitmap (LPRECT); HBITMAP CopyWindowToBitmap (HWND, WORD); HBITMAP CopyClientRectToBitmap(HWND hWnd, LPRECT lpRect); HDIB CopyScreenToDIB (LPRECT); HDIB CopyWindowToDIB (HWND, WORD); HDIB CopyClientRectToDIB(HWND hWnd, LPRECT lpRect); // effect display void DrawTransparentBitmap(HDC, HBITMAP, LONG, LONG, COLORREF); BOOL Fade(int nDeltaR, int nDeltaG, int nDeltaB, BYTE rm, BYTE gm, BYTE bm, BYTE *r, BYTE *g, BYTE *b); // Helper HANDLE CopyHandle(HANDLE h); void Delay(DWORD dwDelayTime); // DIB transform HBITMAP CropBitmap(HBITMAP, LPRECT); HDIB CropDIB(HDIB, LPRECT); HDIB CutDIB(HDIB, LPRECT); HDIB MergeDIB(HDIB hDib1, HDIB hDib2, POINT ptTopLeft); HDIB TransparentMergeDIB(HDIB hDIB1, HDIB hDIB2, POINT ptTopLeft, COLORREF crTransparent); HBITMAP RotateBitmapNT(HBITMAP hBitmap, double fDegrees, COLORREF clrBack); HBITMAP RotateBitmap(HBITMAP hBitmap, double fDegrees, COLORREF clrBack); HDIB RotateDIB(HDIB hDIB, double fDegrees, COLORREF clrBack); HDIB RotateDIB(HDIB hDib); HDIB FlipHorzDIB(HDIB hDib); HDIB FlipVertDIB(HDIB hDib); HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight); HDIB ChangeDIBCanvasSize(HDIB hDIB, int nWidth, int nHeight, int nPosition); // Color quantization HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits); HPALETTE CreateOctreePalette(LPBYTE lpDIB, UINT nMaxColors, UINT nColorBits); // color process HDIB SeparateRGBfromDIB(HDIB hDib, int nIndex); HDIB FilteRGBfromDIB(HDIB hDib, int nIndex); HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors); HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod, double fRedWeight, double fGreenWeight, double fBlueWeight); BOOL AdjustDIBColor(HDIB hDib, int nColorModel, int v1, int v2, int v3); BOOL AdjustDIBBrightness(HDIB hDib, int v); BOOL AdjustDIBContrast(HDIB hDib, int v); void RGBtoHSI(BYTE r, BYTE g, BYTE b, double *h, double *s, double *i); void HSItoRGB(double h, double s, double i, BYTE *r, BYTE *g, BYTE *b); void RGBtoHLS(BYTE r, BYTE g, BYTE b, double *h, double *l, double *s); void HLStoRGB(double h, double l, double s, BYTE *r, BYTE *g, BYTE *b); void CMYKtoRGB(BYTE c, BYTE m, BYTE y, BYTE k, BYTE *r, BYTE *g, BYTE *b); void RGBtoCMYK(BYTE r, BYTE g, BYTE b, BYTE *c, BYTE *m, BYTE *y, BYTE *k); void ChangeContrast(int nDelta, BYTE *r, BYTE *g, BYTE *b); void ChangeBrightness(int nDelta, BYTE *r, BYTE *g, BYTE *b); // image process BOOL HighPassDIB(HDIB hDib, int Strength, int nAlgorithm); BOOL LowPassDIB(HDIB hDib, int Strength, int nAlgorithm); BOOL EdgeEnhanceDIB(HDIB hDib, int Strength, int nDirection); BOOL MedianFilterDIB(HDIB hDib); BOOL ErosionDIB(HDIB hDib, BOOL bHori); BOOL DilationDIB(HDIB hDib, BOOL bHori); BOOL MorphOpenDIB(HDIB hDib, BOOL bHori); BOOL MorphCloseDIB(HDIB hDib, BOOL bHori); BOOL ContourDIB(HDIB hDib, BOOL bHori); BOOL ThinningDIB(HDIB hDib); BOOL ReverseDIB(HDIB hDib); BOOL FFTDIB(HDIB hDIB); BOOL DCTDIB(HDIB hDIB); BOOL WALhDIB(HDIB hDIB); ////////////////////////////////////////////////////////// #endif //__DIBAPI_H_
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值