www.pudn.com > chap_03.rar > DibObject.cpp
//DibObject.cpp
#include "stdafx.h"
#include "DibObject.h"
IMPLEMENT_DYNCREATE(CDibObject, CObject)
char *CDibObject::szExtensions[] = { ".BMP", ".GIF", ".PCX", ".TGA", ".JPG", ".TIF", "" };
//Diagnostics and dump member functions, overridden
#ifdef _DEBUG
void CDibObject::Dump(CDumpContext &dc) const
{
//call base class function first
CObject::Dump(dc);
//now do the stuff for our specific class
dc<<"File Name:"<m_nWidth;
m_nHeight = pDibObject->m_nHeight;
m_nPlanes = pDibObject->m_nPlanes;
m_nBits = pDibObject->m_nBits;
m_nColors = pDibObject->m_nColors;
m_nImageType = pDibObject->m_nImageType;
m_nX = pDibObject->m_nX;
m_nY = pDibObject->m_nY;
m_nLastError = pDibObject->m_nLastError;
m_nScreenPlanes = pDibObject->m_nScreenPlanes;
m_nScreenBits = pDibObject->m_nScreenBits;
m_nPaletteBytes = pDibObject->m_nPaletteBytes;
m_nQuality = pDibObject->m_nQuality;
m_nPaletteCreationType = pDibObject->m_nPaletteCreationType;
int nNumColors = m_nColors;
int nWidthBytes = WidthBytes( m_nBits, m_nWidth );
if( pDibObject->m_hDib != NULL )
{
DWORD dwSize = ::GlobalSize( pDibObject->m_hDib );
char *pData = (char *) ::GlobalLock( pDibObject->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 );
::GlobalUnlock( hGlobal );
m_hDib = hGlobal;
}
else ::GlobalFree( hGlobal );
}
::GlobalUnlock( pDibObject->m_hDib );
}
}
}
////////////////////////////////////////////////////////////////////////
//CDibObject类的构造函数
//----------------------------------------------------------------------
//基本功能:构造一个CDibObject对象。唯一的要求的一个参数是文件名。如果
// 给出了CDC设备上下文参数,图像加载后会立即在该设备上下文中显示
// 出来。如果给出了nX或nY参数,图像会显示在该坐标指定的位置,否
// 则,图像总是显示在坐标为(0, 0)的位置。
//----------------------------------------------------------------------
//参数说明:const char *pszFilename
// CDC *pDC,默认为NULL
// int nX,默认为-1
// int nY,默认为-1
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
CDibObject::CDibObject( const char *pszFilename,
CDC *pDC, int nX, int nY )
{
InitVars();
Load( pszFilename, pDC, nX, nY );
}
////////////////////////////////////////////////////////////////////////
//CDibObject类的析构函数
//----------------------------------------------------------------------
//基本功能:析构CDibObject对象,删除该对象中的图像及相应的变量
//----------------------------------------------------------------------
//参数说明:无
////////////////////////////////////////////////////////////////////////
CDibObject::~CDibObject()
{
if( m_hDib ) ::GlobalFree( m_hDib );
if( m_pszFilename != NULL ) delete [] m_pszFilename;
if( m_pLogPal != NULL ) delete [] m_pLogPal;
}
////////////////////////////////////////////////////////////////////////
//InitVars()函数
//----------------------------------------------------------------------
//基本功能:初始化CDibObject类内部变量
//----------------------------------------------------------------------
//参数说明:BOOL bFlag 标记类中是否有图像打开,默认值为FALSE
////////////////////////////////////////////////////////////////////////
void CDibObject::InitVars( BOOL bFlag )
{
m_nWidth = m_nHeight = m_nBits = m_nColors = m_nImageType = 0;
m_nX = m_nY = 0;
m_nLastError = 0;
m_hDib = NULL;
m_nPaletteCreationType = FIXED_PALETTE;
if( !bFlag )
{
m_pszFilename = NULL;
m_pLogPal = NULL;
}
m_nQuality = 50;
}
////////////////////////////////////////////////////////////////////////
//BOOL Load()
//----------------------------------------------------------------------
//基本功能:本函数把一个图像文件载入CDibObject类。必需的一个参数是文件
// 名。如果给出了CDC设备上下文参数,图像一加载就被绘制。如果给
// 出了nX或nY参数,图像将显示在该坐标指定的位置。否则,图像总是
// 显示在坐标为(0,0)的位置。
//----------------------------------------------------------------------
//参数说明:const char *pszFilename
// CDC *pDC,默认为NULL
// int nX,默认为-1
// int nY,默认为-1
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::Load( const char *pszFilename,
CDC *pDC, int nX, int nY )
{
//获取图像文件类型
m_nImageType = FileType( pszFilename );
if( m_nImageType == 0 )
{
m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
return( FALSE );
}
//删除已存在的图像
KillImage();
m_pszFilename = new char [strlen(pszFilename)+1];
if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
//根据文件类型调用ImageLoad.dll动态链接库中的相应函数打开图像文件
switch( m_nImageType )
{
case IMAGETYPE_BMP:
m_hDib = ::LoadBMP( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
case IMAGETYPE_GIF:
m_hDib = ::LoadGIF( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
case IMAGETYPE_JPG:
m_hDib = ::LoadJPG( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
case IMAGETYPE_PCX:
m_hDib = ::LoadPCX( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
case IMAGETYPE_TGA:
m_hDib = ::LoadTGA( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
case IMAGETYPE_TIF:
m_hDib = ::LoadTIF( pszFilename );
if( m_hDib == NULL ){
m_nLastError = ::GetLastPicLibError();
return( FALSE );
}
break;
}
//处理图像信息头
ProcessImageHeader();
//处理调色板
ProcessPalette();
//若传入了设备上下文指针,就在指定的设备上下文中绘制图像
if( pDC != NULL ) Draw( pDC, nX, nY );
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//BOOL GetImageInfo()
//----------------------------------------------------------------------
//基本功能:本函数获取图像宽度、高度、位平面数、每个像素点的位数、以及颜
// 色数的信息。值为NULL的参数将不被传入。
//----------------------------------------------------------------------
//参数说明:const char *pszFilename
// int *pnWidth, 默认为NULL
// int *pnHeight, 默认为NULL
// int *pnPlanes, 默认为NULL
// int *pnBitsPerPixel, 默认为NULL
// int *pnNumColors, 默认为NULL
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::GetImageInfo( const char *pszFilename, int *pnWidth,
int *pnHeight, int *pnPlanes, int *pnBitsPerPixel, int *pnNumColors )
{
int nImageType;
//获取图像文件类型
nImageType = FileType( pszFilename );
if( nImageType == 0 )
{
m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
return( FALSE );
}
//根据文件类型调用ImageLoad.dll动态链接库中的相应函数获取图像信息
switch( nImageType )
{
case IMAGETYPE_BMP:
return( ::GetBMPInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
case IMAGETYPE_GIF:
return( ::GetGIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
case IMAGETYPE_JPG:
return( ::GetJPGInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
case IMAGETYPE_PCX:
return( ::GetPCXInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
case IMAGETYPE_TGA:
return( ::GetTGAInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
case IMAGETYPE_TIF:
return( ::GetTIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
}
return( FALSE );
}
////////////////////////////////////////////////////////////////////////
//int GetLastError()
//----------------------------------------------------------------------
//基本功能:本函数返回所发生的最后一次CDibObject类错误。详细错误信息见
// "ImageErrors.h"头文件。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nErrorNumber
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::GetLastError( void )
{
return( m_nLastError );
}
////////////////////////////////////////////////////////////////////////
//BOOL Save()
//----------------------------------------------------------------------
//基本功能:本函数保存驻留于CDibObject对象中的当前图像(图像类型定义见
// GetImageType()函数。
//----------------------------------------------------------------------
//参数说明:const char *pszFilename
// int nType,默认为-1
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::Save( const char *pszFilename, int nType )
{
//若没有指定文件类型,则根据文件名判断其文件类型
if( nType == -1 ) nType = ExtensionIndex( pszFilename );
if( nType < IMAGETYPE_FIRSTTYPE || nType > IMAGETYPE_LASTTYPE ) return( FALSE );
m_nImageType = nType;
delete [] m_pszFilename;
m_pszFilename = new char [strlen(pszFilename)+1];
if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
//根据文件类型调用ImageLoad.dll动态链接库中的相应函数保存图像
switch( m_nImageType )
{
case IMAGETYPE_BMP:
return( ::SaveBMP( pszFilename, m_hDib ) );
break;
case IMAGETYPE_GIF:
return( ::SaveGIF( pszFilename, m_hDib ) );
break;
case IMAGETYPE_JPG:
return( ::SaveJPG( pszFilename, m_hDib, m_nQuality ) );
break;
case IMAGETYPE_PCX:
return( ::SavePCX( pszFilename, m_hDib ) );
break;
case IMAGETYPE_TGA:
return( ::SaveTGA( pszFilename, m_hDib ) );
break;
case IMAGETYPE_TIF:
return( ::SaveTIF( pszFilename, m_hDib ) );
break;
}
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//int ExtensionIndex()
//----------------------------------------------------------------------
//基本功能:本函数返回文件名指定的图像类型。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nWidth
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::ExtensionIndex( const char *pszFilename )
{
int Index = 0;
char *pszExtension;
pszExtension = (char *) &pszFilename[strlen(pszFilename)-4];
while( szExtensions[Index][0] )
{
if( !stricmp( pszExtension, szExtensions[Index] ) ) return( Index + 1 );
Index++;
}
return( -1 );
}
////////////////////////////////////////////////////////////////////////
//int GetWidth()
//----------------------------------------------------------------------
//基本功能:本函数返回图像的像素宽度数。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nWidth
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::GetWidth( void )
{
return( m_nWidth );
}
////////////////////////////////////////////////////////////////////////
//int GetHeight( void )
//----------------------------------------------------------------------
//基本功能:本函数返回图像的像素高度数。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nHeight
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::GetHeight( void )
{
return( m_nHeight );
}
////////////////////////////////////////////////////////////////////////
//int GetNumBits( void )
//----------------------------------------------------------------------
//基本功能:本函数返回图像的像素数:1、4、8、16、24、32。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nBits
////////////////////////////////////////////////////////////////////////
int CDibObject::GetNumBits( void )
{
return( m_nBits );
}
////////////////////////////////////////////////////////////////////////
//int GetNumColors( void )
//----------------------------------------------------------------------
//基本功能:本函数返回图像调色板中的颜色。图像为16位色或更高时返回值为0。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nColors
////////////////////////////////////////////////////////////////////////
int CDibObject::GetNumColors( void )
{
return( m_nColors );
}
////////////////////////////////////////////////////////////////////////
//BOOL GetPaletteData()
//----------------------------------------------------------------------
//基本功能:本函数将当前RGB调色板数据填入到所传入的指针中。如果图像是16
// 位色或更高时则不进行任何操作。
//----------------------------------------------------------------------
//参数说明:RGBQUAD *pRGBPalette
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::GetPaletteData( RGBQUAD *pRGBPalette )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return( FALSE );
char *pTemp;
pTemp = (char *) ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
if( pTemp == NULL ) return( FALSE );
memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)],
m_nPaletteBytes );
m_nLastError = IMAGELIB_SUCCESS;
::GlobalUnlock( m_hDib );
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//RGBQUAD GetPaletteData()
//----------------------------------------------------------------------
//基本功能:本函数返回一个指向CDibObject调色板数据序列的指针。如果图像
// 是16位色或更高时则返回NULL。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:返回一个指向CDibObject调色板数据序列的指针
////////////////////////////////////////////////////////////////////////
RGBQUAD *CDibObject::GetPaletteData( void )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return( NULL );
m_nLastError = IMAGELIB_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 = IMAGELIB_MEMORY_ALLOCATION_ERROR;
return( NULL );
}
char *pTemp;
pTemp = (char *) ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
if( pTemp == NULL )
{
delete [] pRGBPalette;
return( NULL );
}
memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)],
m_nColors * sizeof( RGBQUAD ) );
m_nLastError = IMAGELIB_SUCCESS;
::GlobalUnlock( m_hDib );
return( pRGBPalette );
}
////////////////////////////////////////////////////////////////////////
//int GetImageType()
//----------------------------------------------------------------------
//基本功能:本函数返回图像的类型。图像类型定义如下:
// #define IMAGETYPE_NONE 0
// #define IMAGETYPE_BMP 1
// #define IMAGETYPE_GIF 2
// #define IMAGETYPE_PCX 3
// #define IMAGETYPE_TGA 4
// #define IMAGETYPE_JPG 5
// #define IMAGETYPE_TIF 6
//----------------------------------------------------------------------
//参数说明:const char *pFilename
//----------------------------------------------------------------------
//返 回 值:int nImageType
////////////////////////////////////////////////////////////////////////
int CDibObject::GetImageType( const char *pFilename )
{
return( ::FileType( pFilename ) );
}
////////////////////////////////////////////////////////////////////////
//int GetImageType()
//----------------------------------------------------------------------
//基本功能:本函数返回图像的类型。图像类型定义如下:
// #define IMAGETYPE_NONE 0
// #define IMAGETYPE_BMP 1
// #define IMAGETYPE_GIF 2
// #define IMAGETYPE_PCX 3
// #define IMAGETYPE_TGA 4
// #define IMAGETYPE_JPG 5
// #define IMAGETYPE_TIF 6
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nImageType
////////////////////////////////////////////////////////////////////////
int CDibObject::GetImageType( void )
{
return( m_nImageType );
}
////////////////////////////////////////////////////////////////////////
//BOOL Draw( CDC *pDC, int nX, int nY )
//----------------------------------------------------------------------
//基本功能:本函数是在设备描述表上绘制图像。如果X和Y坐标没有给出,图像会
// 被画在(0,0)坐标或上次传入的有效坐标处。
//----------------------------------------------------------------------
//参数说明:CDC *pDC
// int nX,默认为-1
// int nY,默认为-1
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::Draw( CDC *pDC, int nX, int nY )
{
if( nX != -1 ) m_nX = nX;
if( nY != -1 ) m_nY = nY;
m_nLastError = IMAGELIB_HDIB_NULL;
//没有打开图像
if( m_hDib == NULL ) return( FALSE );
char *pTemp;
//锁定图像对象句柄
pTemp = (char *) ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
if( pTemp == NULL ) return( NULL );
//图像信息头
BITMAPINFOHEADER *pBIH;
pBIH = (BITMAPINFOHEADER *) &pTemp[sizeof(BITMAPFILEHEADER)];
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_nPaletteBytes],
(BITMAPINFO *) pBIH, DIB_RGB_COLORS, SRCCOPY );
::GlobalUnlock( m_hDib );
m_nLastError = IMAGELIB_STRETCHDIBITS_ERROR;
if( nRet != m_nHeight ) return( FALSE );
m_nLastError = IMAGELIB_SUCCESS;
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//BOOL CreateLogPalette()
//----------------------------------------------------------------------
//基本功能:本函数根据指定的调色板指针及颜色数创建一个逻辑调色板。
//----------------------------------------------------------------------
//参数说明:CDC *pDC
// int nX,默认为-1
// int nY,默认为-1
//----------------------------------------------------------------------
//返 回 值:创建的逻辑调色板指针
////////////////////////////////////////////////////////////////////////
LOGPALETTE *CDibObject::CreateLogPalette( RGBQUAD *pPalette,
int nNumColors )
{
LOGPALETTE *pLogPal;
int i;
if( pPalette == NULL ) return( NULL );
pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)];
if( pLogPal == NULL ) return( NULL );
//指定调色板版本号
pLogPal->palVersion = 0x300;
//指定调色板颜色数
pLogPal->palNumEntries = (unsigned short) nNumColors;
//复制调色板各颜色项
for( i=0; ipalPalEntry[i].peRed = pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = pPalette[i].rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
}
return( pLogPal );
}
////////////////////////////////////////////////////////////////////////
//void ProcessImageHeader()
//----------------------------------------------------------------------
//基本功能:本函数处理图像信息头各项内容。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::ProcessImageHeader( void )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return;
char *pTemp;
BITMAPINFOHEADER *pBIH;
pTemp = (char *) ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
if( pTemp == NULL ) return;
//得到图像信息头指针
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;
if( m_nPlanes > 1 ) m_nColors <<= ( m_nPlanes - 1 );
if( m_nBits >= 16 ) m_nColors = 0;
int nWidthBytes = WidthBytes(m_nBits, m_nWidth);
pBIH->biSizeImage = nWidthBytes * m_nHeight;
::GlobalUnlock( m_hDib );
m_nLastError = IMAGELIB_SUCCESS;
}
////////////////////////////////////////////////////////////////////////
//void ProcessPalette()
//----------------------------------------------------------------------
//基本功能:处理体调色板。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::ProcessPalette( void )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return;
CWindowDC WindowDC( NULL );
m_nScreenPlanes = WindowDC.GetDeviceCaps( PLANES );
m_nScreenBits = WindowDC.GetDeviceCaps( BITSPIXEL );
m_nPaletteBytes = 0;
m_Palette.DeleteObject();
if( m_nBits <= 8 ) m_nPaletteBytes = m_nColors * sizeof( RGBQUAD );
if( m_nScreenBits >= 16 ) return;
char *pTemp;
pTemp = (char *) ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_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 = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
goto ProcessPaletteExit;
}
m_Palette.CreatePalette( pPalette );
delete [] pPalette;
}
m_nLastError = IMAGELIB_SUCCESS;
ProcessPaletteExit:
::GlobalUnlock( m_hDib );
}
////////////////////////////////////////////////////////////////////////
//void KillImage()
//----------------------------------------------------------------------
//基本功能:清除当前CDibObject类中的图像对象。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::KillImage( void )
{
if( m_hDib ) ::GlobalFree( m_hDib );
m_hDib = NULL;
if( m_pLogPal != NULL ) delete [] m_pLogPal;
m_pLogPal = NULL;
if( m_pszFilename != NULL ) delete [] m_pszFilename;
m_pszFilename = NULL;
m_Palette.DeleteObject();
}
////////////////////////////////////////////////////////////////////////
//BOOL SetPalette( CDC *pDC )
//----------------------------------------------------------------------
//基本功能:本函数将该设备描述表的调色板分配给相应的图像。当一个图像被载
// 入时,它的调色板信息便被存入CDibObject对象中。
//----------------------------------------------------------------------
//参数说明:CDC *pDC
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::SetPalette( CDC *pDC )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return( FALSE );
pDC->SelectPalette( &m_Palette, FALSE );
pDC->RealizePalette();
m_nLastError = IMAGELIB_SUCCESS;
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//BOOL IsLoaded( void )
//----------------------------------------------------------------------
//基本功能:本函数判断是否已经载入了一幅图像
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::IsLoaded( void )
{
return( m_hDib != NULL );
}
////////////////////////////////////////////////////////////////////////
//void GetDIBPointer()
//----------------------------------------------------------------------
//基本功能:得到图像DIB数据指针。
//----------------------------------------------------------------------
//参数说明:int *nWidthBytes 图像的字节宽度
// int nNewBits 新设置的图像颜色位数
// int *nNewWidthBytes 图像颜色位数改变后的字节宽度
// int nNewWidth 新设置的图像宽度(像素)
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void *CDibObject::GetDIBPointer( int *nWidthBytes,
int nNewBits,
int *nNewWidthBytes,
int nNewWidth )
{
m_nLastError = IMAGELIB_HDIB_NULL;
if( m_hDib == NULL ) return( NULL );
void *pTemp;
pTemp = ::GlobalLock( m_hDib );
m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
if( pTemp == NULL ) return( NULL );
if( nWidthBytes != NULL ) *nWidthBytes = WidthBytes( m_nBits, m_nWidth );
if( nNewWidthBytes != NULL )
{
if( nNewWidth == -1 ) nNewWidth = m_nWidth;
*nNewWidthBytes = WidthBytes( nNewBits, nNewWidth );
}
return( pTemp );
}
////////////////////////////////////////////////////////////////////////
//int WidthBytes()
//----------------------------------------------------------------------
//基本功能:本函数根据传入的像素位数及图像宽度(像素)计算其字节宽度。
//----------------------------------------------------------------------
//参数说明:int nBits 每像素位数
// int nWidth 图像的宽度
//----------------------------------------------------------------------
//返 回 值:int 图像的字节宽度
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::WidthBytes( 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;
//一个数的后两位为零,则该数为4的整数倍
while( ( nWidthBytes & 3 ) != 0 ) nWidthBytes++;
return( nWidthBytes );
}
////////////////////////////////////////////////////////////////////////
//void NormalizeCoordinates()
//----------------------------------------------------------------------
//基本功能:规格化处理的图像区域。
//----------------------------------------------------------------------
//参数说明:int *nX1 处理区域左上角X坐标
// int *nY1 处理区域左上角Y坐标
// int *nX2 处理区域右下角X坐标
// int *nY2 处理区域右下角Y坐标
// BOOL *bCompleteImage 处理区域是否为全部区域
// BOOL *bLessThanHalf 处理区域是否为一半区域
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::NormalizeCoordinates( int *nX1, int *nY1, int *nX2, int *nY2,
BOOL *bCompleteImage, BOOL *bLessThanHalf )
{
if( *nX1 == -1 ) *nX1 = 0;
if( *nY1 == -1 ) *nY1 = 0;
if( *nX2 == -1 ) *nX2 = m_nWidth - 1;
if( *nY2 == -1 ) *nY2 = m_nHeight - 1;
if( *nX1 > *nX2 ){
int nTemp;
nTemp = *nX1;
*nX1 = *nX2;
*nX2 = nTemp;
}
if( *nY1 > *nY2 ){
int nTemp;
nTemp = *nY1;
*nY1 = *nY2;
*nY2 = nTemp;
}
if( *nX1 < 0 ) *nX1 = 0;
if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
if( *nX2 < 0 ) *nX2 = 0;
if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
if( *nY1 < 0 ) *nY1 = 0;
if( *nY1 > m_nHeight - 1 ) *nY1 = m_nHeight - 1;
if( *nY2 < 0 ) *nY2 = 0;
if( *nY2 > m_nHeight - 1 ) *nY2 = m_nHeight - 1;
if( bCompleteImage != NULL ) *bCompleteImage = TRUE;
if( bLessThanHalf != NULL ) *bLessThanHalf = FALSE;
if( *nX1 > 0 || *nY1 > 0 || *nX2 < m_nWidth - 1 || *nY2 < m_nHeight - 1 ){
if( bCompleteImage != NULL ) *bCompleteImage = FALSE;
DWORD dwTotalPixels, dwThesePixels;
dwTotalPixels = (DWORD) m_nWidth * m_nHeight;
dwThesePixels = (DWORD) ( (*nX2) - (*nX1) + 1 ) * (DWORD) ( (*nY2) - (*nY1) + 1 );
if( bLessThanHalf != NULL && dwThesePixels <= dwTotalPixels / 2 ) *bLessThanHalf = TRUE;
}
}
////////////////////////////////////////////////////////////////////////
//void operator=()
//----------------------------------------------------------------------
//基本功能:“=”操作符重载。
//----------------------------------------------------------------------
//参数说明:CDibObject &DibObject 另一个CDibObject图像对象。
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::operator= (const CDibObject &DibObject)
{
KillImage();
m_nWidth = DibObject.m_nWidth;
m_nHeight = DibObject.m_nHeight;
m_nPlanes = DibObject.m_nPlanes;
m_nBits = DibObject.m_nBits;
m_nColors = DibObject.m_nColors;
m_nImageType = DibObject.m_nImageType;
m_nX = DibObject.m_nX;
m_nY = DibObject.m_nY;
m_nLastError = DibObject.m_nLastError;
m_nScreenPlanes = DibObject.m_nScreenPlanes;
m_nScreenBits = DibObject.m_nScreenBits;
m_nPaletteBytes = DibObject.m_nPaletteBytes;
m_nQuality = DibObject.m_nQuality;
m_nPaletteCreationType = DibObject.m_nPaletteCreationType;
int nNumColors = m_nColors;
int nWidthBytes = WidthBytes( m_nBits, m_nWidth );
if( DibObject.m_hDib != NULL ){
DWORD dwSize = ::GlobalSize( DibObject.m_hDib );
char *pData = (char *) ::GlobalLock( DibObject.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( DibObject.m_pLogPal != NULL ){
m_pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+DibObject.m_pLogPal->palNumEntries*sizeof(PALETTEENTRY)];
if( m_pLogPal != NULL ){
for( int i=0; ipalNumEntries; i++ ) m_pLogPal[i] = DibObject.m_pLogPal[i];
m_Palette.CreatePalette( m_pLogPal );
}
}
::GlobalUnlock( hGlobal );
m_hDib = hGlobal;
}
else ::GlobalFree( hGlobal );
}
::GlobalUnlock( DibObject.m_hDib );
}
}
if( DibObject.m_pszFilename != NULL ){
m_pszFilename = new char [strlen(DibObject.m_pszFilename)+1];
strcpy( m_pszFilename, DibObject.m_pszFilename );
}
}
////////////////////////////////////////////////////////////////////////
//void CreatePaletteFromDIB()
//----------------------------------------------------------------------
//基本功能:从当前CDibObject位图对象中创建调色板。
//----------------------------------------------------------------------
//参数说明:RGBQUAD *pRGBPalette 调色板指针
// int nNumColors 图像颜色数
//----------------------------------------------------------------------
//返 回 值:无
////////////////////////////////////////////////////////////////////////
void CDibObject::CreatePaletteFromDIB( RGBQUAD *pRGBPalette, int nNumColors )
{
if( pRGBPalette != NULL ){
LOGPALETTE *pPalette;
pPalette = CreateLogPalette( pRGBPalette, nNumColors );
if( pPalette != NULL ){
m_Palette.CreatePalette( pPalette );
delete [] pPalette;
}
else m_nLastError = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
}
}
////////////////////////////////////////////////////////////////////////
//int GetNearestIndex()
//----------------------------------------------------------------------
//基本功能:获取相近颜色索引值。
//----------------------------------------------------------------------
//参数说明:unsigned char ucRed 红色分量
// unsigned char ucGreen 绿色分量
// unsigned char ucBlue 蓝色分量
// RGBQUAD *pRGBPalette 调色板指针
// int nNumColors 颜色数
//----------------------------------------------------------------------
//返 回 值:int 相近颜色索引值
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::GetNearestIndex( unsigned char ucRed,
unsigned char ucGreen,
unsigned char ucBlue,
RGBQUAD *pRGBPalette,
int nNumColors )
{
int i, Index = 0;
DWORD NewDiff, Diff = 100000L;
DWORD Red, Green, Blue;
for( i=0; i pRGBPalette[i].rgbRed ) Red = (DWORD) ( pRGBPalette[i].rgbRed - ucRed );
else Red = (DWORD) ( ucRed - pRGBPalette[i].rgbRed );
if( ucGreen > pRGBPalette[i].rgbGreen ) Green = (DWORD) ( pRGBPalette[i].rgbGreen - ucGreen );
else Green = (DWORD) ( ucGreen - pRGBPalette[i].rgbGreen );
if( ucBlue > pRGBPalette[i].rgbBlue ) Blue = (DWORD) ( pRGBPalette[i].rgbBlue - ucBlue );
else Blue = (DWORD) ( ucBlue - pRGBPalette[i].rgbBlue );
NewDiff = ( Red * Red ) + ( Green * Green ) + ( Blue * Blue );
if( NewDiff < Diff )
{
if( NewDiff <= 1 ) return( i );
Diff = NewDiff;
Index = i;
}
}
return( Index );
}
////////////////////////////////////////////////////////////////////////
//BOOL ChangeFormat( int nNewBitsPerPixel )
//----------------------------------------------------------------------
//基本功能:本函数将图像从当前分辨率转化为指定分辨率。
//----------------------------------------------------------------------
//参数说明:int nNewBitsPerPixel
//----------------------------------------------------------------------
//返 回 值:BOOL:成功返回TRUE,失败返回FALSE
////////////////////////////////////////////////////////////////////////
BOOL CDibObject::ChangeFormat( int nNewBitsPerPixel )
{
m_nLastError = IMAGELIB_SUCCESS;
if( nNewBitsPerPixel == m_nBits ) return( TRUE );
int nOldWidthBytes, nNewWidthBytes;
char *pBuffer = (char *) GetDIBPointer( &nOldWidthBytes, nNewBitsPerPixel, &nNewWidthBytes );
if( pBuffer == NULL ) return( FALSE );
BITMAPINFOHEADER *pOldBIH, *pNewBIH;
BITMAPFILEHEADER *pOldBFH, *pNewBFH;
RGBQUAD *pOldRGBPalette, *pNewRGBPalette;
unsigned char *pOldBits, *pNewBits;
int nNumColors, nNumNewColors;
pOldBFH = (BITMAPFILEHEADER *) pBuffer;
pOldBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
pOldRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
nNumColors = m_nColors;
nNumNewColors = 1 << nNewBitsPerPixel;
if( nNewBitsPerPixel > 8 ) nNumNewColors = 0;
pOldBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
if( m_nBits >= 16 && nNewBitsPerPixel < 16 ){
if( m_pLogPal != NULL ) delete [] m_pLogPal;
m_pLogPal = CreatePaletteFromBitmap( nNumNewColors, pOldBits, m_nBits, m_nWidth, m_nHeight );
}
HGLOBAL hGlobal;
DWORD dwSize;
dwSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + m_nHeight * nNewWidthBytes;
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 = nNumNewColors;
if( m_nBits < 16 && nNewBitsPerPixel < 16 ){
for( i=0; i= 16 ){
for( i=0; ipalPalEntry[i].peRed;
pNewRGBPalette[i].rgbGreen = m_pLogPal->palPalEntry[i].peGreen;
pNewRGBPalette[i].rgbBlue = m_pLogPal->palPalEntry[i].peBlue;
}
}
pNewBIH->biBitCount = nNewBitsPerPixel;
pNewBIH->biSizeImage = nNewWidthBytes * m_nHeight;
pNewBIH->biClrUsed = nNumNewColors;
pNewBFH->bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + pNewBIH->biSizeImage;
pNewBFH->bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD );
pNewBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumNewColors*sizeof(RGBQUAD)];
m_nPaletteBytes = nNumNewColors * sizeof( RGBQUAD );
for( int y=0; y> ( 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:
GETRGB555( ucRed, ucGreen, ucBlue, &pSrc[x*2] );
break;
case 24:
ucRed = pSrc[x*3+2];
ucGreen = pSrc[x*3+1];
ucBlue = pSrc[x*3];
break;
case 32:
GETRGB888( ucRed, ucGreen, ucBlue, &pSrc[x*4] );
break;
}
switch( nNewBitsPerPixel ){
case 1:
if( !( x & 7 ) ) pDest[x/8] = 0;
pDest[x/8] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << ( x & 7 );
break;
case 4:
if( !( x & 1 ) )
pDest[x/2] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << 4;
else
pDest[x/2] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
break;
case 8:
pDest[x] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
break;
case 16:
PUTRGB555( ucRed, ucGreen, ucBlue, &pDest[x*2] );
break;
case 24:
pDest[x*3+2] = ucRed;
pDest[x*3+1] = ucGreen;
pDest[x*3] = ucBlue;
break;
case 32:
PUTRGB888( ucRed, ucGreen, ucBlue, &pDest[x*4] );
break;
}
}
}
::GlobalUnlock( m_hDib );
::GlobalFree( m_hDib );
::GlobalUnlock( hGlobal );
m_hDib = hGlobal;
ProcessImageHeader();
return( TRUE );
}
////////////////////////////////////////////////////////////////////////
//LOGPALETTE CreatePaletteFromBitmap()
//----------------------------------------------------------------------
//基本功能:从当前CDibObject位图对象中创建逻辑调色板。
//----------------------------------------------------------------------
//参数说明:int nNumColors 颜色数
// unsigned char *pBits 位图数据指针
// int nBits 颜色位数
// int nWidth 图像宽度
// int nHeight 图像高度
//----------------------------------------------------------------------
//返 回 值:LOGPALETTE 逻辑调色板指针
////////////////////////////////////////////////////////////////////////
LOGPALETTE *CDibObject::CreatePaletteFromBitmap(int nNumColors,
unsigned char *pBits, int nBits,
int nWidth, int nHeight )
{
RGBQUAD *pRGBPalette;
if( nBits != 8 && m_nPaletteCreationType == POPULARITY_PALETTE ) pRGBPalette = MakePopularityPalette( nNumColors, pBits, nBits, nWidth, nHeight );
else if( nBits != 8 && m_nPaletteCreationType == MEDIAN_CUT_PALETTE ) pRGBPalette = MakeMedianCutPalette( nNumColors, pBits, nBits, nWidth, nHeight );
else if( m_nPaletteCreationType == FIXED_PALETTE ) pRGBPalette = MakeFixedPalette( nNumColors );
if( pRGBPalette == NULL ) return( NULL );
LOGPALETTE *pLogPal = CreateLogPalette( pRGBPalette, nNumColors );
delete [] pRGBPalette;
return( pLogPal );
}
////////////////////////////////////////////////////////////////////////
//void SetPaletteCreationType( int nType )
//----------------------------------------------------------------------
//基本功能:当希望通过颜色还原得到一幅具有调色板的图像时,本函数负责设置
// 调色板的创建类型。可以设置如下:
// #define POPULARITY_PALETTE 0
// #define MEDIAN_CUT_PALETTE 1
// #define FIXED_PALETTE 2
//----------------------------------------------------------------------
//参数说明:int nType
//----------------------------------------------------------------------
//返 回 值:无
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
void CDibObject::SetPaletteCreationType( int nType )
{
m_nPaletteCreationType = nType;
}
////////////////////////////////////////////////////////////////////////
//int GetPaletteCreationType( void )
//----------------------------------------------------------------------
//基本功能:本函数返回用于下一次颜色还原操作的调色板类型。
//----------------------------------------------------------------------
//参数说明:无
//----------------------------------------------------------------------
//返 回 值:int nPaletteCreationType
//----------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
int CDibObject::GetPaletteCreationType( void )
{
return( m_nPaletteCreationType );
}
RGBQUAD *CDibObject::MakePopularityPalette( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
{
RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
if( pRGBQuad == NULL ) return( MakeFixedPalette( nNumColors ) );
memset( pRGBQuad, 0, nNumColors * sizeof( RGBQUAD ) );
BYTE ColMap[256][3];
if( !Popularity( pBits, nBits, nWidth, nHeight, ColMap ) ){
delete [] pRGBQuad;
return( MakeFixedPalette( nNumColors ) );
}
for( int i=0; i