bitmap.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,776 行 · 第 1/4 页
CPP
1,776 行
*dstLine |= mask;
if ( (mask >>= 1) == 0 )
{
dstLine++;
mask = 0x80;
}
}
}
hbitmap = ::CreateBitmap(w, h, 1, 1, data);
if ( !hbitmap )
{
wxLogLastError(_T("CreateBitmap(mask)"));
}
else
{
SetMask(new wxMask((WXHBITMAP)hbitmap));
}
delete[] data;
}
return true;
}
wxImage wxBitmap::ConvertToImage() const
{
// convert DDB to DIB
wxDIB dib(*this);
if ( !dib.IsOk() )
{
return wxNullImage;
}
// and then DIB to our wxImage
wxImage image = dib.ConvertToImage();
if ( !image.Ok() )
{
return wxNullImage;
}
// now do the same for the mask, if we have any
HBITMAP hbmpMask = GetMask() ? (HBITMAP) GetMask()->GetMaskBitmap() : NULL;
if ( hbmpMask )
{
wxDIB dibMask(hbmpMask);
if ( dibMask.IsOk() )
{
// TODO: use wxRawBitmap to iterate over DIB
// we hard code the mask colour for now but we could also make an
// effort (and waste time) to choose a colour not present in the
// image already to avoid having to fudge the pixels below --
// whether it's worth to do it is unclear however
static const int MASK_RED = 1;
static const int MASK_GREEN = 2;
static const int MASK_BLUE = 3;
static const int MASK_BLUE_REPLACEMENT = 2;
const int h = dibMask.GetHeight();
const int w = dibMask.GetWidth();
const int bpp = dibMask.GetDepth();
const int maskBytesPerPixel = bpp >> 3;
const int maskBytesPerLine = wxDIB::GetLineSize(w, bpp);
unsigned char *data = image.GetData();
// remember that DIBs are stored in bottom to top order
unsigned char *
maskLineStart = dibMask.GetData() + ((h - 1) * maskBytesPerLine);
for ( int y = 0; y < h; y++, maskLineStart -= maskBytesPerLine )
{
// traverse one mask DIB line
unsigned char *mask = maskLineStart;
for ( int x = 0; x < w; x++, mask += maskBytesPerPixel )
{
// should this pixel be transparent?
if ( *mask )
{
// no, check that it isn't transparent by accident
if ( (data[0] == MASK_RED) &&
(data[1] == MASK_GREEN) &&
(data[2] == MASK_BLUE) )
{
// we have to fudge the colour a bit to prevent
// this pixel from appearing transparent
data[2] = MASK_BLUE_REPLACEMENT;
}
data += 3;
}
else // yes, transparent pixel
{
*data++ = MASK_RED;
*data++ = MASK_GREEN;
*data++ = MASK_BLUE;
}
}
}
image.SetMaskColour(MASK_RED, MASK_GREEN, MASK_BLUE);
}
}
return image;
}
#endif // wxUSE_WXDIB
#endif // wxUSE_IMAGE
// ----------------------------------------------------------------------------
// loading and saving bitmaps
// ----------------------------------------------------------------------------
bool wxBitmap::LoadFile(const wxString& filename, long type)
{
UnRef();
wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
if ( handler )
{
m_refData = new wxBitmapRefData;
return handler->LoadFile(this, filename, type, -1, -1);
}
#if wxUSE_IMAGE && wxUSE_WXDIB
else // no bitmap handler found
{
wxImage image;
if ( image.LoadFile( filename, type ) && image.Ok() )
{
*this = wxBitmap(image);
return true;
}
}
#endif // wxUSE_IMAGE
return false;
}
bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
{
UnRef();
wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
if ( !handler )
{
wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), type);
return false;
}
m_refData = new wxBitmapRefData;
return handler->Create(this, data, type, width, height, depth);
}
bool wxBitmap::SaveFile(const wxString& filename,
int type,
const wxPalette *palette)
{
wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
if ( handler )
{
return handler->SaveFile(this, filename, type, palette);
}
#if wxUSE_IMAGE && wxUSE_WXDIB
else // no bitmap handler found
{
// FIXME what about palette? shouldn't we use it?
wxImage image = ConvertToImage();
if ( image.Ok() )
{
return image.SaveFile(filename, type);
}
}
#endif // wxUSE_IMAGE
return false;
}
// ----------------------------------------------------------------------------
// sub bitmap extraction
// ----------------------------------------------------------------------------
wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
{
wxCHECK_MSG( Ok() &&
(rect.x >= 0) && (rect.y >= 0) &&
(rect.x+rect.width <= GetWidth()) &&
(rect.y+rect.height <= GetHeight()),
wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
wxBitmap ret( rect.width, rect.height, GetDepth() );
wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
#ifndef __WXMICROWIN__
// handle alpha channel, if any
if (HasAlpha())
ret.UseAlpha();
// copy bitmap data
MemoryHDC dcSrc,
dcDst;
{
SelectInHDC selectSrc(dcSrc, GetHbitmap()),
selectDst(dcDst, GetHbitmapOf(ret));
if ( !selectSrc || !selectDst )
{
wxLogLastError(_T("SelectObjct(hBitmap)"));
}
if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height,
dcSrc, rect.x, rect.y, SRCCOPY) )
{
wxLogLastError(_T("BitBlt"));
}
}
// copy mask if there is one
if ( GetMask() )
{
HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
SelectInHDC selectSrc(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap()),
selectDst(dcDst, hbmpMask);
if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height,
dcSrc, rect.x, rect.y, SRCCOPY) )
{
wxLogLastError(_T("BitBlt"));
}
wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
ret.SetMask(mask);
}
#endif // !__WXMICROWIN__
return ret;
}
// ----------------------------------------------------------------------------
// wxBitmap accessors
// ----------------------------------------------------------------------------
#if wxUSE_PALETTE
wxPalette* wxBitmap::GetPalette() const
{
return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
: (wxPalette *) NULL;
}
#endif
wxMask *wxBitmap::GetMask() const
{
return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask *) NULL;
}
wxBitmap wxBitmap::GetMaskBitmap() const
{
wxBitmap bmp;
wxMask *mask = GetMask();
if ( mask )
bmp.SetHBITMAP(mask->GetMaskBitmap());
return bmp;
}
#ifdef __WXDEBUG__
wxDC *wxBitmap::GetSelectedInto() const
{
return GetBitmapData() ? GetBitmapData()->m_selectedInto : (wxDC *) NULL;
}
#endif
#if WXWIN_COMPATIBILITY_2_4
int wxBitmap::GetQuality() const
{
return 0;
}
#endif // WXWIN_COMPATIBILITY_2_4
void wxBitmap::UseAlpha()
{
if ( GetBitmapData() )
GetBitmapData()->m_hasAlpha = true;
}
bool wxBitmap::HasAlpha() const
{
return GetBitmapData() && GetBitmapData()->m_hasAlpha;
}
// ----------------------------------------------------------------------------
// wxBitmap setters
// ----------------------------------------------------------------------------
#ifdef __WXDEBUG__
void wxBitmap::SetSelectedInto(wxDC *dc)
{
if ( GetBitmapData() )
GetBitmapData()->m_selectedInto = dc;
}
#endif
#if wxUSE_PALETTE
void wxBitmap::SetPalette(const wxPalette& palette)
{
AllocExclusive();
GetBitmapData()->m_bitmapPalette = palette;
}
#endif // wxUSE_PALETTE
void wxBitmap::SetMask(wxMask *mask)
{
AllocExclusive();
GetBitmapData()->SetMask(mask);
}
#if WXWIN_COMPATIBILITY_2_4
void wxBitmap::SetQuality(int WXUNUSED(quality))
{
}
#endif // WXWIN_COMPATIBILITY_2_4
// ----------------------------------------------------------------------------
// raw bitmap access support
// ----------------------------------------------------------------------------
#ifdef wxHAVE_RAW_BITMAP
void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
{
#if wxUSE_WXDIB
if ( !Ok() )
{
// no bitmap, no data (raw or otherwise)
return NULL;
}
// if we're already a DIB we can access our data directly, but if not we
// need to convert this DDB to a DIB section and use it for raw access and
// then convert it back
HBITMAP hDIB;
if ( !GetBitmapData()->m_isDIB )
{
wxCHECK_MSG( !GetBitmapData()->m_dib, NULL,
_T("GetRawData() may be called only once") );
wxDIB *dib = new wxDIB(*this);
if ( !dib->IsOk() )
{
delete dib;
return NULL;
}
// we'll free it in UngetRawData()
GetBitmapData()->m_dib = dib;
hDIB = dib->GetHandle();
}
else // we're a DIB
{
hDIB = GetHbitmap();
}
DIBSECTION ds;
if ( ::GetObject(hDIB, sizeof(ds), &ds) != sizeof(DIBSECTION) )
{
wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") );
return NULL;
}
// check that the bitmap is in correct format
if ( ds.dsBm.bmBitsPixel != bpp )
{
wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") );
return NULL;
}
// ok, store the relevant info in wxPixelDataBase
const LONG h = ds.dsBm.bmHeight;
data.m_width = ds.dsBm.bmWidth;
data.m_height = h;
// remember that DIBs are stored in top to bottom order!
// (We can't just use ds.dsBm.bmWidthBytes here, because it isn't always a
// multiple of 2, as required by the documentation. So we use the official
// formula, which we already use elsewhere.)
const LONG bytesPerRow =
wxDIB::GetLineSize(ds.dsBm.bmWidth, ds.dsBm.bmBitsPixel);
data.m_stride = -bytesPerRow;
char *bits = (char *)ds.dsBm.bmBits;
if ( h > 1 )
{
bits += (h - 1)*bytesPerRow;
}
return bits;
#else
return NULL;
#endif
}
void wxBitmap::UngetRawData(wxPixelDataBase& dataBase)
{
#if wxUSE_WXDIB
if ( !Ok() )
return;
if ( !&dataBase )
{
// invalid data, don't crash -- but don't assert neither as we're
// called automatically from wxPixelDataBase dtor and so there is no
// way to prevent this from happening
return;
}
// if we're a DDB we need to convert DIB back to DDB now to make the
// changes made via raw bitmap access effective
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?