From 10:00 CET Friday 22nd November we will adjust how the server works to deal with some recently reported problems. Therefore there may be a load problem, if you experience more problems than usual trying to access the forum then please PM AndyS or any of the moderators so they can inform me.


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