📄 dibsectionce.cpp
字号:
BOOL CDIBSectionCE::Load(LPCTSTR lpszFileName)
{
CFile file;
if (!file.Open(lpszFileName, CFile::modeRead))
return FALSE;
// Get the current file position.
DWORD dwFileStart = (DWORD)file.GetPosition();
// The first part of the file contains the file header.
// This will tell us if it is a bitmap, how big the header is, and how big
// the file is. The header size in the file header includes the color table.
BITMAPFILEHEADER BmpFileHdr;
int nBytes;
nBytes = file.Read(&BmpFileHdr, sizeof(BmpFileHdr));
if (nBytes != sizeof(BmpFileHdr))
{
TRACE0("Failed to read file header\n");
return FALSE;
}
// Check that we have the magic 'BM' at the start.
if (BmpFileHdr.bfType != DS_BITMAP_FILEMARKER)
{
TRACE0("Not a bitmap file\n");
return FALSE;
}
// Read the header (assuming it's a DIB).
DIBINFO BmpInfo;
nBytes = file.Read(&BmpInfo, sizeof(BITMAPINFOHEADER));
if (nBytes != sizeof(BITMAPINFOHEADER))
{
TRACE0("Failed to read BITMAPINFOHEADER\n");
return FALSE;
}
// Check that we have a real Windows DIB file.
if (BmpInfo.bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
{
TRACE0(" File is not a Windows DIB\n");
return FALSE;
}
// See how big the color table is in the file (if there is one).
int nColors = NumColorEntries(BmpInfo.bmiHeader.biBitCount);
if (nColors > 0)
{
// Read the color table from the file.
int nColorTableSize = nColors * sizeof(RGBQUAD);
nBytes = file.Read(BmpInfo.ColorTable(), nColorTableSize);
if (nBytes != nColorTableSize)
{
TRACE0("Failed to read color table\n");
return FALSE;
}
}
// So how big the bitmap surface is.
int nBitsSize = BmpFileHdr.bfSize - BmpFileHdr.bfOffBits;
// Allocate the memory for the bits and read the bits from the file.
BYTE* pBits = (BYTE*) malloc(nBitsSize);
if (!pBits)
{
TRACE0("Out of memory for DIB bits\n");
return FALSE;
}
// Seek to the bits in the file.
file.Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin);
// read the bits
nBytes = file.Read(pBits, nBitsSize);
if (nBytes != nBitsSize)
{
TRACE0("Failed to read bits\n");
free(pBits);
return FALSE;
}
// Everything went OK.
BmpInfo.bmiHeader.biSizeImage = nBitsSize;
if (!SetBitmap((LPBITMAPINFO) BmpInfo, pBits))
{
TRACE0("Failed to set bitmap info\n");
free(pBits);
return FALSE;
}
TRY {
free(pBits);
}
CATCH (CException, e)
{
TRACE0("wrong to free pBites\n");
}
END_CATCH
return TRUE;
}
// --- In?: lpszFileName - image filename
// --- Out :
// --- Returns : Returns TRUE on success, FALSE otherwise
// --- Effect : Saves the image to file.
#ifndef DIBSECTION_NO_PALETTE
// --- 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 CDIBSectionCE::CreatePalette()
{
m_Palette.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_Palette, 256);
// Get space for the colour entries
RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize];
if (!pRGB)
return CreateHalftonePalette(m_Palette, m_iColorTableSize);
HDC hDC = ::GetDC(NULL);
if (!hDC)
{
delete [] pRGB;
return FALSE;
}
// Create a memory DC compatible with the current DC
CDC MemDC;
MemDC.CreateCompatibleDC(CDC::FromHandle(hDC));
if (!MemDC.GetSafeHdc())
{
delete [] pRGB;
::ReleaseDC(NULL, hDC);
return CreateHalftonePalette(m_Palette, m_iColorTableSize);
}
::ReleaseDC(NULL, hDC);
HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap);
if (!hOldBitmap)
{
delete [] pRGB;
return CreateHalftonePalette(m_Palette, m_iColorTableSize);
}
// Get the colours 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.
#ifdef _WIN32_WCE
int nColours = ::CEGetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB);
#else
int nColours = ::GetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB);
#endif
// Clean up
::SelectObject(MemDC.GetSafeHdc(), hOldBitmap);
if (!nColours) // No colours retrieved => the bitmap in the DC is not a DIB section
{
delete [] pRGB;
return CreateHalftonePalette(m_Palette, m_iColorTableSize);
}
// Create and fill a LOGPALETTE structure with the colours used.
PALETTEINFO PaletteInfo;
PaletteInfo.palNumEntries = (WORD) m_iColorTableSize;
for (int i = 0; i < nColours; i++)
{
PaletteInfo.palPalEntry[i].peRed = pRGB[i].rgbRed;
PaletteInfo.palPalEntry[i].peGreen = pRGB[i].rgbGreen;
PaletteInfo.palPalEntry[i].peBlue = pRGB[i].rgbBlue;
PaletteInfo.palPalEntry[i].peFlags = 0;
}
for (int j = 0; j < (int) m_iColorTableSize; j++)
{
PaletteInfo.palPalEntry[j].peRed = 0;
PaletteInfo.palPalEntry[j].peGreen = 0;
PaletteInfo.palPalEntry[j].peBlue = 0;
PaletteInfo.palPalEntry[j].peFlags = 0;
}
delete [] pRGB;
// Create Palette!
return m_Palette.CreatePalette(&PaletteInfo);
}
// --- 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 CDIBSectionCE::SetPalette(CPalette* pPalette)
{
m_Palette.DeleteObject();
if (!pPalette)
return FALSE;
UINT nColours = pPalette->GetEntryCount();
if (nColours <= 0 || nColours > 256)
return FALSE;
// Get palette entries
PALETTEINFO pi;
pi.palNumEntries = (WORD) pPalette->GetPaletteEntries(0, nColours, (LPPALETTEENTRY) pi);
// TODO: If pi.palNumEntries < m_iColorTableSize, then fill in blanks with 0's
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 CDIBSectionCE::SetLogPalette(LOGPALETTE* pLogPalette)
{
ASSERT(pLogPalette->palVersion == (WORD) 0x300);
UINT nColours = pLogPalette->palNumEntries;
if (nColours <= 0 || nColours > 256)
{
CreatePalette();
return FALSE;
}
// Create new palette
m_Palette.DeleteObject();
if (!m_Palette.CreatePalette(pLogPalette))
{
CreatePalette();
return FALSE;
}
if (m_iColorTableSize == 0)
return TRUE;
// Set the DIB colours
RGBQUAD RGBquads[256];
for (UINT i = 0; i < nColours; 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(nColours, RGBquads);
}
// --- In?: nNumColours - number of colours to set
// pRGB - colours to fill
// --- Out :
// --- Returns : Returns TRUE on success
// --- Effect : Sets the colours used by the image. Only works if # colours <= 256
BOOL CDIBSectionCE::FillDIBColorTable(UINT nNumColours, RGBQUAD *pRGB)
{
if (!pRGB || !nNumColours || !m_iColorTableSize || nNumColours > 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(nNumColours, 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 CDIBSectionCE::GetColorTableEntries(HDC hdc, HBITMAP hBitmap)
{
UINT nColorTableSize = m_iColorTableSize;
if (!nColorTableSize)
return 0;
// Fill the color table with the colours 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[nColorTableSize];
if (pRGB)
{
HBITMAP hOldBitmap = (HBITMAP) SelectObject(hdc, hBitmap);
nCount = CEGetDIBColorTable(hdc, 0, nColorTableSize, pRGB);
SelectObject(hdc, hOldBitmap);
if (nCount)
{
nColorTableSize = nCount;
memcpy(pColorTable, pRGB, nCount*sizeof(RGBQUAD));
}
}
delete [] pRGB;
// Didn't work - so synthesize one.
if (!nCount)
{
int nNumStandardColours = sizeof(ms_StdColours) / sizeof(ms_StdColours[0]);
UINT nIndex = 0;
// The standard colours (16)
for (int i = 0; i < nNumStandardColours; i++)
{
if (nIndex >= nColorTableSize)
break;
memcpy( &(pColorTable[i]), &(ms_StdColours[i]), sizeof(RGBQUAD) );
nIndex++;
}
// A colour cube (6 divisions = 216)
int i = 0;
for (int blue = 0; blue <= 5; blue++)
for (int green = 0; green <= 5; green++)
for (int red = 0; red <= 5; red++)
{
if (nIndex >= nColorTableSize)
break;
pColorTable[i].rgbRed = (BYTE) ((red*255)/5);
pColorTable[i].rgbGreen = (BYTE) ((green*255)/5);
pColorTable[i].rgbBlue = (BYTE) ((blue*255)/5);
pColorTable[i].rgbReserved = 0;
nIndex++;
}
// A grey scale (24 divisions)
for (int grey = 0; grey <= 23; grey++)
{
if (nIndex >= nColorTableSize)
break;
pColorTable[i].rgbRed = (BYTE) (grey*255/23);
pColorTable[i].rgbGreen = (BYTE) (grey*255/23);
pColorTable[i].rgbBlue = (BYTE) (grey*255/23);
pColorTable[i].rgbReserved = 0;
nIndex++;
}
}
return nColorTableSize;
}
/**********************************************************************
This function is from the MS KB article "HOWTO: Get the Color Table of
a 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -