X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/52b64b0a78c7f6c7994d25f6e212c715ab4404ba..19caf2292672bd3c6ecad003ab213709f2d98319:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index 999f43c5be..3241ed03cd 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -108,29 +108,30 @@ wxImage::wxImage( int width, int height, unsigned char* data, bool static_data ) Create( width, height, data, static_data ); } -wxImage::wxImage( const wxString& name, long type ) +wxImage::wxImage( const wxString& name, long type, int index ) { - LoadFile( name, type ); + LoadFile( name, type, index ); } -wxImage::wxImage( const wxString& name, const wxString& mimetype ) +wxImage::wxImage( const wxString& name, const wxString& mimetype, int index ) { - LoadFile( name, mimetype ); + LoadFile( name, mimetype, index ); } #if wxUSE_STREAMS -wxImage::wxImage( wxInputStream& stream, long type ) +wxImage::wxImage( wxInputStream& stream, long type, int index ) { - LoadFile( stream, type ); + LoadFile( stream, type, index ); } -wxImage::wxImage( wxInputStream& stream, const wxString& mimetype ) +wxImage::wxImage( wxInputStream& stream, const wxString& mimetype, int index ) { - LoadFile( stream, mimetype ); + LoadFile( stream, mimetype, index ); } #endif // wxUSE_STREAMS wxImage::wxImage( const wxImage& image ) + : wxObject() { Ref(image); } @@ -198,8 +199,8 @@ wxImage wxImage::Copy() const wxCHECK_MSG( data, image, wxT("unable to create image") ); - if (M_IMGDATA->m_hasMask) - image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); + image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue ); + image.SetMask( M_IMGDATA->m_hasMask ); memcpy( data, GetData(), M_IMGDATA->m_width*M_IMGDATA->m_height*3 ); @@ -275,6 +276,14 @@ wxImage wxImage::Scale( int width, int height ) const } #endif + // In case this is a cursor, make sure the hotspot is scalled accordingly: + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) ) + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, + (GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X)*width)/old_width); + if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ) + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, + (GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y)*height)/old_height); + return image; } @@ -721,33 +730,33 @@ int wxImage::GetHeight() const } -bool wxImage::GetUnusedColour ( unsigned char * r, unsigned char * g, unsigned char * b ) +bool wxImage::FindFirstUnusedColour( + unsigned char *r, unsigned char *g, unsigned char *b, + unsigned char startR, unsigned char startG, unsigned char startB) const { - wxHashTable hTable; + wxImageHistogram histogram; unsigned long key; - ComputeHistogram( hTable ); + ComputeHistogram(histogram); - // start with blackest color and work to lightest - // 0,0,0 is quite likely to be a used color - unsigned char r2 = 1; - unsigned char g2 = 0; - unsigned char b2 = 0; + unsigned char r2 = startR; + unsigned char g2 = startG; + unsigned char b2 = startB; key = (r2 << 16) | (g2 << 8) | b2; - while ( (wxHNode *) hTable.Get(key) ) + while ( histogram.find(key) != histogram.end() ) { // color already used - r2 ++ ; + r2++; if ( r2 >= 255 ) { r2 = 0; - g2 ++ ; + g2++; if ( g2 >= 255 ) { - g2 = 0 ; - b2 ++ ; + g2 = 0; + b2++; if ( b2 >= 255 ) { wxLogError( _("GetUnusedColour:: No Unused Color in image ") ); @@ -759,19 +768,17 @@ bool wxImage::GetUnusedColour ( unsigned char * r, unsigned char * g, unsigne key = (r2 << 16) | (g2 << 8) | b2; } + if (r) *r = r2; + if (g) *g = g2; + if (b) *b = b2; + return TRUE; } -bool wxImage::ApplyMask ( const wxImage & mask ) +bool wxImage::SetMaskFromImage(const wxImage& mask, + unsigned char mr, unsigned char mg, unsigned char mb) { - // what to do if we already have a mask ?? - if (M_IMGDATA->m_hasMask || mask.HasMask() ) - { - wxLogError( _("Image already masked") ); - return FALSE; - } - // check that the images are the same size if ( (M_IMGDATA->m_height != mask.GetHeight() ) || (M_IMGDATA->m_width != mask.GetWidth () ) ) { @@ -781,7 +788,7 @@ bool wxImage::ApplyMask ( const wxImage & mask ) // find unused colour unsigned char r,g,b ; - if (!GetUnusedColour (&r, &g, &b)) + if (!FindFirstUnusedColour(&r, &g, &b)) { wxLogError( _("No Unused Color in image being masked") ); return FALSE ; @@ -794,9 +801,10 @@ bool wxImage::ApplyMask ( const wxImage & mask ) const int h = GetHeight(); for (int j = 0; j < h; j++) + { for (int i = 0; i < w; i++) { - if ((maskdata[0] > 128) && (maskdata[1] > 128) && (maskdata[2] > 128 )) + if ((maskdata[0] == mr) && (maskdata[1] == mg) && (maskdata[2] == mb)) { imgdata[0] = r; imgdata[1] = g; @@ -805,11 +813,10 @@ bool wxImage::ApplyMask ( const wxImage & mask ) imgdata += 3; maskdata += 3; } + } - M_IMGDATA->m_maskRed = r; - M_IMGDATA->m_maskGreen = g; - M_IMGDATA->m_maskBlue = b; - M_IMGDATA->m_hasMask = TRUE; + SetMaskColour(r, g, b); + SetMask(TRUE); return TRUE; } @@ -892,14 +899,14 @@ bool wxImage::HasOption(const wxString& name) const return (M_IMGDATA->m_optionNames.Index(name, FALSE) != wxNOT_FOUND); } -bool wxImage::LoadFile( const wxString& filename, long type ) +bool wxImage::LoadFile( const wxString& filename, long type, int index ) { #if wxUSE_STREAMS if (wxFileExists(filename)) { wxFileInputStream stream(filename); wxBufferedInputStream bstream( stream ); - return LoadFile(bstream, type); + return LoadFile(bstream, type, index); } else { @@ -912,14 +919,14 @@ bool wxImage::LoadFile( const wxString& filename, long type ) #endif // wxUSE_STREAMS } -bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype ) +bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype, int index ) { #if wxUSE_STREAMS if (wxFileExists(filename)) { wxFileInputStream stream(filename); wxBufferedInputStream bstream( stream ); - return LoadFile(bstream, mimetype); + return LoadFile(bstream, mimetype, index); } else { @@ -932,9 +939,29 @@ bool wxImage::LoadFile( const wxString& filename, const wxString& mimetype ) #endif // wxUSE_STREAMS } -bool wxImage::SaveFile( const wxString& filename, int type ) + + +bool wxImage::SaveFile( const wxString& filename ) const +{ + wxString ext = filename.AfterLast('.').Lower(); + + wxImageHandler * pHandler = FindHandler(ext, -1); + if (pHandler) + { + SaveFile(filename, pHandler->GetType()); + return TRUE; + } + + wxLogError(_("Can't save image to file '%s': unknown extension."), filename.c_str()); + + return FALSE; +} + +bool wxImage::SaveFile( const wxString& filename, int type ) const { #if wxUSE_STREAMS + ((wxImage*)this)->SetOption(wxIMAGE_OPTION_FILENAME, filename); + wxFileOutputStream stream(filename); if ( stream.LastError() == wxStream_NOERROR ) @@ -947,9 +974,11 @@ bool wxImage::SaveFile( const wxString& filename, int type ) return FALSE; } -bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype ) +bool wxImage::SaveFile( const wxString& filename, const wxString& mimetype ) const { #if wxUSE_STREAMS + ((wxImage*)this)->SetOption(wxIMAGE_OPTION_FILENAME, filename); + wxFileOutputStream stream(filename); if ( stream.LastError() == wxStream_NOERROR ) @@ -972,23 +1001,72 @@ bool wxImage::CanRead( const wxString &name ) #endif } +int wxImage::GetImageCount( const wxString &name, long type ) +{ +#if wxUSE_STREAMS + wxFileInputStream stream(name); + return GetImageCount(stream, type); +#else + return 0; +#endif +} + #if wxUSE_STREAMS bool wxImage::CanRead( wxInputStream &stream ) { - wxList &list=GetHandlers(); + const wxList& list = GetHandlers(); - for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() ) + for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() ) { - wxImageHandler *handler=(wxImageHandler*)node->GetData(); - if (handler->CanRead( stream )) - return TRUE; + wxImageHandler *handler=(wxImageHandler*)node->GetData(); + if (handler->CanRead( stream )) + return TRUE; } - return FALSE; + return FALSE; } -bool wxImage::LoadFile( wxInputStream& stream, long type ) +int wxImage::GetImageCount( wxInputStream &stream, long type ) +{ + wxImageHandler *handler; + + if ( type == wxBITMAP_TYPE_ANY ) + { + wxList &list=GetHandlers(); + + for (wxList::Node *node = list.GetFirst(); node; node = node->GetNext()) + { + handler=(wxImageHandler*)node->GetData(); + if ( handler->CanRead(stream) ) + return handler->GetImageCount(stream); + + } + + wxLogWarning(_("No handler found for image type.")); + return 0; + } + + handler = FindHandler(type); + + if ( !handler ) + { + wxLogWarning(_("No image handler for type %d defined."), type); + return FALSE; + } + + if ( handler->CanRead(stream) ) + { + return handler->GetImageCount(stream); + } + else + { + wxLogError(_("Image file is not of type %d."), type); + return 0; + } +} + +bool wxImage::LoadFile( wxInputStream& stream, long type, int index ) { UnRef(); @@ -996,15 +1074,15 @@ bool wxImage::LoadFile( wxInputStream& stream, long type ) wxImageHandler *handler; - if (type==wxBITMAP_TYPE_ANY) + if ( type == wxBITMAP_TYPE_ANY ) { wxList &list=GetHandlers(); for ( wxList::Node *node = list.GetFirst(); node; node = node->GetNext() ) { handler=(wxImageHandler*)node->GetData(); - if (handler->CanRead( stream )) - return handler->LoadFile( this, stream ); + if ( handler->CanRead(stream) ) + return handler->LoadFile(this, stream, TRUE/*verbose*/, index); } @@ -1021,10 +1099,10 @@ bool wxImage::LoadFile( wxInputStream& stream, long type ) return FALSE; } - return handler->LoadFile( this, stream ); + return handler->LoadFile(this, stream, TRUE/*verbose*/, index); } -bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype ) +bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int index ) { UnRef(); @@ -1039,10 +1117,10 @@ bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype ) return FALSE; } - return handler->LoadFile( this, stream ); + return handler->LoadFile( this, stream, TRUE/*verbose*/, index ); } -bool wxImage::SaveFile( wxOutputStream& stream, int type ) +bool wxImage::SaveFile( wxOutputStream& stream, int type ) const { wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") ); @@ -1055,10 +1133,10 @@ bool wxImage::SaveFile( wxOutputStream& stream, int type ) return FALSE; } - return handler->SaveFile( this, stream ); + return handler->SaveFile( (wxImage*)this, stream ); } -bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) +bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) const { wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") ); @@ -1071,7 +1149,7 @@ bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) return FALSE; } - return handler->SaveFile( this, stream ); + return handler->SaveFile( (wxImage*)this, stream ); } #endif // wxUSE_STREAMS @@ -1156,7 +1234,10 @@ wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype ) void wxImage::InitStandardHandlers() { +#if wxUSE_STREAMS AddHandler(new wxBMPHandler); +#endif // wxUSE_STREAMS + #if wxUSE_XPM && !defined(__WXGTK__) && !defined(__WXMOTIF__) AddHandler(new wxXPMHandler); #endif @@ -1205,12 +1286,32 @@ bool wxImageHandler::CanRead( const wxString& name ) return CanRead(stream); } - else { - wxLogError( _("Can't check image format of file '%s': file does not exist."), name.c_str() ); + wxLogError( _("Can't check image format of file '%s': file does not exist."), name.c_str() ); + + return FALSE; +} + +bool wxImageHandler::CallDoCanRead(wxInputStream& stream) +{ + off_t posOld = stream.TellI(); + if ( posOld == wxInvalidOffset ) + { + // can't test unseekable stream + return FALSE; + } + + bool ok = DoCanRead(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 FALSE; + + return ok; } #endif // wxUSE_STREAMS @@ -1218,10 +1319,10 @@ bool wxImageHandler::CanRead( const wxString& name ) //----------------------------------------------------------------------------- -// wxBitmap convertion routines +// Deprecated wxBitmap convertion routines //----------------------------------------------------------------------------- -#if wxUSE_GUI +#if WXWIN_COMPATIBILITY_2_2 && wxUSE_GUI #ifdef __WXGTK__ wxBitmap wxImage::ConvertToMonoBitmap( unsigned char red, unsigned char green, unsigned char blue ) const @@ -1243,24 +1344,7 @@ wxImage::wxImage( const wxBitmap &bitmap ) *this = bitmap.ConvertToImage(); } -#endif - - - -// A module to allow wxImage initialization/cleanup -// without calling these functions from app.cpp or from -// the user's application. - -class wxImageModule: public wxModule -{ -DECLARE_DYNAMIC_CLASS(wxImageModule) -public: - wxImageModule() {} - bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; }; - void OnExit() { wxImage::CleanUpHandlers(); }; -}; - -IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule) +#endif // WXWIN_COMPATIBILITY_2_2 && wxUSE_GUI //----------------------------------------------------------------------------- @@ -1272,7 +1356,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule) // less, in this case it would be invoked as CountColours(256)). Default // value for stopafter is -1 (don't care). // -unsigned long wxImage::CountColours( unsigned long stopafter ) +unsigned long wxImage::CountColours( unsigned long stopafter ) const { wxHashTable h; wxObject dummy; @@ -1302,19 +1386,13 @@ unsigned long wxImage::CountColours( unsigned long stopafter ) } -// GRG, Dic/99 -// Computes the histogram of the image and fills a hash table, indexed -// with integer keys built as 0xRRGGBB, containing wxHNode objects. Each -// wxHNode contains an 'index' (useful to build a palette with the image -// colours) and a 'value', which is the number of pixels in the image with -// that colour. -// -unsigned long wxImage::ComputeHistogram( wxHashTable &h ) +unsigned long wxImage::ComputeHistogram( wxImageHistogram &h ) const { unsigned char r, g, b; unsigned char *p; unsigned long size, nentries, key; - wxHNode *hnode; + + h.clear(); p = GetData(); size = GetWidth() * GetHeight(); @@ -1327,18 +1405,9 @@ unsigned long wxImage::ComputeHistogram( wxHashTable &h ) b = *(p++); key = (r << 16) | (g << 8) | b; - hnode = (wxHNode *) h.Get(key); - - if (hnode) - hnode->value++; - else - { - hnode = new wxHNode(); - hnode->index = nentries++; - hnode->value = 1; - - h.Put(key, (wxObject *)hnode); - } + wxImageHistogramEntry& entry = h[key]; + if ( entry.value++ == 0 ) + entry.index = nentries++; } return nentries; @@ -1602,4 +1671,24 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i return rotated; } + + + + +// A module to allow wxImage initialization/cleanup +// without calling these functions from app.cpp or from +// the user's application. + +class wxImageModule: public wxModule +{ +DECLARE_DYNAMIC_CLASS(wxImageModule) +public: + wxImageModule() {} + bool OnInit() { wxImage::InitStandardHandlers(); return TRUE; }; + void OnExit() { wxImage::CleanUpHandlers(); }; +}; + +IMPLEMENT_DYNAMIC_CLASS(wxImageModule, wxModule) + + #endif // wxUSE_IMAGE