X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8650108199bf799f21e29811cddaefd579c98c88..4e2a3778386d60356dab319afa2d3f987f86d6b2:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index 1c30e71c92..b41fee58f6 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -39,12 +39,12 @@ #define HAS_FILE_STREAMS (wxUSE_STREAMS && (wxUSE_FILE || wxUSE_FFILE)) #if HAS_FILE_STREAMS - #if wxUSE_FILE - typedef wxFileInputStream wxImageFileInputStream; - typedef wxFileOutputStream wxImageFileOutputStream; - #elif wxUSE_FFILE + #if wxUSE_FFILE typedef wxFFileInputStream wxImageFileInputStream; typedef wxFFileOutputStream wxImageFileOutputStream; + #elif wxUSE_FILE + typedef wxFileInputStream wxImageFileInputStream; + typedef wxFileOutputStream wxImageFileOutputStream; #endif // wxUSE_FILE/wxUSE_FFILE #endif // HAS_FILE_STREAMS @@ -64,6 +64,7 @@ public: int m_width; int m_height; + wxBitmapType m_type; unsigned char *m_data; bool m_hasMask; @@ -94,6 +95,7 @@ wxImageRefData::wxImageRefData() { m_width = 0; m_height = 0; + m_type = wxBITMAP_TYPE_INVALID; m_data = m_alpha = (unsigned char *) NULL; @@ -140,7 +142,7 @@ wxImage::wxImage( int width, int height, unsigned char* data, unsigned char* alp Create( width, height, data, alpha, static_data ); } -wxImage::wxImage( const wxString& name, long type, int index ) +wxImage::wxImage( const wxString& name, wxBitmapType type, int index ) { LoadFile( name, type, index ); } @@ -151,7 +153,7 @@ wxImage::wxImage( const wxString& name, const wxString& mimetype, int index ) } #if wxUSE_STREAMS -wxImage::wxImage( wxInputStream& stream, long type, int index ) +wxImage::wxImage( wxInputStream& stream, wxBitmapType type, int index ) { LoadFile( stream, type, index ); } @@ -538,13 +540,8 @@ wxImage wxImage::ResampleBox(int width, int height) const const int scale_factor_x_2 = (int)(scale_factor_x / 2); const int scale_factor_y_2 = (int)(scale_factor_y / 2); - // If we want good-looking results we need to pre-blur the image a bit first - wxImage src_image(*this); - src_image = src_image.BlurHorizontal(scale_factor_x_2); - src_image = src_image.BlurVertical(scale_factor_y_2); - - unsigned char* src_data = src_image.GetData(); - unsigned char* src_alpha = src_image.GetAlpha(); + unsigned char* src_data = M_IMGDATA->m_data; + unsigned char* src_alpha = M_IMGDATA->m_alpha; unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_alpha = NULL; @@ -576,7 +573,7 @@ wxImage wxImage::ResampleBox(int width, int height) const j++ ) { // We don't care to average pixels that don't exist (edges) - if ( j < 0 || j > M_IMGDATA->m_height ) + if ( j < 0 || j > M_IMGDATA->m_height - 1 ) continue; for ( int i = int(src_x - scale_factor_x/2.0 + 1); @@ -584,11 +581,11 @@ wxImage wxImage::ResampleBox(int width, int height) const i++ ) { // Don't average edge pixels - if ( i < 0 || i > M_IMGDATA->m_width ) + if ( i < 0 || i > M_IMGDATA->m_width - 1 ) continue; // Calculate the actual index in our source pixels - src_pixel_index = src_y * M_IMGDATA->m_width + src_x; + src_pixel_index = j * M_IMGDATA->m_width + i; sum_r += src_data[src_pixel_index * 3 + 0]; sum_g += src_data[src_pixel_index * 3 + 1]; @@ -675,13 +672,13 @@ wxImage wxImage::ResampleBicubic(int width, int height) const for ( int dsty = 0; dsty < height; dsty++ ) { // We need to calculate the source pixel to interpolate from - Y-axis - double srcpixy = dsty * M_IMGDATA->m_height / height; + double srcpixy = double(dsty * M_IMGDATA->m_height) / height; double dy = srcpixy - (int)srcpixy; for ( int dstx = 0; dstx < width; dstx++ ) { // X-axis of pixel to interpolate from - double srcpixx = dstx * M_IMGDATA->m_width / width; + double srcpixx = double(dstx * M_IMGDATA->m_width) / width; double dx = srcpixx - (int)srcpixx; // Sums for each color channel @@ -743,7 +740,7 @@ wxImage wxImage::ResampleBicubic(int width, int height) const } // Blur in the horizontal direction -wxImage wxImage::BlurHorizontal(int blurRadius) +wxImage wxImage::BlurHorizontal(int blurRadius) const { wxImage ret_image; ret_image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); @@ -858,7 +855,7 @@ wxImage wxImage::BlurHorizontal(int blurRadius) } // Blur in the vertical direction -wxImage wxImage::BlurVertical(int blurRadius) +wxImage wxImage::BlurVertical(int blurRadius) const { wxImage ret_image; ret_image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); @@ -973,7 +970,7 @@ wxImage wxImage::BlurVertical(int blurRadius) } // The new blur function -wxImage wxImage::Blur(int blurRadius) +wxImage wxImage::Blur(int blurRadius) const { wxImage ret_image; ret_image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false); @@ -1288,6 +1285,26 @@ void wxImage::Paste( const wxImage &image, int x, int y ) return; } + // Copy over the alpha channel from the original image + if ( image.HasAlpha() ) + { + if ( !HasAlpha() ) + InitAlpha(); + + unsigned char* source_data = image.GetAlpha() + xx + yy*image.GetWidth(); + int source_step = image.GetWidth(); + + unsigned char* target_data = GetAlpha() + (x+xx) + (y+yy)*M_IMGDATA->m_width; + int target_step = M_IMGDATA->m_width; + + for (int j = 0; j < height; j++, + source_data += source_step, + target_data += target_step) + { + memcpy( target_data, source_data, width ); + } + } + if (!HasMask() && image.HasMask()) { unsigned char r = image.GetMaskRed(); @@ -1444,6 +1461,13 @@ int wxImage::GetHeight() const return M_IMGDATA->m_height; } +wxBitmapType wxImage::GetType() const +{ + wxCHECK_MSG( IsOk(), wxBITMAP_TYPE_INVALID, wxT("invalid image") ); + + return M_IMGDATA->m_type; +} + long wxImage::XYToIndex(int x, int y) const { if ( Ok() && @@ -1665,7 +1689,9 @@ void wxImage::SetAlpha( unsigned char *alpha, bool static_data ) alpha = (unsigned char *)malloc(M_IMGDATA->m_width*M_IMGDATA->m_height); } - free(M_IMGDATA->m_alpha); + if( !M_IMGDATA->m_staticAlpha ) + free(M_IMGDATA->m_alpha); + M_IMGDATA->m_alpha = alpha; M_IMGDATA->m_staticAlpha = static_data; } @@ -1898,8 +1924,11 @@ bool wxImage::ConvertAlphaToMask(unsigned char threshold) } } - free(M_IMGDATA->m_alpha); + if( !M_IMGDATA->m_staticAlpha ) + free(M_IMGDATA->m_alpha); + M_IMGDATA->m_alpha = NULL; + M_IMGDATA->m_staticAlpha = false; return true; } @@ -1994,7 +2023,7 @@ bool wxImage::HasOption(const wxString& name) const // ---------------------------------------------------------------------------- bool wxImage::LoadFile( const wxString& WXUNUSED_UNLESS_STREAMS(filename), - long WXUNUSED_UNLESS_STREAMS(type), + wxBitmapType WXUNUSED_UNLESS_STREAMS(type), int WXUNUSED_UNLESS_STREAMS(index) ) { #if HAS_FILE_STREAMS @@ -2038,25 +2067,23 @@ bool wxImage::LoadFile( const wxString& WXUNUSED_UNLESS_STREAMS(filename), } - bool wxImage::SaveFile( const wxString& filename ) const { wxString ext = filename.AfterLast('.').Lower(); - wxImageHandler * pHandler = FindHandler(ext, -1); - if (pHandler) + wxImageHandler *handler = FindHandler(ext, wxBITMAP_TYPE_ANY); + if ( !handler) { - SaveFile(filename, pHandler->GetType()); - return true; + wxLogError(_("Can't save image to file '%s': unknown extension."), + filename); + return false; } - wxLogError(_("Can't save image to file '%s': unknown extension."), filename.c_str()); - - return false; + return SaveFile(filename, handler->GetType()); } bool wxImage::SaveFile( const wxString& WXUNUSED_UNLESS_STREAMS(filename), - int WXUNUSED_UNLESS_STREAMS(type) ) const + wxBitmapType WXUNUSED_UNLESS_STREAMS(type) ) const { #if HAS_FILE_STREAMS wxCHECK_MSG( Ok(), false, wxT("invalid image") ); @@ -2106,7 +2133,7 @@ bool wxImage::CanRead( const wxString& WXUNUSED_UNLESS_STREAMS(name) ) } int wxImage::GetImageCount( const wxString& WXUNUSED_UNLESS_STREAMS(name), - long WXUNUSED_UNLESS_STREAMS(type) ) + wxBitmapType WXUNUSED_UNLESS_STREAMS(type) ) { #if HAS_FILE_STREAMS wxImageFileInputStream stream(name); @@ -2133,19 +2160,25 @@ bool wxImage::CanRead( wxInputStream &stream ) return false; } -int wxImage::GetImageCount( wxInputStream &stream, long type ) +int wxImage::GetImageCount( wxInputStream &stream, wxBitmapType type ) { wxImageHandler *handler; if ( type == wxBITMAP_TYPE_ANY ) { - wxList &list=GetHandlers(); + const wxList& list = GetHandlers(); - for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext()) + for ( wxList::compatibility_iterator node = list.GetFirst(); + node; + node = node->GetNext() ) { - handler=(wxImageHandler*)node->GetData(); + handler = (wxImageHandler*)node->GetData(); if ( handler->CanRead(stream) ) - return handler->GetImageCount(stream); + { + const int count = handler->GetImageCount(stream); + if ( count >= 0 ) + return count; + } } @@ -2172,7 +2205,16 @@ int wxImage::GetImageCount( wxInputStream &stream, long type ) } } -bool wxImage::LoadFile( wxInputStream& stream, long type, int index ) +bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index) +{ + if ( !handler.LoadFile(this, stream, true/*verbose*/, index) ) + return false; + + M_IMGDATA->m_type = handler.GetType(); + return true; +} + +bool wxImage::LoadFile( wxInputStream& stream, wxBitmapType type, int index ) { UnRef(); @@ -2182,36 +2224,36 @@ bool wxImage::LoadFile( wxInputStream& stream, long type, int index ) if ( type == wxBITMAP_TYPE_ANY ) { - wxList &list=GetHandlers(); - - for ( wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext() ) + const wxList& list = GetHandlers(); + for ( wxList::compatibility_iterator node = list.GetFirst(); + node; + node = node->GetNext() ) { - handler=(wxImageHandler*)node->GetData(); - if ( handler->CanRead(stream) ) - return handler->LoadFile(this, stream, true/*verbose*/, index); - + handler = (wxImageHandler*)node->GetData(); + if ( handler->CanRead(stream) && DoLoad(*handler, stream, index) ) + return true; } wxLogWarning( _("No handler found for image type.") ); + return false; } + //else: have specific type handler = FindHandler(type); - - if (handler == 0) + if ( !handler ) { wxLogWarning( _("No image handler for type %ld defined."), type ); - return false; } - if (stream.IsSeekable() && !handler->CanRead(stream)) + if ( stream.IsSeekable() && !handler->CanRead(stream) ) { wxLogError(_("Image file is not of type %ld."), type); return false; } - else - return handler->LoadFile(this, stream, true/*verbose*/, index); + + return DoLoad(*handler, stream, index); } bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int index ) @@ -2222,23 +2264,32 @@ bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int ind wxImageHandler *handler = FindHandlerMime(mimetype); - if (handler == 0) + if ( !handler ) { wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() ); - return false; } - if (stream.IsSeekable() && !handler->CanRead(stream)) + if ( stream.IsSeekable() && !handler->CanRead(stream) ) { wxLogError(_("Image file is not of type %s."), mimetype); return false; } - else - return handler->LoadFile( this, stream, true/*verbose*/, index ); + + return DoLoad(*handler, stream, index); +} + +bool wxImage::DoSave(wxImageHandler& handler, wxOutputStream& stream) const +{ + wxImage * const self = wx_const_cast(wxImage *, this); + if ( !handler.SaveFile(self, stream) ) + return false; + + M_IMGDATA->m_type = handler.GetType(); + return true; } -bool wxImage::SaveFile( wxOutputStream& stream, int type ) const +bool wxImage::SaveFile( wxOutputStream& stream, wxBitmapType type ) const { wxCHECK_MSG( Ok(), false, wxT("invalid image") ); @@ -2246,11 +2297,10 @@ bool wxImage::SaveFile( wxOutputStream& stream, int type ) const if ( !handler ) { wxLogWarning( _("No image handler for type %d defined."), type ); - return false; } - return handler->SaveFile( (wxImage*)this, stream ); + return DoSave(*handler, stream); } bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) const @@ -2261,12 +2311,11 @@ bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) const if ( !handler ) { wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() ); - - return false; } - return handler->SaveFile( (wxImage*)this, stream ); + return DoSave(*handler, stream); } + #endif // wxUSE_STREAMS // ---------------------------------------------------------------------------- @@ -2333,24 +2382,26 @@ wxImageHandler *wxImage::FindHandler( const wxString& name ) node = node->GetNext(); } - return 0; + return NULL; } -wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType ) +wxImageHandler *wxImage::FindHandler( const wxString& extension, wxBitmapType bitmapType ) { wxList::compatibility_iterator node = sm_handlers.GetFirst(); while (node) { wxImageHandler *handler = (wxImageHandler*)node->GetData(); if ( (handler->GetExtension().Cmp(extension) == 0) && - (bitmapType == -1 || handler->GetType() == bitmapType) ) + ( (bitmapType == wxBITMAP_TYPE_ANY) || (handler->GetType() == bitmapType)) ) + { return handler; + } node = node->GetNext(); } - return 0; + return NULL; } -wxImageHandler *wxImage::FindHandler( long bitmapType ) +wxImageHandler *wxImage::FindHandler(wxBitmapType bitmapType ) { wxList::compatibility_iterator node = sm_handlers.GetFirst(); while (node) @@ -2359,7 +2410,7 @@ wxImageHandler *wxImage::FindHandler( long bitmapType ) if (handler->GetType() == bitmapType) return handler; node = node->GetNext(); } - return 0; + return NULL; } wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype ) @@ -2371,7 +2422,7 @@ wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype ) if (handler->GetMimeType().IsSameAs(mimetype, false)) return handler; node = node->GetNext(); } - return 0; + return NULL; } void wxImage::InitStandardHandlers()