📄 dib.cpp
字号:
// Dib.cpp: implementation of the CDib class.
//////////////////////////////////////////////////////////////////////
//
//用途:IconSnap所需调用的类
//功能:DIB设备无关位图基础操作类
//作者:徐景周
//日期:2001年9月
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BindFile.h"
#include "Dib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
}
CDib::~CDib()
{
}
/****************************************************************************
*
* FUNCTION: FindDIBits
*
* PURPOSE: Locate the image bits in a CF_DIB format DIB.
*
* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
*
* RETURNS: LPSTR - pointer to the image bits
*
*
\****************************************************************************/
LPSTR CDib::FindDIBBits( LPSTR lpbi )
{
return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
}
/* End FindDIBits() *********************************************************/
/****************************************************************************
*
* FUNCTION: DIBNumColors
*
* PURPOSE: Calculates the number of entries in the color table.
*
* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
*
* RETURNS: WORD - Number of entries in the color table.
*
*
\****************************************************************************/
WORD CDib::DIBNumColors( LPSTR lpbi )
{
WORD wBitCount;
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
if (dwClrUsed)
return (WORD) dwClrUsed;
wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
switch (wBitCount)
{
case 1: return 2;
case 4: return 16;
case 8: return 256;
default:return 0;
}
return 0;
}
/* End DIBNumColors() ******************************************************/
/****************************************************************************
*
* FUNCTION: PaletteSize
*
* PURPOSE: Calculates the number of bytes in the color table.
*
* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
*
* RETURNS: WORD - number of bytes in the color table
*
*
\****************************************************************************/
WORD CDib::PaletteSize( LPSTR lpbi )
{
return ( DIBNumColors( lpbi ) * sizeof( RGBQUAD ) );
}
/* End PaletteSize() ********************************************************/
/****************************************************************************
*
* FUNCTION: BytesPerLine
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* PARAMS: LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER
* that begins the CF_DIB block
*
* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
*
*
\****************************************************************************/
DWORD CDib::BytesPerLine( LPBITMAPINFOHEADER lpBMIH )
{
return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
}
/* End BytesPerLine() ********************************************************/
/****************************************************************************
*
* FUNCTION: ConvertDIBFormat
*
* PURPOSE: Creates a new DIB of the requested format, copies the source
* image to the new DIB.
*
* PARAMS: LPBITMAPINFO lpSrcDIB - the source CF_DIB
* UINT nWidth - width for new DIB
* UINT nHeight - height for new DIB
* UINT nbpp - bpp for new DIB
* BOOL bStretch - TRUE to stretch source to dest
* FALSE to take upper left of image
*
* RETURNS: LPBYTE - pointer to new CF_DIB memory block with new image
* NULL on failure
*
*
\****************************************************************************/
LPBYTE CDib::ConvertDIBFormat( LPBITMAPINFO lpSrcDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch )
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
// Allocate and fill out a BITMAPINFO struct for the new DIB
// Allow enough room for a 256-entry color table, just in case
dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( 256 * sizeof( RGBQUAD ) );
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = nbpp;
lpbmi->bmiHeader.biCompression = BI_RGB;
lpbmi->bmiHeader.biSizeImage = 0;
lpbmi->bmiHeader.biXPelsPerMeter = 0;
lpbmi->bmiHeader.biYPelsPerMeter = 0;
lpbmi->bmiHeader.biClrUsed = 0;
lpbmi->bmiHeader.biClrImportant = 0;
// Fill in the color table
if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB ) )
{
free( lpbmi );
return NULL;
}
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (void ** )&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS,(void ** ) &lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine(&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine(&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize );
// Select DIBSections into DCs
hOldSourceBitmap =(HBITMAP ) SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP )SelectObject( hTargetDC, hTargetBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
if( lpbmi->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// If we are asking for a straight copy, do it
if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) )
{
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
else
{
// else, should we stretch it?
if( bStretch )
{
SetStretchBltMode( hTargetDC, COLORONCOLOR );
StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
}
else
{
// or just take the upper left corner of the source
BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
}
}
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
SelectObject( hSourceDC, hOldTargetBitmap );
DeleteDC( hSourceDC );
DeleteDC( hTargetDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
// Allocate enough memory for the new CF_DIB, and copy bits
lpResult =(LPBYTE ) malloc( dwTargetHeaderSize + dwTargetBitsSize );
memcpy( lpResult, lpbmi, dwTargetHeaderSize );
memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize );
// final cleanup
DeleteObject( hTargetBitmap );
DeleteObject( hSourceBitmap );
free( lpbmi );
return lpResult;
}
/* End ConvertDIBFormat() ***************************************************/
/****************************************************************************
*
* FUNCTION: CopyColorTable
*
* PURPOSE: Copies the color table from one CF_DIB to another.
*
* PARAMS: LPBITMAPINFO lpTarget - pointer to target DIB
* LPBITMAPINFO lpSource - pointer to source DIB
*
* RETURNS: BOOL - TRUE for success, FALSE for failure
*
*
\****************************************************************************/
BOOL CDib::CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource )
{
// What we do depends on the target's color depth
switch( lpTarget->bmiHeader.biBitCount )
{
// 8bpp - need 256 entry color table
case 8:
if( lpSource->bmiHeader.biBitCount == 8 )
{ // Source is 8bpp too, copy color table
memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) );
return TRUE;
}
else
{ // Source is != 8bpp, use halftone palette
HPALETTE hPal;
HDC hDC = GetDC( NULL );
PALETTEENTRY pe[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -