Creating an Image Format Plugin



  • Hi all,
    I have been trying to learn how to create an image format plugin for some custom image types. I decided to start simple and basically change the header of a PPM and have a plugin that reads in my "new" PPM format. It seems like I am doing something right - it does see the plugin -

    Found metadata in lib C:/Users/dayd/Documents/build-LibraryTest-Desktop64-Debug/debug/imageformats/ImgLibPlugin.dll, metadata=
    {
    "IID": "imgLibPlugin",
    "MetaData": {
    "Keys": [
    "xyz24"
    ],
    "MimeTypes": [
    "image/xyz24"
    ]
    },
    "className": "ImgLibPlugin",
    "debug": true,
    "version": 329985
    }

    but then it says:
    Got keys from plugin meta data ()

    and continues to load all the other plugins in the usual place:
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qgifd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qicnsd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qicod.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qjpegd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qsvgd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qtgad.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qtiffd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qwbmpd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qwebpd.dll"

    I am currently trying to us QtCreator to step into my dll, but obviously I can't because it isn't loading otherwise. My class definition is:

    
    class IMGLIBPLUGINSHARED_EXPORT ImgLibPlugin : public QImageIOPlugin
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID "imgLibPlugin" FILE "imglib.json")
    public:
        ImgLibPlugin() = default;
        ~ImgLibPlugin() = default;
    
        QStringList keys() const;
        Capabilities capabilities (QIODevice *device, const QByteArray &format) const;
        QImageIOHandler *create (QIODevice *device, const QByteArray &format = QByteArray()) const;
    };
    

    and the implementation is:

    #include "imglibplugin.h"
    #include <iostream>
    QStringList ImgLibPlugin::keys() const
    {
       QStringList supported;
        supported << "xyz24";
    
        std::cerr << "Keys checked \n";
        return supported;
    }
    
    QImageIOPlugin::Capabilities ImgLibPlugin::capabilities(QIODevice *device, const QByteArray &format) const
    {
        QImageIOPlugin::Capabilities cap;
        std::cerr << "Checking capabilities....\n";
        if(format.isEmpty() || !(device->isOpen()))
        {
            return cap;
        }
    
        if(format == "xyz24")
        {
            cap |= CanRead;
            return cap;
        }
        else
        {
            return cap;
        }
    
    
    }
    
    QImageIOHandler* ImgLibPlugin::create(QIODevice *device, const QByteArray &format) const
    {
        QImageIOHandler *handler = new ImgLibHandler();
        handler->setDevice(device);
        handler->setFormat(format);
        std::cerr << "Creating a handler!!!\n";
        return handler;
    }
    

    Can anyone give me some hints as to what piece I am missing?

    Much appreciated!


  • Moderators

    @tenspd137
    Just a note: you can use qDebug() in your plugin to print messages into the QtCreator console.

    Beside that i think it's not guaranteed that in your capabilities() method you always get a (valid) format passed. Thats why you receive also a QIODevice to peek into the binary and check for some headers for example.
    You are assuming that Qt magically already knows your custom format before it asks your plugin if it actually is capable of reading it.



  • Thanks for the suggestion. I changed the capabilities to:

    QImageIOPlugin::Capabilities ImgLibPlugin::capabilities(QIODevice *device, const QByteArray &format) const
    {
        QImageIOPlugin::Capabilities cap;
        qDebug() << "Checking capabilities....\n";
        if((device->isOpen()))
        {
            return cap;
        }
    
        char buf[2];
        device->peek(buf, 2);
    
        if(format == "xyz24" || (buf[0] == 'A' && buf[1]=='A'))
        {
            cap |= CanRead;
            return cap;
        }
        else
        {
            return cap;
        }
    
    
    }
    

    AA is my made up "magic" for this type, which is really just a P6 ppm. I am using a small test program:

    #include <QCoreApplication>
    #include <QImage>
    #include <QImageReader>
    #include <QString>
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        bool loaded = true;
        QString loadFn("test2.xyz24");
        QString saveFn("test.gif");
        //QImageReader reader(loadFn);
        //QImage img = reader.read();
        QImage img;
        loaded = img.load(loadFn,"xyz24");
        //return 0;
        return a.exec();
    }
    

    I am also setting the QT_DEBUG_PLUGINS to 1 in the debug environment. When I step over loaded=img.load(loadfn, "xyz24"), the output in the console is:

    ...all the other dlls....
    QFactoryLoader::QFactoryLoader() looking at "C:/Users/dayd/Documents/build-LibraryTest-Desktop64-Debug/debug/imageformats/ImgLibPlugin.dll"
    Found metadata in lib C:/Users/dayd/Documents/build-LibraryTest-Desktop64-Debug/debug/imageformats/ImgLibPlugin.dll, metadata=
    {
        "IID": "imgLibPlugin",
        "MetaData": {
            "Keys": [
                "xyz24"
            ],
            "MimeTypes": [
                "image/xyz24"
            ]
        },
        "className": "ImgLibPlugin",
        "debug": true,
        "version": 329985
    }
    
    
    Got keys from plugin meta data ()
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qgifd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qicnsd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qicod.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qjpegd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qsvgd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qtgad.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qtiffd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qwbmpd.dll"
    loaded library "C:/Qt/Qt5.9.1/5.9.1/msvc2017_64/plugins/imageformats/qwebpd.dll"
    

    loaded is false and it appears that it is not loading the plugin even though it finds it. Also, none of my qDebug statements are printed. I did check to make sure both the program and the dll are in debug mode.

    Any other suggestions?

    When I figure this out, I am going to make a how to. All the extra format plugins are complex with complex image file formats. AKAIK - there is no simple example as to how to actually do this and create a plugin using QImagIOPlugin.

    Thanks!



  • I have even tried loading it directly with the QPluginLoader - finds metadata, won't load.... :(


  • Lifetime Qt Champion

    Hi,

    It looks like you are missing a ! in your isOpen check.



  • Yes - i finally caught that and I am now able to get it to load. I can step into the plugin part. Now I am trying to step into the handler - right around:

    handler->setDevice(device);
    

    but the debugger steps over it. So that is the next thing I need to find out. I have qDebug statements in that function, but they don't print out. It is as if it is skipping over that call all together....



  • I changed the create function to:
    QImageIOHandler* ImgLibPlugin::create(QIODevice *device, const QByteArray &format) const
    {
    ImgLibHandler handler = new ImgLibHandler();
    handler->setDevice(device);
    handler->setFormat(format);
    return reinterpret_cast<QImageIOHandler
    >(handler);
    }
    Now it will let me step through the ImgLibHandler routines. This is good - I saw it fall apart in the handler, at least I can debug now.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.