📄 imageobject.cpp
字号:
Tmp1 |= ( ( Tmp & 0x20 ) >> 3 );
Tmp1 |= ( ( Tmp & 0x40 ) >> 5 );
Tmp1 |= ( ( Tmp & 0x80 ) >> 7 );
pTemp[x] = Tmp1;
pTemp[xt] = Data1;
}
break;
case 4:
for( x=0; x<xx; x++ ){
xt = nWidth - 1 - x;
Data = pTemp[x];
Tmp = pTemp[xt];
Data = ( Data << 4 ) | ( Data >> 4 );
Tmp = ( Tmp << 4 ) | ( Tmp >> 4 );
pTemp[x] = Tmp;
pTemp[xt] = Data;
}
break;
case 8:
for( x=0; x<xx; x++ ){
xt = nWidth - 1 - x;
Data = pTemp[x];
pTemp[x] = pTemp[xt];
pTemp[xt] = Data;
}
break;
case 16:
for( x=0; x<xx; x++ ){
xt = nWidth - 1 - x;
Data = pTemp[x*2];
pTemp[x*2] = pTemp[xt*2];
pTemp[xt*2] = Data;
Data = pTemp[x*2+1];
pTemp[x*2+1] = pTemp[xt*2+1];
pTemp[xt*2+1] = Data;
}
break;
case 24:
for( x=0; x<xx; x++ ){
xt = nWidth - 1 - x;
Data = pTemp[x*3];
pTemp[x*3] = pTemp[xt*3];
pTemp[xt*3] = Data;
Data = pTemp[x*3+1];
pTemp[x*3+1] = pTemp[xt*3+1];
pTemp[xt*3+1] = Data;
Data = pTemp[x*3+2];
pTemp[x*3+2] = pTemp[xt*3+2];
pTemp[xt*3+2] = Data;
}
break;
case 32:
for( x=0; x<xx; x++ ){
xt = nWidth - 1 - x;
Data = pTemp[x*4];
pTemp[x*4] = pTemp[xt*4];
pTemp[xt*4] = Data;
Data = pTemp[x*4+1];
pTemp[x*4+1] = pTemp[xt*4+1];
pTemp[xt*4+1] = Data;
Data = pTemp[x*4+2];
pTemp[x*4+2] = pTemp[xt*4+2];
pTemp[xt*4+2] = Data;
Data = pTemp[x*4+3];
pTemp[x*4+3] = pTemp[xt*4+3];
pTemp[xt*4+3] = Data;
}
break;
}
}
::GlobalUnlock( m_hDib );
m_nLastError = IMAGELIB_SUCCESS;
return( TRUE );
}
BOOL CImageObject::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<j; i++ ) pNewRGBPalette[i] = pOldRGBPalette[i];
}
else if( m_nBits >= 16 ){
for( i=0; i<j; i++ ){
pNewRGBPalette[i].rgbRed = m_pLogPal->palPalEntry[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<m_nHeight; y++ ){
unsigned char ucRed, ucGreen, ucBlue;
unsigned char *pSrc, *pDest;
pSrc = pOldBits;
pSrc += ( nOldWidthBytes * y );
pDest = pNewBits;
pDest += ( nNewWidthBytes * 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:
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 *CImageObject::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 CImageObject::SetPaletteCreationType( int nType )
{
m_nPaletteCreationType = nType;
}
int CImageObject::GetPaletteCreationType( void )
{
return( m_nPaletteCreationType );
}
RGBQUAD *CImageObject::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<nNumColors; i++ ){
pRGBQuad[i].rgbRed = ColMap[i][0];
pRGBQuad[i].rgbGreen = ColMap[i][1];
pRGBQuad[i].rgbBlue = ColMap[i][2];
}
return( pRGBQuad );
}
RGBQUAD *CImageObject::MakeMedianCutPalette( 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];
WORD *Hist = new WORD[32768];
if( Hist == NULL ){
delete [] pRGBQuad;
return( MakeFixedPalette( nNumColors ) );
}
memset( Hist, 0, 32768 * sizeof( WORD ) );
int nWidthBytes = WidthBytes( nBits, nWidth );
for( int y=0; y<nHeight; y++ ){
unsigned char *pData = pBits;
unsigned char ucRed, ucGreen, ucBlue;
WORD color;
pData += ( y * nWidthBytes );
for( int x=0; x<nWidth; x++ ){
switch( nBits ){
case 16:
GETRGB555( ucRed, ucGreen, ucBlue, &pData[x*2] );
break;
case 24:
ucRed = pData[x*3+2];
ucGreen = pData[x*3+1];
ucBlue = pData[x*3];
break;
case 32:
GETRGB888( ucRed, ucGreen, ucBlue, &pData[x*4] );
break;
}
color = _RGB( ucRed, ucGreen, ucBlue );
if( Hist[color] < 65535 ) Hist[color]++;
}
}
MedianCut( Hist, ColMap, (int) 256 );
for( int i=0; i<nNumColors; i++ ){
pRGBQuad[i].rgbRed = ColMap[i][0];
pRGBQuad[i].rgbGreen = ColMap[i][1];
pRGBQuad[i].rgbBlue = ColMap[i][2];
}
delete [] Hist;
return( pRGBQuad );
}
RGBQUAD *CImageObject::MakeFixedPalette( int nNumColors )
{
RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
if( pRGBQuad == NULL ) return( NULL );
static int colors[] = {
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 = ( ( nNumColors + 15 ) / 16 );
for( int i=0; i<nSteps; i++ ){
for( int j=0; j<16; j++ ){
if( i * 16 + j < nNumColors ){
int r, g, b;
r = colors[j*3];
g = colors[j*3+1];
b = colors[j*3+2];
r = ( ( nSteps - i ) * r ) / nSteps;
g = ( ( nSteps - i ) * g ) / nSteps;
b = ( ( nSteps - i ) * b ) / nSteps;
pRGBQuad[i*16+j].rgbRed = (unsigned char) r;
pRGBQuad[i*16+j].rgbGreen = (unsigned char) g;
pRGBQuad[i*16+j].rgbBlue = (unsigned char) b;
}
}
}
return( pRGBQuad );
}
int CImageObject::GetPaletteBytes( void )
{
return( m_nPaletteBytes );
}
HGLOBAL CImageObject::GetDib( void )
{
return( m_hDib );
}
CPalette *CImageObject::GetPalette( void )
{
return( &m_Palette );
}
LOGPALETTE *CImageObject::GetLogPal( void )
{
return( m_pLogPal );
}
void CImageObject::GetRGBValue(int x, int y, unsigned char &red, unsigned char &green, unsigned char &blue)
{
if(x<0 ||x>=m_nWidth) return;
if(y<0 ||y>=m_nHeight) return;
int nWidthBytes;
char *pBuffer = (char *) GetDIBPointer( &nWidthBytes );
if( pBuffer == NULL ) return;
BITMAPINFOHEADER *pBIH;
BITMAPFILEHEADER *pBFH;
RGBQUAD *pRGBPalette;
unsigned char *pBits;
int nNumColors;
pBFH = (BITMAPFILEHEADER *) pBuffer;
pBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
pRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
nNumColors = m_nColors;
pBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
switch( m_nBits )
{
case 8:
int i;
i=*(pBits+(m_nHeight-1-y)*nWidthBytes+x);
red=pRGBPalette[i].rgbRed;
green=pRGBPalette[i].rgbGreen;
blue=pRGBPalette[i].rgbBlue;
break;
case 16:
GETRGB555(red,green,blue,(pBits+(m_nHeight-1-y)*nWidthBytes+x*2));
break;
case 24:
red=*(pBits+(m_nHeight-1-y)*nWidthBytes+x*3+2);//第三字节为红色
green=*(pBits+(m_nHeight-1-y)*nWidthBytes+x*3+1);//第二字节为绿色
blue=*(pBits+(m_nHeight-1-y)*nWidthBytes+x*3);//第一字节为蓝色
//即RGB图象存放时是以bgr的格式存放的
break;
case 32:
GETRGB888(red,green,blue,(pBits+(m_nHeight-1-y)*nWidthBytes+x*4));
break;
}
}
unsigned char* CImageObject::GetDIBBits()
{
int nWidthBytes;
char *pBuffer = (char *) GetDIBPointer( &nWidthBytes );
if( pBuffer == NULL )
{
return NULL;
}
unsigned char *pBits;
pBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nColors*sizeof(RGBQUAD)];
return pBits;
}
void CImageObject::OnChangeImageSize()
{
m_nHeight=Height;
m_nWidth=Width;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -