mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-06-03 17:08:08 -04:00
Fixed wrong plugin options behaviour
While working on MR !230 I noticed that the options read I entered into several plugins could not be read after reading the image. **The patch fixes problems reading options in plugins and adds option checking in the readtest.cpp.** In particular, the reading test does the following additional actions: - reads options before reading the image; - compare the options read with the options returned by the reader after reading the image; - compares the format and size of the returned image with the format and size returned by the reader.
This commit is contained in:
parent
81b7263d73
commit
b849e48ef4
@ -90,6 +90,107 @@ static QImage::Format preferredFormat(QImage::Format fmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The OptionTest class
|
||||||
|
* Class for testing image options.
|
||||||
|
* Supports the most common options:
|
||||||
|
* - Size
|
||||||
|
* - ImageFormat
|
||||||
|
* - ImageTransformation (rotations)
|
||||||
|
* \todo Add missing options if needed.
|
||||||
|
*/
|
||||||
|
class OptionTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OptionTest()
|
||||||
|
: m_size(QSize())
|
||||||
|
, m_format(QImage::Format_Invalid)
|
||||||
|
, m_transformations(QImageIOHandler::TransformationNone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionTest(const OptionTest&) = default;
|
||||||
|
OptionTest& operator =(const OptionTest&) = default;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief store
|
||||||
|
* Stores the supported options of the reader.
|
||||||
|
* \param reader
|
||||||
|
* \return True on success, otherwise false.
|
||||||
|
*/
|
||||||
|
bool store(const QImageReader *reader = nullptr)
|
||||||
|
{
|
||||||
|
if (reader == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ok = true;
|
||||||
|
if (reader->supportsOption(QImageIOHandler::Size)) {
|
||||||
|
m_size = reader->size();
|
||||||
|
if (m_size.isEmpty())
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
if (reader->supportsOption(QImageIOHandler::ImageFormat)) {
|
||||||
|
m_format = reader->imageFormat();
|
||||||
|
if (m_format == QImage::Format_Invalid)
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
if (reader->supportsOption(QImageIOHandler::ImageTransformation)) {
|
||||||
|
m_transformations = reader->transformation();
|
||||||
|
if (m_transformations < 0 || m_transformations > 7)
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief compare
|
||||||
|
* Compare the stored values with the ones read from the image reader.
|
||||||
|
* \param reader
|
||||||
|
* \return True on success, otherwise false.
|
||||||
|
*/
|
||||||
|
bool compare(const QImageReader *reader)
|
||||||
|
{
|
||||||
|
if (reader == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ok = true;
|
||||||
|
if (reader->supportsOption(QImageIOHandler::Size)) {
|
||||||
|
ok = ok && (m_size == reader->size());
|
||||||
|
}
|
||||||
|
if (reader->supportsOption(QImageIOHandler::ImageFormat)) {
|
||||||
|
ok = ok && (m_format == reader->imageFormat());
|
||||||
|
}
|
||||||
|
if (reader->supportsOption(QImageIOHandler::ImageTransformation)) {
|
||||||
|
ok = ok && (m_transformations == reader->transformation());
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief compare
|
||||||
|
* Compare the image properties with the ones stored.
|
||||||
|
* \param image
|
||||||
|
* \return True on success, otherwise false.
|
||||||
|
*/
|
||||||
|
bool compare(const QImage& image)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
if (!m_size.isEmpty()) {
|
||||||
|
ok = ok && (m_size == image.size());
|
||||||
|
}
|
||||||
|
if (m_format != QImage::Format_Invalid) {
|
||||||
|
ok = ok && (m_format == image.format());
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize m_size;
|
||||||
|
QImage::Format m_format;
|
||||||
|
QImageIOHandler::Transformations m_transformations;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
@ -208,11 +309,32 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionTest optionTest;
|
||||||
|
if (!optionTest.store(&inputReader)) {
|
||||||
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while reading options\n";
|
||||||
|
++failed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!inputReader.read(&inputImage)) {
|
if (!inputReader.read(&inputImage)) {
|
||||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to load: " << inputReader.errorString() << "\n";
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to load: " << inputReader.errorString() << "\n";
|
||||||
++failed;
|
++failed;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!optionTest.compare(&inputReader)) {
|
||||||
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while comparing options\n";
|
||||||
|
++failed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!optionTest.compare(inputImage)) {
|
||||||
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while comparing the image properties with options\n";
|
||||||
|
++failed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (expImage.width() != inputImage.width()) {
|
if (expImage.width() != inputImage.width()) {
|
||||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": width was " << inputImage.width() << " but " << expfilename << " width was "
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": width was " << inputImage.width() << " but " << expfilename << " width was "
|
||||||
<< expImage.width() << "\n";
|
<< expImage.width() << "\n";
|
||||||
|
@ -734,10 +734,12 @@ void EXRHandler::setOption(ImageOption option, const QVariant &value)
|
|||||||
bool EXRHandler::supportsOption(ImageOption option) const
|
bool EXRHandler::supportsOption(ImageOption option) const
|
||||||
{
|
{
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
return true;
|
if (auto d = device())
|
||||||
|
return !d->isSequential();
|
||||||
}
|
}
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
return true;
|
if (auto d = device())
|
||||||
|
return !d->isSequential();
|
||||||
}
|
}
|
||||||
if (option == QImageIOHandler::CompressionRatio) {
|
if (option == QImageIOHandler::CompressionRatio) {
|
||||||
return true;
|
return true;
|
||||||
@ -756,6 +758,9 @@ QVariant EXRHandler::option(ImageOption option) const
|
|||||||
if (auto d = device()) {
|
if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
|
if (m_startPos > -1) {
|
||||||
|
d->seek(m_startPos);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
K_IStream istr(d, QByteArray());
|
K_IStream istr(d, QByteArray());
|
||||||
Imf::RgbaInputFile file(istr);
|
Imf::RgbaInputFile file(istr);
|
||||||
@ -778,6 +783,9 @@ QVariant EXRHandler::option(ImageOption option) const
|
|||||||
if (auto d = device()) {
|
if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
|
if (m_startPos > -1) {
|
||||||
|
d->seek(m_startPos);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
K_IStream istr(d, QByteArray());
|
K_IStream istr(d, QByteArray());
|
||||||
Imf::RgbaInputFile file(istr);
|
Imf::RgbaInputFile file(istr);
|
||||||
|
@ -269,13 +269,13 @@ bool HDRHandler::read(QImage *outImage)
|
|||||||
{
|
{
|
||||||
QDataStream s(device());
|
QDataStream s(device());
|
||||||
|
|
||||||
QSize size = readHeaderSize(s.device());
|
m_imageSize = readHeaderSize(s.device());
|
||||||
if (!size.isValid()) {
|
if (!m_imageSize.isValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage img;
|
QImage img;
|
||||||
if (!LoadHDR(s, size.width(), size.height(), img)) {
|
if (!LoadHDR(s, m_imageSize.width(), m_imageSize.height(), img)) {
|
||||||
// qDebug() << "Error loading HDR file.";
|
// qDebug() << "Error loading HDR file.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -303,7 +303,9 @@ QVariant HDRHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
if (!m_imageSize.isEmpty()) {
|
||||||
|
v = QVariant::fromValue(m_imageSize);
|
||||||
|
} else if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
auto size = readHeaderSize(d);
|
auto size = readHeaderSize(d);
|
||||||
|
@ -22,6 +22,13 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* \brief m_imageSize
|
||||||
|
* Image size cache used by option()
|
||||||
|
*/
|
||||||
|
QSize m_imageSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HDRPlugin : public QImageIOPlugin
|
class HDRPlugin : public QImageIOPlugin
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(LOG_PFMPLUGIN)
|
Q_DECLARE_LOGGING_CATEGORY(LOG_PFMPLUGIN)
|
||||||
Q_LOGGING_CATEGORY(LOG_PFMPLUGIN, "kf.imageformats.plugins.pfm", QtWarningMsg)
|
Q_LOGGING_CATEGORY(LOG_PFMPLUGIN, "kf.imageformats.plugins.pfm", QtWarningMsg)
|
||||||
|
|
||||||
class PfmHeader
|
class PFMHeader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
@ -61,7 +61,7 @@ private:
|
|||||||
QDataStream::ByteOrder m_byteOrder;
|
QDataStream::ByteOrder m_byteOrder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PfmHeader() :
|
PFMHeader() :
|
||||||
m_bw(false),
|
m_bw(false),
|
||||||
m_ps(false),
|
m_ps(false),
|
||||||
m_width(0),
|
m_width(0),
|
||||||
@ -157,7 +157,18 @@ public:
|
|||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
class PFMHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PFMHandlerPrivate() {}
|
||||||
|
~PFMHandlerPrivate() {}
|
||||||
|
|
||||||
|
PFMHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
PFMHandler::PFMHandler()
|
PFMHandler::PFMHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new PFMHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +188,7 @@ bool PFMHandler::canRead(QIODevice *device)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PfmHeader h;
|
PFMHeader h;
|
||||||
if (!h.peek(device)) {
|
if (!h.peek(device)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -187,8 +198,7 @@ bool PFMHandler::canRead(QIODevice *device)
|
|||||||
|
|
||||||
bool PFMHandler::read(QImage *image)
|
bool PFMHandler::read(QImage *image)
|
||||||
{
|
{
|
||||||
PfmHeader header;
|
auto&& header = d->m_header;
|
||||||
|
|
||||||
if (!header.read(device())) {
|
if (!header.read(device())) {
|
||||||
qCWarning(LOG_PFMPLUGIN) << "PFMHandler::read() invalid header";
|
qCWarning(LOG_PFMPLUGIN) << "PFMHandler::read() invalid header";
|
||||||
return false;
|
return false;
|
||||||
@ -265,27 +275,33 @@ QVariant PFMHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& h = d->m_header;
|
||||||
PfmHeader h;
|
if (h.isValid()) {
|
||||||
if (h.peek(d)) {
|
v = QVariant::fromValue(h.size());
|
||||||
|
} else if (auto dev = device()) {
|
||||||
|
if (h.peek(dev)) {
|
||||||
v = QVariant::fromValue(h.size());
|
v = QVariant::fromValue(h.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
if (auto d = device()) {
|
auto&& h = d->m_header;
|
||||||
PfmHeader h;
|
if (h.isValid()) {
|
||||||
if (h.peek(d)) {
|
v = QVariant::fromValue(h.format());
|
||||||
|
} else if (auto dev = device()) {
|
||||||
|
if (h.peek(dev)) {
|
||||||
v = QVariant::fromValue(h.format());
|
v = QVariant::fromValue(h.format());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::Endianness) {
|
if (option == QImageIOHandler::Endianness) {
|
||||||
if (auto d = device()) {
|
auto&& h = d->m_header;
|
||||||
PfmHeader h;
|
if (h.isValid()) {
|
||||||
if (h.peek(d)) {
|
v = QVariant::fromValue(h.byteOrder());
|
||||||
|
} else if (auto dev = device()) {
|
||||||
|
if (h.peek(dev)) {
|
||||||
v = QVariant::fromValue(h.byteOrder());
|
v = QVariant::fromValue(h.byteOrder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#define KIMG_PFM_P_H
|
#define KIMG_PFM_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class PFMHandlerPrivate;
|
||||||
class PFMHandler : public QImageIOHandler
|
class PFMHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,6 +24,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<PFMHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PFMPlugin : public QImageIOPlugin
|
class PFMPlugin : public QImageIOPlugin
|
||||||
|
@ -112,6 +112,10 @@ enum LayerId : quint32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PSDHeader {
|
struct PSDHeader {
|
||||||
|
PSDHeader() {
|
||||||
|
memset(this, 0, sizeof(PSDHeader));
|
||||||
|
}
|
||||||
|
|
||||||
uint signature;
|
uint signature;
|
||||||
ushort version;
|
ushort version;
|
||||||
uchar reserved[6];
|
uchar reserved[6];
|
||||||
@ -1375,7 +1379,17 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
|
|
||||||
} // Private
|
} // Private
|
||||||
|
|
||||||
|
class PSDHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PSDHandlerPrivate() {}
|
||||||
|
~PSDHandlerPrivate() {}
|
||||||
|
PSDHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
PSDHandler::PSDHandler()
|
PSDHandler::PSDHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new PSDHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,7 +1407,7 @@ bool PSDHandler::read(QImage *image)
|
|||||||
QDataStream s(device());
|
QDataStream s(device());
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
PSDHeader header;
|
auto&& header = d->m_header;
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
// Check image file format.
|
// Check image file format.
|
||||||
@ -1430,18 +1444,20 @@ QVariant PSDHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
|
if (IsValid(header)) {
|
||||||
|
v = QVariant::fromValue(QSize(header.width, header.height));
|
||||||
|
}
|
||||||
|
else if (auto dev = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
dev->startTransaction();
|
||||||
auto ba = d->read(sizeof(PSDHeader));
|
auto ba = dev->read(sizeof(PSDHeader));
|
||||||
d->rollbackTransaction();
|
dev->rollbackTransaction();
|
||||||
|
|
||||||
QDataStream s(ba);
|
QDataStream s(ba);
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
PSDHeader header;
|
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
if (s.status() == QDataStream::Ok && IsValid(header))
|
if (s.status() == QDataStream::Ok && IsValid(header))
|
||||||
v = QVariant::fromValue(QSize(header.width, header.height));
|
v = QVariant::fromValue(QSize(header.width, header.height));
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#define KIMG_PSD_P_H
|
#define KIMG_PSD_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class PSDHandlerPrivate;
|
||||||
class PSDHandler : public QImageIOHandler
|
class PSDHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,6 +24,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<PSDHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PSDPlugin : public QImageIOPlugin
|
class PSDPlugin : public QImageIOPlugin
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(LOG_PXRPLUGIN)
|
Q_DECLARE_LOGGING_CATEGORY(LOG_PXRPLUGIN)
|
||||||
Q_LOGGING_CATEGORY(LOG_PXRPLUGIN, "kf.imageformats.plugins.pxr", QtWarningMsg)
|
Q_LOGGING_CATEGORY(LOG_PXRPLUGIN, "kf.imageformats.plugins.pxr", QtWarningMsg)
|
||||||
|
|
||||||
class PxrHeader
|
class PXRHeader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
QByteArray m_rawHeader;
|
QByteArray m_rawHeader;
|
||||||
@ -29,7 +29,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PxrHeader()
|
PXRHeader()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -139,7 +139,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PXRHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PXRHandlerPrivate() {}
|
||||||
|
~PXRHandlerPrivate() {}
|
||||||
|
|
||||||
|
PXRHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
PXRHandler::PXRHandler()
|
PXRHandler::PXRHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new PXRHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +170,7 @@ bool PXRHandler::canRead(QIODevice *device)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PxrHeader h;
|
PXRHeader h;
|
||||||
if (!h.peek(device)) {
|
if (!h.peek(device)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -169,7 +180,7 @@ bool PXRHandler::canRead(QIODevice *device)
|
|||||||
|
|
||||||
bool PXRHandler::read(QImage *image)
|
bool PXRHandler::read(QImage *image)
|
||||||
{
|
{
|
||||||
PxrHeader header;
|
auto&& header = d->m_header;
|
||||||
|
|
||||||
if (!header.read(device())) {
|
if (!header.read(device())) {
|
||||||
qCWarning(LOG_PXRPLUGIN) << "PXRHandler::read() invalid header";
|
qCWarning(LOG_PXRPLUGIN) << "PXRHandler::read() invalid header";
|
||||||
@ -217,8 +228,10 @@ QVariant PXRHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& h = d->m_header;
|
||||||
PxrHeader h;
|
if (h.isValid()) {
|
||||||
|
v = QVariant::fromValue(h.size());
|
||||||
|
} else if (auto d = device()) {
|
||||||
if (h.peek(d)) {
|
if (h.peek(d)) {
|
||||||
v = QVariant::fromValue(h.size());
|
v = QVariant::fromValue(h.size());
|
||||||
}
|
}
|
||||||
@ -226,8 +239,10 @@ QVariant PXRHandler::option(ImageOption option) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
if (auto d = device()) {
|
auto&& h = d->m_header;
|
||||||
PxrHeader h;
|
if (h.isValid()) {
|
||||||
|
v = QVariant::fromValue(h.format());
|
||||||
|
} else if (auto d = device()) {
|
||||||
if (h.peek(d)) {
|
if (h.peek(d)) {
|
||||||
v = QVariant::fromValue(h.format());
|
v = QVariant::fromValue(h.format());
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#define KIMG_PXR_P_H
|
#define KIMG_PXR_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class PXRHandlerPrivate;
|
||||||
class PXRHandler : public QImageIOHandler
|
class PXRHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,6 +24,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<PXRHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PXRPlugin : public QImageIOPlugin
|
class PXRPlugin : public QImageIOPlugin
|
||||||
|
@ -31,6 +31,18 @@ namespace // Private
|
|||||||
#define QOI_END_STREAM_PAD 8
|
#define QOI_END_STREAM_PAD 8
|
||||||
|
|
||||||
struct QoiHeader {
|
struct QoiHeader {
|
||||||
|
QoiHeader()
|
||||||
|
: MagicNumber(0)
|
||||||
|
, Width(0)
|
||||||
|
, Height(0)
|
||||||
|
, Channels(0)
|
||||||
|
, Colorspace(2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QoiHeader(const QoiHeader&) = default;
|
||||||
|
QoiHeader& operator=(const QoiHeader&) = default;
|
||||||
|
|
||||||
quint32 MagicNumber;
|
quint32 MagicNumber;
|
||||||
quint32 Width;
|
quint32 Width;
|
||||||
quint32 Height;
|
quint32 Height;
|
||||||
@ -297,7 +309,19 @@ static bool SaveQOI(QIODevice *device, const QoiHeader &qoi, const QImage &img)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
class QOIHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QOIHandlerPrivate() {}
|
||||||
|
~QOIHandlerPrivate() {}
|
||||||
|
|
||||||
|
QoiHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
QOIHandler::QOIHandler()
|
QOIHandler::QOIHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new QOIHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +352,7 @@ bool QOIHandler::canRead(QIODevice *device)
|
|||||||
|
|
||||||
QDataStream stream(head);
|
QDataStream stream(head);
|
||||||
stream.setByteOrder(QDataStream::BigEndian);
|
stream.setByteOrder(QDataStream::BigEndian);
|
||||||
QoiHeader qoi = {0, 0, 0, 0, 2};
|
QoiHeader qoi;
|
||||||
stream >> qoi;
|
stream >> qoi;
|
||||||
|
|
||||||
return IsSupported(qoi);
|
return IsSupported(qoi);
|
||||||
@ -340,7 +364,7 @@ bool QOIHandler::read(QImage *image)
|
|||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
// Read image header
|
// Read image header
|
||||||
QoiHeader qoi = {0, 0, 0, 0, 2};
|
auto&& qoi = d->m_header;
|
||||||
s >> qoi;
|
s >> qoi;
|
||||||
|
|
||||||
// Check if file is supported
|
// Check if file is supported
|
||||||
@ -402,7 +426,10 @@ QVariant QOIHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
|
if (IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
||||||
|
} else if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
auto ba = d->read(sizeof(QoiHeader));
|
auto ba = d->read(sizeof(QoiHeader));
|
||||||
@ -410,10 +437,7 @@ QVariant QOIHandler::option(ImageOption option) const
|
|||||||
|
|
||||||
QDataStream s(ba);
|
QDataStream s(ba);
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
QoiHeader header = {0, 0, 0, 0, 2};
|
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
||||||
}
|
}
|
||||||
@ -421,7 +445,10 @@ QVariant QOIHandler::option(ImageOption option) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
|
if (IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
|
} else if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
auto ba = d->read(sizeof(QoiHeader));
|
auto ba = d->read(sizeof(QoiHeader));
|
||||||
@ -429,10 +456,7 @@ QVariant QOIHandler::option(ImageOption option) const
|
|||||||
|
|
||||||
QDataStream s(ba);
|
QDataStream s(ba);
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
QoiHeader header = {0, 0, 0, 0, 2};
|
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(imageFormat(header));
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#define KIMG_QOI_P_H
|
#define KIMG_QOI_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class QOIHandlerPrivate;
|
||||||
class QOIHandler : public QImageIOHandler
|
class QOIHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -23,6 +25,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<QOIHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QOIPlugin : public QImageIOPlugin
|
class QOIPlugin : public QImageIOPlugin
|
||||||
|
@ -336,7 +336,19 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
class RASHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RASHandlerPrivate() {}
|
||||||
|
~RASHandlerPrivate() {}
|
||||||
|
|
||||||
|
RasHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
RASHandler::RASHandler()
|
RASHandler::RASHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new RASHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +396,7 @@ bool RASHandler::read(QImage *outImage)
|
|||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
// Read image header.
|
// Read image header.
|
||||||
RasHeader ras;
|
auto&& ras = d->m_header;
|
||||||
s >> ras;
|
s >> ras;
|
||||||
|
|
||||||
if (ras.ColorMapLength > kMaxQVectorSize) {
|
if (ras.ColorMapLength > kMaxQVectorSize) {
|
||||||
@ -426,18 +438,19 @@ QVariant RASHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
|
if (IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
||||||
|
}
|
||||||
|
else if (auto dev = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
dev->startTransaction();
|
||||||
auto ba = d->read(RasHeader::SIZE);
|
auto ba = dev->read(RasHeader::SIZE);
|
||||||
d->rollbackTransaction();
|
dev->rollbackTransaction();
|
||||||
|
|
||||||
QDataStream s(ba);
|
QDataStream s(ba);
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
RasHeader header;
|
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
v = QVariant::fromValue(QSize(header.Width, header.Height));
|
||||||
}
|
}
|
||||||
@ -445,18 +458,19 @@ QVariant RASHandler::option(ImageOption option) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
|
if (IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
|
}
|
||||||
|
else if (auto dev = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
dev->startTransaction();
|
||||||
auto ba = d->read(RasHeader::SIZE);
|
auto ba = dev->read(RasHeader::SIZE);
|
||||||
d->rollbackTransaction();
|
dev->rollbackTransaction();
|
||||||
|
|
||||||
QDataStream s(ba);
|
QDataStream s(ba);
|
||||||
s.setByteOrder(QDataStream::BigEndian);
|
s.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
RasHeader header;
|
|
||||||
s >> header;
|
s >> header;
|
||||||
|
|
||||||
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
if (s.status() == QDataStream::Ok && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(imageFormat(header));
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
#define KIMG_RAS_P_H
|
#define KIMG_RAS_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class RASHandlerPrivate;
|
||||||
class RASHandler : public QImageIOHandler
|
class RASHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -23,6 +25,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<RASHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RASPlugin : public QImageIOPlugin
|
class RASPlugin : public QImageIOPlugin
|
||||||
|
@ -56,18 +56,18 @@ enum TGAType {
|
|||||||
|
|
||||||
/** Tga Header. */
|
/** Tga Header. */
|
||||||
struct TgaHeader {
|
struct TgaHeader {
|
||||||
uchar id_length;
|
uchar id_length = 0;
|
||||||
uchar colormap_type;
|
uchar colormap_type = 0;
|
||||||
uchar image_type;
|
uchar image_type = 0;
|
||||||
ushort colormap_index;
|
ushort colormap_index = 0;
|
||||||
ushort colormap_length;
|
ushort colormap_length = 0;
|
||||||
uchar colormap_size;
|
uchar colormap_size = 0;
|
||||||
ushort x_origin;
|
ushort x_origin = 0;
|
||||||
ushort y_origin;
|
ushort y_origin = 0;
|
||||||
ushort width;
|
ushort width = 0;
|
||||||
ushort height;
|
ushort height = 0;
|
||||||
uchar pixel_size;
|
uchar pixel_size = 0;
|
||||||
uchar flags;
|
uchar flags = 0;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIZE = 18,
|
SIZE = 18,
|
||||||
@ -407,7 +407,18 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
class TGAHandlerPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TGAHandlerPrivate() {}
|
||||||
|
~TGAHandlerPrivate() {}
|
||||||
|
|
||||||
|
TgaHeader m_header;
|
||||||
|
};
|
||||||
|
|
||||||
TGAHandler::TGAHandler()
|
TGAHandler::TGAHandler()
|
||||||
|
: QImageIOHandler()
|
||||||
|
, d(new TGAHandlerPrivate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,20 +435,20 @@ bool TGAHandler::read(QImage *outImage)
|
|||||||
{
|
{
|
||||||
// qDebug() << "Loading TGA file!";
|
// qDebug() << "Loading TGA file!";
|
||||||
|
|
||||||
auto d = device();
|
auto dev = device();
|
||||||
TgaHeader tga;
|
auto&& tga = d->m_header;
|
||||||
if (!peekHeader(d, tga) || !IsSupported(tga)) {
|
if (!peekHeader(dev, tga) || !IsSupported(tga)) {
|
||||||
// qDebug() << "This TGA file is not valid.";
|
// qDebug() << "This TGA file is not valid.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->isSequential()) {
|
if (dev->isSequential()) {
|
||||||
d->read(TgaHeader::SIZE + tga.id_length);
|
dev->read(TgaHeader::SIZE + tga.id_length);
|
||||||
} else {
|
} else {
|
||||||
d->seek(TgaHeader::SIZE + tga.id_length);
|
dev->seek(TgaHeader::SIZE + tga.id_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream s(d);
|
QDataStream s(dev);
|
||||||
s.setByteOrder(QDataStream::LittleEndian);
|
s.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
// Check image file format.
|
// Check image file format.
|
||||||
@ -519,18 +530,22 @@ QVariant TGAHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
TgaHeader header;
|
if (IsSupported(header)) {
|
||||||
if (peekHeader(d, header) && IsSupported(header)) {
|
v = QVariant::fromValue(QSize(header.width, header.height));
|
||||||
|
} else if (auto dev = device()) {
|
||||||
|
if (peekHeader(dev, header) && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(QSize(header.width, header.height));
|
v = QVariant::fromValue(QSize(header.width, header.height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == QImageIOHandler::ImageFormat) {
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
if (auto d = device()) {
|
auto&& header = d->m_header;
|
||||||
TgaHeader header;
|
if (IsSupported(header)) {
|
||||||
if (peekHeader(d, header) && IsSupported(header)) {
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
|
} else if (auto dev = device()) {
|
||||||
|
if (peekHeader(dev, header) && IsSupported(header)) {
|
||||||
v = QVariant::fromValue(imageFormat(header));
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#define KIMG_TGA_P_H
|
#define KIMG_TGA_P_H
|
||||||
|
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class TGAHandlerPrivate;
|
||||||
class TGAHandler : public QImageIOHandler
|
class TGAHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -23,6 +25,9 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QScopedPointer<TGAHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TGAPlugin : public QImageIOPlugin
|
class TGAPlugin : public QImageIOPlugin
|
||||||
|
@ -4149,7 +4149,9 @@ bool XCFHandler::canRead() const
|
|||||||
bool XCFHandler::read(QImage *image)
|
bool XCFHandler::read(QImage *image)
|
||||||
{
|
{
|
||||||
XCFImageFormat xcfif;
|
XCFImageFormat xcfif;
|
||||||
return xcfif.readXCF(device(), image);
|
auto ok = xcfif.readXCF(device(), image);
|
||||||
|
m_imageSize = image->size();
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XCFHandler::write(const QImage &)
|
bool XCFHandler::write(const QImage &)
|
||||||
@ -4169,6 +4171,9 @@ QVariant XCFHandler::option(ImageOption option) const
|
|||||||
QVariant v;
|
QVariant v;
|
||||||
|
|
||||||
if (option == QImageIOHandler::Size) {
|
if (option == QImageIOHandler::Size) {
|
||||||
|
if (!m_imageSize.isEmpty()) {
|
||||||
|
return m_imageSize;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* The image structure always starts at offset 0 in the XCF file.
|
* The image structure always starts at offset 0 in the XCF file.
|
||||||
* byte[9] "gimp xcf " File type identification
|
* byte[9] "gimp xcf " File type identification
|
||||||
@ -4181,7 +4186,7 @@ QVariant XCFHandler::option(ImageOption option) const
|
|||||||
* uint32 width Width of canvas
|
* uint32 width Width of canvas
|
||||||
* uint32 height Height of canvas
|
* uint32 height Height of canvas
|
||||||
*/
|
*/
|
||||||
if (auto d = device()) {
|
else if (auto d = device()) {
|
||||||
// transactions works on both random and sequential devices
|
// transactions works on both random and sequential devices
|
||||||
d->startTransaction();
|
d->startTransaction();
|
||||||
auto ba9 = d->read(9); // "gimp xcf "
|
auto ba9 = d->read(9); // "gimp xcf "
|
||||||
|
@ -24,6 +24,13 @@ public:
|
|||||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* \brief m_imageSize
|
||||||
|
* Image size cache used by option()
|
||||||
|
*/
|
||||||
|
QSize m_imageSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XCFPlugin : public QImageIOPlugin
|
class XCFPlugin : public QImageIOPlugin
|
||||||
|
Loading…
x
Reference in New Issue
Block a user