📄 dibsectn.cpp
字号:
//-----------------------------------------------------------------------------
// (c) 2002 by Basler Vision Technologies
// Section: Vision Components
// Project: BVC
// $Header: DibSectn.cpp, 2, 25.09.2003 12:36:45, Nebelung, H.$
//-----------------------------------------------------------------------------
/**
\file DIBSECTN.CPP
\brief Implementaiton for the DIBSections functions
- Most of the functions in this module which are passed an HBITMAP
as a parameter assume the HBITMAP is not selected into a device
context at the time of the call. Since the underlying APIs usually
require this, so do these functions.
- Throughout this module, code is in place to handle color tables
in DIBSections (in the BITMAPINFO) even when it is not necessary.
This helps the re-usability of the code, since it is often desirable
to include a "suggested" color table when storing 16bpp or higher
BMP files.
*/
#include <stdafx.h>
#include <memory.h>
#include <bvcexception.h>
#include "DibSectn.h"
using namespace Bvc;
/*! Macro to determine the number of bytes per line in the DIB bits. This
accounts for DWORD alignment by adding 31 bits, then dividing by 32,
then rounding up to the next highest count of 4-bytes. Then, we
multiply by 4 to get the total byte count.
*/
#define BYTESPERLINE(Width, BPP) ((WORD)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
/*!
The DIBSection is created with a default color table - for 8bpp and
above, this is a spectrum palette. For 4bpp, it is a stock 16 color
table, and for 1bpp it is black and white.
\return
- HBITMAP a DIBSection HBITMAP of the desired size and bit-depth
- NULL on failure
*/
HBITMAP DSCreateDIBSection(
LONG dwX, //!< Desired width of the DIBSection
LONG dwY, //!< Desired height of the DIBSection
WORD wBits, //!< Desired bit-depth of the DIBSection
BOOL Monochrome //!< If wBits=8 and Monochrome=true the palette will contain grey values only
)
{
HBITMAP hBitmap;
LPBYTE pBits;
int nInfoSize;
LPBITMAPINFO pbmi;
HDC hRefDC;
nInfoSize = sizeof( BITMAPINFOHEADER );
if( wBits <= 8 )
nInfoSize += sizeof(RGBQUAD) * (1 << wBits);
if( ( wBits == 16 ) || ( wBits == 32 ) )
nInfoSize += 3 * sizeof(DWORD);
// Create the header big enough to contain color table and bitmasks if needed
pbmi = (LPBITMAPINFO)malloc( nInfoSize );
ZeroMemory( pbmi, nInfoSize );
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = dwX;
pbmi->bmiHeader.biHeight = dwY;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = wBits;
pbmi->bmiHeader.biCompression = BI_RGB; // override below for 16 and 32bpp
switch( wBits )
{
case 24:
// 24bpp requires no special handling
break;
case 16:
{ // if it's 16bpp, fill in the masks and override the compression
// these are the default masks - you could change them if needed
LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
pMasks[0] = 0x00007c00;
pMasks[1] = 0x000003e0;
pMasks[2] = 0x0000001f;
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
}
break;
case 32:
{ // if it's 32bpp, fill in the masks and override the compression
// these are the default masks - you could change them if needed
LPDWORD pMasks = (LPDWORD)(pbmi->bmiColors);
pMasks[0] = 0x00ff0000;
pMasks[1] = 0x0000ff00;
pMasks[2] = 0x000000ff;
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
}
break;
case 8:
{
if(Monochrome)
{
int i;
for(i=0;i<256;i++)
{
pbmi->bmiColors[i].rgbRed = BYTE( i );
pbmi->bmiColors[i].rgbGreen = BYTE( i );
pbmi->bmiColors[i].rgbBlue = BYTE( i );
pbmi->bmiColors[i].rgbReserved = BYTE( 0 );
}
pbmi->bmiHeader.biClrUsed = 256;
}
else // color
{
HPALETTE hPal;
PALETTEENTRY pe[256];
int i;
// at this point, prgb points to the color table, even
// if bitmasks are present
hPal = DSCreateSpectrumPalette();
GetPaletteEntries( hPal, 0, 256, pe );
for(i=0;i<256;i++)
{
pbmi->bmiColors[i].rgbRed = pe[i].peRed;
pbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
pbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
pbmi->bmiColors[i].rgbReserved = 0;
}
::DeleteObject( hPal );
pbmi->bmiHeader.biClrUsed = 256;
}
}
break;
case 4:
{ // Use a default 16 color table for 4bpp DIBSections
RGBTRIPLE rgb[16] = { { 0x00, 0x00, 0x00 }, // black
{ 0x80, 0x00, 0x00 }, // dark red
{ 0x00, 0x80, 0x00 }, // dark green
{ 0x80, 0x80, 0x00 }, // dark yellow
{ 0x00, 0x00, 0x80 }, // dark blue
{ 0x80, 0x00, 0x80 }, // dark magenta
{ 0x00, 0x80, 0x80 }, // dark cyan
{ 0xC0, 0xC0, 0xC0 }, // light gray
// { 0xC0, 0xDC, 0xC0 }, // money green
// { 0xA6, 0xCA, 0xF0 }, // sky blue
// { 0xFF, 0xFB, 0xF0 }, // cream
// { 0xA0, 0xA0, 0xA4 }, // light gray
{ 0x80, 0x80, 0x80 }, // medium gray
{ 0xFF, 0x00, 0x00 }, // red
{ 0x00, 0xFF, 0x00 }, // green
{ 0xFF, 0xFF, 0x00 }, // yellow
{ 0x00, 0x00, 0xFF }, // blue
{ 0xFF, 0x00, 0xFF }, // magenta
{ 0x00, 0xFF, 0xFF }, // cyan
{ 0xFF, 0xFF, 0xFF } }; // white
int i;
for(i=0;i<16;i++)
{
pbmi->bmiColors[i].rgbRed = rgb[i].rgbtRed;
pbmi->bmiColors[i].rgbGreen = rgb[i].rgbtGreen;
pbmi->bmiColors[i].rgbBlue = rgb[i].rgbtBlue;
pbmi->bmiColors[i].rgbReserved = 0;
}
pbmi->bmiHeader.biClrUsed = 16;
}
break;
case 1: // BW
pbmi->bmiColors[0].rgbRed = pbmi->bmiColors[0].rgbGreen = pbmi->bmiColors[0].rgbBlue = 0;
pbmi->bmiColors[1].rgbRed = pbmi->bmiColors[1].rgbGreen = pbmi->bmiColors[1].rgbBlue = 255;
pbmi->bmiColors[0].rgbReserved = pbmi->bmiColors[1].rgbReserved = 0;
break;
}
// Try to create the bitmap section
hRefDC = GetDC( NULL );
hBitmap = ::CreateDIBSection( hRefDC, pbmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 );
int LastError = GetLastError();
ReleaseDC( NULL, hRefDC );
free( pbmi );
if( hBitmap == NULL )
{
throw BvcException( LastError, _T( "DSCreateDIBSection" ) );
}
return hBitmap;
}
/*!
If the HPALETTE pointer is NULL, no palette is retreived.
If the HPALETTE pointer is non-NULL, the palette is created by
calling DSCreatePaletteForDIBSection. See its comments for
information regarding its functionality.
The LoadImage() API is used to load the bitmap.
\return
- TRUE for success
- FALSE for failure
*/
BOOL DSLoadDIBSectionFromBMPFile(
LPCTSTR szFileName, //!< Name of (BMP) file from which to obtain DIBSection
HBITMAP *phBitmap, //!< Pointer to handle which receives HBITMAP DIBSection
HPALETTE *phPalette //!< Pointer to handle which receives Palette
)
{
if( phBitmap == NULL )
throw BvcException( Bvc::ErrorNumber( E_POINTER ), _T( "DSLoadDIBSectionFromBMPFile" ) );
*phBitmap = NULL;
if( phPalette != NULL )
*phPalette = NULL;
// Use LoadImage() to get the image loaded into a DIBSection
*phBitmap = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
if( *phBitmap == NULL )
throw BvcException( ::GetLastError(), _T( "DSLoadDIBSectionFromBMPFile" ) );
// if they want a palette, get one
if( phPalette != NULL )
*phPalette = DSCreatePaletteForDIBSection( *phBitmap );
return TRUE;
}
/*!
The bitmap is drawn using StretchBlt() if the target DC is a screen
DC and StretchDIBits() otherwise.
A pallete is used, only if the target DC is a screen DC. A more
robust implementation might check RASTERCAPS to see if the target
device is a palettized device.
Also, the palette is selected as a background palette. If it is
desirable to have the palette as a foreground palette, simply
obtain and realize the palette in the foreground before calling
this function.
\return
- TRUE for success
- FALSE for failure
*/
BOOL DSDrawDIBSectionOnDC(
HDC hDC, //< HDC on which to draw the DIBSection
HBITMAP hBitmap, //< the DIBSection to be drawn
LPRECT pRect //< pointer to a rectangle containing the target coordinates
)
{
DIBSECTION ds;
HPALETTE hPal = NULL, hOldPal = NULL;
BOOL bRes;
GetObject( hBitmap, sizeof(DIBSECTION), &ds );
if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
{ // if it's a palette device, select and realize a palette
// as a background palette (won't cause a problem is the
// palette was not selected in the foreground in the main app
hPal = DSCreatePaletteForDIBSection( hBitmap );
hOldPal = SelectPalette( hDC, hPal, TRUE );
RealizePalette( hDC );
}
if( GetDeviceCaps( hDC, TECHNOLOGY ) == DT_RASDISPLAY )
{ // going to the screen, use StretchBlt()
HDC hMemDC;
HBITMAP hOldBitmap;
hMemDC = CreateCompatibleDC( hDC );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap );
bRes = StretchBlt( hDC, pRect->left, pRect->top,
pRect->right-pRect->left, pRect->bottom-pRect->top,
hMemDC, 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, SRCCOPY );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
}
else
{ // going to the printer, use StretchDIBits()
LPBITMAPINFO pbmi;
// if the printer is palettized,
pbmi = DSGetBITMAPINFOForDIBSection( hBitmap );
bRes = (GDI_ERROR != StretchDIBits( hDC, pRect->left, pRect->top,
pRect->right-pRect->left, pRect->bottom-pRect->top,
0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBits,
pbmi, DIB_RGB_COLORS, SRCCOPY ));
free( pbmi );
}
if( GetDeviceCaps( hDC, RASTERCAPS ) & RC_PALETTE )
{
SelectPalette( hDC, hOldPal, TRUE );
::DeleteObject( hPal );
}
return bRes;
}
/*!
\return
- TRUE for success
- FALSE for failure
*/
BOOL DSStoreDIBSectionInBMPFile(
LPCTSTR szFileName, //< Name of (BMP) file in which to store the DIBSection
HBITMAP hBitmap //< handle for HBITMAP DIBSection to be stored
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -