www.pudn.com > MotionEstimation.rar > Dib.cpp


// Dib.cpp: implementation of the CDib class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "MotionEstimation.h" 
#include "Dib.h" 
 
#include  
#include   //CSharefile 
#include  
#include  
 
///////////////////////////////////////////////////////////////////////////// 
// CDib 
 
IMPLEMENT_DYNAMIC(CDib, CObject) 
 
CDib::CDib() 
{ 
	m_pBMI = NULL; 
	m_pBits = NULL; 
	m_pPalette = NULL; 
} 
 
CDib::~CDib() 
{ 
	Free(); 
} 
/////////////////////////////////////////////////////////////////// 
// 函数名称:Free() 
// 功能: 确保所有分配空间的成员变量被释放 
/////////////////////////////////////////////////////////////////// 
void CDib::Free() 
{ 
	// Make sure all member data that might have been allocated is freed. 
	if (m_pBits) 
	{ 
		GlobalFreePtr(m_pBits); 
		m_pBits = NULL; 
	} 
	if (m_pBMI) 
	{ 
		GlobalFreePtr(m_pBMI); 
		m_pBMI = NULL; 
	} 
	if (m_pPalette) 
	{ 
		m_pPalette->DeleteObject(); 
		delete m_pPalette; 
		m_pPalette = NULL; 
	} 
} 
 
/************************************************************************* 
 * 
 * Paint() 
 * 
 * Parameters: 
 * 
 * HDC hDC          - DC to do output to 
 * 
 * LPRECT lpDCRect  - rectangle on DC to do output to 
 * 
 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 
 * 
 * CPalette* pPal   - pointer to CPalette containing DIB's palette 
 * 
 * Return Value: 
 * 
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
 * 
 * Description: 
 *   Painting routine for a DIB.  Calls StretchDIBits() or 
 *   SetDIBitsToDevice() to paint the DIB.  The DIB is 
 *   output to the specified DC, at the coordinates given 
 *   in lpDCRect.  The area of the DIB to be output is 
 *   given by lpDIBRect. 
 * 
 ************************************************************************/ 
 
BOOL CDib::Paint(HDC hDC, LPRECT lpDCRect, LPRECT lpDIBRect) const 
{ 
	if (!m_pBMI) 
		return FALSE; 
 
	CRect r1,r2; 
	r1.top=0; 
	r1.left=0; 
	r1.bottom=Height()-1; 
	r1.right=Width()-1; 
	 
	r2.top=0; 
	r2.left=0; 
	r2.bottom=Height()-1; 
	r2.right=Width()-1; 
 
	if(lpDCRect==NULL) lpDCRect=&r1; 
	if(lpDIBRect==NULL) lpDIBRect=&r2; 
	 
	HPALETTE hPal = NULL;           // Our DIB's palette 
	HPALETTE hOldPal = NULL;        // Previous palette 
 
	// Get the DIB's palette, then select it into DC 
	if (m_pPalette != NULL) 
	{ 
		hPal = (HPALETTE) m_pPalette->m_hObject; 
 
		// Select as background since we have 
		// already realized in forground if needed 
		hOldPal = ::SelectPalette(hDC, hPal, TRUE); 
	} 
 
	/* Make sure to use the stretching mode best for color pictures */ 
	::SetStretchBltMode(hDC, COLORONCOLOR); 
 
	/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */ 
	BOOL bSuccess; 
	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)Height() - 
									  lpDIBRect->top - 
									  RECTHEIGHT(lpDIBRect),     // SrcY 
								   0,                          // nStartScan 
								   (WORD)Height(),             // nNumScans 
								   m_pBits,                    // lpBits 
								   m_pBMI,                     // 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 
							   m_pBits,                      // lpBits 
							   m_pBMI,                       // lpBitsInfo 
							   DIB_RGB_COLORS,               // wUsage 
							   SRCCOPY);                     // dwROP 
 
	/* Reselect old palette */ 
	if (hOldPal != NULL) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE); 
	} 
 
   return bSuccess; 
} 
 
/************************************************************************* 
 * 
 * CreatePalette() 
 * 
 * Return Value: 
 * 
 * TRUE if succesfull, FALSE otherwise 
 * 
 * Description: 
 * 
 * This function creates a palette from a DIB by allocating memory for the 
 * logical palette, reading and storing the colors from the DIB's color table 
 * into the logical palette, creating a palette from this logical palette, 
 * and then returning the palette's handle. This allows the DIB to be 
 * displayed using the best possible colors (important for DIBs with 256 or 
 * more colors). 
 * 
 ************************************************************************/ 
 
BOOL CDib::CreatePalette() 
{ 
	if (!m_pBMI) 
		return FALSE; 
 
   //get the number of colors in the DIB 
   WORD wNumColors = NumColors(); 
 
   if (wNumColors != 0) 
   { 
		// allocate memory block for logical palette 
		HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*wNumColors); 
 
		// if not enough memory, clean up and return NULL 
		if (hLogPal == 0) 
			return FALSE; 
 
		LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal); 
 
		// set version and number of palette entries 
		lpPal->palVersion = PALVERSION; 
		lpPal->palNumEntries = (WORD)wNumColors; 
 
		for (int i = 0; i < (int)wNumColors; i++) 
		{ 
			lpPal->palPalEntry[i].peRed = m_pBMI->bmiColors[i].rgbRed; 
			lpPal->palPalEntry[i].peGreen = m_pBMI->bmiColors[i].rgbGreen; 
			lpPal->palPalEntry[i].peBlue = m_pBMI->bmiColors[i].rgbBlue; 
			lpPal->palPalEntry[i].peFlags = 0; 
		} 
 
		/* create the palette and get handle to it */ 
		if (m_pPalette) 
		{ 
			m_pPalette->DeleteObject(); 
			delete m_pPalette; 
		} 
		m_pPalette = new CPalette; 
		BOOL bResult = m_pPalette->CreatePalette(lpPal); 
		::GlobalUnlock((HGLOBAL) hLogPal); 
		::GlobalFree((HGLOBAL) hLogPal); 
		return bResult; 
	} 
 
	return TRUE; 
} 
 
/************************************************************************* 
 * 
 * Width() 
 * 
 * Return Value: 
 * 
 * DWORD            - width of the DIB 
 * 
 * Description: 
 * 
 * This function gets the width of the DIB from the BITMAPINFOHEADER 
 * width field  
 * 
 ************************************************************************/ 
 
DWORD CDib::Width() const 
{ 
	if (!m_pBMI) 
		return 0; 
 
	/* return the DIB width */ 
	return m_pBMI->bmiHeader.biWidth; 
} 
 
 
/************************************************************************* 
 * 
 * Height() 
 * 
 * Return Value: 
 * 
 * DWORD            - height of the DIB 
 * 
 * Description: 
 * 
 * This function gets the height of the DIB from the BITMAPINFOHEADER 
 * height field  
 * 
 ************************************************************************/ 
 
DWORD CDib::Height() const 
{ 
	if (!m_pBMI) 
		return 0; 
	 
	/* return the DIB height */ 
	return m_pBMI->bmiHeader.biHeight; 
} 
 
 
/************************************************************************* 
 * 
 * PaletteSize() 
 * 
 * Return Value: 
 * 
 * WORD             - size of the color palette of the DIB 
 * 
 * Description: 
 * 
 * This function gets the size required to store the DIB's palette by 
 * multiplying the number of colors by the size of an RGBQUAD  
 * 
 ************************************************************************/ 
 
WORD CDib::PaletteSize() const 
{ 
	if (!m_pBMI) 
		return 0; 
 
	return NumColors() * sizeof(RGBQUAD); 
} 
 
 
/************************************************************************* 
 * 
 * NumColors() 
 * 
 * Return Value: 
 * 
 * WORD             - number of colors in the color table 
 * 
 * Description: 
 * 
 * This function calculates the number of colors in the DIB's color table 
 * by finding the bits per pixel for the DIB (whether Win3.0 or other-style 
 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, 
 * if 24, no colors in color table. 
 * 
 ************************************************************************/ 
 
WORD CDib::NumColors() const 
{ 
	if (!m_pBMI) 
		return 0; 
 
	WORD wBitCount;  // DIB bit count 
 
	/*  The number of colors in the color table can be less than  
	 *  the number of bits per pixel allows for (i.e. lpbi->biClrUsed 
	 *  can be set to some value). 
	 *  If this is the case, return the appropriate value. 
	 */ 
 
	DWORD dwClrUsed; 
 
	dwClrUsed = m_pBMI->bmiHeader.biClrUsed; 
	if (dwClrUsed != 0) 
		return (WORD)dwClrUsed; 
 
	/*  Calculate the number of colors in the color table based on 
	 *  the number of bits per pixel for the DIB. 
	 */ 
	wBitCount = m_pBMI->bmiHeader.biBitCount; 
 
	/* return number of colors based on bits per pixel */ 
	switch (wBitCount) 
	{ 
		case 1: 
			return 2; 
 
		case 4: 
			return 16; 
 
		case 8: 
			return 256; 
 
		default: 
			return 0; 
	} 
} 
 
/************************************************************************* 
 * 
 * Save() 
 * 
 * Saves the specified DIB into the specified CFile.  The CFile 
 * is opened and closed by the caller. 
 * 
 * Parameters: 
 * 
 * CFile& file - open CFile used to save DIB 
 * 
 * Return value: Number of saved ints or CFileException 
 * 
 *************************************************************************/ 
DWORD CDib::Save(CFile& file) const 
{ 
	BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
	DWORD dwDIBSize; 
 
	if (m_pBMI == NULL) 
		return 0; 
 
	// Fill in the fields of the file header 
 
	// Fill in file type (first 2 bytes must be "BM" for a bitmap) 
	bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
 
	// Calculating the size of the DIB is a bit tricky (if we want to 
	// do it right).  The easiest way to do this is to call GlobalSize() 
	// on our global handle, but since the size of our global memory may have 
	// been padded a few bytes, we may end up writing out a few too 
	// many bytes to the file (which may cause problems with some apps). 
	// 
	// So, instead let's calculate the size manually (if we can) 
	// 
	// First, find size of header plus size of color table.  Since the 
	// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains 
	// the size of the structure, let's use this. 
	dwDIBSize = *(LPDWORD)&m_pBMI->bmiHeader + PaletteSize();  // Partial Calculation 
 
	// Now calculate the size of the image 
	if ((m_pBMI->bmiHeader.biCompression == BI_RLE8) || (m_pBMI->bmiHeader.biCompression == BI_RLE4)) 
	{ 
		// It's an RLE bitmap, we can't calculate size, so trust the 
		// biSizeImage field 
		dwDIBSize += m_pBMI->bmiHeader.biSizeImage; 
	} 
	else 
	{ 
		DWORD dwBmBitsSize;  // Size of Bitmap Bits only 
 
		// It's not RLE, so size is Width (DWORD aligned) * Height 
		dwBmBitsSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount)) * m_pBMI->bmiHeader.biHeight; 
		dwDIBSize += dwBmBitsSize; 
 
		// Now, since we have calculated the correct size, why don't we 
		// fill in the biSizeImage field (this will fix any .BMP files which 
		// have this field incorrect). 
		m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize; 
	} 
 
	// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	/* 
	 * Now, calculate the offset the actual bitmap bits will be in 
	 * the file -- It's the Bitmap file header plus the DIB header, 
	 * plus the size of the color table. 
	 */ 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pBMI->bmiHeader.biSize + PaletteSize(); 
 
	// Write the file header 
	file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
	DWORD dwBytesSaved = sizeof(BITMAPFILEHEADER);  
 
	// Write the DIB header 
	UINT nCount = sizeof(BITMAPINFO) + (NumColors()-1)*sizeof(RGBQUAD); 
	dwBytesSaved += nCount;  
	file.Write(m_pBMI, nCount); 
	 
	// Write the DIB bits 
	DWORD dwBytes = m_pBMI->bmiHeader.biBitCount * Width(); 
  // Calculate the number of bytes per line 
	if (dwBytes%32 == 0) 
		dwBytes /= 8; 
	else 
		dwBytes = dwBytes/8 + (32-dwBytes%32)/8 + (((32-dwBytes%32)%8 > 0) ? 1 : 0);  
	nCount = dwBytes * Height(); 
	dwBytesSaved += nCount;  
	file.WriteHuge(m_pBits, nCount); 
 
	return dwBytesSaved; 
} 
/************************************************************************* 
 
  Function:  Read (CFile&) 
 
   Purpose:  Reads in the specified DIB file into a global chunk of 
			 memory. 
 
   Returns:  Number of read ints. 
 
*************************************************************************/ 
 
DWORD CDib::Read(CFile& file) 
{ 
	// Ensures no memory leaks will occur 
	Free(); 
	 
	BITMAPFILEHEADER bmfHeader; 
 
	// Go read the DIB file header and check if it's valid. 
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
		return 0; 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
		return 0; 
	DWORD dwReadints = sizeof(bmfHeader); 
 
	// Allocate memory for DIB 
	m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + 256*sizeof(RGBQUAD)); 
	if (m_pBMI == 0) 
		return 0; 
 
	// Read header. 
	if (file.Read(m_pBMI, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)) != (UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER))) 
	{ 
		GlobalFreePtr(m_pBMI); 
		m_pBMI = NULL; 
		return 0; 
	} 
	dwReadints += bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER); 
 
	DWORD dwLength = file.GetLength(); 
	// Go read the bits. 
	m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength - bmfHeader.bfOffBits); 
	if (m_pBits == 0) 
	{ 
		GlobalFreePtr(m_pBMI); 
		m_pBMI = NULL; 
		return 0; 
	} 
	 
	if (file.ReadHuge(m_pBits, dwLength-bmfHeader.bfOffBits) != (dwLength - bmfHeader.bfOffBits)) 
	{ 
		GlobalFreePtr(m_pBMI); 
		m_pBMI = NULL; 
		GlobalFreePtr(m_pBits); 
		m_pBits = NULL; 
		return 0; 
	} 
	dwReadints += dwLength - bmfHeader.bfOffBits; 
 
	CreatePalette(); 
 
	return dwReadints; 
} 
 
#ifdef _DEBUG 
void CDib::Dump(CDumpContext& dc) const 
{ 
	CObject::Dump(dc); 
} 
#endif 
 
////////////////////////////////////////////////////////////////////////// 
//// Clipboard support 
 
//--------------------------------------------------------------------- 
// 
// Function:   CopyToHandle 
// 
// Purpose:    Makes a copy of the DIB to a global memory block.  Returns 
//             a handle to the new memory block (NULL on error). 
// 
// Returns:    Handle to new global memory block. 
// 
//--------------------------------------------------------------------- 
 
HGLOBAL CDib::CopyToHandle() const 
{ 
	CSharedFile file; 
	try 
	{ 
		if (Save(file)==0) 
			return 0; 
	} 
	catch (CFileException* e) 
	{ 
		e->Delete(); 
		return 0; 
	} 
		 
	return file.Detach(); 
} 
 
//--------------------------------------------------------------------- 
// 
// Function:   ReadFromHandle 
// 
// Purpose:    Initializes from the given global memory block.   
//             and free the memory. 
// Returns:    Number of read ints. 
// 
//--------------------------------------------------------------------- 
 
DWORD CDib::ReadFromHandle(HGLOBAL hGlobal) 
{ 
	CSharedFile file; 
	file.SetHandle(hGlobal, FALSE); 
	DWORD dwResult = Read(file); 
	GlobalFree(file.Detach()); 
	return dwResult; 
} 
 
////////////////////////////////////////////////////////////////////////// 
//// Serialization support 
 
void CDib::Serialize(CArchive& ar)  
{ 
	CFile* pFile = ar.GetFile(); 
	ASSERT(pFile != NULL); 
	if (ar.IsStoring()) 
	{	// storing code 
		Save(*pFile); 
	} 
	else 
	{	// loading code 
		Read(*pFile); 
	} 
} 
//--------------------------------------------------------------------- 
// 
// Function:   IsGray() 
// 
// Purpose:    判断是否为灰度图象 
// 
// Returns:     
//   BOOL     -若是灰度图象,则返回TRUE; 否则返回FALSE. 
// 
//--------------------------------------------------------------------- 
BOOL CDib::IsGray() 
{ 
	if(m_pBMI->bmiHeader.biBitCount!=8)	return FALSE; 
	for( int i=0;i<256;i++) 
	{ 
		if(m_pBMI->bmiColors[i].rgbBlue!=i) return FALSE; 
		if(m_pBMI->bmiColors[i].rgbGreen!=i) return FALSE; 
		if(m_pBMI->bmiColors[i].rgbRed!=i) return FALSE; 
	} 
	return TRUE; 
} 
 
//--------------------------------------------------------------------- 
// 
// Function:   GetXY8() 
// 
// Purpose:    获取灰度图象中点(x,y)的灰度值 
// 
// Returns:     
//   int       -返回像素点(x,y)的灰度值. 
// 
//--------------------------------------------------------------------- 
int CDib::GetXY8(int x, int y) 
{ 
#ifdef _DEBUG 
	//Cause a point on the right or bottom side is outside CRect. 
	CRect rc(0,0, Width(),Height()); 
	ASSERT(rc.PtInRect(CPoint(x,y))); 
	ASSERT(m_pBMI->bmiHeader.biBitCount==8); 
#endif //_DEBUG 
	// call this function only when biBitCount==8 
	int TrueWidth; 
	TrueWidth=(Width()+3)/4*4; 
	y=Height()-1-y; 
	return m_pBits[y*TrueWidth+x]; 
} 
 
//--------------------------------------------------------------------- 
// 
// Function:   SetXY8() 
// 
// Purpose:    将灰度图象中点(x,y)的值赋为val 
// 
//--------------------------------------------------------------------- 
void CDib::SetXY8(int x, int y, int val) 
{ 
#ifdef _DEBUG 
	//Cause a point on the right or bottom side is outside CRect. 
	CRect rc(0,0, Width(),Height()); 
	ASSERT(rc.PtInRect(CPoint(x,y))); 
	ASSERT(m_pBMI->bmiHeader.biBitCount==8); 
#endif //_DEBUG 
	// call this function only when biBitCount==8 
	int TrueWidth; 
	TrueWidth=(Width()+3)/4*4; 
	y=Height()-1-y; 
	m_pBits[y*TrueWidth+x]=val; 
} 
/************************************************************************* 
 * 
 * ToGray() 
 * 
 * Description: 
 *   将彩色图象转换为256色灰度图 
 * 
 ************************************************************************/ 
void CDib::ToGray() 
{ 
	CSize m_size(Width(),Height()); 
	int m_TrueWidth=(Width()+3)/4*4; 
	 
	for(int i=0;i<256;i++) 
	{ 
		m_pBMI->bmiColors[i].rgbReserved=(int)((float)m_pBMI->bmiColors[i].rgbRed*0.3+\ 
			(float)m_pBMI->bmiColors[i].rgbGreen*0.59+\ 
			(float)m_pBMI->bmiColors[i].rgbBlue*0.11+0.5); 
	} 
 
	for(i=0; i<(int)m_TrueWidth*m_size.cy ; i++) 
	{ 
		m_pBits[i]=m_pBMI->bmiColors[m_pBits[i]].rgbReserved; 
	} 
	for(i=0;i<256;i++) 
	{ 
		m_pBMI->bmiColors[i].rgbBlue=i; 
		m_pBMI->bmiColors[i].rgbGreen=i; 
		m_pBMI->bmiColors[i].rgbRed=i; 
		m_pBMI->bmiColors[i].rgbReserved=0; 
	} 
} 
 
CDib& CDib::operator =(CDib &dib) 
{ 
	if(IsValid()) Free(); 
 
	int iSize; 
	iSize=GlobalSize(GlobalHandle(dib.m_pBMI)); 
	m_pBMI=(LPBITMAPINFO)GlobalAllocPtr(GHND, iSize); 
	CopyMemory((LPBYTE)m_pBMI,(LPBYTE)dib.m_pBMI,iSize); 
 
	iSize=GlobalSize(GlobalHandle(dib.m_pBits)); 
	m_pBits=(LPBYTE)GlobalAllocPtr(GHND, iSize); 
	CopyMemory(m_pBits,dib.m_pBits,iSize); 
 
	CreatePalette(); 
 
	return *this; 
} 
 
 
 
void CDib::Copy(CDib &dib) 
{ 
	if(IsValid()) Free(); 
 
	int iSize; 
	iSize=GlobalSize(GlobalHandle(dib.m_pBMI)); 
	m_pBMI=(LPBITMAPINFO)GlobalAllocPtr(GHND, iSize); 
	CopyMemory((LPBYTE)m_pBMI,(LPBYTE)dib.m_pBMI,iSize); 
 
	iSize=GlobalSize(GlobalHandle(dib.m_pBits)); 
	m_pBits=(LPBYTE)GlobalAllocPtr(GHND, iSize); 
	CopyMemory(m_pBits,dib.m_pBits,iSize); 
 
	CreatePalette(); 
} 
		 
void CDib::ConvertToRGB() 
{ 
	if(!IsValid()) return; 
	if(m_pBMI->bmiHeader.biBitCount==24) return; 
	ASSERT(m_pBMI->bmiHeader.biBitCount==8); 
	 
	LPBYTE pBits; 
	LPBITMAPINFO pBMI; 
	int iWidth; 
	int i,j; 
	//prepare bitmapinfoheader for true color bitmap 
	pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, sizeof(BITMAPINFOHEADER)); 
	CopyMemory((PVOID)pBMI, (PVOID)m_pBMI,sizeof(BITMAPINFOHEADER)); 
	pBMI->bmiHeader.biBitCount=24; 
	pBMI->bmiHeader.biClrUsed=0; 
	pBMI->bmiHeader.biSizeImage=0; 
 
	iWidth=((pBMI->bmiHeader.biWidth*3+3)/4*4); 
	 
	// prepare memory for bits	 
	pBits= (LPBYTE)GlobalAllocPtr(GHND, iWidth*pBMI->bmiHeader.biHeight); 
 
	for(i=0;ibmiHeader.biHeight;i++) 
	{ 
		LPBYTE lpSource; 
		LPBYTE lpDest; 
		 
		lpDest=pBits+(pBMI->bmiHeader.biHeight-1-i)*((pBMI->bmiHeader.biWidth*3+3)/4*4); 
		lpSource=m_pBits+(pBMI->bmiHeader.biHeight-1-i)*((pBMI->bmiHeader.biWidth+3)/4*4); 
 
		for(j=0;jbmiHeader.biWidth;j++) 
		{ 
			lpDest[3*j+2]=m_pBMI->bmiColors[lpSource[j]].rgbRed; 
			lpDest[3*j+1]=m_pBMI->bmiColors[lpSource[j]].rgbGreen; 
			lpDest[3*j]=m_pBMI->bmiColors[lpSource[j]].rgbBlue; 
			 
		} 
	} 
	Free(); 
	m_pBMI=pBMI; 
	m_pBits=pBits; 
	CreatePalette(); 
} 
 
/************************************************************************* 
 * 
 * Read() 
 * 
 * Parameters: 
 * 
 * CString filename - 要读取的文件路径名 
 * 
 * Return Value: 
 * 
 * DWORD            - 读取的整数的个数 
 * 
 * Description: 
 *   将DIB文件读到内存中 
 * 
 ************************************************************************/ 
DWORD CDib::Read(CString filename) 
{ 
	CFile file; 
	CFileException fe; 
	DWORD dwSize; 
	if (!file.Open(filename, CFile::modeRead | CFile::shareDenyWrite, &fe)) 
	{ 
		//ReportSaveLoadException(lpszPathName, &fe, FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); 
		AfxMessageBox("read error!"); 
		return 0; 
	} 
	dwSize=Read(file); 
	file.Close(); 
	return dwSize; 
		 
} 
 
DWORD CDib::Save(LPCSTR filename) 
{ 
	CFile file; 
	CFileException fe; 
	DWORD dwSize; 
	if (!file.Open(filename, CFile::modeCreate |CFile::modeWrite | CFile::shareDenyWrite, &fe)) 
	{ 
		//ReportSaveLoadException(lpszPathName, &fe, FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); 
		AfxMessageBox("save error!"); 
		return 0; 
	} 
	dwSize=Save(file); 
	file.Close(); 
	return dwSize; 
} 
 
 
/************************************************************************* 
 * 
 * GetXYR() 
 * 
 * Parameters: 
 * 
 * int x          - 像素点的横坐标 
 * 
 * int y          - 像素点的纵坐标 
 * 
 * Return Value: 
 * 
 * int            - 像素点的R分量值 
 * 
 * Description: 
 *    获取坐标点为(x,y)的像素点的R分量值 
 ************************************************************************/ 
int CDib::GetXYR(int x, int y) 
{ 
    int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	return m_pBits[y*TrueWidth+x*3+2]; 
} 
/************************************************************************* 
* Description: 
*    获取坐标点为(x,y)的像素点的G分量值 
************************************************************************/ 
int CDib::GetXYG(int x, int y) 
{ 
    int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	return m_pBits[y*TrueWidth+x*3+1]; 
} 
/************************************************************************* 
* Description: 
*    获取坐标点为(x,y)的像素点的B分量值 
************************************************************************/ 
int CDib::GetXYB(int x, int y) 
{ 
    int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	return m_pBits[y*TrueWidth+x*3]; 
} 
/************************************************************************* 
* Description: 
*    将坐标点为(x,y)的像素点的R分量值置为val的值 
************************************************************************/ 
void CDib::SetXYR(int x, int y, int val) 
{ 
	int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	m_pBits[y*TrueWidth+x*3+2]=val; 
} 
void CDib::SetXYG(int x, int y, int val) 
{ 
	int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	m_pBits[y*TrueWidth+x*3+1]=val; 
} 
void CDib::SetXYB(int x, int y, int val) 
{ 
	int TrueWidth; 
	TrueWidth=(Width()*3+3)/4*4; 
	y=Height()-1-y; 
	m_pBits[y*TrueWidth+x*3]=val; 
} 
/************************************************************************* 
* Description: 
*    根据R、G、B分量的值计算出亮度分量Y的值 
************************************************************************/ 
float CDib::RGB_Y(int R, int G, int B) 
{ 
	return (float)(0.299*R+0.587*G+0.114*B); 
 
} 
//根据R、G、B分量的值计算出色差分量U的值 
float CDib::RGB_U(int R, int G, int B) 
{ 
	return (float)(-0.16875*R-0.33126*G+0.5*B); 
 
} 
float CDib::RGB_V(int R, int G, int B) 
{ 
	return (float)(0.5*R-0.41869*G-0.08131*B); 
 
} 
//由Y、U、V的值计算得到R、G、B的值 
int CDib::YUV_R(float Y, float U, float V) 
{ 
	int b=(int)(Y+1.402*(V)); 
	if (b > 255) 
	{ 
		b=255; 
	} 
	else if (b < 0) 
	{ 
		b=0; 
	} 
	return (int)(b); 
 
} 
int CDib::YUV_G(float Y, float U, float V) 
{ 
    int b=(int)(Y-0.34413*(U)-0.71414*(V)); 
	if (b > 255) 
	{ 
		b=255; 
	} 
		else if (b < 0) 
	{ 
		b=0; 
	} 
 	return (int)(b); 
 
} 
int CDib::YUV_B(float Y, float U, float V) 
{ 
	int b=(int)(Y+1.772*(U)); 
	if (b > 255) 
	{ 
		b=255; 
	} 
		else if (b < 0) 
	{ 
		b=0; 
	} 
 	return (int)(b); 
 
 
} 
 
//DEL void CDib::RGB_GRAY() 
//DEL { 
//DEL  
//DEL 	if( m_pBMI== NULL || m_pBits == NULL || m_pBMI->bmiHeader.biBitCount!=24) 
//DEL 		return; 
//DEL  
//DEL 	DWORD bmWidthints = (m_pBmih->biWidth * m_pBmih->biBitCount + 31) / 32*4; 
//DEL 	int i,j; 
//DEL 	int r,b,g; 
//DEL 	LPint pint = m_pBits; 
//DEL 	 
//DEL  
//DEL 	ASSERT(pint != NULL); 
//DEL 	memcpy( pint, m_pBits,m_dwSizeImage); 
//DEL 	if( m_hBitmap ) 
//DEL 		::DeleteObject(m_hBitmap); 
//DEL 	m_hBitmap = hBitmap; 
//DEL 	if( m_pBits && !m_bNoDelBits ) 
//DEL 		delete[] m_pBits; 
//DEL 	m_pBits = pint; 
//DEL 	m_bNoDelBits = 1; 
//DEL 	m_bGray = 1; 
//DEL  
//DEL } 
//将真彩色图象转换为YUV表示法,即获取坐标为(x,y)的像素点 
//的Y、U、V分量的值 
int CDib::GETXY_Y(int x,int y) 
{ 
  return((int)RGB_Y(GetXYR(x,y),GetXYG(x,y),GetXYB(x,y))); 
} 
int CDib::GETXY_U(int x,int y) 
{ 
  return((int)RGB_U(GetXYR(x,y),GetXYG(x,y),GetXYB(x,y))); 
} 
int CDib::GETXY_V(int x,int y) 
{ 
  return((int)RGB_V(GetXYR(x,y),GetXYG(x,y),GetXYB(x,y))); 
}