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?
-
Hi,
Start your application with the QT_DEBUG_PLUGINS environment variable set to 1 to see what happens with your plugin.
-
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:
-
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.
-
@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.
-
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:
The build settings for debug:
I already removed the
release
flag fromCONFIG
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? -
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?
-
@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
-
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...