www.pudn.com > vc++peizhun.rar > DibImage.cpp


/////////////////////////////////////////////////////////////////////// 
// DibImage.cpp: implementation of the CDibImage class. 
//  DIB(Independent Bitmap) 函数: 
// 
//  PaintDIB()          - 绘制DIB对象 
//  CreateDIBPalette()  - 创建DIB对象调色板 
//  FindDIBBits()       - 返回DIB图像象素起始位置 
//  DIBWidth()          - 返回DIB宽度 
//  DIBHeight()         - 返回DIB高度 
//  PaletteSize()       - 返回DIB调色板大小 
//  DIBNumColors()      - 计算DIB调色板颜色数目 
//  CopyHandle()        - 拷贝内存块 
// 
//  SaveDIB()           - 将DIB保存到指定文件中 
//  ReadDIBFile()       - 重指定文件中读取DIB对象 
// 
//  图像点运算函数: 
// 
//  LinerTrans()		- 图像线性变换 
//	WindowTrans()		- 图像窗口变换 
//  GrayStretch()		- 图像灰度拉伸 
//  InteEqualize()		-直方图均衡 
// 
//	图像几何变换函数 
//  TranslationDIB1()   - 图像平移 
//  TranslationDIB()    - 图像平移 
//  MirrorDIB()		    - 图像镜像 
//  TransposeDIB()		- 图像转置 
//  ZoomDIB()			- 图像缩放 
//  RotateDIB()			- 图像旋转 
//	 
//  图像正交变换函数: 
// 
//  FFT()				- 快速付立叶变换 
//  IFFT()				- 快速付立叶反变换 
//  DCT()				- 离散余弦变换 
//  WALSH()				- 沃尔什-哈达玛变换 
// 
//  Fourier()			- 图像的付立叶变换 
//  DIBDct()			- 图像的离散余弦变换 
//  DIBWalsh()			- 图像的沃尔什-哈达玛变换 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Direct.h" 
#include "DibImage.h" 
 
#include  
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDibImage::CDibImage() 
{ 
 
} 
 
CDibImage::~CDibImage() 
{ 
 
} 
 
////////////////////////////////////////////////////////////////////// 
// DIB(Independent Bitmap) 函数 
////////////////////////////////////////////////////////////////////// 
 
/************************************************************************* 
 * 函数名称: 
 *   PaintDIB() 
 * 参数: 
 *   HDC hDC            - 输出设备DC 
 *   LPRECT lpDCRect    - 绘制矩形区域 
 *   HDIB hDIB          - 指向DIB对象的指针 
 *   LPRECT lpDIBRect   - 要输出的DIB区域 
 *   CPalette* pPal     - 指向DIB对象调色板的指针 
 * 返回值: 
 *   BOOL               - 绘制成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者 
 * SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指 
 * 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数 
 * lpDIBRect指定。 
 ************************************************************************/ 
BOOL CDibImage::PaintDIB(HDC     hDC, 
					LPRECT  lpDCRect, 
					HDIB    hDIB, 
					LPRECT  lpDIBRect, 
					CPalette* pPal) 
{ 
	LPSTR    lpDIBHdr;            // BITMAPINFOHEADER指针 
	LPSTR    lpDIBBits;           // DIB象素指针 
	BOOL     bSuccess=FALSE;      // 成功标志 
	HPALETTE hPal=NULL;           // DIB调色板 
	HPALETTE hOldPal=NULL;        // 以前的调色板 
 
	if (hDIB == NULL) 
	{ 
		return FALSE; 
	} 
	 
	lpDIBHdr  = (LPSTR)::GlobalLock((HGLOBAL) hDIB);// 锁定DIB	 
	lpDIBBits = FindDIBBits(lpDIBHdr);	// 找到DIB图像象素起始位置 
 
	if (pPal != NULL)					// 获取DIB调色板,并选中它 
	{ 
		hPal = (HPALETTE) pPal->m_hObject;	 
		hOldPal = ::SelectPalette(hDC, hPal, TRUE);	// 选中调色板 
	} 
 
	::SetStretchBltMode(hDC, COLORONCOLOR);			// 设置显示模式 
 
	// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象 
	if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) && 
	   (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 
	{ 
		// 原始大小,不用拉伸。 
		bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC 
								   lpDCRect->left,             // DestX 
								   lpDCRect->top,              // DestY 
								   RECTWIDTH(lpDCRect),        // nDestWidth 
								   RECTHEIGHT(lpDCRect),       // nDestHeight 
								   lpDIBRect->left,            // SrcX 
								   (int)DIBHeight(lpDIBHdr) - 
									  lpDIBRect->top - 
									  RECTHEIGHT(lpDIBRect),   // SrcY 
								   0,                          // nStartScan 
								   (WORD)DIBHeight(lpDIBHdr),  // nNumScans 
								   lpDIBBits,                  // lpBits 
								   (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo 
								   DIB_RGB_COLORS);            // wUsage 
	} 
    else 
	{ 
		// 非原始大小,拉伸。 
		bSuccess = ::StretchDIBits(hDC,                          // hDC 
							   lpDCRect->left,                 // DestX 
							   lpDCRect->top,                  // DestY 
							   RECTWIDTH(lpDCRect),            // nDestWidth 
							   RECTHEIGHT(lpDCRect),           // nDestHeight 
							   lpDIBRect->left,                // SrcX 
							   lpDIBRect->top,                 // SrcY 
							   RECTWIDTH(lpDIBRect),           // wSrcWidth 
							   RECTHEIGHT(lpDIBRect),          // wSrcHeight 
							   lpDIBBits,                      // lpBits 
							   (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo 
							   DIB_RGB_COLORS,                 // wUsage 
							   SRCCOPY);                       // dwROP 
	} 
	  
	::GlobalUnlock((HGLOBAL) hDIB);				// 解除锁定	 
	if (hOldPal != NULL) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE);	// 恢复以前的调色板 
	}	 
	return bSuccess; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   CreateDIBPalette() 
 * 参数: 
 *   HDIB hDIB          - 指向DIB对象的指针 
 *   CPalette* pPal     - 指向DIB对象调色板的指针 
 * 返回值: 
 *   BOOL               - 创建成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中, 
 * 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样 
 * 可以用最好的颜色来显示DIB图像。 
 ************************************************************************/ 
BOOL CDibImage::CreateDIBPalette(HDIB hDIB, CPalette* pPal) 
{ 
	 
	LPLOGPALETTE lpPal;		// 指向逻辑调色板的指针 
	HANDLE hLogPal;			// 逻辑调色板的句柄 
	HPALETTE hPal = NULL;	// 调色板的句柄 
	int i;					// 循环变量	 
	WORD wNumColors;		// 颜色表中的颜色数目	 
	LPSTR lpbi;				// 指向DIB的指针	 
	LPBITMAPINFO lpbmi;		// 指向BITMAPINFO结构的指针(Win3.0)	 
	LPBITMAPCOREINFO lpbmc;	// 指向BITMAPCOREINFO结构的指针	 
	BOOL bWinStyleDIB;		// 表明是否是Win3.0 DIB的标记	 
	BOOL bResult = FALSE;	// 创建结果 
	 
	if (hDIB == NULL) 
	{ 
		return FALSE; 
	} 
		 
	lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);	// 锁定DIB 
	lpbmi = (LPBITMAPINFO)lpbi;		// 获取指向BITMAPINFO结构的指针(Win3.0) 
	lpbmc = (LPBITMAPCOREINFO)lpbi;	// 获取指向BITMAPCOREINFO结构的指针 
	wNumColors = DIBNumColors(lpbi);// 获取DIB中颜色表中的颜色数目 
	 
	if (wNumColors != 0) 
	{ 
		// 分配为逻辑调色板内存 
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
									+ sizeof(PALETTEENTRY) 
									* wNumColors);	 
		// 如果内存不足,退出 
		if (hLogPal == 0) 
		{	 
			::GlobalUnlock((HGLOBAL) hDIB);	// 解除锁定 
			return FALSE; 
		} 
		 
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);		 
		lpPal->palVersion = PALVERSION;			// 设置版本号 
		lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目 
		bWinStyleDIB = IS_WIN30_DIB(lpbi);		// 判断是否是WIN3.0的DIB 
 
		// 读取调色板 
		for (i = 0; i < (int)wNumColors; i++) 
		{ 
			if (bWinStyleDIB) 
			{ 
				// 读取红色绿色蓝色分量 
				lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 
				lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 
				lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;				 
				// 保留位 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
			else 
			{ 
				// 读取红色绿色蓝色分量 
				lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 
				lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 
				lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;				 
				// 保留位 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
		} 
			 
		bResult = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针 
		::GlobalUnlock((HGLOBAL) hLogPal);	// 解除锁定 
		::GlobalFree((HGLOBAL) hLogPal);	// 释放逻辑调色板 
	} 
	 
	::GlobalUnlock((HGLOBAL) hDIB);			// 解除锁定 
	return bResult; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   FindDIBBits() 
 * 参数: 
 *   LPSTR lpbi         - 指向DIB对象的指针 
 * 返回值: 
 *   LPSTR              - 指向DIB图像象素起始位置 
 * 说明: 
 *   该函数计算DIB中图像象素的起始位置,并返回指向它的指针。 
 ************************************************************************/ 
LPSTR CDibImage::FindDIBBits(LPSTR lpbi) 
{ 
	return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi)); 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   DIBWidth() 
 * 参数: 
 *   LPSTR lpbi         - 指向DIB对象的指针 
 * 返回值: 
 *   DWORD              - DIB中图像的宽度 
 * 说明: 
 *   该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER 
 * 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。 
 ************************************************************************/ 
DWORD CDibImage::DIBWidth(LPSTR lpDIB) 
{ 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	// 返回DIB中图像的宽度 
	if (IS_WIN30_DIB(lpDIB)) 
	{		 
		return lpbmi->biWidth;		// 对于Windows 3.0 DIB,返回lpbmi->biWidth 
	} 
	else 
	{		 
		return (DWORD)lpbmc->bcWidth;	// 对于其它格式的DIB,返回lpbmc->bcWidth 
	} 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   DIBHeight() 
 * 参数: 
 *   LPSTR lpDIB        - 指向DIB对象的指针 
 * 返回值: 
 *   DWORD              - DIB中图像的高度 
 * 说明: 
 *   该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER 
 * 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。 
 ************************************************************************/ 
DWORD CDibImage::DIBHeight(LPSTR lpDIB) 
{	 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	// 返回DIB中图像的宽度 
	if (IS_WIN30_DIB(lpDIB)) 
	{		 
		return lpbmi->biHeight;		// 对于Windows 3.0 DIB,返回lpbmi->biHeight 
	} 
	else 
	{		 
		return (DWORD)lpbmc->bcHeight;	// 对于其它格式的DIB,返回lpbmc->bcHeight 
	} 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   PaletteSize() 
 * 参数: 
 *   LPSTR lpbi         - 指向DIB对象的指针 
 * 返回值: 
 *   WORD               - DIB中调色板的大小 
 * 说明: 
 *   该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目× 
 * RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。 
 ************************************************************************/ 
WORD CDibImage::PaletteSize(LPSTR lpbi) 
{ 
	// 计算DIB中调色板的大小 
	if (IS_WIN30_DIB (lpbi)) 
	{ 
		//返回颜色数目×RGBQUAD的大小 
		return (WORD)(DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
	} 
	else 
	{ 
		//返回颜色数目×RGBTRIPLE的大小 
		return (WORD)(DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 
	} 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   DIBNumColors() 
 * 参数: 
 *   LPSTR lpbi         - 指向DIB对象的指针 
 * 返回值: 
 *   WORD               - 返回调色板中颜色的种数 
 * 说明: 
 *   该函数返回DIB中调色板的颜色的种数。对于单色位图,返回2, 
 * 对于16色位图,返回16,对于256色位图,返回256;对于真彩色 
 * 位图(24位),没有调色板,返回0。 
 ************************************************************************/ 
WORD CDibImage::DIBNumColors(LPSTR lpbi) 
{ 
	WORD wBitCount; 
 
	// 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。 
	// 对于这种情况,则返回一个近似的数值。 
	 
	// 判断是否是WIN3.0 DIB 
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		DWORD dwClrUsed; 
		dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;	// 读取dwClrUsed值 
		 
		if (dwClrUsed != 0) 
		{ 
			// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值 
			return (WORD)dwClrUsed; 
		} 
	} 
 
	// 读取象素的位数 
	if (IS_WIN30_DIB(lpbi)) 
	{		 
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;	// 读取biBitCount值 
	} 
	else 
	{		 
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;	// 读取biBitCount值 
	} 
	 
	// 按照象素的位数计算颜色数目 
	switch (wBitCount) 
	{ 
		case 1: 
			return 2; 
			break; 
		case 4: 
			return 16; 
			break; 
		case 8: 
			return 256; 
			break; 
		default: 
			return 0; 
			break; 
	} 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   CopyHandle() 
 * 参数: 
 *   HGLOBAL h          - 要复制的内存区域 
 * 返回值: 
 *   HGLOBAL            - 复制后的新内存区域 
 * 说明: 
 *   该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。 
 ************************************************************************/ 
HGLOBAL CDibImage::CopyHandle (HGLOBAL h) 
{ 
	if (h == NULL) 
	{ 
		return NULL; 
	} 
	 
	DWORD dwLen = ::GlobalSize((HGLOBAL) h);	// 获取指定内存区域大小 
	HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);	// 分配新内存空间	 
	if (hCopy != NULL)							// 判断分配是否成功 
	{ 
		void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
		void* lp     = ::GlobalLock((HGLOBAL) h); 
		 
		memcpy(lpCopy, lp, dwLen); 
		 
		::GlobalUnlock(hCopy); 
		::GlobalUnlock(h); 
	} 
 
	return hCopy; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   SaveDIB() 
 * 参数: 
 *   HDIB hDib          - 要保存的DIB 
 *   CFile& file        - 保存文件CFile 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE或者CFileException 
 * 说明: 
 *   该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。 
 *************************************************************************/ 
BOOL CDibImage::SaveDIB(HDIB hDib, CFile& file) 
{	 
	BITMAPFILEHEADER bmfHdr;	// Bitmap文件头	 
	LPBITMAPINFOHEADER lpBI;	// 指向BITMAPINFOHEADER的指针 
	DWORD dwDIBSize;			// DIB大小 
 
	if (hDib == NULL) 
	{ 
		return FALSE; 
	} 
 
	// 读取BITMAPINFO结构,并锁定 
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);	 
	if (lpBI == NULL) 
	{ 
		return FALSE; 
	} 
	 
	// 判断是否是WIN3.0 DIB 
	if (!IS_WIN30_DIB(lpBI)) 
	{ 
		// 不支持其它类型的DIB保存 
		::GlobalUnlock((HGLOBAL) hDib); 
		return FALSE; 
	} 
 
	//////////////////////////////////////////////////////////////////////// 
	// 填充文件头///////////////////////////////////////////////////////////	 
	bmfHdr.bfType = DIB_HEADER_MARKER;		// 文件类型"BM" 
 
	// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并 
	// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。 
	 
	// 文件头大小+颜色表大小 
	// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小) 
	dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); 
	 
	// 计算图像大小 
	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
	{ 
		// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值 
		dwDIBSize += lpBI->biSizeImage; 
	} 
	else 
	{		 
		DWORD dwBmBitsSize;			// 象素的大小 
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount))  
			* lpBI->biHeight;		// 大小为Width * Height 
		dwDIBSize += dwBmBitsSize;	// 计算出DIB真正的大小 
 
		// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的) 
		lpBI->biSizeImage = dwBmBitsSize; 
	} 
 
	// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小 
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
	 
	// 两个保留字 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
											  + PaletteSize((LPSTR)lpBI); 
 
	///////////////////////////////////////////////////////////////////////// 
	// 尝试写文件//////////////////////////////////////////////////////////// 
	TRY 
	{		 
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));	// 写文件头 
		file.WriteHuge(lpBI, dwDIBSize);					// 写DIB头和象素 
	} 
	CATCH (CFileException, e) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		THROW_LAST(); 
	} 
	END_CATCH 
	 
	::GlobalUnlock((HGLOBAL) hDib); 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   ReadDIBFile() 
 * 参数: 
 *   CFile& file        - 要读取得文件文件CFile 
 * 返回值: 
 *   HDIB               - 成功返回DIB的句柄,否则返回NULL。 
 * 说明: 
 *   该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER 
 * 外的内容都将被读入内存。 
 *************************************************************************/ 
HDIB CDibImage::ReadDIBFile(CFile& file) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	HDIB hDIB; 
	LPSTR pDIB; 
	DWORD dwBitsSize; 
 
	dwBitsSize = file.GetLength();		// 获取DIB(文件)长度(字节) 
 
	// 尝试读取DIB文件头 
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
	{ 
		return NULL; 
	} 
	// 判断是否是DIB对象,检查头两个字节是否是"BM" 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
	{ 
		return NULL; 
	} 
	// 为DIB分配内存 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
	if (hDIB == 0) 
	{ 
		return NULL; 
	} 
	 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
		dwBitsSize - sizeof(BITMAPFILEHEADER) )		// 读象素 
	{ 
		::GlobalUnlock((HGLOBAL) hDIB); 
		::GlobalFree((HGLOBAL) hDIB); 
		return NULL; 
	} 
 
	::GlobalUnlock((HGLOBAL) hDIB); 
	return hDIB; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 图像点运算函数 
////////////////////////////////////////////////////////////////////// 
 
/************************************************************************* 
 * 函数名称: 
 *   LinerTrans() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   FLOAT fA		    - 线性变换的斜率 
 *   FLOAT fB           - 线性变换的截距 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行灰度的线性变换操作。 
 ************************************************************************/ 
BOOL CDibImage::LinerTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
						   FLOAT fA, FLOAT fB) 
{		 
	unsigned char*	lpSrc;		// 指向源图像的指针 
	LONG	i;					// 循环变量 
	LONG	j;		 
	LONG	lLineBytes;			// 图像每行的字节数	 
	FLOAT	fTemp;				// 中间变量	 
 
	lLineBytes = WIDTHBYTES(lWidth * 8);	// 计算图像每行的字节数 
		 
	for(i = 0; i < lHeight; i++)			// 每行 
	{		 
		for(j = 0; j < lWidth; j++)			// 每列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;			 
			fTemp = fA * (*lpSrc) + fB;		// 线性变换	 
			 
			if (fTemp > 255)				// 判断是否超出范围 
			{ 
				*lpSrc = 255; 
			} 
			else if (fTemp < 0) 
			{ 
				*lpSrc = 0; 
			} 
			else 
			{				 
				*lpSrc = (unsigned char) (fTemp + 0.5);	// 四舍五入 
			} 
		} 
	} 
	 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   ThresholdTrans() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   BYTE  bThre	    - 阈值 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置 
 * 灰度值为0;灰度值大于阈值的象素直接设置为255。 
 ************************************************************************/ 
BOOL CDibImage::ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre) 
{	 
	unsigned char*	lpSrc;				// 指向源图像的指针	 
	LONG	i;							// 循环变量 
	LONG	j;	 
	LONG	lLineBytes;					// 图像每行的字节数 
		 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数	 
	 
	for(i = 0; i < lHeight; i++)		// 每行 
	{		 
		for(j = 0; j < lWidth; j++)		// 每列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;			 
			 
			if ((*lpSrc) < bThre)		// 判断是否小于阈值 
			{ 
				*lpSrc = 0; 
			} 
			else 
			{ 
				*lpSrc = 255; 
			} 
		} 
	} 
	 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   WindowTrans() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   BYTE  bLow		    - 窗口下限 
 *   BYTE  bUp          - 窗口上限 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行窗口变换。只有在窗口范围内的灰度保持不变, 
 * 小于下限的象素直接设置灰度值为0;大于上限的象素直接设置灰度值为255。 
 ************************************************************************/ 
BOOL CDibImage::WindowTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
							BYTE bLow, BYTE bUp) 
{	 
	unsigned char*	lpSrc;				// 指向源图像的指针	 
	LONG	i;							// 循环变量 
	LONG	j; 
	LONG	lLineBytes;					// 图像每行的字节数 
		 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数	 
	 
	for(i = 0; i < lHeight; i++)		// 每行 
	{	 
		for(j = 0; j < lWidth; j++)		// 每列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;			 
			if ((*lpSrc) < bLow)		// 判断是否超出范围 
			{ 
				*lpSrc = 0; 
			} 
			else if ((*lpSrc) > bUp) 
			{ 
				*lpSrc = 255; 
			} 
		} 
	} 
	 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   GrayStretch() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   BYTE bX1			- 灰度拉伸第一个点的X坐标 
 *   BYTE bY1			- 灰度拉伸第一个点的Y坐标 
 *   BYTE bX2			- 灰度拉伸第二个点的X坐标 
 *   BYTE bY2			- 灰度拉伸第二个点的Y坐标 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行灰度拉伸。 
 ************************************************************************/ 
BOOL CDibImage::GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
							BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2) 
{	 
	unsigned char*	lpSrc;				// 指向源图像的指针 
	LONG	i;							// 循环变量 
	LONG	j;	 
	BYTE	bMap[256];					// 灰度映射表	 
	LONG	lLineBytes;					// 图像每行的字节数 
	 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 
	 
	// 计算灰度映射表 
	for (i = 0; i <= bX1; i++) 
	{		 
		if (bX1 > 0)					// 判断bX1是否大于0(防止分母为0) 
		{ 
			bMap[i] = (BYTE) bY1 * i / bX1; 
		} 
		else 
		{ 
			bMap[i] = 0; 
		} 
	} 
	for (; i <= bX2; i++) 
	{ 
		if (bX2 != bX1)					// 判断bX1是否等于bX2(防止分母为0) 
		{ 
			bMap[i] = bY1 + (BYTE) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1)); 
		} 
		else 
		{ 
			bMap[i] = bY1; 
		} 
	} 
	for (; i < 256; i++) 
	{	 
		if (bX2 != 255)					// 判断bX2是否等于255(防止分母为0) 
		{ 
			bMap[i] = bY2 + (BYTE) ((255 - bY2) * (i - bX2) / (255 - bX2)); 
		} 
		else 
		{ 
			bMap[i] = 255; 
		} 
	} 
		 
	for(i = 0; i < lHeight; i++)		// 每行 
	{		 
		for(j = 0; j < lWidth; j++)		// 每列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;			 
			// 计算新的灰度值 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   InteEqualize() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行直方图均衡。 
 ************************************************************************/ 
BOOL CDibImage::InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{	 
	unsigned char*	lpSrc;				// 指向源图像的指针	 
	LONG	lTemp;						// 临时变量	 
	LONG	i;							// 循环变量 
	LONG	j;	 
	BYTE	bMap[256];					// 灰度映射表	 
	LONG	lCount[256];				// 灰度映射表 
	LONG	lLineBytes;					// 图像每行的字节数 
		 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 
		 
	for (i = 0; i < 256; i ++)			// 重置计数为0 
	{ 
		lCount[i] = 0; 
	} 
	 
	// 计算各个灰度值的计数 
	for (i = 0; i < lHeight; i ++) 
	{ 
		for (j = 0; j < lWidth; j ++) 
		{ 
			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j; 
			lCount[*(lpSrc)]++; 
		} 
	} 
	 
	// 计算灰度映射表 
	for (i = 0; i < 256; i++) 
	{ 
		lTemp = 0;		 
		for (j = 0; j <= i ; j++) 
		{ 
			lTemp += lCount[j]; 
		} 
		 
		// 计算对应的新灰度值 
		bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth); 
	} 
		 
	for(i = 0; i < lHeight; i++)			// 每行 
	{ 
		for(j = 0; j < lWidth; j++)			// 每列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;			 
			// 计算新的灰度值 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	return TRUE; 
} 
 
////////////////////////////////////////////////////////////////////// 
// 图像几何变换函数 
////////////////////////////////////////////////////////////////////// 
 
/************************************************************************* 
 * 函数名称: 
 *   TranslationDIB1() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   LONG  lXOffset     - X轴平移量(象素数) 
 *   LONG  lYOffset     - Y轴平移量(象素数) 
 * 返回值: 
 *   BOOL               - 平移成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像 
 * 将截去,空白部分用白色填充。 
 ************************************************************************/ 
BOOL CDibImage::TranslationDIB1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
								LONG lXOffset, LONG lYOffset) 
{	 
	LPSTR	lpSrc;					// 指向源图像的指针	 
	LPSTR	lpDst;					// 指向要复制区域的指针 
	LPSTR	lpNewDIBBits;			// 指向复制图像的指针 
	HLOCAL	hNewDIBBits; 
	LONG	i;						// 象素在新DIB中的坐标 
	LONG	j;	 
	LONG	i0;						// 象素在源DIB中的坐标 
	LONG	j0;	 
	LONG lLineBytes;				// 图像每行的字节数 
	 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 
	 
	// 暂时分配内存,以保存新图像 
	hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
	if (hNewDIBBits == NULL) 
	{ 
		return FALSE; 
	} 
		 
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits);	 
		 
	for(i = 0; i < lHeight; i++)					// 每行 
	{		 
		for(j = 0; j < lWidth; j++)					// 每列 
		{ 
			// 指向新DIB第i行,第j个象素的指针 
			// 注意由于DIB中图像第一行其实保存在最后一行的位置,因此lpDst 
			// 值不是(char *)lpNewDIBBits + lLineBytes * i + j,而是 
			// (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j 
			lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 计算该象素在源DIB中的坐标 
			i0 = i - lXOffset; 
			j0 = j - lYOffset; 
			 
			// 判断是否在源图范围内 
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
			{ 
				// 指向源DIB第i0行,第j0个象素的指针 
				// 同样要注意DIB上下倒置的问题 
				lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;							 
				*lpDst = *lpSrc;					// 复制象素 
			} 
			else 
			{ 
				// 对于源图中没有的象素,直接赋值为255 
				* ((unsigned char*)lpDst) = 255; 
			} 
		} 
	} 
	 
	// 复制平移后的图像 
	memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 
	 
	LocalUnlock(hNewDIBBits); 
	LocalFree(hNewDIBBits); 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   TranslationDIB() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   LONG  lXOffset     - X轴平移量(象素数) 
 *   LONG  lYOffset     - Y轴平移量(象素数) 
 * 返回值: 
 *   BOOL               - 平移成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像 
 * 将截去,空白部分用白色填充。 
 ************************************************************************/ 
BOOL CDibImage::TranslationDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
							   LONG lXOffset, LONG lYOffset) 
{	 
	CRect	rectSrc;	// 平移后剩余图像在源图像中的位置(矩形区域)	 
	CRect	rectDst;	// 平移后剩余图像在新图像中的位置(矩形区域)	 
	LPSTR	lpSrc;		// 指向源图像的指针	 
	LPSTR	lpDst;		// 指向要复制区域的指针	 
	LPSTR	lpNewDIBBits;	// 指向复制图像的指针 
	HLOCAL	hNewDIBBits; 
	BOOL	bVisible;	// 指明图像是否全部移去可视区间	 
	LONG	i;			// 循环变量	 
	LONG lLineBytes;	// 图像每行的字节数 
		 
	lLineBytes = WIDTHBYTES(lWidth * 8);	// 计算图像每行的字节数	 
	bVisible = TRUE;	// 赋初值 
	 
	// 计算rectSrc和rectDst的X坐标 
	if (lXOffset <= -lWidth) 
	{		 
		bVisible = FALSE;	// X轴方向全部移出可视区域 
	} 
	else if (lXOffset <= 0) 
	{		 
		rectDst.left = 0;	// 移动后,有图区域左上角X坐标为0 
		 
		// 移动后,有图区域右下角X坐标为lWidth - |lXOffset| = lWidth + lXOffset 
		rectDst.right = lWidth + lXOffset; 
	} 
	else if (lXOffset < lWidth) 
	{	 
		rectDst.left = lXOffset;	// 移动后,有图区域左上角X坐标为lXOffset	 
		rectDst.right = lWidth;		// 移动后,有图区域右下角X坐标为lWidth 
	} 
	else 
	{		 
		bVisible = FALSE;			// X轴方向全部移出可视区域 
	} 
	 
	// 平移后剩余图像在源图像中的X坐标 
	rectSrc.left = rectDst.left - lXOffset; 
	rectSrc.right = rectDst.right - lXOffset; 
	 
	//  计算rectSrc和rectDst的Y坐标 
	if (lYOffset <= -lHeight) 
	{		 
		bVisible = FALSE;			// Y轴方向全部移出可视区域 
	} 
	else if (lYOffset <= 0) 
	{		 
		rectDst.top = 0;			// 移动后,有图区域左上角Y坐标为0 
		 
		// 移动后,有图区域右下角Y坐标为lHeight - |lYOffset| = lHeight + lYOffset 
		rectDst.bottom = lHeight + lYOffset; 
	} 
	else if (lYOffset < lHeight) 
	{		 
		rectDst.top = lYOffset;		// 移动后,有图区域左上角Y坐标为lYOffset		 
		rectDst.bottom = lHeight;	// 移动后,有图区域右下角Y坐标为lHeight 
	} 
	else 
	{		 
		bVisible = FALSE;			// X轴方向全部移出可视区域 
	} 
	 
	// 平移后剩余图像在源图像中的Y坐标 
	rectSrc.top = rectDst.top - lYOffset; 
	rectSrc.bottom = rectDst.bottom - lYOffset; 
	 
	// 暂时分配内存,以保存新图像 
	hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); 
	if (hNewDIBBits == NULL) 
	{ 
		return FALSE; 
	} 
	 
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 
	 
	// 初始化新分配的内存,设定初始值为255 
	lpDst = (char *)lpNewDIBBits; 
	memset(lpDst, (BYTE)255, lLineBytes * lHeight); 
		 
	if (bVisible)		// 如果有部分图像可见 
	{ 
		// 平移图像 
		for(i = 0; i < (rectSrc.bottom - rectSrc.top); i++) 
		{ 
			// 要复制区域的起点,注意由于DIB图像内容是上下倒置的,第一行内容是保存 
			// 在最后一行,因此复制区域的起点不是lpDIBBits + lLineBytes * (i +  
			// rectSrc.top) + rectSrc.left,而是 lpDIBBits + lLineBytes *  
			// (lHeight - i - rectSrc.top - 1) + rectSrc.left。 
			 
			lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - i - rectSrc.top 
				- 1) + rectSrc.left; 
			 
			// 要目标区域的起点,同样注意上下倒置的问题。 
			lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - i - rectDst.top 
				- 1) + rectDst.left; 
			 
			// 拷贝每一行,宽度为rectSrc.right - rectSrc.left 
			memcpy(lpDst, lpSrc, rectSrc.right - rectSrc.left); 
			 
		} 
	} 
 
	// 复制平移后的图像 
	memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); 
	 
	LocalUnlock(hNewDIBBits); 
	LocalFree(hNewDIBBits); 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   MirrorDIB() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   BOOL  bDirection   - 镜像的方向,TRUE表示水平镜像,FALSE表示垂直镜像 
 * 返回值: 
 *   BOOL               - 镜像成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来镜像DIB图像。可以指定镜像的方式是水平还是垂直。 
 ************************************************************************/ 
BOOL CDibImage::MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,  
						  BOOL bDirection) 
{		 
	LPSTR	lpSrc;						// 指向源图像的指针	 
	LPSTR	lpDst;						// 指向要复制区域的指针	 
	LPSTR	lpBits;						// 指向复制图像的指针 
	HLOCAL	hBits;	 
	LONG	i;							// 循环变量 
	LONG	j;	 
	LONG lLineBytes;					// 图像每行的字节数	 
	 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数		 
	hBits = LocalAlloc(LHND, lLineBytes);	// 暂时分配内存,以保存一行图像 
	if (hBits == NULL) 
	{ 
		return FALSE; 
	} 
	 
	lpBits = (char * )LocalLock(hBits); 
	 
	// 判断镜像方式 
	if (bDirection)		// 水平镜像 
	{	 
		// 针对图像每行进行操作 
		for(i = 0; i < lHeight; i++) 
		{ 
			// 针对每行图像左半部分进行操作 
			for(j = 0; j < lWidth / 2; j++) 
			{				 
				// 指向倒数第i行,第j个象素的指针 
				lpSrc = (char *)lpDIBBits + lLineBytes * i + j;				 
				// 指向倒数第i行,倒数第j个象素的指针 
				lpDst = (char *)lpDIBBits + lLineBytes * (i + 1) - j; 
				 
				// 备份一个象素 
				*lpBits = *lpDst; 
				 
				// 将倒数第i行,第j个象素复制到倒数第i行,倒数第j个象素 
				*lpDst = *lpSrc;				 
				// 将倒数第i行,倒数第j个象素复制到倒数第i行,第j个象素 
				*lpSrc = *lpBits; 
			}			 
		} 
	} 
	else				// 垂直镜像 
	{ 
		// 针对上半图像进行操作 
		for(i = 0; i < lHeight / 2; i++) 
		{			 
			// 指向倒数第i行象素起点的指针 
			lpSrc = (char *)lpDIBBits + lLineBytes * i;			 
			// 指向第i行象素起点的指针 
			lpDst = (char *)lpDIBBits + lLineBytes * (lHeight - i - 1); 
			 
			// 备份一行,宽度为lWidth 
			memcpy(lpBits, lpDst, lLineBytes); 
			 
			// 将倒数第i行象素复制到第i行 
			memcpy(lpDst, lpSrc, lLineBytes);			 
			// 将第i行象素复制到倒数第i行 
			memcpy(lpSrc, lpBits, lLineBytes);			 
		} 
	} 
	 
	LocalUnlock(hBits); 
	LocalFree(hBits); 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   TransposeDIB() 
 * 参数: 
 *   LPSTR lpDIB		- 指向源DIB的指针 
 * 返回值: 
 *   BOOL               - 转置成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来转置DIB图像,即图像x、y坐标互换。函数将不会改变图像的大小, 
 * 但是图像的高宽将互换。 
 ************************************************************************/ 
BOOL CDibImage::TransposeDIB(LPSTR lpDIB) 
{	 
	LONG	lWidth;				// 图像的宽度 
	LONG	lHeight;			// 图像的高度	 
	LPSTR	lpDIBBits;			// 指向源图像的指针	 
	LPSTR	lpSrc;				// 指向源象素的指针	 
	LPSTR	lpDst;				// 指向转置图像对应象素的指针	 
	LPSTR	lpNewDIBBits;		// 指向转置图像的指针 
	HLOCAL	hNewDIBBits; 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0) 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针 
	LONG	i;					 
	LONG	j;	 
	LONG lLineBytes;			// 图像每行的字节数 
	LONG lNewLineBytes;			// 新图像每行的字节数 
 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	 
	lpDIBBits = FindDIBBits(lpDIB);		// 找到源DIB图像象素起始位置	 
	lWidth = DIBWidth(lpDIB);			// 获取图像的"宽度"(4的倍数) 
	lHeight = DIBHeight(lpDIB);			// 获取图像的高度 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 
	lNewLineBytes = WIDTHBYTES(lHeight * 8);	// 计算新图像每行的字节数 
	 
	// 暂时分配内存,以保存新图像 
	hNewDIBBits = LocalAlloc(LHND, lWidth * lNewLineBytes); 
	if (hNewDIBBits == NULL) 
	{ 
		return FALSE; 
	} 
	 
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 
		 
	for(i = 0; i < lHeight; i++)	// 针对图像每行进行操作 
	{		 
		for(j = 0; j < lWidth; j++)	// 针对每行图像每列进行操作 
		{			 
			// 指向源DIB第i行,第j个象素的指针 
			lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;	 
			 
			// 指向转置DIB第j行,第i个象素的指针 
			// 注意此处lWidth和lHeight是源DIB的宽度和高度,应该互换 
			lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lWidth - 1 - j) + i; 
			 
			// 复制象素 
			*lpDst = *lpSrc;			 
		}		 
	} 
	 
	// 复制转置后的图像 
	memcpy(lpDIBBits, lpNewDIBBits, lWidth * lNewLineBytes); 
	 
	// 互换DIB中图像的高宽 
	if (IS_WIN30_DIB(lpDIB)) 
	{ 
		// 对于Windows 3.0 DIB 
		lpbmi->biWidth = lHeight;		 
		lpbmi->biHeight = lWidth; 
	} 
	else 
	{ 
		// 对于其它格式的DIB 
		lpbmc->bcWidth = (unsigned short) lHeight; 
		lpbmc->bcHeight = (unsigned short) lWidth; 
	} 
	 
	LocalUnlock(hNewDIBBits); 
	LocalFree(hNewDIBBits); 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   ZoomDIB() 
 * 参数: 
 *   LPSTR lpDIB		- 指向源DIB的指针 
 *   float fXZoomRatio	- X轴方向缩放比率 
 *   float fYZoomRatio	- Y轴方向缩放比率 
 * 返回值: 
 *   HGLOBAL            - 缩放成功返回新DIB句柄,否则返回NULL。 
 * 说明: 
 *   该函数用来缩放DIB图像,返回新生成DIB的句柄。 
 ************************************************************************/ 
HGLOBAL CDibImage::ZoomDIB(LPSTR lpDIB, float fXZoomRatio, float fYZoomRatio) 
{ 
	LONG	lWidth;				// 源图像的宽度 
	LONG	lHeight;			// 源图像的高度	 
	LONG	lNewWidth;			// 缩放后图像的宽度 
	LONG	lNewHeight;			// 缩放后图像的高度	 
	LONG	lNewLineBytes;		// 缩放后图像的宽度(lNewWidth',必须是4的倍数)	 
	LPSTR	lpDIBBits;			// 指向源图像的指针	 
	LPSTR	lpSrc;				// 指向源象素的指针	 
	HDIB	hDIB;				// 缩放后新DIB句柄	 
	LPSTR	lpDst;				// 指向缩放图像对应象素的指针	 
	LPSTR	lpNewDIB;			// 指向缩放图像的指针 
	LPSTR	lpNewDIBBits;	 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0)	 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针	 
 
	LONG	i;					// 循环变量(象素在新DIB中的坐标) 
	LONG	j;	 
	LONG	i0;					// 象素在源DIB中的坐标 
	LONG	j0; 
	 
	 
	LONG lLineBytes;			// 图像每行的字节数	 
	lpDIBBits = FindDIBBits(lpDIB);	// 找到源DIB图像象素起始位置		 
	lWidth = DIBWidth(lpDIB);	// 获取图像的宽度 
	lLineBytes = WIDTHBYTES(lWidth * 8);	// 计算图像每行的字节数 
	lHeight = DIBHeight(lpDIB);	// 获取图像的高度 
	 
	// 计算缩放后的图像实际宽度 
	// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分 
	lNewWidth = (LONG) (DIBWidth(lpDIB) * fXZoomRatio + 0.5); 
	 
	// 计算新图像每行的字节数 
	lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 
	 
	// 计算缩放后的图像高度 
	lNewHeight = (LONG) (lHeight * fYZoomRatio + 0.5); 
	 
	// 分配内存,以保存新DIB 
	hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +  
		*(LPDWORD)lpDIB + PaletteSize(lpDIB));	 
	if (hDIB == NULL) 
	{ 
		return NULL; 
	} 
	 
	lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB); 
	 
	// 复制DIB信息头和调色板 
	memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
	 
	// 找到新DIB象素起始位置 
	lpNewDIBBits = FindDIBBits(lpNewDIB); 
	lpbmi = (LPBITMAPINFOHEADER)lpNewDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpNewDIB; 
	 
	// 更新DIB中图像的高度和宽度 
	if (IS_WIN30_DIB(lpNewDIB)) 
	{ 
		// 对于Windows 3.0 DIB 
		lpbmi->biWidth = lNewWidth; 
		lpbmi->biHeight = lNewHeight; 
	} 
	else 
	{ 
		// 对于其它格式的DIB 
		lpbmc->bcWidth = (unsigned short) lNewWidth; 
		lpbmc->bcHeight = (unsigned short) lNewHeight; 
	} 
		 
	for(i = 0; i < lNewHeight; i++)		// 针对图像每行进行操作 
	{		 
		for(j = 0; j < lNewWidth; j++)	// 针对图像每列进行操作 
		{			 
			// 指向新DIB第i行,第j个象素的指针 
			// 注意此处宽度和高度是新DIB的宽度和高度 
			lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; 
			 
			// 计算该象素在源DIB中的坐标 
			i0 = (LONG) (i / fYZoomRatio + 0.5); 
			j0 = (LONG) (j / fXZoomRatio + 0.5); 
			 
			// 判断是否在源图范围内 
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
			{				 
				// 指向源DIB第i0行,第j0个象素的指针 
				lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;				 
				// 复制象素 
				*lpDst = *lpSrc; 
			} 
			else 
			{ 
				// 对于源图中没有的象素,直接赋值为255 
				* ((unsigned char*)lpDst) = 255; 
			}			 
		}		 
	} 
	 
	return hDIB; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   RotateDIB() 
 * 参数: 
 *   LPSTR lpDIB		- 指向源DIB的指针 
 *   int iRotateAngle	- 旋转的角度(0-360度) 
 * 返回值: 
 *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。 
 * 说明: 
 *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。 
 * 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插 
 * 值算法进行插值。 
 ************************************************************************/ 
HGLOBAL CDibImage::RotateDIB(LPSTR lpDIB, int iRotateAngle) 
{	 
	LONG	lWidth;				// 源图像的宽度 
	LONG	lHeight;			// 源图像的高度	 
	LONG	lNewWidth;			// 旋转后图像的宽度 
	LONG	lNewHeight;			// 旋转后图像的高度	 
	LONG	lLineBytes;			// 图像每行的字节数	 
	LONG	lNewLineBytes;		// 旋转后图像的宽度(lNewWidth',必须是4的倍数)	 
	LPSTR	lpDIBBits;			// 指向源图像的指针	 
	LPSTR	lpSrc;				// 指向源象素的指针	 
	HDIB	hDIB;				// 旋转后新DIB句柄	 
	LPSTR	lpDst;				// 指向旋转图像对应象素的指针	 
	LPSTR	lpNewDIB;			// 指向旋转图像的指针 
	LPSTR	lpNewDIBBits;	 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0)	 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针 
		 
	LONG	i;					// 循环变量(象素在新DIB中的坐标) 
	LONG	j;	 
	LONG	i0;					// 象素在源DIB中的坐标 
	LONG	j0;	 
	 
	float	fRotateAngle;		// 旋转角度(弧度)	 
	float	fSina, fCosa;		// 旋转角度的正弦和余弦	 
	// 源图四个角的坐标(以图像中心为坐标系原点) 
	float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;	 
	// 旋转后四个角的坐标(以图像中心为坐标系原点) 
	float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4; 
	float	f1,f2; 
		 
	lpDIBBits = FindDIBBits(lpDIB);		// 找到源DIB图像象素起始位置	 
	lWidth = DIBWidth(lpDIB);			// 获取图像的"宽度"(4的倍数)	 
	lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数	 
	lHeight = DIBHeight(lpDIB);			// 获取图像的高度 
	 
	// 将旋转角度从度转换到弧度 
	fRotateAngle = (float) RADIAN(iRotateAngle);	 
	fSina = (float) sin((double)fRotateAngle);	// 计算旋转角度的正弦 
	fCosa = (float) cos((double)fRotateAngle);	// 计算旋转角度的余弦 
	 
	// 计算原图的四个角的坐标(以图像中心为坐标系原点) 
	fSrcX1 = (float) (- (lWidth  - 1) / 2); 
	fSrcY1 = (float) (  (lHeight - 1) / 2); 
	fSrcX2 = (float) (  (lWidth  - 1) / 2); 
	fSrcY2 = (float) (  (lHeight - 1) / 2); 
	fSrcX3 = (float) (- (lWidth  - 1) / 2); 
	fSrcY3 = (float) (- (lHeight - 1) / 2); 
	fSrcX4 = (float) (  (lWidth  - 1) / 2); 
	fSrcY4 = (float) (- (lHeight - 1) / 2); 
	 
	// 计算新图四个角的坐标(以图像中心为坐标系原点) 
	fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1; 
	fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1; 
	fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2; 
	fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2; 
	fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3; 
	fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3; 
	fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4; 
	fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4; 
	 
	// 计算旋转后的图像实际宽度 
	lNewWidth  = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5); 
	 
	// 计算新图像每行的字节数 
	lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 
	 
	// 计算旋转后的图像高度 
	lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5); 
	 
	// 两个常数,这样不用以后每次都计算了 
	f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina 
		+ 0.5 * (lWidth  - 1)); 
	f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa 
		+ 0.5 * (lHeight - 1)); 
	 
	// 分配内存,以保存新DIB 
	hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +  
		*(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
	if (hDIB == NULL) 
	{ 
		return NULL; 
	} 
 
	lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB); 
	 
	// 复制DIB信息头和调色板 
	memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
	 
	// 找到新DIB象素起始位置 
	lpNewDIBBits = FindDIBBits(lpNewDIB); 
	 
	lpbmi = (LPBITMAPINFOHEADER)lpNewDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpNewDIB; 
 
	// 更新DIB中图像的高度和宽度 
	if (IS_WIN30_DIB(lpNewDIB)) 
	{ 
		// 对于Windows 3.0 DIB 
		lpbmi->biWidth = lNewWidth; 
		lpbmi->biHeight = lNewHeight; 
	} 
	else 
	{ 
		// 对于其它格式的DIB 
		lpbmc->bcWidth = (unsigned short) lNewWidth; 
		lpbmc->bcHeight = (unsigned short) lNewHeight; 
	} 
		 
	for(i = 0; i < lNewHeight; i++)		// 针对图像每行进行操作 
	{		 
		for(j = 0; j < lNewWidth; j++)	// 针对图像每列进行操作 
		{ 
			// 指向新DIB第i行,第j个象素的指针 
			// 注意此处宽度和高度是新DIB的宽度和高度 
			lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; 
			 
			// 计算该象素在源DIB中的坐标 
			i0 = (LONG) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5); 
			j0 = (LONG) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5); 
			 
			// 判断是否在源图范围内 
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
			{ 
				// 指向源DIB第i0行,第j0个象素的指针 
				lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0; 
				 
				// 复制象素 
				*lpDst = *lpSrc; 
			} 
			else 
			{ 
				// 对于源图中没有的象素,直接赋值为255 
				* ((unsigned char*)lpDst) = 255; 
			}			 
		}		 
	} 
	 
	return hDIB; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   RotateDIB2() 
 * 参数: 
 *   LPSTR lpDIB		- 指向源DIB的指针 
 *   int iRotateAngle	- 旋转的角度(0-360度) 
 * 返回值: 
 *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。 
 * 说明: 
 *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。 
 * 调用该函数会自动扩大图像以显示所有的象素。函数中采用双线性插 
 * 值算法进行插值。 
 ************************************************************************/ 
HGLOBAL CDibImage::RotateDIB2(LPSTR lpDIB, int iRotateAngle) 
{	 
	LONG	lWidth;				// 源图像的宽度 
	LONG	lHeight;			// 源图像的高度	 
	LONG	lNewWidth;			// 旋转后图像的宽度 
	LONG	lNewHeight;			// 旋转后图像的高度 
	LONG	lNewLineBytes;		// 旋转后图像的宽度(lNewWidth',必须是4的倍数)	 
	LPSTR	lpDIBBits;			// 指向源图像的指针	 
	HDIB	hDIB;				// 旋转后新DIB句柄	 
	LPSTR	lpDst;				// 指向旋转图像对应象素的指针	 
	LPSTR	lpNewDIB;			// 指向旋转图像的指针 
	LPSTR	lpNewDIBBits;	 
	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0)	 
	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针 
		 
	LONG	i;					// 循环变量(象素在新DIB中的坐标) 
	LONG	j;	 
	FLOAT	i0;					// 象素在源DIB中的坐标 
	FLOAT	j0;	 
	 
	float	fRotateAngle;		// 旋转角度(弧度)	 
	float	fSina, fCosa;		// 旋转角度的正弦和余弦	 
	// 源图四个角的坐标(以图像中心为坐标系原点) 
	float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;	 
	// 旋转后四个角的坐标(以图像中心为坐标系原点) 
	float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4; 
	float	f1,f2; 
	 
	 
	lpDIBBits = FindDIBBits(lpDIB);		// 找到源DIB图像象素起始位置	 
	lWidth = DIBWidth(lpDIB);			// 获取图像的宽度 
	lHeight = DIBHeight(lpDIB);			// 获取图像的高度 
	 
	// 将旋转角度从度转换到弧度 
	fRotateAngle = (float) RADIAN(iRotateAngle); 
		 
	fSina = (float) sin((double)fRotateAngle);	// 计算旋转角度的正弦 
	fCosa = (float) cos((double)fRotateAngle);	// 计算旋转角度的余弦 
	 
	// 计算原图的四个角的坐标(以图像中心为坐标系原点) 
	fSrcX1 = (float) (- (lWidth  - 1) / 2); 
	fSrcY1 = (float) (  (lHeight - 1) / 2); 
	fSrcX2 = (float) (  (lWidth  - 1) / 2); 
	fSrcY2 = (float) (  (lHeight - 1) / 2); 
	fSrcX3 = (float) (- (lWidth  - 1) / 2); 
	fSrcY3 = (float) (- (lHeight - 1) / 2); 
	fSrcX4 = (float) (  (lWidth  - 1) / 2); 
	fSrcY4 = (float) (- (lHeight - 1) / 2); 
	 
	// 计算新图四个角的坐标(以图像中心为坐标系原点) 
	fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1; 
	fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1; 
	fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2; 
	fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2; 
	fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3; 
	fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3; 
	fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4; 
	fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4; 
	 
	// 计算旋转后的图像实际宽度 
	lNewWidth  = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5); 
	lNewLineBytes = WIDTHBYTES(lNewWidth * 8); 
	 
	// 计算旋转后的图像高度 
	lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5); 
	 
	f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina 
		+ 0.5 * (lWidth  - 1)); 
	f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa 
		+ 0.5 * (lHeight - 1)); 
	 
	// 分配内存,以保存新DIB 
	hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +  
		*(LPDWORD)lpDIB + PaletteSize(lpDIB));	 
	if (hDIB == NULL) 
	{ 
		return NULL; 
	} 
 
	lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB); 
	 
	// 复制DIB信息头和调色板 
	memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB)); 
	 
	// 找到新DIB象素起始位置 
	lpNewDIBBits = FindDIBBits(lpNewDIB); 
	lpbmi = (LPBITMAPINFOHEADER)lpNewDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpNewDIB; 
 
	// 更新DIB中图像的高度和宽度 
	if (IS_WIN30_DIB(lpNewDIB)) 
	{ 
		// 对于Windows 3.0 DIB 
		lpbmi->biWidth = lNewWidth; 
		lpbmi->biHeight = lNewHeight; 
	} 
	else 
	{ 
		// 对于其它格式的DIB 
		lpbmc->bcWidth = (unsigned short) lNewWidth; 
		lpbmc->bcHeight = (unsigned short) lNewHeight; 
	} 
		 
	for(i = 0; i < lNewHeight; i++)		// 针对图像每行进行操作 
	{			 
		for(j = 0; j < lNewWidth; j++)	// 针对图像每列进行操作 
		{ 
			// 指向新DIB第i行,第j个象素的指针 
			// 注意此处宽度和高度是新DIB的宽度和高度 
			lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; 
			 
			// 计算该象素在源DIB中的坐标 
			i0 = -((float) j) * fSina + ((float) i) * fCosa + f2; 
			j0 =  ((float) j) * fCosa + ((float) i) * fSina + f1; 
			 
			// 利用双线性插值算法来估算象素值 
			*lpDst = Interpolation (lpDIBBits, lWidth, lHeight, j0, i0);			 
		}		 
	} 
	 
	return hDIB; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   Interpolation() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 *   FLOAT x			- 插值元素的x坐标 
 *   FLOAT y		    - 插值元素的y坐标 
 * 返回值: 
 *   unsigned char      - 返回插值计算结果。 
 * 说明: 
 *   该函数利用双线性插值算法来估算象素值。对于超出图像范围的象素, 
 * 直接返回255。 
 ************************************************************************/ 
unsigned char CDibImage::Interpolation (LPSTR lpDIBBits, LONG lWidth,  
										LONG lHeight, FLOAT x, FLOAT y) 
{ 
	// 四个最临近象素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2) 
	LONG	i1, i2; 
	LONG	j1, j2; 
	 
	unsigned char	f1, f2, f3, f4;	// 四个最临近象素值	 
	unsigned char	f12, f34;		// 二个插值中间值	 
 
	// 定义一个值,当象素坐标相差小于改值时认为坐标相同 
	FLOAT			EXP;	 
 
	LONG lLineBytes;				// 图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
	 
	EXP = (FLOAT) 0.0001; 
	 
	// 计算四个最临近象素的坐标 
	i1 = (LONG) x; 
	i2 = i1 + 1; 
	j1 = (LONG) y; 
	j2 = j1 + 1; 
	 
	// 根据不同情况分别处理 
	if( (x < 0) || (x > lWidth - 1) || (y < 0) || (y > lHeight - 1)) 
	{		 
		return 255;		// 要计算的点不在源图范围内,直接返回255。 
	} 
	else 
	{ 
		if (fabs(x - lWidth + 1) <= EXP) 
		{ 
			// 要计算的点在图像右边缘上 
			if (fabs(y - lHeight + 1) <= EXP) 
			{ 
				// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值 
				f1 = *((unsigned char *)lpDIBBits + lLineBytes *  
					(lHeight - 1 - j1) + i1); 
				return f1; 
			} 
			else 
			{ 
				// 在图像右边缘上且不是最后一点,直接一次插值即可 
				f1 = *((unsigned char *)lpDIBBits + lLineBytes *  
					(lHeight - 1 - j1) + i1); 
				f3 = *((unsigned char *)lpDIBBits + lLineBytes *  
					(lHeight - 1 - j1) + i2); 
				 
				// 返回插值结果 
				return ((unsigned char) (f1 + (y -j1) * (f3 - f1))); 
			} 
		} 
		else if (fabs(y - lHeight + 1) <= EXP) 
		{ 
			// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可 
			f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1); 
			f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1); 
			 
			// 返回插值结果 
			return ((unsigned char) (f1 + (x -i1) * (f2 - f1))); 
		} 
		else 
		{ 
			// 计算四个最临近象素值 
			f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1); 
			f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1); 
			f3 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i2); 
			f4 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i2); 
			 
			// 插值1 
			f12 = (unsigned char) (f1 + (x - i1) * (f2 - f1));			 
			// 插值2 
			f34 = (unsigned char) (f3 + (x - i1) * (f4 - f3));			 
			// 插值3 
			return ((unsigned char) (f12 + (y -j1) * (f34 - f12))); 
		} 
	} 
} 
 
////////////////////////////////////////////////////////////////////// 
//  图像正交变换函数 
////////////////////////////////////////////////////////////////////// 
/************************************************************************* 
 * 函数名称: 
 *   FFT() 
 * 参数: 
 *   complex * TD	- 指向时域数组的指针 
 *   complex * FD	- 指向频域数组的指针 
 *   r						-2的幂数,即迭代次数 
 * 返回值: 
 *   无。 
 * 说明: 
 *   该函数用来实现快速付立叶变换。 
 ************************************************************************/ 
VOID CDibImage::FFT(complex * TD, complex * FD, int r) 
{	 
	LONG	count;				// 付立叶变换点数	 
	int		i,j,k;				// 循环变量 
	int		bfsize,p;	 
	double	angle;				// 角度	 
	complex *W,*X1,*X2,*X; 
	 
	count = 1 << r;				// 计算付立叶变换点数 
	 
	// 分配运算所需存储器 
	W  = new complex[count / 2]; 
	X1 = new complex[count]; 
	X2 = new complex[count]; 
	 
	// 计算加权系数 
	for(i = 0; i < count / 2; i++) 
	{ 
		angle = -i * PI * 2 / count; 
		W[i] = complex (cos(angle), sin(angle)); 
	} 
	 
	// 将时域点写入X1 
	memcpy(X1, TD, sizeof(complex) * count); 
	 
	// 采用蝶形算法进行快速付立叶变换 
	for(k = 0; k < r; k++) 
	{ 
		for(j = 0; j < 1 << k; j++) 
		{ 
			bfsize = 1 << (r-k); 
			for(i = 0; i < bfsize / 2; i++) 
			{ 
				p = j * bfsize; 
				X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2]; 
				X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2])  
					* W[i * (1< * FD	- 指向频域值的指针 
 *   complex * TD	- 指向时域值的指针 
 *   r						-2的幂数 
 * 返回值: 
 *   无。 
 * 说明: 
 *   该函数用来实现快速付立叶反变换。 
 ************************************************************************/ 
VOID CDibImage::IFFT(complex * FD, complex * TD, int r) 
{	 
	LONG	count;					// 付立叶变换点数	 
	int		i;						// 循环变量	 
	complex *X;	 
	 
	count = 1 << r;					// 计算付立叶变换点数 
	X = new complex[count];	// 分配运算所需存储器 
	memcpy(X, FD, sizeof(complex) * count);	// 将频域点写入X 
	 
	// 求共轭 
	for(i = 0; i < count; i++) 
	{ 
		X[i] = complex (X[i].real(), -X[i].imag()); 
	} 
	 
	FFT(X, TD, r);					// 调用快速付立叶变换 
	 
	// 求时域点的共轭 
	for(i = 0; i < count; i++) 
	{ 
		TD[i] = complex (TD[i].real() / count, -TD[i].imag() / count); 
	} 
	 
	delete X; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   Fourier() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行付立叶变换。 
 ************************************************************************/ 
BOOL CDibImage::Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{		 
	unsigned char*	lpSrc;	// 指向源图像的指针 
	double	dTemp;	 
	LONG	i;				// 循环变量 
	LONG	j;	 
	LONG	w;				// 进行付立叶变换的宽度(2的整数次方) 
	LONG	h;				// 进行付立叶变换的高度(2的整数次方)	 
	int		wp; 
	int		hp; 
		 
	LONG	lLineBytes;		// 图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	// 计算图像每行的字节数 
	 
	// 赋初值 
	w = 1; 
	h = 1; 
	wp = 0; 
	hp = 0; 
	 
	// 计算进行付立叶变换的宽度和高度(2的整数次方) 
	while(w * 2 <= lWidth) 
	{ 
		w *= 2; 
		wp++; 
	}	 
	while(h * 2 <= lHeight) 
	{ 
		h *= 2; 
		hp++; 
	} 
	 
	complex *TD = new complex[w * h]; 
	complex *FD = new complex[w * h]; 
		 
	for(i = 0; i < h; i++)			// 行 
	{		 
		for(j = 0; j < w; j++)		// 列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 给时域赋值 
			TD[j + w * i] = complex(*(lpSrc), 0); 
		} 
	} 
	 
	for(i = 0; i < h; i++) 
	{ 
		// 对y方向进行快速付立叶变换 
		FFT(&TD[w * i], &FD[w * i], wp); 
	} 
	 
	// 保存变换结果 
	for(i = 0; i < h; i++) 
	{ 
		for(j = 0; j < w; j++) 
		{ 
			TD[i + h * j] = FD[j + w * i]; 
		} 
	} 
	 
	for(i = 0; i < w; i++) 
	{ 
		// 对x方向进行快速付立叶变换 
		FFT(&TD[i * h], &FD[i * h], hp); 
	} 
		 
	for(i = 0; i < h; i++)			// 行 
	{		 
		for(j = 0; j < w; j++)		// 列 
		{ 
			// 计算频谱 
			dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() +  
				         FD[j * h + i].imag() * FD[j * h + i].imag()) / 100; 
			if (dTemp > 255) 
			{ 
				dTemp = 255; 
			} 
			 
			// 指向DIB第(i *X; 
		 
	count = 1<[count*2];	 
	memset(X, 0, sizeof(complex) * count * 2);	// 赋初值为0 
	 
	// 将时域点写入数组X 
	for(i=0;i (f[i], 0); 
	} 
		 
	FFT(X,X,r+1);				// 调用快速付立叶变换		 
	dTemp = 1/sqrt(count);		// 调整系数		 
	F[0] = X[0].real() * dTemp;	// 求F[0]	 
	dTemp *= sqrt(2); 
	 
	// 求F[u]	 
	for(i = 1; i < count; i++) 
	{ 
		F[i]=(X[i].real() * cos(i*PI/(count*2)) + X[i].imag() *  
			sin(i*PI/(count*2))) * dTemp; 
	} 
	 
	delete X; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   IDCT() 
 * 参数: 
 *   double * F				- 指向频域值的指针 
 *   double * f				- 指向时域值的指针 
 *   r						-2的幂数 
 * 返回值: 
 *   无。 
 * 说明: 
 *   该函数用来实现快速离散余弦反变换。该函数也利用2N点的快速付立叶变换 
 * 来实现离散余弦反变换。 
 ************************************************************************/ 
VOID CDibImage::IDCT(double *F, double *f, int r) 
{ 
	LONG	count;			// 离散余弦反变换点数 
	int		i;				// 循环变量 
	double	dTemp, d0;	 
	complex *X; 
		 
	count = 1<[count*2];	 
	memset(X, 0, sizeof(complex) * count * 2);	// 赋初值为0 
	 
	// 将频域变换后点写入数组X 
	for(i=0;i (F[i] * cos(i*PI/(count*2)), F[i] *  
			sin(i*PI/(count*2))); 
	} 
	 
	IFFT(X,X,r+1);		// 调用快速付立叶反变换 
	 
	// 调整系数 
	dTemp = sqrt(2.0/count); 
	d0 = (sqrt(1.0/count) - dTemp) * F[0]; 
	 
	for(i = 0; i < count; i++) 
	{ 
		f[i] = d0 + X[i].real()* dTemp * 2 * count; 
	} 
	 
	delete X; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   DIBDct() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行离散余弦变换。 
 ************************************************************************/ 
BOOL CDibImage::DIBDct(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{		 
	unsigned char*	lpSrc;	// 指向源图像的指针	 
	LONG	i;				// 循环变量 
	LONG	j;	 
	LONG	w;				// 进行付立叶变换的宽度(2的整数次方) 
	LONG	h;				// 进行付立叶变换的高度(2的整数次方) 
	double	dTemp;	 
	int		wp; 
	int		hp; 
		 
	LONG	lLineBytes;		// 图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
	 
	// 赋初值 
	w = 1; 
	h = 1; 
	wp = 0; 
	hp = 0; 
	 
	// 计算进行离散余弦变换的宽度和高度(2的整数次方) 
	while(w * 2 <= lWidth) 
	{ 
		w *= 2; 
		wp++; 
	} 
	 
	while(h * 2 <= lHeight) 
	{ 
		h *= 2; 
		hp++; 
	} 
	 
	double *f = new double[w * h]; 
	double *F = new double[w * h]; 
		 
	for(i = 0; i < h; i++)			// 行 
	{		 
		for(j = 0; j < w; j++)		// 列 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 给时域赋值 
			f[j + i * w] = *(lpSrc); 
		} 
	} 
	 
	for(i = 0; i < h; i++) 
	{ 
		// 对y方向进行离散余弦变换 
		DCT(&f[w * i], &F[w * i], wp); 
	} 
	 
	// 保存计算结果 
	for(i = 0; i < h; i++) 
	{ 
		for(j = 0; j < w; j++) 
		{ 
			f[j * h + i] = F[j + w * i]; 
		} 
	} 
	 
	for(j = 0; j < w; j++) 
	{ 
		// 对x方向进行离散余弦变换 
		DCT(&f[j * h], &F[j * h], hp); 
	}	 
	 
	for(i = 0; i < h; i++)			// 行 
	{		 
		for(j = 0; j < w; j++)		// 列 
		{ 
			dTemp = fabs(F[j*h+i]);	// 计算频谱 
			 
			// 判断是否超过255 
			if (dTemp > 255) 
			{ 
				dTemp = 255; 
			} 
			 
			// 指向DIB第y行,第x个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 更新源图像 
			* (lpSrc) = (BYTE)(dTemp); 
		} 
	} 
	 
	delete f; 
	delete F; 
 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   WALSH() 
 * 参数: 
 *   double * f				- 指向时域值的指针 
 *   double * F				- 指向频域值的指针 
 *   r						-2的幂数 
 * 返回值: 
 *   无。 
 * 说明: 
 *   该函数用来实现快速沃尔什-哈达玛变换。 
 ************************************************************************/ 
VOID CDibImage::WALSH(double *f, double *F, int r) 
{	 
	LONG	count;				// 沃尔什-哈达玛变换点数	 
	int		i,j,k;				// 循环变量 
	int		bfsize,p;	 
	double *X1,*X2,*X; 
		 
	count = 1 << r;				// 计算快速沃尔什变换点数	 
	X1 = new double[count];		// 分配运算所需的数组 
	X2 = new double[count];		// 分配运算所需的数组 
		 
	memcpy(X1, f, sizeof(double) * count);	// 将时域点写入数组X1 
	 
	// 蝶形运算 
	for(k = 0; k < r; k++) 
	{ 
		for(j = 0; j < 1< 255)			 
			{					 
				dTemp = 255;				 
			} 
			 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 更新源图像 
			* (lpSrc) = (BYTE)(dTemp); 
		} 
	} 
	 
	delete f; 
	delete F; 
 
	return TRUE; 
} 
 
/************************************************************************* 
 * 函数名称: 
 *   DIBWalsh1() 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 返回值: 
 *   BOOL               - 成功返回TRUE,否则返回FALSE。 
 * 说明: 
 *   该函数用来对图像进行沃尔什-哈达玛变换。于上面不同的是,此处是将二维 
 * 矩阵转换成一个列向量,然后对该列向量进行一次一维沃尔什-哈达玛变换。 
 ************************************************************************/ 
BOOL CDibImage::DIBWalsh1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) 
{	 
	unsigned char*	lpSrc;		// 指向源图像的指针 
	LONG	i,j;				// 循环变量	 
	LONG	w;					// 进行付立叶变换的宽度(2的整数次方) 
	LONG	h;					// 进行付立叶变换的高度(2的整数次方) 
	double	dTemp;	 
	int		wp; 
	int		hp; 
		 
	LONG	lLineBytes;			// 图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
	 
	// 赋初值 
	w = 1; 
	h = 1; 
	wp = 0; 
	hp = 0; 
	 
	// 计算进行离散余弦变换的宽度和高度(2的整数次方) 
	while(w * 2 <= lWidth) 
	{ 
		w *= 2; 
		wp++; 
	}	 
	while(h * 2 <= lHeight) 
	{ 
		h *= 2; 
		hp++; 
	} 
	 
	double *f = new double[w * h]; 
	double *F = new double[w * h]; 
		 
	for(i = 0; i < w; i++)			// 列 
	{ 
		for(j = 0; j < h; j++)		// 行 
		{ 
			// 指向DIB第j行,第i个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i; 
			 
			// 给时域赋值 
			f[j + i * w] = *(lpSrc); 
		} 
	} 
	 
	// 调用快速沃尔什-哈达玛变换 
	WALSH(f, F, wp + hp); 
		 
	for(i = 0; i < w; i++)			// 列 
	{		 
		for(j = 0; j < h; j++)		// 行 
		{			 
			dTemp = fabs(F[i * w + j] * 1000);	// 计算频谱 
			if (dTemp > 255) 
			{ 
				dTemp = 255; 
			} 
			 
			// 指向DIB第j行,第i个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j) + i; 
			 
			// 更新源图像 
			* (lpSrc) = (BYTE)(dTemp); 
		} 
	} 
	 
	delete f; 
	delete F; 
 
	return TRUE; 
}