X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/591d3fa2106eae93a22829c7b2665dec524b4c00..3b241537efde9ed3b5b6c1fb0756f00517e0bbd9:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index b41fee58f6..cbe275bc19 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -53,7 +53,14 @@ IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxImage,WXDLLEXPORT) #endif //----------------------------------------------------------------------------- -// wxImage +// global data +//----------------------------------------------------------------------------- + +wxList wxImage::sm_handlers; +wxImage wxNullImage; + +//----------------------------------------------------------------------------- +// wxImageRefData //----------------------------------------------------------------------------- class wxImageRefData: public wxObjectRefData @@ -88,7 +95,7 @@ public: wxArrayString m_optionNames; wxArrayString m_optionValues; - DECLARE_NO_COPY_CLASS(wxImageRefData) + wxDECLARE_NO_COPY_CLASS(wxImageRefData); }; wxImageRefData::wxImageRefData() @@ -117,58 +124,15 @@ wxImageRefData::~wxImageRefData() free( m_alpha ); } -wxList wxImage::sm_handlers; - -wxImage wxNullImage; +//----------------------------------------------------------------------------- +// wxImage //----------------------------------------------------------------------------- -#define M_IMGDATA wx_static_cast(wxImageRefData*, m_refData) +#define M_IMGDATA static_cast(m_refData) IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject) -wxImage::wxImage( int width, int height, bool clear ) -{ - Create( width, height, clear ); -} - -wxImage::wxImage( int width, int height, unsigned char* data, bool static_data ) -{ - Create( width, height, data, static_data ); -} - -wxImage::wxImage( int width, int height, unsigned char* data, unsigned char* alpha, bool static_data ) -{ - Create( width, height, data, alpha, static_data ); -} - -wxImage::wxImage( const wxString& name, wxBitmapType type, int index ) -{ - LoadFile( name, type, index ); -} - -wxImage::wxImage( const wxString& name, const wxString& mimetype, int index ) -{ - LoadFile( name, mimetype, index ); -} - -#if wxUSE_STREAMS -wxImage::wxImage( wxInputStream& stream, wxBitmapType type, int index ) -{ - LoadFile( stream, type, index ); -} - -wxImage::wxImage( wxInputStream& stream, const wxString& mimetype, int index ) -{ - LoadFile( stream, mimetype, index ); -} -#endif // wxUSE_STREAMS - -wxImage::wxImage(const char* const* xpmData) -{ - Create(xpmData); -} - bool wxImage::Create(const char* const* xpmData) { #if wxUSE_XPM @@ -195,13 +159,15 @@ bool wxImage::Create( int width, int height, bool clear ) return false; } - if (clear) - memset(M_IMGDATA->m_data, 0, width*height*3); - M_IMGDATA->m_width = width; M_IMGDATA->m_height = height; M_IMGDATA->m_ok = true; + if (clear) + { + Clear(); + } + return true; } @@ -236,6 +202,7 @@ bool wxImage::Create( int width, int height, unsigned char* data, unsigned char* M_IMGDATA->m_height = height; M_IMGDATA->m_ok = true; M_IMGDATA->m_static = static_data; + M_IMGDATA->m_staticAlpha = static_data; return true; } @@ -245,6 +212,11 @@ void wxImage::Destroy() UnRef(); } +void wxImage::Clear(unsigned char value) +{ + memset(M_IMGDATA->m_data, value, M_IMGDATA->m_width*M_IMGDATA->m_height*3); +} + wxObjectRefData* wxImage::CreateRefData() const { return new wxImageRefData; @@ -252,7 +224,7 @@ wxObjectRefData* wxImage::CreateRefData() const wxObjectRefData* wxImage::CloneRefData(const wxObjectRefData* that) const { - const wxImageRefData* refData = wx_static_cast(const wxImageRefData*, that); + const wxImageRefData* refData = static_cast(that); wxCHECK_MSG(refData->m_ok, NULL, wxT("invalid image") ); wxImageRefData* refData_new = new wxImageRefData; @@ -1270,7 +1242,6 @@ void wxImage::Paste( const wxImage &image, int x, int y ) (GetMaskGreen()==image.GetMaskGreen()) && (GetMaskBlue()==image.GetMaskBlue())))) { - width *= 3; unsigned char* source_data = image.GetData() + xx*3 + yy*3*image.GetWidth(); int source_step = image.GetWidth()*3; @@ -1278,11 +1249,10 @@ void wxImage::Paste( const wxImage &image, int x, int y ) int target_step = M_IMGDATA->m_width*3; for (int j = 0; j < height; j++) { - memcpy( target_data, source_data, width ); + memcpy( target_data, source_data, width*3 ); source_data += source_step; target_data += target_step; } - return; } // Copy over the alpha channel from the original image @@ -1311,7 +1281,6 @@ void wxImage::Paste( const wxImage &image, int x, int y ) unsigned char g = image.GetMaskGreen(); unsigned char b = image.GetMaskBlue(); - width *= 3; unsigned char* source_data = image.GetData() + xx*3 + yy*3*image.GetWidth(); int source_step = image.GetWidth()*3; @@ -1320,7 +1289,7 @@ void wxImage::Paste( const wxImage &image, int x, int y ) for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i+=3) + for (int i = 0; i < width*3; i+=3) { if ((source_data[i] != r) || (source_data[i+1] != g) || @@ -1393,7 +1362,7 @@ wxImage wxImage::ConvertToGreyscale( double lr, double lg, double lb ) const { // calculate the luma double luma = (src[0] * lr + src[1] * lg + src[2] * lb) + 0.5; - dest[0] = dest[1] = dest[2] = wx_static_cast(unsigned char, luma); + dest[0] = dest[1] = dest[2] = static_cast(luma); } } @@ -1468,6 +1437,16 @@ wxBitmapType wxImage::GetType() const return M_IMGDATA->m_type; } +void wxImage::SetType(wxBitmapType type) +{ + wxCHECK_RET( IsOk(), "must create the image before setting its type"); + + // type can be wxBITMAP_TYPE_INVALID to reset the image type to default + wxASSERT_MSG( type != wxBITMAP_TYPE_MAX, "invalid bitmap type" ); + + M_IMGDATA->m_type = type; +} + long wxImage::XYToIndex(int x, int y) const { if ( Ok() && @@ -1890,16 +1869,28 @@ bool wxImage::SetMaskFromImage(const wxImage& mask, bool wxImage::ConvertAlphaToMask(unsigned char threshold) { - if (!HasAlpha()) + if ( !HasAlpha() ) return true; unsigned char mr, mg, mb; - if (!FindFirstUnusedColour(&mr, &mg, &mb)) + if ( !FindFirstUnusedColour(&mr, &mg, &mb) ) { wxLogError( _("No unused colour in image being masked.") ); return false; } + ConvertAlphaToMask(mr, mg, mb, threshold); + return true; +} + +void wxImage::ConvertAlphaToMask(unsigned char mr, + unsigned char mg, + unsigned char mb, + unsigned char threshold) +{ + if ( !HasAlpha() ) + return; + AllocExclusive(); SetMask(true); @@ -1924,13 +1915,11 @@ bool wxImage::ConvertAlphaToMask(unsigned char threshold) } } - if( !M_IMGDATA->m_staticAlpha ) + if ( !M_IMGDATA->m_staticAlpha ) free(M_IMGDATA->m_alpha); M_IMGDATA->m_alpha = NULL; M_IMGDATA->m_staticAlpha = false; - - return true; } // ---------------------------------------------------------------------------- @@ -1971,12 +1960,10 @@ void wxImage::SetPalette(const wxPalette& palette) void wxImage::SetOption(const wxString& name, const wxString& value) { - wxCHECK_RET( Ok(), wxT("invalid image") ); - AllocExclusive(); int idx = M_IMGDATA->m_optionNames.Index(name, false); - if (idx == wxNOT_FOUND) + if ( idx == wxNOT_FOUND ) { M_IMGDATA->m_optionNames.Add(name); M_IMGDATA->m_optionValues.Add(value); @@ -1997,10 +1984,11 @@ void wxImage::SetOption(const wxString& name, int value) wxString wxImage::GetOption(const wxString& name) const { - wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid image") ); + if ( !M_IMGDATA ) + return wxEmptyString; int idx = M_IMGDATA->m_optionNames.Index(name, false); - if (idx == wxNOT_FOUND) + if ( idx == wxNOT_FOUND ) return wxEmptyString; else return M_IMGDATA->m_optionValues[idx]; @@ -2013,9 +2001,8 @@ int wxImage::GetOptionInt(const wxString& name) const bool wxImage::HasOption(const wxString& name) const { - wxCHECK_MSG( Ok(), false, wxT("invalid image") ); - - return (M_IMGDATA->m_optionNames.Index(name, false) != wxNOT_FOUND); + return M_IMGDATA ? M_IMGDATA->m_optionNames.Index(name, false) != wxNOT_FOUND + : false; } // ---------------------------------------------------------------------------- @@ -2207,18 +2194,42 @@ int wxImage::GetImageCount( wxInputStream &stream, wxBitmapType type ) bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index) { + // save the options values which can be clobbered by the handler (e.g. many + // of them call Destroy() before trying to load the file) + const unsigned maxWidth = GetOptionInt(wxIMAGE_OPTION_MAX_WIDTH), + maxHeight = GetOptionInt(wxIMAGE_OPTION_MAX_HEIGHT); + if ( !handler.LoadFile(this, stream, true/*verbose*/, index) ) return false; M_IMGDATA->m_type = handler.GetType(); + + // rescale the image to the specified size if needed + if ( maxWidth || maxHeight ) + { + const unsigned widthOrig = GetWidth(), + heightOrig = GetHeight(); + + // this uses the same (trivial) algorithm as the JPEG handler + unsigned width = widthOrig, + height = heightOrig; + while ( (maxWidth && width > maxWidth) || + (maxHeight && height > maxHeight) ) + { + width /= 2; + height /= 2; + } + + if ( width != widthOrig || height != heightOrig ) + Rescale(width, height, wxIMAGE_QUALITY_HIGH); + } + return true; } bool wxImage::LoadFile( wxInputStream& stream, wxBitmapType type, int index ) { - UnRef(); - - m_refData = new wxImageRefData; + AllocExclusive(); wxImageHandler *handler; @@ -2281,7 +2292,7 @@ bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int ind bool wxImage::DoSave(wxImageHandler& handler, wxOutputStream& stream) const { - wxImage * const self = wx_const_cast(wxImage *, this); + wxImage * const self = const_cast(this); if ( !handler.SaveFile(self, stream) ) return false; @@ -2391,10 +2402,12 @@ wxImageHandler *wxImage::FindHandler( const wxString& extension, wxBitmapType bi while (node) { wxImageHandler *handler = (wxImageHandler*)node->GetData(); - if ( (handler->GetExtension().Cmp(extension) == 0) && - ( (bitmapType == wxBITMAP_TYPE_ANY) || (handler->GetType() == bitmapType)) ) + if ((bitmapType == wxBITMAP_TYPE_ANY) || (handler->GetType() == bitmapType)) { - return handler; + if (handler->GetExtension() == extension) + return handler; + if (handler->GetAltExtensions().Index(extension, false) != wxNOT_FOUND) + return handler; } node = node->GetNext(); } @@ -2456,6 +2469,8 @@ wxString wxImage::GetImageExtWildcard() { wxImageHandler* Handler = (wxImageHandler*)Node->GetData(); fmts += wxT("*.") + Handler->GetExtension(); + for (size_t i = 0; i < Handler->GetAltExtensions().size(); i++) + fmts += wxT(";*.") + Handler->GetAltExtensions()[i]; Node = Node->GetNext(); if ( Node ) fmts += wxT(";"); }