📄 dibsectn.cpp
字号:
)
{
HANDLE hFile;
BITMAPFILEHEADER bfh;
LPBITMAPINFO pbmi;
DWORD dwTotalDIBBytes, dwSize, dwWritten;
LPBYTE pBits;
// Open the file for writing (overwrites any previous version of that file)
if( (hFile=CreateFile(szFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE )
return FALSE;
// Get the BITMAPINFO for the DIBSection
if( (pbmi = DSGetBITMAPINFOForDIBSection( hBitmap )) == NULL )
{
CloseHandle( hFile );
return FALSE;
}
// What's the total size of the DIB information (not counting file header)?
dwTotalDIBBytes = DSTotalBytesSize( pbmi );
// Construct the file header
ZeroMemory( &bfh, sizeof(BITMAPFILEHEADER) );
bfh.bfType = 0x4d42; // 'BM'
bfh.bfSize = dwTotalDIBBytes + sizeof(BITMAPFILEHEADER);
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + pbmi->bmiHeader.biSize + DSColorTableSize(pbmi) );
// Write the file header
if( ( ! WriteFile( hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL ) ) ||
( dwWritten != sizeof(BITMAPFILEHEADER) ) )
{
free( pbmi );
CloseHandle( hFile );
return FALSE;
}
// Write the BITMAPINFO
dwSize = sizeof(BITMAPINFOHEADER) + DSColorTableSize( pbmi );
if( ( ! WriteFile( hFile, pbmi, dwSize, &dwWritten, NULL ) ) ||
( dwWritten != dwSize ) )
{
free( pbmi );
CloseHandle( hFile );
return FALSE;
}
// Write the bits
pBits = DSGetPointerToDIBSectionImageBits( hBitmap );
dwSize = DSImageBitsSize( pbmi );
if( ( ! WriteFile( hFile, pBits, dwSize, &dwWritten, NULL ) ) ||
( dwWritten != dwSize ) )
{
free( pbmi );
CloseHandle( hFile );
return FALSE;
}
// clean up and leave
free( pbmi );
CloseHandle( hFile );
return TRUE;
}
/*!
Creates a palette to be used to display the DIBSection on a
palettized display device.
If the DIBSection contains a color table, those colors are used
to create the palette. However, if the DIBSection is greater than
8bpp (ie sans color table), then a suitable palette is derived
from either CreateHalftonePalette() or GetStockObject() depending
on the video mode.
\return
a palette which can be used to display the DIBSection on palettized devices
*/
HPALETTE DSCreatePaletteForDIBSection(
HBITMAP hBitmap //!< a DIBSection for which to get a palette
)
{
BITMAP bm;
HPALETTE hPalette;
// Get the color depth of the DIBSection
GetObject( hBitmap, sizeof(BITMAP), &bm );
// If the DIBSection is 256 color or less, it has a color table
if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 )
{
HDC hMemDC;
HBITMAP hOldBitmap;
RGBQUAD rgb[256];
LPLOGPALETTE pLogPal;
WORD i;
int nColors;
// Find out how many colors are in the color table
nColors = 1 << ( bm.bmBitsPixel * bm.bmPlanes );
// Create a memory DC and select the DIBSection into it
hMemDC = CreateCompatibleDC( NULL );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
// Get the DIBSection's color table
GetDIBColorTable( hMemDC, 0, nColors, rgb );
// Create a palette from the color table
pLogPal = (LOGPALETTE*)malloc( sizeof(LOGPALETTE) + (nColors*sizeof(PALETTEENTRY)) );
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = WORD( nColors );
for(i=0;i<nColors;i++)
{
pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
}
hPalette = CreatePalette( pLogPal );
// Clean up
free( pLogPal );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else // It has no color table, so make one up
{
hPalette = DSCreateSpectrumPalette();
}
return hPalette;
}
/*!
The returned BITMAPINFO contains a color table, even if the
bit-depth does not require one - this way the caller can override
the optional color table if need be.
The caller is responsible for de-allocating the memory block using
the CRT function free().
\return
a pointer to a newly allocated memory block containing
the BITMAPINFO structure which describes the DIBSection.
*/
LPBITMAPINFO DSGetBITMAPINFOForDIBSection(
HBITMAP hBitmap //!< a DIBSection for which to get the BITMAPINFO
)
{
LPBITMAPINFO pbmi;
DIBSECTION ds;
LPRGBQUAD prgb;
GetObject( hBitmap, sizeof(DIBSECTION), &ds );
// load the header and the bitmasks if present
// per function comments above, we allocate space for a color
// table even if it is not needed
if( ds.dsBmih.biCompression == BI_BITFIELDS )
{ // has a bitmask - be sure to allocate for and copy them
pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) + (256*sizeof(RGBQUAD)) );
CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) + (3*sizeof(DWORD)) );
prgb = (LPRGBQUAD)&(pbmi->bmiColors[3]);
}
else
{ // no bitmask - just the header and color table
pbmi = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + (256*sizeof(RGBQUAD)) );
CopyMemory( &(pbmi->bmiHeader), &(ds.dsBmih), sizeof(BITMAPINFOHEADER) );
prgb = pbmi->bmiColors;
}
// at this point, prgb points to the color table, even
// if bitmasks are present
// Now for the color table
if( ( ds.dsBm.bmBitsPixel * ds.dsBm.bmPlanes ) <= 8 )
{ // the DIBSection is 256 color or less (has color table)
HDC hMemDC;
HBITMAP hOldBitmap;
hMemDC = CreateCompatibleDC( NULL );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
GetDIBColorTable( hMemDC, 0, 1<<(ds.dsBm.bmBitsPixel*ds.dsBm.bmPlanes), prgb );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else
{ // the DIBSection is >8bpp (has no color table) so make one up
HPALETTE hPal;
PALETTEENTRY pe[256];
int i;
// where are we going to get the colors? from a spectrum palette
hPal = DSCreateSpectrumPalette();
GetPaletteEntries( hPal, 0, 256, pe );
for(i=0;i<256;i++)
{
prgb[i].rgbRed = pe[i].peRed;
prgb[i].rgbGreen = pe[i].peGreen;
prgb[i].rgbBlue = pe[i].peBlue;
prgb[i].rgbReserved = 0;
}
::DeleteObject( hPal );
pbmi->bmiHeader.biClrUsed = 256;
}
return pbmi;
}
/*!
\return
the size, in bytes, of the color table for the DIB
*/
DWORD DSColorTableSize(
LPBITMAPINFO pbmi //!< pointer to a BITMAPINFO describing a DIB
)
{
DWORD dwColors;
dwColors = 0;
if( pbmi->bmiHeader.biClrUsed != 0 )
dwColors = pbmi->bmiHeader.biClrUsed;
else if( pbmi->bmiHeader.biBitCount > 8 )
dwColors = 0;
else
dwColors = 1 << (pbmi->bmiHeader.biBitCount * pbmi->bmiHeader.biPlanes);
if( pbmi->bmiHeader.biCompression == BI_BITFIELDS )
return (sizeof(DWORD)*3) + (dwColors*sizeof(RGBQUAD));
return (dwColors*sizeof(RGBQUAD));
}
/*!
\return
the size, in bytes, of the DIB's image bits
*/
DWORD DSImageBitsSize(
LPBITMAPINFO pbmi //!< pointer to a BITMAPINFO describing a DIB
)
{
switch( pbmi->bmiHeader.biCompression )
{
case BI_RLE8:
case BI_RLE4:
return pbmi->bmiHeader.biSizeImage;
break;
default: // should not have to use "default"
case BI_RGB:
case BI_BITFIELDS:
return BYTESPERLINE(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biBitCount*pbmi->bmiHeader.biPlanes)*pbmi->bmiHeader.biHeight;
break;
}
// return 0;
}
/*!
\return
the size, in bytes, of the DIB's memory footprint
*/
DWORD DSTotalBytesSize(
LPBITMAPINFO pbmi //!< pointer to a BITMAPINFO describing a DIB
)
{
return DSImageBitsSize(pbmi) + sizeof(BITMAPINFOHEADER) + DSColorTableSize(pbmi);
}
/*!
\return
pointer to the bitmap's bits
*/
LPBYTE DSGetPointerToDIBSectionImageBits(
HBITMAP hBitmap //!< handle for HBITMAP DIBSection
)
{
DIBSECTION ds;
GetObject( hBitmap, sizeof(DIBSECTION), &ds );
return (LPBYTE)ds.dsBm.bmBits;
}
/*!
This function was stolen from Mike Irvine's SEEDIB sample. There's
no source code comments in his version either :)
This function will build a palette with a spectrum of colors. It is
useful when you want to display a number of DIBs each with a different
palette yet still have an a good selection of colors to which the
DIBs' colors will be mapped.
\return
a handle to a spectrum palette - NULL on failure
*/
HPALETTE DSCreateSpectrumPalette( void )
{
HPALETTE hPal;
LPLOGPALETTE lplgPal;
BYTE red, green, blue;
int i;
lplgPal = (LPLOGPALETTE)GlobalAlloc( GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 );
if (!lplgPal)
return NULL;
lplgPal->palVersion = 0x300;
lplgPal->palNumEntries = 256;
red = green = blue = 0;
for (i = 0; i < 256; i++) {
lplgPal->palPalEntry[i].peRed = red;
lplgPal->palPalEntry[i].peGreen = green;
lplgPal->palPalEntry[i].peBlue = blue;
lplgPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
if (!(green += 32))
blue += 64;
}
hPal = CreatePalette(lplgPal);
GlobalFree(lplgPal);
return hPal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -