📄 cdib.cpp
字号:
if (numwritten != sizeof(hdr))
{
RETAILMSG(CDIB_ERROR_MSG, (TEXT("CDIB: Save: Failed to write BITMAPFILEHEADER.\r\n")));
return FALSE;
}
// Write the DIB header
numwritten = fwrite( (void *)lpbi, sizeof(BYTE), dwBitmapInfoSize, pFile );
if (numwritten != dwBitmapInfoSize)
{
RETAILMSG(CDIB_ERROR_MSG, (TEXT("CDIB: Save: Failed to write BitmapInfoSize.\r\n")));
return FALSE;
}
// Write DIB bits
numwritten = fwrite( GetDIBits(), sizeof(BYTE), lpbi->biSizeImage, pFile );
if (numwritten != lpbi->biSizeImage)
{
RETAILMSG(CDIB_ERROR_MSG, (TEXT("CDIB: Save: Failed to write bits.\r\n")));
return FALSE;
}
fclose(pFile);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// CDIB palette stuff
//
// --- In?: nNumColors - number of colors to set
// pColors - array of RGBQUAD's containing colors to set
// --- Out :
// --- Returns : Returns TRUE on success, FALSE otherwise
// --- Effect : Sets the colors used by the image. Only works if # colors <= 256
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::SetColorTable(UINT nNumColors, RGBQUAD *pColors)
{
if (!m_hBitmap ||!pColors || !nNumColors || m_iColorTableSize == 0 || nNumColors > 256)
return FALSE;
LPRGBQUAD pColorTable = GetColorTable();
ASSERT(pColorTable);
int nCount = min(m_iColorTableSize, nNumColors);
::memset(pColorTable, 0, m_iColorTableSize*sizeof(RGBQUAD));
::memcpy(pColorTable, pColors, nCount*sizeof(RGBQUAD));
return TRUE;
}
// --- In?:
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Creates the palette from the DIBSection's color table. Assumes
// m_iColorTableSize has been set and the DIBsection m_hBitmap created
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::CreatePalette()
{
//m_hPal DeleteObject();
if (!m_hBitmap)
return FALSE;
// Create a 256 color halftone palette if there is no color table in the DIBSection
if (m_iColorTableSize == 0)
return CreateHalftonePalette(m_hPal, 256);
// Get space for the color entries
RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize];
if (!pRGB)
return CreateHalftonePalette(m_hPal, m_iColorTableSize);
HDC hDC = ::GetDC(NULL);
if (!hDC)
{
delete [] pRGB;
return FALSE;
}
// Create a memory DC compatible with the current DC
HDC hMemDC = CreateCompatibleDC(hDC);
if (!hMemDC)
{
delete [] pRGB;
ReleaseDC(NULL, hDC);
return CreateHalftonePalette(m_hPal, m_iColorTableSize);
}
ReleaseDC(NULL, hDC);
HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemDC, m_hBitmap);
if (!hOldBitmap)
{
delete [] pRGB;
return CreateHalftonePalette(m_hPal, m_iColorTableSize);
}
// Get the colors used. WinCE does not support GetDIBColorTable so if you
// are using this on a CE device with palettes, then you need to replace
// the call with code that manually gets the color table from the m_DIBinfo structure.
int nColors = CEGetDIBColorTable(hDC, 0, m_iColorTableSize, pRGB);
// Clean up
SelectObject(hMemDC, hOldBitmap);
if (!nColors) // No colors retrieved => the bitmap in the DC is not a DIB section
{
delete [] pRGB;
return CreateHalftonePalette(m_hPal, m_iColorTableSize);
}
// Create and fill a LOGPALETTE structure with the colors used.
PALETTEINFO PaletteInfo;
PaletteInfo.palNumEntries = m_iColorTableSize;
for (int ii = 0; ii < nColors; ii++)
{
PaletteInfo.palPalEntry[ii].peRed = pRGB[ii].rgbRed;
PaletteInfo.palPalEntry[ii].peGreen = pRGB[ii].rgbGreen;
PaletteInfo.palPalEntry[ii].peBlue = pRGB[ii].rgbBlue;
PaletteInfo.palPalEntry[ii].peFlags = 0;
}
delete [] pRGB;
// Create Palette!
m_hPal = ::CreatePalette( &PaletteInfo );
return (NULL != m_hPal);
}
// --- In?: pPalette - new palette to use
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Sets the current palette used by the image from the supplied CPalette,
// and sets the color table in the DIBSection
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::SetPalette(HPALETTE hPal)
{
// m_Palette.DeleteObject();
if (!hPal)
return FALSE;
WORD nColors;
::GetObject(hPal, sizeof(WORD), &nColors);
if (nColors <= 0 || nColors > 256)
return FALSE;
// Get palette entries
PALETTEINFO pi;
pi.palNumEntries = (WORD) ::GetPaletteEntries(hPal, 0, nColors, (LPPALETTEENTRY) pi);
return SetLogPalette(&pi);
}
// --- In?: pLogPalette - new palette to use
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Sets the current palette used by the image from the supplied LOGPALETTE
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::SetLogPalette(LOGPALETTE* pLogPalette)
{
if (!pLogPalette)
{
CreatePalette();
return FALSE;
}
ASSERT(pLogPalette->palVersion == (WORD) 0x300);
UINT nColors = pLogPalette->palNumEntries;
if (nColors <= 0 || nColors > 256)
{
CreatePalette();
return FALSE;
}
// Create new palette
DeleteObject( m_hPal );
m_hPal = ::CreatePalette(pLogPalette);
if (!m_hPal)
{
CreatePalette();
return FALSE;
}
if (m_iColorTableSize == 0)
return TRUE;
// Set the DIB colors
RGBQUAD RGBquads[256];
for (UINT i = 0; i < nColors; i++)
{
RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed;
RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen;
RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue;
RGBquads[i].rgbReserved = 0;
}
return FillDIBColorTable(nColors, RGBquads);
}
// --- In?: nNumColors - number of colors to set
// pRGB - colors to fill
// --- Out :
// --- Returns : Returns TRUE on success
// --- Effect : Sets the colors used by the image. Only works if # colors <= 256
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::FillDIBColorTable(UINT nNumColors, RGBQUAD *pRGB)
{
if (!pRGB || !nNumColors || !m_iColorTableSize || nNumColors > 256)
return FALSE;
// get the number of colors to return per BITMAPINFOHEADER docs
UINT nColors;
LPBITMAPINFOHEADER pBmih = GetBitmapInfoHeader();
if (pBmih->biClrUsed)
nColors = pBmih->biClrUsed;
else
nColors = 1 << (pBmih->biBitCount*pBmih->biPlanes);
// Initialize the loop variables
nColors = min(nNumColors, nColors);
LPRGBQUAD pColorTable = GetColorTable();
for (UINT iColor = 0; iColor < nColors; iColor++)
{
pColorTable[iColor].rgbReserved = 0;
pColorTable[iColor].rgbBlue = pRGB[iColor].rgbBlue;
pColorTable[iColor].rgbRed = pRGB[iColor].rgbRed;
pColorTable[iColor].rgbGreen = pRGB[iColor].rgbGreen;
}
return TRUE;
}
//#endif // DIBSECTION_NO_PALETTE
// --- In?: hdc - the Device Context in which the DIBSection is selected
// hBitmap - the bitmap whose solor entries are to be queried
// lpbi - a pointer to a BITMAPINFO structure that will have it's
// color table filled.
// --- Out :
// --- Returns : the number of colors placed in the color table
// --- Effect : This function is a replacement for GetDIBits, in that it retrieves
// (or synthesizes) the color table from the given bitmap, and stores
// the values in the BITMAPINFO structure supplied.
//
///////////////////////////////////////////////////////////////////////////////
UINT CDIB::GetColorTableEntries(HDC hdc, HBITMAP hBitmap)
{
if (!m_iColorTableSize)
return 0;
// Fill the color table with the colors from the bitmap's color table
LPRGBQUAD pColorTable = GetColorTable();
// Get the color table from the HBITMAP and copy them over.
UINT nCount;
RGBQUAD* pRGB = new RGBQUAD[m_iColorTableSize];
if (pRGB)
{
HBITMAP hOldBitmap = (HBITMAP) SelectObject(hdc, hBitmap);
nCount = CEGetDIBColorTable(hdc, 0, m_iColorTableSize, pRGB);
SelectObject(hdc, hOldBitmap);
if (nCount)
{
// m_iColorTableSize = nCount;
memcpy(pColorTable, pRGB, nCount*sizeof(RGBQUAD));
}
}
delete [] pRGB;
// Didn't work - so synthesize one.
if (!nCount)
{
nCount = min( m_iColorTableSize, sizeof(ms_StdColors) / sizeof(ms_StdColors[0]) );
memcpy(pColorTable, ms_StdColors, nCount*sizeof(RGBQUAD));
}
return nCount;
}
///////////////////////////////////////////////////////////////////////////////
//
// This function is from the MS KB article "HOWTO: Get the Color Table of
// DIBSection in Windows CE".
//
// PARAMETERS:
// HDC - the Device Context in which the DIBSection is selected
/// UINT - the index of the first color table entry to retrieve
// UINT - the number of color table entries to retrieve
// RGBQUAD - a buffer large enough to hold the number of RGBQUAD
// entries requested
//
// RETURNS:
// UINT - the number of colors placed in the buffer
//
//
///////////////////////////////////////////////////////////////////////////////
UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors)
{
if (pColors == NULL)
return 0; // No place to put them, fail
// Get a description of the DIB Section
HBITMAP hDIBSection = (HBITMAP) GetCurrentObject( hdc, OBJ_BITMAP );
DIBSECTION ds;
DWORD dwSize = GetObject( hDIBSection, sizeof(DIBSECTION), &ds );
if (dwSize != sizeof(DIBSECTION))
return 0; // Must not be a DIBSection, fail
if (ds.dsBmih.biBitCount > 8)
return 0; // Not Palettized, fail
// get the number of colors to return per BITMAPINFOHEADER docs
UINT cColors;
if (ds.dsBmih.biClrUsed)
cColors = ds.dsBmih.biClrUsed;
else
cColors = 1 << (ds.dsBmih.biBitCount * ds.dsBmih.biPlanes);
// Create a mask for the palette index bits for 1, 2, 4, and 8 bpp
WORD wIndexMask = (0xFF << (8 - ds.dsBmih.biBitCount)) & 0x00FF;
// Get the pointer to the image bits
LPBYTE pBits = (LPBYTE) ds.dsBm.bmBits;
// Initialize the loop variables
cColors = min( cColors, cEntries );
BYTE OldPalIndex = *pBits;
UINT TestPixelY;
if (ds.dsBmih.biHeight > 0 )
// If button up DIB, pBits points to last row
TestPixelY = ds.dsBm.bmHeight-1;
else
// If top down DIB, pBits points to first row
TestPixelY = 0;
for (UINT iColor = uStartIndex; iColor < cColors; iColor++)
{
COLORREF rgbColor;
// Set the palette index for the test pixel,
// modifying only the bits for one pixel
*pBits = (iColor << (8 - ds.dsBmih.biBitCount)) | (*pBits & ~wIndexMask);
// now get the resulting color
rgbColor = GetPixel( hdc, 0, TestPixelY );
pColors[iColor - uStartIndex].rgbReserved = 0;
pColors[iColor - uStartIndex].rgbBlue = GetBValue(rgbColor);
pColors[iColor - uStartIndex].rgbRed = GetRValue(rgbColor);
pColors[iColor - uStartIndex].rgbGreen = GetGValue(rgbColor);
}
// Restore the test pixel
*pBits = OldPalIndex;
return cColors;
}
///////////////////////////////////////////////////////////////////////////////
//
// --- In?: pDC - device context to use when calling CreateCompatibleDC
// bSelectPalette - if TRUE, the current palette will be preselected
// --- Out :
// --- Returns : A pointer to a memory DC
// --- Effect : Creates a memory DC and selects in the current bitmap so it can be
// modified using the GDI functions. Only one memDC can be created for
// a given CDIB object. If you have a memDC but wish to recreate it
// as compatible with a different DC, then call ReleaseMemoryDC first.
// If the memory DC has already been created then it will be recycled.
// Note that if using this in an environment where the color depth of
// the screen may change, then you will need to set "m_bReuseMemDC" to FALSE
//
///////////////////////////////////////////////////////////////////////////////
HDC CDIB::GetMemoryDC(HDC hDC /*=NULL*/, BOOL bSelectPalette /*=TRUE*/)
{
#ifdef DIBSECTION_NO_MEMDC_REUSE
ReleaseMemoryDC(TRUE);
#else
if (!m_bReuseMemDC)
{
ReleaseMemoryDC(TRUE);
}
else if (m_hMemDC) // Already created?
{
return m_hMemDC;
}
#endif // DIBSECTION_NO_MEMDC_REUSE
// Create a memory DC compatible with the given DC
m_hMemDC = CreateCompatibleDC(hDC);
if (!m_hMemDC)
return NULL;
// Select in the bitmap
m_hOldBitmap = (HBITMAP) ::SelectObject(m_hMemDC, m_hBitmap);
// Select in the palette
if (bSelectPalette && UsesPalette(m_hMemDC))
{
// Palette should already have been created - but just in case...
if (!m_hPal)
CreatePalette();
m_hOldPal = SelectPalette( m_hMemDC, m_hPal, FALSE );
RealizePalette( m_hMemDC );
}
else
m_hOldPal = NULL;
return m_hMemDC;
}
///////////////////////////////////////////////////////////////////////////////
//
// --- In?: bForceRelease - if TRUE, then the memory DC is forcibly released
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Selects out the current bitmap and deletes the mem dc. If bForceRelease
// is FALSE, then the DC release will not actually occur. This is provided
// so you can have
//
// GetMemoryDC(...)
// ... do something
// ReleaseMemoryDC()
//
// bracketed calls. If m_bReuseMemDC is subsequently set to FALSE, then
// the same code fragment will still work.
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDIB::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/)
{
if ( !m_hMemDC
#ifndef DIBSECTION_NO_MEMDC_REUSE
|| (m_bReuseMemDC && !bForceRelease)
#endif // DIBSECTION_NO_MEMDC_REUSE
)
return TRUE; // Nothing to do
// Select out the current bitmap
if (m_hOldBitmap)
::SelectObject(m_hMemDC, m_hOldBitmap);
m_hOldBitmap = NULL;
#ifndef DIBSECTION_NO_PALETTE
// Select out the current palette
if (m_hOldPal)
SelectPalette(m_hMemDC, m_hOldPal, FALSE);
m_hOldPal = NULL;
#endif // DIBSECTION_NO_PALETTE
// Delete the memory DC
return DeleteDC(m_hMemDC);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -