diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -55,6 +55,7 @@ # Loads each image in read//, and compares the # result against the data read from the corresponding png file kimageformats_read_tests( + hdr pcx psd ras diff --git a/autotests/read/hdr/rgb.hdr b/autotests/read/hdr/rgb.hdr new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ -typedef Q_UINT8 uchar; +typedef unsigned char uchar; namespace // Private. { @@ -93,19 +93,22 @@ uchar val, code; // Create dst image. - if (!img.create(width, height, 32)) { + img = QImage(width, height, QImage::Format_RGB32); + if (img.isNull()) { return false; } - QMemArray image(width * 4); + QByteArray lineArray; + lineArray.resize(4 * width); + uchar *image = (uchar *) lineArray.data(); for (int cline = 0; cline < height; cline++) { QRgb *scanline = (QRgb *) img.scanLine(cline); // determine scanline type if ((width < MINELEN) || (MAXELEN < width)) { - Read_Old_Line(image.data(), width, s); - RGBE_To_QRgbLine(image.data(), scanline, width); + Read_Old_Line(image, width, s); + RGBE_To_QRgbLine(image, scanline, width); continue; } @@ -116,9 +119,9 @@ } if (val != 2) { - s.device()->at(s.device()->at() - 1); - Read_Old_Line(image.data(), width, s); - RGBE_To_QRgbLine(image.data(), scanline, width); + s.device()->ungetChar(val); + Read_Old_Line(image, width, s); + RGBE_To_QRgbLine(image, scanline, width); continue; } @@ -132,8 +135,8 @@ if ((image[1] != 2) || (image[2] & 128)) { image[0] = 2; - Read_Old_Line(image.data() + 4, width - 1, s); - RGBE_To_QRgbLine(image.data(), scanline, width); + Read_Old_Line(image + 4, width - 1, s); + RGBE_To_QRgbLine(image, scanline, width); continue; } @@ -168,24 +171,24 @@ } } - RGBE_To_QRgbLine(image.data(), scanline, width); + RGBE_To_QRgbLine(image, scanline, width); } return true; } } // namespace -Q_DECL_EXPORT void kimgio_hdr_read(QImageIO *io) +bool HDRHandler::read(QImage *outImage) { int len; char line[MAXLINE]; //bool validHeader = false; bool validFormat = false; // Parse header do { - len = io->ioDevice()->readLine(line, MAXLINE); + len = device()->readLine(line, MAXLINE); /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0) { @@ -199,40 +202,78 @@ if (/*!validHeader ||*/ !validFormat) { // qDebug() << "Unknown HDR format."; - io->setImage(0); - io->setStatus(-1); - return; + return false; } - io->ioDevice()->readLine(line, MAXLINE); + device()->readLine(line, MAXLINE); char s1[3], s2[3]; int width, height; if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4) //if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 ) { // qDebug() << "Invalid HDR file."; - io->setImage(0); - io->setStatus(-1); - return; + return false; } - QDataStream s(io->ioDevice()); + QDataStream s(device()); QImage img; if (!LoadHDR(s, width, height, img)) { // qDebug() << "Error loading HDR file."; - io->setImage(0); - io->setStatus(-1); - return; + return false; + } + + *outImage = img; + return true; +} + +HDRHandler::HDRHandler() +{ +} + +bool HDRHandler::canRead() const +{ + if (canRead(device())) { + setFormat("hdr"); + return true; + } + return false; +} + +bool HDRHandler::canRead(QIODevice *device) +{ + if (!device) { + qWarning("HDRHandler::canRead() called with no device"); + return false; } - io->setImage(img); - io->setStatus(0); + return device->peek(11) == "#?RADIANCE\n" || device->peek(7) == "#?RGBE\n"; } -Q_DECL_EXPORT void kimgio_hdr_write(QImageIO *) +QImageIOPlugin::Capabilities HDRPlugin::capabilities(QIODevice *device, const QByteArray &format) const { - // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.) + if (format == "hdr") { + return Capabilities(CanRead); + } + if (!format.isEmpty()) { + return {}; + } + if (!device->isOpen()) { + return {}; + } + + Capabilities cap; + if (device->isReadable() && HDRHandler::canRead(device)) { + cap |= CanRead; + } + return cap; } +QImageIOHandler *HDRPlugin::create(QIODevice *device, const QByteArray &format) const +{ + QImageIOHandler *handler = new HDRHandler; + handler->setDevice(device); + handler->setFormat(format); + return handler; +} diff --git a/src/imageformats/hdr.json b/src/imageformats/hdr.json new file mode 100644 --- /dev/null +++ b/src/imageformats/hdr.json @@ -0,0 +1,4 @@ +{ + "Keys": [ "hdr" ], + "MimeTypes": [ "image/x-hdr", "image/vnd.radiance" ] +} diff --git a/src/imageformats/hdr_p.h b/src/imageformats/hdr_p.h --- a/src/imageformats/hdr_p.h +++ b/src/imageformats/hdr_p.h @@ -10,12 +10,27 @@ #ifndef KIMG_HDR_P_H #define KIMG_HDR_P_H -class QImageIO; +#include -extern "C" { - void kimgio_hdr_read(QImageIO *); - void kimgio_hdr_write(QImageIO *); -} +class HDRHandler : public QImageIOHandler +{ +public: + HDRHandler(); -#endif + bool canRead() const override; + bool read(QImage *outImage) override; + static bool canRead(QIODevice *device); +}; + +class HDRPlugin : public QImageIOPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "hdr.json") + +public: + Capabilities capabilities(QIODevice *device, const QByteArray &format) const override; + QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; +}; + +#endif // KIMG_HDR_P_H