#include <msp/io/file.h>
#include <msp/strings/format.h>
#include "imageloader.h"
-#ifdef WITH_LIBPNG
-#include "png/pngloader.h"
-#endif
-#ifdef WITH_DEVIL
-#include "devil/devilloader.h"
-#endif
using namespace std;
namespace Msp {
namespace Graphics {
+bool ImageLoader::registered_loaders_changed = false;
+
ImageLoader::ImageLoader():
source(0)
{ }
ImageLoader *ImageLoader::open_io(IO::Seekable &io)
{
- char sig_buf[8];
- unsigned sig_len = io.read(sig_buf, sizeof(sig_buf));
- string sig(sig_buf, sig_len);
- io.seek(0, IO::S_BEG);
+ list<RegisterBase *> &loaders = get_registered_loaders();
+ if(registered_loaders_changed)
+ {
+ registered_loaders_changed = false;
+ loaders.sort(signature_size_compare);
+ }
+
+ vector<char> sig_buf(loaders.back()->get_signature_size());
+ unsigned sig_len = io.read(&sig_buf[0], sig_buf.size());
+ string signature(sig_buf.begin(), sig_buf.end());
- // TODO register loader classes automatically
ImageLoader *loader = 0;
- if(0)
- ;
-#ifdef WITH_LIBPNG
- else if(PngLoader::detect(sig))
- loader = new PngLoader(io);
-#endif
-#ifdef WITH_DEVIL
- else if(DevilLoader::detect(sig))
- loader = new DevilLoader(io);
-#endif
- else
+ for(list<RegisterBase *>::const_iterator i=loaders.begin(); (!loader && i!=loaders.end()); ++i)
+ if((*i)->detect(signature))
+ loader = (*i)->create(io);
+
+ io.seek(0, IO::S_BEG);
+
+ if(!loader)
{
string sig_hex;
for(unsigned i=0; i<sig_len; ++i)
return loader;
}
+
+ImageLoader::RegisterBase::RegisterBase()
+{
+ get_registered_loaders().push_back(this);
+ registered_loaders_changed = true;
+}
+
+
+list<ImageLoader::RegisterBase *> &ImageLoader::get_registered_loaders()
+{
+ static list<RegisterBase *> regs;
+ return regs;
+}
+
+bool ImageLoader::signature_size_compare(RegisterBase *r1, RegisterBase *r2)
+{
+ return r1->get_signature_size()<r2->get_signature_size();
+}
+
} // namespace Graphics
} // namespace Msp
class ImageLoader
{
private:
- IO::Base *source;
+ class RegisterBase
+ {
+ protected:
+ RegisterBase();
+ public:
+ virtual ~RegisterBase() { }
+
+ virtual unsigned get_signature_size() const = 0;
+ virtual bool detect(const std::string &) const = 0;
+ virtual ImageLoader *create(IO::Seekable &) const = 0;
+ };
+
protected:
+ template<typename T>
+ class Register: RegisterBase
+ {
+ public:
+ virtual unsigned get_signature_size() const { return T::get_signature_size(); }
+ virtual bool detect(const std::string &s) const { return T::detect(s); }
+ virtual T *create(IO::Seekable &io) const { return new T(io); }
+ };
+
+private:
+ IO::Base *source;
+ static std::list<RegisterBase *> &get_registered_loaders();
+ static bool registered_loaders_changed;
+ static bool signature_size_compare(RegisterBase *, RegisterBase *);
+
+protected:
ImageLoader();
public:
virtual ~ImageLoader();