Added wxGraphicsBitmap::ConvertToImage().
Allow to convert wxGraphicsBitmap directly to wxImage, without passing by wxBitmap. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69353 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
5f606e6515
commit
08b2d55fdf
@ -19,6 +19,7 @@
|
||||
#include "wx/geometry.h"
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/dc.h"
|
||||
#include "wx/image.h"
|
||||
#include "wx/vector.h"
|
||||
|
||||
enum wxAntialiasMode
|
||||
@ -166,6 +167,14 @@ class WXDLLIMPEXP_CORE wxGraphicsBitmap : public wxGraphicsObject
|
||||
public:
|
||||
wxGraphicsBitmap() {}
|
||||
virtual ~wxGraphicsBitmap() {}
|
||||
|
||||
// Convert bitmap to wxImage: this is more efficient than converting to
|
||||
// wxBitmap first and then to wxImage and also works without X server
|
||||
// connection under Unix that wxBitmap requires.
|
||||
#if wxUSE_IMAGE
|
||||
wxImage ConvertToImage() const;
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
private:
|
||||
DECLARE_DYNAMIC_CLASS(wxGraphicsBitmap)
|
||||
};
|
||||
|
@ -282,6 +282,20 @@ public:
|
||||
Default constructor creates an invalid bitmap.
|
||||
*/
|
||||
wxGraphicsBitmap() {}
|
||||
|
||||
/**
|
||||
Return the contents of this bitmap as wxImage.
|
||||
|
||||
Using this method is more efficient than converting wxGraphicsBitmap to
|
||||
wxBitmap first and then to wxImage and can be useful if, for example,
|
||||
you want to save wxGraphicsBitmap as a disk file in a format not
|
||||
directly supported by wxBitmap.
|
||||
|
||||
Invalid image is returned if the bitmap is invalid.
|
||||
|
||||
@since 2.9.3
|
||||
*/
|
||||
wxImage ConvertToImage() const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -317,6 +317,11 @@ public:
|
||||
virtual cairo_surface_t* GetCairoSurface() { return m_surface; }
|
||||
virtual cairo_pattern_t* GetCairoPattern() { return m_pattern; }
|
||||
virtual wxSize GetSize() { return wxSize(m_width, m_height); }
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
wxImage ConvertToImage() const;
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
private :
|
||||
// Allocate m_buffer for the bitmap of the given size in the given format.
|
||||
//
|
||||
@ -1249,6 +1254,166 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
||||
#endif // wxHAS_RAW_BITMAP
|
||||
}
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
|
||||
// Helper functions for dealing with alpha pre-multiplication.
|
||||
namespace
|
||||
{
|
||||
|
||||
inline unsigned char Premultiply(unsigned char alpha, unsigned char data)
|
||||
{
|
||||
return alpha ? (data * alpha)/0xff : data;
|
||||
}
|
||||
|
||||
inline unsigned char Unpremultiply(unsigned char alpha, unsigned char data)
|
||||
{
|
||||
return alpha ? (data * 0xff)/alpha : data;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer,
|
||||
const wxImage& image)
|
||||
: wxGraphicsObjectRefData(renderer)
|
||||
{
|
||||
const cairo_format_t bufferFormat = image.HasAlpha()
|
||||
? CAIRO_FORMAT_ARGB32
|
||||
: CAIRO_FORMAT_RGB24;
|
||||
|
||||
InitBuffer(image.GetWidth(), image.GetHeight(), bufferFormat);
|
||||
|
||||
// Copy wxImage data into the buffer. Notice that we work with wxUint32
|
||||
// values and not bytes becase Cairo always works with buffers in native
|
||||
// endianness.
|
||||
wxUint32* dst = reinterpret_cast<wxUint32*>(m_buffer);
|
||||
const unsigned char* src = image.GetData();
|
||||
|
||||
if ( bufferFormat == CAIRO_FORMAT_ARGB32 )
|
||||
{
|
||||
const unsigned char* alpha = image.GetAlpha();
|
||||
|
||||
for ( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
for ( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
const unsigned char a = *alpha++;
|
||||
|
||||
*dst++ = a << 24 |
|
||||
Premultiply(a, src[0]) << 16 |
|
||||
Premultiply(a, src[1]) << 8 |
|
||||
Premultiply(a, src[2]);
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // RGB
|
||||
{
|
||||
for ( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
for ( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
*dst++ = src[0] << 16 |
|
||||
src[1] << 8 |
|
||||
src[2];
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitSurface(bufferFormat);
|
||||
}
|
||||
|
||||
wxImage wxCairoBitmapData::ConvertToImage() const
|
||||
{
|
||||
wxImage image(m_width, m_height, false /* don't clear */);
|
||||
|
||||
// Get the surface type and format.
|
||||
wxCHECK_MSG( cairo_surface_get_type(m_surface) == CAIRO_SURFACE_TYPE_IMAGE,
|
||||
wxNullImage,
|
||||
wxS("Can't convert non-image surface to image.") );
|
||||
|
||||
switch ( cairo_image_surface_get_format(m_surface) )
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
image.SetAlpha();
|
||||
break;
|
||||
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
// Nothing to do, we don't use alpha by default.
|
||||
break;
|
||||
|
||||
case CAIRO_FORMAT_A8:
|
||||
case CAIRO_FORMAT_A1:
|
||||
wxFAIL_MSG(wxS("Unsupported Cairo image surface type."));
|
||||
return wxNullImage;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG(wxS("Unknown Cairo image surface type."));
|
||||
return wxNullImage;
|
||||
}
|
||||
|
||||
// Prepare for copying data.
|
||||
const wxUint32* src = (wxUint32*)cairo_image_surface_get_data(m_surface);
|
||||
wxCHECK_MSG( src, wxNullImage, wxS("Failed to get Cairo surface data.") );
|
||||
|
||||
int stride = cairo_image_surface_get_stride(m_surface);
|
||||
wxCHECK_MSG( stride > 0, wxNullImage,
|
||||
wxS("Failed to get Cairo surface stride.") );
|
||||
|
||||
// As we work with wxUint32 pointers and not char ones, we need to adjust
|
||||
// the stride accordingly. This should be lossless as the stride must be a
|
||||
// multiple of pixel size.
|
||||
wxASSERT_MSG( !(stride % sizeof(wxUint32)), wxS("Unexpected stride.") );
|
||||
stride /= sizeof(wxUint32);
|
||||
|
||||
unsigned char* dst = image.GetData();
|
||||
unsigned char *alpha = image.GetAlpha();
|
||||
if ( alpha )
|
||||
{
|
||||
// We need to also copy alpha and undo the pre-multiplication as Cairo
|
||||
// stores pre-multiplied values in this format while wxImage does not.
|
||||
for ( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
const wxUint32* const rowStart = src;
|
||||
for ( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
const wxUint32 argb = *src++;
|
||||
|
||||
*alpha++ = (argb & 0xff000000) >> 24;
|
||||
|
||||
// Copy the RGB data undoing the pre-multiplication.
|
||||
*dst++ = Unpremultiply(*alpha, (argb & 0x00ff0000) >> 16);
|
||||
*dst++ = Unpremultiply(*alpha, (argb & 0x0000ff00) >> 8);
|
||||
*dst++ = Unpremultiply(*alpha, (argb & 0x000000ff));
|
||||
}
|
||||
|
||||
src = rowStart + stride;
|
||||
}
|
||||
}
|
||||
else // RGB
|
||||
{
|
||||
// Things are pretty simple in this case, just copy RGB bytes.
|
||||
for ( int y = 0; y < m_height; y++ )
|
||||
{
|
||||
const wxUint32* const rowStart = src;
|
||||
for ( int x = 0; x < m_width; x++ )
|
||||
{
|
||||
const wxUint32 argb = *src++;
|
||||
|
||||
*dst++ = (argb & 0x00ff0000) >> 16;
|
||||
*dst++ = (argb & 0x0000ff00) >> 8;
|
||||
*dst++ = (argb & 0x000000ff);
|
||||
}
|
||||
|
||||
src = rowStart + stride;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
wxCairoBitmapData::~wxCairoBitmapData()
|
||||
{
|
||||
if (m_pattern)
|
||||
@ -1260,7 +1425,21 @@ wxCairoBitmapData::~wxCairoBitmapData()
|
||||
delete [] m_buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGraphicsBitmap implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
|
||||
wxImage wxGraphicsBitmap::ConvertToImage() const
|
||||
{
|
||||
const wxCairoBitmapData* const
|
||||
data = static_cast<wxCairoBitmapData*>(GetGraphicsData());
|
||||
|
||||
return data ? data->ConvertToImage() : wxNullImage;
|
||||
}
|
||||
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxCairoContext implementation
|
||||
|
@ -978,6 +978,14 @@ public:
|
||||
|
||||
virtual CGImageRef GetBitmap() { return m_bitmap; }
|
||||
bool IsMonochrome() { return m_monochrome; }
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
wxImage ConvertToImage() const
|
||||
{
|
||||
return wxBitmap(m_bitmap).ConvertToImage();
|
||||
}
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
private :
|
||||
CGImageRef m_bitmap;
|
||||
bool m_monochrome;
|
||||
@ -993,6 +1001,18 @@ wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
|
||||
CGImageRelease( m_bitmap );
|
||||
}
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
|
||||
wxImage wxGraphicsBitmap::ConvertToImage() const
|
||||
{
|
||||
wxMacCoreGraphicsBitmapData* const
|
||||
data = static_cast<wxMacCoreGraphicsBitmapData*>(GetRefData());
|
||||
|
||||
return data ? data->ConvertToImage() : wxNullImage;
|
||||
}
|
||||
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
//
|
||||
// Graphics Matrix
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user