X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5c33522fca7cddc441a316f5b9fb50d7685435ba..c753eb9269d1e6c99b80a2d782ce49d9864ac1da:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index 6857a0d3da..d8cbaa2cfd 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 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; @@ -1897,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); @@ -1931,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; } // ---------------------------------------------------------------------------- @@ -1978,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); @@ -2004,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]; @@ -2020,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; } // ---------------------------------------------------------------------------- @@ -2214,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; @@ -2398,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(); } @@ -2463,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(";"); } @@ -2650,19 +2658,27 @@ void wxImage::RotateHue(double angle) IMPLEMENT_ABSTRACT_CLASS(wxImageHandler,wxObject) #if wxUSE_STREAMS -bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose), int WXUNUSED(index) ) +int wxImageHandler::GetImageCount( wxInputStream& stream ) { - return false; -} + // NOTE: this code is the same of wxAnimationDecoder::CanRead and + // wxImageHandler::CallDoCanRead -bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) ) -{ - return false; -} + if ( !stream.IsSeekable() ) + return false; // can't test unseekable stream -int wxImageHandler::GetImageCount( wxInputStream& WXUNUSED(stream) ) -{ - return 1; + wxFileOffset posOld = stream.TellI(); + int n = DoGetImageCount(stream); + + // restore the old position to be able to test other formats and so on + if ( stream.SeekI(posOld) == wxInvalidOffset ) + { + wxLogDebug(_T("Failed to rewind the stream in wxImageHandler!")); + + // reading would fail anyhow as we're not at the right position + return false; + } + + return n; } bool wxImageHandler::CanRead( const wxString& name ) @@ -2680,13 +2696,13 @@ bool wxImageHandler::CanRead( const wxString& name ) bool wxImageHandler::CallDoCanRead(wxInputStream& stream) { - wxFileOffset posOld = stream.TellI(); - if ( posOld == wxInvalidOffset ) - { - // can't test unseekable stream - return false; - } + // NOTE: this code is the same of wxAnimationDecoder::CanRead and + // wxImageHandler::GetImageCount + + if ( !stream.IsSeekable() ) + return false; // can't test unseekable stream + wxFileOffset posOld = stream.TellI(); bool ok = DoCanRead(stream); // restore the old position to be able to test other formats and so on