modifications for raw bitmap support and for using DIBs
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19710 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -31,6 +31,7 @@ class WXDLLEXPORT wxCursor;
|
|||||||
class WXDLLEXPORT wxControl;
|
class WXDLLEXPORT wxControl;
|
||||||
class WXDLLEXPORT wxImage;
|
class WXDLLEXPORT wxImage;
|
||||||
class WXDLLEXPORT wxPalette;
|
class WXDLLEXPORT wxPalette;
|
||||||
|
class WXDLLEXPORT wxRawBitmapData;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxBitmap: a mono or colour bitmap
|
// wxBitmap: a mono or colour bitmap
|
||||||
@@ -58,13 +59,24 @@ public:
|
|||||||
// New constructor for generalised creation from data
|
// New constructor for generalised creation from data
|
||||||
wxBitmap(void *data, long type, int width, int height, int depth = 1);
|
wxBitmap(void *data, long type, int width, int height, int depth = 1);
|
||||||
|
|
||||||
// If depth is omitted, will create a bitmap compatible with the display
|
// Create a new, uninitialized bitmap of the given size and depth (if it
|
||||||
|
// is omitted, will create a bitmap compatible with the display)
|
||||||
|
//
|
||||||
|
// NB: this ctor will create a DIB for 24 and 32bpp bitmaps, use ctor
|
||||||
|
// taking a DC argument if you want to force using DDB in this case
|
||||||
wxBitmap(int width, int height, int depth = -1);
|
wxBitmap(int width, int height, int depth = -1);
|
||||||
|
|
||||||
|
// Create a bitmap compatible with the given DC
|
||||||
|
wxBitmap(int width, int height, const wxDC& dc);
|
||||||
|
|
||||||
#if wxUSE_IMAGE
|
#if wxUSE_IMAGE
|
||||||
// Convert from wxImage:
|
// Convert from wxImage
|
||||||
wxBitmap(const wxImage& image, int depth = -1)
|
wxBitmap(const wxImage& image, int depth = -1)
|
||||||
{ (void)CreateFromImage(image, depth); }
|
{ (void)CreateFromImage(image, depth); }
|
||||||
|
|
||||||
|
// Create a DDB compatible with the given DC from wxImage
|
||||||
|
wxBitmap(const wxImage& image, const wxDC& dc)
|
||||||
|
{ (void)CreateFromImage(image, dc); }
|
||||||
#endif // wxUSE_IMAGE
|
#endif // wxUSE_IMAGE
|
||||||
|
|
||||||
// we must have this, otherwise icons are silently copied into bitmaps using
|
// we must have this, otherwise icons are silently copied into bitmaps using
|
||||||
@@ -108,6 +120,7 @@ public:
|
|||||||
bool CopyFromCursor(const wxCursor& cursor);
|
bool CopyFromCursor(const wxCursor& cursor);
|
||||||
|
|
||||||
virtual bool Create(int width, int height, int depth = -1);
|
virtual bool Create(int width, int height, int depth = -1);
|
||||||
|
virtual bool Create(int width, int height, const wxDC& dc);
|
||||||
virtual bool Create(void *data, long type, int width, int height, int depth = 1);
|
virtual bool Create(void *data, long type, int width, int height, int depth = 1);
|
||||||
virtual bool LoadFile(const wxString& name, long type = wxBITMAP_TYPE_BMP_RESOURCE);
|
virtual bool LoadFile(const wxString& name, long type = wxBITMAP_TYPE_BMP_RESOURCE);
|
||||||
virtual bool SaveFile(const wxString& name, int type, const wxPalette *cmap = NULL);
|
virtual bool SaveFile(const wxString& name, int type, const wxPalette *cmap = NULL);
|
||||||
@@ -115,6 +128,10 @@ public:
|
|||||||
wxBitmapRefData *GetBitmapData() const
|
wxBitmapRefData *GetBitmapData() const
|
||||||
{ return (wxBitmapRefData *)m_refData; }
|
{ return (wxBitmapRefData *)m_refData; }
|
||||||
|
|
||||||
|
// raw bitmap access support functions
|
||||||
|
bool GetRawData(wxRawBitmapData *data);
|
||||||
|
void UngetRawData(wxRawBitmapData *) { /* nothing to do here */ }
|
||||||
|
|
||||||
#if wxUSE_PALETTE
|
#if wxUSE_PALETTE
|
||||||
wxPalette* GetPalette() const;
|
wxPalette* GetPalette() const;
|
||||||
void SetPalette(const wxPalette& palette);
|
void SetPalette(const wxPalette& palette);
|
||||||
@@ -140,14 +157,16 @@ public:
|
|||||||
void SetOk(bool isOk);
|
void SetOk(bool isOk);
|
||||||
#endif // WXWIN_COMPATIBILITY_2
|
#endif // WXWIN_COMPATIBILITY_2
|
||||||
|
|
||||||
#if wxUSE_PALETTE
|
|
||||||
#if WXWIN_COMPATIBILITY
|
#if WXWIN_COMPATIBILITY
|
||||||
|
#if wxUSE_PALETTE
|
||||||
wxPalette *GetColourMap() const { return GetPalette(); }
|
wxPalette *GetColourMap() const { return GetPalette(); }
|
||||||
void SetColourMap(wxPalette *cmap) { SetPalette(*cmap); };
|
void SetColourMap(wxPalette *cmap) { SetPalette(*cmap); };
|
||||||
#endif // WXWIN_COMPATIBILITY
|
|
||||||
#endif // wxUSE_PALETTE
|
#endif // wxUSE_PALETTE
|
||||||
|
#endif // WXWIN_COMPATIBILITY
|
||||||
|
|
||||||
|
// implementation only from now on
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
// Implementation
|
|
||||||
public:
|
public:
|
||||||
void SetHBITMAP(WXHBITMAP bmp) { SetHandle((WXHANDLE)bmp); }
|
void SetHBITMAP(WXHBITMAP bmp) { SetHandle((WXHANDLE)bmp); }
|
||||||
WXHBITMAP GetHBITMAP() const { return (WXHBITMAP)GetHandle(); }
|
WXHBITMAP GetHBITMAP() const { return (WXHBITMAP)GetHandle(); }
|
||||||
@@ -180,17 +199,20 @@ protected:
|
|||||||
// creates the bitmap from XPM data, supposed to be called from ctor
|
// creates the bitmap from XPM data, supposed to be called from ctor
|
||||||
bool CreateFromXpm(const char **bits);
|
bool CreateFromXpm(const char **bits);
|
||||||
|
|
||||||
|
// creates an uninitialized bitmap, called from Create()s above
|
||||||
|
bool DoCreate(int w, int h, int depth, WXHDC hdc);
|
||||||
|
|
||||||
#if wxUSE_IMAGE
|
#if wxUSE_IMAGE
|
||||||
// creates the bitmap from wxImage, supposed to be called from ctor
|
// creates the bitmap from wxImage, supposed to be called from ctor
|
||||||
bool CreateFromImage(const wxImage& image, int depth);
|
bool CreateFromImage(const wxImage& image, int depth);
|
||||||
|
|
||||||
|
// creates a DDB from wxImage, supposed to be called from ctor
|
||||||
|
bool CreateFromImage(const wxImage& image, const wxDC& dc);
|
||||||
|
|
||||||
|
// common part of the 2 methods above (hdc may be 0)
|
||||||
|
bool CreateFromImage(const wxImage& image, int depth, WXHDC hdc);
|
||||||
#endif // wxUSE_IMAGE
|
#endif // wxUSE_IMAGE
|
||||||
|
|
||||||
#if wxUSE_DIB_FOR_BITMAP
|
|
||||||
void *CreateDIB(int width, int height, int depth);
|
|
||||||
|
|
||||||
void CopyDIBLine(void* src, void* dest, int count) const;
|
|
||||||
#endif // wxUSE_DIB_FOR_BITMAP
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
// common part of CopyFromIcon/CopyFromCursor for Win32
|
// common part of CopyFromIcon/CopyFromCursor for Win32
|
||||||
|
@@ -50,6 +50,8 @@
|
|||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
#include "wx/xpmdecod.h"
|
#include "wx/xpmdecod.h"
|
||||||
|
|
||||||
|
#include "wx/rawbmp.h"
|
||||||
|
|
||||||
// missing from mingw32 header
|
// missing from mingw32 header
|
||||||
#ifndef CLR_INVALID
|
#ifndef CLR_INVALID
|
||||||
#define CLR_INVALID ((COLORREF)-1)
|
#define CLR_INVALID ((COLORREF)-1)
|
||||||
@@ -122,6 +124,34 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
|
|||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// helper functions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// decide whether we should create a DIB or a DDB for the given parameters
|
||||||
|
static bool wxShouldCreateDIB(int w, int h, int d, WXHDC hdc)
|
||||||
|
{
|
||||||
|
// here is the logic:
|
||||||
|
//
|
||||||
|
// (a) if hdc is specified, the caller explicitly wants DDB
|
||||||
|
// (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp or
|
||||||
|
// less DIBs anyhow)
|
||||||
|
// (c) finally, create DIBs under Win9x even if the depth hasn't been
|
||||||
|
// explicitly specified but the current display depth is 24 or more
|
||||||
|
// and the image is "big", i.e. > 16Mb which is the theoretical limit
|
||||||
|
// for DDBs under Win9x
|
||||||
|
//
|
||||||
|
// consequences (all of which seem to make sense):
|
||||||
|
//
|
||||||
|
// (i) by default, DDBs are created (depth == -1 usually)
|
||||||
|
// (ii) DIBs can be created by explicitly specifying the depth
|
||||||
|
// (iii) using a DC always forces creating a DDB
|
||||||
|
return !hdc &&
|
||||||
|
(d >= 24 ||
|
||||||
|
(d == -1 &&
|
||||||
|
wxDIB::GetLineSize(w, wxDisplayDepth())*h > 16*1024*1024));
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxBitmapRefData
|
// wxBitmapRefData
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -161,7 +191,6 @@ void wxBitmapRefData::Free()
|
|||||||
void wxBitmap::Init()
|
void wxBitmap::Init()
|
||||||
{
|
{
|
||||||
// m_refData = NULL; done in the base class ctor
|
// m_refData = NULL; done in the base class ctor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGDIImageRefData *wxBitmap::CreateData() const
|
wxGDIImageRefData *wxBitmap::CreateData() const
|
||||||
@@ -387,26 +416,54 @@ wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
|
|||||||
LoadFile(filename, (int)type);
|
LoadFile(filename, (int)type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxBitmap::Create(int w, int h, int d)
|
bool wxBitmap::Create(int width, int height, int depth)
|
||||||
|
{
|
||||||
|
return DoCreate(width, height, depth, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxBitmap::Create(int width, int height, const wxDC& dc)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( dc.Ok(), FALSE, _T("invalid HDC in wxBitmap::Create()") );
|
||||||
|
|
||||||
|
return DoCreate(width, height, -1, dc.GetHDC());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc)
|
||||||
{
|
{
|
||||||
UnRef();
|
UnRef();
|
||||||
|
|
||||||
m_refData = new wxBitmapRefData;
|
m_refData = new wxBitmapRefData;
|
||||||
|
|
||||||
#if wxUSE_DIB_FOR_BITMAP
|
GetBitmapData()->m_width = w;
|
||||||
if ( w && h && d >= 16 )
|
GetBitmapData()->m_height = h;
|
||||||
|
|
||||||
|
HBITMAP hbmp;
|
||||||
|
|
||||||
|
if ( wxShouldCreateDIB(w, h, d, hdc) )
|
||||||
{
|
{
|
||||||
if ( !CreateDIB(w, h, d) )
|
if ( d == -1 )
|
||||||
|
{
|
||||||
|
// create DIBs without alpha channel by default
|
||||||
|
d = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDIB dib(w, h, d);
|
||||||
|
if ( !dib.IsOk() )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
// don't delete the DIB section in dib object dtor
|
||||||
|
hbmp = dib.Detach();
|
||||||
|
|
||||||
|
GetBitmapData()->m_depth = d;
|
||||||
|
GetBitmapData()->m_hasAlpha = d == 32; // 32bpp DIBs have alpha channel
|
||||||
}
|
}
|
||||||
else
|
else // create a DDB
|
||||||
#endif // wxUSE_DIB_FOR_BITMAP
|
|
||||||
{
|
{
|
||||||
GetBitmapData()->m_width = w;
|
if ( d == -1 )
|
||||||
GetBitmapData()->m_height = h;
|
d = wxDisplayDepth();
|
||||||
|
|
||||||
GetBitmapData()->m_depth = d;
|
GetBitmapData()->m_depth = d;
|
||||||
|
|
||||||
HBITMAP hbmp;
|
|
||||||
#ifndef __WXMICROWIN__
|
#ifndef __WXMICROWIN__
|
||||||
if ( d > 0 )
|
if ( d > 0 )
|
||||||
{
|
{
|
||||||
@@ -428,13 +485,13 @@ bool wxBitmap::Create(int w, int h, int d)
|
|||||||
|
|
||||||
GetBitmapData()->m_depth = wxDisplayDepth();
|
GetBitmapData()->m_depth = wxDisplayDepth();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetHBITMAP((WXHBITMAP)hbmp);
|
SetHBITMAP((WXHBITMAP)hbmp);
|
||||||
|
|
||||||
#if WXWIN_COMPATIBILITY_2
|
#if WXWIN_COMPATIBILITY_2
|
||||||
GetBitmapData()->m_ok = hbmp != 0;
|
GetBitmapData()->m_ok = hbmp != 0;
|
||||||
#endif // WXWIN_COMPATIBILITY_2
|
#endif // WXWIN_COMPATIBILITY_2
|
||||||
}
|
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@@ -449,7 +506,7 @@ bool wxBitmap::Create(int w, int h, int d)
|
|||||||
// make sense to use #ifdefs inside the function bodies
|
// make sense to use #ifdefs inside the function bodies
|
||||||
#ifdef __WXMICROWIN__
|
#ifdef __WXMICROWIN__
|
||||||
|
|
||||||
bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
bool wxBitmap::CreateFromImage(const wxImage& image, int depth, const wxDC& dc)
|
||||||
{
|
{
|
||||||
// Set this to 1 to experiment with mask code,
|
// Set this to 1 to experiment with mask code,
|
||||||
// which currently doesn't work
|
// which currently doesn't work
|
||||||
@@ -637,7 +694,20 @@ wxImage wxBitmap::ConvertToImage() const
|
|||||||
// wxImage to/from conversions
|
// wxImage to/from conversions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
|
||||||
|
{
|
||||||
|
return CreateFromImage(image, depth, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( dc.Ok(), FALSE,
|
||||||
|
_T("invalid HDC in wxBitmap::CreateFromImage()") );
|
||||||
|
|
||||||
|
return CreateFromImage(image, -1, dc.GetHDC());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc )
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
|
wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
|
||||||
|
|
||||||
@@ -656,7 +726,6 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
|||||||
wxBitmapRefData *refData = new wxBitmapRefData;
|
wxBitmapRefData *refData = new wxBitmapRefData;
|
||||||
refData->m_width = w;
|
refData->m_width = w;
|
||||||
refData->m_height = h;
|
refData->m_height = h;
|
||||||
refData->m_depth = dib.GetDepth();
|
|
||||||
refData->m_hasAlpha = image.HasAlpha();
|
refData->m_hasAlpha = image.HasAlpha();
|
||||||
|
|
||||||
m_refData = refData;
|
m_refData = refData;
|
||||||
@@ -665,16 +734,21 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
|||||||
// next either store DIB as is or create a DDB from it
|
// next either store DIB as is or create a DDB from it
|
||||||
HBITMAP hbitmap;
|
HBITMAP hbitmap;
|
||||||
|
|
||||||
// TODO: if we're ready to use DIB as is, we can just do this:
|
// are we going to use DIB?
|
||||||
// if ( ... )
|
if ( wxShouldCreateDIB(w, h, depth, hdc) )
|
||||||
// hbitmap = dib.Detach();
|
{
|
||||||
// else
|
// don't delete the DIB section in dib object dtor
|
||||||
|
hbitmap = dib.Detach();
|
||||||
|
|
||||||
|
refData->m_depth = dib.GetDepth();
|
||||||
|
}
|
||||||
|
else // we need to convert DIB to DDB
|
||||||
{
|
{
|
||||||
// create and set the device-dependent bitmap
|
// create and set the device-dependent bitmap
|
||||||
//
|
//
|
||||||
// VZ: why don't we just use SetDIBits() instead? because of the
|
// VZ: why don't we just use SetDIBits() instead? because of the
|
||||||
// palette or is there some other reason?
|
// palette or is there some other reason?
|
||||||
hbitmap = ::CreateCompatibleBitmap(ScreenHDC(), w, h);
|
hbitmap = ::CreateCompatibleBitmap(hdc ? (HDC)hdc : ScreenHDC(), w, h);
|
||||||
if ( !hbitmap )
|
if ( !hbitmap )
|
||||||
{
|
{
|
||||||
wxLogLastError(_T("CreateCompatibleBitmap()"));
|
wxLogLastError(_T("CreateCompatibleBitmap()"));
|
||||||
@@ -745,6 +819,8 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
|||||||
::SelectPalette(hdcMem, hOldPalette, FALSE);
|
::SelectPalette(hdcMem, hOldPalette, FALSE);
|
||||||
}
|
}
|
||||||
#endif // wxUSE_PALETTE
|
#endif // wxUSE_PALETTE
|
||||||
|
|
||||||
|
refData->m_depth = depth == -1 ? wxDisplayDepth() : depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate this object
|
// validate this object
|
||||||
@@ -1119,6 +1195,46 @@ void wxBitmap::SetQuality(int WXUNUSED(quality))
|
|||||||
|
|
||||||
#endif // WXWIN_COMPATIBILITY_2_4
|
#endif // WXWIN_COMPATIBILITY_2_4
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// raw bitmap access support
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool wxBitmap::GetRawData(wxRawBitmapData *data)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( data, FALSE, _T("NULL pointer in wxBitmap::GetRawData") );
|
||||||
|
|
||||||
|
if ( !Ok() )
|
||||||
|
{
|
||||||
|
// no bitmap, no data (raw or otherwise)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only support raw access to the DIBs, so check if we have one
|
||||||
|
DIBSECTION ds;
|
||||||
|
if ( !::GetObject(GetHbitmap(), sizeof(ds), &ds) )
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok, store the relevant info in wxRawBitmapData
|
||||||
|
const LONG h = ds.dsBm.bmHeight;
|
||||||
|
|
||||||
|
data->m_width = ds.dsBm.bmWidth;
|
||||||
|
data->m_height = h;
|
||||||
|
data->m_bypp = ds.dsBm.bmBitsPixel / 8;
|
||||||
|
|
||||||
|
// remember that DIBs are stored in top to bottom order!
|
||||||
|
const LONG bytesPerRow = ds.dsBm.bmWidthBytes;
|
||||||
|
data->m_stride = -bytesPerRow;
|
||||||
|
data->m_pixels = (unsigned char *)ds.dsBm.bmBits;
|
||||||
|
if ( h > 1 )
|
||||||
|
{
|
||||||
|
data->m_pixels += (h - 1)*bytesPerRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// TODO: to be replaced by something better
|
// TODO: to be replaced by something better
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user