www.pudn.com > backmode824.rar > Dibapi.cpp


#include "WindowsX.h" 
#include "stdafx.h" 
#include "mmsystem.h" 
#include "math.h" 
#include "Dibapi.h" 
// Compile using winmm.lib 
 
//*********************************************** 
//                调色板函数群  
//  ********************************************** 
//********************************************** 
//     HPALETTE CreateDIBPalette(LPBYTE lpbi) 
//********************************************* 
HPALETTE CreateDIBPalette(LPBYTE lpbi) 
{ 
	LPLOGPALETTE lpPal; 
	HANDLE hLogPal; 
	HPALETTE hPal=NULL; 
	LPBITMAPINFO lpbmi; 
	LPBITMAPCOREINFO lpbmc; 
	BOOL bWinStyleDIB; 
	int i,wNumColors; 
 
	if(!lpbi) 
		return NULL; 
	lpbmi=(LPBITMAPINFO)lpbi; 
	lpbmc=(LPBITMAPCOREINFO)lpbi; 
//	 
	wNumColors=DIBNumColors(lpbi); 
	if(wNumColors==0) 
		return NULL; 
	bWinStyleDIB=IS_WIN30_DIB(lpbi); 
	if(wNumColors) 
	{ 
		hLogPal=GlobalAlloc(GHND,sizeof(LOGPALETTE)* 
			sizeof(PALETTEENTRY)*wNumColors); 
		if(!hLogPal) 
		{ 
			//GlobalUnlock(lpbi); 
			return NULL; 
		} 
		lpPal=(LPLOGPALETTE)GlobalLock(hLogPal); 
		lpPal->palVersion=PALVERSION; 
		lpPal->palNumEntries=wNumColors; 
		for(i=0;ipalPalEntry[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 
			{ 
				//	GlobalUnlock(lpbi); 
				//	lpbmc=(LPBITMAPCOREINFO)GlobalLock(lpbi); 
					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; 
			} 
		} 
		hPal=CreatePalette(lpPal); 
		if(!hPal) 
		{ 
			GlobalUnlock(hLogPal); 
			GlobalFree(hLogPal); 
		//	GlobalUnlock(lpbi); 
			return NULL; 
		} 
 
		GlobalUnlock(hLogPal); 
		GlobalFree(hLogPal); 
	} 
//	GlobalUnlock(lpbi); 
	return hPal;  
} 
 
//*********************************************** 
//         HPALETTE GetSystemPalette(void) 
//  ********************************************** 
HPALETTE GetSystemPalette(void) 
{ 
	HDC hDC; 
	static HPALETTE hPal=NULL; 
	HANDLE hLogPal; 
	LPLOGPALETTE lpLogPal; 
	int nColors; 
 
	hDC=GetDC(NULL); 
	if(!hDC) 
		return NULL; 
	nColors=PalEntriesOnDevice(hDC); 
	hLogPal=GlobalAlloc(GHND,sizeof(LOGPALETTE)+nColors* 
		sizeof(PALETTEENTRY)); 
	if(!hLogPal) 
		return NULL; 
	lpLogPal=(LPLOGPALETTE)GlobalLock(hLogPal); 
	lpLogPal->palVersion=PALVERSION; 
	lpLogPal->palNumEntries=nColors; 
	GetSystemPaletteEntries(hDC,0,nColors, 
		(LPPALETTEENTRY)(lpLogPal->palPalEntry)); 
	hPal=CreatePalette(lpLogPal); 
	GlobalUnlock(hLogPal); 
	GlobalFree(hLogPal); 
	ReleaseDC(NULL,hDC); 
	return hPal; 
} 
 
//*********************************************** 
//         int PalEntriesOnDevice(HDC hDC) 
//  ********************************************** 
int PalEntriesOnDevice(HDC hDC) 
{ 
	int nColors; 
	nColors=(1<<(GetDeviceCaps(hDC,BITSPIXEL)* 
		GetDeviceCaps(hDC,PLANES))); 
	 
	if(nColors>256) nColors=256; 
	if(nColors<0) nColors=0; 
	return nColors; 
} 
 
//*********************************************** 
//    BOOL DisplayPalette(HDC hDC,LPRECT lpRect,HPALETTE hPal) 
//  ********************************************** 
BOOL HDisplayPalette(HDC hDC,LPRECT lpRect,HPALETTE hPal) 
{ 
	if(!hPal) 
		return FALSE; 
	int nEntries; 
	PALETTEENTRY pe[256]; 
	nEntries=GetPaletteEntries(hPal,0,256,pe); 
	int nSqr=(int)sqrt((double)nEntries); 
	int nWidth=(lpRect->right-lpRect->left)/nSqr; 
	int nHeight=(lpRect->bottom-lpRect->top)/nSqr; 
	lpRect->right=lpRect->left+nWidth*nSqr; 
	lpRect->bottom=lpRect->top+nHeight*nSqr; 
 
	HPALETTE hOldPalette=(HPALETTE)SelectPalette(hDC,hPal,FALSE); 
	RealizePalette(hDC); 
 
	HBRUSH hBrush,hOldBrush; 
	int x,y; 
	for(int i=0;ileft+x*nWidth, 
				  lpRect->top+y*nHeight, 
				  lpRect->left+(x+1)*nWidth, 
				  lpRect->top+(y+1)*nHeight);				 
		SelectObject(hDC,hOldBrush); 
		DeleteObject(hBrush); 
	} 
	SelectPalette(hDC,hPal,FALSE); 
	return TRUE; 
} 
 
//*********************************************** 
//  BOOL MapDIBColorsToPalette(HDIB hDIB,HPALETTE hPalette) 
//  ********************************************** 
BOOL MapDIBColorsToPalette(HDIB hDIB,HPALETTE hPalette) 
{ 
	if(!hDIB) 
		return FALSE; 
	if(!hPalette) 
		return FALSE; 
	LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
	if(!lpbi) 
		return FALSE; 
	LPRGBQUAD pctThis=(LPRGBQUAD)((LPBYTE)lpbi+lpbi->biSize); 
	BYTE imap[256]; 
	for(int i=0;i<256;i++) 
	{ 
		imap[i]=(BYTE)GetNearestPaletteIndex(hPalette, 
						RGB(pctThis->rgbRed, 
							pctThis->rgbGreen, 
							pctThis->rgbBlue)); 
		pctThis++; 
	} 
	LPBYTE pBits=(LPBYTE)lpbi+lpbi->biSize+PaletteSize((LPBYTE)lpbi); 
	int iSize=WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth)*lpbi->biHeight; 
	while(iSize--) 
	{ 
		*pBits=imap[*pBits]; 
		pBits++; 
	} 
	PALETTEENTRY pe[256]; 
	GetPaletteEntries(hPalette,0,256,pe); 
	pctThis=(LPRGBQUAD)((LPBYTE)lpbi+lpbi->biSize); 
	for(i=0;i<256;i++) 
	{ 
		pctThis->rgbRed=pe[i].peRed; 
		pctThis->rgbGreen=pe[i].peGreen; 
		pctThis->rgbBlue=pe[i].peBlue; 
		pctThis++; 
	} 
	GlobalUnlock(hDIB); 
	return TRUE; 
} 
 
 
 
 
 
//*********************************************** 
//                 属性函数群  
//  ********************************************** 
//*********************************************** 
//           DWORD BytesPerLine(LPBYTE lpDIB) 
//  ********************************************** 
DWORD BytesPerLine(LPBYTE lpDIB) 
{ 
	return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth* 
		((LPBITMAPINFOHEADER)lpDIB)->biPlanes* 
		((LPBITMAPINFOHEADER)lpDIB)->biBitCount); 
} 
 
 
//*********************************************** 
//       DWORD DIBBlockSize(LPBYTE lpDIB) 
//  ********************************************** 
DWORD DIBBlockSize(LPBYTE lpDIB) 
{ 
	if(((LPBITMAPINFOHEADER)lpDIB)->biSizeImage==0) 
	{ 
		((LPBITMAPINFOHEADER)lpDIB)->biSizeImage= 
			BytesPerLine(lpDIB)*((LPBITMAPINFOHEADER) 
			lpDIB)->biHeight; 
	} 
	return ((LPBITMAPINFOHEADER)lpDIB)->biSize+PaletteSize( 
		lpDIB)+((LPBITMAPINFOHEADER)lpDIB)->biSizeImage; 
} 
 
//*********************************************** 
//       WORD DIBBitCount(LPBYTE lpDIB) 
//  ********************************************** 
WORD DIBBitCount(LPBYTE lpDIB) 
{ 
	return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; 
} 
 
//*********************************************** 
//       DWORD DIBHeight(LPBYTE lpDIB) 
//  ********************************************** 
DWORD DIBHeight(LPBYTE lpDIB) 
{ 
	return ((LPBITMAPINFOHEADER)lpDIB)->biHeight; 
} 
 
//********************************************** 
//         WORD DIBNumColors(LPBYTE lpDIB) 
//  ********************************************** 
WORD DIBNumColors(LPBYTE lpDIB) 
{ 
	WORD wBitCount; 
	if(IS_WIN30_DIB(lpDIB)) 
	{ 
		DWORD dwClrUsed; 
		dwClrUsed=((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; 
		if(dwClrUsed) 
		{ 
			return (WORD)dwClrUsed; 
		} 
	} 
	if(IS_WIN30_DIB(lpDIB)) 
		wBitCount=((LPBITMAPINFOHEADER)lpDIB)->biBitCount; 
	else 
		wBitCount=((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; 
 
	switch(wBitCount) 
	{ 
	case 1: 
		return 2; 
	case 4: 
		return 16; 
	case 8: 
		return 256; 
	default: 
		return 0; 
	} 
} 
//*********************************************** 
//        LPBYTE FindDIBBits(LPBYTE lpDIB) 
//  ********************************************** 
LPBYTE FindDIBBits(LPBYTE lpDIB) 
{ 
	DWORD nOffSize; 
	UINT nNumColors; 
 
	nNumColors=DIBNumColors(lpDIB); 
	nOffSize=((LPBITMAPINFOHEADER)lpDIB)->biSize 
		+nNumColors*sizeof(RGBQUAD); 
	return ((LPBYTE)(lpDIB+nOffSize)); 
} 
 
 
//*********************************************** 
//        WORD PaletteSize(LPBYTE lpDIB) 
//  ********************************************** 
WORD PaletteSize(LPBYTE lpDIB) 
{ 
  WORD PalSize; 
  UINT nNumColors; 
   
  if(!(nNumColors=(UINT)(((LPBITMAPINFOHEADER)lpDIB)->biClrUsed))) 
  { 
	if(((LPBITMAPINFOHEADER)lpDIB)->biBitCount!=24) 
		nNumColors=1<<(((LPBITMAPINFOHEADER)lpDIB)->biBitCount); 
  } 
  PalSize=nNumColors*sizeof(RGBQUAD); 
  return PalSize; 
} 
 
 
//*********************************************** 
//           DWORD BytesPerLine(HDIB hDIB) 
//  ********************************************** 
DWORD BytesPerLine(HDIB hDIB) 
{ 
	DWORD nBPL; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
 
	nBPL=WIDTHBYTES(lpbih->biWidth* 
		lpbih->biPlanes*lpbih->biBitCount); 
	GlobalUnlock(hDIB); 
	return nBPL; 
} 
 
 
//*********************************************** 
//       DWORD DIBBlockSize(HDIB hDIB) 
//  ********************************************** 
DWORD DIBBlockSize(HDIB hDIB) 
{ 
	DWORD nBBS; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
 
	if(lpbih->biSizeImage==0) 
	{ 
		lpbih->biSizeImage= 
			BytesPerLine(hDIB)*lpbih->biHeight; 
	} 
	nBBS=lpbih->biSize+PaletteSize(hDIB)*lpbih->biSizeImage; 
	GlobalUnlock(hDIB); 
	return nBBS; 
} 
 
//*********************************************** 
//       WORD DIBBitCount(HDIB hDIB) 
//  ********************************************** 
WORD DIBBitCount(HDIB hDIB) 
{ 
	WORD nBBC; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
 
	nBBC=lpbih->biBitCount; 
	GlobalUnlock(hDIB); 
	return nBBC; 
} 
 
//*********************************************** 
//       DWORD DIBHeight(HDIB hDIB) 
//  ********************************************** 
DWORD DIBHeight(HDIB hDIB) 
{ 
	DWORD nh; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
 
	nh= lpbih->biHeight; 
	GlobalUnlock(hDIB); 
	return nh; 
} 
 
//********************************************** 
//         WORD DIBNumColors(HDIB hDIB) 
//  ********************************************** 
WORD DIBNumColors(HDIB hDIB) 
{ 
	WORD wBitCount; 
	DWORD dwClrUsed; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
	LPBITMAPCOREHEADER lpbich; 
	LPBITMAPCOREINFO   lpbic; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
 
	if(IS_WIN30_DIB(lpbih)) 
	{ 
		dwClrUsed=lpbih->biClrUsed; 
		if(dwClrUsed) 
		{ 
			GlobalUnlock(hDIB); 
			return (WORD)dwClrUsed; 
		} 
	} 
	if(IS_WIN30_DIB(lpbih)) 
	{ 
		wBitCount=lpbih->biBitCount; 
		GlobalUnlock(hDIB); 
	} 
	else 
	{ 
        GlobalUnlock(hDIB); 
		lpbic=(LPBITMAPCOREINFO)GlobalLock(hDIB); 
	    if(lpbic==NULL) return 0; 
	    lpbich=(LPBITMAPCOREHEADER)lpbic; 
	    if(lpbich==NULL) return 0; 
		wBitCount=lpbich->bcBitCount; 
		GlobalUnlock(hDIB); 
	} 
	switch(wBitCount) 
	{ 
	case 1: 
		return 2; 
	case 4: 
		return 16; 
	case 8: 
		return 256; 
	default: 
		return 0; 
	} 
} 
 
//*********************************************** 
//       DWORD DIBWidth(HDIB hDIB) 
//  ********************************************** 
DWORD DIBWidth(HDIB hDIB) 
{ 
	DWORD DibW; 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
	DibW=lpbih->biWidth; 
	GlobalUnlock(hDIB); 
	return DibW; 
} 
 
 
 
//*********************************************** 
//        LPBYTE FindDIBBits(HDIB hDIB) 
//  ********************************************** 
LPBYTE FindDIBBits(HDIB hDIB) 
{ 
	LPBITMAPINFO lpbi; 
	LPBITMAPINFOHEADER lpbih; 
	DWORD nOffSize; 
	UINT nNumColors; 
 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(lpbi==NULL) return 0; 
	lpbih=(LPBITMAPINFOHEADER)lpbi; 
	if(lpbih==NULL) return 0; 
	 
	nNumColors=DIBNumColors(hDIB); 
	nOffSize=lpbih->biSize+nNumColors*sizeof(RGBQUAD); 
//	GlobalUnlock(hDIB); 
	return ((LPBYTE)(lpbih+nOffSize)); 
} 
 
 
//*********************************************** 
//        WORD PaletteSize(HDIB hDIB) 
//  ********************************************** 
WORD PaletteSize(HDIB hDIB) 
{ 
  WORD PalSize; 
  UINT nNumColors; 
  LPBITMAPINFO lpbi; 
  LPBITMAPINFOHEADER lpbih; 
 
  lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
  if(lpbi==NULL) return 0; 
  lpbih=(LPBITMAPINFOHEADER)lpbi; 
  if(lpbih==NULL) return 0; 
  if(!(nNumColors=(UINT)(lpbih->biClrUsed))) 
  { 
	if(lpbih->biBitCount!=24) 
		nNumColors=1<<(lpbih->biBitCount); 
  } 
  GlobalUnlock(hDIB); 
  PalSize=nNumColors*sizeof(RGBQUAD); 
  return PalSize; 
} 
 
 
 
 
//*********************************************** 
//                 初始化函数群  
//  ********************************************** 
//*********************************************** 
//  HDIB CreateDIB(DWORD dwWidth,DWORD dwHeight,WORD wBitCount) 
//  ********************************************** 
HDIB CreateDIB(DWORD dwWidth,DWORD dwHeight,WORD wBitCount) 
{ 
	BITMAPINFOHEADER bi; 
	LPBITMAPINFOHEADER lpbi; 
	DWORD dwLen; 
	HDIB hDIB; 
	DWORD dwBytesPerLine; 
	if(wBitCount<=1) 
		wBitCount=1; 
	else if(wBitCount<=4) 
		wBitCount=4; 
	else if(wBitCount<=8) 
		wBitCount=8; 
	else if(wBitCount<=24) 
		wBitCount=24; 
	else 
		wBitCount=8; 
 
	bi.biSize=sizeof(BITMAPINFOHEADER); 
	bi.biWidth=dwWidth; 
	bi.biHeight=dwHeight; 
	bi.biPlanes=1; 
	bi.biBitCount=wBitCount; 
	bi.biCompression=BI_RGB; 
	bi.biSizeImage=0; 
	bi.biXPelsPerMeter=0; 
	bi.biYPelsPerMeter=0; 
	bi.biClrUsed=0; 
	bi.biClrImportant=0; 
 
	dwBytesPerLine=WIDTHBYTES(wBitCount *dwWidth); 
	dwLen=bi.biSize+PaletteSize((LPBYTE)&bi)+ 
		(dwBytesPerLine*dwHeight); 
	hDIB=GlobalAlloc(GHND,dwLen); 
	if(!hDIB) 
		return NULL; 
	lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
	*lpbi=bi; 
	GlobalUnlock(hDIB); 
	return hDIB;	 
} 
 
 
//*********************************************** 
//  HDIB CreateDefaultDIB(DWORD dwWidth,DWORD dwHeight) 
//  ********************************************** 
HDIB CreateDefaultDIB(DWORD dwWidth,DWORD dwHeight) 
{ 
	HDC hDC=GetDC(NULL); 
	if(!hDC) 
		return NULL; 
	int nDeviceBitsPixel=GetDeviceCaps(hDC,BITSPIXEL); 
	HDIB hDIB=CreateDIB(dwWidth,dwHeight,nDeviceBitsPixel); 
	LPBITMAPINFO lpbmi=(LPBITMAPINFO)GlobalLock(hDIB); 
	LPBYTE lpDIBBits=FindDIBBits((LPBYTE)lpbmi); 
	DWORD dwBitsSize=lpbmi->bmiHeader.biHeight* 
		BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); 
 
	for(DWORD l=0;l8) 
	{ 
		GlobalUnlock(hDIB); 
		ReleaseDC(NULL,hDC); 
		return hDIB; 
	} 
                 
	int nColors=PalEntriesOnDevice(hDC); 
	PALETTEENTRY pe[256]; 
	GetSystemPaletteEntries(hDC,0,nColors,pe); 
	for(int i=0;ibmiColors[i].rgbRed=pe[i].peRed; 
		lpbmi->bmiColors[i].rgbGreen=pe[i].peGreen; 
		lpbmi->bmiColors[i].rgbBlue=pe[i].peBlue; 
	} 
 
	GlobalUnlock(hDIB); 
	ReleaseDC(NULL,hDC); 
	return hDIB; 
} 
 
//*********************************************** 
//       void DestroyDIB(HDIB hDib) 
//  ********************************************** 
void DestroyDIB(HDIB hDib) 
{ 
	GlobalFree(hDib); 
	return; 
} 
 
//*********************************************** 
//       HANDLE ReadDIBFile(HANDLE hFile) 
//  ********************************************** 
HANDLE ReadDIBFile(HANDLE hFile) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	DWORD dwBitSize; 
	UINT nNumColors; 
	HANDLE hDIB; 
	HANDLE hDIBtmp; 
	LPBITMAPINFOHEADER lpbi; 
	DWORD offBits; 
	DWORD dwRead; 
 
	dwBitSize=GetFileSize(hFile,NULL); 
	hDIB=GlobalAlloc(GMEM_MOVEABLE, 
					 (DWORD)(sizeof(BITMAPINFOHEADER)+ 
					 256*sizeof(RGBQUAD))); 
	if(!hDIB) 
	{ 
		return(NULL); 
	} 
	lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
	if(!lpbi) 
	{ 
		GlobalFree(hDIB); 
		return(NULL); 
	} 
 
	if(!ReadFile(hFile, 
				 (LPBYTE)&bmfHeader, 
				 sizeof(BITMAPFILEHEADER), 
				 &dwRead, 
				 NULL)) 
		goto ErrExit; 
	if(bmfHeader.bfType!=DIB_HEADER_MARKER) 
		goto ErrExit; 
 
	if(!ReadFile(hFile, 
				 (LPBYTE)lpbi, 
				 sizeof(BITMAPINFOHEADER), 
				 &dwRead, 
				 NULL)) 
		goto ErrExit; 
	if(sizeof(BITMAPINFOHEADER)!=dwRead) 
		goto ErrExit; 
 
	if(lpbi->biSize==sizeof(BITMAPCOREHEADER)) 
		goto ErrExit; 
     
	if(!(nNumColors=(UINT)lpbi->biClrUsed)) 
	{ 
		if(lpbi->biBitCount!=24) 
			nNumColors=1<biBitCount; 
	} 
 
	if(lpbi->biClrUsed==0)   
		lpbi->biClrUsed=nNumColors; 
	if(lpbi->biSizeImage==0) 
	{ 
		lpbi->biSizeImage=(((lpbi->biWidth* 
			(DWORD)lpbi->biBitCount+31)&~31)>>3)*lpbi->biHeight; 
 
	} 
 
	GlobalUnlock(hDIB); 
 
	hDIBtmp=GlobalReAlloc(hDIB,lpbi->biSize+nNumColors* 
		sizeof(RGBQUAD)+lpbi->biSizeImage,0); 
	if(!hDIBtmp) 
		goto ErrExitUnLock; 
	else 
		hDIB=hDIBtmp; 
	lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
	ReadFile(hFile, 
		     (LPBYTE)lpbi+lpbi->biSize, 
			 nNumColors*sizeof(RGBQUAD), 
			 &dwRead, 
			 NULL); 
	offBits=lpbi->biSize+nNumColors*sizeof(RGBQUAD); 
	if(bmfHeader.bfOffBits!=0L) 
		SetFilePointer(hFile,bmfHeader.bfOffBits,NULL,FILE_BEGIN); 
	if(ReadFile(hFile,(LPBYTE)lpbi+offBits,lpbi->biSizeImage,&dwRead,NULL)) 
		goto OKExit; 
 
ErrExit: 
	GlobalUnlock(hDIB); 
ErrExitUnLock: 
	GlobalFree(hDIB); 
	return NULL; 
OKExit: 
    GlobalUnlock(hDIB); 
	return hDIB; 
 
} 
 
//*********************************************** 
//       HANDLE LoadDIB(LPSTR lpPathName) 
//  ********************************************** 
HANDLE LoadDIB(LPCTSTR lpFileName) 
{ 
	HANDLE hDIB; 
	HANDLE hFile; 
	SetCursor(LoadCursor(NULL,IDC_WAIT)); 
 
	if((hFile=CreateFile(lpFileName, 
						 GENERIC_READ, 
						 FILE_SHARE_READ, 
						 NULL, 
						 OPEN_EXISTING, 
						 FILE_ATTRIBUTE_NORMAL| 
						 FILE_FLAG_SEQUENTIAL_SCAN, 
						 NULL)) !=INVALID_HANDLE_VALUE) 
	{ 
		hDIB=ReadDIBFile(hFile); 
		CloseHandle(hFile); 
		SetCursor(LoadCursor(NULL,IDC_ARROW)); 
		return hDIB; 
	} 
	else 
	{ 
		SetCursor(LoadCursor(NULL,IDC_ARROW)); 
		return NULL; 
	} 
} 
 
//*********************************************** 
//   BOOL SaveDIB(HANDLE hDib,LPCTSTR lpFileName) 
//  ********************************************** 
BOOL SaveDIB(HANDLE hDib,LPCTSTR lpFileName) 
{ 
    BITMAPFILEHEADER bmfHeader; 
	LPBITMAPINFOHEADER lpBI; 
	HANDLE fh; 
	DWORD dwDIBSize; 
	DWORD dwWritten; 
 
	if(!hDib) 
		return FALSE; 
	fh=CreateFile(lpFileName, 
				  GENERIC_WRITE, 
				  0, 
				  NULL, 
				  CREATE_ALWAYS, 
				  FILE_ATTRIBUTE_NORMAL| 
				  FILE_FLAG_SEQUENTIAL_SCAN, 
				  NULL); 
	if(fh==INVALID_HANDLE_VALUE) 
		return FALSE; 
	lpBI=(LPBITMAPINFOHEADER)GlobalLock(hDib); 
	if(!lpBI) 
	{ 
		CloseHandle(fh); 
		return FALSE; 
	} 
	if(lpBI->biSize!=sizeof(BITMAPINFOHEADER)) 
	{ 
		GlobalUnlock(hDib); 
		CloseHandle(fh); 
		return FALSE; 
	} 
	bmfHeader.bfType=DIB_HEADER_MARKER; //"BM" 
 
	dwDIBSize=*(LPWORD)lpBI+ 
				DIBNumColors((LPBYTE)lpBI)*sizeof(RGBQUAD); 
	if((lpBI->biCompression==BI_RLE8)|| 
	   (lpBI->biCompression==BI_RLE4)) 
	   dwDIBSize+=lpBI->biSizeImage; 
	else 
	{ 
		DWORD dwBMBitsSize; 
		dwBMBitsSize=WIDTHBYTES((lpBI->biWidth)* 
			((DWORD)lpBI->biBitCount))*lpBI->biHeight; 
		dwDIBSize+=dwBMBitsSize; 
		lpBI->biSizeImage=dwBMBitsSize; 
	} 
 
	bmfHeader.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER); 
	bmfHeader.bfReserved1=0; 
	bmfHeader.bfReserved2=0; 
 
	bmfHeader.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+ 
		lpBI->biSize+DIBNumColors((LPBYTE)lpBI)*sizeof(RGBQUAD); 
	WriteFile(fh,(LPBYTE)&bmfHeader, 
		sizeof(BITMAPFILEHEADER),&dwWritten,NULL); 
	WriteFile(fh,(LPBYTE)lpBI,dwDIBSize,&dwWritten,NULL); 
 
	GlobalUnlock(hDib); 
	CloseHandle(fh); 
	if(dwWritten==0) 
		return FALSE; 
	else 
		return TRUE; 
} 
 
 
 
//*********************************************** 
//                 显示函数 
//  ********************************************** 
//************************************************************* 
//     BOOL PaintDIB(HDC hDC,LPRECT lpDCRect,HANDLE hDIB, 
//	      		   LPRECT lpDIBRect,HPALETTE hPal, DWORD dwRop) 
//  ************************************************************* 
BOOL PaintDIB(HDC hDC,LPRECT lpDCRect,HANDLE hDIB, 
			  LPRECT lpDIBRect,HPALETTE hPal, DWORD dwRop) 
{ 
	LPBYTE lpDIBHdr; 
	LPBYTE lpDIBBits; 
	BOOL bSuccess=FALSE; 
	HPALETTE hOldPal=NULL; 
	if(!hDIB) 
		return FALSE; 
	lpDIBHdr = (LPBYTE)GlobalLock(hDIB); 
	lpDIBBits=lpDIBHdr+sizeof(BITMAPINFOHEADER)+ 
		DIBNumColors(lpDIBHdr)*sizeof(RGBQUAD); 
	if(!hPal) 
		hPal=CreateDIBPalette(lpDIBHdr); 
	if(hPal) 
	{ 
		hOldPal=SelectPalette(hDC,hPal,TRUE); 
		RealizePalette(hDC); 
	} 
	SetStretchBltMode(hDC,COLORONCOLOR); 
	bSuccess=StretchDIBits(hDC, 
						   lpDCRect->left, 
						   lpDCRect->top, 
						   RECTWIDTH(lpDCRect), 
						   RECTHEIGHT(lpDCRect), 
						   lpDIBRect->left, 
						   ((LPBITMAPINFOHEADER)lpDIBHdr)->biHeight 
						   -lpDIBRect->top-RECTHEIGHT(lpDIBRect), 
							RECTWIDTH(lpDIBRect), 
						    RECTHEIGHT(lpDIBRect), 
							lpDIBBits, 
							(LPBITMAPINFO)lpDIBHdr, 
							DIB_RGB_COLORS, 
							SRCCOPY); 
 
//	GlobalUnlock(hDIB); 
	if(hOldPal) 
		SelectPalette(hDC,hOldPal,FALSE); 
	GlobalUnlock(hDIB); 
	return bSuccess; 
} 
 
//************************************************************* 
//    BOOL PaintBitmap(HDC hDC,LPRECT lpDCRect,HBITMAP hDDB, 
//				 LPRECT lpDDBRect,HPALETTE hPal, DWORD dwRop) 
//  ************************************************************* 
BOOL PaintBitmap(HDC hDC,LPRECT lpDCRect,HBITMAP hDDB, 
				 LPRECT lpDDBRect,HPALETTE hPal, DWORD dwRop) 
{ 
	HDC hMemDC; 
	HBITMAP hOldBitmap; 
	HPALETTE hOldPal1=NULL; 
	HPALETTE hOldPal2=NULL; 
	BOOL bSuccess=FALSE; 
 
	hMemDC=CreateCompatibleDC(hDC); 
	if(!hMemDC) 
		return FALSE; 
	if(hPal) 
	{ 
		hOldPal1=SelectPalette(hMemDC,hPal,TRUE); 
		hOldPal2=SelectPalette(hDC,hPal,TRUE); 
		RealizePalette(hDC); 
	} 
	hOldBitmap=(HBITMAP)SelectObject(hMemDC,hDDB); 
	SetStretchBltMode(hDC,COLORONCOLOR); 
	if((RECTWIDTH(lpDCRect)==RECTWIDTH(lpDDBRect))&& 
		(RECTHEIGHT(lpDCRect)==RECTHEIGHT(lpDDBRect))) 
		bSuccess=BitBlt(hDC, 
						lpDCRect->left, 
						lpDCRect->top, 
						RECTWIDTH(lpDCRect), 
						RECTHEIGHT(lpDCRect), 
						hMemDC, 
						lpDDBRect->left, 
						lpDDBRect->top, 
						dwRop); 
	else 
		bSuccess=StretchBlt(hDC, 
						    lpDCRect->left, 
						    lpDCRect->top, 
					     	RECTWIDTH(lpDCRect), 
						    RECTHEIGHT(lpDCRect), 
						    hMemDC, 
						    lpDDBRect->left, 
						    lpDDBRect->top, 
							RECTWIDTH(lpDDBRect), 
						    RECTHEIGHT(lpDDBRect), 
						    dwRop); 
	SelectObject(hMemDC,hOldBitmap); 
	if(hOldPal1) 
		SelectPalette(hDC,hOldPal1,FALSE); 
	if(hOldPal2) 
		SelectPalette(hDC,hOldPal2,FALSE); 
	DeleteDC(hMemDC); 
	return bSuccess; 
} 
 
 
 
 
 
 
//*********************************************** 
//                操作函数 
//  ********************************************** 
//*********************************************** 
//   HBITMAP DIBTODIBSECTION(LPBYTE lpDIB) 
//  ********************************************** 
HBITMAP DIBToDIBSection(LPBYTE lpDIB) 
{ 
	LPBYTE lpSourceBits; 
	HDC hDC=NULL; 
	HDC hSourceDC; 
	HBITMAP hSourceBitmap; 
	HBITMAP hOldSourceBitmap; 
	DWORD dwSourceBitsSize; 
 
	LPBITMAPINFO lpSrcDIB=(LPBITMAPINFO)lpDIB; 
	if(!lpSrcDIB) 
		return NULL; 
	hDC=GetDC(NULL); 
	hSourceBitmap=CreateDIBSection(hDC,lpSrcDIB, 
		DIB_RGB_COLORS,(VOID **)&lpSourceBits,NULL,0); 
 
	hSourceDC=CreateCompatibleDC(hDC); 
 
	dwSourceBitsSize=lpSrcDIB->bmiHeader.biHeight* 
		BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); 
	memcpy(lpSourceBits,FindDIBBits((LPBYTE)lpSrcDIB), 
		dwSourceBitsSize); 
	hOldSourceBitmap=(HBITMAP)SelectObject(hSourceDC,hSourceBitmap); 
	if(lpSrcDIB->bmiHeader.biBitCount<=8) 
		SetDIBColorTable(hSourceDC, 
						 0, 
						 1<bmiHeader.biBitCount, 
						 lpSrcDIB->bmiColors); 
		SelectObject(hSourceDC,hOldSourceBitmap); 
		DeleteDC(hSourceDC); 
		ReleaseDC(NULL,hDC); 
		GdiFlush(); 
		return hSourceBitmap;	 
} 
 
//*********************************************** 
//   HDIB DIBSectionToDIB(HBITMAP hBitmap) 
//  ********************************************** 
HDIB DIBSectionToDIB(HBITMAP hBitmap) 
{ 
	HDC hDC=NULL,hSourceDC; 
	HBITMAP hOldSourceBitmap; 
	HANDLE hNewDIB; 
	LPBITMAPINFO lpbmi=NULL; 
	DWORD dwSize; 
	DIBSECTION ds; 
	DWORD dwColorNum; 
 
	GetObject(hBitmap,sizeof(DIBSECTION),&ds); 
	dwColorNum=ds.dsBmih.biClrUsed; 
	if((dwColorNum==0)&&(ds.dsBmih.biBitCount<=8)) 
		dwColorNum=1<bmiHeader.biSize=sizeof(BITMAPINFOHEADER); 
	lpbmi->bmiHeader.biWidth=ds.dsBm.bmWidth; 
	lpbmi->bmiHeader.biHeight=ds.dsBm.bmHeight; 
	lpbmi->bmiHeader.biPlanes=1; 
	lpbmi->bmiHeader.biBitCount=ds.dsBmih.biBitCount; 
	lpbmi->bmiHeader.biCompression=ds.dsBmih.biCompression; 
	lpbmi->bmiHeader.biSizeImage=ds.dsBmih.biSizeImage; 
	lpbmi->bmiHeader.biXPelsPerMeter=ds.dsBmih.biXPelsPerMeter; 
	lpbmi->bmiHeader.biYPelsPerMeter=ds.dsBmih.biYPelsPerMeter; 
	lpbmi->bmiHeader.biClrUsed=ds.dsBmih.biClrUsed; 
	lpbmi->bmiHeader.biClrImportant=ds.dsBmih.biClrImportant; 
	hDC=GetDC(NULL); 
 
	if(!GetDIBits(hDC, 
				 hBitmap, 
				 0L, 
				 (DWORD)ds.dsBm.bmHeight, 
				 (LPBYTE)lpbmi+(WORD)lpbmi->bmiHeader.biSize 
				 +(dwColorNum*sizeof(RGBQUAD)), 
				 (LPBITMAPINFO)lpbmi, 
				 (DWORD)DIB_RGB_COLORS)	  ) 
	{ 
		GlobalUnlock(hNewDIB); 
		ReleaseDC(NULL,hDC); 
		return NULL; 
	} 
	hSourceDC=CreateCompatibleDC(hDC); 
	hOldSourceBitmap=(HBITMAP)SelectObject(hSourceDC,hBitmap); 
	if(lpbmi->bmiHeader.biBitCount<=8) 
		GetDIBColorTable(hSourceDC,0,1<bmiHeader.biBitCount, 
		lpbmi->bmiColors); 
	SelectObject(hSourceDC,hOldSourceBitmap); 
	DeleteDC(hSourceDC); 
	ReleaseDC(NULL,hDC); 
	GlobalUnlock(hNewDIB); 
	return hNewDIB; 
} 
 
//*********************************************** 
//   BOOL CopyColorTabel(LPBITMAPINFO lpTarget,LPBITMAPINFO lpSource, 
//					HPALETTE hPalSrc); 
//  ********************************************** 
BOOL CopyColorTable(LPBITMAPINFO lpTarget,LPBITMAPINFO lpSource, 
					HPALETTE hPalSrc) 
{ 
	switch(lpTarget->bmiHeader.biBitCount) 
	{ 
	case 8: 
		if(hPalSrc) 
		{ 
			PALETTEENTRY pe[256]; 
			UINT i; 
			GetPaletteEntries(hPalSrc,0,256,pe); 
			for(i=0;i<256;i++) 
			{ 
				lpTarget->bmiColors[i].rgbRed=pe[i].peRed; 
				lpTarget->bmiColors[i].rgbGreen=pe[i].peGreen; 
				lpTarget->bmiColors[i].rgbBlue=pe[i].peBlue; 
				lpTarget->bmiColors[i].rgbReserved=0; 
			} 
		} 
		else 
		{ 
			if(lpSource->bmiHeader.biBitCount==8) 
			{ 
				memcpy(lpTarget->bmiColors,lpSource->bmiColors, 
					256*sizeof(RGBQUAD)); 
			} 
			else 
			{ 
				HPALETTE hPal; 
				HDC hDC=GetDC(NULL); 
				PALETTEENTRY pe[256]; 
				UINT i; 
				hPal=CreateOctreePalette((LPBYTE)lpSource,236,8); 
				if(!hPal) 
					hPal=CreateHalftonePalette(hDC); 
				ReleaseDC(NULL,hDC); 
 
				GetPaletteEntries(hPal,0,256,pe); 
				DeleteObject(hPal); 
				for(i=0;i<256;i++) 
				{ 
					lpTarget->bmiColors[i].rgbRed=pe[i].peRed; 
					lpTarget->bmiColors[i].rgbGreen=pe[i].peGreen; 
					lpTarget->bmiColors[i].rgbBlue=pe[i].peBlue; 
					lpTarget->bmiColors[i].rgbReserved=pe[i].peFlags; 
				} 
			} 
		} 
	break; 
	case 4: 
		if(hPalSrc) 
		{ 
			PALETTEENTRY pe[16]; 
			UINT i; 
			GetPaletteEntries(hPalSrc,0,16,pe); 
			for(i=0;i<16;i++) 
			{ 
				lpTarget->bmiColors[i].rgbRed=pe[i].peRed; 
				lpTarget->bmiColors[i].rgbGreen=pe[i].peGreen; 
				lpTarget->bmiColors[i].rgbBlue=pe[i].peBlue; 
				lpTarget->bmiColors[i].rgbReserved=0; 
			} 
		} 
		else 
		{ 
			if(lpSource->bmiHeader.biBitCount==8) 
			{ 
				memcpy(lpTarget->bmiColors,lpSource->bmiColors, 
					16*sizeof(RGBQUAD)); 
			} 
			else 
			{ 
				HPALETTE hPal; 
				PALETTEENTRY pe[256]; 
				UINT i; 
				hPal=(HPALETTE)GetStockObject(DEFAULT_PALETTE); 
				GetPaletteEntries(hPal,0,16,pe); 
				DeleteObject(hPal); 
				for(i=0;i<16;i++) 
				{ 
					lpTarget->bmiColors[i].rgbRed=pe[i].peRed; 
					lpTarget->bmiColors[i].rgbGreen=pe[i].peGreen; 
					lpTarget->bmiColors[i].rgbBlue=pe[i].peBlue; 
					lpTarget->bmiColors[i].rgbReserved=pe[i].peFlags; 
				} 
			} 
		} 
	break; 
	case 1: 
		lpTarget->bmiColors[0].rgbRed=0; 
		lpTarget->bmiColors[0].rgbGreen=0; 
		lpTarget->bmiColors[0].rgbBlue=0; 
		lpTarget->bmiColors[0].rgbReserved=0; 
		lpTarget->bmiColors[1].rgbRed=255; 
		lpTarget->bmiColors[1].rgbGreen=255; 
		lpTarget->bmiColors[1].rgbBlue=255; 
		lpTarget->bmiColors[1].rgbReserved=0; 
	break; 
	case 32: 
	case 24: 
	case 16: 
	default: 
	break; 
	} 
	return TRUE; 
} 
 
//*********************************************** 
//   HDIB ConvertDIBFormat(LPBYTE lpDIB,UINT nWidth,UINT nHeight, 
//					  UINT nbpp,BOOL bStrech,HPALETTE hPalSrc) 
//  ********************************************** 
HDIB ConvertDIBFormat(LPBYTE lpDIB,UINT nWidth,UINT nHeight, 
					  UINT nbpp,BOOL bStretch,HPALETTE hPalSrc) 
{ 
	LPBITMAPINFO lpSrcDIB=(LPBITMAPINFO)lpDIB; 
	LPBITMAPINFO lpbmi=NULL; 
	LPBYTE lpSourceBits,lpTargetBits,lpResult; 
	HDC hDC=NULL,hSourceDC,hTargetDC; 
	HBITMAP hSourceBitmap,hTargetBitmap,hOldTargetBitmap, 
		   hOldSourceBitmap; 
	DWORD dwSourceBitsSize,dwTargetBitsSize,dwTargetHeaderSize, 
		  dwColorNum; 
	HDIB hDib; 
 
	if(nbpp<=8) 
		dwColorNum=1<bmiHeader.biSize=sizeof(BITMAPINFOHEADER); 
	lpbmi->bmiHeader.biWidth=nWidth; 
	lpbmi->bmiHeader.biHeight=nHeight; 
	lpbmi->bmiHeader.biPlanes=1; 
	lpbmi->bmiHeader.biBitCount=nbpp; 
	lpbmi->bmiHeader.biCompression=BI_RGB; 
	lpbmi->bmiHeader.biSizeImage=0; 
	lpbmi->bmiHeader.biXPelsPerMeter=0; 
	lpbmi->bmiHeader.biYPelsPerMeter=0; 
	lpbmi->bmiHeader.biClrUsed=0; 
	lpbmi->bmiHeader.biClrImportant=0; 
 
	if(!CopyColorTable(lpbmi,(LPBITMAPINFO)lpSrcDIB,hPalSrc)) 
	{ 
		free(lpbmi); 
		return NULL; 
	} 
	hDC=GetDC(NULL); 
	hTargetBitmap=CreateDIBSection(hDC,lpbmi,DIB_RGB_COLORS, 
		(VOID **)&lpTargetBits,NULL,0); 
	hSourceBitmap=CreateDIBSection(hDC,lpSrcDIB,DIB_RGB_COLORS, 
		(VOID **)&lpSourceBits,NULL,0); 
	hSourceDC=CreateCompatibleDC(hDC); 
	hTargetDC=CreateCompatibleDC(hDC); 
 
	dwSourceBitsSize=lpSrcDIB->bmiHeader.biHeight* 
		BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); 
	dwTargetBitsSize=lpbmi->bmiHeader.biHeight* 
		BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); 
	memcpy(lpSourceBits,FindDIBBits((LPBYTE)lpSrcDIB),dwSourceBitsSize); 
	lpbmi->bmiHeader.biSizeImage=dwTargetBitsSize; 
 
	hOldSourceBitmap=(HBITMAP)SelectObject(hSourceDC,hSourceBitmap); 
	hOldTargetBitmap=(HBITMAP)SelectObject(hTargetDC,hTargetBitmap); 
 
	if(lpSrcDIB->bmiHeader.biBitCount<=8) 
		SetDIBColorTable(hSourceDC,0, 
			1<bmiHeader.biBitCount, 
			lpSrcDIB->bmiColors); 
	if(lpbmi->bmiHeader.biBitCount<=8) 
		SetDIBColorTable(hTargetDC,0, 
			1<bmiHeader.biBitCount, 
			lpbmi->bmiColors); 
	if((lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth)&& 
		(lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight)) 
		BitBlt(hTargetDC,0,0, 
			   lpbmi->bmiHeader.biWidth, 
			   lpbmi->bmiHeader.biHeight, 
			   hSourceDC,0,0,SRCCOPY);				 
	else 
	{ 
		if(bStretch) 
		{ 
			SetStretchBltMode(hTargetDC,COLORONCOLOR); 
			StretchBlt(hTargetDC,0,0, 
				        lpbmi->bmiHeader.biWidth, 
						lpbmi->bmiHeader.biHeight, 
						hSourceDC,0,0, 
						lpSrcDIB->bmiHeader.biWidth, 
						lpSrcDIB->bmiHeader.biHeight, 
						SRCCOPY); 
		} 
		else 
		{ 
			BitBlt(hTargetDC,0,0, 
				   lpbmi->bmiHeader.biWidth, 
				   lpbmi->bmiHeader.biHeight, 
				   hSourceDC,0,0,SRCCOPY); 
 
		} 
	} 
	SelectObject(hSourceDC,hOldSourceBitmap); 
	SelectObject(hTargetDC,hOldSourceBitmap); 
	DeleteDC(hSourceDC); 
	DeleteDC(hTargetDC); 
	ReleaseDC(NULL,hDC); 
	GdiFlush(); 
 
	hDib=GlobalAlloc(GHND,dwTargetBitsSize+dwTargetHeaderSize); 
	lpResult=(LPBYTE)GlobalLock(hDib); 
	memcpy(lpResult,lpbmi,dwTargetHeaderSize); 
	memcpy(FindDIBBits((LPBYTE)lpResult),lpTargetBits,dwTargetBitsSize); 
 
	DeleteObject(hTargetBitmap); 
	DeleteObject(hSourceBitmap); 
	free(lpbmi); 
	GlobalUnlock(hDib); 
	return hDib; 
} 
 
//*********************************************** 
// HDIB BitmaptoDIB(HBITMAP hBitmap,HPALETTE hPal) 
//					   
//  ********************************************** 
HDIB BitmapToDIB(HBITMAP hBitmap,HPALETTE hPal) 
{ 
	BITMAP bm; 
	BITMAPINFOHEADER bi; 
	LPBITMAPINFOHEADER lpbi; 
	DWORD dwLen; 
	HANDLE hDIB,h; 
	HDC hDC; 
	WORD biBits; 
 
	if(!hBitmap) 
		return NULL; 
	if(!GetObject(hBitmap,sizeof(bm),(LPBYTE)&bm)) 
		return NULL; 
	if(hPal==NULL) 
		hPal=(HPALETTE)GetStockObject(DEFAULT_PALETTE); 
	biBits=bm.bmPlanes*bm.bmBitsPixel; 
	if(biBits<=1) 
		biBits=1; 
	else if(biBits<=4) 
		biBits=4; 
	else if(biBits<=8) 
		biBits=8; 
	else 
		biBits=24; 
	bi.biSize=sizeof(BITMAPINFOHEADER); 
	bi.biWidth=bm.bmWidth; 
	bi.biHeight=bm.bmHeight; 
	bi.biPlanes=1; 
	bi.biBitCount=biBits; 
	bi.biCompression=BI_RGB; 
	bi.biSizeImage=0; 
	bi.biXPelsPerMeter=0; 
	bi.biYPelsPerMeter=0; 
	bi.biClrUsed=0; 
	bi.biClrImportant=0; 
 
	dwLen=bi.biSize+PaletteSize((LPBYTE)&bi); 
	hDC=GetDC(NULL); 
	hPal=SelectPalette(hDC,hPal,FALSE); 
	RealizePalette(hDC); 
	hDIB=GlobalAlloc(GMEM_MOVEABLE,dwLen); 
	if(!hDIB) 
	{ 
		SelectPalette(hDC,hPal,TRUE); 
		RealizePalette(hDC); 
		ReleaseDC(NULL,hDC); 
		return NULL; 
	} 
	lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
	*lpbi=bi; 
	GetDIBits(hDC,hBitmap,0,(UINT)bi.biHeight,NULL, 
		(LPBITMAPINFO)lpbi,DIB_RGB_COLORS); 
	bi=*lpbi; 
	GlobalUnlock(hDIB); 
 
	if(bi.biSizeImage==0) 
		bi.biSizeImage=WIDTHBYTES((DWORD)bm.bmWidth*biBits)* 
		bm.bmHeight; 
	DWORD dwOldLen=dwLen; 
	dwLen=bi.biSize+PaletteSize((LPBYTE)&bi)+bi.biSizeImage; 
	h=GlobalReAlloc(hDIB,dwLen,0); 
	if(h) 
		hDIB=h; 
	else 
	{ 
		GlobalFree(hDIB); 
		hDIB=NULL; 
		SelectPalette(hDC,hPal,TRUE); 
		RealizePalette(hDC); 
		ReleaseDC(NULL,hDC); 
		return NULL; 
	} 
	lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDIB); 
	if(GetDIBits(hDC,hBitmap,0,(UINT)bm.bmHeight, 
		(LPBYTE)lpbi+(WORD)lpbi->biSize+PaletteSize((LPBYTE)lpbi), 
		(LPBITMAPINFO)lpbi, 
		DIB_RGB_COLORS)==0) 
	{ 
		GlobalUnlock(hDIB); 
		hDIB=NULL; 
		SelectPalette(hDC,hPal,TRUE); 
		RealizePalette(hDC); 
		ReleaseDC(NULL,hDC); 
		return NULL; 
	} 
	bi=*lpbi; 
	GlobalUnlock(hDIB); 
	SelectPalette(hDC,hPal,TRUE); 
	RealizePalette(hDC); 
	ReleaseDC(NULL,hDC); 
	return hDIB; 
} 
 
//*********************************************** 
//HDIB BitmapToDIB(HBITMAP hBitmap, 
//			HPALETTE hPalette,WORD wBitCount) 
//  ********************************************** 
HDIB BitmapToDIB(HBITMAP hBitmap,HPALETTE hPalette,WORD wBitCount) 
{ 
	HDIB hNewDib; 
	LPBYTE lpbi; 
	if(!hBitmap) 
		return NULL; 
	BITMAP bm; 
	GetObject(hBitmap,sizeof(bm),(LPBYTE)&bm); 
	int biBits=bm.bmPlanes*bm.bmBitsPixel; 
	if(biBits<=1) 
		biBits=1; 
	else if(biBits<=4) 
		biBits=4; 
	else if(biBits<=8) 
		biBits=8; 
	else 
		biBits=24; 
	HDIB hDib=BitmapToDIB(hBitmap,hPalette); 
	if(!hDib) 
		return NULL; 
	if(wBitCount==biBits) 
		hNewDib=hDib; 
	else 
	{ 
		lpbi=(LPBYTE)GlobalLock(hDib); 
		hNewDib=ConvertDIBFormat( 
			lpbi, 
			(UINT)(((LPBITMAPINFOHEADER)lpbi)->biWidth), 
			(UINT)(((LPBITMAPINFOHEADER)lpbi)->biHeight), 
			 wBitCount, 
			 FALSE, 
			 hPalette); 
		GlobalUnlock(hDib); 
		GlobalFree(hDib); 
	} 
	return hNewDib;	 
} 
 
//*********************************************** 
//HBITMAP DIBToBitmap(HDIB hDIB,HPALETTE hPal) 
//			 
//  ********************************************** 
HBITMAP DIBToBitmap(HDIB hDIB,HPALETTE hPal) 
{ 
	LPBYTE lpDIBHdr,lpDIBBits; 
	HBITMAP hBitmap; 
	HDC hDC; 
	HPALETTE hOldPal=NULL; 
 
	if(!hDIB) 
		return NULL; 
	lpDIBHdr=(LPBYTE)GlobalLock(hDIB); 
	lpDIBBits=FindDIBBits(lpDIBHdr); 
	hDC=GetDC(NULL); 
	if(!hDC) 
	{ 
		GlobalUnlock(hDIB); 
		return NULL; 
	} 
	if(hPal) 
	{ 
		hOldPal=SelectPalette(hDC,hPal,FALSE); 
		RealizePalette(hDC); 
	} 
	hBitmap=CreateDIBitmap(hDC, 
						   (LPBITMAPINFOHEADER)lpDIBHdr, 
						   CBM_INIT, 
						   lpDIBBits, 
						   (LPBITMAPINFO)lpDIBHdr, 
						   DIB_RGB_COLORS); 
	if(hOldPal) 
		SelectPalette(hDC,hOldPal,FALSE); 
	ReleaseDC(NULL,hDC); 
	GlobalUnlock(hDIB); 
	return hBitmap; 
} 
 
 
//*********************************************** 
//                捕获函数群  
//  ********************************************** 
//********************************************** 
//     HBITMAP CopyScreenToBitmap(LPRECT lpRect) 
//********************************************* 
HBITMAP CopyScreenToBitmap(LPRECT lpRect) 
{ 
	HDC hScrDC,hMemDC; 
	HBITMAP hBitmap,hOldBitmap; 
	int nx,ny,nx2,ny2; 
	int nWidth,nHeight; 
	int xScrn,yScrn; 
 
	if(IsRectEmpty(lpRect)) 
		return NULL; 
	hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL); 
	hMemDC=CreateCompatibleDC(hScrDC); 
	nx=lpRect->left; 
	ny=lpRect->top; 
	nx2=lpRect->right; 
	ny2=lpRect->bottom; 
	xScrn=GetDeviceCaps(hScrDC,HORZRES); 
	yScrn=GetDeviceCaps(hScrDC,VERTRES); 
	if(nx<0) 
		nx=0; 
	if(ny<0) 
		ny=0; 
	if(nx2>xScrn) 
		nx2=xScrn; 
	if(ny2>yScrn) 
		ny2=yScrn; 
	nWidth=nx2-nx; 
	nHeight=ny2-ny; 
 
	hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight); 
	hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap); 
 
	BitBlt(hMemDC,0,0,nWidth,nHeight,hScrDC,nx,ny,SRCCOPY); 
	hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap); 
	DeleteDC(hScrDC); 
	DeleteDC(hMemDC); 
	return hBitmap;			 
} 
 
//********************************************** 
//    HBITMAP CopyWindowToBitmap(HWND hWnd,WORD fPrintArea) 
//********************************************* 
HBITMAP CopyWindowToBitmap(HWND hWnd,WORD fPrintArea) 
{ 
	HBITMAP hBitmap=NULL; 
	if(!hWnd) 
		return NULL; 
	switch(fPrintArea) 
	{ 
	case PW_WINDOW: 
		{ 
			RECT rectWnd; 
			GetWindowRect(hWnd,&rectWnd); 
			hBitmap=CopyScreenToBitmap(&rectWnd); 
			break; 
		} 
	case PW_CLIENT: 
		{ 
			RECT rectClient; 
			POINT pt1,pt2; 
			GetClientRect(hWnd,&rectClient); 
			pt1.x=rectClient.left; 
			pt1.y=rectClient.top; 
			pt2.x=rectClient.right; 
			pt2.y=rectClient.bottom; 
			ClientToScreen(hWnd,&pt1); 
			ClientToScreen(hWnd,&pt2); 
			rectClient.left=pt1.x; 
			rectClient.top=pt1.y; 
			rectClient.right=pt2.x; 
			rectClient.bottom=pt2.y; 
			hBitmap=CopyScreenToBitmap(&rectClient); 
			break; 
		} 
	default: 
		return NULL; 
	} 
	return hBitmap; 
} 
 
//********************************************** 
//     HBITMAP CopyClientRectToBitmap(HWND hWnd,LPRECT lpRect) 
//********************************************* 
HBITMAP CopyClientRectToBitmap(HWND hWnd,LPRECT lpRect) 
{ 
	HBITMAP hBitmap=NULL; 
	if(!hWnd) 
		return NULL; 
	POINT pt1,pt2; 
	pt1.x=lpRect->left; 
	pt1.y=lpRect->top; 
	pt2.x=lpRect->right; 
	pt2.y=lpRect->bottom; 
	ClientToScreen(hWnd,&pt1); 
	ClientToScreen(hWnd,&pt2); 
	lpRect->left=pt1.x; 
	lpRect->top=pt1.y; 
	lpRect->right=pt2.x; 
	lpRect->bottom=pt2.y; 
	hBitmap=CopyScreenToBitmap(lpRect); 
	pt1.x=lpRect->left; 
	pt1.y=lpRect->top; 
	pt2.x=lpRect->right; 
	pt2.y=lpRect->bottom; 
	ScreenToClient(hWnd,&pt1); 
	ScreenToClient(hWnd,&pt2); 
	lpRect->left=pt1.x; 
	lpRect->top=pt1.y; 
	lpRect->right=pt2.x; 
	lpRect->bottom=pt2.y; 
	return hBitmap; 
} 
 
//********************************************** 
// HDIB CopyScreenTODIB(LPRECT lpRect) 
//********************************************* 
HDIB CopyScreenToDIB(LPRECT lpRect) 
{ 
	HBITMAP hBitmap; 
	HPALETTE hPalette=NULL; 
	HDIB hDIB=NULL; 
	hBitmap=CopyScreenToBitmap(lpRect); 
	if(!hBitmap) 
		return NULL; 
	hPalette=GetSystemPalette(); 
	hDIB=BitmapToDIB(hBitmap,hPalette); 
	DeleteObject(hPalette); 
	DeleteObject(hBitmap); 
	return hDIB; 
} 
 
//********************************************** 
//    HDIB CopyWindowToDIB(HWND hWnd,WORD fPrintArea) 
//********************************************* 
HDIB CopyWindowToDIB(HWND hWnd,WORD fPrintArea) 
{ 
	HBITMAP hBitmap=NULL; 
	HPALETTE hPalette=NULL; 
	HDIB hDIB=NULL; 
	if(!hWnd) 
		return NULL; 
	hBitmap=CopyWindowToBitmap(hWnd,fPrintArea); 
	hPalette=GetSystemPalette(); 
	hDIB=BitmapToDIB(hBitmap,hPalette); 
	DeleteObject(hPalette); 
	DeleteObject(hBitmap); 
	return hDIB; 
} 
 
//********************************************** 
//  HDIB CopyClientRectToDIB(HWND hWnd,LPRECT lpRect) 
//********************************************* 
HDIB CopyClientRectToDIB(HWND hWnd,LPRECT lpRect) 
{ 
	HBITMAP hBitmap=NULL; 
	HPALETTE hPalette=NULL; 
	HDIB hDIB=NULL; 
	if(!hWnd) 
		return NULL; 
	hBitmap=CopyClientRectToBitmap(hWnd,lpRect); 
	hPalette=GetSystemPalette(); 
	hDIB=BitmapToDIB(hBitmap,hPalette); 
	DeleteObject(hPalette); 
	DeleteObject(hBitmap); 
	return hDIB; 
} 
 
//*********************************************** 
//                定时函数  
//  ********************************************** 
//*********************************************** 
//        void Delay (DWORD dwDelayTime) 
//  ********************************************** 
void Delay (DWORD dwDelayTime) 
{ 
	DWORD dwTimeBegin,dwTimeEnd; 
	dwTimeBegin=timeGetTime(); 
	do 
	{ 
		dwTimeEnd=timeGetTime(); 
	}while((dwTimeEnd-dwTimeBegin)rm) *r=rm; 
	if(*g>gm) *g=gm; 
	if(*b>bm) *b=bm; 
	if((*r==rm)&&(*g==gm)&&(*b=bm)) 
		return TRUE; 
	else 
		return FALSE; 
} 
 
//*********************************************** 
//        HANDLE CopyHandle(HANDLE h) 
//  ********************************************** 
HANDLE CopyHandle(HANDLE h) 
{ 
	if(h==NULL) 
		return NULL; 
	DWORD dwLen=::GlobalSize((HGLOBAL)h); 
	HANDLE hCopy=::GlobalAlloc(GHND,dwLen); 
	if(hCopy==NULL) 
		return NULL; 
	void *lpCopy=::GlobalLock((HGLOBAL)hCopy); 
	void *lp    =::GlobalLock((HGLOBAL)h); 
	::CopyMemory(lpCopy,lp,dwLen); 
	::GlobalUnlock(hCopy); 
	::GlobalUnlock(h); 
	return hCopy; 
} 
 
//*********************************************** 
//            颜色处理函数 
//  ********************************************** 
//*********************************************** 
//       HPALETTE ConvertToGrayScale(HDIB hnib,int nMethod, 
//   double fRedWeight, double fGreenWeight,double fBlueWeight) 
//  ********************************************** 
HPALETTE ConvertToGrayScale(HDIB hDib,int nMethod, 
    double fRedWeight, double fGreenWeight,double fBlueWeight) 
{ 
	if  (hDib == NULL) 
		return NULL; 
	BITMAPINFO* lpbi = (BITMAPINFO *)GlobalLock(hDib); 
	if(!lpbi) 
		return NULL; 
	WaitCursorBegin(); 
	// get color number 
	WORD wNumColors =DIBNumColors((LPBYTE)lpbi); 
	if (wNumColors == 0) // There is no palette 
	GlobalUnlock (hDib); 
	//  reduce colors to 256 
	HDIB hNewDib=ColorQuantizeDIB(hDib,8,256); 
	LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); 
    if (!lpDIB) 
	{ 
		WaitCursorEnd(); 
		return NULL; 
	} 
	DWORD dwSize =DIBBlockSize(lpDIB); 
    hDib = GlobalReAlloc(hDib, dwSize, 0); 
	lpbi= (BITMAPINFO *)GlobalLock(hDib); 
	CopyMemory((LPBYTE)lpbi,(LPBYTE)lpDIB,dwSize); 
	GlobalUnlock (hNewDib); 
	GlobalFree (hNewDib); 
 
	wNumColors = DIBNumColors((LPBYTE)lpbi); 
    BYTE GrayValue = 0; 
	WORD i; 
 
	switch (nMethod) 
	{ 
	case MAXIMUM_GRAY: 
		for (i=0; ibmiColors[i].rgbRed, 
                               lpbi->bmiColors[i].rgbGreen), 
                               lpbi->bmiColors[i].rgbBlue); 
			lpbi->bmiColors[i].rgbRed  =       
			lpbi->bmiColors[i].rgbGreen =          
			lpbi->bmiColors[i].rgbBlue = GrayValue; 
		} 
    break; 
	case MEAN_GRAY: 
		for (i=0; ibmiColors[i].rgbRed + 
						   lpbi->bmiColors[i].rgbGreen + 
						   lpbi->bmiColors[i].rgbBlue)/3); 
			lpbi->bmiColors[i].rgbRed =          
			lpbi->bmiColors[i].rgbGreen = 
            lpbi->bmiColors[i].rgbBlue = GrayValue; 
		} 
	break; 
          
    case WEIGHT_GRAY: 
		for (i=0; ibmiColors[i].rgbRed*fRedWeight+ 
				       lpbi->bmiColors[i].rgbGreen*fGreenWeight+ 
					   lpbi->bmiColors[i].rgbBlue*fBlueWeight)); 
			lpbi->bmiColors[i].rgbRed= 
			lpbi->bmiColors[i].rgbGreen = 
			lpbi->bmiColors[i].rgbBlue=GrayValue; 
		} 
	break; 
	} 
	HPALETTE hNewDIB; 
	hNewDIB=CreateDIBPalette((LPBYTE)lpbi); 
	GlobalUnlock(hDib);	 
    WaitCursorEnd(); 
	return hNewDIB; 
} 
 
  
 //************************************************************** 
 //*   CreateOctreePalette ()      
 //*   Parameters:     
 //*   HDIB hDIB               - Handle to source DIB          
 //*   UINT nMaxColors         - destination color number 
 //*   UINT nColorBits         - destination color bits 
 //*   Return Value: 
 //*   HPALETTE                - Handle to the result palette 
 //*   Description:         
 //*   This function use Octree color quantization algorithm to get 
 //*   optimal m kinds of color to represent total n kinds of color 
 //*   in a DIB, and use the m kinds of color to build a palette. 
 //*   With the palette, we can display the DIE on reasonable accuracy. 
 //***************************************************************** 
HPALETTE CreateOctreePalette(HDIB hDIB,UINT nMaxColors, 
							 UINT nColorBits) 
{ 
	HANDLE hImage; 
	LPBITMAPINFO lpbi; 
	if(!hDIB) 
		return NULL; 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	hImage = DIBToDIBSection((LPBYTE)lpbi); 
	GlobalUnlock(hDIB); 
    if (!hImage) 
		return NULL; 
	 return BuildOctreePalette(hImage, nMaxColors, nColorBits); 
} 
 
//************************************************************** 
 //*   CreateOctreePalette ()      
 //*   Parameters:     
 //*   LPBYTE lpbIB            - Pointer to DID data buffer          
 //*   UINT nMaxColors         - destination color number 
 //*   UINT nColorBits         - destination color bits 
 //*   Return Value: 
 //*   HPALETTE                - Handle to the result palette 
 //*   Description:         
 //*   This function use Octree color quantization algorithm to get 
 //*   optimal m kinds of color to represent total n kinds of color 
 //*   in a DIB, and use the m kinds of color to build a palette. 
 //*   With the palette, we can display the DIE on reasonable accuracy. 
 //***************************************************************** 
HPALETTE CreateOctreePalette(LPBYTE lpDIB,UINT nMaxColors, 
                             UINT nColorBits) 
{ 
	HANDLE hImage; 
	hImage = DIBToDIBSection(lpDIB); 
	if (! hImage) 
		return NULL; 
	return BuildOctreePalette(hImage,nMaxColors, nColorBits); 
} 
 
//*********************************************** 
//  HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, 
//							UINT nColorBits) 
//  ********************************************** 
// local function to build optimal palette from DlBSection 
HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, 
							UINT nColorBits) 
{ 
	DIBSECTION ds; 
	int i, j, nPad; 
	BYTE* pbBits; 
	WORD* pwBits; 
	DWORD* pdwBits; 
    DWORD rmask,gmask,bmask; 
	int rright, gright, bright; 
	int rleft, gleft, bleft; 
	BYTE r, g, b; 
	WORD wColor; 
	DWORD dwColor, dwSize; 
    LOGPALETTE* plp; 
	HPALETTE hPalette; 
	NODE* pTree; 
	UINT nLeafCount, nIndex; 
	NODE* pReducibleNodes[9]; 
	HDC hdc; 
	BYTE* pBuffer; 
    BITMAPINFO bmi; 
	 
          
    //Initialize octree variables 
	pTree = NULL; 
	nLeafCount = 0; 
	if (nColorBits > 8) // Just in case 
		return NULL;         
    for (i=0; i<=(int) nColorBits; i++) 
		pReducibleNodes[i] = NULL; 
	// Scan the DIB and build the octree 
    GetObject(hImage, sizeof (ds), &ds);          
    nPad = ds.dsBm.bmWidthBytes-(((ds.dsBmih.biWidth * 
            ds.dsBmih.biBitCount)+7)/8); 
	switch (ds.dsBmih.biBitCount) 
	{ 
       case 1://  1-bit DIB 
       case 4://  4-bit DIB 
       case 8://  8-bit DIB 
         // The strategy here is to use ::GetDlBits to convert the 
         // image into a 24-bit DIR one scan line at a time. A pleasant 
         // side effect of using ::GetDlBits in this manner is that RLE- 
         // encoded 4-bit and 8-bit DIBs will be uncompressed. 
	     hdc = GetDC (NULL); 
         pBuffer = new BYTE[ds.dsBmih.biWidth * 3]; 
         ZeroMemory(&bmi, sizeof (bmi)); 
         bmi .bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
         bmi .bmiHeader.biWidth = ds.dsBmih.biWidth; 
         bmi .bmiHeader.biHeight = ds.dsBmih.biHeight; 
         bmi .bmiHeader.biPlanes = 1; 
         bmi. bmiHeader.biBitCount = 24; 
         bmi. bmiHeader.biCompression = BI_RGB; 
         for (i=0; i nMaxColors) 
					 ReduceTree(nColorBits, &nLeafCount, 
								pReducibleNodes); 
			 } 
		 } 
             delete pBuffer; 
             ReleaseDC (NULL, hdc); 
         break; 
		 case 16: // One case for 16-bit DIBs 
			 if (ds.dsBmih.biCompression == BI_BITFIELDS) 
			 { 
				 rmask = ds.dsBitfields[0]; 
				 gmask = ds.dsBitfields[1]; 
				 bmask = ds.dsBitfields[2]; 
			 } 
			 else 
			 { 
				 rmask = 0x7C00; 
				 gmask = 0x03E0; 
				 bmask = 0x001F; 
			 } 
			  
			 rright = GetRightShiftCount (rmask); 
			 gright = GetRightShiftCount (gmask); 
			 bright = GetRightShiftCount (bmask); 
			 rleft  = GetLeftShiftCount  (rmask); 
			 gleft  = GetLeftShiftCount  (gmask); 
             bleft  = GetLeftShiftCount (bmask); 
			 pwBits = (WORD*) ds.dsBm.bmBits; 
			 for (i=0; i>bright)<>gright)<>rright)<nMaxColors) 
						 ReduceTree (nColorBits, &nLeafCount, 
									pReducibleNodes); 
				 } 
				 pwBits=(WORD*)(((BYTE*)pwBits)+nPad); 
			 } 
		break; 
        case 24: // Another for 24-bit DIBS 
			pbBits=(BYTE*)ds.dsBm.bmBits; 
			for (i=0; i nMaxColors) 
						ReduceTree(nColorBits,&nLeafCount, 
								   pReducibleNodes);  
				} 
                pbBits+=nPad; 
			} 
		break; 
		case 32: // And another for 32-bit DIEs 
			if(ds.dsBmih.biCompression == BI_BITFIELDS) 
			{ 
                rmask = ds.dsBitfields[0]; 
                gmask = ds.dsBitfields[1]; 
                bmask = ds.dsBitfields[2]; 
			} 
			else 
			{ 
				rmask = 0x00FF0000; 
                gmask = 0x0000FF00; 
				bmask = 0x000000FF; 
			} 
			rright = GetRightShiftCount (rmask); 
            gright = GetRightShiftCount (gmask); 
			bright = GetRightShiftCount (bmask); 
            pdwBits =(DWORD*) ds.dsBm.bmBits; 
			for (i=0; i>bright); 
					g=(BYTE)((dwColor & gmask)>>gright); 
					r=(BYTE)((dwColor & rmask)>>rright); 
					AddColor(&pTree,r,g,b,nColorBits,0,&nLeafCount, 
						     pReducibleNodes); 
					while(nLeafCount > nMaxColors) 
						ReduceTree(nColorBits, &nLeafCount, 
								   pReducibleNodes); 
				} 
				pdwBits=(DWORD*)(((BYTE*) pdwBits) + nPad); 
			} 
        break; 
		default: // nIB must be 16, 24, or 32bit! 
			return NULL; 
		break; 
    } 
    if(nLeafCount > nMaxColors) 
	{ // Sanity check 
		DeleteTree (&pTree); 
		return NULL; 
    } 
	// Create a logical palette front the colors in the octree 
	dwSize=sizeof(LOGPALETTE) + 
		   ((nLeafCount-1)*sizeof(PALETTEENTRY)); 
	if((plp= (LOGPALETTE*) HeapAlloc(GetProcessHeap(),0, 
									 dwSize))== NULL) 
	{ 
        DeleteTree (&pTree); 
		return NULL; 
	} 
	plp->palVersion = 0x300; 
	plp->palNumEntries = (WORD) nLeafCount; 
	nIndex=0; 
	GetPaletteColors(pTree,plp->palPalEntry,&nIndex); 
	hPalette=CreatePalette (plp); 
	HeapFree(GetProcessHeap(),0,plp); 
	DeleteTree(&pTree); 
	return hPalette; 
} 
 
 
//*********************************************** 
//  void AddColor(NODE** ppNode,BYTE r,BYTE g,BYTE b,UINT nColorBits, 
//			  UINT nLevel,UINT* pLeafCount,NODE** pReducibleNodes) 
//  ********************************************** 
// local function to add a color to octree 
void AddColor(NODE** ppNode,BYTE r,BYTE g,BYTE b,UINT nColorBits, 
			  UINT nLevel,UINT* pLeafCount,NODE** pReducibleNodes) 
 
{ 
	int nIndex,shift; 
	static BYTE mask[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; 
	//     If the node doesn't exist, create it 
	if (*ppNode==NULL) 
		*ppNode=CreateNode(nLevel,nColorBits,pLeafCount, 
						   pReducibleNodes); 
	//     Update color information if it's a leaf node 
	if ((*ppNode)->bIsLeaf) 
	{ 
		(*ppNode) ->nPixelCount++; 
        (*ppNode) ->nRedSum+= r; 
		(*ppNode)->nGreenSum+= g; 
		(*ppNode)->nBlueSum+= b; 
	} 
	//     Recurse a level deeper if the node is not a leaf 
	else 
	{ 
		shift =7 - nLevel; 
		nIndex=(((r&mask[nLevel])>>shift)<<2)| 
                 (((g&mask[nLevel])>>shift)<<1)| 
                 ((b&mask[nLevel])>>shift); 
		AddColor(&((*ppNode)->pChild[nIndex]),r,g,b,nColorBits, 
			     nLevel+1,pLeafCount,pReducibleNodes); 
	} 
} 
 
//*********************************************** 
//  NODE* CreateNode(UINT nLevel,UINT nColorBits,UINT* pLeafCount, 
//				 NODE** pReducibleNodes) 
//  ********************************************** 
// local function to create a new node in octree 
NODE* CreateNode(UINT nLevel,UINT nColorBits,UINT* pLeafCount, 
				 NODE** pReducibleNodes) 
{ 
	NODE* pNode; 
	 
	if((pNode = (NODE*)HeapAlloc(GetProcessHeap(), 
					HEAP_ZERO_MEMORY,sizeof (NODE))) == NULL) 
		return NULL; 
 
	pNode->bIsLeaf=(nLevel== nColorBits)?TRUE:FALSE; 
	if (pNode->bIsLeaf) 
		(*pLeafCount) ++; 
	else 
	{ // Add the node to the reducible list for this level 
		pNode->pNext= pReducibleNodes[nLevel]; 
		pReducibleNodes[nLevel] = pNode; 
	} 
    return pNode; 
} 
 
//*********************************************** 
//  void ReduceTree(UINT nColorBits,UINT* pLeafCount, 
//				NODE** pReducibleNodes) 
//  ********************************************** 
// local function to reduce the nodes of octree 
void ReduceTree(UINT nColorBits,UINT* pLeafCount, 
				NODE** pReducibleNodes) 
{ 
	int i; 
	NODE* pNode; 
	UINT nRedSum, nGreenSum, nBlueSum, nChildren; 
	// Find the deepest level containing at least ,one reducible node 
	for(i=nColorBits - 1;(i>0) &&(pReducibleNodes[i]==NULL);i--); 
	// Reduce the node most recently added to the list at level i 
	pNode = pReducibleNodes[i]; 
	pReducibleNodes[i]= pNode->pNext; 
	nRedSum = nGreenSum = nBlueSum = nChildren = 0; 
	for (i=0; i<8; i++) 
	{ 
        if (pNode->pChild[i]!= NULL) 
		{ 
            nRedSum +=   pNode->pChild[i]->nRedSum; 
			nGreenSum += pNode->pChild[i]->nGreenSum; 
			nBlueSum +=  pNode->pChild[i]->nBlueSum; 
			pNode->nPixelCount += pNode->pChild[i]->nPixelCount; 
			HeapFree(GetProcessHeap(),0,pNode->pChild[i]); 
			pNode->pChild[i] = NULL; 
			nChildren++; 
		} 
	} 
	pNode->bIsLeaf=TRUE; 
	pNode->nRedSum = nRedSum; 
	pNode->nGreenSum = nGreenSum; 
	pNode->nBlueSum = nBlueSum; 
	*pLeafCount -= (nChildren - 1); 
} 
 
 
//*********************************************** 
//  void DeleteTree (NODE** ppNode)   
// 
//  ********************************************** 
//  local function to delete a node of octree 
void DeleteTree (NODE** ppNode)          
{ 
	int i; 
	for (i=0; i<8; i++) 
	{ 
		if((*ppNode)->pChild[i]!=NULL) 
			DeleteTree(&((*ppNode)->pChild[i])); 
	} 
	HeapFree(GetProcessHeap (), 0, *ppNode); 
	*ppNode = NULL; 
	return;         
} 
      
 
//*********************************************** 
// void GetPaletteColors (NODE* pTree,PALETTEENTRY* pPalEntries, 
//					   UINT* pIndex) 
//  **********************************************     
//  local function to get color entry from a palette 
void GetPaletteColors (NODE* pTree,PALETTEENTRY* pPalEntries, 
					   UINT* pIndex) 
{ 
	int i; 
	if (pTree->bIsLeaf) 
	{ 
		pPalEntries[*pIndex].peRed = 
			(BYTE)((pTree->nRedSum)/(pTree->nPixelCount)); 
		pPalEntries[*pIndex].peGreen= 
			(BYTE)((pTree->nGreenSum)/(pTree->nPixelCount)); 
		pPalEntries[*pIndex].peBlue = 
			(BYTE)((pTree->nBlueSum)/(pTree->nPixelCount)); 
		(*pIndex) ++; 
	} 
	else 
	{ 
		for (i=0; i<8; i++) 
		{ 
			if (pTree->pChild[i] != NULL) 
				GetPaletteColors(pTree->pChild[i], pPalEntries, pIndex); 
		} 
	} 
} 
          
 
//*********************************************** 
// int GetRightShiftCount (DWORD dwVal) 
//					   
//  **********************************************   
//local function to get pixel count 
int GetRightShiftCount (DWORD dwVal) 
{ 
	int i; 
	for (i=0; i>=1; 
	} 
	return -1; 
} 
 
//*********************************************** 
// int GetLeftShiftCount (DWORD dwVal) 
//					   
//  **********************************************   
//local function to get pixel count 
int GetLeftShiftCount (DWORD dwVal) 
{ 
	int nCount, i; 
	nCount = 0; 
	for (i=0; i>=1; 
	} 
	return(8-nCount); 
} 
 
 
//*********************************************** 
// HDIB ColorQuantizeDIB(HDIB hDIB,UINT nColorBits,UINT nMaxColors) 
//					   
//  **********************************************   
HDIB ColorQuantizeDIB(HDIB hDIB,UINT nColorBits,UINT nMaxColors) 
{ 
	HPALETTE hPal=NULL; 
	WaitCursorBegin(); 
	LPBYTE lpDIB=(LPBYTE)GlobalLock(hDIB); 
 
	hPal=CreateOctreePalette(lpDIB,nMaxColors,nColorBits); 
	GlobalUnlock(hDIB); 
 
	LPBITMAPINFO lpbi; 
	lpbi=(LPBITMAPINFO)GlobalLock(hDIB); 
	if(!lpbi) 
		return NULL; 
	HDIB hNewDIB=ConvertDIBFormat((LPBYTE)lpbi,lpbi->bmiHeader.biWidth, 
		lpbi->bmiHeader.biHeight,nColorBits,FALSE,hPal); 
	GlobalUnlock(hDIB); 
	WaitCursorEnd(); 
	return hNewDIB; 
 
} 
 
//颜色空间相互转换函数 
void HSItoRGB(double h,double s,double i, 
			  BYTE *r,BYTE *g,BYTE *b) 
{ 
	double V1 =s*cos(h); 
	double V2 =s*sin(h); 
	int iR=(int)(0.816496*V2+0.57735*i); 
	int iG=(int)(0.7071 *V1-0.40824*V2+0.57735*i); 
	int iB=(int)(-0.7071 *V1-0.40824*V2+0.57735*i); 
	*r= BOUND(iR, 0, 255); 
	*g= BOUND(iG, 0, 255); 
	*b= BOUND(iB, 0, 255); 
	return; 
} 
 
void RGBtoHSI(BYTE r,BYTE g,BYTE b, 
			  double *h,double *s,double *i) 
{ 
	double V1 = 0.7071*((double)g-(double)b); 
	double V2 = 0.816496*(double)r-0.40824*((double)g+(double)b); 
	*h=atan2(V1, V2); 
	*s=sqrt(V1*V1+V2*V2); 
	*i=0.57735*((double)r+(double)g+(double)b); 
} 
          
          
//local function used in RLStoRGB 
double Value(double n1, double n2, double hue) 
{ 
	if   (hue > 360.0) 
		hue -= 360.0; 
	else if (hue < 0.0) 
		hue += 360.0; 
 
	if   (hue < 60.0) 
		return (n1+(n2-n1)*hue/60.0); 
	else if (hue < 180.0) 
		return n2; 
		else if (hue < 240.0) 
			return (n1+(n2-n1)*(240.0-hue)/60.0); 
			else 
				return n1; 
} 
 
 
 
void HLStoRGB(double h,double l,double s, 
			  BYTE *r,BYTE *g, BYTE *b) 
{ 
	double m1, m2; 
	double R,G,B; 
 
	if (l <= 0.5) 
		m2 = l*(1.0+s); 
	else 
		m2 = l+s-l*s; 
 
	m1 =2.0*l-m2; 
	if (s == 0) 
	{ 
		if (h == UNDEFINED) 
			R = G = B = 1; 
		else     // error!! 
			R=  G = B = 0.0; 
	} 
	else 
	{ 
		R = Value(m1, m2, h+120.0); 
		G = Value(m1, m2, h); 
		B = Value(m1, m2, h-120.0); 
	} 
	int iR = (int) (R*255.0); 
	int iG = (int) (G*255.0); 
	int iB = (int) (B*255.0); 
	*r= (BYTE)BOUND(iR, 0, 255); 
	*g= (BYTE)BOUND(iG, 0, 255); 
	*b= (BYTE)BOUND(iB, 0, 255); 
	return; 
} 
 
void RGBtoHLS(BYTE r,BYTE g,BYTE b, 
			  double *h,double *l,double *s) 
{ 
	double mx,mn,delta; 
	double R, G, B; 
	 
	R = (double)r/255.0; 
	G = (double)g/255.0; 
	B = (double)b/255.0; 
	mx = max(R, max(G, B)); 
	mn = min(R, min(G, B)); 
	*l = (mx+mn)/2.0; 
	if (mx == mn) 
	{ 
		*s = 0.0; 
        *h= UNDEFINED;          // undefined! 
	} 
	else 
	{ 
		delta = mx-mn; 
		if (*l < 0.5) 
			*s = delta/(mx+mn); 
		else 
			*s = delta/(2.0-mx-mn); 
 
		if (R == mx) 
			*h = (G-B)/delta; 
		else if (G == mx) 
			*h = 2.0+(B-R)/delta; 
			else if (B == mx) 
				*h = 4.0+(R-G)/delta; 
			*h *= 60.0; 
            if (*h < 0.0) 
				*h += 360.0; 
			else if (*h > 360.0) 
				*h -= 360.0; 
	} 
	return; 
} 
 
void RGBtoHSV(BYTE r,BYTE g,BYTE b, 
			  double *h,double *s,double *v) 
{ 
	double mx,mn,d; 
	double R, G, B; 
	 
	R = (double)r/255.0; 
	G = (double)g/255.0; 
	B = (double)b/255.0; 
	mx = max(R, max(G, B)); 
	mn = min(R, min(G, B)); 
	*v=mx;d=mx-mn; 
	if(mx)	*s=d/mx; 
	else  *s=0.0; 
	if(fabs(d)>0.0001) 
	{ 
		if(mx==R)	*h=(G-B)/d; 
		if(mx==G)	*h=2.0+(B-R)/d; 
		if(mx==B)    *h=4.0+(R-G)/d; 
	} 
	else *h=0.0; 
	*h=(*h)/6.0; 
	if((*h)<0.0) *h=(*h)+1.0;  
	return; 
} 
 
void RGBtoHS(BYTE r,BYTE g,BYTE b, 
			  double *h,double *s) 
{ 
	double mx,mn,d; 
	double R, G, B; 
	 
	R = (double)r/255.0; 
	G = (double)g/255.0; 
	B = (double)b/255.0; 
	mx = max(R, max(G, B)); 
	mn = min(R, min(G, B)); 
	//*v=mx; 
	d=mx-mn; 
	if(mx)	*s=d/mx; 
	else  *s=0.0; 
	if(fabs(d)>0.0001) 
	{ 
		if(mx==R)	*h=(G-B)/d; 
		if(mx==G)	*h=2.0+(B-R)/d; 
		if(mx==B)    *h=4.0+(R-G)/d; 
	} 
	else *h=0.0; 
	*h=(*h)/6.0; 
	if((*h)<0.0) *h=(*h)+1.0;  
	return; 
} 
 
void CMYKtoRGB(BYTE c,BYTE m,BYTE y,BYTE k, 
			  BYTE *r,BYTE *g,BYTE *b) 
{ 
	c +=k; 
	m +=k; 
	y +=k; 
	 
	*r=255-c; 
	*g=255-m; 
	*b=255-y; 
	return; 
} 
 
void RGBtoCMYK(BYTE r,BYTE g,BYTE b, 
			   BYTE *c,BYTE *m,BYTE *y,BYTE *k) 
{ 
	*c=255-r; 
	*m=255-g; 
	*y=255-b; 
 
	*k=min(*c,min(*m,*y)); 
	*c-=*k; 
	*m-=*k; 
	*y-=*k; 
	return; 
} 
 
BOOL   RGBToShort2HS(LPBITMAPINFOHEADER lpbi,LPBYTE lpdib, 
				   short *lpDataH,short *lpDataS) 
{ 
	BYTE r, g, b; 
	double s, h,v; 
	int nx,ny,index; 
		 
	if((lpbi == NULL)|(lpdib == NULL)) return FALSE; 
	// get color number 
	int nDelta=WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) 
					-lpbi->biWidth*lpbi->biBitCount/8; 
	WORD wNumColors = DIBNumColors((LPBYTE)lpbi); 
	if (wNumColors)           // There is palette 
	{ 
		RGBQUAD	*lpRGB=(RGBQUAD *)((LPSTR)lpbi+lpbi->biSize); 
		for (ny=0; nybiHeight; ny++) 
		{ 
			for (nx=0; nxbiWidth; nx++) 
			{ 
					index=(BYTE)(*(lpdib)); 
					r=lpRGB[index].rgbRed ; 
					g=lpRGB[index].rgbGreen; 
					b=lpRGB[index].rgbBlue; 
					RGBtoHSV(r,g,b,&h,&s,&v); 
					*lpDataH=(short)(h*100); 
					*lpDataS=(short)(s*100); 
					lpdib++;lpDataH++;lpDataS++;						 
			} 
			lpdib += nDelta; 
		} 
	} 
	else     // No palette 
	{ 
		for (ny=0; nybiHeight; ny++) 
			{ 
				for (nx=0; nxbiWidth; nx++) 
				{ 
					b = (BYTE)*(lpdib); 
					g = (BYTE)*(lpdib+1); 
					r = (BYTE)*(lpdib+2); 
					RGBtoHSV(r,g,b,&h,&s,&v); 
					*lpDataH=(short)(h*1000); 
				//	*lpDataS=(short)(s*100); 
					lpdib=lpdib+3; 
					lpDataH++; 
				//	lpDataS++;				 
				} 
				lpdib += nDelta; 
		} 
	} 
	return TRUE; 
} 
 
BOOL AdjustDIBColor(HDIB hDib, int nColorModel,int v1, 
					int v2, int v3) 
{ 
	BYTE r, g, b, c, m, y, k; 
	int dr, dg, db, dc, dm, dy; 
	double dh, ds, dv, dl, h, s, v, l; 
	 
	if   (hDib == NULL) 
		return FALSE; 
	BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib); 
	if (!bmi) 
		return FALSE; 
	 
	WaitCursorBegin (); 
	switch (nColorModel) 
	{ 
	case RGB_COLOR: 
		dr = v1; 
		dg = v2; 
		db = v3; 
	break; 
	case CMYK_COLOR: 
		dc = v1; 
		dm = v2; 
		dy = v3; 
	break; 
	case HSI_COLOR: 
		if (v1 < 0) 
			v1 += 360; 
		dh = v1; 
		ds = v2; 
		dv = v3; 
	break; 
	case HLS_COLOR: 
		if (v1 < 0) 
            v1 += 360; 
		dh = v1; 
		dl = v2/100.0; 
		ds = v3/100.0; 
	break; 
	} 
	 
	// get color number 
	WORD wNumColors = DIBNumColors((LPBYTE)bmi); 
	if (wNumColors)           // There is palette 
	{ 
		WORD i; 
		switch (nColorModel)          
		{ 
		case RGB_COLOR: 
			for (i=0; ibmiColors[i].rgbRed = 
					BOUND(bmi->bmiColors[i].rgbRed+dr,0,255); 
				bmi->bmiColors[i].rgbGreen= 
					BOUND(bmi->bmiColors[i].rgbGreen+dg,0,255); 
                bmi->bmiColors[i].rgbBlue = 
					BOUND(bmi->bmiColors[i].rgbBlue+db,0,255); 
			} 
		break; 
		case CMYK_COLOR: 
			for (i=0; ibmiColors[i].rgbRed; 
				g = bmi->bmiColors[i].rgbGreen; 
                b = bmi->bmiColors[i].rgbBlue; 
				RGBtoCMYK(r,g,b,&c,&m,&y,&k); 
				c += dc; 
				m += dm; 
				y += dy; 
				CMYKtoRGB(c,m,y,k,&r,&g,&b); 
				bmi->bmiColors[i].rgbRed  = r; 
				bmi->bmiColors[i].rgbGreen= g; 
				bmi->bmiColors[i].rgbBlue = b; 
			} 
		break; 
		case HSI_COLOR: 
			for (i=0; ibmiColors[i].rgbRed; 
				g = bmi->bmiColors[i].rgbGreen; 
				b = bmi->bmiColors[i].rgbBlue; 
				RGBtoHSI(r,g,b,&h,&s,&v); 
				h += dh; 
				s += ds; 
				v += dv; 
				HSItoRGB(h,s,v,&r,&g,&b); 
				bmi->bmiColors[i].rgbRed  = r; 
				bmi->bmiColors[i].rgbGreen= g; 
				bmi->bmiColors[i].rgbBlue = b; 
			} 
		break; 
		case HLS_COLOR: 
			for (i=0; ibmiColors[i].rgbRed; 
				g = bmi->bmiColors[i].rgbGreen; 
				b = bmi->bmiColors[i].rgbBlue; 
				RGBtoHLS(r,g,b,&h,&l,&s); 
				if (h != UNDEFINED) 
					h = BOUND(h+dh, 0.0, 360.0); 
				l = BOUND(l+dl, 0.0, 1.0); 
				s = BOUND(s+ds, 0.0, 1.0); 
				HLStoRGB(h,l,s,&r,&g,&b); 
				bmi->bmiColors[i].rgbRed  = r; 
				bmi->bmiColors[i].rgbGreen= g; 
				bmi->bmiColors[i].rgbBlue = b; 
			} 
		break; 
		} //switch end 
	} //if end 
	else     // No palette 
	{ 
		// bits position 
		LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)bmi; 
		LPBYTE lpBits=(LPBYTE)lpbi+lpbi->biSize; 
		int nDelta=WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) 
					-lpbi->biWidth*lpbi->biBitCount/ 8; 
		int nx,ny; 
		 
		switch (nColorModel) 
        { 
		case RGB_COLOR: 
			for (ny=0; nybiHeight; ny++) 
			{ 
				for (nx=0; nxbiWidth; nx++) 
				{ 
					b = (BYTE)*(lpBits); 
					g = (BYTE)*(lpBits+1); 
					r = (BYTE)*(lpBits+2); 
					*lpBits++ = BOUND(b+db, 0, 255); 
					*lpBits++ = BOUND(g+dg, 0, 255); 
                    *lpBits++ = BOUND(r+dr, 0, 255); 
				} 
				lpBits += nDelta; 
			} 
		break; 
		case CMYK_COLOR: 
			for (ny=0; nybiHeight; ny++) 
			{ 
				for (nx=0; nxbiWidth; nx++) 
				{ 
					b = (BYTE)*(lpBits); 
					g = (BYTE)*(lpBits+1); 
					r = (BYTE)*(lpBits+2); 
					RGBtoCMYK(r,g,b,&c,&m,&y,&k); 
					c += dc; 
					m += dm; 
					y += dy; 
					CMYKtoRGB(c,m,y,k,&r,&g,&b); 
					*lpBits++ =b; 
					*lpBits++ =g; 
					*lpBits++ =r; 
				} 
				lpBits += nDelta; 
			} 
		break; 
		case HSI_COLOR: 
			for (ny=0; nybiHeight; ny++) 
			{ 
				for (nx=0; nxbiWidth; nx++) 
				{ 
					b = (BYTE)*(lpBits); 
					g = (BYTE)*(lpBits+1); 
					r = (BYTE)*(lpBits+2); 
					RGBtoHSI(r,g,b,&h,&s,&v); 
					h += dh; 
					s += ds; 
					v += dv; 
					HSItoRGB(h,s,v,&r,&g,&b); 
					*lpBits++ = b; 
					*lpBits++ = g; 
					*lpBits++ = r; 
				} 
				lpBits += nDelta; 
			} 
		break; 
		case HLS_COLOR: 
			for (ny=0; nybiHeight; ny++) 
			{ 
				for (nx=0; nxbiWidth; nx++) 
				{ 
					b = (BYTE)*(lpBits); 
					g = (BYTE)*(lpBits+1); 
					r = (BYTE)*(lpBits+2); 
					RGBtoHLS(r,g,b,&h,&l,&s); 
					if (h != UNDEFINED) 
                        h = BOUND(h+dh, 0.0, 360.0); 
					l = BOUND(l+dl, 0.0, 1.0); 
					s = BOUND(s+ds, 0.0, 1.0); 
					HLStoRGB(h,l,s,&r,&g,&b); 
					*lpBits++ = b; 
					*lpBits++ = g; 
					*lpBits++ = r; 
				} 
				lpBits += nDelta; 
			} 
		break; 
        } //switch end  
	} //else end 
	GlobalUnlock (hDib); 
	WaitCursorEnd(); 
	return TRUE; 
} 
 
//亮度调整 
void ChangeBrightness(int nDelta,BYTE *r,BYTE *g,BYTE *b) 
{ 
	int R=*r+nDelta; 
	int G=*g+nDelta; 
	int B=*b+nDelta; 
 
	*r=(BYTE)BOUND(R,0,255); 
	*g=(BYTE)BOUND(G,0,255); 
	*b=(BYTE)BOUND(B,0,255); 
	return; 
} 
 
BOOL AdjustDIBBrightness(HDIB hDib,int v) 
{ 
	if(hDib==NULL) 
		return FALSE; 
	BITMAPINFO *bmi=(BITMAPINFO *)GlobalLock(hDib); 
	if(!bmi)  
		return FALSE; 
	WaitCursorBegin(); 
	WORD wNumColors=DIBNumColors((LPBYTE)bmi); 
	if(wNumColors) 
	{ 
		for(WORD i=0;ibmiColors[i].rgbRed), 
							 &(bmi->bmiColors[i].rgbGreen), 
							 &(bmi->bmiColors[i].rgbBlue)); 
		} 
	} 
	else //No Palette 
	{ 
		LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)bmi; 
		LPBYTE lpBits=(LPBYTE)lpbi+lpbi->biSize; 
		int nDelta=WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) 
			-lpbi->biWidth*lpbi->biBitCount/8; 
		BYTE r,g,b; 
		for(int ny=0;nybiHeight;ny++) 
		{ 
			for(int nx=0;nxbiWidth;nx++) 
			{ 
				b=(BYTE)*(lpBits); 
				g=(BYTE)*(lpBits+1); 
				r=(BYTE)*(lpBits+2); 
				ChangeBrightness(v,&r,&g,&b); 
				*lpBits++=b; 
				*lpBits++=g; 
				*lpBits++=r; 
			} 
			lpBits+=nDelta; 
		} 
	} 
	GlobalUnlock(hDib); 
	WaitCursorEnd(); 
	return TRUE; 
} 
 
//对比度调整 
void IncreaseContrast(BYTE *pByte,const int Low, 
					  const int High, const float Grad) 
{ 
	if(*pByte<=Low) 
		*pByte=0; 
	else if((Low<(*pByte))&&(*pByte=0) 
	{ 
		int Low=0+nDelta; 
		int Hight=255-nDelta; 
		float Grad=((float)(Hight-Low))/255; 
		IncreaseContrast(r,Low,Hight,Grad); 
		IncreaseContrast(g,Low,Hight,Grad); 
		IncreaseContrast(b,Low,Hight,Grad); 
	} 
	else 
	{ 
		float Grad=255/(255+(float)nDelta+(float)nDelta); 
		DecreaseContrast(r,nDelta,Grad); 
		DecreaseContrast(g,nDelta,Grad); 
		DecreaseContrast(b,nDelta,Grad); 
	} 
	return; 
} 
 
BOOL AdjustDIBContrast(HDIB hDib,int v) 
{ 
 
	if(hDib==NULL) 
		return FALSE; 
	BITMAPINFO *bmi=(BITMAPINFO *)GlobalLock(hDib); 
	if(!bmi) 
		return FALSE; 
 
	WORD wNumColors=DIBNumColors((LPBYTE)bmi); 
	if(wNumColors) 
	{ 
		for(WORD i=0;ibmiColors[i].rgbRed), 
						   &(bmi->bmiColors[i].rgbGreen), 
						   &(bmi->bmiColors[i].rgbBlue)); 
		} 
	} 
	else//No Palette 
	{ 
		LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)bmi; 
		LPBYTE lpBits=(LPBYTE)lpbi+lpbi->biSize; 
		int nDelta=WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) 
			-lpbi->biWidth*lpbi->biBitCount/8; 
		BYTE r,g,b; 
 
		for(int ny=0;nybiHeight;ny++) 
		{ 
			for(int nx=0;nxbiWidth;nx++) 
			{ 
				b=(BYTE)*(lpBits); 
				g=(BYTE)*(lpBits+1); 
				r=(BYTE)*(lpBits+2); 
				ChangeContrast(v,&r,&g,&b); 
				*lpBits++=b; 
				*lpBits++=g; 
				*lpBits++=r; 
			} 
			lpBits+=nDelta; 
		} 
	} 
	GlobalUnlock(hDib); 
	WaitCursorEnd(); 
	return TRUE; 
} 
//*********************************************** 
//  图象处理函数 
//  ********************************************** 
//*********************************************************************** 
//*  Parameters:          
//* HDIB hDib              - objective DIB handle 
//*  KERNEL *lpKernel - pointer of kernel used to convolute with DIB 
//*  int Strength     - operation strength set to the convolute 
//*  int nKernelNum  - kernel number used to convolute 
//*  Return Value: 
//* BOOL        - True is success, else False 
//* Description: 
//*  This is the generic convolute function to DIB 
//************************************************************************* 
BOOL ConvoluteDIB24(HDIB hDib,KERNEL *lpKernel,int Strength, 
					int nKernelNum) 
   { 
	WaitCursorBegin (); 
	HDIB hNewDib=NULL; 
	//  we only convolute 24bpp DIB, so first convert DIB to 24bpp 
	WORD wBitCount = DIBBitCount(hDib); 
	if (wBitCount != 24) 
	{ 
		//hNewDib = ConvertDlBFormat(hDib, 24, NULL); 
		return FALSE; 
	} 
	else 
		hNewDib = CopyHandle(hDib); 
	if (! hNewDib) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	// new DIB attributes 
	WORD wDIBWidth = (WORD)DIBWidth(hNewDib); 
	WORD wDIBHeight =(WORD)DIBHeight(hNewDib); 
	WORD wBytesPerLine =(WORD)BytesPerLine(hNewDib); 
	DWORD dwImageSize = wBytesPerLine * wDIBHeight; 
	// Allocate and lock memory for filtered image data 
	HGLOBAL hFilteredBits = GlobalAlloc(GHND,dwImageSize); 
	if (!hFilteredBits) 
	{ 
		WaitCursorEnd(); 
        return FALSE; 
	} 
	LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); 
	// get bits address in DIB 
	LPBYTE lpDIB = (LPBYTE) GlobalLock (hNewDib); 
	LPBYTE lpDIBits = FindDIBBits(lpDIB); 
	// convolute... 
	for (int i=1;i red) 
						red = r; 
				if (g > green) 
						green = g; 
				if (b > blue) 
						blue = b; 
				//red += r; green += g; blue += b; 
			} 
			//  original RGB value in center pixel  (j, i) 
			LONG lOffset= PIXEL_OFFSET24(i,j,wBytesPerLine); 
			BYTE OldB = *(lpDIBits + lOffset++); 
			BYTE OldG = *(lpDIBits + lOffset++); 
            BYTE OldR = *(lpDIBits + lOffset); 
			// When we get here, red, green and blue have the new RGB value. 
            if (Strength != 10) 
            { 
				//  Interpolate pixel data 
				red=OldR+(((red-OldR)*Strength)/10); 
				green =OldG+(((green-OldG)*Strength)/10); 
				blue = OldB+(((blue-OldB)*Strength)/10); 
            } 
			lOffset= PIXEL_OFFSET24(i,j, wBytesPerLine); 
            *(lpDestImage+lOffset++)= BOUND(blue, 0, 255); 
            *(lpDestImage+lOffset++)= BOUND(green, 0, 255); 
            *(lpDestImage+lOffset)  = BOUND(red, 0, 255); 
		} 
		// a filtered image is available in lpDestlmage 
		//  copy it to DIB bits 
		memcpy (lpDIBits, lpDestImage, dwImageSize); 
		//  cleanup temp buffers 
		GlobalUnlock (hFilteredBits); 
		GlobalFree (hFilteredBits); 
		GlobalUnlock (hNewDib); 
		 
		// rebuild hDib 
		HDIB hTmp = NULL; 
		if (wBitCount != 24) 
		{ 
			return FALSE; 
			//hTmp = ConvertDlBFormat(hNewDib, wBitCount, NULL); 
		} 
         else 
			 hTmp = CopyHandle(hNewDib); 
		 GlobalFree (hNewDib); 
		 DWORD dwSize = GlobalSize(hTmp); 
		 memcpy((LPBYTE)GlobalLock(hDib), 
			 (LPBYTE)GlobalLock(hTmp),dwSize); 
		 GlobalUnlock (hTmp); 
		 GlobalFree (hTmp); 
		 GlobalUnlock (hDib); 
		 WaitCursorEnd(); 
		 return TRUE; 
} 
 
//   local function: perform convolution to DIB with a kernel 
void DoConvoluteDlB24(int *red,int *green,int *blue,int i, 
					int j,WORD wBytesPerLine, 
					LPBYTE lpDIBits, KERNEL *lpKernel) 
{ 
	BYTE b[9], g[9],r[9]; 
	LONG lOffset; 
	int k1,k2; 
	 
	k1=i-1;k2=j-1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[0]=*(lpDIBits + lOffset++); 
	g[0]=*(lpDIBits + lOffset++); 
	r[0]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[1]=*(lpDIBits + lOffset++); 
	g[1]=*(lpDIBits + lOffset++); 
	r[1]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[2]=*(lpDIBits + lOffset++); 
	g[2]=*(lpDIBits + lOffset++); 
	r[2]=*(lpDIBits + lOffset); 
	k1=i;k2=j-1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[3]=*(lpDIBits + lOffset++); 
	g[3]=*(lpDIBits + lOffset++); 
	r[3]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[4]=*(lpDIBits + lOffset++); 
	g[4]=*(lpDIBits + lOffset++); 
	r[4]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[5]=*(lpDIBits + lOffset++); 
	g[5]=*(lpDIBits + lOffset++); 
	r[5]=*(lpDIBits + lOffset); 
	k1=i+1;k2=j-1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[6]=*(lpDIBits + lOffset++); 
	g[6]=*(lpDIBits + lOffset++); 
	r[6]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[7]=*(lpDIBits + lOffset++); 
	g[7]=*(lpDIBits + lOffset++); 
	r[7]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET24(k1,k2, wBytesPerLine); 
    b[8]=*(lpDIBits + lOffset++); 
	g[8]=*(lpDIBits + lOffset++); 
	r[8]=*(lpDIBits + lOffset); 
 
	*red=*green =*blue = 0; 
	for (int k=0; k<8; ++k) 
	{ 
		*red  +=lpKernel->Element[k]*r[k]; 
		*green+=lpKernel->Element[k]*g[k]; 
		*blue +=lpKernel->Element[k]*b[k]; 
	} 
 
	if (lpKernel->Divisor!= 1) 
	{ 
		*red  /=lpKernel->Divisor; 
		*green/=lpKernel->Divisor; 
		*blue /=lpKernel->Divisor; 
	} 
	//getoff opposite 
	*red  = abs(*red); 
	*green = abs(*green); 
	*blue = abs(*blue); 
	return; 
} 
 
//*********************************************************************** 
//*  Parameters:          
//* HDIB hDib              - objective DIB handle 
//*  KERNEL *lpKernel - pointer of kernel used to convolute with DIB 
//*  int Strength     - operation strength set to the convolute 
//*  int nKernelNum  - kernel number used to convolute 
//*  Return Value: 
//* BOOL        - True is success, else False 
//* Description: 
//*  This is the generic convolute function to DIB 
//************************************************************************* 
BOOL ConvoluteDIB08(HDIB hDib,KERNEL *lpKernel,int Strength, 
					int nKernelNum) 
   { 
	WaitCursorBegin (); 
	HDIB hNewDib=NULL; 
	//  we only convolute 24bpp DIB, so first convert DIB to 24bpp 
	WORD wBitCount = DIBBitCount(hDib); 
	if (wBitCount != 8) 
	{ 
		//hNewDib = ConvertDlBFormat(hDib, 24, NULL); 
		return FALSE; 
	} 
	else 
		hNewDib = CopyHandle(hDib); 
	if (! hNewDib) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	// new DIB attributes 
	WORD wDIBWidth = (WORD)DIBWidth(hNewDib); 
	WORD wDIBHeight =(WORD)DIBHeight(hNewDib); 
	WORD wBytesPerLine =(WORD)BytesPerLine(hNewDib); 
	DWORD dwImageSize = wBytesPerLine * wDIBHeight; 
	// Allocate and lock memory for filtered image data 
	HGLOBAL hFilteredBits = GlobalAlloc(GHND,dwImageSize); 
	if (!hFilteredBits) 
	{ 
		WaitCursorEnd(); 
        return FALSE; 
	} 
	LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); 
	// get bits address in DIB 
	LPBYTE lpDIB = (LPBYTE) GlobalLock (hNewDib); 
	LPBYTE lpDIBits = FindDIBBits(lpDIB); 
	// convolute... 
	for (int i=1;i gray) 
						gray = g1; 
				//red += r; green += g; blue += b; 
			} 
			//  original RGB value in center pixel  (j, i) 
			LONG lOffset= PIXEL_OFFSET08(i,j,wBytesPerLine); 
			BYTE OldGray = *(lpDIBits + lOffset); 
		    // When we get here, red, green and blue have the new RGB value. 
            if (Strength != 10) 
            { 
				//  Interpolate pixel data 
				gray=OldGray+(((gray-OldGray)*Strength)/10); 
			} 
			lOffset= PIXEL_OFFSET08(i,j, wBytesPerLine); 
            *(lpDestImage+lOffset)= BOUND(gray, 0, 255); 
            } 
		// a filtered image is available in lpDestlmage 
		//  copy it to DIB bits 
		memcpy (lpDIBits, lpDestImage, dwImageSize); 
		//  cleanup temp buffers 
		GlobalUnlock (hFilteredBits); 
		GlobalFree (hFilteredBits); 
		GlobalUnlock (hNewDib); 
		 
		// rebuild hDib 
		HDIB hTmp = NULL; 
		if (wBitCount != 8) 
		{ 
			return FALSE; 
			//hTmp = ConvertDlBFormat(hNewDib, wBitCount, NULL); 
		} 
         else 
			 hTmp = CopyHandle(hNewDib); 
		 GlobalFree (hNewDib); 
		 DWORD dwSize = GlobalSize(hTmp); 
		 memcpy((LPBYTE)GlobalLock(hDib), 
			 (LPBYTE)GlobalLock(hTmp),dwSize); 
		 GlobalUnlock (hTmp); 
		 GlobalFree (hTmp); 
		 GlobalUnlock (hDib); 
		 WaitCursorEnd(); 
		 return TRUE; 
} 
 
//   local function: perform convolution to DIB with a kernel 
void DoConvoluteDlB08(int *gray,int i,int j,WORD wBytesPerLine, 
					LPBYTE lpDIBits, KERNEL *lpKernel) 
{ 
	BYTE  g[9]; 
	LONG lOffset; 
	int k1,k2; 
	 
	k1=i-1;k2=j-1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);			 
    g[0]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);			 
    g[1]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine); 
    g[2]=*(lpDIBits + lOffset); 
	k1=i;k2=j-1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);		  
    g[3]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);	 
    g[4]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);	 
    g[5]=*(lpDIBits + lOffset); 
	k1=i+1;k2=j-1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine);		 
    g[6]=*(lpDIBits + lOffset); 
		k2=j; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine); 
    g[7]=*(lpDIBits + lOffset); 
		k2=j+1; 
	lOffset= PIXEL_OFFSET08(k1,k2, wBytesPerLine); 
    g[8]=*(lpDIBits + lOffset); 
	 
	*gray = 0; 
	for (int k=0; k<8; ++k) 
		*gray+=lpKernel->Element[k]*g[k]; 
		 
	if (lpKernel->Divisor!= 1) 
			*gray/=lpKernel->Divisor; 
		 
	//getoff opposite 
	*gray = abs(*gray); 
	return; 
} 
 
 
//高通滤波器 
BOOL HighPassDIB(HDIB hDib,int Strength,int nAlgorithm) 
{ 
	BOOL bSuccess=FALSE; 
	LPBITMAPINFO lpbm; 
	lpbm=(LPBITMAPINFO)GlobalLock(hDib); 
	KERNEL HIGHPASS1={ {-1,-1,-1,-1, 9,-1,-1,-1,-1},1}; 
	KERNEL HIGHPASS2={ { 0,-1, 0,-1, 5,-1, 0,-1, 0},1}; 
	KERNEL HIGHPASS3={ { 1,-2, 1,-2, 5,-2, 1,-2,-1},1}; 
	if(!lpbm) 
		return FALSE; 
	int KernelNum=0; 
 
	KernelNum=1; 
	if(lpbm->bmiHeader.biBitCount==8) 
	{ 
			switch(nAlgorithm) 
				{ 
				case FILTER1: 
					bSuccess=ConvoluteDIB08(hDib,&HIGHPASS1,Strength,KernelNum); 
				break; 
				case FILTER2: 
					bSuccess=ConvoluteDIB08(hDib,&HIGHPASS2,Strength,KernelNum); 
				break; 
				case FILTER3: 
					bSuccess=ConvoluteDIB08(hDib,&HIGHPASS3,Strength,KernelNum); 
				break; 
				default: 
				break; 
				} 
	} 
	else 
		if(lpbm->bmiHeader.biBitCount==24) 
		{ 
				switch(nAlgorithm) 
				{ 
				case FILTER1: 
					bSuccess=ConvoluteDIB24(hDib,&HIGHPASS1,Strength,KernelNum); 
				break; 
				case FILTER2: 
					bSuccess=ConvoluteDIB24(hDib,&HIGHPASS2,Strength,KernelNum); 
				break; 
				case FILTER3: 
					bSuccess=ConvoluteDIB24(hDib,&HIGHPASS3,Strength,KernelNum); 
				break; 
				default: 
				break; 
				} 
		} 
	GlobalUnlock(hDib); 
	return bSuccess; 
} 
 
 
 
//低通滤波器 
BOOL LowPassDIB(HDIB hDib,int Strength,int nAlgorithm) 
{ 
	BOOL bSuccess=FALSE; 
	LPBITMAPINFO lpbm; 
	lpbm=(LPBITMAPINFO)GlobalLock(hDib); 
	KERNEL LOWPASS1={ { 1,1,1,1,1,1,1,1,1 }, 9}; 
	KERNEL LOWPASS2={ { 1,1,1,1,2,1,1,1,1},10 }; 
	KERNEL LOWPASS3={ { 1,2,1,2,4,2,1,2,1},16 }; 
 
	if(!lpbm) 
		return FALSE; 
	int KernelNum=0; 
 
	KernelNum=1; 
	if(lpbm->bmiHeader.biBitCount==8) 
	{ 
			switch(nAlgorithm) 
			{ 
			case FILTER1: 
				bSuccess=ConvoluteDIB08(hDib,&LOWPASS1,Strength,KernelNum); 
			break; 
			case FILTER2: 
				bSuccess=ConvoluteDIB08(hDib,&LOWPASS2,Strength,KernelNum); 
			break; 
			case FILTER3: 
				bSuccess=ConvoluteDIB08(hDib,&LOWPASS3,Strength,KernelNum); 
			break; 
			default: 
			break; 
			} 
	} 
	else 
		if(lpbm->bmiHeader.biBitCount==24) 
		{ 
				switch(nAlgorithm) 
				{ 
				case FILTER1: 
					bSuccess=ConvoluteDIB24(hDib,&LOWPASS1,Strength,KernelNum); 
				break; 
				case FILTER2: 
					bSuccess=ConvoluteDIB24(hDib,&LOWPASS2,Strength,KernelNum); 
				break; 
				case FILTER3: 
					bSuccess=ConvoluteDIB24(hDib,&LOWPASS3,Strength,KernelNum); 
				break; 
				default: 
				break; 
				} 
		}	 
	GlobalUnlock(FALSE); 
	return bSuccess; 
} 
 
//中值滤波 
//********************************************************************* 
//*   This is the media filtering function to DIB 
//********************************************************************** 
BOOL MedianFilterDIB24(HDIB hDib) 
{ 
	WaitCursorBegin (); 
	HDIB hNewDib = NULL; 
	WORD wBitCount = DIBBitCount(hDib); 
	if (wBitCount != 24) 
	{ 
		//hNewDib = ConvertDlBFormat(hDib, 24~ NULL); 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	else 
		hNewDib = CopyHandle(hDib); 
	if (!hNewDib) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	//  new DIB attributes 
	WORD wDIBWidth = (WORD)DIBWidth(hNewDib); 
	WORD wDIBHeight = (WORD)DIBHeight (hNewDib); 
	WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); 
	DWORD dwImageSize = wBytesPerLine*wDIBHeight; 
	// Allocate and lock memory for filtered image data 
	HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); 
    if (!hFilteredBits) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
 
	 LPBYTE lpDestImage =(LPBYTE)GlobalLock(hFilteredBits); 
	 // get bits address in DIB 
	 LPBYTE lpDIB=(LPBYTE)GlobalLock(hNewDib); 
	 LPBYTE lpDIBits=FindDIBBits(lpDIB); 
	 //  convolute..          
	 for (int i=1; i *(BYTE *)e2) 
		return 1; 
	return 0; 
} 
 
BOOL MedianPassDIB(HDIB hDib) 
{ 
	BOOL bSuccess=FALSE; 
	if(!hDib) 
		return FALSE; 
	LPBITMAPINFO lpbm=(LPBITMAPINFO)GlobalLock(hDib); 
	if(!lpbm) 
		return FALSE; 
	if(lpbm->bmiHeader.biBitCount==8) 
		bSuccess=MedianFilterDIB08(hDib); 
	else 
		if(lpbm->bmiHeader.biBitCount==24) 
			bSuccess=MedianFilterDIB24(hDib); 
	GlobalUnlock(hDib); 
	return bSuccess; 
} 
//二值化函数 
BOOL BinaryDIB08(HDIB hDib) 
{ 
	WaitCursorBegin (); 
	HDIB hNewDib = NULL; 
	WORD wBitCount = DIBBitCount(hDib); 
	if (wBitCount != 8) 
	{ 
		//hNewDib = ConvertDlBFormat(hDib, 24~ NULL); 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	else 
		hNewDib = CopyHandle(hDib); 
	if (!hNewDib) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	//  new DIB attributes 
	WORD wDIBWidth = (WORD)DIBWidth(hNewDib); 
	WORD wDIBHeight = (WORD)DIBHeight (hNewDib); 
	WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); 
	DWORD dwImageSize = wBytesPerLine*wDIBHeight; 
	// Allocate and lock memory for filtered image data 
	HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); 
    if (!hFilteredBits) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
 
	 LPBYTE lpDestImage =(LPBYTE)GlobalLock(hFilteredBits); 
	 // get bits address in DIB 
	 LPBYTE lpDIB=(LPBYTE)GlobalLock(hNewDib); 
	 LPBYTE lpDIBits=FindDIBBits(lpDIB); 
	 int GrayTable[25]; 
	 int i,j; 
	 for(i=0;i<25;i++) 
		 GrayTable[i]=0; 
	 unsigned short gray; 
	 LONG lOffset; 
	 //  convolute..          
	 for (i=1; iGrayTable[i])&&(GrayTable[i]!=0))  min=i; 
	 
	for (i=1; imin)  
				*(lpDestImage+lOffset)=255; 
			 else 
					*(lpDestImage+lOffset)=0; 
			} 
	 memcpy(lpDIBits, lpDestImage, dwImageSize); 
     //  cleanup temp buffers 
	 GlobalUnlock (hFilteredBits); 
     GlobalFree (hFilteredBits); 
	 GlobalUnlock (hNewDib); 
	 //  rebuild hDib 
	 HDIB hTmp = NULL; 
	 hTmp = CopyHandle(hNewDib); 
	 GlobalFree (hNewDib); 
	 DWORD dwSize = GlobalSize(hTmp); 
	 memcpy ((LPBYTE)GlobalLock(hDib), 
	 (LPBYTE)GlobalLock(hTmp), dwSize); 
	 GlobalUnlock (hTmp); 
	 GlobalFree (hTmp); 
	 GlobalUnlock (hDib); 
	 WaitCursorEnd(); 
	 return TRUE; 
} 
//数据读取函数 
BOOL ReadDIB08(LPCTSTR lpDataFile,HDIB hDib) 
{ 
	HANDLE fh; 
	DWORD dwWritten; 
	fh=CreateFile(lpDataFile, 
				  GENERIC_WRITE, 
				  0, 
				  NULL, 
				  CREATE_ALWAYS, 
				  FILE_ATTRIBUTE_NORMAL| 
				  FILE_FLAG_SEQUENTIAL_SCAN, 
				  NULL); 
	if(fh==INVALID_HANDLE_VALUE) 
		return FALSE; 
	WaitCursorBegin (); 
	WORD wBitCount = DIBBitCount(hDib); 
	if (wBitCount != 8) 
	{ 
		WaitCursorEnd(); 
		return FALSE; 
	} 
	LPBYTE lpDIB=(LPBYTE)GlobalLock(hDib); 
	WORD wDIBHeight = (WORD)DIBHeight (hDib); 
	WORD wBytesPerLine = (WORD)BytesPerLine(hDib); 
	DWORD dwImageSize = wBytesPerLine*wDIBHeight; 
	LPBYTE lpDIBits=FindDIBBits(lpDIB); 
	WriteFile(fh,(LPBYTE)lpDIBits,dwImageSize,&dwWritten,NULL); 
	GlobalUnlock(hDib); 
	CloseHandle(fh); 
	WaitCursorEnd(); 
	if(dwWritten==0) 
		return FALSE; 
	else 
		return TRUE; 
	 
}