+ return 0;
+}
+
+#if wxUSE_STREAMS
+
+bool wxImage::CanRead( wxInputStream &stream )
+{
+ const wxList& list = GetHandlers();
+
+ for ( wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext() )
+ {
+ wxImageHandler *handler=(wxImageHandler*)node->GetData();
+ if (handler->CanRead( stream ))
+ return true;
+ }
+
+ return false;
+}
+
+int wxImage::GetImageCount( wxInputStream &stream, wxBitmapType type )
+{
+ wxImageHandler *handler;
+
+ if ( type == wxBITMAP_TYPE_ANY )
+ {
+ const wxList& list = GetHandlers();
+
+ for ( wxList::compatibility_iterator node = list.GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ handler = (wxImageHandler*)node->GetData();
+ if ( handler->CanRead(stream) )
+ {
+ const int count = handler->GetImageCount(stream);
+ if ( count >= 0 )
+ return count;
+ }
+
+ }
+
+ 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::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);
+
+ // Preserve the original stream position if possible to rewind back to it
+ // if we failed to load the file -- maybe the next handler that we try can
+ // succeed after us then.
+ wxFileOffset posOld = wxInvalidOffset;
+ if ( stream.IsSeekable() )
+ posOld = stream.TellI();
+
+ if ( !handler.LoadFile(this, stream, true/*verbose*/, index) )
+ {
+ if ( posOld != wxInvalidOffset )
+ stream.SeekI(posOld);
+
+ return false;
+ }
+
+ // 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);
+ }
+
+ // Set this after Rescale, which currently does not preserve it
+ M_IMGDATA->m_type = handler.GetType();
+
+ return true;
+}
+
+bool wxImage::LoadFile( wxInputStream& stream, wxBitmapType type, int index )
+{
+ AllocExclusive();
+
+ wxImageHandler *handler;
+
+ if ( type == wxBITMAP_TYPE_ANY )
+ {
+ if ( !stream.IsSeekable() )
+ {
+ // The error message about image data format being unknown below
+ // would be misleading in this case as we are not even going to try
+ // any handlers because CanRead() never does anything for not
+ // seekable stream, so try to be more precise here.
+ wxLogError(_("Can't automatically determine the image format "
+ "for non-seekable input."));
+ return false;
+ }
+
+ const wxList& list = GetHandlers();
+ for ( wxList::compatibility_iterator node = list.GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ handler = (wxImageHandler*)node->GetData();
+ if ( handler->CanRead(stream) && DoLoad(*handler, stream, index) )
+ return true;
+ }
+
+ wxLogWarning( _("Unknown image data format.") );
+
+ return false;
+ }
+ //else: have specific type
+
+ handler = FindHandler(type);
+ if ( !handler )
+ {
+ wxLogWarning( _("No image handler for type %d defined."), type );
+ return false;
+ }
+
+ if ( stream.IsSeekable() && !handler->CanRead(stream) )
+ {
+ wxLogError(_("This is not a %s."), handler->GetName());
+ return false;
+ }
+
+ return DoLoad(*handler, stream, index);
+}
+
+bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int index )
+{
+ UnRef();
+
+ m_refData = new wxImageRefData;
+
+ wxImageHandler *handler = FindHandlerMime(mimetype);
+
+ if ( !handler )
+ {
+ wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
+ return false;
+ }
+
+ if ( stream.IsSeekable() && !handler->CanRead(stream) )
+ {
+ wxLogError(_("Image is not of type %s."), mimetype);
+ return false;
+ }
+
+ return DoLoad(*handler, stream, index);
+}
+
+bool wxImage::DoSave(wxImageHandler& handler, wxOutputStream& stream) const
+{
+ wxImage * const self = const_cast<wxImage *>(this);
+ if ( !handler.SaveFile(self, stream) )
+ return false;
+
+ M_IMGDATA->m_type = handler.GetType();
+ return true;
+}
+
+bool wxImage::SaveFile( wxOutputStream& stream, wxBitmapType type ) const
+{
+ wxCHECK_MSG( IsOk(), false, wxT("invalid image") );
+
+ wxImageHandler *handler = FindHandler(type);
+ if ( !handler )
+ {
+ wxLogWarning( _("No image handler for type %d defined."), type );
+ return false;
+ }
+
+ return DoSave(*handler, stream);
+}
+
+bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) const
+{
+ wxCHECK_MSG( IsOk(), false, wxT("invalid image") );
+
+ wxImageHandler *handler = FindHandlerMime(mimetype);
+ if ( !handler )
+ {
+ wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
+ }
+
+ return DoSave(*handler, stream);
+}
+
+#endif // wxUSE_STREAMS
+
+// ----------------------------------------------------------------------------
+// image I/O handlers
+// ----------------------------------------------------------------------------
+
+void wxImage::AddHandler( wxImageHandler *handler )
+{
+ // Check for an existing handler of the type being added.
+ if (FindHandler( handler->GetType() ) == 0)
+ {
+ sm_handlers.Append( handler );
+ }
+ else
+ {
+ // This is not documented behaviour, merely the simplest 'fix'
+ // for preventing duplicate additions. If someone ever has
+ // a good reason to add and remove duplicate handlers (and they
+ // may) we should probably refcount the duplicates.
+ // also an issue in InsertHandler below.
+
+ wxLogDebug( wxT("Adding duplicate image handler for '%s'"),
+ handler->GetName().c_str() );
+ delete handler;
+ }
+}
+
+void wxImage::InsertHandler( wxImageHandler *handler )
+{
+ // Check for an existing handler of the type being added.
+ if (FindHandler( handler->GetType() ) == 0)
+ {
+ sm_handlers.Insert( handler );
+ }
+ else
+ {
+ // see AddHandler for additional comments.
+ wxLogDebug( wxT("Inserting duplicate image handler for '%s'"),
+ handler->GetName().c_str() );
+ delete handler;
+ }
+}
+
+bool wxImage::RemoveHandler( const wxString& name )
+{
+ wxImageHandler *handler = FindHandler(name);
+ if (handler)
+ {
+ sm_handlers.DeleteObject(handler);
+ delete handler;
+ return true;
+ }
+ else
+ return false;
+}
+
+wxImageHandler *wxImage::FindHandler( const wxString& name )
+{
+ wxList::compatibility_iterator node = sm_handlers.GetFirst();
+ while (node)
+ {
+ wxImageHandler *handler = (wxImageHandler*)node->GetData();
+ if (handler->GetName().Cmp(name) == 0) return handler;
+
+ node = node->GetNext();
+ }
+ return NULL;
+}
+
+wxImageHandler *wxImage::FindHandler( const wxString& extension, wxBitmapType bitmapType )
+{
+ wxList::compatibility_iterator node = sm_handlers.GetFirst();
+ while (node)
+ {
+ wxImageHandler *handler = (wxImageHandler*)node->GetData();
+ if ((bitmapType == wxBITMAP_TYPE_ANY) || (handler->GetType() == bitmapType))
+ {
+ if (handler->GetExtension() == extension)
+ return handler;
+ if (handler->GetAltExtensions().Index(extension, false) != wxNOT_FOUND)
+ return handler;
+ }
+ node = node->GetNext();
+ }
+ return NULL;
+}
+
+wxImageHandler *wxImage::FindHandler(wxBitmapType bitmapType )
+{
+ wxList::compatibility_iterator node = sm_handlers.GetFirst();
+ while (node)
+ {
+ wxImageHandler *handler = (wxImageHandler *)node->GetData();
+ if (handler->GetType() == bitmapType) return handler;
+ node = node->GetNext();
+ }
+ return NULL;
+}
+
+wxImageHandler *wxImage::FindHandlerMime( const wxString& mimetype )
+{
+ wxList::compatibility_iterator node = sm_handlers.GetFirst();
+ while (node)
+ {
+ wxImageHandler *handler = (wxImageHandler *)node->GetData();
+ if (handler->GetMimeType().IsSameAs(mimetype, false)) return handler;
+ node = node->GetNext();
+ }
+ return NULL;
+}
+
+void wxImage::InitStandardHandlers()
+{
+#if wxUSE_STREAMS
+ AddHandler(new wxBMPHandler);
+#endif // wxUSE_STREAMS
+}
+
+void wxImage::CleanUpHandlers()
+{
+ wxList::compatibility_iterator node = sm_handlers.GetFirst();
+ while (node)
+ {
+ wxImageHandler *handler = (wxImageHandler *)node->GetData();
+ wxList::compatibility_iterator next = node->GetNext();
+ delete handler;
+ node = next;
+ }
+
+ sm_handlers.Clear();
+}
+
+wxString wxImage::GetImageExtWildcard()
+{
+ wxString fmts;
+
+ wxList& Handlers = wxImage::GetHandlers();
+ wxList::compatibility_iterator Node = Handlers.GetFirst();
+ while ( Node )
+ {
+ 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(";");
+ }
+
+ return wxT("(") + fmts + wxT(")|") + fmts;
+}