www.pudn.com > dip_1_1_bmp2jpeg.rar > Image.cpp


/***************************************************************/ 
/*文件名:     image.cpp               				           */ 
/*文件描述:                                                   */ 
/*相关文件:   image.h	               */ 
/*主要函数:   read and write and Displan                                                */ 
/*提交日期:                        作  者:王瑞   张洪明      */ 
/*编 辑 器: Visual C++                                        */ 
/*版权:    先进人及通信联合实验室                             */ 
/*版权说明:任何使用必须保留版权信息和历史纪录信息			   */ 
/*修改纪录:												   */ 
/*日  期        版本        修改人         修改内容            */ 
/***************************************************************/ 
 
#include "stdafx.h" 
#include "math.h" 
#include   // for GlobalAllocPtr 
#include "image.h" 
 
IMPLEMENT_SERIAL(CImage, CObject, 0) 
 
/////////////////////////////////////////////////////////////////// 
CImage::CImage(): m_bIsDIB(TRUE),m_dwLength(0L), 
				  m_pDib (NULL),m_pData(NULL) 
{ 
	m_pPal	=new CPalette; 
} 
     
/////////////////////////////////////////////////////////////////// 
CImage::CImage(const CImage& img)//copy constructor 
{ 
	m_bIsDIB=img.m_bIsDIB; 
	m_dwLength=img.m_dwLength; 
	m_pDib=0; 
	if(img.m_pDib){ 
		m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength); 
		if(!m_pDib) 
		{ 
	        AfxMessageBox("Unable to allocate DIB memory"); 
			return; 
		} 
		memcpy(m_pDib,img.m_pDib,m_dwLength); 
	    m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * img.NumColors(); 
	} 
	m_pPal=new CPalette; 
	CreateDIBPalette(); 
} 
/////////////////////////////////////////////////////////////////// 
CImage::CImage(CImage& img,	CPoint start,	CSize size) 
{ 
	int		bpp; 
	int		bytepp; 
	long	hdlen;/*size of the DIB header info*/ 
	LPBITMAPINFOHEADER pBMIH; 
 
	ASSERT(img.m_pDib); 
	WORD dww=img.Width(); 
	WORD dwh=img.Height(); 
	if(( (size.cx+start.x)>dww )||( (size.cy+start.y)>dwh )) 
	{		 
		CRect rect1 = CRect(CPoint(0,0),CSize(dww-1,dwh-1)); 
		CRect rect = CRect(start,size); 
		rect &= rect1; 
		 
		start.x = rect.left; 
		start.y = rect.top; 
		 
		size.cx = rect.right  - rect.left; 
		size.cy = rect.bottom - rect.top; 
 
   
	} 
	img.Data(); 
	 
	m_bIsDIB = FALSE; 
    hdlen = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * img.NumColors(); 
 
	bpp		= img.Bits(); 
	bytepp	= bpp / 8; 
 
	ASSERT(bpp != 16 && bpp != 32); 
 
    DWORD bypeinoneline = ByteNumForOneLine((WORD)size.cx, bpp);//Bytes per line 
	 
    m_dwLength = hdlen + bypeinoneline * size.cy; 
 
    if (!AllocateMemory( )){ 
		return; 
	} 
	memcpy(m_pDib, img.m_pDib, hdlen); 
 
    pBMIH = BMInfoHdPtr(); 
    pBMIH->biWidth = size.cx; 
    pBMIH->biHeight = size.cy; 
    pBMIH->biSizeImage = size.cx * size.cy * bytepp; 
 
    m_pData =  (BYTE*)(m_pDib + hdlen); 
 
	BYTE* p1, *p2; 
	long  t1, t2; 
	t1 = dww * bytepp; 
	t2 = size.cx * bytepp; 
	p1 = ( BYTE* ) ( img.m_pData + (start.y * dww + start.x) * bytepp); 
	p2 = m_pData; 
	for(int i=0 ; i<(int)size.cy; i++) 
	{ 
		memcpy(p2 , p1 , t2); 
		p1 += t1; 
		p2 += t2; 
	} 
 
	Dib();	 
	img.Dib(); 
	m_pPal=new CPalette; 
	CreateDIBPalette(); 
} 
/////////////////////////////////////////////// 
/*the constructor used to create a DIB of size 'size' 
 with no initializing image data*/ 
CImage::CImage(CSize size,int NumColor,int Bits) 
{ 
    LPBITMAPINFOHEADER pBMIH; 
    m_dwLength = sizeof(BITMAPINFOHEADER) +  
					sizeof(RGBQUAD) * NumColor; 
    if (!AllocateMemory()) return; 
	DWORD dwBytes = Transform((WORD)size.cx); 
 
    m_dwLength += dwBytes * size.cy * Bits / 8; 
    if (!AllocateMemory(TRUE)){ 
		return; 
	} 
    pBMIH=BMInfoHdPtr(); 
	pBMIH->biSize = sizeof(BITMAPINFOHEADER); 
    pBMIH->biWidth = size.cx; 
    pBMIH->biHeight = size.cy; 
    pBMIH->biSizeImage = size.cx*size.cy; 
    pBMIH->biPlanes = 1; 
    pBMIH->biBitCount = Bits; // 1, 4, 8, or 24 
    pBMIH->biCompression = BI_RGB; 
    pBMIH->biXPelsPerMeter = 0; 
    pBMIH->biYPelsPerMeter = 0; 
    pBMIH->biClrUsed = 0; 
    pBMIH->biClrImportant = 0; 
    m_pData =  (BYTE*)(m_pDib + sizeof(BITMAPINFOHEADER) + 
              sizeof(RGBQUAD) * NumColor); 
	SetDIB(); 
	m_pPal=new CPalette; 
	CreateGreyPalette(); 
} 
/////////////////////////////////////////////////////////////////// 
	//part copy constructor 
CImage& CImage::operator=(const CImage& img) 
{ 
	m_bIsDIB=img.m_bIsDIB; 
	m_dwLength=img.m_dwLength; 
	if(img.m_pDib){ 
		TRY	{ 
			if(m_pDib){ 
			m_pDib = (BYTE*) GlobalReAllocPtr(m_pDib, 
                                            m_dwLength, GHND); 
			}else 
			{ 
				m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength); 
			} 
		} 
		CATCH (CMemoryException, e) { 
	        AfxMessageBox("Unable to allocate DIB memory"); 
			return *this; 
		} 
		END_CATCH 
 
		memcpy(m_pDib,img.m_pDib,m_dwLength); 
	    m_pData = (BYTE*)((BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * img.NumColors()); 
	}else 
	{ 
		GlobalFree(m_pDib); 
		m_pDib=0; 
	} 
	if(m_pPal) delete m_pPal; 
	m_pPal=new CPalette; 
	CreateDIBPalette(); 
	return *this; 
} 
/////////////////////////////////////////////////////////////////// 
CImage::~CImage() 
{ 
    if(m_dwLength != 0L)  
        GlobalFreePtr(m_pDib);  // free the DIB memory 
    if(m_pPal) 
		delete m_pPal; 
} 
 
/////////////////////////////////////////////////////////////////// 
void CImage::Serialize(CArchive& ar) 
{ 
    ar.Flush(); 
    if (ar.IsStoring())  
	{ 
		WriteToFile(ar.GetFile()); 
    } 
    else  
	{ 
		ReadFromFile(ar.GetFile()); 
    } 
} 
 
/////////////////////////////////////////////////////////////////// 
BOOL CImage::WriteAsBMP(CFile* pFile) 
{ 
    Dib(); 
	BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
	LPBITMAPINFOHEADER pBMIH=BMInfoHdPtr();   // Pointer to DIB info structure 
 
	if (m_pDib == NULL) 
		return FALSE; 
 
	/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ 
	bmfHdr.bfType = 0x4d42;  // "BM" 
 
	// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
 
	bmfHdr.bfSize = m_dwLength + sizeof(BITMAPFILEHEADER); 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + pBMIH->biSize 
											  + NumColors()*sizeof(RGBQUAD); 
	WORD hdLength=sizeof(BITMAPINFOHEADER) 
					+ NumColors()*sizeof(RGBQUAD); 
	TRY { 
		// Write the file header 
		pFile->Write((BYTE*)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
		// Write the DIB header 
        pFile->Write(m_pDib, hdLength); 
		// Write the DIB bits 
        pFile->Write(m_pData, m_dwLength-hdLength); 
    } 
    CATCH (CFileException, e) { 
        AfxMessageBox("Write error--possible disk full condition"); 
        return FALSE; 
    } 
    END_CATCH 
    return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////// 
/* The MakeBitmap() 
   CDC* pDoc :    Device Context 
   bmSize    :    Change the parameter and return it 
   Function:      Replaces the DC's old existing bitmap  
                  with the new one construced from this DIB 
   Return Value:  the old bitmap in DC 
*/ 
////////////////////////////////////////////////////////     
CBitmap* CImage::MakeBitmap(CDC* pDC, CSize& bmSize) 
{ 
    BITMAP bm; 
    DWORD  dwFore, dwBack; 
	LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); 
	LPBITMAPINFO pBMI = BMInfoPtr(); 
    // checks to see whether DIB buffer is properly loaded 
    if (m_dwLength == 0L) { 
        bmSize.cx = bmSize.cy = 0; 
        return NULL; 
    } 
 
    // this code conditions the DC for mono or color 
	SetPalette(pDC); 
    int nPlanes = pDC->GetDeviceCaps(PLANES); 
    int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL); 
    CBitmap* pConfigBitmap = new CBitmap; 
    char bits[100]; 
    if (pBMIH->biBitCount == 1) { 
        pConfigBitmap->CreateBitmap(1, 1, 1, 1, bits); 
    } 
    else { 
        pConfigBitmap->CreateBitmap(1, 1, nPlanes, nBitsPixel, bits); 
    } 
    CBitmap* pOriginalBitmap = 
        (CBitmap*) pDC->SelectObject(pConfigBitmap); 
 
// CreateDIBitmap "switches bits" for mono bitmaps, depending on colors, 
//  so we'll fool it 
    if (GetMonoColors(dwFore, dwBack)) { 
        SetMonoColors(0L, 0xFFFFFFL); 
    } 
//the following CreateDIBitmap() creates a DDB from this DIB     
//#ifdef _WIN32 
    HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH, 
            CBM_INIT, (CONST BYTE*) m_pData, pBMI, DIB_RGB_COLORS); 
//#else 
//    HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH, 
//            CBM_INIT, (BYTE*) m_pData, pBMI, DIB_RGB_COLORS); 
//#endif 
    if (hBitmap == NULL) { 
        TRACE("null bitmap\n");   
        delete pDC->SelectObject(pOriginalBitmap); // delete config bitmap 
        return NULL; // untested error logic 
    } 
     
    SetMonoColors(dwFore, dwBack); 
     
    // Can't use CBitmap::FromHandle here because we need to 
    //  delete the object later 
    CBitmap* pBitmap = new CBitmap; 
    pBitmap->Attach(hBitmap); 
    pBitmap->GetObject(sizeof(bm), &bm); 
    bmSize.cx = bm.bmWidth; 
    bmSize.cy = bm.bmHeight; 
    delete pDC->SelectObject(pBitmap); // delete configuration bitmap 
    return pOriginalBitmap; 
} 
/////////////////////////////////////////////////////////////////// 
//create a DIBpalette according to the palette info in the inforhead of object 
BOOL CImage::CreateDIBPalette() 
{ 
	LPLOGPALETTE lpPal;      // pointer to a logical palette 
	LPBITMAPINFO pBMI = BMInfoPtr(); 
	int i;                   // loop index 
	WORD wNumColors;         // number of colors in color table 
	BOOL bResult=FALSE; 
 
	/* if handle to DIB is invalid, return FALSE */ 
 
	if (!m_pDib)  return FALSE; 
 
   /* get the number of colors in the DIB */ 
	Dib(); 
	wNumColors = NumColors(); 
	if (wNumColors != 0) 
	{ 
		/* allocate memory block for logical palette */ 
		/* if not enough memory, clean up and return NULL */ 
 
		lpPal = (LPLOGPALETTE) GlobalAllocPtr(GHND, sizeof(LOGPALETTE) 
									+ sizeof(PALETTEENTRY) 
									* wNumColors); 
		if (lpPal == 0) return FALSE; 
 
		/* set version and number of palette entries */ 
		lpPal->palVersion = 0x300; 
		lpPal->palNumEntries = wNumColors; 
 
		for (i = 0; i < (int)wNumColors; i++) 
		{ 
			lpPal->palPalEntry[i].peRed = pBMI->bmiColors[i].rgbRed; 
			lpPal->palPalEntry[i].peGreen = pBMI->bmiColors[i].rgbGreen; 
			lpPal->palPalEntry[i].peBlue = pBMI->bmiColors[i].rgbBlue; 
			lpPal->palPalEntry[i].peFlags = 0; 
		} 
 
		/* create the palette and get handle to it */ 
		if(m_pPal)delete m_pPal; 
		m_pPal=new CPalette; 
		bResult = m_pPal->CreatePalette(lpPal); 
		GlobalFreePtr(lpPal); 
	} 
 
	return bResult; 
} 
BOOL CImage::GetColorImage(BYTE* pData,DWORD dwWidth,DWORD dwHeight) 
{ 
 
	ImageClear(); 
	LPBITMAPINFOHEADER pBMIH; 
 
	//make the number of bytes in one line can be divided exactly by 4 
    DWORD dwBytes = Transform(dwWidth);//bytes per line 
 
	DWORD dwDataLength = dwBytes*dwHeight*3; 
	m_dwLength =dwDataLength+sizeof(BITMAPINFOHEADER) 
				+sizeof(RGBQUAD) * 0; 
 
 
    if (!AllocateMemory()) { 
        return FALSE;        
    } 
    pBMIH=BMInfoHdPtr(); 
	pBMIH->biSize = sizeof(BITMAPINFOHEADER); 
    pBMIH->biWidth = dwWidth; 
    pBMIH->biHeight = dwHeight; 
    pBMIH->biPlanes = 1; 
    pBMIH->biBitCount = 24; 
    pBMIH->biCompression = BI_RGB; 
    pBMIH->biSizeImage = 0; 
    pBMIH->biXPelsPerMeter = 0; 
    pBMIH->biYPelsPerMeter = 0; 
    pBMIH->biClrUsed = 0; 
    pBMIH->biClrImportant = 0; 
   	m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * NumColors(); 
	CreateGreyPalette(); 
 
    TRY { 
		memcpy(m_pData,pData,dwDataLength); 
	} 
	CATCH (CFileException, e) { 
        AfxMessageBox("Data transfer error!"); 
        GlobalFreePtr(m_pDib); // free the DIB memory 
        return FALSE; 
	} 
	END_CATCH 
 
	SetDIB(FALSE); 
	Dib();					 
    return TRUE; 
} 
/////////////////////////////////////////////////////////////////// 
BOOL CImage::CreateGreyPalette() 
{ 
	LPLOGPALETTE lpPal;      // pointer to a logical palette 
	LPBITMAPINFO pBMI = BMInfoPtr(); 
	HANDLE hLogPal;          // handle to a logical palette 
	int i;                   // loop index 
	WORD wNumColors=NumColors();         // number of colors in color table 
	BOOL bResult=FALSE; 
	/* allocate memory block for logical palette */ 
	hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
								+ sizeof(PALETTEENTRY) 
								* wNumColors); 
 
	/* if not enough memory, clean up and return NULL */ 
	if (hLogPal == 0) return FALSE; 
	lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); 
 
	/* set version and number of palette entries */ 
	lpPal->palVersion = 0x300; 
	lpPal->palNumEntries = wNumColors; 
	//set the grey value of palette   
	for (i = 0; i < (int)wNumColors; i++) 
	{ 
		lpPal->palPalEntry[i].peRed = i; 
		lpPal->palPalEntry[i].peGreen = i; 
		lpPal->palPalEntry[i].peBlue = i; 
		lpPal->palPalEntry[i].peFlags = 0; 
		pBMI->bmiColors[i].rgbRed=i; 
		pBMI->bmiColors[i].rgbGreen=i; 
		pBMI->bmiColors[i].rgbBlue=i; 
	} 
 
		/* create the palette and get handle to it */ 
	if(m_pPal)delete m_pPal; 
	m_pPal=new CPalette; 
	bResult = m_pPal->CreatePalette(lpPal); 
	::GlobalUnlock((HGLOBAL) hLogPal); 
	::GlobalFree((HGLOBAL) hLogPal); 
	return bResult; 
} 
/////////////////////////////////////////////////////////////////// 
//create a grey DIB  according to the color bmp  
//and creat a grey palette according to the  
//inforhead of  the color bmp 
BOOL CImage::CreateGreyDib() 
{ 
	BYTE	y[256]; 
	WORD	i, j, w, h;  
	DWORD	dwL; 
	BOOL	bResult = FALSE; 
	LPBITMAPINFO pBMI; 
 
	if ( !m_pDib )  		return FALSE; 
 
	w		= Width(); 
	h		= Height(); 
	dwL		= w * h; 
	pBMI	= BMInfoPtr(); 
 
	switch(Bits()) 
	{ 
	case 8: 
		{ 
			Data(); 
			for (i = 0; i < NumColors() ; i++) 
			{ 
				y[i] = (BYTE)( float( pBMI->bmiColors[i] . rgbRed)  * 0.3 
							 + float( pBMI->bmiColors[i] . rgbGreen)* 0.59 
							 + float( pBMI->bmiColors[i] . rgbBlue) * 0.11); 
				if(y[i] > 255)  
					y[i] = 255; 
			} 
			CreateGreyPalette(); 
			for(DWORD d=0 ; d Data(); 
 
			for(i=0; iGetSafeHdc(), origin.x, origin.y, 
       (WORD) pBMIH->biWidth, (WORD) pBMIH->biHeight, 0, 0, 0, 
       (WORD) pBMIH->biHeight, m_pData, pBMI, 
       DIB_RGB_COLORS)) { 
        return FALSE; 
    } 
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////// 
BOOL CImage::Stretch(CDC* pDC, CPoint origin, CSize size) const 
{ 
    // direct to device--bypass the GDI bitmap 
	LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); 
	LPBITMAPINFO pBMI = BMInfoPtr(); 
    if (!m_pDib) { 
        return FALSE; // nothing to display 
    } 
    if (!::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, 
        size.cx, size.cy, 0, 0, (WORD) pBMIH->biWidth, 
        (WORD) pBMIH->biHeight, m_pData, pBMI, 
        DIB_RGB_COLORS, SRCCOPY)) { 
        return FALSE; 
    } 
    return TRUE; 
} 
/////////////////////////////////////////////////////////////////// 
WORD CImage::Bits() const 
{ 
	ASSERT(m_pDib); 
    return ((LPBITMAPINFOHEADER)m_pDib)->biBitCount; 
} 
 
/////////////////////////////////////////////////////////////////// 
DWORD CImage::Length() const 
{ 
    return m_dwLength; 
} 
/////////////////////////////////////////////////////////////////// 
 
CSize CImage::Size() const 
{ 
    ASSERT(m_pDib); 
	LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); 
    return CSize((int) pBMIH->biWidth, (int) pBMIH->biHeight); 
} 
/////////////////////////////////////////////////////////////////// 
 
WORD CImage::Height() const 
{ 
    ASSERT(m_pDib); 
	return (WORD)(((LPBITMAPINFOHEADER)m_pDib)->biHeight); 
} 
/////////////////////////////////////////////////////////////////// 
 
WORD CImage::Width() const 
{ 
    ASSERT(m_pDib); 
    return (WORD) (((LPBITMAPINFOHEADER)m_pDib)->biWidth); 
} 
/////////////////////////////////////////////////////////////////// 
//return the number of entries in the color pallete 
WORD CImage::NumColors() const 
{ 
    ASSERT(m_pDib); 
	LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr(); 
	if(m_pDib==NULL) return NULL; 
	if(pBMIH->biClrUsed!=0) 
		return (WORD)pBMIH->biClrUsed; 
	switch(pBMIH->biBitCount) 
	{ 
	case 1: 
		return 2; 
	case 4: 
		return 16; 
	case 8: 
		return 256; 
	default: 
		return 0; 
	} 
} 
/////////////////////////////////////////////////////////////////// 
LPBITMAPINFOHEADER CImage::BMInfoHdPtr() const 
{ 
	return (LPBITMAPINFOHEADER)m_pDib; 
} 
/////////////////////////////////////////////////////////////////// 
LPBITMAPINFO CImage::BMInfoPtr() const 
{ 
	return (LPBITMAPINFO)m_pDib; 
} 
/////////////////////////////////////////////////////////////////// 
RGBQUAD* CImage::BMColorTblPtr() const 
{ 
	return (RGBQUAD*)((int)m_pDib+sizeof(BITMAPINFOHEADER)); 
} 
/////////////////////////////////////////////////////////////////// 
void CImage::SetDIB(BOOL Flag) 
{ 
	if(Flag) m_bIsDIB=TRUE; 
	else m_bIsDIB=FALSE; 
} 
/////////////////////////////////////////////////////////////////// 
// To convert the non-DIB to DIB type 
BYTE* CImage::Dib() 
{ 
	if(!m_pDib) return NULL; 
	if(m_bIsDIB) return m_pData; 
 
	WORD		i, j; 
	BYTE		*p1, *p2; 
	WORD bpp	=	Bits(); 
	WORD bytepp =	bpp / 8; 
	WORD w		=	Width(); 
	WORD h		=	Height(); 
	long lBpl	=	w * bytepp; 
	WORD halfline = h / 2; 
 
	//reverse the order of scanning 
	//for(i=0 ; i0; i--) 
	{ 
		p1 = m_pData + i * dwBNFOL; 
		p2 = m_pData + i * lBpl; 
		memmove(p1, p2, lBpl); 
		memset(p1+lBpl, 0x00, (dwBNFOL - lBpl)); 
	} 
 
	SetDIB(); 
	return m_pData; 
} 
///////////////////////////////////////// 
//implement the reverse function of dib() 
BYTE* CImage::Data() 
{ 
	if(!m_pDib) return NULL; 
	if(!m_bIsDIB) return m_pData; 
 
	WORD	i,j; 
	BYTE	*p1, *p2; 
	WORD	bpp		= Bits();//bpp 
	WORD	Bytepp	= bpp / 8; 
	WORD	w		= Width(); 
	WORD	h		= Height(); 
	WORD	halfline= h/2; 
 
	LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr( ); 
 
	if(pBMIH->biCompression!=BI_RGB) 
	{ 
		AfxMessageBox("Con't process compressed image"); 
		return NULL; 
	} 
 
	if((w * bpp) % 32) 
	{ 
		long	t		= w * Bytepp; 
		DWORD dwBNFOL	= ByteNumForOneLine(w, bpp); 
		p2 = p1 = m_pData; 
		for(i=0; im_hObject) return FALSE; 
	VERIFY(pDC->SelectPalette(m_pPal,bBackground)); 
	return(pDC->RealizePalette()); 
} 
/////////////////////////////////////////////////////////////////// 
void CImage::SetMonoColors(DWORD dwForeground, DWORD dwBackground) 
{ 
    if (Bits() != 1) { 
        return; 
    } 
    unsigned long far* pPalette = (unsigned long far*) 
                       BMColorTblPtr(); 
    *pPalette = dwForeground; 
    *(++pPalette) = dwBackground; 
    return; 
} 
 
/////////////////////////////////////////////////////////////////// 
BOOL CImage::GetMonoColors(DWORD& dwForeground, DWORD& dwBackground) 
{ 
    if (Bits() != 1) { 
        return FALSE; 
    } 
    unsigned long far* pPalette = (unsigned long far*) 
                       BMColorTblPtr(); 
    dwForeground = *pPalette; 
    dwBackground = *(++pPalette); 
    return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////// 
BOOL CImage::AllocateMemory(BOOL bRealloc) // bRealloc default = FALSE 
{ 
    if (bRealloc) {   
        m_pDib = (BYTE*) GlobalReAllocPtr(m_pDib, 
                                                m_dwLength, GHND); 
    } 
    else { 
        m_pDib = (BYTE*) GlobalAllocPtr(GHND, m_dwLength); 
    } 
    if (!m_pDib) { 
        AfxMessageBox("Unable to allocate DIB memory"); 
        m_dwLength = 0L; 
        return FALSE; 
    } 
    return TRUE; 
} 
/*Record of Modify 
 *	Date		Operator	Modify			 
 * 1999.4.9		S.S.G		if the width of the bitmap can not be inter-divided by 8 
 *							We must alloc enough additional memory!! and some situations 
 *							must be processed 
*/ 
BOOL CImage::ReadFromBMP(CFile * pFile) 
 
 
{ 
	BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
	BITMAPINFOHEADER bmhdr;	 //header for bitmap info 
	long   biWidth;     
	long   biHeight;  
 
    ASSERT(m_dwLength == 0L); // DIB must be empty 
 
	if ((pFile->Read((BYTE*)&bmfHdr, sizeof(bmfHdr)) != 
		sizeof(bmfHdr))) { 
        AfxMessageBox("Read error"); 
        return FALSE; 
    } 
	if (bmfHdr.bfType != 0x4d42) 
	{ 
        AfxMessageBox("Invalid bitmap file"); 
		return FALSE; 
	} 
	//1999.4.9 added 
	if ((pFile->Read((BYTE*)&bmhdr, sizeof(bmhdr)) != 
		sizeof(bmhdr))) { 
        AfxMessageBox("Read error"); 
        return FALSE; 
    } 
	if(bmhdr.biSize != sizeof(bmhdr)) 
	{ 
        AfxMessageBox("Invalid bitmap file"); 
		return FALSE; 
	} 
	if(bmhdr.biBitCount == 16 && bmhdr.biBitCount == 32) 
	{ 
        AfxMessageBox("Sorry! Current version only support\n 8bpp and 24bpp BMP!"); 
		return FALSE; 
	} 
 
	if(bmhdr.biCompression != BI_RGB ) 
	{ 
        AfxMessageBox("Sorry! Current version do NOT support\n compressed BMP!"); 
		return FALSE; 
	} 
	biWidth = bmhdr.biWidth; 
	biHeight= abs(bmhdr.biHeight);  
	DWORD dwBytes = ByteNumForOneLine(biWidth, bmhdr.biBitCount); 
    //->| 
    m_dwLength = pFile->GetLength(); 
	m_dwLength -= sizeof(BITMAPFILEHEADER); 
	/*1999.4.9 added the following line*/ 
	//add the needed extent memory!!! 
	m_dwLength += (dwBytes - (bmhdr.biBitCount / 8) * bmhdr.biWidth) * bmhdr.biHeight; 
 
    if (!AllocateMemory()) { 
        return FALSE;        
    } 
 
	pFile->Seek(sizeof(BITMAPFILEHEADER), CFile::begin); 
    TRY { 
		pFile->Read(m_pDib, m_dwLength); 
	} 
	CATCH (CFileException, e) { 
        AfxMessageBox("Read error"); 
        GlobalFreePtr(m_pDib);  // free the DIB memory 
        return FALSE; 
	} 
	END_CATCH 
 
    m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * NumColors(); 
	CreateDIBPalette(); 
	SetDIB();  
    return TRUE; 
} 
 
BOOL CImage::ReadFromPGM(CFile * pFile) 
{ 
    // file assumed to be open 
	LPBITMAPINFOHEADER pBMIH; 
	char ch;	 
	WORD w, h, i=0, j=0; 
	char str[10]; 
	CString sfilehead; 
 
	ASSERT(m_dwLength == 0); 
 
    DWORD dwFileLength = pFile->GetLength(); 
	DWORD dwDataPos=0; 
	pFile->Seek(0,CFile::begin); 
    TRY { 
		pFile->Read(sfilehead.GetBuffer(30), 30); 
    	} 
	CATCH (CFileException, e) { 
        AfxMessageBox("Read error"); 
        return FALSE; 
	} 
	END_CATCH 
	 
	sfilehead.ReleaseBuffer(); 
	if(sfilehead == "")	{ 
		AfxMessageBox("Invalid PGM image file"); 
		return false; 
	} 
	if(sfilehead.GetAt(0) != 'P'||sfilehead.GetAt(1) != '5') { 
		AfxMessageBox("Invalid PGM image file"); 
		return false; 
	} 
 
	int tt = 0;	dwDataPos = 0; 
	while(tt != 3) 
	{ 
		if(sfilehead.GetAt(dwDataPos) == '\n') 
			tt++; 
		dwDataPos++; 
		if(dwDataPos > 30) 
		{ 
			AfxMessageBox("The format is wrong!"); 
			return false; 
		} 
	} 
 
	dwFileLength -= dwDataPos; 
 
	i=0;	ch=sfilehead.GetAt(i++); 
	while(ch!='\n')  ch=sfilehead.GetAt(i++); 
	j=0;  	ch=sfilehead.GetAt(i++); 
	while(ch!=' ') 
	   { str[j++]=ch; ch=sfilehead.GetAt(i++);} 
	str[j]='\0';	w=atoi(str); 
 
	j=0;	ch=sfilehead.GetAt(i++); 
	while(ch!='\n')  
		{str[j++]=ch;	ch=sfilehead.GetAt(i++);} 
	str[j]='\0';	h=atoi(str); 
 
	if( DWORD(w*h) > dwFileLength) 
	{ 
		AfxMessageBox("w*h != DataLength, The image data is wrong!"); 
		return false; 
	} 
	//make the number of bytes in one line can be divided exactly by 4 
    DWORD dwBytes = Transform(w);//bytes per line 
 
	m_dwLength = DWORD(dwBytes * h) + sizeof(BITMAPINFOHEADER) 
				              + sizeof(RGBQUAD) * 256; 
    if (!AllocateMemory()) { 
		AfxMessageBox("Allocmemory Error"); 
        return FALSE;} 
 
    pBMIH=BMInfoHdPtr(); 
	pBMIH->biSize = sizeof(BITMAPINFOHEADER); 
    pBMIH->biWidth = w; 
    pBMIH->biHeight = h; 
    pBMIH->biPlanes = 1; 
    pBMIH->biBitCount = 8; 
    pBMIH->biCompression = BI_RGB; 
    pBMIH->biSizeImage = 0; 
    pBMIH->biXPelsPerMeter = 0; 
    pBMIH->biYPelsPerMeter = 0; 
    pBMIH->biClrUsed = 0; 
    pBMIH->biClrImportant = 0; 
    m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * NumColors(); 
    pFile->Seek(dwDataPos/*+1 980518 modified!!*/,CFile::begin); 
    long dd; 
	TRY { 
			dd = pFile->Read(m_pData, DWORD(w * h)); 
			//pFile->Read(m_pData, dwFileLength); 
		} 
	CATCH (CFileException, e) { 
		AfxMessageBox("Read error"); 
        GlobalFreePtr(m_pDib);  // free the DIB memory 
        return FALSE;	} 
	END_CATCH 
 
	CreateGreyPalette(); 
	SetDIB(FALSE); 
	Dib();    
    return TRUE; 
} 
 
BOOL CImage::WriteAsPGM(CFile * pFile) 
{ 
	WORD w, h; 
	char cWidth[5]; 
	char cHeight[5]; 
	char* PgmHead = new char[30]; 
	Data(); 
 
	strcpy(PgmHead, "P5\n"); 
	if (m_pDib == NULL) 
		return FALSE; 
	if(Bits() != 8)  
	{ 
		AfxMessageBox("It is not 8-greylevel image!");		 
		return false;	} 
 
	w = Width();		h = Height(); 
	itoa(w,cWidth,10);	itoa(h,cHeight,10); 
	strcat(PgmHead,cWidth);		strcat(PgmHead," "); 
	strcat(PgmHead,cHeight);	strcat(PgmHead,"\n255\n"); 
 
	// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
 
	WORD hdLength = sizeof(BITMAPINFOHEADER) 
					 + NumColors()*sizeof(RGBQUAD); 
	TRY { 
		pFile->Write(PgmHead,strlen(PgmHead)); 
        pFile->Write(m_pData, (long)w*h); 
    } 
    CATCH (CFileException, e) { 
        AfxMessageBox("Write error--possible disk full condition"); 
        return FALSE; 
    } 
    END_CATCH 
	Dib(); 
	delete PgmHead; 
    return TRUE; 
} 
 
BOOL CImage::WriteAsData(CFile* pFile) 
{ 
	WORD w = Width(); 
	WORD h = Height(); 
	BYTE* pData = Data(); 
	TRY  
	{ 
        pFile->Write(pData, (long)w*h); 
    } 
    CATCH (CFileException, e)  
	{ 
        AfxMessageBox("Write error--possible disk full condition"); 
        return FALSE; 
    } 
    END_CATCH 
	Dib(); 
    return TRUE; 
} 
 
BOOL CImage::ReadFromFile(CFile * pFile) 
{ 
	BOOL	bReturn; 
	CString FileName=pFile->GetFilePath(); 
	 
	m_strFileName = FileName; 
 
	int nPointPos=FileName.Find("."); 
	FileName.MakeLower(); 
	FileName=FileName.Mid(nPointPos+1); 
	bReturn = FALSE; 
 
	if(FileName=="bmp")	 
		return ReadFromBMP(pFile); 
	if(FileName=="pgm")   
		return ReadFromPGM(pFile); 
	if(FileName == "img") 
		return ReadFromIMG(pFile); 
	if(FileName == "dat") 
		return ReadFromDAT(pFile); 
	if(ReadFromPGM(pFile)) 
		return TRUE; 
	return FALSE; 
} 
 
BOOL CImage::ReadFromFile(CString filename) 
{ 
	/* 
	 *	 
	 * 
	CString	ext  = filename; 
	int nPointPos=ext.Find("."); 
	ext.MakeLower(); 
	ext=ext.Mid(nPointPos+1); 
	 
	*/ 
	CFile* pFile = new CFile(); 
	//CFileException e; 
	LPCTSTR file_name = filename; 
	 
	if(!pFile->Open(file_name,CFile::modeRead)) 
	{ 
		AfxMessageBox("In CImage::ReadFromFile(),Can not opent the file!"); 
		return false; 
	} 
 
//pFile->Open(filename,CFile::modeRead); 
	BOOL b = ReadFromFile(pFile); 
	 
	pFile->Close(); 
	delete pFile; 
	return b; 
} 
 
 
BOOL CImage::WriteToFile(CFile * pFile) 
{ 
	CString FileName=pFile->GetFileName(); 
	int nPointPos=FileName.Find("."); 
	FileName.MakeLower(); 
	FileName=FileName.Mid(nPointPos+1); 
 
	if(FileName=="bmp")	 
		return WriteAsBMP(pFile); 
	if(FileName=="pgm")   
		return WriteAsPGM(pFile); 
	if(FileName=="bin") 
		return WriteAsData(pFile); 
	if(FileName=="txt") 
	{ 
		CString temp = pFile->GetFilePath(); 
		pFile -> Close(); 
		BOOL b = SaveAsText(temp, FALSE); 
		pFile -> Open(temp, CFile::modeWrite); 
		return b; 
	} 
	 
	return WriteAsPGM(pFile); 
} 
 
BOOL CImage::WriteToFile(CString filename) 
{ 
	CFile* pFile = new CFile; 
	if(!pFile->Open(filename,CFile::modeWrite|CFile::modeCreate)) 
	{ 
		AfxMessageBox("In CImage::WriteToFile(),Can not opent the file!"); 
		return false; 
	} 
 
	BOOL b = WriteToFile(pFile); 
	 
	pFile->Close(); 
	delete pFile; 
	return b;	 
} 
 
void CImage::ImageClear() 
{ 
    if (m_pDib)  
        GlobalFreePtr(m_pDib);  // free the DIB memory 
	m_pDib     = NULL; 
	m_pData    = NULL; 
	m_pPal     = NULL;// wr add  
	m_bIsDIB   = TRUE; 
	m_dwLength = 0L;  
} 
 
DWORD CImage::Transform(WORD width) 
{ 
    DWORD dwBytes = (width * 8) / 32; 
    if ((width * 8) % 32) { 
        dwBytes ++; 
    } 
    dwBytes *= 4; //bytes per line	 
	return dwBytes; 
} 
 
BOOL CImage::ReadFromIMG(CFile* pFile) 
{ 
	int		bpp; 
	LPBITMAPINFOHEADER pBMIH; 
    DWORD dwFileLength = pFile->GetLength(); 
    WORD w,h; 
 
	pFile->Read((WORD* )&w,sizeof(WORD)); 
	pFile->Read((WORD* )&h,sizeof(WORD)); 
 
	dwFileLength -= 2 * sizeof(WORD); 
	bpp = int(dwFileLength / (w * h)); 
	if(bpp != 1 && bpp != 3)/* 8 or 24 */ 
	{ 
		AfxMessageBox("Wrong Data!"); 
		return false; 
	} 
 
    DWORD dwBytes = Transform(w);//bytes per line 
 
	m_dwLength = DWORD(dwBytes * h * bpp) + sizeof(BITMAPINFOHEADER) 
				              + sizeof(RGBQUAD) * 256; 
    if (!AllocateMemory()) { 
		AfxMessageBox("Allocmemory Error"); 
        return FALSE;} 
 
    pBMIH=BMInfoHdPtr(); 
	pBMIH->biSize = sizeof(BITMAPINFOHEADER); 
    pBMIH->biWidth = w; 
    pBMIH->biHeight = h; 
    pBMIH->biPlanes = 1; 
    pBMIH->biBitCount = 8 * bpp; 
    pBMIH->biCompression = BI_RGB; 
    pBMIH->biSizeImage = 0; 
    pBMIH->biXPelsPerMeter = 0; 
    pBMIH->biYPelsPerMeter = 0; 
    pBMIH->biClrUsed = 0; 
    pBMIH->biClrImportant = 0; 
    m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * NumColors(); 
	CreateGreyPalette(); 
 
    TRY { 
		pFile->Read(m_pData, dwFileLength); 
	} 
	CATCH (CFileException, e) { 
        AfxMessageBox("Read error"); 
        GlobalFreePtr(m_pDib);  // free the DIB memory 
        return FALSE; 
	} 
	END_CATCH 
 
	SetDIB(true); 
	Dib(); 
    return TRUE; 
} 
 
BOOL CImage::ReadFromDAT(CFile* pFile) 
{ 
	LPBITMAPINFOHEADER pBMIH; 
    DWORD dwFileLength = pFile->GetLength(); 
    WORD w,h; 
	///////just for MIT facebase!!! 
	w = 256; 
	h = 240; 
 
	if(dwFileLength != (DWORD)(w * h)) 
	{ 
		AfxMessageBox("Wrong Data!"); 
		return false; 
	} 
 
    DWORD dwBytes = Transform(w);//bytes per line 
 
	m_dwLength = DWORD(dwBytes * h) + sizeof(BITMAPINFOHEADER) 
				              + sizeof(RGBQUAD) * 256; 
    if (!AllocateMemory()) { 
		AfxMessageBox("Allocmemory Error"); 
        return FALSE;} 
 
    pBMIH=BMInfoHdPtr(); 
	pBMIH->biSize = sizeof(BITMAPINFOHEADER); 
    pBMIH->biWidth = w; 
    pBMIH->biHeight = h; 
    pBMIH->biPlanes = 1; 
    pBMIH->biBitCount = 8; 
    pBMIH->biCompression = BI_RGB; 
    pBMIH->biSizeImage = 0; 
    pBMIH->biXPelsPerMeter = 0; 
    pBMIH->biYPelsPerMeter = 0; 
    pBMIH->biClrUsed = 0; 
    pBMIH->biClrImportant = 0; 
    m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) + 
               sizeof(RGBQUAD) * NumColors(); 
	CreateGreyPalette(); 
 
    TRY { 
		pFile->Read(m_pData, dwFileLength); 
	} 
	CATCH (CFileException, e) { 
        AfxMessageBox("Read error"); 
        GlobalFreePtr(m_pDib);  // free the DIB memory 
        return FALSE; 
	} 
	END_CATCH 
 
	SetDIB(false); 
	Dib(); 
    return TRUE; 
} 
/////////////////the property of the image//////////////// 
BYTE	CImage::Get8NeiborAver(BYTE* pGreyData, WORD w, WORD h, CPoint pos) 
{ 
	double temp; 
	int x = pos.x; 
	int y = pos.y; 
	int t = y * w + x; 
	if(x == 0 && y != 0) 
	{ 
		temp  =	pGreyData[t-w] + pGreyData[t-w+1] + 
				pGreyData[t+1] +  
				pGreyData[t+w] + pGreyData[t+w+1]; 
		temp /= 5; 
		return (BYTE)temp; 
	} 
	if(x != 0 && y == 0) 
	{ 
		temp  =	pGreyData[t-1] + pGreyData[t+1] +  
				pGreyData[t+w-1] + pGreyData[t+w] + pGreyData[t+w+1]; 
		temp /= 5; 
		return (BYTE)temp; 
	} 
	if(x == 0 && y != 0) 
	{ 
		temp  =	pGreyData[t+1] + 
				pGreyData[t+w] + pGreyData[t+w+1]; 
		temp /= 3; 
		return (BYTE)temp; 
	} 
 
	if(x == w-1 && y != h-1) 
	{ 
		temp  =	pGreyData[t-w-1] + pGreyData[t-w] + 
				pGreyData[t-1] +  
				pGreyData[t+w-1] + pGreyData[t+w]; 
		temp /= 5; 
		return (BYTE)temp; 
	} 
	if(x != w-1 && y == h-1) 
	{ 
	temp  =	pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-w+1] + 
			pGreyData[t-1] + pGreyData[t+1]; 
	temp /= 5; 
	return (BYTE)temp; 
	} 
	if(x = w-1 && y == h-1) 
	{ 
		temp  =	pGreyData[t-w-1] + pGreyData[t-w] +  
				pGreyData[t-1]; 
		temp /= 3; 
		return (BYTE)temp; 
	} 
	temp  =	pGreyData[t-w-1] + pGreyData[t-w] + pGreyData[t-w+1] + 
			pGreyData[t-1]   + pGreyData[t+1] + 
			pGreyData[t+w-1] + pGreyData[t+w] + pGreyData[t+w+1]; 
	temp /= 8; 
	return (BYTE)temp; 
} 
 
 
DWORD CImage::ByteNumForOneLine(WORD nDIBWidth, int nBpp) 
{ 
    DWORD dwBytes = (nDIBWidth * nBpp) / 32; 
	if ((nDIBWidth * nBpp) % 32)  
		dwBytes ++; 
 
    dwBytes *= 4;//bytes per line 
	 
	return	dwBytes; 
} 
/////////////////////////////////////////////// 
/* 
 * SSG, 1999.6. 2 
 * Save the data as text 
*/ 
/////////////////////////////////////////////// 
BOOL CImage::SaveAsText(CString	 filename, BOOL	bIsBinary) 
{ 
	int		w; 
	long	l, size; 
	char	buf[20]; 
	CFile	f; 
	BYTE	*pData; 
 
	pData = Data(); 
	 
	if (m_pDib == NULL) 
		return FALSE; 
	if(Bits() != 8) { 
		AfxMessageBox("It is not 8-greylevel image!");		 
		return false;	 
	} 
	w = Width(); 
	size = w * Height(); 
 
	f.Open(filename, CFile::modeCreate | CFile::modeWrite ); 
	if(bIsBinary) 
	{ 
		for(l=0; l= (DWORD)(scrW * scrH))  break; 
					sum += scrImage[scrOff + n]; 
					num++; 
				} 
			} 
			if(num!=0)  
				destImage[destOff + j] = (BYTE)(sum / num); 
			else   
				destImage[destOff + j] = (BYTE)sum; 
		} 
	} 
} 
 
//////////////////////////////////////////////////////////////////////// 
//author:   ssg 
//Modified version based on the one from Liu Ming Bao 
//Para1:	BYTE* image:	the source image data poiter 
//Para2:	BYTE* rimage:	the resulting image data poiter 
//Para3,4:	int w, h:		source image's width and height in pixel 
//para5:	float cscale:	the scale to shrink 
////////////////////////////////////////////////////////////////////////// 
void CImage::ShrinkImage(BYTE *scrImage, BYTE* destImage, WORD w, WORD h, float cscale) 
{ 
	DWORD		i, j, m, n, scrOff, destOff, destw, desth; 
	DWORD		num,sum; 
	double	step_w, step_h,tm, tn; 
	 
	destw = (WORD) (w * cscale); 
	desth = (WORD) (h * cscale); 
	 
	step_w = (double)w / destw; 
	step_h = (double)h / desth; 
	 
	for (i=0; i < desth; i++)  
	{ 
		tm=i*step_h; 
		destOff = destw * i; 
		for (j=0; j < destw; j++)  
		{ 
			sum=0;       
			num = 0; 
			tn=j*step_w; 
			for (m = (WORD)tm + 1; m <= (WORD)(tm + step_h); m++)   
			{ 
				scrOff=w*m; 
				for (n = (WORD)tn + 1; n <= (WORD)(tn + step_w); n++)   
				{ 
					sum += scrImage[scrOff+n]; 
					if(scrOff >= (DWORD)(w * h))  
						break; 
					num++; 
				} 
			} 
			if(num!=0)  
				destImage[destOff + j] = (BYTE)(sum/num); 
			else   
				destImage[destOff + j]=(BYTE)sum; 
		} 
	} 
}