📄 bvcdib.cpp
字号:
//-----------------------------------------------------------------------------
// (c) 2002 by Basler Vision Technologies
// Section: Vision Components
// Project: BVC
// $Header: BvcDib.cpp, 6, 12.04.2005 18:46:53, Nebelung, H.$
//-----------------------------------------------------------------------------
/**
\file BvcDib.cpp
*
\brief <type brief description here>
*
* <type long description here>
*/
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "BvcDib.h"
#include <assert.h>
#include "dibsectn.h"
/*! \def IPL_SUPPORT
If this symbol is defined CDib supports IPL's (= Intel Performance Library)
native image format IplImage.
*/
#ifdef IPL_SUPPORT
#include <ipl.h>
#endif
using namespace Bvc;
//! Default constructor
CDib::CDib() :
m_hBitmap(NULL),
m_Orientation(BottomUp),
m_PaletteType(Color),
m_RefCount(0)
{
#ifdef IPL_SUPPORT
m_pIplImage = NULL;
#endif
}
//! Destroy all BMP related resources
void CDib::Destroy()
{
// Destroy the referenced DIB section
if(m_hBitmap)
{
if(!::DeleteObject(m_hBitmap))
throw BvcException( ::GetLastError(), _T( "CDib::Destroy" ));
m_hBitmap = NULL;
}
#ifdef IPL_SUPPORT
// Destroy the IPL image header
if(m_pIplImage)
{
iplDeallocate( m_pIplImage, IPL_IMAGE_HEADER );
m_pIplImage = NULL;
}
#endif // #ifdef IPL_SUPPORT
}
//! Increments the reference counter of this object
long CDib::AddRef()
{
return ::InterlockedIncrement(&m_RefCount);
}
//! Decrements the reference counter of this object. Destroys the object if the reference counter becomes 0.
void CDib::Release()
{
::InterlockedDecrement(&m_RefCount);
if(0 == m_RefCount)
delete this;
}
//! Create a CDib object
CDib* CDib::Create( CSize Size, unsigned int BitsPerPixel, Orientation_t Orientation, PaletteType_t PaletteType )
{
CDib *pDib = new CDib();
pDib->m_Orientation = Orientation;
pDib->m_PaletteType = PaletteType;
pDib->m_hBitmap = DSCreateDIBSection( Size.cx, Orientation == BottomUp ? Size.cy : -Size.cy, WORD( BitsPerPixel ), PaletteType == Monochrome );
if(!pDib->m_hBitmap)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::Create" ) );
pDib->AddRef();
pDib->Refresh();
return pDib;
}
//! Loads the bitmap from a BMP file
CDib* CDib::LoadBMP( CString FileName )
{
CDib *pDib = new CDib();
if(!DSLoadDIBSectionFromBMPFile( (LPCTSTR) FileName, &pDib->m_hBitmap, NULL ))
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::LoadBMP" ) );
// BMP files are always bottom up
pDib->m_Orientation = BottomUp;
// Check if the image is Mono8
pDib->m_PaletteType = Color;
LPBITMAPINFO pBitmapInfo = DSGetBITMAPINFOForDIBSection( pDib->m_hBitmap );
if(pBitmapInfo->bmiHeader.biBitCount == 8)
{
for(int i=0; i<256; ++i)
{
if( pBitmapInfo->bmiColors[i].rgbRed != i
|| pBitmapInfo->bmiColors[i].rgbGreen != i
|| pBitmapInfo->bmiColors[i].rgbBlue != i )
break;
}
pDib->m_PaletteType = Monochrome;
}
free(pBitmapInfo);
pDib->AddRef();
pDib->Refresh();
return pDib;
}
//! Virtual destructor
CDib::~CDib()
{
Destroy();
}
//! checks if twobitmaps share the same properties
bool CDib::IsEqualType( const CDib& Dib ) const
{
BITMAP ThisBitmap;
BITMAP Bitmap;
GetBitmap(&ThisBitmap);
Dib.GetBitmap(&Bitmap);
return( Bitmap.bmType == ThisBitmap.bmType
&& Bitmap.bmWidth == ThisBitmap.bmWidth
&& Bitmap.bmHeight == ThisBitmap.bmHeight
&& Bitmap.bmWidthBytes == ThisBitmap.bmWidthBytes
&& Bitmap.bmPlanes == ThisBitmap.bmPlanes
&& Bitmap.bmBitsPixel == ThisBitmap.bmBitsPixel
&& Dib.m_Orientation == m_Orientation );
}
//! Stores the bitmap to a BMP file
void CDib::StoreBMP( CString FileName ) const
{
if( m_Orientation == TopDown )
{
// BMP file have to be stores bottom up so we have to topple it
HBITMAP hBitmap = GetToppledCopy();
DSStoreDIBSectionInBMPFile( (LPCTSTR) FileName, hBitmap);
::DeleteObject(hBitmap);
}
else
{
DSStoreDIBSectionInBMPFile( (LPCTSTR) FileName, m_hBitmap);
}
}
//! Gets a HBITMAP handle (no ownership is granted!)
HBITMAP CDib::GetBitmapHandle() const
{
return m_hBitmap;
}
//! Returns a pointer to the pixel data
void* CDib::GetPixels() const
{
BITMAP Bitmap;
if(!::GetObject(m_hBitmap, sizeof(BITMAP), &Bitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetPixels" ) );
return Bitmap.bmBits;
}
//! Returns the bitmap's size 1
void CDib::GetSize(CSize *pSize) const
{
assert(pSize);
if(!m_hBitmap)
{
pSize->cx = 0;
pSize->cy = 0;
}
else
{
BITMAP Bitmap;
if(!::GetObject(m_hBitmap, sizeof(BITMAP), &Bitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetSize" ) );
pSize->cx = Bitmap.bmWidth;
pSize->cy = Bitmap.bmHeight;
}
}
//! Returns the bitmap's size 2
CSize CDib::GetSize() const
{
CSize Size;
GetSize(&Size);
return Size;
}
//! Returns the total size of a line in bytes
unsigned long CDib::GetWidthBytes() const
{
BITMAP Bitmap;
if(!::GetObject(m_hBitmap, sizeof(BITMAP), &Bitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetSize" ) );
return Bitmap.bmWidthBytes;
}
//! Returns the total size of the image in bytes
unsigned long CDib::GetTotalPixelBytes() const
{
BITMAP Bitmap;
if(!::GetObject(m_hBitmap, sizeof(BITMAP), &Bitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetSize" ) );
return Bitmap.bmWidthBytes * Bitmap.bmHeight;
}
//! Returns the bitmap's bits per pixel
unsigned short CDib::GetBitsPerPixel() const
{
BITMAP Bitmap;
if(!::GetObject(m_hBitmap, sizeof(BITMAP), &Bitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetBitsPerPixel" ) );
return Bitmap.bmBitsPixel;
}
//! Returns the bitmaps orientation (BottomUp or TopDown)
CDib::Orientation_t CDib::GetOrientation() const
{
return m_Orientation;
}
//! Returns the bitmaps palette type (e.g., color or monochrome )
CDib::PaletteType_t CDib::GetPaletteType() const
{
return m_PaletteType;
}
//! Returns the bitmaps BITMAPINFORHEADER
void CDib::GetBitmapInfoHeader(BITMAPINFOHEADER *pBitmapInfoHeader) const
{
DIBSECTION DibSection;
if(!::GetObject(m_hBitmap, sizeof(DIBSECTION), &DibSection))
throw BvcException( ::GetLastError(), _T( "CDib::GetBitmapInfoHeader" ) );
::CopyMemory(pBitmapInfoHeader, &(DibSection.dsBmih), sizeof(BITMAPINFOHEADER));
}
//! Returns a bitmaps BITMAPINFO which has to be freed by the user
void CDib::GetBitmapInfo(BITMAPINFO **ppBitmapInfo, unsigned long *pBitmapInfoBytes) const
{
*ppBitmapInfo = DSGetBITMAPINFOForDIBSection( m_hBitmap );
*pBitmapInfoBytes = sizeof(BITMAPINFOHEADER) + DSColorTableSize( *ppBitmapInfo );
}
//! Returns the bitmaps BITMAP
void CDib::GetBitmap(BITMAP *pBitmap) const
{
if(!::GetObject(m_hBitmap, sizeof(BITMAP), pBitmap))
throw BvcException( ::GetLastError(), _T( "CDib::GetBitmap" ) );
}
//! Topples the bitmap
void CDib::Topple()
{
if (m_hBitmap == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::Topple - No bitmap present" ) );
HBITMAP hBitmap = GetToppledCopy();
Destroy();
m_hBitmap = hBitmap;
m_Orientation = m_Orientation == BottomUp ? TopDown : BottomUp;
Refresh();
}
//! Clones the Bitmap
CDib* CDib::Clone(
bool Topple //!< If true the clone will be toppled with resprect to the original bitmap
) const
{
if (m_hBitmap == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::Clone - No bitmap present" ) );
HBITMAP pBitmap = NULL;
if(Topple)
{
pBitmap = GetToppledCopy();
}
else
{
pBitmap = GetCopy();
}
CDib *pDib = new CDib();
pDib->m_hBitmap = pBitmap;
pDib->m_Orientation = Topple ? (m_Orientation == BottomUp ? TopDown : BottomUp) : m_Orientation;
pDib->m_PaletteType = m_PaletteType;
pDib->AddRef();
pDib->Refresh();
return pDib;
}
//! Copies the image to the clipboard
void CDib::CopyToClipboard()
{
if ( GetOrientation() == CDib::TopDown )
{
CDib* pDib = Clone(true);
if (pDib == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::CopyToClipboard" ) );
pDib->CopyToClipboard();
delete pDib;
}
else
{
HGLOBAL hGlobal = NULL;
try
{
if (m_hBitmap == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::CopyToClipboard - No bitmap present" ) );
// Get BITMAPINFO Header
LPBITMAPINFO pBitmapInfo;
pBitmapInfo = DSGetBITMAPINFOForDIBSection( m_hBitmap );
if(!pBitmapInfo)
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
// Create a suitable global memory buffer and lock it
DWORD TotalDIBBytes = DSTotalBytesSize( pBitmapInfo );
hGlobal = GlobalAlloc(GHND | GMEM_SHARE, TotalDIBBytes );
if(!hGlobal)
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
// Lock the global Buffer
char* pBuffer = (char*) GlobalLock(hGlobal);
if ( pBuffer == NULL )
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
// Copy the information header and the color table to the global Buffer
DWORD dwHeaderSize = sizeof(BITMAPINFOHEADER) + DSColorTableSize( pBitmapInfo );
CopyMemory(pBuffer, &pBitmapInfo->bmiHeader, dwHeaderSize);
// Copy the image data to the global buffer
LPBYTE pBits = DSGetPointerToDIBSectionImageBits( m_hBitmap );
DWORD dwSize = DSImageBitsSize( pBitmapInfo );
CopyMemory(((PBYTE) pBuffer) + dwHeaderSize, pBits, dwSize);
// Clean up
free(pBitmapInfo);
GlobalUnlock(hGlobal);
// set the buffer to the clipboard
if(!::OpenClipboard(NULL))
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
if(!::EmptyClipboard())
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
if(!::SetClipboardData(CF_DIB, hGlobal))
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
if(!::CloseClipboard())
throw BvcException( ::GetLastError(), _T( "CDib::CopyToClipboard" ) );
}
catch(BvcException e)
{
if(hGlobal)
::GlobalFree(hGlobal);
throw e;
}
}
}
//! Returns a DIB section which is a copy of the referenced bitmap
HBITMAP CDib::GetCopy() const
{
if (m_hBitmap == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::GetCopy - No bitmap present" ) );
LPBITMAPINFO pBitmap = DSGetBITMAPINFOForDIBSection(m_hBitmap);
if (! pBitmap) throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::GetCopy - No bitmap info present" ) );
pBitmap->bmiHeader.biHeight = m_Orientation == TopDown ? -pBitmap->bmiHeader.biHeight : pBitmap->bmiHeader.biHeight;
LPBYTE pSrc = DSGetPointerToDIBSectionImageBits(m_hBitmap);
if (!pSrc) throw BvcException( ::GetLastError(), _T( "CDib::GetCopy" ) );
LPBYTE pDst = NULL;
HBITMAP hBitmap = ::CreateDIBSection( NULL, pBitmap, DIB_RGB_COLORS, (void**)&pDst, NULL, 0 );
const size_t imagesize = pBitmap->bmiHeader.biSizeImage;
free(pBitmap);
if(hBitmap == NULL || pDst == NULL)
throw BvcException( ::GetLastError(), _T( "CDib::GetCopy" ) );
memcpy( pDst, pSrc, imagesize );
return hBitmap;
}
//! Returns a DIB section which is a toppled copy of the referenced bitmap
HBITMAP CDib::GetToppledCopy() const
{
if (m_hBitmap == NULL)
throw BvcException( Bvc::ErrorNumber( E_FAIL ), _T( "CDib::GetToppledCopy - No bitmap present" ) );
LPBITMAPINFO pBitmap = DSGetBITMAPINFOForDIBSection(m_hBitmap);
if (!pBitmap) throw BvcException( ::GetLastError(), _T( "CDib::GetToppledCopy" ) );
LPBYTE pSrc = DSGetPointerToDIBSectionImageBits(m_hBitmap);
if (!pSrc) throw BvcException( ::GetLastError(), _T( "CDib::GetToppledCopy" ) );
// Create a version of the image which is top down if the original image was bottom up
// and vice versa.
// BEWARE : For some strange reason the newly created image will have a biHeight > 0
// even if we created it with biHeight < 0. Nevertheless the bitmap object somehow
// remembers the fact that it is top-down because if it's drawn it appears correct
pBitmap->bmiHeader.biHeight = -pBitmap->bmiHeader.biHeight;
LPBYTE pDst = NULL;
HBITMAP hBitmap = ::CreateDIBSection( NULL, pBitmap, DIB_RGB_COLORS, (void**)&pDst, NULL, 0 );
if(hBitmap == NULL || pDst == NULL)
throw BvcException( ::GetLastError(), _T( "CDib::GetToppledCopy" ) );
DWORD rowlength = GetWidthBytes();
for( int i = 0, m = abs(pBitmap->bmiHeader.biHeight) - 1; i < abs(pBitmap->bmiHeader.biHeight); i++, m-- )
{
memcpy(pDst + m * rowlength, pSrc + i * rowlength, rowlength);
}
free(pBitmap);
return hBitmap;
}
//! This function is called whenever the bitmap is re-created
void CDib::Refresh()
{
// TODO : Create a matching palette (but honestly : who is using
// palettised graphic cards any more? :-)
#ifdef IPL_SUPPORT
// Create a IPL header describing the BMP. No additional memory is allocated
if( m_hBitmap )
{
BITMAP Bitmap;
GetBitmap(&Bitmap);
int nChannels = Bitmap.bmBitsPixel == 1 ? 1 : Bitmap.bmBitsPixel/8;
int depth = Bitmap.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
int origin = m_Orientation == BottomUp ? IPL_ORIGIN_BL : IPL_ORIGIN_TL;
m_pIplImage = iplCreateImageHeader(
nChannels, // number of channels
0, // # of alpha channel, 0-absent
depth, // bit depth of channel
"RGB", // color model
"BGR", // channel sequence
IPL_DATA_ORDER_PIXEL,// data ordering : by pixels or by channels
origin, // bitmap origin : _TL = top left, _BL = bottom left
IPL_ALIGN_DWORD,// scan lines alignment
Bitmap.bmWidth, // width in pixels
Bitmap.bmHeight, // height and
0, // ROI, 0 - entire image
0, // MASK ROI, 0 - entire image
0, // image ID - reserved
0); // tile info.
m_pIplImage->imageData = m_pIplImage->imageDataOrigin = (char*)(Bitmap.bmBits);
}
#endif // #ifdef IPL_SUPPORT
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -