www.pudn.com > LlxDip.rar > DibAPI.cpp


#include "stdafx.h" 
#include "DibAPI.h" 
 
/* 
* Dib文件头标志(字符串"BM",写DIB时用到该常数) 
*/ 
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') 
 
/************************************************************************* 
* 
* 函数名称: 
*   PaintDIB() 
* 
* 参数: 
*   HDC hDC            - 输出设备DC 
*   LPRECT lpDCRect    - 绘制矩形区域 
*   HDIB hDIB          - 指向DIB对象的指针 
*   LPRECT lpDIBRect   - 要输出的DIB区域 
*   CPalette* pPal     - 指向DIB对象调色板的指针 
* 
* 返回值: 
*   BOOL               - 绘制成功返回TRUE,否则返回FALSE。 
* 
* 说明: 
*   该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者 
* SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指 
* 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数 
* lpDIBRect指定。 
* 
************************************************************************/ 
 
BOOL WINAPI PaintDIB(HDC     hDC, 
					 LPRECT  lpDCRect, 
					 HDIB    hDIB, 
					 LPRECT  lpDIBRect, 
					 CPalette* pPal) 
{ 
	LPSTR    lpDIBHdr;            // BITMAPINFOHEADER指针 
	LPSTR    lpDIBBits;           // DIB象素指针 
	BOOL     bSuccess=FALSE;      // 成功标志 
	HPALETTE hPal=NULL;           // DIB调色板 
	HPALETTE hOldPal=NULL;        // 以前的调色板 
	 
	// 判断DIB对象是否为空 
	if (hDIB == NULL) 
	{ 
		// 返回 
		return FALSE; 
	} 
	 
	// 锁定DIB 
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIBHdr); 
	 
	// 获取DIB调色板,并选中它 
	if (pPal != NULL) 
	{ 
		hPal = (HPALETTE) pPal->m_hObject; 
		 
		// 选中调色板 
		hOldPal = ::SelectPalette(hDC, hPal, TRUE); 
	} 
	 
	// 设置显示模式 
	::SetStretchBltMode(hDC, COLORONCOLOR); 
	 
	// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象 
	if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) && 
		(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 
	{ 
		// 原始大小,不用拉伸。 
		bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC 
			lpDCRect->left,             // DestX 
			lpDCRect->top,              // DestY 
			RECTWIDTH(lpDCRect),        // nDestWidth 
			RECTHEIGHT(lpDCRect),       // nDestHeight 
			lpDIBRect->left,            // SrcX 
			(int)DIBHeight(lpDIBHdr) - 
			lpDIBRect->top - 
			RECTHEIGHT(lpDIBRect),   // SrcY 
			0,                          // nStartScan 
			(WORD)DIBHeight(lpDIBHdr),  // nNumScans 
			lpDIBBits,                  // lpBits 
			(LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo 
			DIB_RGB_COLORS);            // wUsage 
	} 
    else 
	{ 
		// 非原始大小,拉伸。 
		bSuccess = ::StretchDIBits(hDC,                          // hDC 
			lpDCRect->left,                 // DestX 
			lpDCRect->top,                  // DestY 
			RECTWIDTH(lpDCRect),            // nDestWidth 
			RECTHEIGHT(lpDCRect),           // nDestHeight 
			lpDIBRect->left,                // SrcX 
			lpDIBRect->top,                 // SrcY 
			RECTWIDTH(lpDIBRect),           // wSrcWidth 
			RECTHEIGHT(lpDIBRect),          // wSrcHeight 
			lpDIBBits,                      // lpBits 
			(LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo 
			DIB_RGB_COLORS,                 // wUsage 
			SRCCOPY);                       // dwROP 
	} 
	 
    // 解除锁定 
	::GlobalUnlock((HGLOBAL) hDIB); 
	 
	// 恢复以前的调色板 
	if (hOldPal != NULL) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE); 
	} 
	 
	// 返回 
	return bSuccess; 
} 
 
/************************************************************************* 
* 
* 函数名称: 
*   CreateDIBPalette() 
* 
* 参数: 
*   HDIB hDIB          - 指向DIB对象的指针 
*   CPalette* pPal     - 指向DIB对象调色板的指针 
* 
* 返回值: 
*   BOOL               - 创建成功返回TRUE,否则返回FALSE。 
* 
* 说明: 
*   该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中, 
* 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样 
* 可以用最好的颜色来显示DIB图像。 
* 
************************************************************************/ 
 
 
BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal) 
{ 
	// 指向逻辑调色板的指针 
	LPLOGPALETTE lpPal; 
	 
	// 逻辑调色板的句柄 
	HANDLE hLogPal; 
	 
	// 调色板的句柄 
	HPALETTE hPal = NULL; 
	 
	// 循环变量 
	int i; 
	 
	// 颜色表中的颜色数目 
	WORD wNumColors; 
	 
	// 指向DIB的指针 
	LPSTR lpbi; 
	 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFO lpbmi; 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREINFO lpbmc; 
	 
	// 表明是否是Win3.0 DIB的标记 
	BOOL bWinStyleDIB; 
	 
	// 创建结果 
	BOOL bResult = FALSE; 
	 
	// 判断DIB是否为空 
	if (hDIB == NULL) 
	{ 
		// 返回FALSE 
		return FALSE; 
	} 
	 
	// 锁定DIB 
	lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	 
	// 获取指向BITMAPINFO结构的指针(Win3.0) 
	lpbmi = (LPBITMAPINFO)lpbi; 
	 
	// 获取指向BITMAPCOREINFO结构的指针 
	lpbmc = (LPBITMAPCOREINFO)lpbi; 
	 
	// 获取DIB中颜色表中的颜色数目 
	wNumColors = ::DIBNumColors(lpbi); 
	 
	if (wNumColors != 0) 
	{ 
		// 分配为逻辑调色板内存 
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
			+ sizeof(PALETTEENTRY) 
			* wNumColors); 
		 
		// 如果内存不足,退出 
		if (hLogPal == 0) 
		{ 
			// 解除锁定 
			::GlobalUnlock((HGLOBAL) hDIB); 
			 
			// 返回FALSE 
			return FALSE; 
		} 
		 
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); 
		 
		// 设置版本号 
		lpPal->palVersion = PALVERSION; 
		 
		// 设置颜色数目 
		lpPal->palNumEntries = (WORD)wNumColors; 
		 
		// 判断是否是WIN3.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; 
			} 
		} 
		 
		// 按照逻辑调色板创建调色板,并返回指针 
		bResult = pPal->CreatePalette(lpPal); 
		 
		// 解除锁定 
		::GlobalUnlock((HGLOBAL) hLogPal); 
		 
		// 释放逻辑调色板 
		::GlobalFree((HGLOBAL) hLogPal); 
	} 
	 
	// 解除锁定 
	::GlobalUnlock((HGLOBAL) hDIB); 
	 
	// 返回结果 
	return bResult; 
} 
 
/************************************************************************* 
* 
* 函数名称: 
*   FindDIBBits() 
* 
* 参数: 
*   LPSTR lpbi         - 指向DIB对象的指针 
* 
* 返回值: 
*   LPSTR              - 指向DIB图像象素起始位置 
* 
* 说明: 
*   该函数计算DIB中图像象素的起始位置,并返回指向它的指针。 
* 
************************************************************************/ 
 
 
LPSTR WINAPI FindDIBBits(LPSTR lpbi) 
{ 
	return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   DIBWidth() 
* 
* 参数: 
*   LPSTR lpbi         - 指向DIB对象的指针 
* 
* 返回值: 
*   DWORD              - DIB中图像的宽度 
* 
* 说明: 
*   该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER 
* 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。 
* 
************************************************************************/ 
 
 
DWORD WINAPI DIBWidth(LPSTR lpDIB) 
{ 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFOHEADER lpbmi; 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREHEADER lpbmc; 
	 
	// 获取指针 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
	 
	// 返回DIB中图像的宽度 
	if (IS_WIN30_DIB(lpDIB)) 
	{ 
		// 对于Windows 3.0 DIB,返回lpbmi->biWidth 
		return lpbmi->biWidth; 
	} 
	else 
	{ 
		// 对于其它格式的DIB,返回lpbmc->bcWidth 
		return (DWORD)lpbmc->bcWidth; 
	} 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   DIBHeight() 
* 
* 参数: 
*   LPSTR lpDIB        - 指向DIB对象的指针 
* 
* 返回值: 
*   DWORD              - DIB中图像的高度 
* 
* 说明: 
*   该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER 
* 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。 
* 
************************************************************************/ 
 
 
DWORD WINAPI DIBHeight(LPSTR lpDIB) 
{ 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFOHEADER lpbmi; 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREHEADER lpbmc; 
	 
	// 获取指针 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
	 
	// 返回DIB中图像的宽度 
	if (IS_WIN30_DIB(lpDIB)) 
	{ 
		// 对于Windows 3.0 DIB,返回lpbmi->biHeight 
		return lpbmi->biHeight; 
	} 
	else 
	{ 
		// 对于其它格式的DIB,返回lpbmc->bcHeight 
		return (DWORD)lpbmc->bcHeight; 
	} 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   PaletteSize() 
* 
* 参数: 
*   LPSTR lpbi         - 指向DIB对象的指针 
* 
* 返回值: 
*   WORD               - DIB中调色板的大小 
* 
* 说明: 
*   该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目× 
* RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。 
* 
************************************************************************/ 
 
 
WORD WINAPI PaletteSize(LPSTR lpbi) 
{ 
	// 计算DIB中调色板的大小 
	if (IS_WIN30_DIB (lpbi)) 
	{ 
		//返回颜色数目×RGBQUAD的大小 
		return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
	} 
	else 
	{ 
		//返回颜色数目×RGBTRIPLE的大小 
		return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 
	} 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   DIBNumColors() 
* 
* 参数: 
*   LPSTR lpbi         - 指向DIB对象的指针 
* 
* 返回值: 
*   WORD               - 返回调色板中颜色的种数 
* 
* 说明: 
*   该函数返回DIB中调色板的颜色的种数。对于单色位图,返回2, 
* 对于16色位图,返回16,对于256色位图,返回256;对于真彩色 
* 位图(24位),没有调色板,返回0。 
* 
************************************************************************/ 
WORD WINAPI DIBNumColors(LPSTR lpbi) 
{ 
	WORD wBitCount; 
	 
	// 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。 
	// 对于这种情况,则返回一个近似的数值。 
	 
	// 判断是否是WIN3.0 DIB 
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		DWORD dwClrUsed; 
		 
		// 读取dwClrUsed值 
		dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; 
		 
		if (dwClrUsed != 0) 
		{ 
			// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值 
			return (WORD)dwClrUsed; 
		} 
	} 
	 
	// 读取象素的位数 
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		// 读取biBitCount值 
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 
	} 
	else 
	{ 
		// 读取biBitCount值 
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; 
	} 
	 
	// 按照象素的位数计算颜色数目 
	switch (wBitCount) 
	{ 
	case 1: 
		return 2; 
		 
	case 4: 
		return 16; 
		 
	case 8: 
		return 256; 
		 
	default: 
		return 0; 
	} 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   DIBBitCount() 
* 
* 参数: 
*   LPSTR lpbi         - 指向DIB对象的指针 
* 
* 返回值: 
*   WORD               - 返回调色板中颜色的种数 
* 
* 说明: 
*   该函数返回DIBBitCount。 
* 
************************************************************************/ 
WORD WINAPI DIBBitCount(LPSTR lpbi) 
{ 
	WORD wBitCount; 
	 
	// 读取象素的位数 
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		// 读取biBitCount值 
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 
	} 
	else 
	{ 
		// 读取biBitCount值 
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; 
	} 
	 
	// 返回wBitCount 
	return wBitCount; 
} 
 
/************************************************************************* 
* 
* 函数名称: 
*   CopyHandle() 
* 
* 参数: 
*   HGLOBAL h          - 要复制的内存区域 
* 
* 返回值: 
*   HGLOBAL            - 复制后的新内存区域 
* 
* 说明: 
*   该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。 
* 
************************************************************************/ 
 
HGLOBAL WINAPI CopyHandle (HGLOBAL h) 
{ 
	if (h == NULL) 
		return NULL; 
	 
	// 获取指定内存区域大小 
	DWORD dwLen = ::GlobalSize((HGLOBAL) h); 
	 
	// 分配新内存空间 
	HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); 
	 
	// 判断分配是否成功 
	if (hCopy != NULL) 
	{ 
		// 锁定 
		void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
		void* lp     = ::GlobalLock((HGLOBAL) h); 
		 
		// 复制 
		memcpy(lpCopy, lp, dwLen); 
		 
		// 解除锁定 
		::GlobalUnlock(hCopy); 
		::GlobalUnlock(h); 
	} 
	 
	return hCopy; 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   SaveDIB() 
* 
* 参数: 
*   HDIB hDib          - 要保存的DIB 
*   CFile& file        - 保存文件CFile 
* 
* 返回值: 
*   BOOL               - 成功返回TRUE,否则返回FALSE或者CFileException 
* 
* 说明: 
*   该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。 
* 
*************************************************************************/ 
 
 
BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) 
{ 
	// Bitmap文件头 
	BITMAPFILEHEADER bmfHdr; 
	 
	// 指向BITMAPINFOHEADER的指针 
	LPBITMAPINFOHEADER lpBI; 
	 
	// DIB大小 
	DWORD dwDIBSize; 
	 
	if (hDib == NULL) 
	{ 
		// 如果DIB为空,返回FALSE 
		return FALSE; 
	} 
	 
	// 读取BITMAPINFO结构,并锁定 
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); 
	 
	if (lpBI == NULL) 
	{ 
		// 为空,返回FALSE 
		return FALSE; 
	} 
	 
	// 判断是否是WIN3.0 DIB 
	if (!IS_WIN30_DIB(lpBI)) 
	{ 
		// 不支持其它类型的DIB保存 
		 
		// 解除锁定 
		::GlobalUnlock((HGLOBAL) hDib); 
		 
		// 返回FALSE 
		return FALSE; 
	} 
	 
	// 填充文件头 
	 
	// 文件类型"BM" 
	bmfHdr.bfType = DIB_HEADER_MARKER; 
	 
	// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并 
	// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。 
	 
	// 文件头大小+颜色表大小 
	// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小) 
	dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); 
	 
	// 计算图像大小 
	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
	{ 
		// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值 
		dwDIBSize += lpBI->biSizeImage; 
	} 
	else 
	{ 
		// 象素的大小 
		DWORD dwBmBitsSize; 
		 
		// 大小为Width * Height 
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; 
		 
		// 计算出DIB真正的大小 
		dwDIBSize += dwBmBitsSize; 
		 
		// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的) 
		lpBI->biSizeImage = dwBmBitsSize; 
	} 
	 
	 
	// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小 
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
	 
	// 两个保留字 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
	 
	// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
		+ PaletteSize((LPSTR)lpBI); 
	// 尝试写文件 
	TRY 
	{ 
		// 写文件头 
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
		 
		// 写DIB头和象素 
		file.WriteHuge(lpBI, dwDIBSize); 
	} 
	CATCH (CFileException, e) 
	{ 
		// 解除锁定 
		::GlobalUnlock((HGLOBAL) hDib); 
		 
		// 抛出异常 
		THROW_LAST(); 
	} 
	END_CATCH 
		 
		// 解除锁定 
		::GlobalUnlock((HGLOBAL) hDib); 
	 
	// 返回TRUE 
	return TRUE; 
} 
 
 
/************************************************************************* 
* 
* 函数名称: 
*   ReadDIBFile() 
* 
* 参数: 
*   CFile& file        - 要读取得文件文件CFile 
* 
* 返回值: 
*   HDIB               - 成功返回DIB的句柄,否则返回NULL。 
* 
* 说明: 
*   该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER 
* 外的内容都将被读入内存。 
* 
*************************************************************************/ 
 
HDIB WINAPI ReadDIBFile(CFile& file) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	DWORD dwBitsSize; 
	HDIB hDIB; 
	LPSTR pDIB; 
	 
	// 获取DIB(文件)长度(字节) 
	dwBitsSize = file.GetLength(); 
	 
	// 尝试读取DIB文件头 
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
	{ 
		// 大小不对,返回NULL。 
		return NULL; 
	} 
	 
	// 判断是否是DIB对象,检查头两个字节是否是"BM" 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
	{ 
		// 非DIB对象,返回NULL。 
		return NULL; 
	} 
	 
	// 为DIB分配内存 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
	if (hDIB == 0) 
	{ 
		// 内存分配失败,返回NULL。 
		return NULL; 
	} 
	 
	// 锁定 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	 
	// 读象素 
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
		dwBitsSize - sizeof(BITMAPFILEHEADER) ) 
	{ 
		// 大小不对。 
		 
		// 解除锁定 
		::GlobalUnlock((HGLOBAL) hDIB); 
		 
		// 释放内存 
		::GlobalFree((HGLOBAL) hDIB); 
		 
		// 返回NULL。 
		return NULL; 
	} 
	 
	// 解除锁定 
	::GlobalUnlock((HGLOBAL) hDIB); 
	 
	// 返回DIB句柄 
	return hDIB; 
} 
 
 
void WINAPI ConvertShort(unsigned short *array, long length) 
{ 
   unsigned long b1, b2; 
   unsigned char *ptr; 
 
   ptr = (unsigned char *)array; 
   while (length--) { 
      b1 = *ptr++; 
      b2 = *ptr++; 
      *array++ = (unsigned short)((b1 << 8) | (b2)); 
   } 
} 
 
 
void WINAPI ConvertLong(unsigned long  *array, long length) 
{ 
   unsigned long b1, b2, b3, b4; 
   unsigned char *ptr; 
 
   ptr = (unsigned char *)array; 
   while (length--) { 
      b1 = *ptr++; 
      b2 = *ptr++; 
      b3 = *ptr++; 
      b4 = *ptr++; 
      *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); 
   } 
} 
 
 
HDIB WINAPI NewDIB(long width, long height,unsigned short biBitCount) 
{ 
	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;ibmiColors[i].rgbRed =(BYTE)i; 
			lpmf->bmiColors[i].rgbGreen =(BYTE)i; 
			lpmf->bmiColors[i].rgbBlue =(BYTE)i; 
		} 
	} 
 
	::GlobalUnlock((HGLOBAL) hDIB); 
	 
	return hDIB; 
} 
 
void WINAPI	ConvertRGBtoY(HDIB hDIB) 
{ 
	LPSTR	lpDIB; 
	 
	// 由DIB句柄得到DIB指针并锁定DIB 
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
	 
	// 指向DIB象素数据区的指针 
	LPSTR   lpDIBBits;	 
	 
	// 指向DIB象素的指针 
	BYTE *	lpSrc;	 
	 
	// 图像宽度 
	LONG	lWidth;	 
	// 图像高度 
	LONG  	lHeight;	 
	 
	// 图像每行的字节数 
	LONG	lLineBytes;	 
	 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFO lpbmi;	 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREINFO lpbmc; 
	 
	// 获取指向BITMAPINFO结构的指针(Win3.0) 
	lpbmi = (LPBITMAPINFO)lpDIB;	 
	 
	// 获取指向BITMAPCOREINFO结构的指针 
	lpbmc = (LPBITMAPCOREINFO)lpDIB;	 
	 
	// 灰度映射表 
	BYTE bMap[256]; 
	 
	// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板 
	int	i,j; 
	for (i = 0; i < 256; i ++) 
	{ 
		// 计算该颜色对应的灰度值 
		bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed + 0.587 * lpbmi->bmiColors[i].rgbGreen + 0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);	 
 
		// 更新DIB调色板红色分量 
		lpbmi->bmiColors[i].rgbRed = i; 
		 
		// 更新DIB调色板绿色分量 
		lpbmi->bmiColors[i].rgbGreen = i;	 
		 
		// 更新DIB调色板蓝色分量 
		lpbmi->bmiColors[i].rgbBlue = i; 
		 
		// 更新DIB调色板保留位 
		lpbmi->bmiColors[i].rgbReserved = 0; 
		 
	} 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB); 
	 
	// 获取图像宽度 
	lWidth = ::DIBWidth(lpDIB);	 
	 
	// 获取图像高度 
	lHeight = ::DIBHeight(lpDIB);	 
	 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	 
	 
	// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) 
	 
	//逐行扫描 
	for(i = 0; i < lHeight; i++) 
	{ 
		 
		//逐列扫描 
		for(j = 0; j < lWidth; j++) 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 变换 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	//解除锁定 
	::GlobalUnlock ((HGLOBAL)hDIB); 
} 
 
 
void WINAPI	ConvertRGBtoU(HDIB hDIB) 
{ 
	LPSTR	lpDIB; 
	 
	// 由DIB句柄得到DIB指针并锁定DIB 
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
	 
	// 指向DIB象素数据区的指针 
	LPSTR   lpDIBBits;	 
	 
	// 指向DIB象素的指针 
	BYTE *	lpSrc;	 
	 
	// 图像宽度 
	LONG	lWidth;	 
	// 图像高度 
	LONG  	lHeight;	 
	 
	// 图像每行的字节数 
	LONG	lLineBytes;	 
	 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFO lpbmi;	 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREINFO lpbmc; 
	 
	// 获取指向BITMAPINFO结构的指针(Win3.0) 
	lpbmi = (LPBITMAPINFO)lpDIB;	 
	 
	// 获取指向BITMAPCOREINFO结构的指针 
	lpbmc = (LPBITMAPCOREINFO)lpDIB;	 
	 
	// 灰度映射表 
	BYTE bMap[256]; 
	 
	// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板 
	int	i,j; 
	for (i = 0; i < 256; i ++) 
	{ 
		// 计算该颜色对应的灰度值 
		bMap[i] = (BYTE)(-0.147 * lpbmi->bmiColors[i].rgbRed +	-0.289 * lpbmi->bmiColors[i].rgbGreen + 0.436 * lpbmi->bmiColors[i].rgbBlue + 0.5);	 
 
		// 更新DIB调色板红色分量 
		lpbmi->bmiColors[i].rgbRed = i; 
		 
		// 更新DIB调色板绿色分量 
		lpbmi->bmiColors[i].rgbGreen = i;	 
		 
		// 更新DIB调色板蓝色分量 
		lpbmi->bmiColors[i].rgbBlue = i; 
		 
		// 更新DIB调色板保留位 
		lpbmi->bmiColors[i].rgbReserved = 0; 
		 
	} 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB); 
	 
	// 获取图像宽度 
	lWidth = ::DIBWidth(lpDIB);	 
	 
	// 获取图像高度 
	lHeight = ::DIBHeight(lpDIB);	 
	 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	 
	 
	// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) 
	 
	//逐行扫描 
	for(i = 0; i < lHeight; i++) 
	{ 
		 
		//逐列扫描 
		for(j = 0; j < lWidth; j++) 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 变换 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	//解除锁定 
	::GlobalUnlock ((HGLOBAL)hDIB);	 
} 
 
 
void WINAPI	ConvertRGBtoV(HDIB hDIB) 
{ 
	LPSTR	lpDIB; 
	 
	// 由DIB句柄得到DIB指针并锁定DIB 
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
	 
	// 指向DIB象素数据区的指针 
	LPSTR   lpDIBBits;	 
	 
	// 指向DIB象素的指针 
	BYTE *	lpSrc;	 
	 
	// 图像宽度 
	LONG	lWidth;	 
	// 图像高度 
	LONG  	lHeight;	 
	 
	// 图像每行的字节数 
	LONG	lLineBytes;	 
	 
	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPINFO lpbmi;	 
	 
	// 指向BITMAPCOREINFO结构的指针 
	LPBITMAPCOREINFO lpbmc; 
	 
	// 获取指向BITMAPINFO结构的指针(Win3.0) 
	lpbmi = (LPBITMAPINFO)lpDIB;	 
	 
	// 获取指向BITMAPCOREINFO结构的指针 
	lpbmc = (LPBITMAPCOREINFO)lpDIB;	 
	 
	// 灰度映射表 
	BYTE bMap[256]; 
	 
	// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板 
	int	i,j; 
	for (i = 0; i < 256; i ++) 
	{ 
		// 计算该颜色对应的灰度值 
		bMap[i] = (BYTE)(0.615 * lpbmi->bmiColors[i].rgbRed + -0.515 * lpbmi->bmiColors[i].rgbGreen + -0.100 * lpbmi->bmiColors[i].rgbBlue + 0.5);	 
 
		// 更新DIB调色板红色分量 
		lpbmi->bmiColors[i].rgbRed = i; 
		 
		// 更新DIB调色板绿色分量 
		lpbmi->bmiColors[i].rgbGreen = i;	 
		 
		// 更新DIB调色板蓝色分量 
		lpbmi->bmiColors[i].rgbBlue = i; 
		 
		// 更新DIB调色板保留位 
		lpbmi->bmiColors[i].rgbReserved = 0; 
		 
	} 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB); 
	 
	// 获取图像宽度 
	lWidth = ::DIBWidth(lpDIB);	 
	 
	// 获取图像高度 
	lHeight = ::DIBHeight(lpDIB);	 
	 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	 
	 
	// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) 
	 
	//逐行扫描 
	for(i = 0; i < lHeight; i++) 
	{ 
		 
		//逐列扫描 
		for(j = 0; j < lWidth; j++) 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 变换 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	//解除锁定 
	::GlobalUnlock ((HGLOBAL)hDIB);	 
} 
/***************************************************** 
*  
*   函数名称: 
*      Template: 
* 
*    参数: 
*	   HDIB    hDIB         -图像的句柄 
*      int  tem_w           -模板的宽度 
*      int  tem_h           -模板的高度 
*       
*    功能: 
*	   对图像进行中值 
* 
*    说明: 
*	   为处理方便起见,模板的宽度和高度都应为奇数 
*******************************************************/ 
 
HDIB   WINAPI  MidFilter(HDIB hDIB,int tem_w,int tem_h) 
{ 
 
    //统计中间值 
    BYTE mid; 
 
	BYTE *temp=(BYTE*)malloc(tem_w*tem_h*sizeof(BYTE)); 
 
    //指向图像起始位置的指针 
    BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) hDIB); 
 
	//指向象素起始位置的指针 
	BYTE *pScrBuff =(BYTE*)::FindDIBBits((char*)lpDIB); 
    
	//获取图像的颜色信息 
    int numColors=(int) ::DIBNumColors((char *)lpDIB); 
 
    //如果图像不是256色返回 
     if (numColors!=256)  
	 {    
        //解除锁定 
	  	::GlobalUnlock((HGLOBAL) hDIB); 
 
		//返回 
		return(hDIB); 
	 } 
     
    //将指向图像象素起始位置的指针,赋值给指针变量 
    BYTE* oldbuf = pScrBuff; 
 
    //循环变量 
    int i,j,m,n; 
 
	int w, h, dw; 
 
	//获取图像的宽度 
	w = (int) ::DIBWidth((char *)lpDIB); 
	 
	//获取图像的高度 
	h = (int) ::DIBHeight((char *)lpDIB); 
	 
	//计算图像每行的字节数 
	dw = (w+3)/4*4;       
	 
	//建立一个和原图像大小相同的25色灰度位图 
    HDIB newhDIB=NewDIB(w,h,8);   
     
	//指向新的位图的指针 
	BYTE *newlpDIB=(BYTE*)::GlobalLock((HGLOBAL) newhDIB); 
 
	//指向新的位图的象素起始位置的指针  
    BYTE *destBuf = (BYTE*)FindDIBBits((char *)newlpDIB); 
     
   //将指向新图像象素起始位置的指针,赋值给指针变量 
    BYTE *newbuf=destBuf;  
	 
	//对图像进行扫描 
    
	//行  
    for(i=0;i(w-(tem_w+1)/2) || i<((tem_h-1)/2) || i>(h-(tem_h+1)/2) ) 
	      *(newbuf+i*dw+j)=*(oldbuf+i*dw+j); 
		  
         //对于其他的象素进行模板操作 
		 else  
         {  
 
          //将点(i,j)点作为模板的中心 
          for(m=i-((tem_h-1)/2);m<=i+((tem_h-1)/2);m++) 
          { 
		     for(n=j-((tem_w-1)/2);n<=j+((tem_w-1)/2);n++) 
		     
             //将以点(i,j)为中心,与模板大小相同的范围内的象素传递到模板矩阵中 
		     temp[(m-i+((tem_h-1)/2))*tem_w+n-j+((tem_w-1)/2)]=*(oldbuf+m*dw+n); 
		   
		  } 
           
		 //利用气泡法计算中值 
           for(m=0;mtemp[n+1])  
			    mid=temp[n]; 
                temp[n]=temp[n+1]; 
			    temp[n+1]=mid; 
			  } 
		    
		   }  
 
           //将计算的结果放到新的位图的相应位置 
	      *(newbuf+i*dw+j)=temp[(tem_w*tem_h-1)/2]; 
		 } 
	   } 
	}  
    
	//解除锁定 
	::GlobalUnlock((HGLOBAL)hDIB); 
     
	//返回新的位图的句柄 
    return(newhDIB); 
} 
/************************************************************************* 
 * 
 * 函数名称: 
 *   InteEqualize() 
 * 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 
 * 说明: 
 *   该函数用来对图像进行直方图均衡。 
 * 
 ************************************************************************/ 
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; 
}