📄 imageobject.cpp
字号:
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++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -