Custom image plugin testing difficulties
-
Well as I showed above, with the QT_DEBUG_PLUGINS variable set, the program is picking it up. However, it still refuses to load it. Is the IID or keys array invalid? I figured if it was choking on the plugin code itself, it would either error, segfault, or spit out a corrupt PNG.
-
Without seeing your code, it's pretty much Crystal Ball Debugging (™) I can't say
-
Well, I had posted my code in the original post. However, my handler class was tweaked a bit after spotting some errors, so here's the updated class code:
EDIT: I did a few tests on QImageReader that should fail with unsupported format error, but I keep getting "unknown error." I attempted to load my ".pro" qmake file to see which error it would get but still unknown error. However, I compiled qtraw from Github, dropped it into an imageformats subdirectory and it ran fine.
#include <QDataStream> #include <QImage> #include <QIODevice> #include <QtGlobal> #include <QtMath> #include <QVariant> #include <QVector> #include <QImageIOHandler> class TimHandler final: public QImageIOHandler { public: bool canRead() const; bool read(QImage *img); QVariant option(ImageOption op) const override; bool supportsOption(ImageOption op) const override; }; #define BIT16 0.121568627451 bool TimHandler::canRead() const { return device()->peek(4) == "\x10\x0\x0\x0"; } static inline quint32 rgba5551ToArgb32(quint16 c) { quint32 r = ((c & 0xf800) >> 11) / BIT16; quint32 g = ((c & 0x7c0) >> 6) / BIT16; quint32 b = ((c & 0x3e) >> 1) / BIT16; quint32 a = c & 1 ? 0 : 0xff; return ((a << 24) | (r << 16) | (g << 8) | b); } bool TimHandler::read(QImage *img) { QDataStream ds(device()); ds.setByteOrder(QDataStream::LittleEndian); quint32 magic, flags; ds >> magic >> flags; if (ds.status() != QDataStream::Ok || magic != 0x10) return false; bool hasClut = flags & 0x8 ? true : false; quint8 pxlMode = flags & 0x7; quint8 bpp; switch (pxlMode) { case 0: bpp = 4; break; case 1: bpp = 8; break; case 2: bpp = 16; break; case 3: bpp = 24; break; default: bpp = 4; } QVector<QRgb> clut; if (hasClut) { quint32 colors, npals; ds.skipRawData(12); ds >> colors >> npals; for (quint16 i = 0; i < (colors*npals); i++) { quint16 c; ds >> c; clut.append(rgba5551ToArgb32(c)); } } ds.skipRawData(8); quint16 w, h; ds >> w >> h; w = (w*16)/bpp; if (img) delete img; img = new QImage(w, h, QImage::Format_ARGB32); if (hasClut) img->setColorTable(clut); for (quint16 y = 0; y < h; y++) { for (quint16 x = 0; x < w; x++) { switch (bpp) { case 4: { quint8 p; ds >> p; img->setPixel(x++, y, p & 0xf0); img->setPixel(x, y, p & 0xf); } break; case 8: { quint8 p; ds >> p; img->setPixel(x, y, p); } break; case 16: { quint16 p; ds >> p; img->setPixel(x, y, rgba5551ToArgb32(p)); } break; } } } return true; } bool TimHandler::supportsOption(ImageOption op) const { switch (op) { case Size: return true; default: return false; } } QVariant TimHandler::option(ImageOption op) const { switch (op) { case Size: { quint32 size; quint16 w, h; QDataStream ds(device()); ds.skipRawData(8); ds >> size; size -= 4; // 12 - image size - palette x - palette y ds.skipRawData(size); ds >> w >> h; return QSize(w, h); } default: return QVariant(); } }
-
Sorry about the code part, I had a problem when I read it first and only saw the end of it.
What about a more simple json ?{ "Keys": [ "tim" ], "MimeTypes": [ "image/x-tim" ] }
-
Well, while I could try that, I don't know if that's the mime type for TIM files. A Google search doesn't help either. My examination of qtraw shows that it too lacks a mime type entry. Thus, I thought it was unnecessary.
EDIT: tried it anyway, still nothing
-
Just thought of something… Your plugin code is correct but:
img.load("0025.tim", "tim");
"0025.tim" is a relative path, is that image in the same folder as your executable ? You should rather give the full path to it.
-
Same directory, yep. Though of course in a real world scenario this would be different.
-
I forgot a correction I made:
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "tim.json")
-
Yeah, I changed it to that in my progress trying to fix it, but no go. I booted up QtCreator and created a new project from Qt plugin template but I see nothing unusual in comparison with my code, aside from the constructor with QObject* parameter, which I skipped in my code because I saw no point for an empty constructor/destructor.
-
So after a little tinkering, I got qmake to generate main.moc which I thought was needed, but I'm still having issues with the plugin not being discovered. Additionally, the RGBA5551 conversion function was incorrect, which I fixed, but that shouldn't be the make-or-break factor.
-
Not being discovered or not loaded ? Did you put your plugin in a imageformats subfolder ?
-
Yep. Even set target.path in my .pro file thinking that was the issue. Qt seems very nitpicky.
EDIT: Just debugged again, found this gem of an error:
QLibraryPrivate::loadPlugin failed on "/home/admin/Documents/Qt-extra/imageformats/qtim/timtest/imageformats/libqtim.so" : "Cannot load library /home/admin/Documents/Qt-extra/imageformats/qtim/timtest/imageformats/libqtim.so: (/home/admin/Documents/Qt-extra/imageformats/qtim/timtest/imageformats/libqtim.so: undefined symbol: _ZN11QTimHandler9setOptionEN15QImageIOHandler11ImageOptionERK8QVariant)"
-
Which version of Qt are you using ?
What happens if you try to load it by hand using QLibrary ?