diff options
author | aavit <qt_aavit@ovi.com> | 2012-02-22 13:48:48 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-01 12:57:36 +0100 |
commit | aa48df6f9b4a431b3a802ac1a2a15db1ed5dc696 (patch) | |
tree | df899a4baaabf845ea94a6da88371456c32e9e90 | |
parent | 94aed3b5808f5095ee3040e928551035a21f0a6d (diff) |
Add wbmp plugin
This is a port to Qt 5/qtimageformats of the contribution
https://qt.gitorious.org/qt/qt/merge_requests/1117
by
Dmitry Zelenkovskiy <Dmitry.Zelenkovskiy@nokia.com>
Change-Id: I9cdd249d3c58c5f922ccd2d43f92f1bd2e3fd86f
Reviewed-by: Jason Barron <jason.barron@nokia.com>
Reviewed-by: aavit <qt_aavit@ovi.com>
-rw-r--r-- | src/plugins/imageformats/imageformats.pro | 3 | ||||
-rw-r--r-- | src/plugins/imageformats/wbmp/main.cpp | 103 | ||||
-rw-r--r-- | src/plugins/imageformats/wbmp/qwbmphandler.cpp | 361 | ||||
-rw-r--r-- | src/plugins/imageformats/wbmp/qwbmphandler_p.h | 83 | ||||
-rw-r--r-- | src/plugins/imageformats/wbmp/wbmp.json | 3 | ||||
-rw-r--r-- | src/plugins/imageformats/wbmp/wbmp.pro | 12 | ||||
-rw-r--r-- | tests/auto/auto.pro | 3 | ||||
-rw-r--r-- | tests/auto/wbmp/tst_qwbmp.cpp | 78 | ||||
-rw-r--r-- | tests/auto/wbmp/wbmp.pro | 11 | ||||
-rw-r--r-- | tests/shared/images/wbmp.qrc | 6 | ||||
-rw-r--r-- | tests/shared/images/wbmp/qt-logo-big.wbmp | bin | 0 -> 8006 bytes | |||
-rw-r--r-- | tests/shared/images/wbmp/qt-logo-small.wbmp | bin | 0 -> 1652 bytes |
12 files changed, 661 insertions, 2 deletions
diff --git a/src/plugins/imageformats/imageformats.pro b/src/plugins/imageformats/imageformats.pro index 70ee4ae..5bde0c7 100644 --- a/src/plugins/imageformats/imageformats.pro +++ b/src/plugins/imageformats/imageformats.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ - tga + tga \ + wbmp contains(QT_CONFIG, system-zlib): SUBDIRS += mng tiff diff --git a/src/plugins/imageformats/wbmp/main.cpp b/src/plugins/imageformats/wbmp/main.cpp new file mode 100644 index 0000000..1d5e1e3 --- /dev/null +++ b/src/plugins/imageformats/wbmp/main.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the WBMP plugin in the Qt ImageFormats module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qimageiohandler.h> + +#ifndef QT_NO_IMAGEFORMATPLUGIN + +#ifdef QT_NO_IMAGEFORMAT_WBMP +#undef QT_NO_IMAGEFORMAT_WBMP +#endif + +#include "qwbmphandler_p.h" + +QT_BEGIN_NAMESPACE + +class QWbmpPlugin : public QImageIOPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "wbmp.json") + +public: + QStringList keys() const; + QImageIOPlugin::Capabilities capabilities(QIODevice *device, const QByteArray &format) const; + QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const; +}; + +QImageIOPlugin::Capabilities QWbmpPlugin::capabilities(QIODevice *device, const QByteArray &format) const +{ + if (format == "wbmp") + return Capabilities(CanRead | CanWrite); + + if (!format.isEmpty()) + return 0; + + if (!device->isOpen()) + return 0; + + Capabilities cap; + if (device->isReadable() && QWbmpHandler::canRead(device)) + cap |= CanRead; + + if (device->isWritable()) + cap |= CanWrite; + + return cap; +} + +QImageIOHandler * QWbmpPlugin::create(QIODevice *device, const QByteArray &format) const +{ + QImageIOHandler *handler = new QWbmpHandler(device); + + handler->setFormat(format); + return handler; +} + +QStringList QWbmpPlugin::keys() const +{ + return QStringList() << QLatin1String("wbmp"); +} + +QT_END_NAMESPACE + +#include "main.moc" + +#endif /* QT_NO_IMAGEFORMATPLUGIN */ diff --git a/src/plugins/imageformats/wbmp/qwbmphandler.cpp b/src/plugins/imageformats/wbmp/qwbmphandler.cpp new file mode 100644 index 0000000..f3896b6 --- /dev/null +++ b/src/plugins/imageformats/wbmp/qwbmphandler.cpp @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the WBMP plugin in the Qt ImageFormats module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwbmphandler_p.h" + +/*! + \class QWbmpHandler + \since 5.0 + \brief The QWbmpHandler class provides support for the WBMP image format. + \internal +*/ + +#include <qimage.h> +#include <qvariant.h> + +QT_BEGIN_NAMESPACE + +// This struct represents header of WBMP image file +struct WBMPHeader +{ + quint8 type; // Type of WBMP image (always equal to 0) + quint8 format; // Format of WBMP image + quint32 width; // Width of the image already decoded from multibyte integer + quint32 height; // Height of the image already decoded from multibyte integer +}; +#define WBMPFIXEDHEADER_SIZE 2 + +// Data renderers and writers which takes care of data alignment endiness and stuff +static bool readMultiByteInt(QIODevice *iodev, quint32 *num) +{ + quint32 res = 0; + + quint8 c; + unsigned int count = 0; + do { + // Do not allow to read longer + // then we can store in num + if (++count > sizeof(*num)) + return false; + + if (!iodev->getChar(reinterpret_cast<char *>(&c))) + return false; + + res = (res << 7) | (c & 0x7F); + + } while (c & 0x80); + + *num = res; + return true; +} + +static bool writeMultiByteInt(QIODevice *iodev, quint32 num) +{ + quint64 tmp = num & 0x7F; + num >>= 7; + + while (num) { + quint8 c = num & 0x7F; + num = num >> 7; + tmp = (tmp << 8) | (c | 0x80); + } + + while (tmp) { + quint8 c = tmp & 0xFF; + if (!iodev->putChar(c)) + return false; + tmp >>= 8; + } + return true; +} + +static bool readWBMPHeader(QIODevice *iodev, WBMPHeader *hdr) +{ + if (!iodev) + return false; + + uchar tmp[WBMPFIXEDHEADER_SIZE]; + if (iodev->read(reinterpret_cast<char *>(tmp), WBMPFIXEDHEADER_SIZE) == WBMPFIXEDHEADER_SIZE) { + hdr->type = tmp[0]; + hdr->format = tmp[1]; + } else { + return false; + } + + if (readMultiByteInt(iodev, &hdr->width) + && readMultiByteInt(iodev, &hdr->height)) { + return true; + } + return false; +} + +static bool writeWBMPHeader(QIODevice *iodev, const WBMPHeader &hdr) +{ + if (iodev) { + uchar tmp[WBMPFIXEDHEADER_SIZE]; + tmp[0] = hdr.type; + tmp[1] = hdr.format; + if (iodev->write(reinterpret_cast<char *>(tmp), WBMPFIXEDHEADER_SIZE) != WBMPFIXEDHEADER_SIZE) + return false; + + if (writeMultiByteInt(iodev, hdr.width) && + writeMultiByteInt(iodev, hdr.height)) + return true; + } + return false; +} + +static bool writeWBMPData(QIODevice *iodev, const QImage &image) +{ + if (iodev) { + int h = image.height(); + int bpl = (image.width() + 7) / 8; + + for (int l=0; l<h; l++) { + if (iodev->write(reinterpret_cast<const char *>(image.constScanLine(l)), bpl) != bpl) + return false; + } + return true; + } + return false; +} + +static bool readWBMPData(QIODevice *iodev, QImage &image) +{ + if (iodev) { + int h = image.height(); + int bpl = (image.width() + 7) / 8; + + for (int l = 0; l < h; l++) { + if (iodev->read(reinterpret_cast<char *>(image.scanLine(l)), bpl) != bpl) + return false; + } + return true; + } + return false; +} + +class WBMPReader +{ +public: + WBMPReader(QIODevice *iodevice); + + QImage readImage(); + bool writeImage(QImage image); + + static bool canRead(QIODevice *iodevice); + +private: + QIODevice *iodev; + WBMPHeader hdr; +}; + +// WBMP common reader and writer implementation +WBMPReader::WBMPReader(QIODevice *iodevice) : iodev(iodevice) +{ + memset(&hdr, 0, sizeof(hdr)); +} + +QImage WBMPReader::readImage() +{ + if (!readWBMPHeader(iodev, &hdr)) + return QImage(); + + QImage image(hdr.width, hdr.height, QImage::Format_Mono); + if (!readWBMPData(iodev, image)) + return QImage(); + + return image; +} + +bool WBMPReader::writeImage(QImage image) +{ + if (image.format() != QImage::Format_Mono) + image = image.convertToFormat(QImage::Format_Mono); + + if (image.colorTable().at(0) == image.colorTable().at(1)) { + // degenerate image: actually blank. + image.fill((qGray(image.colorTable().at(0)) < 128) ? 0 : 1); + } else if (qGray(image.colorTable().at(0)) > qGray(image.colorTable().at(1))) { + // Conform to WBMP's convention about black and white + image.invertPixels(); + } + + hdr.type = 0; + hdr.format = 0; + hdr.width = image.width(); + hdr.height = image.height(); + + if (!writeWBMPHeader(iodev, hdr)) + return false; + + if (!writeWBMPData(iodev, image)) + return false; + + return true; +} + +bool WBMPReader::canRead(QIODevice *device) +{ + if (device) { + + if (device->isSequential()) + return false; + + // Save previous position + qint64 oldPos = device->pos(); + + WBMPHeader hdr; + if (readWBMPHeader(device, &hdr)) { + if ((hdr.type == 0) && (hdr.format == 0)) { + qint64 imageSize = hdr.height * ((hdr.width + 7) / 8); + qint64 available = device->bytesAvailable(); + device->seek(oldPos); + return (imageSize == available); + } + } + device->seek(oldPos); + } + return false; +} + +/*! + Constructs an instance of QWbmpHandler initialized to use \a device. +*/ +QWbmpHandler::QWbmpHandler(QIODevice *device) : + m_reader(new WBMPReader(device)) +{ +} + +/*! + Destructor for QWbmpHandler. +*/ +QWbmpHandler::~QWbmpHandler() +{ + delete m_reader; +} + +/*! + * Verifies if some values (magic bytes) are set as expected in the header of the file. + * If the magic bytes were found, it is assumed that the QWbmpHandler can read the file. + */ +bool QWbmpHandler::canRead() const +{ + bool bCanRead = false; + + QIODevice *device = QImageIOHandler::device(); + if (device) { + bCanRead = QWbmpHandler::canRead(device); + if (bCanRead) + setFormat("wbmp"); + + } else { + qWarning("QWbmpHandler::canRead() called with no device"); + } + + return bCanRead; +} + +/*! \reimp +*/ +bool QWbmpHandler::read(QImage *image) +{ + bool bSuccess = false; + QImage img = m_reader->readImage(); + + if (!img.isNull()) { + bSuccess = true; + *image = img; + } + + return bSuccess; +} + +/*! \reimp +*/ +bool QWbmpHandler::write(const QImage &image) +{ + if (image.isNull()) + return false; + + return m_reader->writeImage(image); +} + +/*! + Only Size option is supported +*/ +QVariant QWbmpHandler::option(ImageOption option) const +{ + if (option == QImageIOHandler::Size) { + QIODevice *device = QImageIOHandler::device(); + if (device->isSequential()) + return QVariant(); + + // Save old position + qint64 oldPos = device->pos(); + + WBMPHeader hdr; + if (readWBMPHeader(device, &hdr)) { + device->seek(oldPos); + return QSize(hdr.width, hdr.height); + } + + device->seek(oldPos); + + } else if (option == QImageIOHandler::ImageFormat) { + return QVariant(QImage::Format_Mono); + } + + return QVariant(); +} + +bool QWbmpHandler::supportsOption(ImageOption option) const +{ + return (option == QImageIOHandler::Size) || + (option == QImageIOHandler::ImageFormat); +} + +bool QWbmpHandler::canRead(QIODevice *device) +{ + return WBMPReader::canRead(device); +} + +QT_END_NAMESPACE diff --git a/src/plugins/imageformats/wbmp/qwbmphandler_p.h b/src/plugins/imageformats/wbmp/qwbmphandler_p.h new file mode 100644 index 0000000..7b2f99b --- /dev/null +++ b/src/plugins/imageformats/wbmp/qwbmphandler_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the WBMP plugin in the Qt ImageFormats module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QWBMPHANDLER_P_H +#define QWBMPHANDLER_P_H + +#include <qimageiohandler.h> + +QT_BEGIN_NAMESPACE + +class WBMPReader; + +class QWbmpHandler : public QImageIOHandler +{ +public: + QWbmpHandler(QIODevice *device); + virtual ~QWbmpHandler(); + + bool canRead() const; + bool read(QImage *image); + bool write(const QImage &image); + + QVariant option(ImageOption option) const; + bool supportsOption(ImageOption option) const; + + static bool canRead(QIODevice *device); + +private: + WBMPReader *m_reader; +}; + +QT_END_NAMESPACE + +#endif /* QWBMPHANDLER_P_H */ diff --git a/src/plugins/imageformats/wbmp/wbmp.json b/src/plugins/imageformats/wbmp/wbmp.json new file mode 100644 index 0000000..aad31e8 --- /dev/null +++ b/src/plugins/imageformats/wbmp/wbmp.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "wbmp" ] +} diff --git a/src/plugins/imageformats/wbmp/wbmp.pro b/src/plugins/imageformats/wbmp/wbmp.pro new file mode 100644 index 0000000..9fe3040 --- /dev/null +++ b/src/plugins/imageformats/wbmp/wbmp.pro @@ -0,0 +1,12 @@ +TARGET = qwbmp +load(qt_plugin) + +HEADERS += qwbmphandler.h +SOURCES += qwbmphandler.cpp +OTHER_FILES += wbmp.json + +SOURCES += main.cpp + +DESTDIR = $$QT.gui.plugins/imageformats +target.path += $$[QT_INSTALL_PLUGINS]/imageformats +INSTALLS += target diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 70ee4ae..5bde0c7 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ - tga + tga \ + wbmp contains(QT_CONFIG, system-zlib): SUBDIRS += mng tiff diff --git a/tests/auto/wbmp/tst_qwbmp.cpp b/tests/auto/wbmp/tst_qwbmp.cpp new file mode 100644 index 0000000..c5ae7ed --- /dev/null +++ b/tests/auto/wbmp/tst_qwbmp.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the WBMP plugin in the Qt ImageFormats module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QtGui/QtGui> + +class tst_qwbmp: public QObject +{ + Q_OBJECT + +private slots: + void readImage_data(); + void readImage(); +}; + +void tst_qwbmp::readImage_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QSize>("size"); + + QTest::newRow("qt-logo-small") << QString("qt-logo-small.wbmp") << QSize(123, 103); + QTest::newRow("qt-logo-big") << QString("qt-logo-big.wbmp") << QSize(250, 250); +} + +void tst_qwbmp::readImage() +{ + QFETCH(QString, fileName); + QFETCH(QSize, size); + + QString path = QString(":/wbmp/") + fileName; + QImageReader reader(path); + QVERIFY(reader.canRead()); + QImage image = reader.read(); + QVERIFY(!image.isNull()); + QCOMPARE(image.size(), size); +} + +QTEST_MAIN(tst_qwbmp) + +#include "tst_qwbmp.moc" diff --git a/tests/auto/wbmp/wbmp.pro b/tests/auto/wbmp/wbmp.pro new file mode 100644 index 0000000..e557184 --- /dev/null +++ b/tests/auto/wbmp/wbmp.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = tst_qwbmp +DEPENDPATH += . +INCLUDEPATH += . + +QT = core gui testlib +CONFIG -= app_bundle +CONFIG += testcase + +SOURCES += tst_qwbmp.cpp +RESOURCES += $$PWD/../../shared/images/wbmp.qrc diff --git a/tests/shared/images/wbmp.qrc b/tests/shared/images/wbmp.qrc new file mode 100644 index 0000000..bea46a1 --- /dev/null +++ b/tests/shared/images/wbmp.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>wbmp/qt-logo-big.wbmp</file> + <file>wbmp/qt-logo-small.wbmp</file> + </qresource> +</RCC> diff --git a/tests/shared/images/wbmp/qt-logo-big.wbmp b/tests/shared/images/wbmp/qt-logo-big.wbmp Binary files differnew file mode 100644 index 0000000..c275b8f --- /dev/null +++ b/tests/shared/images/wbmp/qt-logo-big.wbmp diff --git a/tests/shared/images/wbmp/qt-logo-small.wbmp b/tests/shared/images/wbmp/qt-logo-small.wbmp Binary files differnew file mode 100644 index 0000000..fe6a238 --- /dev/null +++ b/tests/shared/images/wbmp/qt-logo-small.wbmp |