www.gusucode.com > VC++图像分水岭分割算法控件及示例源代码-源码程序 > VC++图像分水岭分割算法控件及示例源代码-源码程序/code/include/ImageObject.cpp

    // ImageObject.cpp: implementation of the CImageObject class.
// Download by http://www.NewXing.com
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageObject.h"
#include "ImageLoad.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNCREATE( CImageObject, CObject ) 

char *CImageObject::pszExtensions[] = { ".bmp", ".gif", ".pcx", ".tga", ".jpg", ".tif", "" };

//////////////////////////////////////////////////
// Constructor and destructor
//
CImageObject::CImageObject()
{
	m_nWidth = m_nHeight = m_nBits = m_nColors = m_nImageType = 0;
	m_nX = m_nY = 0;
	m_nLastError = 0;
	m_hDib = NULL;
	m_nPaletteCreationType = JGPT_FIXED_PALETTE;
    m_pszFileName = NULL;
    m_pLogPalette = NULL;
	m_nQuality = 80;
	m_pDib = NULL;
	m_lBufSize = 0;
}

CImageObject::CImageObject( const char *pszFileName, CDC *pDC, int nX, int nY )
{
	m_nWidth = m_nHeight = m_nBits = m_nColors = m_nImageType = 0;
	m_nX = m_nY = 0;
	m_nLastError = 0;
	m_hDib = NULL;
	m_nPaletteCreationType = JGPT_FIXED_PALETTE;
	m_pszFileName = NULL;
	m_pLogPalette = NULL;
	m_nQuality = 80;
	m_pDib = NULL;
	m_lBufSize = 0;
	LoadFromFile( pszFileName, pDC, nX, nY );
}

void CImageObject::operator=( const CImageObject &ImageObject )
{
	DestroyImage();

	m_nLastError = ImageObject.m_nLastError;

    m_nWidth = ImageObject.m_nWidth;
	m_nHeight = ImageObject.m_nHeight;
	m_nPlanes = ImageObject.m_nPlanes;
	m_nBits = ImageObject.m_nBits;
	m_nColors = ImageObject.m_nColors;
	m_nImageType = ImageObject.m_nImageType;
	
	m_nX = ImageObject.m_nX;
	m_nY = ImageObject.m_nY;

	m_nScreenPlanes = ImageObject.m_nScreenPlanes;
	m_nScreenBits = ImageObject.m_nScreenBits;
	m_nPaletteInBytes = ImageObject.m_nPaletteInBytes;
	m_nQuality = ImageObject.m_nQuality;
	m_nPaletteCreationType = ImageObject.m_nPaletteCreationType;
	
	int nNumColors = m_nColors;
	int nWidthBytes = GetWidthInBytes( m_nBits, m_nWidth );
	
	if( ImageObject.m_hDib != NULL )
	{
		DWORD dwSize = ::GlobalSize( ImageObject.m_hDib );
		char *pData = ( char * )::GlobalLock( ImageObject.m_hDib );
		if( pData != NULL )
		{
			HGLOBAL hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
			if( hGlobal != NULL )
			{
				char *pDestData = ( char * )::GlobalLock( hGlobal );
				if( pDestData != NULL )
				{
					memcpy( pDestData, pData, dwSize );
					if( nNumColors != 0 )
						CreatePaletteFromDIB( ( RGBQUAD * )&pData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], nNumColors );
					else if( ImageObject.m_pLogPalette != NULL )
					{
						m_pLogPalette = (LOGPALETTE *) new char[ sizeof( LOGPALETTE ) + ImageObject.m_pLogPalette->palNumEntries * sizeof( PALETTEENTRY ) ];
						if( m_pLogPalette != NULL )
						{
							for( int i=0; i<ImageObject.m_pLogPalette->palNumEntries; i++ )
								m_pLogPalette[i] = ImageObject.m_pLogPalette[i];
							m_Palette.CreatePalette( m_pLogPalette );
						}
					}
					::GlobalUnlock( hGlobal );
					m_hDib = hGlobal;
				}
				else ::GlobalFree( hGlobal );
			}
			::GlobalUnlock( ImageObject.m_hDib );
		}
	}
	if( ImageObject.m_pszFileName != NULL )
	{
		m_pszFileName = new char [strlen( ImageObject.m_pszFileName ) + 1 ];
		strcpy( m_pszFileName, ImageObject.m_pszFileName );
	}
}

CImageObject::~CImageObject()
{
	if(m_pDib)
		::GlobalUnlock(m_hDib);
	if(m_hDib)
		::GlobalFree( m_hDib );
	if(m_pszFileName != NULL )
	{
		delete[] m_pszFileName;
		m_pszFileName = NULL;
	}
}

//////////////////////////////////////////
// Get/set member functions
//
int CImageObject::GetExtensionIndex( const char *pszFileName )
{
	int Index = 0;
	char *pszExt;
	pszExt = ( char * )&pszFileName[ strlen( pszFileName ) - 4 ];
	while( pszExtensions[ Index ][ 0 ] )
	{
		if( !stricmp( pszExt, pszExtensions[ Index ] ) ) 
			return( Index + 1 );
		Index++;
	}
	return( -1 );
}

int CImageObject::GetLastError( void )
{
	return( m_nLastError );
}

bool CImageObject::IsLoaded( void )
{
	return( m_hDib != NULL );
}

int CImageObject::GetWidth( void )
{
	return( m_nWidth );
}

int CImageObject::GetHeight( void )
{
	return( m_nHeight );
}

int CImageObject::GetBits( void )
{
	return( m_nBits );
}

int CImageObject::GetColors( void )
{
	return( m_nColors );
}

HGLOBAL CImageObject::GetDib( void )
{
	return( m_hDib );
}

void CImageObject::SetDib( HGLOBAL hDib )
{
	m_hDib = hDib;
}


long CImageObject::GetSize()
{
   return (long) sizeof(BITMAPFILEHEADER)
        +sizeof(BITMAPINFOHEADER)
		+m_nColors*sizeof(RGBQUAD)
		+GetWidthInBytes(m_nBits,m_nWidth)*m_nHeight;
}

int CImageObject::GetDestX()
{
	return m_nX;
}

int CImageObject::GetDestY()
{
	return m_nY;
}

BYTE * CImageObject::GetDibPoint(void)
{
	return(m_pDib);
}
// Palette
int CImageObject::GetPaletteInBytes( void )
{
	return( m_nPaletteInBytes );
}

CPalette *CImageObject::GetPalette( void )
{
	return( &m_Palette );
}

LOGPALETTE *CImageObject::GetLogPalette( void )
{
	return( m_pLogPalette );
}

void CImageObject::SetLogPalette( LOGPALETTE *pLogPalette )
{
	m_pLogPalette = pLogPalette;
}

void CImageObject::SetPaletteCreationType( int nType )
{
	m_nPaletteCreationType = nType;
}

int CImageObject::GetPaletteCreationType( void )
{
	return( m_nPaletteCreationType );
}

void CImageObject::SetQuality( int nQuality )
{
	m_nQuality = nQuality;
}

/*
int CImageObject::GetImageType( const char *pszFileName )
{
	return( ::FileType( pszFileName ) );
}
*/
char *CImageObject::GetImageName()
{
  return( m_pszFileName );
}

int CImageObject::GetImageType( void )
{
	return( m_nImageType );
}

//////////////////////////////////////////
// Get/set member functions
//
/*
bool CImageObject::GetImageInfo( const char *pszFileName, int *pnWidth,
	int *pnHeight, int *pnPlanes, int *pnBitsPerPixel, int *pnNumColors )
{
	int nImageType;
	nImageType = ::FileType( pszFileName );
	if( nImageType == 0 )
	{
		m_nLastError = GL_UNSUPPORTED_FILETYPE;
		return( false );
	}
	switch( nImageType )
	{
		case GT_BMP:
			if( ::GetBMPInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
		case GT_GIF:
			if( ::GetGIFInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
		case GT_JPG:
			if( ::GetJPGInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
		case GT_PCX:
			if( ::GetPCXInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
		case GT_TGA:
			if( ::GetTGAInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
		case GT_TIF:
			if( ::GetTIFInfo( pszFileName, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) )
				return( true );
		  break;
	}
	return( false );
}
*/
bool CImageObject::GetImageInfo( ImageINFO *gi )
{
	int nWidth, nHeight, nPlanes, nColorDepth, nColorNumber;

	if( m_nImageType == 0 )
	{
		m_nLastError = GL_UNSUPPORTED_FILETYPE;
		return( false );
	}
	switch( m_nImageType )
	{
		case GT_BMP:
			if( ::GetBMPInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
		case GT_GIF:
			if( ::GetGIFInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
		case GT_JPG:
			if( ::GetJPGInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
		case GT_PCX:
			if( ::GetPCXInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
		case GT_TGA:
			if( ::GetTGAInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
		case GT_TIF:
			if( ::GetTIFInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( true );
			}
		  break;
	}
	return( false );
}

ImageINFO *CImageObject::GetImageInfo( void )
{
	int nWidth, nHeight, nPlanes, nColorDepth, nColorNumber;

	if( m_nImageType == 0 )
	{
		m_nLastError = GL_UNSUPPORTED_FILETYPE;
		return( false );
	}
	switch( m_nImageType )
	{
		case GT_BMP:
			if( ::GetBMPInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
		case GT_GIF:
			if( ::GetGIFInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
		case GT_JPG:
			if( ::GetJPGInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
		case GT_PCX:
			if( ::GetPCXInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
		case GT_TGA:
			if( ::GetTGAInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
		case GT_TIF:
			if( ::GetTIFInfo( m_pszFileName, &nWidth, &nHeight, &nPlanes, &nColorDepth, &nColorNumber ) )
			{
      	ImageINFO *gi = new ImageINFO;
			  gi->nWidth = nWidth;
			  gi->nHeight = nHeight;
			  gi->nPlanes = nPlanes;
			  gi->nColorDepth = nColorDepth;
			  gi->nColorNumber = nColorNumber;
				return( gi );
			}
		  break;
	}
	return( NULL );
}

// Change color depth of the Image
bool CImageObject::SetColorDepth( int nColorDepth )
{
	m_nLastError = GL_SUCCESS;
	if( nColorDepth == m_nBits )
		return( true );
	int nOldWidthInBytes, nNewWidthInBytes;
	char *pBuffer = ( char * )GetDIBPointer( &nOldWidthInBytes, nColorDepth, &nNewWidthInBytes );
	if( pBuffer == NULL )
		return( false );

	BITMAPINFOHEADER *pOldBIH, *pNewBIH;
	BITMAPFILEHEADER *pOldBFH, *pNewBFH;
	RGBQUAD *pOldRGBPalette, *pNewRGBPalette;
	unsigned char *pOldBits, *pNewBits;
	int nOldColors, nNewColors;
	pOldBFH = ( BITMAPFILEHEADER * )pBuffer;
	pOldBIH = ( BITMAPINFOHEADER * )&pBuffer[ sizeof( BITMAPFILEHEADER ) ];
	pOldRGBPalette = ( RGBQUAD * )&pBuffer[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ];
	nOldColors = m_nColors;
	nNewColors = 1 << nColorDepth;
	if( nColorDepth > 8 )
		nNewColors = 0;
	pOldBits = ( unsigned char * )&pBuffer[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER) + nOldColors * sizeof( RGBQUAD ) ];
	if( m_nBits >= 16 && nColorDepth < 16 )
	{
		if( m_pLogPalette != NULL )
			delete[] m_pLogPalette;
		m_pLogPalette = CreatePaletteFromBitmap( nNewColors, pOldBits, m_nBits, m_nWidth, m_nHeight );
	}

	HGLOBAL hGlobal;
	DWORD dwSize;
	dwSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewColors * sizeof( RGBQUAD ) + m_nHeight * nNewWidthInBytes;
	hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
	if( hGlobal == NULL )
	{
		::GlobalUnlock( m_hDib );
		return( false );
	}
	pBuffer = (char *) ::GlobalLock( hGlobal );
	if( pBuffer == NULL )
	{
		::GlobalFree( hGlobal );
		::GlobalUnlock( m_hDib );
		return( false );
	}

	pNewBFH = ( BITMAPFILEHEADER * )pBuffer;
	pNewBIH = ( BITMAPINFOHEADER * )&pBuffer[ sizeof( BITMAPFILEHEADER ) ];
	pNewRGBPalette = ( RGBQUAD * )&pBuffer[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ];
	*pNewBFH = *pOldBFH;
	*pNewBIH = *pOldBIH;
	int i, j = nNewColors;
	if( m_nBits < 16 && nColorDepth < 16 )
	{
		for( i=0; i<j; i++ )
			pNewRGBPalette[i] = pOldRGBPalette[i];
	}
	else if( m_nBits >= 16 )
	{
 		for( i=0; i<j; i++ )
		{
			pNewRGBPalette[ i ].rgbRed = m_pLogPalette->palPalEntry[ i ].peRed;
			pNewRGBPalette[ i ].rgbGreen = m_pLogPalette->palPalEntry[ i ].peGreen;
			pNewRGBPalette[ i ].rgbBlue = m_pLogPalette->palPalEntry[ i ].peBlue;
		}
	}

	pNewBIH->biBitCount = nColorDepth;
	pNewBIH->biSizeImage = nNewWidthInBytes * m_nHeight;
	pNewBIH->biClrUsed = nNewColors;
	pNewBFH->bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewColors * sizeof( RGBQUAD ) + pNewBIH->biSizeImage;
	pNewBFH->bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewColors * sizeof( RGBQUAD );
	pNewBits = ( unsigned char * )&pBuffer[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewColors * sizeof( RGBQUAD ) ];
	m_nPaletteInBytes = nNewColors * sizeof( RGBQUAD );
	for( int y=0; y<m_nHeight; y++ )
	{
		unsigned char ucRed, ucGreen, ucBlue;
		unsigned char *pSrc, *pDest;
		pSrc = pOldBits;
		pSrc += ( nOldWidthInBytes * y );
		pDest = pNewBits;
		pDest += ( nNewWidthInBytes * y );
		for( int x=0; x<m_nWidth; x++ )
		{
			switch( m_nBits )
			{
				case 1:
					if( pSrc[ x/8 ] & ( 0x80 >> ( x & 7 ) ) )
						ucRed = ucGreen = ucBlue = 0xff;
					else
						ucRed = ucGreen = ucBlue = 0x00;
					break;
				case 4:
					if( !( x & 1 ) )
					{
						ucRed = pOldRGBPalette[ pSrc[ x/2 ] >> 4 ].rgbRed;
						ucGreen = pOldRGBPalette[ pSrc[ x/2 ] >> 4 ].rgbGreen;
						ucBlue = pOldRGBPalette[ pSrc[ x/2 ] >> 4 ].rgbBlue;
					}
					else
					{
						ucRed = pOldRGBPalette[ pSrc[ x/2 ] & 15 ].rgbRed;
						ucGreen = pOldRGBPalette[ pSrc[ x/2 ] & 15 ].rgbGreen;
						ucBlue = pOldRGBPalette[ pSrc[ x/2 ] & 15 ].rgbBlue;
					}
					break;
				case 8:
					ucRed = pOldRGBPalette[ pSrc[ x ] ].rgbRed;
					ucGreen = pOldRGBPalette[ pSrc[ x ] ].rgbGreen;
					ucBlue = pOldRGBPalette[ pSrc[ x ] ].rgbBlue;
					break;
				case 16:
					GET_RGB_16( ucRed, ucGreen, ucBlue, &pSrc[ 2*x ] );
					break;
				case 24:
					ucRed = pSrc[ 3*x + 2 ];
					ucGreen = pSrc[ 3*x + 1 ];
					ucBlue = pSrc[ 3*x ];
					break;
				case 32:
					GET_RGB_32( ucRed, ucGreen, ucBlue, &pSrc[ 4*x ] );
					break;
			}
			switch( nColorDepth )
			{
				case 1:
					if( !( x & 7 ) )
						pDest[ x/8 ] = 0;
					pDest[ x/8 ] |= ( unsigned char )GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNewColors ) << ( x & 7 );
					break;
				case 4:
					if( !( x & 1 ) )
						pDest[ x/2 ] = ( unsigned char )GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNewColors ) << 4;
					else
						pDest[ x/2 ] |= ( unsigned char )GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNewColors );
					break;
				case 8:
					pDest[ x ] = ( unsigned char )GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNewColors );
					break;
				case 16:
					PUT_RGB_16( ucRed, ucGreen, ucBlue, &pDest[ 2*x ] );
					break;
				case 24:
					pDest[ 3*x + 2 ] = ucRed;
					pDest[ 3*x + 1 ] = ucGreen;
					pDest[ 3*x ] = ucBlue;
					break;
				case 32:
					PUT_RGB_32( ucRed, ucGreen, ucBlue, &pDest[ 4*x ] );
					break;
			}
		}
	}

	::GlobalUnlock( m_hDib );
	::GlobalFree( m_hDib );
	::GlobalUnlock( hGlobal );
	m_hDib = hGlobal;
	LoadImageHeader();
	return( true );
}

//////////////////////////////////////////
// Palette functions
//
bool CImageObject::SetPalette( CDC *pDC )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( false );
	pDC->SelectPalette( &m_Palette, false );
	pDC->RealizePalette();
	m_nLastError = GL_SUCCESS;
	return( true );
}

bool CImageObject::GetPaletteData( RGBQUAD *pRGBPalette )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( false );
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return( false );
	memcpy( pRGBPalette, &pTemp[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ], m_nPaletteInBytes );
	m_nLastError = GL_SUCCESS;
	::GlobalUnlock( m_hDib );
	return( true );
}

RGBQUAD *CImageObject::GetPaletteData( void )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( NULL );
	m_nLastError = GL_NO_PALETTE_FOR_HIGH_COLOR;
	if( m_nColors <= 0 || m_nColors > 256 )
		return( NULL );
	RGBQUAD *pRGBPalette;
	pRGBPalette = new RGBQUAD[ m_nColors ];
	if( pRGBPalette == NULL )
	{
		m_nLastError = GL_MEMORY_ALLOCATION_ERROR;
		return( NULL );
	}
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
	{
		delete[] pRGBPalette;
		return( NULL );
	}
	memcpy( pRGBPalette, &pTemp[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ], m_nColors * sizeof( RGBQUAD ) );
	m_nLastError = GL_SUCCESS;
	::GlobalUnlock( m_hDib );
	return( pRGBPalette );
}

//////////////////////////////////////////
// Load and Save functions
//
bool CImageObject::LoadFromFile( const char *pszFileName, CDC *pDC, int nX, int nY )
{
	m_nImageType = ::FileType( pszFileName );
	if( m_nImageType == 0 )
	{
		m_nLastError = GL_UNSUPPORTED_FILETYPE;
		return( false );
	}
	DestroyImage();
	m_pszFileName = new char[ strlen( pszFileName ) + 1 ];
	if( m_pszFileName != NULL )
		strcpy( m_pszFileName, pszFileName );
	switch( m_nImageType )
	{
		case GT_BMP:
			m_hDib = ::LoadBMP( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		case GT_GIF:
			m_hDib = ::LoadGIF( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		case GT_JPG:
			m_hDib = ::LoadJPG( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		case GT_PCX:
			m_hDib = ::LoadPCX( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		case GT_TGA:
			m_hDib = ::LoadTGA( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		case GT_TIF:
			m_hDib = ::LoadTIF( pszFileName );
			if( m_hDib == NULL )
			{
				m_nLastError = ::GetLastPicLibError();
				return( false );
			}
			break;
		}
	LoadImageHeader();
	LoadPalette();
	
    //----------------------------------------------------------------------
	// added by maple to support GetPixelColor() and SetPixelColor()  
	// 2004.3.26
	if(m_pDib!=NULL)
		::GlobalUnlock(m_hDib);
	m_pDib = (BYTE *)::GlobalLock(m_hDib);

	//----------------------------------------------------------------------
	if( pDC != NULL )
		Draw( pDC, nX, nY );
	return( true );
}

bool CImageObject::SaveToFile( const char *pszFileName, int nType )
{
	if( nType == -1 )
		nType = GetExtensionIndex( pszFileName );
	if( nType < GT_FIRSTTYPE || nType > GT_LASTTYPE )
		return( false );
	m_nImageType = nType;
	delete[] m_pszFileName;
	m_pszFileName = new char [ strlen( pszFileName ) + 1 ];
	if( m_pszFileName != NULL )
		strcpy( m_pszFileName, pszFileName );
	switch( m_nImageType )
	{
		case GT_BMP:
			if( SaveBMP( pszFileName, m_hDib ) )
				return( true );
		  break;
		case GT_GIF:
			if( ::SaveGIF( pszFileName, m_hDib ) )
				return( true );
		  break;
		case GT_JPG:
			if( ::SaveJPG( pszFileName, m_hDib, m_nQuality ) )
				return( true );
		  break;
		case GT_PCX:
			if( ::SavePCX( pszFileName, m_hDib ) )
				return( true );
		  break;
		case GT_TGA:
			if( ::SaveTGA( pszFileName, m_hDib ) )
				return( true );
		  break;
		case GT_TIF:
			if( ::SaveTIF( pszFileName, m_hDib ) )
				return( true );
		  break;
	}
	return( false );  // true?
}

//////////////////////////////////////////
// Draw functions
//
bool CImageObject::Draw( CDC *pDC, int nX, int nY )
{
	if( nX != -1 )
		m_nX = nX;
	if( nY != -1 )
		m_nY = nY;
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( false );
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return( NULL );
	BITMAPINFOHEADER *pBIH;
	pBIH = ( BITMAPINFOHEADER * )&pTemp[ sizeof( BITMAPFILEHEADER ) ];
	::SetStretchBltMode(pDC->GetSafeHdc(),COLORONCOLOR);
	int nRet = ::StretchDIBits( pDC->m_hDC, m_nX, m_nY, m_nWidth, m_nHeight,
		                        0, 0, m_nWidth, m_nHeight,
		                        (const void FAR *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nPaletteInBytes], 
		                        (BITMAPINFO *) pBIH,
								DIB_RGB_COLORS, 
								SRCCOPY );
	::GlobalUnlock( m_hDib );
	m_nLastError = GL_STRETCHDIBITS_ERROR;
	if( nRet != m_nHeight )
		return( false );
	m_nLastError = GL_SUCCESS;
	return( true );
}


/***********************************************************************
*  Description: this function was added by maple,2004.3.21
*
*  函数名称:DrawTo
* 
*  参数:  CDC *pDC        -- 绘图设备环境
*            int nDestX      -- 绘制起点横坐标
*            int nDestY      -- 绘制七点纵坐标
*            int nDestWidth  -- 绘制目标区域宽度
*            int nDestHeight -- 绘制目标区域高度
* 
*  返回值:  bool 
*
*  说明:    该函数用于将一图象绘制到指定区域。          
************************************************************************/

bool CImageObject::DrawTo(CDC *pDC,int nDestX ,int nDestY ,int nDestWidth,int nDestHeight)
{
	if( nDestX != -1 )
		m_nX = nDestX;
	if( nDestY != -1 )
		m_nY = nDestY;
	if(nDestWidth != 0)
		m_nDestWidth = nDestWidth;
	if(nDestHeight != 0)
		m_nDestHeight = nDestHeight;
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( false );
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return( NULL );
	BITMAPINFOHEADER *pBIH;
	pBIH = ( BITMAPINFOHEADER * )&pTemp[ sizeof( BITMAPFILEHEADER ) ];
	::SetStretchBltMode(pDC->GetSafeHdc(),COLORONCOLOR);
	int nRet = ::StretchDIBits( pDC->m_hDC, m_nX, m_nY, m_nDestWidth, m_nDestHeight,
		                        0, 0, m_nWidth, m_nHeight,	
		                        (const void FAR *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nPaletteInBytes], 
		                        (BITMAPINFO *) pBIH,
								DIB_RGB_COLORS, 
								SRCCOPY );
	::GlobalUnlock( m_hDib );
	m_nLastError = GL_STRETCHDIBITS_ERROR;
	if( nRet != m_nHeight )
		return( false );
	m_nLastError = GL_SUCCESS;
	return( true );
}

bool CImageObject::DrawToHdc(HDC pHdc, int nDestX ,int nDestY ,int nDestWidth,int nDestHeight)
{
	if( nDestX != -1 )
		m_nX = nDestX;
	if( nDestY != -1 )
		m_nY = nDestY;
	if(nDestWidth != 0)
		m_nDestWidth = nDestWidth;
	if(nDestHeight != 0)
		m_nDestHeight = nDestHeight;
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( false );
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return( NULL );
	BITMAPINFOHEADER *pBIH;
	pBIH = ( BITMAPINFOHEADER * )&pTemp[ sizeof( BITMAPFILEHEADER ) ];
	::SetStretchBltMode(pHdc, COLORONCOLOR);
	int nRet = ::StretchDIBits( pHdc, m_nX, m_nY, m_nDestWidth, m_nDestHeight,
		                        0, 0, m_nWidth, m_nHeight,	
		                        (const void FAR *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nPaletteInBytes], 
		                        (BITMAPINFO *) pBIH,
								DIB_RGB_COLORS, 
								SRCCOPY );
	::GlobalUnlock( m_hDib );
	m_nLastError = GL_STRETCHDIBITS_ERROR;
	if( nRet != m_nHeight )
		return( false );
	m_nLastError = GL_SUCCESS;
	return( true );
}
//////////////////////////////////////////
// Basic private member functions
//
void CImageObject::LoadImageHeader( void )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return;
	char *pTemp;
	BITMAPINFOHEADER *pBIH;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return;

	BITMAPFILEHEADER * pBFH;
	pBFH = (BITMAPFILEHEADER *) pTemp;
	WORD bfType = pBFH->bfType;

	pBIH = ( BITMAPINFOHEADER * )&pTemp[ sizeof( BITMAPFILEHEADER ) ];
	m_nWidth = pBIH->biWidth;
	m_nHeight = pBIH->biHeight;
	m_nPlanes = pBIH->biPlanes;
	m_nBits = pBIH->biBitCount;
	m_nColors = 1 << m_nBits;

//	DWORD tmp = pBIH->biClrUsed;
//
//    LONG PIX = pBIH->biXPelsPerMeter;
//	LONG PIY = pBIH->biYPelsPerMeter;


	if( m_nPlanes > 1 )
		m_nColors <<= ( m_nPlanes - 1 );
	if( m_nBits >= 16 )
		m_nColors = 0;
	::GlobalUnlock( m_hDib );
	m_nLastError = GL_SUCCESS;
}

void CImageObject::LoadPalette( void )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return;
	CWindowDC WindowDC( NULL );
	m_nScreenPlanes = WindowDC.GetDeviceCaps( PLANES );
	m_nScreenBits = WindowDC.GetDeviceCaps( BITSPIXEL );
	m_nPaletteInBytes = 0;
	m_Palette.DeleteObject();
	if( m_nBits <= 8 )
		m_nPaletteInBytes = m_nColors * sizeof( RGBQUAD );
	if( m_nScreenBits >= 16 )
		return;
	char *pTemp;
	pTemp = ( char * )::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return;
	if( m_nBits <= 8 )
	{
		RGBQUAD *pRGBPalette;
		pRGBPalette = ( RGBQUAD * )&pTemp[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ];
		LOGPALETTE *pPalette;
		pPalette = CreateLogPalette( pRGBPalette, m_nColors );
		if( pPalette == NULL )
		{
			m_nLastError = GL_LOGICAL_PALETTE_CREATION_ERROR;
			// These statements are inserted by June.
			::GlobalUnlock( m_hDib );
			return;
			//goto LoadPaletteExit;
		}
		m_Palette.CreatePalette( pPalette );
		delete[] pPalette;
	}
	m_nLastError = GL_SUCCESS; 
//LoadPaletteExit:
	::GlobalUnlock( m_hDib );
}

void CImageObject::DestroyImage( void )
{
// add by maple
	if( m_pDib)
		::GlobalUnlock(m_hDib);
	m_pDib = NULL;
//---------------------------------------
	if( m_hDib )
		::GlobalFree( m_hDib );
	m_hDib = NULL;

	if( m_pLogPalette != NULL )
		delete[] m_pLogPalette;
	m_pLogPalette = NULL;
	if( m_pszFileName != NULL )
		delete[] m_pszFileName;
	m_pszFileName = NULL;
	m_Palette.DeleteObject();
}

LOGPALETTE *CImageObject::CreateLogPalette( RGBQUAD *pPalette, int nNumColors )
{
	LOGPALETTE *pLogPalette;
	int i;
	if( pPalette == NULL )
		return( NULL );
	pLogPalette = ( LOGPALETTE * )new char[ sizeof( LOGPALETTE ) + nNumColors * sizeof( PALETTEENTRY ) ];
	if( pLogPalette == NULL )
		return( NULL );
	pLogPalette->palVersion = 0x300;
	pLogPalette->palNumEntries = ( unsigned short )nNumColors;
	for( i=0; i<nNumColors; i++ )
	{
		pLogPalette->palPalEntry[ i ].peRed = pPalette[ i ].rgbRed;
		pLogPalette->palPalEntry[ i ].peGreen = pPalette[ i ].rgbGreen;
		pLogPalette->palPalEntry[ i ].peBlue = pPalette[ i ].rgbBlue;
		pLogPalette->palPalEntry[ i ].peFlags = 0;
	}
	return( pLogPalette );
}

void *CImageObject::GetDIBPointer( int *nWidthBytes, int nNewBits, int *nNewWidthBytes, int nNewWidth )
{
	m_nLastError = GL_HDIB_NULL;
	if( m_hDib == NULL )
		return( NULL );
	void *pTemp;
	pTemp = ::GlobalLock( m_hDib );
	m_nLastError = GL_MEMORY_LOCK_ERROR;
	if( pTemp == NULL )
		return( NULL );
	if( nWidthBytes != NULL )
		*nWidthBytes = GetWidthInBytes( m_nBits, m_nWidth );
	if( nNewWidthBytes != NULL )
	{
		if( nNewWidth == -1 )
			nNewWidth = m_nWidth;
		*nNewWidthBytes = GetWidthInBytes( nNewBits, nNewWidth );
	}
	return( pTemp );
}

int CImageObject::GetWidthInBytes( int nBits, int nWidth )
{
	int nWidthBytes;
	nWidthBytes = nWidth;
	if( nBits == 1 )
		nWidthBytes = ( nWidth + 7 ) / 8;
	else if( nBits == 4 )
		nWidthBytes = ( nWidth + 1 ) / 2;
	else if( nBits == 16 )
		nWidthBytes = nWidth * 2;
	else if( nBits == 24 )
		nWidthBytes = nWidth * 3;
	else if( nBits == 32 )
		nWidthBytes = nWidth * 4;
	while( ( nWidthBytes & 3 ) != 0 )
		nWidthBytes++;
	return( nWidthBytes );
}

int CImageObject::GetNearestIndex( unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue, RGBQUAD *pRGBPalette, int nColors )
{
	int i, Index = 0;
	DWORD NewDiff, Diff = 100000L;
	DWORD dwRed, dwGreen, dwBlue;
	for( i=0; i<nColors; i++ )
	{
		if( ucRed > pRGBPalette[ i ].rgbRed )
			dwRed = ( DWORD )( pRGBPalette[ i ].rgbRed - ucRed );
		else
			dwRed = ( DWORD )( ucRed - pRGBPalette[ i ].rgbRed );
		if( ucGreen > pRGBPalette[ i ].rgbGreen )
			dwGreen = ( DWORD )( pRGBPalette[ i ].rgbGreen - ucGreen );
		else
			dwGreen = ( DWORD )( ucGreen - pRGBPalette[ i ].rgbGreen );
		if( ucBlue > pRGBPalette[ i ].rgbBlue )
			dwBlue = ( DWORD )( pRGBPalette[ i ].rgbBlue - ucBlue );
		else
			dwBlue = ( DWORD )( ucBlue - pRGBPalette[ i ].rgbBlue );
		NewDiff = ( dwRed * dwRed ) + ( dwGreen * dwGreen ) + ( dwBlue * dwBlue );
		if( NewDiff < Diff )
		{
			if( NewDiff <= 1 ) 
				return( i );
			Diff = NewDiff;
			Index = i;
		}
	}
	return( Index );
}

void CImageObject::CreatePaletteFromDIB( RGBQUAD *pRGBPalette, int nColors )
{
	if( pRGBPalette != NULL )
	{
		LOGPALETTE *pPalette;
		pPalette = CreateLogPalette( pRGBPalette, nColors );
		if( pPalette != NULL )
		{
			m_Palette.CreatePalette( pPalette );
			delete[] pPalette;
		}
		else
			m_nLastError = GL_LOGICAL_PALETTE_CREATION_ERROR;
	}
}

LOGPALETTE *CImageObject::CreatePaletteFromBitmap( int nColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
{
	RGBQUAD *pRGBPalette;
	if( nBits != 8 && m_nPaletteCreationType == JGPT_POPULARITY_PALETTE )
		pRGBPalette = GeneratePopularityPalette( nColors, pBits, nBits, nWidth, nHeight );
	else if( nBits != 8 && m_nPaletteCreationType == JGPT_MEDIAN_CUT_PALETTE )
		pRGBPalette = GenerateMedianCutPalette( nColors, pBits, nBits, nWidth, nHeight );
	else if( m_nPaletteCreationType == JGPT_FIXED_PALETTE )
		pRGBPalette = GenerateFixedPalette( nColors );
	if( pRGBPalette == NULL )
		return( NULL );
	LOGPALETTE *pLogPalette = CreateLogPalette( pRGBPalette, nColors );
	delete[] pRGBPalette;
	return( pLogPalette );
}

RGBQUAD *CImageObject::GeneratePopularityPalette( int nColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
{
	RGBQUAD *pRGBQuad = new RGBQUAD[ nColors ];
	if( pRGBQuad == NULL )
		return( GenerateFixedPalette( nColors ) );
	memset( pRGBQuad, 0, nColors * sizeof( RGBQUAD ) );
	BYTE bzColorMap[ 256 ][ 3 ];
	if( !::Popularity( pBits, nBits, nWidth, nHeight, bzColorMap ) )
	{
		delete[] pRGBQuad;
		return( GenerateFixedPalette( nColors ) );
	}
	for( int i=0; i<nColors; i++ )
	{
		pRGBQuad[ i ].rgbRed = bzColorMap[ i ][ 0 ];
		pRGBQuad[ i ].rgbGreen = bzColorMap[ i ][ 1 ];
		pRGBQuad[ i ].rgbBlue = bzColorMap[ i ][ 2 ];
	}
	return( pRGBQuad );
}

RGBQUAD *CImageObject::GenerateMedianCutPalette( int nColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
{
	RGBQUAD *pRGBQuad = new RGBQUAD[ nColors ];
	if( pRGBQuad == NULL )
		return( GenerateFixedPalette( nColors ) );
	memset( pRGBQuad, 0, nColors * sizeof( RGBQUAD ) );
	BYTE bzColorMap[ 256 ][ 3 ];
	WORD *Hist = new WORD[ 32768 ];
	if( Hist == NULL )
	{
		delete [] pRGBQuad;
		return( GenerateFixedPalette( nColors ) );
	}
	memset( Hist, 0, 32768 * sizeof( WORD ) );
	int nWidthBytes = GetWidthInBytes( nBits, nWidth );

	for( int y=0; y<nHeight; y++ )
	{
		unsigned char *pData = pBits;
		unsigned char ucRed, ucGreen, ucBlue;
		WORD wColor;
		pData += ( y * nWidthBytes );
		for( int x=0; x<nWidth; x++ )
		{
			switch( nBits )
			{
				case 16:
					GET_RGB_16( ucRed, ucGreen, ucBlue, &pData[ 2*x ] );
					break;
				case 24:
					ucRed = pData[ 3*x + 2 ];
					ucGreen = pData[3*x + 1 ];
					ucBlue = pData[ 3*x ];
					break;
				case 32:
					GET_RGB_32( ucRed, ucGreen, ucBlue, &pData[ 4*x ] );
					break;
			}
			wColor = _RGB( ucRed, ucGreen, ucBlue );
			if( Hist[ wColor ] < 65535 )
				Hist[ wColor ]++;
		}
	}
	
	::MedianCut( Hist, bzColorMap, ( int )256 );
	for( int i=0; i<nColors; i++ )
	{
		pRGBQuad[ i ].rgbRed = bzColorMap[ i ][ 0 ];
		pRGBQuad[ i ].rgbGreen = bzColorMap[ i ][ 1 ];
		pRGBQuad[ i ].rgbBlue = bzColorMap[ i ][ 2 ];
	}
	delete[] Hist;
	return( pRGBQuad );
}

RGBQUAD *CImageObject::GenerateFixedPalette( int nColors )
{
	RGBQUAD *pRGBQuad = new RGBQUAD[ nColors ];
	if( pRGBQuad == NULL )
		return( NULL );
	static int nzColors[] = {	255, 255, 255,   0,   0,   0, 255,   0,   0,   0,   0, 255,
		                          0, 255,   0, 150, 150, 150, 255, 255,		0,   0, 150, 150,
								  					150,   0, 150, 150, 150,   0,   0, 255, 255, 255,   0, 255,
									  				255, 120, 120, 120, 255, 120,	120, 120, 255,	90,  90,  90 };
	int nSteps = ( ( nColors + 15 ) / 16 );
	for( int i=0; i<nSteps; i++ )
	{
		for( int j=0; j<16; j++ )
		{
			if( i * 16 + j < nColors )
			{
				int r, g, b;
				r = nzColors[ 3*j ];
				g = nzColors[ 3*j + 1 ];
				b = nzColors[ 3*j + 2 ];
				r = ( ( nSteps - i ) * r ) / nSteps;
				g = ( ( nSteps - i ) * g ) / nSteps;
				b = ( ( nSteps - i ) * b ) / nSteps;
				pRGBQuad[ 16*i + j ].rgbRed = ( unsigned char )r;
				pRGBQuad[ 16*i + j ].rgbGreen = ( unsigned char )g;
				pRGBQuad[ 16*i + j ].rgbBlue = ( unsigned char )b;
			}
		}
	}
	return( pRGBQuad );
}

// Diagnostics and dump member functions, overrided
#ifdef _DEBUG
void CImageObject::Dump( CDumpContext& dc ) const
{
  // call base class function first
  CObject::Dump( dc );
  // now do the stuff for our specific class
//  dc << "last name: " << m_lastName << "\n" << "first name: " << m_firstName << "\n";
}

void CImageObject::AssertValid() const
{ 
	// call inherited AssertValid first
  CObject::AssertValid();
	// check CImageObject members...
//  ASSERT( !m_strName.IsEmpty()); // Must have a name
//  ASSERT( m_salary > 0 ); // Must have an income
} 

#endif

/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:LoadDIBTOBuf
* 
*  参数:  BYTE * buf   --  传入的用于放置象素值的区域的指针 
*   
*  返回值:  bool
*
*  说明:    该函数将图象DIB中对应的象素值转移到m_buf中,变成同一格式,
*            便于处理。        
************************************************************************/

bool CImageObject::LoadDIBToBuf(BYTE * buf)
{
	if(m_hDib == NULL)
		return FALSE;

  	RGBQUAD color ;
	COLORREF colorref;

	if(m_pDib)
		m_pDib = (BYTE *)::GlobalUnlock(m_hDib);
	m_pDib = (BYTE *)::GlobalLock(m_hDib);

	if(m_pDib!=NULL)
	{
		for( int j=0; j<m_nHeight; j++)
			for(int i=0; i<m_nWidth; i++) 
			{
				color = GetPixelColor( i, j );
				colorref =RGB(color.rgbRed, color.rgbGreen, color.rgbBlue);
				unsigned long temp=(long)j*(long)m_nWidth*3+(long)i*3;
			  	    *(buf+temp)=GetBValue(colorref);
			        *(buf+temp+1)=GetGValue(colorref);
				    *(buf+temp+2)=GetRValue(colorref);
			}
	}

	::GlobalUnlock(m_hDib);
 
	return TRUE;	
}

/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:UpdateDIB
* 
*  参数:  int nNewWidth    -- 图象经过处理后新的宽度   
*            int nNewHeight   -- 图象经过处理后新的高度
* 
*  返回值:  bool
*
*  说明:    该函数用处理后的buf中的象素值来更新DIB,
*            并根据传入的新的高度和宽度来决定是否新建一DIB。            
************************************************************************/

bool CImageObject::UpdateDIB(int nNewWidth,int nNewHeight,BYTE * buf)
{
    // if the size of the image has no change,
	// we only need to update the old DIB.

	if(nNewWidth == m_nWidth && nNewHeight == m_nHeight)
	{
    	RGBQUAD color ;

 	    if(m_pDib!=NULL)
		    ::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);

	    if(m_pDib!=NULL)
		{
    	    for( int j=0; j<m_nHeight; j++)
		        for( int i=0; i<m_nWidth; i++)
				{   
			       unsigned long temp=(long)j*(long)m_nWidth*3+(long)i*3;
              	   BYTE r,g,b;
             	   b=*(buf+temp);
               	   g=*(buf+temp+1);
               	   r=*(buf+temp+2);

			       color.rgbRed   = r ;
			       color.rgbGreen = g;
			       color.rgbBlue  = b;
		    	   SetPixelColor( i, j, color ) ;
				} 
		    ::GlobalUnlock(m_hDib);
			return(true);
		}
		else
		{
		    ::GlobalUnlock(m_hDib);
			return(false);
		}


	}
	// the size of the image has been changed
	// we must create a new DIb to replace the old one.
	else   
	{
		RGBQUAD color ;
		HGLOBAL hNewDib;
		DWORD dwNewSize;
		BYTE * pNewBuf;
		BYTE * pNewBits;
		BITMAPFILEHEADER *pOldBFH,*pNewBFH;
		BITMAPINFOHEADER *pOldBIH,*pNewBIH;
		RGBQUAD *pOldPalette,*pNewPalette;

	    if(m_pDib!=NULL)
		    ::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);
		if(m_pDib==NULL)
		{
			::GlobalUnlock(m_hDib);
			return(false);
		}

		dwNewSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
			     +m_nColors*sizeof(RGBQUAD)+GetWidthInBytes(m_nBits,nNewWidth)*nNewHeight;
		hNewDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwNewSize);
		if(hNewDib==NULL)
		{
			::GlobalUnlock(m_hDib);
			return (false);
		}

		pNewBuf = (BYTE *)::GlobalLock(hNewDib);
		if(pNewBuf==NULL)
		{
            ::GlobalFree(hNewDib);
			::GlobalUnlock(m_hDib);
			return (false);
		}
   
		pOldBFH = (BITMAPFILEHEADER *)m_pDib;
		pOldBIH = (BITMAPINFOHEADER *)(m_pDib+sizeof(BITMAPFILEHEADER));
		pOldPalette = (RGBQUAD *)(m_pDib+sizeof(BITMAPFILEHEADER)+
			                   sizeof(BITMAPINFOHEADER));
		
		pNewBFH = (BITMAPFILEHEADER *) pNewBuf;
		pNewBIH = (BITMAPINFOHEADER *) (pNewBuf+sizeof(BITMAPFILEHEADER));
		pNewPalette = (RGBQUAD *)(pNewBuf+sizeof(BITMAPFILEHEADER)+
			                   sizeof(BITMAPINFOHEADER));
		pNewBits = pNewBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
			       +m_nColors*sizeof(RGBQUAD);

		*pNewBFH = *pOldBFH;
		*pNewBIH = *pOldBIH; 
        pNewBFH->bfSize = dwNewSize;
		pNewBIH->biWidth = (LONG)nNewWidth;
		pNewBIH->biHeight = (LONG)nNewHeight;
		pNewBIH->biSizeImage = (DWORD)GetWidthInBytes(m_nBits,nNewWidth)*nNewHeight;
  
		for(int k=0;k<m_nColors;k++)
            pNewPalette[k] = pOldPalette[k];
 
		// very important!!
        // if we miss the following two lines,the display of the image
  		m_nWidth = nNewWidth;         
		m_nHeight = nNewHeight; 
		
        m_nPlanes = pNewBIH->biPlanes;      
		m_nBits = pNewBIH->biBitCount;
		m_nColors = pNewBIH->biClrUsed;
		m_nPaletteInBytes = m_nColors*sizeof(RGBQUAD);
		
		
		// will be wrong!
		::GlobalUnlock(m_hDib);
		::GlobalFree(m_hDib);
		::GlobalUnlock(hNewDib);
		SetDib(hNewDib);
       		
	    if(m_pDib)
		    m_pDib = (BYTE *)::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);

	    if(m_pDib!=NULL)
		{
    	    for( int j=0; j<m_nHeight; j++)
		        for( int i=0; i<m_nWidth; i++)
				{   
			       unsigned long temp=(long)j*(long)m_nWidth*3+(long)i*3;
              	   BYTE r,g,b;
             	   b=*(buf+temp);
               	   g=*(buf+temp+1);
               	   r=*(buf+temp+2);

			       color.rgbRed   = r ;
			       color.rgbGreen = g;
			       color.rgbBlue  = b;
		    	   SetPixelColor( i, j, color ) ;
				} 

	        ::GlobalUnlock(m_hDib);
     	    return TRUE;
		}
		else
		{
			::GlobalUnlock(m_hDib);
			return(false);
		}
	}

}



/***********************************************************************
*  Description: this function was added by maple,2004.3.22
*
*  函数名称:CreatDIBFromBits
* 
*  参数:  int nWidth    -- 要新建的图象的宽度   
*            int nHeight   -- 要新建的图象的高度
*            BYTE * buf    -- 存放象素值的内存区域指针
* 
*  返回值:  bool
*
*  说明:    该函数利用一块存放象素值的内存区域来创建一个DIB,所
*            创建的图象是24位位图。            
************************************************************************/


bool CImageObject::CreateDIBFromBits(int nWidth,int nHeight,BYTE * buf)
{
    RGBQUAD color;
	HGLOBAL hDib;
	DWORD dwSize;
	BYTE * pBuf;
	BITMAPFILEHEADER *pBFH;
	BITMAPINFOHEADER *pBIH;

	dwSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
			 +GetWidthInBytes(24,nWidth)*nHeight;
	hDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwSize);
	if(hDib==NULL)
	{
		return (false);
	}
	
	pBuf = (BYTE *)::GlobalLock(hDib);
	if(pBuf==NULL)
	{
		::GlobalFree(hDib);
		return (false);
	}
	pBFH = (BITMAPFILEHEADER *) pBuf;
	pBIH = (BITMAPINFOHEADER *) (pBuf+sizeof(BITMAPFILEHEADER));
    
	pBFH->bfType = (WORD)19778;
	pBFH->bfSize = (DWORD)dwSize;
	pBFH->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
	
	pBIH->biSize = (DWORD)40;
	m_nWidth = pBIH->biWidth = (LONG)nWidth;
	m_nHeight = pBIH->biHeight = (LONG)nHeight;
	m_nPlanes = pBIH->biPlanes = (WORD)1;
	m_nBits = pBIH->biBitCount = (WORD)24;
	pBIH->biCompression = BI_RGB;
	pBIH->biSizeImage = (DWORD)GetWidthInBytes(24,nWidth)*nHeight;
//	pBIH->biXPelsPerMeter = (LONG)4724;
//	pBIH->biYPelsPerMeter = (LONG)4724; 
    m_nColors = pBIH->biClrUsed = (DWORD)0;
	pBIH->biClrImportant = (DWORD)0;

	m_nPaletteInBytes = 0;     // used in Draw() 

	::GlobalUnlock(hDib);
	SetDib(hDib);
	
	if(m_pDib)
		m_pDib = (BYTE *)::GlobalUnlock(m_hDib);
	m_pDib = (BYTE *)::GlobalLock(m_hDib);
	
	if(m_pDib!=NULL)     
	{
		BYTE * pBits = m_pDib+sizeof(BITMAPFILEHEADER)
			+sizeof(BITMAPINFOHEADER);

		for( int k=0; k<GetWidthInBytes(24,nWidth)*nHeight; k++)
			pBits[k] = 0;

		for( int j=0; j<m_nHeight; j++)
			for( int i=0; i<m_nWidth; i++)
			{   
 				unsigned long temp=(long)j*(long)m_nWidth*3+(long)i*3;				
				BYTE r,g,b;
				b=*(buf+temp);
				g=*(buf+temp+1);
				r=*(buf+temp+2);
				
				color.rgbRed   = r ;
				color.rgbGreen = g;
				color.rgbBlue  = b;
				SetPixelColor( i, j, color ) ;
			} 
			
			::GlobalUnlock(m_hDib);
			return TRUE;
	}
	else
	{
		::GlobalUnlock(m_hDib);
		return(false);
	}
}


/***********************************************************************
*  Description: this function was added by maple,2004.3.22
*
*  函数名称:CreatFromHANDLE
* 
*  参数:  HANDLE handle    -- 要新建的图象的宽度   
*
*  返回值:  bool
*
*  说明:    该函数利用从剪贴板获得的标准DIB句柄创建一个用于
*            该ImageObject的包含BITMAPFILEHEADER的DIB。            
************************************************************************/

bool CImageObject::CreateFromHANDLE(HANDLE handle)
{

	HANDLE hDib;
	BYTE * pBuf,*pTemp;
	BITMAPFILEHEADER *pBFH;
	BITMAPINFOHEADER *pBIH;
	DWORD size = ::GlobalSize(handle);
	DWORD dwSize = ::GlobalSize(handle)+sizeof(BITMAPFILEHEADER);
	hDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwSize);
	if(hDib==NULL)
	{
		return (false);
	}
	pBuf = (BYTE *)::GlobalLock(hDib);
	if(pBuf==NULL)
	{
		::GlobalFree(hDib);
		return(false);
	}
	pTemp = (BYTE *)::GlobalLock(handle);
	if(pTemp==NULL)
	{
		return (false);
	}

    pBFH = (BITMAPFILEHEADER *)pBuf;
	pBFH->bfType = (WORD)19778;
	pBFH->bfSize = (DWORD)dwSize;
	pBFH->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);


	memcpy(pBuf+sizeof(BITMAPFILEHEADER),pTemp,size);

	pBIH = (BITMAPINFOHEADER *)(pBuf+sizeof(BITMAPFILEHEADER));
	m_nWidth = pBIH->biWidth;
	m_nHeight = pBIH->biHeight;
	m_nPlanes = pBIH->biPlanes;
	m_nBits = pBIH->biBitCount;
	m_nColors = pBIH->biClrUsed;
	m_nPaletteInBytes = m_nColors*sizeof(RGBQUAD);
    
	::GlobalUnlock(handle);
    ::GlobalUnlock(hDib); 
	SetDib(hDib);

	return(TRUE);
}


/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:GetPixelColor
* 
*  参数:  int x    -- 图象的横坐标   
*            int y    -- 图象的纵坐标
* 
*  返回值:  RGBQUAD  -- 点(x,y)处对应的RGBQUAD结构的象素值 
*
*  说明:    该函数用于获取(x,y)处的象素值,
*            被LoadDIBToBuf()所调用或者单独使用          
************************************************************************/

RGBQUAD CImageObject::GetPixelColor(int x,int y)
{
	RGBQUAD rgb;
	rgb.rgbBlue = rgb.rgbGreen = rgb.rgbRed = rgb.rgbReserved = 0;
    if(m_pDib == NULL)
		return rgb;

    y = m_nHeight -1 - y;  // add by maple,2004.5.14
	
	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);
    
	if (m_nColors)
	{   
		BYTE tmp;
		tmp = GetPixelIndex(x,y);
	    rgb = GetPaletteColor(tmp);
	} 
	else
	{
		BYTE* iDst  = pBits + y*GetWidthInBytes(m_nBits,m_nWidth) + x*3;
		rgb.rgbBlue = *iDst++;
		rgb.rgbGreen= *iDst++;
		rgb.rgbRed  = *iDst;
    	rgb.rgbReserved =(BYTE) 0;
	}

	return rgb;
}



/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:GetPaletteColor
* 
*  参数:  BYTE idx -- 调色板中对应的下标 值
* 
*  返回值:  RGBQUAD  -- 点(x,y)处对应的RGBQUAD结构的象素值 
*
*  说明:    该函数用于调色板中下标 idx 对应的RGBQUAD,被 GetPixelColor()调用        
************************************************************************/

RGBQUAD CImageObject::GetPaletteColor(BYTE idx)
{
	RGBQUAD rgb = {0,0,0,0};
	
	if ((m_pDib)&&(m_nColors))
	{
		BYTE* iDst = (BYTE*)(m_pDib +sizeof(BITMAPFILEHEADER)
			         +sizeof(BITMAPINFOHEADER));
		if (idx<m_nColors)
		{
			long ldx=idx*sizeof(RGBQUAD);
			rgb.rgbBlue = iDst[ldx++];
			rgb.rgbGreen=iDst[ldx++];
			rgb.rgbRed =iDst[ldx++];
			rgb.rgbReserved = iDst[ldx];
		}
	}

	return rgb;
}

/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:GetPixelIndex
* 
*  参数:  int x    -- 横坐标
*            int y    -- 纵坐标
* 
*  返回值:  BYTE     -- 点(x,y)的象素值在调色板中的下标
*
*  说明:    该函数用于获取(x,y)的象素值在调色板中的下标。
*            被函数 GetPaletteColor()所调用       
************************************************************************/

BYTE CImageObject::GetPixelIndex(int x,int y)
{

    if ((m_pDib==NULL)||(m_nColors==0)) return 0;

	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);
	   
	if (m_nBits==8)
	{
		return (BYTE)*(pBits+y*GetWidthInBytes(m_nBits,m_nWidth)+x);
	}
	else 
	{
		BYTE pos;
		BYTE iDst= (BYTE)*(pBits+y*GetWidthInBytes(m_nBits,m_nWidth)+(x*m_nBits >> 3));
		if (m_nBits==4)
		{
			pos = (BYTE)(4*(1-x%2));
			iDst &= (0x0F<<pos);
			return (BYTE)(iDst >> pos);
		} 
		else if (m_nBits==1)
		{
			pos = (BYTE)(7-x%8);
			iDst &= (0x01<<pos);
			
			return (BYTE)(iDst >> pos);
		}
	}
	   
	return 0;
}


/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:SetPixelColor
* 
*  参数:  int x            -- 横坐标
*            int y            -- 纵坐标
*            RGBQUAD  color   -- RGBQUAD结构的调色板象素值
* 
*  返回值:  void     
*
*  说明:    该函数用color中对应的象素值代替(x,y)对应的象素值 
*            被函数UpdateDIB(所调用
************************************************************************/

void CImageObject:: SetPixelColor(int x,int y,RGBQUAD color)
{
    if ((m_pDib==NULL)||(x<0)||(y<0)||
		  (x>=m_nWidth)||(y>=m_nHeight)) 
	return;

	y = m_nHeight -1 - y;   // add by maple, 2004.5.14
	
	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);

	if (m_nColors)
		SetPixelIndex(x,y,GetNearestIndex(color));
	else 
	{
		BYTE* iDst = pBits + y*GetWidthInBytes(m_nBits,m_nWidth) + x*3;
		*iDst++ = color.rgbBlue;
		*iDst++ = color.rgbGreen;
		*iDst   = color.rgbRed;
	}
}



/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:SetPixelIndex
* 
*  参数:  int x            -- 横坐标
*            int y            -- 纵坐标
*            BYTE index       -- (x,y)中象素值所对应的在调色板中的下标
* 
*  返回值:  void     
*
*  说明:    该函数用下标index来替换原DIB中的索引
*            被函数SetPixelColor()所调用
************************************************************************/

void CImageObject::SetPixelIndex(int x,int y,BYTE index)
{

	if ((m_pDib==NULL)||(m_nColors==0)||
		(x<0)||(y<0)||(x>=m_nWidth)||(y>=m_nHeight)) return ;

	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);
	
	if (m_nBits==8)
	{
	    *(pBits+y*GetWidthInBytes(m_nBits,m_nWidth) + x)=index;
		return;
	} 
	else 
	{
		BYTE pos;
		BYTE* iDst= pBits + y*GetWidthInBytes(m_nBits,m_nWidth) + (x*m_nBits >> 3);
		if (m_nBits==4)
		{
			pos = (BYTE)(4*(1-x%2));
			*iDst &= ~(0x0F<<pos);
			*iDst |= ((index & 0x0F)<<pos);
			return;
		} 
		else if (m_nBits==1)
		{
			pos = (BYTE)(7-x%8);
			*iDst &= ~(0x01<<pos);
			*iDst |= ((index & 0x01)<<pos);
			return;
		}
	}	
}


/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:GetNearestIndex
* 
*  参数:  RGBQUAD color  -- 调色板的一个单元结构
*
*  返回值:  BYTE           -- 输入调色板单元所对应的索引
*
*  说明:    该函数用来得到输入调色板单元所对应的索引,
*            它作为函数 SetPixelIndex()的一个参数被调用。
************************************************************************/

BYTE CImageObject::GetNearestIndex(RGBQUAD color)
{

	if ((m_pDib==NULL)||(m_nColors==0)) return 0;

	BYTE* iDst = m_pDib+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
	long distance=200000;
	int i,j=0;
	long k,l;

	for(i=0,l=0;i<m_nColors;i++,l+=sizeof(RGBQUAD))
	{
		k = (iDst[l]-color.rgbBlue)*(iDst[l]-color.rgbBlue)+
			(iDst[l+1]-color.rgbGreen)*(iDst[l+1]-color.rgbGreen)+
			(iDst[l+2]-color.rgbRed)*(iDst[l+2]-color.rgbRed);
//		k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed);
		if (k==0)
		{
			j=i;
			break;
		}
		if (k<distance){
			distance=k;
			j=i;
		}
	} 
	
	return (BYTE)j;
}

////////////////////////////////////////////////////////////////////////
//  以下四个函数专用于256色灰度图象
////////////////////////////////////////////////////////////////////////

/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:LoadDIBTOBuf2
* 
*  参数:  BYTE * buf   --  传入的用于放置象素值的区域的指针 
*   
*  返回值:  bool
*
*  说明:    该函数专用于256色灰度图象,DIB中对应的象素值转移到m_buf中,
*            每个点的象素值占一个字节。        
************************************************************************/

bool CImageObject::LoadDIBToBuf2(BYTE * buf)
{
	if(m_hDib == NULL)
		return false;
	if(m_pDib)
		m_pDib = (BYTE *)::GlobalUnlock(m_hDib);
	m_pDib = (BYTE *)::GlobalLock(m_hDib);

	if(m_pDib!=NULL)
	{
		int nWidthInBytes = GetWidthInBytes(m_nBits,m_nWidth);
		for( int j=0; j<m_nHeight; j++)
			for(int i=0; i<m_nWidth; i++) 
			{
			   *(buf+j*m_nWidth+i) = GetPixelColor2(i,j);
			}
	}

	::GlobalUnlock(m_hDib);
 
	return true;		
}



/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:UpdateDIB2
* 
*  参数:  int nNewWidth    -- 图象经过处理后新的宽度   
*            int nNewHeight   -- 图象经过处理后新的高度
* 
*  返回值:  bool
*
*  说明:    更新256灰度图象的DIB 
*            该函数用处理后的buf中的象素值来更新DIB,
*            并根据传入的新的高度和宽度来决定是否新建一DIB。            
************************************************************************/

bool CImageObject::UpdateDIB2(int nNewWidth,int nNewHeight,BYTE * buf)
{
    // if the size of the image has no change,
	// we only need to update the old DIB.

	if(nNewWidth == m_nWidth && nNewHeight == m_nHeight)
	{
 	    if(m_pDib!=NULL)
		    ::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);

	    if(m_pDib!=NULL)
		{
			BYTE color;
    	    for( int j=0; j<m_nHeight; j++)
		        for( int i=0; i<m_nWidth; i++)
				{   
                   color = *(buf+j*m_nWidth+i);
		    	   SetPixelColor2( i, j, color ) ;
				} 
		    ::GlobalUnlock(m_hDib);
			return(true);
		}
		else
		{
		    ::GlobalUnlock(m_hDib);
			return(false);
		}


	}
	// the size of the image has been changed
	// we must create a new DIb to replace the old one.
	else   
	{
		HGLOBAL hNewDib;
		DWORD dwNewSize;
		BYTE * pNewBuf;
		BYTE * pNewBits;
		BITMAPFILEHEADER *pOldBFH,*pNewBFH;
		BITMAPINFOHEADER *pOldBIH,*pNewBIH;
		RGBQUAD *pOldPalette,*pNewPalette;

	    if(m_pDib!=NULL)
		    ::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);
		if(m_pDib==NULL)
		{
			::GlobalUnlock(m_hDib);
			return(false);
		}

		dwNewSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
			     +m_nColors*sizeof(RGBQUAD)+GetWidthInBytes(m_nBits,nNewWidth)*nNewHeight;
		hNewDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwNewSize);
		if(hNewDib==NULL)
		{
			::GlobalUnlock(m_hDib);
			return (false);
		}

		pNewBuf = (BYTE *)::GlobalLock(hNewDib);
		if(pNewBuf==NULL)
		{
            ::GlobalFree(hNewDib);
			::GlobalUnlock(m_hDib);
			return (false);
		}
   
		pOldBFH = (BITMAPFILEHEADER *)m_pDib;
		pOldBIH = (BITMAPINFOHEADER *)(m_pDib+sizeof(BITMAPFILEHEADER));
		pOldPalette = (RGBQUAD *)(m_pDib+sizeof(BITMAPFILEHEADER)+
			                   sizeof(BITMAPINFOHEADER));
		
		pNewBFH = (BITMAPFILEHEADER *) pNewBuf;
		pNewBIH = (BITMAPINFOHEADER *) (pNewBuf+sizeof(BITMAPFILEHEADER));
		pNewPalette = (RGBQUAD *)(pNewBuf+sizeof(BITMAPFILEHEADER)+
			                   sizeof(BITMAPINFOHEADER));
		pNewBits = pNewBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
			       +m_nColors*sizeof(RGBQUAD);

		*pNewBFH = *pOldBFH;
		*pNewBIH = *pOldBIH; 
        pNewBFH->bfSize = dwNewSize;
		pNewBIH->biWidth = (LONG)nNewWidth;
		pNewBIH->biHeight = (LONG)nNewHeight;
		pNewBIH->biSizeImage = (DWORD)GetWidthInBytes(m_nBits,nNewWidth)*nNewHeight;
  
		for(int k=0;k<m_nColors;k++)
            pNewPalette[k] = pOldPalette[k];
 
		// very important!!
        // if we miss the following two lines,the display of the image
  		m_nWidth = nNewWidth;         
		m_nHeight = nNewHeight; 
		
        m_nPlanes = pNewBIH->biPlanes;      
		m_nBits = pNewBIH->biBitCount;
		m_nColors = pNewBIH->biClrUsed;
		m_nPaletteInBytes = m_nColors*sizeof(RGBQUAD);
		
		
		// will be wrong!
		::GlobalUnlock(m_hDib);
		::GlobalFree(m_hDib);
		::GlobalUnlock(hNewDib);
		SetDib(hNewDib);
       		
	    if(m_pDib)
		    m_pDib = (BYTE *)::GlobalUnlock(m_hDib);
	    m_pDib = (BYTE *)::GlobalLock(m_hDib);

	    if(m_pDib!=NULL)
		{
    	    BYTE color;
			for( int j=0; j<m_nHeight; j++)
		        for( int i=0; i<m_nWidth; i++)
				{  
					color = *(buf+j*m_nWidth+i);
		    	    SetPixelColor2( i, j, color ) ;
				} 
	        ::GlobalUnlock(m_hDib);
     	    return TRUE;
		}
		else
		{
			::GlobalUnlock(m_hDib);
			return(false);
		}
	}

}

/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:GetPixelColor2
* 
*  参数:  int x    -- 图象的横坐标   
*            int y    -- 图象的纵坐标
* 
*  返回值:  RGBQUAD  -- 点(x,y)处对应的RGBQUAD结构的象素值 
*
*  说明: 此函数专用于256色灰度图象,用于获取(x,y)处的象素值,   
*         被LoadDIBToBuf()所调用或者单独使用   
************************************************************************/
BYTE CImageObject::GetPixelColor2(int x,int y)
{
    if(m_pDib == NULL)
		return (BYTE)0;
   
	y = m_nHeight -1 - y;   // add by maple, 2004.5.14
	
	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);
	BYTE tmpColor;
	    tmpColor = * (pBits + y*GetWidthInBytes(m_nBits,m_nWidth) + x);
	return tmpColor;

}


/***********************************************************************
*  Description: this function was added by maple,2004.3.18
*
*  函数名称:SetPixelColor2
* 
*  参数:  int x            -- 横坐标
*            int y            -- 纵坐标
*            BYTE  color      -- 指定坐标对应的象素值  
* 
*  返回值:  void     
*
*  说明:    该函数专用于256色灰度图象, 
*            用color中对应的象素值代替(x,y)对应的象素值, 
*            被函数UpdateDIB(所调用或者单独使用。
************************************************************************/

void CImageObject:: SetPixelColor2(int x,int y,BYTE color)
{
    if ((m_pDib==NULL)||(x<0)||(y<0)||
		  (x>=m_nWidth)||(y>=m_nHeight)) 
	return;
    
    y = m_nHeight -1 - y;   // add by maple, 2004.5.14

	BYTE * pBits = m_pDib + sizeof(BITMAPFILEHEADER)
		+ sizeof(BITMAPINFOHEADER) + m_nColors*sizeof(RGBQUAD);
 
	*(pBits+y*GetWidthInBytes(m_nBits,m_nWidth) + x) = color;		
}

/***********************************************************************
*  Description: this function was added by maple,2004.4.16
*
*  函数名称:SaveBMP()
*
*  参数:    const char * strPathName   -- 文件保存名
*            HGLOBAL hDib               -- 位图句柄
*
*  返回值:  BOOL
*
*  说明:   该函数用于代替 imageload.dll中的保存BMP的函数
************************************************************************/

BOOL CImageObject::SaveBMP(const char * strPathName, HGLOBAL hDib )
{
    if(hDib == NULL)
		return FALSE;
	BYTE * pDib;
	pDib = (BYTE *)::GlobalLock(hDib);
	if(pDib == NULL)
		return FALSE;

	// 得到文件长度
	long filelength = (long)::GlobalSize(hDib);
	CFile file(strPathName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);
   
	// 往文件里写图象数据
	file.Write(pDib,filelength);
	file.Close();

	::GlobalUnlock(hDib);
  
	return TRUE;	
}