Planned maintenance has been done but it did not solve the problem. So work will continue on this and a new time for trying updates will be announced asap.

QImageIOPlugin doesn't work



  • I tryed to write a plugin which introduces a new file format .ti which enables reading and writing files in ascii art.

    When I try out the plugin in it doesn't seem to work.

    My plugin files look like this:

    TEMPLATE = lib
    TARGET = textimage
    CONFIG += plugin release
    VERSION = 1.0.0
    
    HEADERS += \
        textimagehandler.h \
        textimageplugin.h
    
    SOURCES += \
        textimagehandler.cpp \
        textimageplugin.cpp
    
    target.path += $$[QT_INSTALL_PLUGINS]/imageformats
    INSTALLS += target
    
    DISTFILES += \
        textimageplugin.json
    
    #ifndef TEXTIMAGEHANDLER_H
    #define TEXTIMAGEHANDLER_H
    
    #include <QImageIOHandler>
    
    class TextImageHandler : public QImageIOHandler
    {
    public:
        bool read(QImage *image) override;
        bool write(const QImage &image) override;
    
        bool canRead() const override;
        static bool canRead(QIODevice *device);
    };
    
    #endif // TEXTIMAGEHANDLER_H
    
    #ifndef TEXTIMAGEPLUGIN_H
    #define TEXTIMAGEPLUGIN_H
    
    #include <QImageIOPlugin>
    
    class TextImagePlugin : public QImageIOPlugin
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(
            IID "org.qt-project.Qt.QImageIOFactoryInterface" FILE "textimageplugin.json")
    public:
        QStringList keys() const;
    
        Capabilities capabilities(
            QIODevice *device, const QByteArray &format) const override;
        QImageIOHandler *create(
            QIODevice *device,
            const QByteArray &format = QByteArray{}) const override;
    };
    
    #endif // TEXTIMAGEPLUGIN_H
    
    #include "textimagehandler.h"
    
    #include <QTextStream>
    #include <QRegExp>
    #include <QImage>
    
    const char map[] =  " .:ilNAM";
    
    bool TextImageHandler::read(QImage *image)
    {
        QTextStream stream{device()};
        QString line = stream.readLine();
    
        if(line !=  "TEXT" || stream.status() != QTextStream::Ok) {
            return false;
        }
    
        line = stream.readLine();
    
         QRegExp re( R"(\d+)x(\d+)" );
         int width;
         int height;
         if(re.exactMatch(line)) {
    
             bool ok;
    
             width = re.cap(1).toInt(&ok);
             if(!ok) {
                 return false;
             }
    
             height = re.cap(2).toInt(&ok);
             if(!ok) {
                 return false;
             }
         }
         else{
             return false;
         }
    
    
         QImage result{width, height, QImage::Format_ARGB32};
         for( int y=0; y<height; ++y )
         {
             line = stream.readLine();
             if( line.length() != width )
                 return false;
    
             for( int x=0; x<width; ++x )
             {
                 switch( QString(map).indexOf(line[x]) )
                 {
                 case 0:
                     result.setPixel( x, y, 0xffffffff );
                     break;
                 case 1:
                     result.setPixel( x, y, 0xffdfdfdf );
                     break;
                 case 2:
                     result.setPixel( x, y, 0xffbfbfbf );
                     break;
                 case 3:
                     result.setPixel( x, y, 0xff9f9f9f );
                     break;
                 case 4:
                     result.setPixel( x, y, 0xff7f7f7f );
                     break;
                 case 5:
                     result.setPixel( x, y, 0xff5f5f5f );
                     break;
                 case 6:
                     result.setPixel( x, y, 0xff3f3f3f );
                     break;
                 case 7:
                     result.setPixel( x, y, 0xff000000 );
                     break;
                 default:
                     return false;
                 }
             }
         }
    
         if(stream.status() != QTextStream::Ok) {
             return false;
         }
         *image  = result;
         return true;
    }
    
    bool TextImageHandler::write(const QImage &image)
    {
        QTextStream stream{device()};
    
        stream << "TEXT\n";
        stream << image.width() << "x" << image.height() << "\n";
    
        for( int y=0; y<image.height(); ++y )
        {
            for( int x=0; x<image.width(); ++x )
            {
                QRgb rgb = image.pixel( x, y );
                int r = rgb & 0xff;
                int g = (rgb >> 8) & 0xff;
                int b = (rgb >> 16) & 0xff;
    
                stream << map[ 7 - (((r+g+b)/3)>>5) & 0x7 ];
            }
            stream << "\n";
        }
    
        if( stream.status() != QTextStream::Ok ) {
            return false;
        }
        return true;
    }
    
    bool TextImageHandler::canRead() const
    {
          return canRead( device() );
    }
    
    bool TextImageHandler::canRead(QIODevice *device)
    {
        if( device->peek(4) == "TEXT" ) {
            return true;
        }
    
        return false;
    }
    
    #include "textimageplugin.h"
    
    #include "textimagehandler.h"
    
    QStringList TextImagePlugin::keys() const
    {
        return QStringList{"ti"};
    }
    
    QImageIOPlugin::Capabilities TextImagePlugin::capabilities(
        QIODevice *device, const QByteArray &format) const
    {
        if(format == "ti") {
            return (QImageIOPlugin::CanRead | QImageIOPlugin::CanWrite);
        }
    
        if(!format.isEmpty()) {
            return nullptr;
        }
    
        if(!device->isOpen()) {
            return  nullptr;
        }
    
        QImageIOPlugin::Capabilities result;
    
        if(device->isReadable() && TextImageHandler::canRead(device)) {
            result |= QImageIOPlugin::CanRead;
        }
    
        if(device->isWritable()) {
            result |= QImageIOPlugin::CanWrite;
        }
        return result;
    }
    
    QImageIOHandler *TextImagePlugin::create(
        QIODevice *device, const QByteArray &format) const
    {
        auto result = new TextImageHandler{};
    
        result->setDevice(device);
        result->setFormat(format);
        return result;
    }
    
    {
      "Keys": [ "ti" ],
      "MimeTypes": [ "image/ti", "image/ti" ]
    }
    

    I generate a plugin file with adding install to make. It looks like this:

    Bibliothek "release\textimage1.lib" und Objekt "release\textimage1.exp" werden erstellt.
     copy /y release\textimage1.dll E:\Qt\5.12.2\msvc2017\plugins\imageformats\textimage1.dll
         1 Datei(en) kopiert.
    18:55:39: The process "E:\Qt\Tools\QtCreator\bin\jom.exe" exited normally.
    18:55:39: Elapsed time: 00:02.
    

    When i try to run a small sample programm the new ti format does not show up:

    #include <QApplication>
    
    #include <QImage>
    #include <QImageReader>
    #include <QByteArray>
    
    #include <QtDebug>
    
    int main( int argc, char **argv )
    { 
        QApplication app( argc, argv );
    
        for(const auto& supported : QImageReader::supportedImageFormats ()) {
            qDebug() << supported;
        }
    }
    
    18:51:03: Starting E:\Cpp_Projekte\QT\Foundations_of_QT\CH11_image_plugin\read\build-read-Desktop_Qt_5_12_2_MSVC2017_32bit-Debug\debug\read.exe ...
    "bmp"
    "cur"
    "gif"
    "icns"
    "ico"
    "jpeg"
    "jpg"
    "pbm"
    "pgm"
    "png"
    "ppm"
    "svg"
    "svgz"
    "tga"
    "tif"
    "tiff"
    "wbmp"
    "webp"
    "xbm"
    "xpm"
    18:51:04: E:/Cpp_Projekte/QT/Foundations_of_QT/CH11_image_plugin/read/build-read-Desktop_Qt_5_12_2_MSVC2017_32bit-Debug/debug/read.exe exited with code 0
    

    What can be wrong. I assumed generating the file under "Qt\5.12.2\msvc2017\plugins\imageformats" is correct?


  • Lifetime Qt Champion

    Hi,

    Start your application with the QT_DEBUG_PLUGINS environment variable set to 1 to see what happens with your plugin.


  • Qt Champions 2018

    Apart from @SGaist 's answer - you can't mix debug and release plugins on windows. So either compile your testapp in release mode or your plugin as debug.



  • I compiled both now as debug and enabled QT_DEBUG_PLUGINS. It gives me this output:

    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/styles/qwindowsvistastyled.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qgifd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicnsd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicod.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qjpegd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qsvgd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtgad.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtiffd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwbmpd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwebpd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/platforms/qwindowsd.dll" 
    

    It looks like my dll doesn't even get loaded but why is that so?

    The folder contains the file textimage1.dll which is supposed to be the plugin:

    0_1561233369247_ba7c8c52-5122-4725-9510-7c56d588b661-image.png


  • Qt Champions 2018

    There must be also an output during startup - you only pasted the stuff during shutdown...



  • I get this error on startup:

    
    "The plugin 'E:/Qt/5.12.2/msvc2017/plugins/imageformats/textimage1.dll' uses incompatible Qt library. (Cannot mix debug and release libraries.)" 
             not a plugin
    QFactoryLoader::QFactoryLoader() checking directory path "E:/Cpp_Projekte/QT/Foundations_of_QT/CH11_image_plugin/read/build-read-Desktop_Qt_5_12_2_MSVC2017_32bit-Debug/debug/imageformats" ...
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qgifd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicnsd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicod.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qjpegd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qsvgd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtgad.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtiffd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwbmpd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwebpd.dll"
    

    I build the plugin and the project with MSVC2017 32 Bit Debug to get the Debug Output. There should not be a mix?

    The output of the plugin file looks like this:

    22:57:44: Running steps for project image_plugin...
    22:57:44: Configuration unchanged, skipping qmake step.
    22:57:44: Starting: "E:\Qt\Tools\QtCreator\bin\jom.exe" install
    	E:\Qt\Tools\QtCreator\bin\jom.exe -f Makefile.Release install
    	copy /y release\textimage1.dll E:\Qt\5.12.2\msvc2017\plugins\imageformats\textimage1.dll
            1 Datei(en) kopiert.
    22:57:44: The process "E:\Qt\Tools\QtCreator\bin\jom.exe" exited normally.
    22:57:44: Elapsed time: 00:00.
    

  • Qt Champions 2018

    @sandro4912 said in QImageIOPlugin doesn't work:

    copy /y release\textimage1.dll E:\Qt\5.12.2\msvc2017\plugins\imageformats\textimage1.dll

    This does not look like a debug build.


  • Lifetime Qt Champion

    Your plugin is named: textimage1.dll It is missing the d suffix for your debug build.

    You can use TARGET = $$qtLibraryTarget(textimage)



  • Than i wonder why it is not build as debug.

    I clearly select debug and then build:

    0_1561275497852_958750a2-35c8-4131-bb00-c2b24a1eb0fb-image.png

    The build settings for debug:

    0_1561275704127_5d06df1a-fa93-4f74-b158-600fdf3aff97-image.png

    I already removed the release flag from CONFIG so it should not get forced into release or should it?

    TEMPLATE = lib
    CONFIG += plugin
    TARGET = $$qtLibraryTarget(textimage)
    VERSION = 1.0.0
    
    HEADERS += \
        textimagehandler.h \
        textimageplugin.h
    
    SOURCES += \
        textimagehandler.cpp \
        textimageplugin.cpp
    
    target.path += $$[QT_INSTALL_PLUGINS]/imageformats
    INSTALLS += target
    
    DISTFILES += \
        textimageplugin.json
    

    What does TARGET = $$qtLibraryTarget(textimage) do? why is it needed?


  • Qt Champions 2018

    @sandro4912

    Your plugin is named: textimage1.dll It is missing the d suffix for your debug build.

    On Windows, the library must be called textimage1d.dll if it is a debug version. The reason was already explained above: On Windows, you cannot mix debug and release objects.



  • Ok but were do i change the name with the d suffix? In the pro file? Or can i just rename it manually?


  • Qt Champions 2018

    @sandro4912 said in QImageIOPlugin doesn't work:

    Ok but were do i change the name with the d suffix? In the pro file? Or can i just rename it manually?

    Simply read @SGaist 's answer: 'You can use TARGET = $$qtLibraryTarget(textimage)'



  • I added the target but it doesn't seem to add the d suffix to make it debug:

    TEMPLATE = lib
    CONFIG += plugin
    VERSION = 1.0.0
    
    HEADERS += \
        textimagehandler.h \
        textimageplugin.h
    
    SOURCES += \
        textimagehandler.cpp \
        textimageplugin.cpp
    
    TARGET = $$qtLibraryTarget(textimage)
    target.path += $$[QT_INSTALL_PLUGINS]/imageformats
    INSTALLS += target
    
    DISTFILES += \
        textimageplugin.json
    

  • Lifetime Qt Champion

    Did you re-run qmake after changing the TARGET value ?



  • Ok i guess i forgot to rerun it. Now i could generate the debug files.

    When running my testprogram with debug it stills fails but the message is different

    Got keys from plugin meta data ()
    QFactoryLoader::QFactoryLoader() checking directory path "E:/Cpp_Projekte/QT/Foundations_of_QT/CH11_image_plugin/read/build-read-Desktop_Qt_5_12_2_MSVC2017_32bit-Debug/debug/imageformats" ...
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qgifd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicnsd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicod.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qjpegd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qsvgd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtgad.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtiffd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwbmpd.dll"
    loaded library "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwebpd.dll"
    "bmp"
    "cur"
    "gif"
    "icns"
    "ico"
    "jpeg"
    "jpg"
    "pbm"
    "pgm"
    "png"
    "ppm"
    "svg"
    "svgz"
    "tga"
    "tif"
    "tiff"
    "wbmp"
    "webp"
    "xbm"
    "xpm"
    Failed to load.
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/styles/qwindowsvistastyled.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qgifd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicnsd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qicod.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qjpegd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qsvgd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtgad.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qtiffd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwbmpd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/imageformats/qwebpd.dll" 
    QLibraryPrivate::unload succeeded on "E:/Qt/5.12.2/msvc2017/plugins/platforms/qwindowsd.dll"
    

    let me know if you need more information...


Log in to reply