Run clang-format on all cpp/h files

NO_CHANGELOG
This commit is contained in:
Ahmad Samir 2021-03-08 20:15:33 +02:00
parent 04e276dcb3
commit 1169859b07
32 changed files with 989 additions and 1273 deletions

View File

@ -35,61 +35,27 @@ private:
QTest::addColumn<QImage::Format>("pngformat"); QTest::addColumn<QImage::Format>("pngformat");
QTest::addColumn<bool>("compress"); QTest::addColumn<bool>("compress");
QTest::newRow("4x4 no alpha RLE") QTest::newRow("4x4 no alpha RLE") << QFINDTESTDATA("pic/4x4-simple-color.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString() << false
<< QFINDTESTDATA("pic/4x4-simple-color.pic") << QImage::Format_RGB32 << true;
<< QFINDTESTDATA("pic/4x4-simple-color.png")
<< QString()
<< false
<< QImage::Format_RGB32
<< true;
QTest::newRow("4x4 no alpha raw") QTest::newRow("4x4 no alpha raw") << QFINDTESTDATA("pic/4x4-simple-color-uncompressed.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString()
<< QFINDTESTDATA("pic/4x4-simple-color-uncompressed.pic") << false << QImage::Format_RGB32 << false;
<< QFINDTESTDATA("pic/4x4-simple-color.png")
<< QString()
<< false
<< QImage::Format_RGB32
<< false;
QTest::newRow("Short comment") QTest::newRow("Short comment") << QFINDTESTDATA("pic/short-comment.pic") << QFINDTESTDATA("pic/4x4-simple-color.png")
<< QFINDTESTDATA("pic/short-comment.pic") << QStringLiteral("Test comment value") << false << QImage::Format_RGB32 << true;
<< QFINDTESTDATA("pic/4x4-simple-color.png")
<< QStringLiteral("Test comment value")
<< false
<< QImage::Format_RGB32
<< true;
QTest::newRow("Long comment") QTest::newRow("Long comment") << QFINDTESTDATA("pic/long-comment.pic") << QFINDTESTDATA("pic/4x4-simple-color.png")
<< QFINDTESTDATA("pic/long-comment.pic") << QStringLiteral("Test comment value that goes right up to the end of the comment field and has no") << false
<< QFINDTESTDATA("pic/4x4-simple-color.png") << QImage::Format_RGB32 << true;
<< QStringLiteral("Test comment value that goes right up to the end of the comment field and has no")
<< false
<< QImage::Format_RGB32
<< true;
QTest::newRow("Long run-lengths") QTest::newRow("Long run-lengths") << QFINDTESTDATA("pic/long-runs.pic") << QFINDTESTDATA("pic/long-runs.png") << QString() << false
<< QFINDTESTDATA("pic/long-runs.pic") << QImage::Format_RGB32 << true;
<< QFINDTESTDATA("pic/long-runs.png")
<< QString()
<< false
<< QImage::Format_RGB32
<< true;
QTest::newRow("4x4 with alpha RLE") QTest::newRow("4x4 with alpha RLE") << QFINDTESTDATA("pic/4x4-alpha.pic") << QFINDTESTDATA("pic/4x4-alpha.png") << QString() << true
<< QFINDTESTDATA("pic/4x4-alpha.pic") << QImage::Format_ARGB32 << true;
<< QFINDTESTDATA("pic/4x4-alpha.png")
<< QString()
<< true
<< QImage::Format_ARGB32
<< true;
QTest::newRow("4x4 with alpha raw") QTest::newRow("4x4 with alpha raw") << QFINDTESTDATA("pic/4x4-alpha-uncompressed.pic") << QFINDTESTDATA("pic/4x4-alpha.png") << QString() << true
<< QFINDTESTDATA("pic/4x4-alpha-uncompressed.pic") << QImage::Format_ARGB32 << false;
<< QFINDTESTDATA("pic/4x4-alpha.png")
<< QString()
<< true
<< QImage::Format_ARGB32
<< false;
} }
private Q_SLOTS: private Q_SLOTS:
@ -106,13 +72,8 @@ private Q_SLOTS:
// so there is no actual data loss in converting to RGB16. // so there is no actual data loss in converting to RGB16.
// This just tests that the pic plugin can deal with different // This just tests that the pic plugin can deal with different
// input formats. // input formats.
QTest::newRow("altered format") QTest::newRow("altered format") << QFINDTESTDATA("pic/4x4-simple-color.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString() << false
<< QFINDTESTDATA("pic/4x4-simple-color.pic") << QImage::Format_RGB16 << true;
<< QFINDTESTDATA("pic/4x4-simple-color.png")
<< QString()
<< false
<< QImage::Format_RGB16
<< true;
} }
void testRead_data() void testRead_data()
@ -148,17 +109,12 @@ private Q_SLOTS:
imgWriter.write(pngImage); imgWriter.write(pngImage);
if (expData != picData) { if (expData != picData) {
QString fileNameBase = QUuid::createUuid().toString() QString fileNameBase = QUuid::createUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
.remove(QLatin1Char('{'))
.remove(QLatin1Char('}'));
QFile dumpFile(fileNameBase + QStringLiteral(".pic")); QFile dumpFile(fileNameBase + QStringLiteral(".pic"));
QVERIFY2(dumpFile.open(QIODevice::WriteOnly), qPrintable(dumpFile.errorString())); QVERIFY2(dumpFile.open(QIODevice::WriteOnly), qPrintable(dumpFile.errorString()));
dumpFile.write(picData); dumpFile.write(picData);
QString msg = QStringLiteral("Written data (") QString msg =
+ dumpFile.fileName() QStringLiteral("Written data (") + dumpFile.fileName() + QStringLiteral(") differed from expected data (") + picfile + QLatin1Char(')');
+ QStringLiteral(") differed from expected data (")
+ picfile
+ QLatin1Char(')');
QFAIL(qPrintable(msg)); QFAIL(qPrintable(msg));
} }
} }
@ -182,28 +138,19 @@ private Q_SLOTS:
QCOMPARE(inputImage.width(), expImage.width()); QCOMPARE(inputImage.width(), expImage.width());
QCOMPARE(inputImage.height(), expImage.height()); QCOMPARE(inputImage.height(), expImage.height());
QCOMPARE(inputImage.hasAlphaChannel(), alpha); QCOMPARE(inputImage.hasAlphaChannel(), alpha);
QCOMPARE(inputImage.format(), alpha ? QImage::Format_ARGB32 QCOMPARE(inputImage.format(), alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
: QImage::Format_RGB32);
expImage = expImage.convertToFormat(pngformat); expImage = expImage.convertToFormat(pngformat);
expImage = expImage.convertToFormat(alpha ? QImage::Format_ARGB32 expImage = expImage.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
: QImage::Format_RGB32);
if (inputImage != expImage) { if (inputImage != expImage) {
QString fileNameBase = QUuid::createUuid().toString() QString fileNameBase = QUuid::createUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
.remove(QLatin1Char('{'))
.remove(QLatin1Char('}'));
QFile picDumpFile(fileNameBase + QStringLiteral("-expected.data")); QFile picDumpFile(fileNameBase + QStringLiteral("-expected.data"));
QVERIFY2(picDumpFile.open(QIODevice::WriteOnly), qPrintable(picDumpFile.errorString())); QVERIFY2(picDumpFile.open(QIODevice::WriteOnly), qPrintable(picDumpFile.errorString()));
picDumpFile.write(reinterpret_cast<const char *>(inputImage.bits()), picDumpFile.write(reinterpret_cast<const char *>(inputImage.bits()), inputImage.sizeInBytes());
inputImage.sizeInBytes());
QFile pngDumpFile(fileNameBase + QStringLiteral("-actual.data")); QFile pngDumpFile(fileNameBase + QStringLiteral("-actual.data"));
QVERIFY2(pngDumpFile.open(QIODevice::WriteOnly), qPrintable(pngDumpFile.errorString())); QVERIFY2(pngDumpFile.open(QIODevice::WriteOnly), qPrintable(pngDumpFile.errorString()));
pngDumpFile.write(reinterpret_cast<const char *>(expImage.bits()), pngDumpFile.write(reinterpret_cast<const char *>(expImage.bits()), expImage.sizeInBytes());
expImage.sizeInBytes()); QString msg = QStringLiteral("Read image (") + picDumpFile.fileName() + QStringLiteral(") differed from expected image (") + pngDumpFile.fileName()
QString msg = QStringLiteral("Read image (")
+ picDumpFile.fileName()
+ QStringLiteral(") differed from expected image (")
+ pngDumpFile.fileName()
+ QLatin1Char(')'); + QLatin1Char(')');
QFAIL(qPrintable(msg)); QFAIL(qPrintable(msg));
} }
@ -252,8 +199,7 @@ private Q_SLOTS:
QImageReader inputReader(picfile, "pic"); QImageReader inputReader(picfile, "pic");
QCOMPARE(inputReader.imageFormat(), QCOMPARE(inputReader.imageFormat(), alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
} }
}; };

View File

@ -22,17 +22,12 @@ static void writeImageData(const char *name, const QString &filename, const QIma
if (file.open(QIODevice::WriteOnly)) { if (file.open(QIODevice::WriteOnly)) {
qint64 written = file.write(reinterpret_cast<const char *>(image.bits()), image.sizeInBytes()); qint64 written = file.write(reinterpret_cast<const char *>(image.bits()), image.sizeInBytes());
if (written == image.sizeInBytes()) { if (written == image.sizeInBytes()) {
QTextStream(stdout) << " " << name QTextStream(stdout) << " " << name << " written to " << filename << "\n";
<< " written to " << filename << "\n";
} else { } else {
QTextStream(stdout) << " could not write " << name QTextStream(stdout) << " could not write " << name << " to " << filename << ":" << file.errorString() << "\n";
<< " to " << filename << ":"
<< file.errorString() << "\n";
} }
} else { } else {
QTextStream(stdout) << " could not open " QTextStream(stdout) << " could not open " << filename << ":" << file.errorString() << "\n";
<< filename << ":"
<< file.errorString() << "\n";
} }
} }
@ -63,8 +58,7 @@ static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
// allow each byte to be different by up to 1, to allow for rounding errors // allow each byte to be different by up to 1, to allow for rounding errors
static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness) static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
{ {
return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness) return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness) : fuzzyeq<quint8>(im1, im2, fuzziness);
: fuzzyeq<quint8>(im1, im2, fuzziness);
} }
// Returns the original format if we support, or returns // Returns the original format if we support, or returns
@ -97,8 +91,7 @@ int main(int argc, char ** argv)
parser.addHelpOption(); parser.addHelpOption();
parser.addVersionOption(); parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test")); parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test"));
QCommandLineOption fuzz( QCommandLineOption fuzz(QStringList() << QStringLiteral("f") << QStringLiteral("fuzz"),
QStringList() << QStringLiteral("f") << QStringLiteral("fuzz"),
QStringLiteral("Allow for some deviation in ARGB data."), QStringLiteral("Allow for some deviation in ARGB data."),
QStringLiteral("max")); QStringLiteral("max"));
parser.addOption(fuzz); parser.addOption(fuzz);
@ -136,13 +129,14 @@ int main(int argc, char ** argv)
int failed = 0; int failed = 0;
QTextStream(stdout) << "********* " QTextStream(stdout) << "********* "
<< "Starting basic read tests for " << "Starting basic read tests for " << suffix << " images *********\n";
<< suffix << " images *********\n";
const QList<QByteArray> formats = QImageReader::supportedImageFormats(); const QList<QByteArray> formats = QImageReader::supportedImageFormats();
QStringList formatStrings; QStringList formatStrings;
formatStrings.reserve(formats.size()); formatStrings.reserve(formats.size());
std::transform(formats.begin(), formats.end(), std::back_inserter(formatStrings), [](const QByteArray &format) { return QString(format); }); std::transform(formats.begin(), formats.end(), std::back_inserter(formatStrings), [](const QByteArray &format) {
return QString(format);
});
QTextStream(stdout) << "QImageReader::supportedImageFormats: " << formatStrings.join(", ") << "\n"; QTextStream(stdout) << "QImageReader::supportedImageFormats: " << formatStrings.join(", ") << "\n";
const QFileInfoList lstImgDir = imgdir.entryInfoList(); const QFileInfoList lstImgDir = imgdir.entryInfoList();
@ -159,39 +153,26 @@ int main(int argc, char ** argv)
QImage expImage; QImage expImage;
if (!expReader.read(&expImage)) { if (!expReader.read(&expImage)) {
QTextStream(stdout) << "ERROR: " << fi.fileName() QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << expfilename << ": " << expReader.errorString() << "\n";
<< ": could not load " << expfilename
<< ": " << expReader.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
if (!inputReader.canRead()) { if (!inputReader.canRead()) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed can read: " << inputReader.errorString() << "\n";
<< ": failed can read: "
<< inputReader.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
if (!inputReader.read(&inputImage)) { if (!inputReader.read(&inputImage)) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to load: " << inputReader.errorString() << "\n";
<< ": failed to load: "
<< inputReader.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
if (expImage.width() != inputImage.width()) { if (expImage.width() != inputImage.width()) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": width was " << inputImage.width() << " but " << expfilename << " width was "
<< ": width was " << inputImage.width()
<< " but " << expfilename << " width was "
<< expImage.width() << "\n"; << expImage.width() << "\n";
++failed; ++failed;
} else if (expImage.height() != inputImage.height()) { } else if (expImage.height() != inputImage.height()) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": height was " << inputImage.height() << " but " << expfilename << " height was "
<< ": height was " << inputImage.height()
<< " but " << expfilename << " height was "
<< expImage.height() << "\n"; << expImage.height() << "\n";
++failed; ++failed;
} else { } else {
@ -200,42 +181,30 @@ int main(int argc, char ** argv)
QImage::Format cmpFormat = inputFormat == expFormat ? inputFormat : QImage::Format_ARGB32; QImage::Format cmpFormat = inputFormat == expFormat ? inputFormat : QImage::Format_ARGB32;
if (inputImage.format() != cmpFormat) { if (inputImage.format() != cmpFormat) {
QTextStream(stdout) << "INFO : " << fi.fileName() QTextStream(stdout) << "INFO : " << fi.fileName() << ": converting " << fi.fileName() << " from " << formatToString(inputImage.format())
<< ": converting " << fi.fileName()
<< " from " << formatToString(inputImage.format())
<< " to " << formatToString(cmpFormat) << '\n'; << " to " << formatToString(cmpFormat) << '\n';
inputImage = inputImage.convertToFormat(cmpFormat); inputImage = inputImage.convertToFormat(cmpFormat);
} }
if (expImage.format() != cmpFormat) { if (expImage.format() != cmpFormat) {
QTextStream(stdout) << "INFO : " << fi.fileName() QTextStream(stdout) << "INFO : " << fi.fileName() << ": converting " << expfilename << " from " << formatToString(expImage.format()) << " to "
<< ": converting " << expfilename << formatToString(cmpFormat) << '\n';
<< " from " << formatToString(expImage.format())
<< " to " << formatToString(cmpFormat) << '\n';
expImage = expImage.convertToFormat(cmpFormat); expImage = expImage.convertToFormat(cmpFormat);
} }
if (fuzzyeq(inputImage, expImage, fuzziness)) { if (fuzzyeq(inputImage, expImage, fuzziness)) {
QTextStream(stdout) << "PASS : " << fi.fileName() << "\n"; QTextStream(stdout) << "PASS : " << fi.fileName() << "\n";
++passed; ++passed;
} else { } else {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": differs from " << expfilename << "\n";
<< ": differs from " << expfilename << "\n"; writeImageData("expected data", fi.fileName() + QLatin1String("-expected.data"), expImage);
writeImageData("expected data", writeImageData("actual data", fi.fileName() + QLatin1String("-actual.data"), inputImage);
fi.fileName() + QLatin1String("-expected.data"),
expImage);
writeImageData("actual data",
fi.fileName() + QLatin1String("-actual.data"),
inputImage);
++failed; ++failed;
} }
} }
} }
QTextStream(stdout) << "Totals: " QTextStream(stdout) << "Totals: " << passed << " passed, " << failed << " failed\n";
<< passed << " passed, "
<< failed << " failed\n";
QTextStream(stdout) << "********* " QTextStream(stdout) << "********* "
<< "Finished basic read tests for " << "Finished basic read tests for " << suffix << " images *********\n";
<< suffix << " images *********\n";
return failed == 0 ? 0 : 1; return failed == 0 ? 0 : 1;
} }

View File

@ -29,8 +29,7 @@ int main(int argc, char ** argv)
parser.addHelpOption(); parser.addHelpOption();
parser.addVersionOption(); parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test.")); parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test."));
QCommandLineOption lossless( QCommandLineOption lossless(QStringList() << QStringLiteral("l") << QStringLiteral("lossless"),
QStringList() << QStringLiteral("l") << QStringLiteral("lossless"),
QStringLiteral("Check that reading back the data gives the same image.")); QStringLiteral("Check that reading back the data gives the same image."));
parser.addOption(lossless); parser.addOption(lossless);
@ -56,8 +55,7 @@ int main(int argc, char ** argv)
int failed = 0; int failed = 0;
QTextStream(stdout) << "********* " QTextStream(stdout) << "********* "
<< "Starting basic write tests for " << "Starting basic write tests for " << suffix << " images *********\n";
<< suffix << " images *********\n";
const QFileInfoList lstImgDir = imgdir.entryInfoList(); const QFileInfoList lstImgDir = imgdir.entryInfoList();
for (const QFileInfo &fi : lstImgDir) { for (const QFileInfo &fi : lstImgDir) {
int suffixPos = fi.filePath().count() - suffix.count(); int suffixPos = fi.filePath().count() - suffix.count();
@ -67,20 +65,14 @@ int main(int argc, char ** argv)
QImageReader pngReader(pngfile, "png"); QImageReader pngReader(pngfile, "png");
QImage pngImage; QImage pngImage;
if (!pngReader.read(&pngImage)) { if (!pngReader.read(&pngImage)) {
QTextStream(stdout) << "ERROR: " << fi.fileName() QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << pngfilename << ": " << pngReader.errorString() << "\n";
<< ": could not load " << pngfilename
<< ": " << pngReader.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
QFile expFile(fi.filePath()); QFile expFile(fi.filePath());
if (!expFile.open(QIODevice::ReadOnly)) { if (!expFile.open(QIODevice::ReadOnly)) {
QTextStream(stdout) << "ERROR: " << fi.fileName() QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not open " << fi.fileName() << ": " << expFile.errorString() << "\n";
<< ": could not open " << fi.fileName()
<< ": " << expFile.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
@ -91,10 +83,7 @@ int main(int argc, char ** argv)
char buf[1]; char buf[1];
qint64 result = expFile.read(buf, 1); qint64 result = expFile.read(buf, 1);
if (result < 0) { if (result < 0) {
QTextStream(stdout) << "ERROR: " << fi.fileName() QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << fi.fileName() << ": " << expFile.errorString() << "\n";
<< ": could not load " << fi.fileName()
<< ": " << expFile.errorString()
<< "\n";
++failed; ++failed;
continue; continue;
} }
@ -105,16 +94,14 @@ int main(int argc, char ** argv)
QBuffer buffer(&writtenData); QBuffer buffer(&writtenData);
QImageWriter imgWriter(&buffer, format.constData()); QImageWriter imgWriter(&buffer, format.constData());
if (!imgWriter.write(pngImage)) { if (!imgWriter.write(pngImage)) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to write image data\n";
<< ": failed to write image data\n";
++failed; ++failed;
continue; continue;
} }
} }
if (expData != writtenData) { if (expData != writtenData) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": written data differs from " << fi.fileName() << "\n";
<< ": written data differs from " << fi.fileName() << "\n";
++failed; ++failed;
continue; continue;
} }
@ -124,8 +111,7 @@ int main(int argc, char ** argv)
QBuffer buffer(&writtenData); QBuffer buffer(&writtenData);
QImageReader imgReader(&buffer, format.constData()); QImageReader imgReader(&buffer, format.constData());
if (!imgReader.read(&reReadImage)) { if (!imgReader.read(&reReadImage)) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": could not read back the written data\n";
<< ": could not read back the written data\n";
++failed; ++failed;
continue; continue;
} }
@ -134,8 +120,7 @@ int main(int argc, char ** argv)
if (parser.isSet(lossless)) { if (parser.isSet(lossless)) {
if (pngImage != reReadImage) { if (pngImage != reReadImage) {
QTextStream(stdout) << "FAIL : " << fi.fileName() QTextStream(stdout) << "FAIL : " << fi.fileName() << ": re-reading the data resulted in a different image\n";
<< ": re-reading the data resulted in a different image\n";
++failed; ++failed;
continue; continue;
} }
@ -145,12 +130,9 @@ int main(int argc, char ** argv)
++passed; ++passed;
} }
QTextStream(stdout) << "Totals: " QTextStream(stdout) << "Totals: " << passed << " passed, " << failed << " failed\n";
<< passed << " passed, "
<< failed << " failed\n";
QTextStream(stdout) << "********* " QTextStream(stdout) << "********* "
<< "Finished basic write tests for " << "Finished basic write tests for " << suffix << " images *********\n";
<< suffix << " images *********\n";
return failed == 0 ? 0 : 1; return failed == 0 ? 0 : 1;
} }

View File

@ -9,12 +9,11 @@
#include <QDebug> #include <QDebug>
#include <QImage> #include <QImage>
#include <QScopeGuard> #include <QScopeGuard>
#include <QtEndian>
#include <QVariant> #include <QVariant>
#include <QtEndian>
namespace namespace
{ {
struct ChunkHeader { struct ChunkHeader {
char magic[4]; char magic[4];
quint32_le size; quint32_le size;
@ -64,8 +63,7 @@ bool ANIHandler::canRead() const
const QByteArray nextFrame = device()->peek(sizeof(ChunkHeader)); const QByteArray nextFrame = device()->peek(sizeof(ChunkHeader));
if (nextFrame.size() == sizeof(ChunkHeader)) { if (nextFrame.size() == sizeof(ChunkHeader)) {
const auto *header = reinterpret_cast<const ChunkHeader *>(nextFrame.data()); const auto *header = reinterpret_cast<const ChunkHeader *>(nextFrame.data());
if (qstrncmp(header->magic, "icon", sizeof(header->magic)) == 0 if (qstrncmp(header->magic, "icon", sizeof(header->magic)) == 0 && header->size > 0) {
&& header->size > 0) {
setFormat("ani"); setFormat("ani");
return true; return true;
} }
@ -377,8 +375,7 @@ bool ANIHandler::ensureScanned() const
mutableThis->m_displayRate = aniHeader->iDispRate; mutableThis->m_displayRate = aniHeader->iDispRate;
} else if (chunkId == "rate" || chunkId == "seq ") { } else if (chunkId == "rate" || chunkId == "seq ") {
const QByteArray data = device()->read(chunkSize); const QByteArray data = device()->read(chunkSize);
if (static_cast<quint32_le>(data.size()) != chunkSize if (static_cast<quint32_le>(data.size()) != chunkSize || data.size() % sizeof(quint32_le) != 0) {
|| data.size() % sizeof(quint32_le) != 0) {
return false; return false;
} }
@ -455,8 +452,7 @@ bool ANIHandler::ensureScanned() const
const QByteArray curHeaderData = device()->read(sizeof(CurHeader)); const QByteArray curHeaderData = device()->read(sizeof(CurHeader));
const QByteArray cursorDirEntryData = device()->read(sizeof(CursorDirEntry)); const QByteArray cursorDirEntryData = device()->read(sizeof(CursorDirEntry));
if (curHeaderData.length() == sizeof(CurHeader) if (curHeaderData.length() == sizeof(CurHeader) && cursorDirEntryData.length() == sizeof(CursorDirEntry)) {
&& cursorDirEntryData.length() == sizeof(CursorDirEntry)) {
auto *cursorDirEntry = reinterpret_cast<const CursorDirEntry *>(cursorDirEntryData.data()); auto *cursorDirEntry = reinterpret_cast<const CursorDirEntry *>(cursorDirEntryData.data());
mutableThis->m_size = QSize(cursorDirEntry->bWidth, cursorDirEntry->bHeight); mutableThis->m_size = QSize(cursorDirEntry->bWidth, cursorDirEntry->bHeight);
} }

View File

@ -53,7 +53,6 @@ private:
QString m_name; QString m_name;
QString m_artist; QString m_artist;
QSize m_size; QSize m_size;
}; };
class ANIPlugin : public QImageIOPlugin class ANIPlugin : public QImageIOPlugin

View File

@ -6,23 +6,22 @@
SPDX-License-Identifier: BSD-2-Clause SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <QtGlobal>
#include <QThread> #include <QThread>
#include <QtGlobal>
#include <QColorSpace> #include <QColorSpace>
#include "avif_p.h" #include "avif_p.h"
#include <cfloat> #include <cfloat>
QAVIFHandler::QAVIFHandler()
QAVIFHandler::QAVIFHandler() : : m_parseState(ParseAvifNotParsed)
m_parseState(ParseAvifNotParsed), , m_quality(52)
m_quality(52), , m_container_width(0)
m_container_width(0), , m_container_height(0)
m_container_height(0), , m_rawAvifData(AVIF_DATA_EMPTY)
m_rawAvifData(AVIF_DATA_EMPTY), , m_decoder(nullptr)
m_decoder(nullptr), , m_must_jump_to_next_image(false)
m_must_jump_to_next_image(false)
{ {
} }
@ -96,7 +95,6 @@ bool QAVIFHandler::ensureDecoder()
return false; return false;
} }
m_decoder = avifDecoderCreate(); m_decoder = avifDecoderCreate();
avifResult decodeResult; avifResult decodeResult;
@ -124,7 +122,6 @@ bool QAVIFHandler::ensureDecoder()
decodeResult = avifDecoderNextImage(m_decoder); decodeResult = avifDecoderNextImage(m_decoder);
if (decodeResult == AVIF_RESULT_OK) { if (decodeResult == AVIF_RESULT_OK) {
m_container_width = m_decoder->image->width; m_container_width = m_decoder->image->width;
m_container_height = m_decoder->image->height; m_container_height = m_decoder->image->height;
@ -208,7 +205,6 @@ bool QAVIFHandler::decode_one_frame()
const QPointF bluePoint(QAVIFHandler::CompatibleChromacity(prim[4], prim[5])); const QPointF bluePoint(QAVIFHandler::CompatibleChromacity(prim[4], prim[5]));
const QPointF whitePoint(QAVIFHandler::CompatibleChromacity(prim[6], prim[7])); const QPointF whitePoint(QAVIFHandler::CompatibleChromacity(prim[6], prim[7]));
QColorSpace::TransferFunction q_trc = QColorSpace::TransferFunction::Custom; QColorSpace::TransferFunction q_trc = QColorSpace::TransferFunction::Custom;
float q_trc_gamma = 0.0f; float q_trc_gamma = 0.0f;
@ -235,7 +231,8 @@ bool QAVIFHandler::decode_one_frame()
break; break;
default: default:
qWarning("CICP colorPrimaries: %d, transferCharacteristics: %d\nThe colorspace is unsupported by this plug-in yet.", qWarning("CICP colorPrimaries: %d, transferCharacteristics: %d\nThe colorspace is unsupported by this plug-in yet.",
m_decoder->image->colorPrimaries, m_decoder->image->transferCharacteristics); m_decoder->image->colorPrimaries,
m_decoder->image->transferCharacteristics);
q_trc = QColorSpace::TransferFunction::SRgb; q_trc = QColorSpace::TransferFunction::SRgb;
break; break;
} }
@ -303,8 +300,8 @@ bool QAVIFHandler::decode_one_frame()
} }
if (m_decoder->image->transformFlags & AVIF_TRANSFORM_CLAP) { if (m_decoder->image->transformFlags & AVIF_TRANSFORM_CLAP) {
if ((m_decoder->image->clap.widthD > 0) && (m_decoder->image->clap.heightD > 0) && if ((m_decoder->image->clap.widthD > 0) && (m_decoder->image->clap.heightD > 0) && (m_decoder->image->clap.horizOffD > 0)
(m_decoder->image->clap.horizOffD > 0) && (m_decoder->image->clap.vertOffD > 0)) { && (m_decoder->image->clap.vertOffD > 0)) {
int new_width, new_height, offx, offy; int new_width, new_height, offx, offy;
new_width = (int)((double)(m_decoder->image->clap.widthN) / (m_decoder->image->clap.widthD) + 0.5); new_width = (int)((double)(m_decoder->image->clap.widthN) / (m_decoder->image->clap.widthD) + 0.5);
@ -318,17 +315,14 @@ bool QAVIFHandler::decode_one_frame()
} }
if (new_width > 0 && new_height > 0) { if (new_width > 0 && new_height > 0) {
offx = ((double)((int32_t)m_decoder->image->clap.horizOffN)) / (m_decoder->image->clap.horizOffD) + (result.width() - new_width) / 2.0 + 0.5;
offx = ((double)((int32_t) m_decoder->image->clap.horizOffN)) / (m_decoder->image->clap.horizOffD) +
(result.width() - new_width) / 2.0 + 0.5;
if (offx < 0) { if (offx < 0) {
offx = 0; offx = 0;
} else if (offx > (result.width() - new_width)) { } else if (offx > (result.width() - new_width)) {
offx = result.width() - new_width; offx = result.width() - new_width;
} }
offy = ((double)((int32_t) m_decoder->image->clap.vertOffN)) / (m_decoder->image->clap.vertOffD) + offy = ((double)((int32_t)m_decoder->image->clap.vertOffN)) / (m_decoder->image->clap.vertOffD) + (result.height() - new_height) / 2.0 + 0.5;
(result.height() - new_height) / 2.0 + 0.5;
if (offy < 0) { if (offy < 0) {
offy = 0; offy = 0;
} else if (offy > (result.height() - new_height)) { } else if (offy > (result.height() - new_height)) {
@ -496,7 +490,6 @@ bool QAVIFHandler::write(const QImage &image)
/* AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED */ /* AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED */
break; break;
} }
} }
if (save_depth > 8) { // QImage::Format_Grayscale16 if (save_depth > 8) { // QImage::Format_Grayscale16
@ -603,9 +596,7 @@ bool QAVIFHandler::write(const QImage &image)
} }
// in case primaries or trc were not identified // in case primaries or trc were not identified
if ((primaries_to_save == 2) || if ((primaries_to_save == 2) || (transfer_to_save == 2)) {
(transfer_to_save == 2)) {
// upgrade image to higher bit depth // upgrade image to higher bit depth
if (save_depth == 8) { if (save_depth == 8) {
save_depth = 10; save_depth = 10;
@ -616,8 +607,7 @@ bool QAVIFHandler::write(const QImage &image)
} }
} }
if ((primaries_to_save == 2) && if ((primaries_to_save == 2) && (transfer_to_save != 2)) { // other primaries but known trc
(transfer_to_save != 2)) { //other primaries but known trc
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709 primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709 matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
@ -636,8 +626,7 @@ bool QAVIFHandler::write(const QImage &image)
transfer_to_save = (avifTransferCharacteristics)13; transfer_to_save = (avifTransferCharacteristics)13;
break; break;
} }
} else if ((primaries_to_save != 2) && } else if ((primaries_to_save != 2) && (transfer_to_save == 2)) { // recognized primaries but other trc
(transfer_to_save == 2)) { //recognized primaries but other trc
transfer_to_save = (avifTransferCharacteristics)13; transfer_to_save = (avifTransferCharacteristics)13;
tmpcolorimage.convertToColorSpace(tmpcolorimage.colorSpace().withTransferFunction(QColorSpace::TransferFunction::SRgb)); tmpcolorimage.convertToColorSpace(tmpcolorimage.colorSpace().withTransferFunction(QColorSpace::TransferFunction::SRgb));
} else { // unrecognized profile } else { // unrecognized profile
@ -721,7 +710,6 @@ bool QAVIFHandler::write(const QImage &image)
return false; return false;
} }
QVariant QAVIFHandler::option(ImageOption option) const QVariant QAVIFHandler::option(ImageOption option) const
{ {
if (option == Quality) { if (option == Quality) {
@ -765,9 +753,7 @@ void QAVIFHandler::setOption(ImageOption option, const QVariant &value)
bool QAVIFHandler::supportsOption(ImageOption option) const bool QAVIFHandler::supportsOption(ImageOption option) const
{ {
return option == Quality return option == Quality || option == Size || option == Animation;
|| option == Size
|| option == Animation;
} }
int QAVIFHandler::imageCount() const int QAVIFHandler::imageCount() const
@ -817,11 +803,12 @@ bool QAVIFHandler::jumpToNextImage()
return false; return false;
} }
if ((m_container_width != m_decoder->image->width) || if ((m_container_width != m_decoder->image->width) || (m_container_height != m_decoder->image->height)) {
(m_container_height != m_decoder->image->height)) {
qWarning("Decoded image sequence size (%dx%d) do not match first image size (%dx%d)!", qWarning("Decoded image sequence size (%dx%d) do not match first image size (%dx%d)!",
m_decoder->image->width, m_decoder->image->height, m_decoder->image->width,
m_container_width, m_container_height); m_decoder->image->height,
m_container_width,
m_container_height);
m_parseState = ParseAvifError; m_parseState = ParseAvifError;
return false; return false;
@ -833,7 +820,6 @@ bool QAVIFHandler::jumpToNextImage()
m_parseState = ParseAvifError; m_parseState = ParseAvifError;
return false; return false;
} }
} }
bool QAVIFHandler::jumpToImage(int imageNumber) bool QAVIFHandler::jumpToImage(int imageNumber)
@ -866,11 +852,12 @@ bool QAVIFHandler::jumpToImage(int imageNumber)
return false; return false;
} }
if ((m_container_width != m_decoder->image->width) || if ((m_container_width != m_decoder->image->width) || (m_container_height != m_decoder->image->height)) {
(m_container_height != m_decoder->image->height)) {
qWarning("Decoded image sequence size (%dx%d) do not match declared container size (%dx%d)!", qWarning("Decoded image sequence size (%dx%d) do not match declared container size (%dx%d)!",
m_decoder->image->width, m_decoder->image->height, m_decoder->image->width,
m_container_width, m_container_height); m_decoder->image->height,
m_container_width,
m_container_height);
m_parseState = ParseAvifError; m_parseState = ParseAvifError;
return false; return false;

View File

@ -9,13 +9,13 @@
#ifndef KIMG_AVIF_P_H #ifndef KIMG_AVIF_P_H
#define KIMG_AVIF_P_H #define KIMG_AVIF_P_H
#include <QImage>
#include <QVariant>
#include <qimageiohandler.h>
#include <QImageIOPlugin>
#include <QByteArray> #include <QByteArray>
#include <QImage>
#include <QImageIOPlugin>
#include <QPointF> #include <QPointF>
#include <QVariant>
#include <avif/avif.h> #include <avif/avif.h>
#include <qimageiohandler.h>
class QAVIFHandler : public QImageIOHandler class QAVIFHandler : public QImageIOHandler
{ {
@ -41,14 +41,14 @@ public:
int nextImageDelay() const override; int nextImageDelay() const override;
int loopCount() const override; int loopCount() const override;
private: private:
static QPointF CompatibleChromacity(qreal chrX, qreal chrY); static QPointF CompatibleChromacity(qreal chrX, qreal chrY);
bool ensureParsed() const; bool ensureParsed() const;
bool ensureDecoder(); bool ensureDecoder();
bool decode_one_frame(); bool decode_one_frame();
enum ParseAvifState enum ParseAvifState {
{
ParseAvifError = -1, ParseAvifError = -1,
ParseAvifNotParsed = 0, ParseAvifNotParsed = 0,
ParseAvifSuccess = 1, ParseAvifSuccess = 1,

View File

@ -9,13 +9,13 @@
*/ */
#include "eps_p.h" #include "eps_p.h"
#include <QCoreApplication>
#include <QImage> #include <QImage>
#include <QImageReader> #include <QImageReader>
#include <QPainter> #include <QPainter>
#include <QPrinter> #include <QPrinter>
#include <QProcess> #include <QProcess>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QCoreApplication>
// logging category for this framework, default: log stuff >= warning // logging category for this framework, default: log stuff >= warning
Q_LOGGING_CATEGORY(EPSPLUGIN, "kf.imageformats.plugins.eps", QtWarningMsg) Q_LOGGING_CATEGORY(EPSPLUGIN, "kf.imageformats.plugins.eps", QtWarningMsg)
@ -51,19 +51,13 @@ static bool seekToCodeStart(QIODevice *io, qint64 &ps_offset, qint64 &ps_size)
return false; return false;
} }
ps_offset // Offset is in little endian ps_offset // Offset is in little endian
= qint64(((unsigned char)buf[0]) = qint64(((unsigned char)buf[0]) + ((unsigned char)buf[1] << 8) + ((unsigned char)buf[2] << 16) + ((unsigned char)buf[3] << 24));
+ ((unsigned char)buf[1] << 8)
+ ((unsigned char)buf[2] << 16)
+ ((unsigned char)buf[3] << 24));
if (io->read(buf, 4) != 4) { // Get size of PostScript code in the MS-DOS EPS file. if (io->read(buf, 4) != 4) { // Get size of PostScript code in the MS-DOS EPS file.
qCDebug(EPSPLUGIN) << "cannot read size of MS-DOS EPS file"; qCDebug(EPSPLUGIN) << "cannot read size of MS-DOS EPS file";
return false; return false;
} }
ps_size // Size is in little endian ps_size // Size is in little endian
= qint64(((unsigned char)buf[0]) = qint64(((unsigned char)buf[0]) + ((unsigned char)buf[1] << 8) + ((unsigned char)buf[2] << 16) + ((unsigned char)buf[3] << 24));
+ ((unsigned char)buf[1] << 8)
+ ((unsigned char)buf[2] << 16)
+ ((unsigned char)buf[3] << 24));
qCDebug(EPSPLUGIN) << "Offset: " << ps_offset << " Size: " << ps_size; qCDebug(EPSPLUGIN) << "Offset: " << ps_offset << " Size: " << ps_size;
if (!io->seek(ps_offset)) { // Get offset of PostScript code in the MS-DOS EPS file. if (!io->seek(ps_offset)) { // Get offset of PostScript code in the MS-DOS EPS file.
qCDebug(EPSPLUGIN) << "cannot seek in MS-DOS EPS file"; qCDebug(EPSPLUGIN) << "cannot seek in MS-DOS EPS file";
@ -101,8 +95,7 @@ static bool bbox(QIODevice *io, int *x1, int *y1, int *x2, int *y2)
// Some EPS files have non-integer values for the bbox // Some EPS files have non-integer values for the bbox
// We don't support that currently, but at least we parse it // We don't support that currently, but at least we parse it
float _x1, _y1, _x2, _y2; float _x1, _y1, _x2, _y2;
if (sscanf(buf, "%*s %f %f %f %f", if (sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) {
&_x1, &_y1, &_x2, &_y2) == 4) {
qCDebug(EPSPLUGIN) << "BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2; qCDebug(EPSPLUGIN) << "BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2;
*x1 = int(_x1); *x1 = int(_x1);
*y1 = int(_y1); *y1 = int(_y1);
@ -177,23 +170,17 @@ bool EPSHandler::read(QImage *image)
// create GS command line // create GS command line
QStringList gsArgs; QStringList gsArgs;
gsArgs << QLatin1String("-sOutputFile=") + tmpFile.fileName() gsArgs << QLatin1String("-sOutputFile=") + tmpFile.fileName() << QStringLiteral("-q") << QStringLiteral("-g%1x%2").arg(wantedWidth).arg(wantedHeight)
<< QStringLiteral("-q") << QStringLiteral("-dSAFER") << QStringLiteral("-dPARANOIDSAFER") << QStringLiteral("-dNOPAUSE") << QStringLiteral("-sDEVICE=ppm")
<< QStringLiteral("-g%1x%2").arg(wantedWidth).arg(wantedHeight)
<< QStringLiteral("-dSAFER")
<< QStringLiteral("-dPARANOIDSAFER")
<< QStringLiteral("-dNOPAUSE")
<< QStringLiteral("-sDEVICE=ppm")
<< QStringLiteral("-c") << QStringLiteral("-c")
<< QStringLiteral("0 0 moveto " << QStringLiteral(
"0 0 moveto "
"1000 0 lineto " "1000 0 lineto "
"1000 1000 lineto " "1000 1000 lineto "
"0 1000 lineto " "0 1000 lineto "
"1 1 254 255 div setrgbcolor fill " "1 1 254 255 div setrgbcolor fill "
"0 0 0 setrgbcolor") "0 0 0 setrgbcolor")
<< QStringLiteral("-") << QStringLiteral("-") << QStringLiteral("-c") << QStringLiteral("showpage quit");
<< QStringLiteral("-c")
<< QStringLiteral("showpage quit");
qCDebug(EPSPLUGIN) << "Running gs with args" << gsArgs; qCDebug(EPSPLUGIN) << "Running gs with args" << gsArgs;
QProcess converter; QProcess converter;
@ -277,24 +264,16 @@ bool EPSHandler::write(const QImage &image)
// pdftops comes with Poppler and produces much smaller EPS files than GhostScript // pdftops comes with Poppler and produces much smaller EPS files than GhostScript
QStringList pdftopsArgs; QStringList pdftopsArgs;
pdftopsArgs << QStringLiteral("-eps") pdftopsArgs << QStringLiteral("-eps") << tmpFile.fileName() << QStringLiteral("-");
<< tmpFile.fileName()
<< QStringLiteral("-");
qCDebug(EPSPLUGIN) << "Running pdftops with args" << pdftopsArgs; qCDebug(EPSPLUGIN) << "Running pdftops with args" << pdftopsArgs;
converter.start(QStringLiteral("pdftops"), pdftopsArgs); converter.start(QStringLiteral("pdftops"), pdftopsArgs);
if (!converter.waitForStarted()) { if (!converter.waitForStarted()) {
// GhostScript produces huge files, and takes a long time doing so // GhostScript produces huge files, and takes a long time doing so
QStringList gsArgs; QStringList gsArgs;
gsArgs << QStringLiteral("-q") << QStringLiteral("-P-") gsArgs << QStringLiteral("-q") << QStringLiteral("-P-") << QStringLiteral("-dNOPAUSE") << QStringLiteral("-dBATCH") << QStringLiteral("-dSAFER")
<< QStringLiteral("-dNOPAUSE") << QStringLiteral("-dBATCH") << QStringLiteral("-sDEVICE=epswrite") << QStringLiteral("-sOutputFile=-") << QStringLiteral("-c") << QStringLiteral("save")
<< QStringLiteral("-dSAFER") << QStringLiteral("pop") << QStringLiteral("-f") << tmpFile.fileName();
<< QStringLiteral("-sDEVICE=epswrite")
<< QStringLiteral("-sOutputFile=-")
<< QStringLiteral("-c")
<< QStringLiteral("save") << QStringLiteral("pop")
<< QStringLiteral("-f")
<< tmpFile.fileName();
qCDebug(EPSPLUGIN) << "Failed to start pdftops; trying gs with args" << gsArgs; qCDebug(EPSPLUGIN) << "Failed to start pdftops; trying gs with args" << gsArgs;
converter.start(QStringLiteral("gs"), gsArgs); converter.start(QStringLiteral("gs"), gsArgs);

View File

@ -35,4 +35,3 @@ public:
Q_DECLARE_LOGGING_CATEGORY(EPSPLUGIN) Q_DECLARE_LOGGING_CATEGORY(EPSPLUGIN)
#endif // KIMG_EPS_P_H #endif // KIMG_EPS_P_H

View File

@ -9,35 +9,36 @@
#include "exr_p.h" #include "exr_p.h"
#include <ImfRgbaFile.h> #include <IexThrowErrnoExc.h>
#include <ImfStandardAttributes.h>
#include <ImathBox.h> #include <ImathBox.h>
#include <ImfInputFile.h> #include <ImfArray.h>
#include <ImfBoxAttribute.h> #include <ImfBoxAttribute.h>
#include <ImfChannelListAttribute.h> #include <ImfChannelListAttribute.h>
#include <ImfCompressionAttribute.h> #include <ImfCompressionAttribute.h>
#include <ImfConvert.h>
#include <ImfFloatAttribute.h> #include <ImfFloatAttribute.h>
#include <ImfInputFile.h>
#include <ImfIntAttribute.h> #include <ImfIntAttribute.h>
#include <ImfLineOrderAttribute.h> #include <ImfLineOrderAttribute.h>
#include <ImfRgbaFile.h>
#include <ImfStandardAttributes.h>
#include <ImfStringAttribute.h> #include <ImfStringAttribute.h>
#include <ImfVecAttribute.h> #include <ImfVecAttribute.h>
#include <ImfArray.h>
#include <ImfConvert.h>
#include <ImfVersion.h> #include <ImfVersion.h>
#include <IexThrowErrnoExc.h>
#include <iostream> #include <iostream>
#include <QImage>
#include <QDataStream> #include <QDataStream>
#include <QDebug> #include <QDebug>
#include <QImage>
#include <QImageIOPlugin> #include <QImageIOPlugin>
class K_IStream : public Imf::IStream class K_IStream : public Imf::IStream
{ {
public: public:
K_IStream(QIODevice *dev, const QByteArray &fileName): K_IStream(QIODevice *dev, const QByteArray &fileName)
IStream(fileName.data()), m_dev(dev) : IStream(fileName.data())
, m_dev(dev)
{ {
} }

View File

@ -44,7 +44,6 @@ typedef enum {
INDEXED, INDEXED,
} GimpImageBaseType; } GimpImageBaseType;
// From GIMP "libgimp/gimpenums.h" v2.4 // From GIMP "libgimp/gimpenums.h" v2.4
//! Effect to apply when layers are merged together. //! Effect to apply when layers are merged together.
@ -74,7 +73,6 @@ typedef enum {
GRAIN_MERGE_MODE GRAIN_MERGE_MODE
} LayerModeEffects; } LayerModeEffects;
// From GIMP "paint_funcs.c" v1.2 // From GIMP "paint_funcs.c" v1.2
/*! /*!

View File

@ -8,8 +8,8 @@
#include "hdr_p.h" #include "hdr_p.h"
#include <QImage>
#include <QDataStream> #include <QDataStream>
#include <QImage>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QRegularExpressionMatch> #include <QRegularExpressionMatch>
@ -21,7 +21,6 @@ Q_LOGGING_CATEGORY(HDRPLUGIN, "kf.imageformats.plugins.hdr", QtWarningMsg)
namespace // Private. namespace // Private.
{ {
#define MAXLINE 1024 #define MAXLINE 1024
#define MINELEN 8 // minimum scanline length for encoding #define MINELEN 8 // minimum scanline length for encoding
#define MAXELEN 0x7fff // maximum scanline length for encoding #define MAXELEN 0x7fff // maximum scanline length for encoding
@ -81,9 +80,7 @@ static void RGBE_To_QRgbLine(uchar *image, QRgb *scanline, int width)
v = 1.0f / float(1 << -e); v = 1.0f / float(1 << -e);
} }
scanline[j] = qRgb(ClipToByte(float(image[0]) * v), scanline[j] = qRgb(ClipToByte(float(image[0]) * v), ClipToByte(float(image[1]) * v), ClipToByte(float(image[2]) * v));
ClipToByte(float(image[1]) * v),
ClipToByte(float(image[2]) * v));
image += 4; image += 4;
} }
@ -228,8 +225,7 @@ bool HDRHandler::read(QImage *outImage)
return false; return false;
} }
if ( (match.captured(1).at(1) != u'Y') || if ((match.captured(1).at(1) != u'Y') || (match.captured(3).at(1) != u'X')) {
(match.captured(3).at(1) != u'X') ) {
qCDebug(HDRPLUGIN) << "Unsupported image orientation in HDR file."; qCDebug(HDRPLUGIN) << "Unsupported image orientation in HDR file.";
return false; return false;
} }

View File

@ -10,17 +10,19 @@
#include "heif_p.h" #include "heif_p.h"
#include "libheif/heif_cxx.h" #include "libheif/heif_cxx.h"
#include <QPointF>
#include <QColorSpace> #include <QColorSpace>
#include <QDebug> #include <QDebug>
#include <QPointF>
#include <QSysInfo> #include <QSysInfo>
#include <string.h> #include <string.h>
namespace // Private. namespace // Private.
{ {
struct HeifQIODeviceWriter : public heif::Context::Writer { struct HeifQIODeviceWriter : public heif::Context::Writer {
HeifQIODeviceWriter(QIODevice *device) : m_ioDevice(device) {} HeifQIODeviceWriter(QIODevice *device)
: m_ioDevice(device)
{
}
heif_error write(const void *data, size_t size) override heif_error write(const void *data, size_t size) override
{ {
@ -49,9 +51,9 @@ private:
} // namespace } // namespace
HEIFHandler::HEIFHandler() : HEIFHandler::HEIFHandler()
m_parseState(ParseHeicNotParsed), : m_parseState(ParseHeicNotParsed)
m_quality(100) , m_quality(100)
{ {
} }
@ -126,7 +128,6 @@ bool HEIFHandler::write(const QImage &image)
tmpformat = QImage::Format_RGB888; tmpformat = QImage::Format_RGB888;
chroma = heif_chroma_interleaved_RGB; chroma = heif_chroma_interleaved_RGB;
} }
} }
const QImage tmpimage = image.convertToFormat(tmpformat); const QImage tmpimage = image.convertToFormat(tmpformat);
@ -342,8 +343,7 @@ void HEIFHandler::setOption(ImageOption option, const QVariant &value)
bool HEIFHandler::supportsOption(ImageOption option) const bool HEIFHandler::supportsOption(ImageOption option) const
{ {
return option == Quality return option == Quality || option == Size;
|| option == Size;
} }
bool HEIFHandler::ensureParsed() const bool HEIFHandler::ensureParsed() const
@ -376,8 +376,7 @@ bool HEIFHandler::ensureDecoder()
try { try {
heif::Context ctx; heif::Context ctx;
ctx.read_from_memory_without_copy((const void *)(buffer.constData()), ctx.read_from_memory_without_copy((const void *)(buffer.constData()), buffer.size());
buffer.size());
heif::ImageHandle handle = ctx.get_primary_image_handle(); heif::ImageHandle handle = ctx.get_primary_image_handle();
@ -413,7 +412,6 @@ bool HEIFHandler::ensureDecoder()
return false; return false;
} }
heif::Image img = handle.decode_image(heif_colorspace_RGB, chroma); heif::Image img = handle.decode_image(heif_colorspace_RGB, chroma);
const int imageWidth = img.get_width(heif_channel_interleaved); const int imageWidth = img.get_width(heif_channel_interleaved);
@ -598,7 +596,6 @@ bool HEIFHandler::ensureDecoder()
dest_pixel++; dest_pixel++;
} }
} }
} }
break; break;
default: default:
@ -659,7 +656,8 @@ bool HEIFHandler::ensureDecoder()
break; break;
default: default:
qWarning("CICP color_primaries: %d, transfer_characteristics: %d\nThe colorspace is unsupported by this plug-in yet.", qWarning("CICP color_primaries: %d, transfer_characteristics: %d\nThe colorspace is unsupported by this plug-in yet.",
nclx->color_primaries, nclx->transfer_characteristics); nclx->color_primaries,
nclx->transfer_characteristics);
q_trc = QColorSpace::TransferFunction::SRgb; q_trc = QColorSpace::TransferFunction::SRgb;
break; break;
} }
@ -683,7 +681,6 @@ bool HEIFHandler::ensureDecoder()
if (!m_current_image.colorSpace().isValid()) { if (!m_current_image.colorSpace().isValid()) {
qWarning() << "invalid color profile created from NCLX"; qWarning() << "invalid color profile created from NCLX";
} }
} }
} else { } else {

View File

@ -28,6 +28,7 @@ public:
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override; void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override; bool supportsOption(ImageOption option) const override;
private: private:
static bool isSupportedBMFFType(const QByteArray &header); static bool isSupportedBMFFType(const QByteArray &header);
bool ensureParsed() const; bool ensureParsed() const;

View File

@ -12,9 +12,9 @@
#include <kzip.h> #include <kzip.h>
#include <QImage>
#include <QIODevice>
#include <QFile> #include <QFile>
#include <QIODevice>
#include <QImage>
static constexpr char s_magic[] = "application/x-krita"; static constexpr char s_magic[] = "application/x-krita";
static constexpr int s_magic_size = sizeof(s_magic) - 1; // -1 to remove the last \0 static constexpr int s_magic_size = sizeof(s_magic) - 1; // -1 to remove the last \0
@ -35,10 +35,12 @@ bool KraHandler::canRead() const
bool KraHandler::read(QImage *image) bool KraHandler::read(QImage *image)
{ {
KZip zip(device()); KZip zip(device());
if (!zip.open(QIODevice::ReadOnly)) return false; if (!zip.open(QIODevice::ReadOnly))
return false;
const KArchiveEntry *entry = zip.directory()->entry(QStringLiteral("mergedimage.png")); const KArchiveEntry *entry = zip.directory()->entry(QStringLiteral("mergedimage.png"));
if (!entry || !entry->isFile()) return false; if (!entry || !entry->isFile())
return false;
const KZipFileEntry *fileZipEntry = static_cast<const KZipFileEntry *>(entry); const KZipFileEntry *fileZipEntry = static_cast<const KZipFileEntry *>(entry);

View File

@ -31,6 +31,4 @@ public:
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
}; };
#endif #endif

View File

@ -34,10 +34,12 @@ bool OraHandler::canRead() const
bool OraHandler::read(QImage *image) bool OraHandler::read(QImage *image)
{ {
KZip zip(device()); KZip zip(device());
if (!zip.open(QIODevice::ReadOnly)) return false; if (!zip.open(QIODevice::ReadOnly))
return false;
const KArchiveEntry *entry = zip.directory()->entry(QStringLiteral("mergedimage.png")); const KArchiveEntry *entry = zip.directory()->entry(QStringLiteral("mergedimage.png"));
if (!entry || !entry->isFile()) return false; if (!entry || !entry->isFile())
return false;
const KZipFileEntry *fileZipEntry = static_cast<const KZipFileEntry *>(entry); const KZipFileEntry *fileZipEntry = static_cast<const KZipFileEntry *>(entry);

View File

@ -21,7 +21,6 @@ public:
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
}; };
class OraPlugin : public QImageIOPlugin class OraPlugin : public QImageIOPlugin
{ {
Q_OBJECT Q_OBJECT
@ -31,6 +30,4 @@ public:
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
}; };
#endif #endif

View File

@ -12,7 +12,6 @@
#include <QDebug> #include <QDebug>
#include <QImage> #include <QImage>
#pragma pack(push, 1) #pragma pack(push, 1)
class RGB class RGB
{ {
@ -29,7 +28,6 @@ public:
c.b = qBlue(color); c.b = qBlue(color);
return c; return c;
} }
}; };
class Palette class Palette
@ -151,12 +149,16 @@ static QDataStream &operator>>(QDataStream &s, PCXHEADER &ph)
ph.Reserved = res; ph.Reserved = res;
ph.NPlanes = np; ph.NPlanes = np;
quint16 bytesperline; quint16 bytesperline;
s >> bytesperline; ph.BytesPerLine = bytesperline; s >> bytesperline;
ph.BytesPerLine = bytesperline;
quint16 paletteinfo; quint16 paletteinfo;
s >> paletteinfo; ph.PaletteInfo = paletteinfo; s >> paletteinfo;
ph.PaletteInfo = paletteinfo;
quint16 hscreensize, vscreensize; quint16 hscreensize, vscreensize;
s >> hscreensize; ph.HScreenSize = hscreensize; s >> hscreensize;
s >> vscreensize; ph.VScreenSize = vscreensize; ph.HScreenSize = hscreensize;
s >> vscreensize;
ph.VScreenSize = vscreensize;
// Skip the rest of the header // Skip the rest of the header
quint8 byte; quint8 byte;

View File

@ -21,9 +21,9 @@
#include <QDebug> #include <QDebug>
#include <QImage> #include <QImage>
#include <QVariant> #include <QVariant>
#include <qendian.h>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <qendian.h>
/** /**
* Reads a PIC file header from a data stream. * Reads a PIC file header from a data stream.
@ -181,15 +181,13 @@ static bool readRow(QDataStream &stream, QRgb *row, quint16 width, const QList<P
return qRgba(red, green, blue, alpha); return qRgba(red, green, blue, alpha);
}; };
auto updatePixel = [&](QRgb oldPixel, QRgb newPixel) -> QRgb { auto updatePixel = [&](QRgb oldPixel, QRgb newPixel) -> QRgb {
return qRgba( return qRgba(qRed((channel.code & RED) ? newPixel : oldPixel),
qRed((channel.code & RED) ? newPixel : oldPixel),
qGreen((channel.code & GREEN) ? newPixel : oldPixel), qGreen((channel.code & GREEN) ? newPixel : oldPixel),
qBlue((channel.code & BLUE) ? newPixel : oldPixel), qBlue((channel.code & BLUE) ? newPixel : oldPixel),
qAlpha((channel.code & ALPHA) ? newPixel : oldPixel)); qAlpha((channel.code & ALPHA) ? newPixel : oldPixel));
}; };
if (channel.encoding == MixedRLE) { if (channel.encoding == MixedRLE) {
bool success = decodeRLEData(RLEVariant::PIC, stream, row, width, bool success = decodeRLEData(RLEVariant::PIC, stream, row, width, readPixel, updatePixel);
readPixel, updatePixel);
if (!success) { if (!success) {
qDebug() << "decodeRLEData failed"; qDebug() << "decodeRLEData failed";
return false; return false;
@ -265,9 +263,7 @@ bool SoftimagePICHandler::read(QImage *image)
bool SoftimagePICHandler::write(const QImage &_image) bool SoftimagePICHandler::write(const QImage &_image)
{ {
bool alpha = _image.hasAlphaChannel(); bool alpha = _image.hasAlphaChannel();
const QImage image = _image.convertToFormat( const QImage image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
alpha ? QImage::Format_ARGB32
: QImage::Format_RGB32);
if (image.width() < 0 || image.height() < 0) { if (image.width() < 0 || image.height() < 0) {
qDebug() << "Image size invalid:" << image.width() << image.height(); qDebug() << "Image size invalid:" << image.width() << image.height();
@ -296,18 +292,13 @@ bool SoftimagePICHandler::write(const QImage &_image)
/* Write the RGB part of the scanline */ /* Write the RGB part of the scanline */
auto rgbEqual = [](QRgb p1, QRgb p2) -> bool { auto rgbEqual = [](QRgb p1, QRgb p2) -> bool {
return qRed(p1) == qRed(p2) && return qRed(p1) == qRed(p2) && qGreen(p1) == qGreen(p2) && qBlue(p1) == qBlue(p2);
qGreen(p1) == qGreen(p2) &&
qBlue(p1) == qBlue(p2);
}; };
auto writeRgb = [](QDataStream &str, QRgb pixel) -> void { auto writeRgb = [](QDataStream &str, QRgb pixel) -> void {
str << quint8(qRed(pixel)) str << quint8(qRed(pixel)) << quint8(qGreen(pixel)) << quint8(qBlue(pixel));
<< quint8(qGreen(pixel))
<< quint8(qBlue(pixel));
}; };
if (m_compression) { if (m_compression) {
encodeRLEData(RLEVariant::PIC, stream, row, image.width(), encodeRLEData(RLEVariant::PIC, stream, row, image.width(), rgbEqual, writeRgb);
rgbEqual, writeRgb);
} else { } else {
for (int i = 0; i < image.width(); ++i) { for (int i = 0; i < image.width(); ++i) {
writeRgb(stream, row[i]); writeRgb(stream, row[i]);
@ -323,8 +314,7 @@ bool SoftimagePICHandler::write(const QImage &_image)
str << quint8(qAlpha(pixel)); str << quint8(qAlpha(pixel));
}; };
if (m_compression) { if (m_compression) {
encodeRLEData(RLEVariant::PIC, stream, row, image.width(), encodeRLEData(RLEVariant::PIC, stream, row, image.width(), alphaEqual, writeAlpha);
alphaEqual, writeAlpha);
} else { } else {
for (int i = 0; i < image.width(); ++i) { for (int i = 0; i < image.width(); ++i) {
writeAlpha(stream, row[i]); writeAlpha(stream, row[i]);
@ -408,9 +398,7 @@ QVariant SoftimagePICHandler::option(ImageOption option) const
if (const_cast<SoftimagePICHandler *>(this)->readHeader()) { if (const_cast<SoftimagePICHandler *>(this)->readHeader()) {
QString descStr = QString::fromUtf8(m_header.comment); QString descStr = QString::fromUtf8(m_header.comment);
if (!descStr.isEmpty()) { if (!descStr.isEmpty()) {
return QString(QStringLiteral("Description: ") + return QString(QStringLiteral("Description: ") + descStr + QStringLiteral("\n\n"));
descStr +
QStringLiteral("\n\n"));
} }
} }
return QString(); return QString();
@ -431,10 +419,7 @@ QVariant SoftimagePICHandler::option(ImageOption option) const
bool SoftimagePICHandler::supportsOption(ImageOption option) const bool SoftimagePICHandler::supportsOption(ImageOption option) const
{ {
return (option == CompressionRatio || return (option == CompressionRatio || option == Description || option == ImageFormat || option == Size);
option == Description ||
option == ImageFormat ||
option == Size);
} }
QImageIOPlugin::Capabilities SoftimagePICPlugin::capabilities(QIODevice *device, const QByteArray &format) const QImageIOPlugin::Capabilities SoftimagePICPlugin::capabilities(QIODevice *device, const QByteArray &format) const

View File

@ -8,8 +8,8 @@
#ifndef KIMG_PIC_P_H #ifndef KIMG_PIC_P_H
#define KIMG_PIC_P_H #define KIMG_PIC_P_H
#include <QImageIOPlugin>
#include <QDataStream> #include <QDataStream>
#include <QImageIOPlugin>
/** /**
* The magic number at the start of a SoftImage PIC file. * The magic number at the start of a SoftImage PIC file.
@ -70,9 +70,12 @@ struct PicHeader {
, height(_height) , height(_height)
, ratio(1.0f) , ratio(1.0f)
, fields(BothScanlines) , fields(BothScanlines)
{} {
}
/** Construct an invalid header. */ /** Construct an invalid header. */
PicHeader() {} PicHeader()
{
}
quint32 magic; /**< Should be PIC_MAGIC_NUMBER */ quint32 magic; /**< Should be PIC_MAGIC_NUMBER */
float version; /**< Version of something (header? file format?) (ignored) */ float version; /**< Version of something (header? file format?) (ignored) */
@ -88,9 +91,9 @@ struct PicHeader {
/** /**
* Returns true if the @p magic and @p id fields are set correctly. * Returns true if the @p magic and @p id fields are set correctly.
*/ */
bool isValid() const { bool isValid() const
return magic == PIC_MAGIC_NUMBER {
&& id == "PICT"; return magic == PIC_MAGIC_NUMBER && id == "PICT";
} }
/** /**
@ -123,7 +126,8 @@ struct PicChannel {
: size(_size) : size(_size)
, encoding(_encoding) , encoding(_encoding)
, code(_code) , code(_code)
{} {
}
/** /**
* Constructs a default channel description for a SoftImage PIC file. * Constructs a default channel description for a SoftImage PIC file.
* *
@ -135,7 +139,8 @@ struct PicChannel {
*/ */
PicChannel() PicChannel()
: size(8) : size(8)
{} {
}
}; };
class SoftimagePICHandler : public QImageIOHandler class SoftimagePICHandler : public QImageIOHandler
@ -161,7 +166,8 @@ public:
SoftimagePICHandler() SoftimagePICHandler()
: m_state(Ready) : m_state(Ready)
, m_compression(true) , m_compression(true)
{} {
}
bool readHeader(); bool readHeader();
bool readChannels(); bool readChannels();

View File

@ -31,7 +31,6 @@ typedef quint8 uchar;
namespace // Private. namespace // Private.
{ {
enum ColorMode { enum ColorMode {
CM_BITMAP = 0, CM_BITMAP = 0,
CM_GRAYSCALE = 1, CM_GRAYSCALE = 1,
@ -105,22 +104,27 @@ static void skip_section(QDataStream &s)
} }
template<class Trait> template<class Trait>
static Trait readPixel(QDataStream &stream) { static Trait readPixel(QDataStream &stream)
{
Trait pixel; Trait pixel;
stream >> pixel; stream >> pixel;
return pixel; return pixel;
} }
static QRgb updateRed(QRgb oldPixel, quint8 redPixel) { static QRgb updateRed(QRgb oldPixel, quint8 redPixel)
{
return qRgba(redPixel, qGreen(oldPixel), qBlue(oldPixel), qAlpha(oldPixel)); return qRgba(redPixel, qGreen(oldPixel), qBlue(oldPixel), qAlpha(oldPixel));
} }
static QRgb updateGreen(QRgb oldPixel, quint8 greenPixel) { static QRgb updateGreen(QRgb oldPixel, quint8 greenPixel)
{
return qRgba(qRed(oldPixel), greenPixel, qBlue(oldPixel), qAlpha(oldPixel)); return qRgba(qRed(oldPixel), greenPixel, qBlue(oldPixel), qAlpha(oldPixel));
} }
static QRgb updateBlue(QRgb oldPixel, quint8 bluePixel) { static QRgb updateBlue(QRgb oldPixel, quint8 bluePixel)
{
return qRgba(qRed(oldPixel), qGreen(oldPixel), bluePixel, qAlpha(oldPixel)); return qRgba(qRed(oldPixel), qGreen(oldPixel), bluePixel, qAlpha(oldPixel));
} }
static QRgb updateAlpha(QRgb oldPixel, quint8 alphaPixel) { static QRgb updateAlpha(QRgb oldPixel, quint8 alphaPixel)
{
return qRgba(qRed(oldPixel), qGreen(oldPixel), qBlue(oldPixel), alphaPixel); return qRgba(qRed(oldPixel), qGreen(oldPixel), qBlue(oldPixel), alphaPixel);
} }
typedef QRgb (*channelUpdater)(QRgb, quint8); typedef QRgb (*channelUpdater)(QRgb, quint8);
@ -151,13 +155,11 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
quint32 channel_num = header.channel_count; quint32 channel_num = header.channel_count;
QImage::Format fmt = header.depth == 8 ? QImage::Format_RGB32 QImage::Format fmt = header.depth == 8 ? QImage::Format_RGB32 : QImage::Format_RGBX64;
: QImage::Format_RGBX64;
// Clear the image. // Clear the image.
if (channel_num >= 4) { if (channel_num >= 4) {
// Enable alpha. // Enable alpha.
fmt = header.depth == 8 ? QImage::Format_ARGB32 fmt = header.depth == 8 ? QImage::Format_ARGB32 : QImage::Format_RGBA64;
: QImage::Format_RGBA64;
// Ignore the other channels. // Ignore the other channels.
channel_num = 4; channel_num = 4;
@ -185,20 +187,21 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
return false; return false;
} }
static const channelUpdater updaters[4] = { static const channelUpdater updaters[4] = {updateRed, updateGreen, updateBlue, updateAlpha};
updateRed,
updateGreen,
updateBlue,
updateAlpha
};
typedef QRgba64 (*channelUpdater16)(QRgba64, quint16); typedef QRgba64 (*channelUpdater16)(QRgba64, quint16);
static const channelUpdater16 updaters64[4] = { static const channelUpdater16 updaters64[4] = {[](QRgba64 oldPixel, quint16 redPixel) {
[](QRgba64 oldPixel, quint16 redPixel) {return qRgba64((oldPixel & ~(0xFFFFull << 0)) | (quint64( redPixel) << 0));}, return qRgba64((oldPixel & ~(0xFFFFull << 0)) | (quint64(redPixel) << 0));
[](QRgba64 oldPixel, quint16 greenPixel){return qRgba64((oldPixel & ~(0xFFFFull << 16)) | (quint64(greenPixel) << 16));}, },
[](QRgba64 oldPixel, quint16 bluePixel) {return qRgba64((oldPixel & ~(0xFFFFull << 32)) | (quint64( bluePixel) << 32));}, [](QRgba64 oldPixel, quint16 greenPixel) {
[](QRgba64 oldPixel, quint16 alphaPixel){return qRgba64((oldPixel & ~(0xFFFFull << 48)) | (quint64(alphaPixel) << 48));} return qRgba64((oldPixel & ~(0xFFFFull << 16)) | (quint64(greenPixel) << 16));
}; },
[](QRgba64 oldPixel, quint16 bluePixel) {
return qRgba64((oldPixel & ~(0xFFFFull << 32)) | (quint64(bluePixel) << 32));
},
[](QRgba64 oldPixel, quint16 alphaPixel) {
return qRgba64((oldPixel & ~(0xFFFFull << 48)) | (quint64(alphaPixel) << 48));
}};
if (compression) { if (compression) {
// Skip row lengths. // Skip row lengths.
@ -210,14 +213,10 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
for (unsigned short channel = 0; channel < channel_num; channel++) { for (unsigned short channel = 0; channel < channel_num; channel++) {
bool success = false; bool success = false;
if (header.depth == 8) { if (header.depth == 8) {
success = decodeRLEData(RLEVariant::PackBits, stream, success = decodeRLEData(RLEVariant::PackBits, stream, image_data, channel_size, &readPixel<quint8>, updaters[channel]);
image_data, channel_size,
&readPixel<quint8>, updaters[channel]);
} else if (header.depth == 16) { } else if (header.depth == 16) {
QRgba64 *image_data = reinterpret_cast<QRgba64 *>(img.bits()); QRgba64 *image_data = reinterpret_cast<QRgba64 *>(img.bits());
success = decodeRLEData(RLEVariant::PackBits16, stream, success = decodeRLEData(RLEVariant::PackBits16, stream, image_data, channel_size, &readPixel<quint8>, updaters64[channel]);
image_data, channel_size,
&readPixel<quint8>, updaters64[channel]);
} }
if (!success) { if (!success) {

View File

@ -32,4 +32,3 @@ public:
}; };
#endif // KIMG_PSD_P_H #endif // KIMG_PSD_P_H

View File

@ -9,9 +9,9 @@
#include "ras_p.h" #include "ras_p.h"
#include <QImage>
#include <QDataStream> #include <QDataStream>
#include <QDebug> #include <QDebug>
#include <QImage>
namespace // Private. namespace // Private.
{ {
@ -46,7 +46,9 @@ struct RasHeader {
quint32 Type; quint32 Type;
quint32 ColorMapType; quint32 ColorMapType;
quint32 ColorMapLength; quint32 ColorMapLength;
enum { SIZE = 32, }; // 8 fields of four bytes each enum {
SIZE = 32,
}; // 8 fields of four bytes each
}; };
static QDataStream &operator>>(QDataStream &s, RasHeader &head) static QDataStream &operator>>(QDataStream &s, RasHeader &head)
@ -79,8 +81,7 @@ static bool IsSupported(const RasHeader &head)
// check for an appropriate depth // check for an appropriate depth
// we support 8bit+palette, 24bit and 32bit ONLY! // we support 8bit+palette, 24bit and 32bit ONLY!
// TODO: add support for 1bit // TODO: add support for 1bit
if (!((head.Depth == 8 && head.ColorMapType == 1) if (!((head.Depth == 8 && head.ColorMapType == 1) || head.Depth == 24 || head.Depth == 32)) {
|| head.Depth == 24 || head.Depth == 32)) {
return false; return false;
} }
// the Type field adds support for RLE(BGR), RGB and other encodings // the Type field adds support for RLE(BGR), RGB and other encodings
@ -168,7 +169,6 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
img.setPixel(x, y, qRgb(red, green, blue)); img.setPixel(x, y, qRgb(red, green, blue));
} }
} }
} }
if (ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) { if (ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) {
@ -306,7 +306,6 @@ bool RASHandler::read(QImage *outImage)
QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{ {
if (format == "ras") { if (format == "ras") {
return Capabilities(CanRead); return Capabilities(CanRead);
} }

View File

@ -24,14 +24,17 @@
#include <QMap> #include <QMap>
#include <QVector> #include <QVector>
#include <QImage>
#include <QDebug> #include <QDebug>
#include <QImage>
class RLEData : public QVector<uchar> class RLEData : public QVector<uchar>
{ {
public: public:
RLEData() {} RLEData()
RLEData(const uchar *d, uint l, uint o) : _offset(o) {
}
RLEData(const uchar *d, uint l, uint o)
: _offset(o)
{ {
for (uint i = 0; i < l; i++) { for (uint i = 0; i < l; i++) {
append(d[i]); append(d[i]);
@ -51,7 +54,11 @@ private:
class RLEMap : public QMap<RLEData, uint> class RLEMap : public QMap<RLEData, uint>
{ {
public: public:
RLEMap() : _counter(0), _offset(0) {} RLEMap()
: _counter(0)
, _offset(0)
{
}
uint insert(const uchar *d, uint l); uint insert(const uchar *d, uint l);
QVector<const RLEData *> vector(); QVector<const RLEData *> vector();
void setBaseOffset(uint o) void setBaseOffset(uint o)
@ -74,7 +81,12 @@ public:
bool writeImage(const QImage &); bool writeImage(const QImage &);
private: private:
enum { NORMAL, DITHERED, SCREEN, COLORMAP, }; // colormap enum {
NORMAL,
DITHERED,
SCREEN,
COLORMAP,
}; // colormap
QIODevice *_dev; QIODevice *_dev;
QDataStream _stream; QDataStream _stream;
@ -108,9 +120,9 @@ private:
uchar intensity(uchar); uchar intensity(uchar);
}; };
SGIImage::SGIImage(QIODevice *io) : SGIImage::SGIImage(QIODevice *io)
_starttab(nullptr), : _starttab(nullptr)
_lengthtab(nullptr) , _lengthtab(nullptr)
{ {
_dev = io; _dev = io;
_stream.setDevice(_dev); _stream.setDevice(_dev);
@ -746,8 +758,7 @@ bool RGBHandler::canRead(QIODevice *device)
QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{ {
if (format == "rgb" || format == "rgba" || if (format == "rgb" || format == "rgba" || format == "bw" || format == "sgi") {
format == "bw" || format == "sgi") {
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
} }
if (!format.isEmpty()) { if (!format.isEmpty()) {

View File

@ -33,4 +33,3 @@ public:
}; };
#endif // KIMG_RGB_P_H #endif // KIMG_RGB_P_H

View File

@ -8,8 +8,8 @@
#ifndef KIMAGEFORMATS_RLE_P_H #ifndef KIMAGEFORMATS_RLE_P_H
#define KIMAGEFORMATS_RLE_P_H #define KIMAGEFORMATS_RLE_P_H
#include <QDebug>
#include <QDataStream> #include <QDataStream>
#include <QDebug>
/** /**
* The RLEVariant to use. * The RLEVariant to use.
@ -64,12 +64,7 @@ enum class RLEVariant {
* into @p buf, @c false otherwise. * into @p buf, @c false otherwise.
*/ */
template<typename Item, typename Func1, typename Func2> template<typename Item, typename Func1, typename Func2>
static inline bool decodeRLEData(RLEVariant variant, static inline bool decodeRLEData(RLEVariant variant, QDataStream &stream, Item *dest, quint32 length, Func1 readData, Func2 updateItem)
QDataStream &stream,
Item *dest,
quint32 length,
Func1 readData,
Func2 updateItem)
{ {
unsigned offset = 0; // in dest unsigned offset = 0; // in dest
bool is_msb = true; // only used for 16-bit PackBits, data is big-endian bool is_msb = true; // only used for 16-bit PackBits, data is big-endian
@ -154,7 +149,6 @@ static inline bool decodeRLEData(RLEVariant variant,
return stream.status() == QDataStream::Ok; return stream.status() == QDataStream::Ok;
} }
/** /**
* Encodes data in run-length encoding format. * Encodes data in run-length encoding format.
* *
@ -170,18 +164,10 @@ static inline bool decodeRLEData(RLEVariant variant,
* and writes the item to the data stream. * and writes the item to the data stream.
*/ */
template<typename Item, typename Func1, typename Func2> template<typename Item, typename Func1, typename Func2>
static inline void encodeRLEData(RLEVariant variant, static inline void encodeRLEData(RLEVariant variant, QDataStream &stream, const Item *data, unsigned length, Func1 itemsEqual, Func2 writeItem)
QDataStream &stream,
const Item *data,
unsigned length,
Func1 itemsEqual,
Func2 writeItem)
{ {
unsigned offset = 0; unsigned offset = 0;
const unsigned maxEncodableChunk = const unsigned maxEncodableChunk = (variant == RLEVariant::PIC) ? 65535u : 128;
(variant == RLEVariant::PIC)
? 65535u
: 128;
while (offset < length) { while (offset < length) {
const Item *chunkStart = data + offset; const Item *chunkStart = data + offset;
unsigned maxChunk = qMin(length - offset, maxEncodableChunk); unsigned maxChunk = qMin(length - offset, maxEncodableChunk);
@ -220,10 +206,7 @@ static inline void encodeRLEData(RLEVariant variant,
} }
chunkLength = 1; chunkLength = 1;
chunkEnd = chunkStart + 1; chunkEnd = chunkStart + 1;
while (chunkLength < maxChunk && while (chunkLength < maxChunk && (chunkLength + 1u == maxChunk || !itemsEqual(*chunkEnd, *(chunkEnd + 1)))) {
(chunkLength + 1u == maxChunk ||
!itemsEqual(*chunkEnd, *(chunkEnd+1))))
{
++chunkEnd; ++chunkEnd;
++chunkLength; ++chunkLength;
} }

View File

@ -20,9 +20,9 @@
#include <assert.h> #include <assert.h>
#include <QImage>
#include <QDataStream> #include <QDataStream>
#include <QDebug> #include <QDebug>
#include <QImage>
typedef quint32 uint; typedef quint32 uint;
typedef quint16 ushort; typedef quint16 ushort;
@ -30,7 +30,6 @@ typedef quint8 uchar;
namespace // Private. namespace // Private.
{ {
// Header format of saved files. // Header format of saved files.
uchar targaMagic[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uchar targaMagic[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -69,7 +68,9 @@ struct TgaHeader {
uchar pixel_size; uchar pixel_size;
uchar flags; uchar flags;
enum { SIZE = 18, }; // const static int SIZE = 18; enum {
SIZE = 18,
}; // const static int SIZE = 18;
}; };
static QDataStream &operator>>(QDataStream &s, TgaHeader &head) static QDataStream &operator>>(QDataStream &s, TgaHeader &head)
@ -88,30 +89,23 @@ static QDataStream &operator>> (QDataStream &s, TgaHeader &head)
s >> head.flags; s >> head.flags;
/*qDebug() << "id_length: " << head.id_length << " - colormap_type: " << head.colormap_type << " - image_type: " << head.image_type; /*qDebug() << "id_length: " << head.id_length << " - colormap_type: " << head.colormap_type << " - image_type: " << head.image_type;
qDebug() << "colormap_index: " << head.colormap_index << " - colormap_length: " << head.colormap_length << " - colormap_size: " << head.colormap_size; qDebug() << "colormap_index: " << head.colormap_index << " - colormap_length: " << head.colormap_length << " - colormap_size: " << head.colormap_size;
qDebug() << "x_origin: " << head.x_origin << " - y_origin: " << head.y_origin << " - width:" << head.width << " - height:" << head.height << " - pixelsize: " << head.pixel_size << " - flags: " << head.flags;*/ qDebug() << "x_origin: " << head.x_origin << " - y_origin: " << head.y_origin << " - width:" << head.width << " - height:" << head.height << " - pixelsize:
" << head.pixel_size << " - flags: " << head.flags;*/
return s; return s;
} }
static bool IsSupported(const TgaHeader &head) static bool IsSupported(const TgaHeader &head)
{ {
if (head.image_type != TGA_TYPE_INDEXED && if (head.image_type != TGA_TYPE_INDEXED && head.image_type != TGA_TYPE_RGB && head.image_type != TGA_TYPE_GREY && head.image_type != TGA_TYPE_RLE_INDEXED
head.image_type != TGA_TYPE_RGB && && head.image_type != TGA_TYPE_RLE_RGB && head.image_type != TGA_TYPE_RLE_GREY) {
head.image_type != TGA_TYPE_GREY &&
head.image_type != TGA_TYPE_RLE_INDEXED &&
head.image_type != TGA_TYPE_RLE_RGB &&
head.image_type != TGA_TYPE_RLE_GREY) {
return false; return false;
} }
if (head.image_type == TGA_TYPE_INDEXED || if (head.image_type == TGA_TYPE_INDEXED || head.image_type == TGA_TYPE_RLE_INDEXED) {
head.image_type == TGA_TYPE_RLE_INDEXED) {
if (head.colormap_length > 256 || head.colormap_size != 24 || head.colormap_type != 1) { if (head.colormap_length > 256 || head.colormap_size != 24 || head.colormap_type != 1) {
return false; return false;
} }
} }
if (head.image_type == TGA_TYPE_RGB || if (head.image_type == TGA_TYPE_RGB || head.image_type == TGA_TYPE_GREY || head.image_type == TGA_TYPE_RLE_RGB || head.image_type == TGA_TYPE_RLE_GREY) {
head.image_type == TGA_TYPE_GREY ||
head.image_type == TGA_TYPE_RLE_RGB ||
head.image_type == TGA_TYPE_RLE_GREY) {
if (head.colormap_type != 0) { if (head.colormap_type != 0) {
return false; return false;
} }
@ -119,8 +113,7 @@ static bool IsSupported(const TgaHeader &head)
if (head.width == 0 || head.height == 0) { if (head.width == 0 || head.height == 0) {
return false; return false;
} }
if (head.pixel_size != 8 && head.pixel_size != 16 && if (head.pixel_size != 8 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) {
head.pixel_size != 24 && head.pixel_size != 32) {
return false; return false;
} }
return true; return true;
@ -138,7 +131,11 @@ struct TgaHeaderInfo {
bool rgb; bool rgb;
bool grey; bool grey;
TgaHeaderInfo(const TgaHeader &tga) : rle(false), pal(false), rgb(false), grey(false) TgaHeaderInfo(const TgaHeader &tga)
: rle(false)
, pal(false)
, rgb(false)
, grey(false)
{ {
switch (tga.image_type) { switch (tga.image_type) {
case TGA_TYPE_RLE_INDEXED: case TGA_TYPE_RLE_INDEXED:
@ -282,11 +279,11 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
return false; return false;
} }
if ((uint)dataRead < count) { if ((uint)dataRead < count) {
const size_t toCopy = count - dataRead; const size_t toCopy = count - dataRead;
if (&dst[dataRead] + toCopy > imgEnd) { if (&dst[dataRead] + toCopy > imgEnd) {
qWarning() << "Trying to write out of bounds!" << ptrdiff_t(image) << ptrdiff_t(&dst[dataRead]);; qWarning() << "Trying to write out of bounds!" << ptrdiff_t(image) << ptrdiff_t(&dst[dataRead]);
;
valid = false; valid = false;
break; break;
} }

View File

@ -8,15 +8,15 @@
#include "xcf_p.h" #include "xcf_p.h"
#include <stdlib.h> #include <QDebug>
#include <QImage>
#include <QPainter>
#include <QIODevice> #include <QIODevice>
#include <QImage>
#include <QLoggingCategory>
#include <QPainter>
#include <QStack> #include <QStack>
#include <QVector> #include <QVector>
#include <QDebug>
#include <QLoggingCategory>
#include <QtEndian> #include <QtEndian>
#include <stdlib.h>
#include <string.h> #include <string.h>
@ -27,7 +27,8 @@ Q_LOGGING_CATEGORY(XCFPLUGIN, "kf.imageformats.plugins.xcf", QtWarningMsg)
const float INCHESPERMETER = (100.0f / 2.54f); const float INCHESPERMETER = (100.0f / 2.54f);
namespace { namespace
{
struct RandomTable { struct RandomTable {
// From glibc // From glibc
static constexpr int rand_r(unsigned int *seed) static constexpr int rand_r(unsigned int *seed)
@ -54,7 +55,8 @@ struct RandomTable {
return result; return result;
} }
constexpr RandomTable() : values{} constexpr RandomTable()
: values{}
{ {
unsigned int next = RANDOM_SEED; unsigned int next = RANDOM_SEED;
@ -88,7 +90,6 @@ class XCFImageFormat
{ {
Q_GADGET Q_GADGET
public: public:
//! Properties which can be stored in an XCF file. //! Properties which can be stored in an XCF file.
enum PropType { enum PropType {
PROP_END = 0, PROP_END = 0,
@ -239,7 +240,6 @@ public:
CompositeIntersect, CompositeIntersect,
}; };
XCFImageFormat(); XCFImageFormat();
bool readXCF(QIODevice *device, QImage *image); bool readXCF(QIODevice *device, QImage *image);
@ -290,7 +290,8 @@ private:
quint32 visible = 1; //!< Is the layer visible? quint32 visible = 1; //!< Is the layer visible?
quint32 linked; //!< Is this layer linked (geometrically) quint32 linked; //!< Is this layer linked (geometrically)
quint32 preserve_transparency; //!< Preserve alpha when drawing on layer? quint32 preserve_transparency; //!< Preserve alpha when drawing on layer?
quint32 apply_mask = 9; //!< Apply the layer mask? Use 9 as "uninitilized". Spec says "If the property does not appear for a layer which has a layer mask, it defaults to true (1). quint32 apply_mask = 9; //!< Apply the layer mask? Use 9 as "uninitilized". Spec says "If the property does not appear for a layer which has a layer
//!< mask, it defaults to true (1).
// Robust readers should force this to false if the layer has no layer mask. // Robust readers should force this to false if the layer has no layer mask.
quint32 edit_mask; //!< Is the layer mask the being edited? quint32 edit_mask; //!< Is the layer mask the being edited?
quint32 show_mask; //!< Show the layer mask rather than the image? quint32 show_mask; //!< Show the layer mask rather than the image?
@ -311,7 +312,10 @@ private:
//! copied in different ways. //! copied in different ways.
void (*assignBytes)(Layer &layer, uint i, uint j); void (*assignBytes)(Layer &layer, uint i, uint j);
Layer(void) : name(nullptr) {} Layer(void)
: name(nullptr)
{
}
~Layer(void) ~Layer(void)
{ {
delete[] name; delete[] name;
@ -347,10 +351,14 @@ private:
bool initialized; //!< Is the QImage initialized? bool initialized; //!< Is the QImage initialized?
QImage image; //!< final QImage QImage image; //!< final QImage
XCFImage(void) : initialized(false) {} XCFImage(void)
: initialized(false)
{
}
}; };
static qint64 readOffsetPtr(QDataStream &stream) { static qint64 readOffsetPtr(QDataStream &stream)
{
if (stream.version() >= 11) { if (stream.version() >= 11) {
qint64 ret; qint64 ret;
stream >> ret; stream >> ret;
@ -383,12 +391,10 @@ private:
//! The bottom-most layer is copied into the final QImage by this //! The bottom-most layer is copied into the final QImage by this
//! routine. //! routine.
typedef void (*PixelCopyOperation)(const Layer &layer, uint i, uint j, int k, int l, typedef void (*PixelCopyOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n);
//! Higher layers are merged into the final QImage by this routine. //! Higher layers are merged into the final QImage by this routine.
typedef void (*PixelMergeOperation)(const Layer &layer, uint i, uint j, int k, int l, typedef void (*PixelMergeOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n);
static bool modeAffectsSourceAlpha(const quint32 type); static bool modeAffectsSourceAlpha(const quint32 type);
@ -406,42 +412,26 @@ private:
bool loadMask(QDataStream &xcf_io, Layer &layer); bool loadMask(QDataStream &xcf_io, Layer &layer);
bool loadChannelProperties(QDataStream &xcf_io, Layer &layer); bool loadChannelProperties(QDataStream &xcf_io, Layer &layer);
bool initializeImage(XCFImage &xcf_image); bool initializeImage(XCFImage &xcf_image);
bool loadTileRLE(QDataStream &xcf_io, uchar *tile, int size, bool loadTileRLE(QDataStream &xcf_io, uchar *tile, int size, int data_length, qint32 bpp);
int data_length, qint32 bpp);
static void copyLayerToImage(XCFImage &xcf_image); static void copyLayerToImage(XCFImage &xcf_image);
static void copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, static void copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, static void copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, static void copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, static void copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n);
static void copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void mergeLayerIntoImage(XCFImage &xcf_image); static void mergeLayerIntoImage(XCFImage &xcf_image);
static void mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, static void mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, static void mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, static void mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, static void mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
QImage &image, int m, int n); static void mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
static void mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l,
QImage &image, int m, int n);
static void initializeRandomTable(); static void initializeRandomTable();
static void dissolveRGBPixels(QImage &image, int x, int y); static void dissolveRGBPixels(QImage &image, int x, int y);
@ -536,7 +526,6 @@ bool XCFImageFormat::modeAffectsSourceAlpha(const quint32 type)
} }
} }
//! Change a QRgb value's alpha only. //! Change a QRgb value's alpha only.
inline QRgb qRgba(const QRgb rgb, int a) inline QRgb qRgba(const QRgb rgb, int a)
{ {
@ -571,8 +560,7 @@ void XCFImageFormat::initializeRandomTable()
} }
} }
inline inline int XCFImageFormat::add_lut(int a, int b)
int XCFImageFormat::add_lut(int a, int b)
{ {
return qMin(a + b, 255); return qMin(a + b, 255);
} }
@ -650,7 +638,8 @@ bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
xcf_image.num_layers = layer_offsets.size(); xcf_image.num_layers = layer_offsets.size();
if (layer_offsets.size() == 0) { if (layer_offsets.size() == 0) {
qCDebug(XCFPLUGIN) << "XCF: no layers!"; return false; qCDebug(XCFPLUGIN) << "XCF: no layers!";
return false;
} }
qCDebug(XCFPLUGIN) << xcf_image.num_layers << "layers"; qCDebug(XCFPLUGIN) << xcf_image.num_layers << "layers";
@ -882,11 +871,9 @@ bool XCFImageFormat::loadLayer(QDataStream &xcf_io, XCFImage &xcf_image)
return false; return false;
} }
qCDebug(XCFPLUGIN) qCDebug(XCFPLUGIN) << "layer: \"" << layer.name << "\", size: " << layer.width << " x " << layer.height << ", type: " << GimpImageType(layer.type)
<< "layer: \"" << layer.name << "\", size: " << layer.width << " x " << ", mode: " << layer.mode << ", opacity: " << layer.opacity << ", visible: " << layer.visible << ", offset: " << layer.x_offset << ", "
<< layer.height << ", type: " << GimpImageType(layer.type) << ", mode: " << layer.mode << layer.y_offset;
<< ", opacity: " << layer.opacity << ", visible: " << layer.visible
<< ", offset: " << layer.x_offset << ", " << layer.y_offset;
// Skip reading the rest of it if it is not visible. Typically, when // Skip reading the rest of it if it is not visible. Typically, when
// you export an image from the The GIMP it flattens (or merges) only // you export an image from the The GIMP it flattens (or merges) only
@ -1083,8 +1070,7 @@ bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
// SANITY CHECK: Catch corrupted XCF image file where the width or height // SANITY CHECK: Catch corrupted XCF image file where the width or height
// of a tile is reported are bogus. See Bug# 234030. // of a tile is reported are bogus. See Bug# 234030.
if (layer.width > 32767 || layer.height > 32767 if (layer.width > 32767 || layer.height > 32767 || (sizeof(void *) == 4 && layer.width * layer.height > 16384 * 16384)) {
|| (sizeof(void *) == 4 && layer.width * layer.height > 16384 * 16384)) {
return false; return false;
} }
@ -1112,12 +1098,9 @@ bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
for (uint j = 0; j < layer.nrows; j++) { for (uint j = 0; j < layer.nrows; j++) {
for (uint i = 0; i < layer.ncols; i++) { for (uint i = 0; i < layer.ncols; i++) {
uint tile_width = (i + 1) * TILE_WIDTH <= layer.width ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
uint tile_width = (i + 1) * TILE_WIDTH <= layer.width uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
? TILE_WIDTH : layer.width - i * TILE_WIDTH;
uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
// Try to create the most appropriate QImage (each GIMP layer // Try to create the most appropriate QImage (each GIMP layer
// type is treated slightly differently) // type is treated slightly differently)
@ -1287,7 +1270,6 @@ void XCFImageFormat::assignImageBytes(Layer &layer, uint i, uint j)
uchar *dataPtr = bits + y * bytesPerLine; uchar *dataPtr = bits + y * bytesPerLine;
uchar *alphaPtr = layer.alpha_tiles[j][i].scanLine(y); uchar *alphaPtr = layer.alpha_tiles[j][i].scanLine(y);
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
// The "if" here should not be necessary, but apparently there // The "if" here should not be necessary, but apparently there
// are some cases where the image can contain larger indices // are some cases where the image can contain larger indices
// than there are colors in the palette. (A bug in The GIMP?) // than there are colors in the palette. (A bug in The GIMP?)
@ -1436,7 +1418,6 @@ bool XCFImageFormat::loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp)
for (uint j = 0; j < layer.nrows; j++) { for (uint j = 0; j < layer.nrows; j++) {
for (uint i = 0; i < layer.ncols; i++) { for (uint i = 0; i < layer.ncols; i++) {
if (offset == 0) { if (offset == 0) {
qCDebug(XCFPLUGIN) << "XCF: incorrect number of tiles in layer " << layer.name; qCDebug(XCFPLUGIN) << "XCF: incorrect number of tiles in layer " << layer.name;
return false; return false;
@ -1551,8 +1532,7 @@ bool XCFImageFormat::loadMask(QDataStream &xcf_io, Layer &layer)
* \return true if there were no I/O errors and no obvious corruption of * \return true if there were no I/O errors and no obvious corruption of
* the RLE data. * the RLE data.
*/ */
bool XCFImageFormat::loadTileRLE(QDataStream &xcf_io, uchar *tile, int image_size, bool XCFImageFormat::loadTileRLE(QDataStream &xcf_io, uchar *tile, int image_size, int data_length, qint32 bpp)
int data_length, qint32 bpp)
{ {
uchar *data; uchar *data;
@ -1587,7 +1567,6 @@ bool XCFImageFormat::loadTileRLE(QDataStream &xcf_io, uchar *tile, int image_siz
xcfdatalimit = &xcfodata[data_length - 1]; xcfdatalimit = &xcfodata[data_length - 1];
for (int i = 0; i < bpp; ++i) { for (int i = 0; i < bpp; ++i) {
data = tile + i; data = tile + i;
int count = 0; int count = 0;
@ -1719,13 +1698,11 @@ bool XCFImageFormat::loadChannelProperties(QDataStream &xcf_io, Layer &layer)
break; break;
case PROP_COLOR: case PROP_COLOR:
property >> layer.mask_channel.red >> layer.mask_channel.green property >> layer.mask_channel.red >> layer.mask_channel.green >> layer.mask_channel.blue;
>> layer.mask_channel.blue;
break; break;
case PROP_FLOAT_COLOR: case PROP_FLOAT_COLOR:
property >> layer.mask_channel.redF >> layer.mask_channel.greenF property >> layer.mask_channel.redF >> layer.mask_channel.greenF >> layer.mask_channel.blueF;
>> layer.mask_channel.blueF;
break; break;
case PROP_TATTOO: case PROP_TATTOO:
@ -2018,7 +1995,6 @@ void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
for (int l = 0; l < layer.image_tiles[j][i].height(); l++) { for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
for (int k = 0; k < layer.image_tiles[j][i].width(); k++) { for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
int m = x + k + layer.x_offset; int m = x + k + layer.x_offset;
int n = y + l + layer.y_offset; int n = y + l + layer.y_offset;
@ -2046,8 +2022,7 @@ void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.opacity; uchar src_a = layer.opacity;
@ -2058,8 +2033,7 @@ void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2077,8 +2051,7 @@ void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = layer.image_tiles[j][i].pixelIndex(k, l); int src = layer.image_tiles[j][i].pixelIndex(k, l);
image.setPixel(m, n, src); image.setPixel(m, n, src);
@ -2097,8 +2070,7 @@ void XCFImageFormat::copyGrayToGray(const Layer &layer, uint i, uint j, int k, i
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.opacity; uchar src_a = layer.opacity;
@ -2118,8 +2090,7 @@ void XCFImageFormat::copyGrayToRGB(const Layer &layer, uint i, uint j, int k, in
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l); uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
@ -2127,8 +2098,7 @@ void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, i
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2146,8 +2116,7 @@ void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, i
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = layer.image_tiles[j][i].pixelIndex(k, l); int src = layer.image_tiles[j][i].pixelIndex(k, l);
image.setPixel(m, n, src); image.setPixel(m, n, src);
@ -2164,16 +2133,13 @@ void XCFImageFormat::copyIndexedToIndexed(const Layer &layer, uint i, uint j, in
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
uchar src = layer.image_tiles[j][i].pixelIndex(k, l); uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l); uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
if (layer.apply_mask == 1 && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles.size() > (int)j &&
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2199,16 +2165,14 @@ void XCFImageFormat::copyIndexedAToIndexed(const Layer &layer, uint i, uint j, i
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l); uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2312,7 +2276,6 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
qCDebug(XCFPLUGIN) << "Unhandled composite mode" << compositeMode; qCDebug(XCFPLUGIN) << "Unhandled composite mode" << compositeMode;
} }
switch (layer.type) { switch (layer.type) {
case RGB_GIMAGE: case RGB_GIMAGE:
case RGBA_GIMAGE: case RGBA_GIMAGE:
@ -2373,8 +2336,7 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
} }
// Shortcut for common case // Shortcut for common case
if (merge == mergeRGBToRGB && layer.apply_mask != 1 if (merge == mergeRGBToRGB && layer.apply_mask != 1 && layer.mode == NORMAL_MODE) {
&& layer.mode == NORMAL_MODE) {
QPainter painter(&image); QPainter painter(&image);
painter.setOpacity(layer.opacity / 255.0); painter.setOpacity(layer.opacity / 255.0);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
@ -2384,7 +2346,6 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
for (int l = 0; l < layer.image_tiles[j][i].height(); l++) { for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
for (int k = 0; k < layer.image_tiles[j][i].width(); k++) { for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
int m = x + k + layer.x_offset; int m = x + k + layer.x_offset;
int n = y + l + layer.y_offset; int n = y + l + layer.y_offset;
@ -2412,8 +2373,7 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
QRgb dst = image.pixel(m, n); QRgb dst = image.pixel(m, n);
@ -2515,8 +2475,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_g = new_g; src_g = new_g;
src_b = new_b; src_b = new_b;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY: { case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY: {
uchar new_r = dst_r; uchar new_r = dst_r;
uchar new_g = dst_g; uchar new_g = dst_g;
@ -2533,8 +2492,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_g = new_g; src_g = new_g;
src_b = new_b; src_b = new_b;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_HSV_VALUE_LEGACY: { case GIMP_LAYER_MODE_HSV_VALUE_LEGACY: {
uchar new_r = dst_r; uchar new_r = dst_r;
uchar new_g = dst_g; uchar new_g = dst_g;
@ -2551,8 +2509,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_g = new_g; src_g = new_g;
src_b = new_b; src_b = new_b;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_HSL_COLOR_LEGACY: { case GIMP_LAYER_MODE_HSL_COLOR_LEGACY: {
uchar new_r = dst_r; uchar new_r = dst_r;
uchar new_g = dst_g; uchar new_g = dst_g;
@ -2570,8 +2527,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_g = new_g; src_g = new_g;
src_b = new_b; src_b = new_b;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_DODGE_LEGACY: { case GIMP_LAYER_MODE_DODGE_LEGACY: {
uint tmp; uint tmp;
@ -2588,8 +2544,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_b = (uchar)qMin(tmp, 255u); src_b = (uchar)qMin(tmp, 255u);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_BURN_LEGACY: { case GIMP_LAYER_MODE_BURN_LEGACY: {
uint tmp; uint tmp;
@ -2609,8 +2564,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_b = 255 - src_b; src_b = 255 - src_b;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: { case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: {
uint tmp; uint tmp;
if (src_r > 128) { if (src_r > 128) {
@ -2637,29 +2591,24 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_b = (uchar)qMin(tmp >> 8, 255u); src_b = (uchar)qMin(tmp >> 8, 255u);
} }
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: { case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: {
uint tmpS, tmpM; uint tmpS, tmpM;
tmpM = INT_MULT(dst_r, src_r); tmpM = INT_MULT(dst_r, src_r);
tmpS = 255 - INT_MULT((255 - dst_r), (255 - src_r)); tmpS = 255 - INT_MULT((255 - dst_r), (255 - src_r));
src_r = INT_MULT((255 - dst_r), tmpM) src_r = INT_MULT((255 - dst_r), tmpM) + INT_MULT(dst_r, tmpS);
+ INT_MULT(dst_r, tmpS);
tmpM = INT_MULT(dst_g, src_g); tmpM = INT_MULT(dst_g, src_g);
tmpS = 255 - INT_MULT((255 - dst_g), (255 - src_g)); tmpS = 255 - INT_MULT((255 - dst_g), (255 - src_g));
src_g = INT_MULT((255 - dst_g), tmpM) src_g = INT_MULT((255 - dst_g), tmpM) + INT_MULT(dst_g, tmpS);
+ INT_MULT(dst_g, tmpS);
tmpM = INT_MULT(dst_b, src_b); tmpM = INT_MULT(dst_b, src_b);
tmpS = 255 - INT_MULT((255 - dst_b), (255 - src_b)); tmpS = 255 - INT_MULT((255 - dst_b), (255 - src_b));
src_b = INT_MULT((255 - dst_b), tmpM) src_b = INT_MULT((255 - dst_b), tmpM) + INT_MULT(dst_b, tmpS);
+ INT_MULT(dst_b, tmpS);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: { case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: {
int tmp; int tmp;
@ -2679,8 +2628,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_b = (uchar)tmp; src_b = (uchar)tmp;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: { case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: {
int tmp; int tmp;
@ -2700,8 +2648,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
src_b = (uchar)tmp; src_b = (uchar)tmp;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
default: default:
break; break;
} }
@ -2710,8 +2657,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2743,8 +2689,7 @@ void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, in
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = layer.image_tiles[j][i].pixelIndex(k, l); int src = layer.image_tiles[j][i].pixelIndex(k, l);
image.setPixel(m, n, src); image.setPixel(m, n, src);
@ -2761,8 +2706,7 @@ void XCFImageFormat::mergeGrayToGray(const Layer &layer, uint i, uint j, int k,
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = qGray(layer.image_tiles[j][i].pixel(k, l)); int src = qGray(layer.image_tiles[j][i].pixel(k, l));
int dst = image.pixelIndex(m, n); int dst = image.pixelIndex(m, n);
@ -2776,53 +2720,42 @@ void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k,
switch (layer.mode) { switch (layer.mode) {
case MULTIPLY_MODE: { case MULTIPLY_MODE: {
src = INT_MULT(src, dst); src = INT_MULT(src, dst);
} } break;
break;
case DIVIDE_MODE: { case DIVIDE_MODE: {
src = qMin((dst * 256) / (1 + src), 255); src = qMin((dst * 256) / (1 + src), 255);
} } break;
break;
case SCREEN_MODE: { case SCREEN_MODE: {
src = 255 - INT_MULT(255 - dst, 255 - src); src = 255 - INT_MULT(255 - dst, 255 - src);
} } break;
break;
case OVERLAY_MODE: { case OVERLAY_MODE: {
src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst)); src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
} } break;
break;
case DIFFERENCE_MODE: { case DIFFERENCE_MODE: {
src = dst > src ? dst - src : src - dst; src = dst > src ? dst - src : src - dst;
} } break;
break;
case ADDITION_MODE: { case ADDITION_MODE: {
src = add_lut(dst, src); src = add_lut(dst, src);
} } break;
break;
case SUBTRACT_MODE: { case SUBTRACT_MODE: {
src = dst > src ? dst - src : 0; src = dst > src ? dst - src : 0;
} } break;
break;
case DARKEN_ONLY_MODE: { case DARKEN_ONLY_MODE: {
src = dst < src ? dst : src; src = dst < src ? dst : src;
} } break;
break;
case LIGHTEN_ONLY_MODE: { case LIGHTEN_ONLY_MODE: {
src = dst < src ? src : dst; src = dst < src ? src : dst;
} } break;
break;
case DODGE_MODE: { case DODGE_MODE: {
uint tmp = dst << 8; uint tmp = dst << 8;
tmp /= 256 - src; tmp /= 256 - src;
src = (uchar)qMin(tmp, 255u); src = (uchar)qMin(tmp, 255u);
} } break;
break;
case BURN_MODE: { case BURN_MODE: {
uint tmp = (255 - dst) << 8; uint tmp = (255 - dst) << 8;
tmp /= src + 1; tmp /= src + 1;
src = (uchar)qMin(tmp, 255u); src = (uchar)qMin(tmp, 255u);
src = 255 - src; src = 255 - src;
} } break;
break;
case HARDLIGHT_MODE: { case HARDLIGHT_MODE: {
uint tmp; uint tmp;
if (src > 128) { if (src > 128) {
@ -2832,18 +2765,15 @@ void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k,
tmp = (int)dst * ((int)src << 1); tmp = (int)dst * ((int)src << 1);
src = (uchar)qMin(tmp >> 8, 255u); src = (uchar)qMin(tmp >> 8, 255u);
} }
} } break;
break;
case SOFTLIGHT_MODE: { case SOFTLIGHT_MODE: {
uint tmpS, tmpM; uint tmpS, tmpM;
tmpM = INT_MULT(dst, src); tmpM = INT_MULT(dst, src);
tmpS = 255 - INT_MULT((255 - dst), (255 - src)); tmpS = 255 - INT_MULT((255 - dst), (255 - src));
src = INT_MULT((255 - dst), tmpM) src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
+ INT_MULT(dst, tmpS);
} } break;
break;
case GRAIN_EXTRACT_MODE: { case GRAIN_EXTRACT_MODE: {
int tmp; int tmp;
@ -2852,8 +2782,7 @@ void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k,
tmp = qMax(tmp, 0); tmp = qMax(tmp, 0);
src = (uchar)tmp; src = (uchar)tmp;
} } break;
break;
case GRAIN_MERGE_MODE: { case GRAIN_MERGE_MODE: {
int tmp; int tmp;
@ -2862,16 +2791,14 @@ void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k,
tmp = qMax(tmp, 0); tmp = qMax(tmp, 0);
src = (uchar)tmp; src = (uchar)tmp;
} } break;
break;
} }
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -2898,8 +2825,7 @@ void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k,
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.opacity; uchar src_a = layer.opacity;
@ -2919,8 +2845,7 @@ void XCFImageFormat::mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, i
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = qGray(layer.image_tiles[j][i].pixel(k, l)); int src = qGray(layer.image_tiles[j][i].pixel(k, l));
int dst = qGray(image.pixel(m, n)); int dst = qGray(image.pixel(m, n));
@ -2936,63 +2861,52 @@ void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k,
case MULTIPLY_MODE: { case MULTIPLY_MODE: {
src = INT_MULT(src, dst); src = INT_MULT(src, dst);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case DIVIDE_MODE: { case DIVIDE_MODE: {
src = qMin((dst * 256) / (1 + src), 255); src = qMin((dst * 256) / (1 + src), 255);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case SCREEN_MODE: { case SCREEN_MODE: {
src = 255 - INT_MULT(255 - dst, 255 - src); src = 255 - INT_MULT(255 - dst, 255 - src);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case OVERLAY_MODE: { case OVERLAY_MODE: {
src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst)); src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case DIFFERENCE_MODE: { case DIFFERENCE_MODE: {
src = dst > src ? dst - src : src - dst; src = dst > src ? dst - src : src - dst;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case ADDITION_MODE: { case ADDITION_MODE: {
src = add_lut(dst, src); src = add_lut(dst, src);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case SUBTRACT_MODE: { case SUBTRACT_MODE: {
src = dst > src ? dst - src : 0; src = dst > src ? dst - src : 0;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case DARKEN_ONLY_MODE: { case DARKEN_ONLY_MODE: {
src = dst < src ? dst : src; src = dst < src ? dst : src;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case LIGHTEN_ONLY_MODE: { case LIGHTEN_ONLY_MODE: {
src = dst < src ? src : dst; src = dst < src ? src : dst;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case DODGE_MODE: { case DODGE_MODE: {
uint tmp = dst << 8; uint tmp = dst << 8;
tmp /= 256 - src; tmp /= 256 - src;
src = (uchar)qMin(tmp, 255u); src = (uchar)qMin(tmp, 255u);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case BURN_MODE: { case BURN_MODE: {
uint tmp = (255 - dst) << 8; uint tmp = (255 - dst) << 8;
tmp /= src + 1; tmp /= src + 1;
src = (uchar)qMin(tmp, 255u); src = (uchar)qMin(tmp, 255u);
src = 255 - src; src = 255 - src;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case HARDLIGHT_MODE: { case HARDLIGHT_MODE: {
uint tmp; uint tmp;
if (src > 128) { if (src > 128) {
@ -3003,19 +2917,16 @@ void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k,
src = (uchar)qMin(tmp >> 8, 255u); src = (uchar)qMin(tmp >> 8, 255u);
} }
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case SOFTLIGHT_MODE: { case SOFTLIGHT_MODE: {
uint tmpS, tmpM; uint tmpS, tmpM;
tmpM = INT_MULT(dst, src); tmpM = INT_MULT(dst, src);
tmpS = 255 - INT_MULT((255 - dst), (255 - src)); tmpS = 255 - INT_MULT((255 - dst), (255 - src));
src = INT_MULT((255 - dst), tmpM) src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
+ INT_MULT(dst, tmpS);
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GRAIN_EXTRACT_MODE: { case GRAIN_EXTRACT_MODE: {
int tmp; int tmp;
@ -3025,8 +2936,7 @@ void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k,
src = (uchar)tmp; src = (uchar)tmp;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
case GRAIN_MERGE_MODE: { case GRAIN_MERGE_MODE: {
int tmp; int tmp;
@ -3036,15 +2946,13 @@ void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k,
src = (uchar)tmp; src = (uchar)tmp;
src_a = qMin(src_a, dst_a); src_a = qMin(src_a, dst_a);
} } break;
break;
} }
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -3073,8 +2981,7 @@ void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k,
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
int src = layer.image_tiles[j][i].pixelIndex(k, l); int src = layer.image_tiles[j][i].pixelIndex(k, l);
image.setPixel(m, n, src); image.setPixel(m, n, src);
@ -3091,16 +2998,13 @@ void XCFImageFormat::mergeIndexedToIndexed(const Layer &layer, uint i, uint j, i
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
uchar src = layer.image_tiles[j][i].pixelIndex(k, l); uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l); uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
if (layer.apply_mask == 1 && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles.size() > (int)j &&
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }
@ -3123,16 +3027,14 @@ void XCFImageFormat::mergeIndexedAToIndexed(const Layer &layer, uint i, uint j,
* \param m x pixel of destination image. * \param m x pixel of destination image.
* \param n y pixel of destination image. * \param n y pixel of destination image.
*/ */
void XCFImageFormat::mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, void XCFImageFormat::mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
QImage &image, int m, int n)
{ {
QRgb src = layer.image_tiles[j][i].pixel(k, l); QRgb src = layer.image_tiles[j][i].pixel(k, l);
uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l); uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
src_a = INT_MULT(src_a, layer.opacity); src_a = INT_MULT(src_a, layer.opacity);
// Apply the mask (if any) // Apply the mask (if any)
if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
layer.mask_tiles[j].size() > (int)i) {
src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l)); src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
} }

View File

@ -7,8 +7,8 @@
#ifndef FORMAT_ENUM_H #ifndef FORMAT_ENUM_H
#define FORMAT_ENUM_H #define FORMAT_ENUM_H
#include <QMetaEnum>
#include <QImage> #include <QImage>
#include <QMetaEnum>
QImage::Format formatFromString(const QString &str) QImage::Format formatFromString(const QString &str)
{ {

View File

@ -27,19 +27,15 @@ int main(int argc, char **argv)
parser.addVersionOption(); parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("in"), QStringLiteral("input image file")); parser.addPositionalArgument(QStringLiteral("in"), QStringLiteral("input image file"));
parser.addPositionalArgument(QStringLiteral("out"), QStringLiteral("output image file")); parser.addPositionalArgument(QStringLiteral("out"), QStringLiteral("output image file"));
QCommandLineOption informat( QCommandLineOption informat(QStringList() << QStringLiteral("i") << QStringLiteral("informat"),
QStringList() << QStringLiteral("i") << QStringLiteral("informat"),
QStringLiteral("Image format for input file"), QStringLiteral("Image format for input file"),
QStringLiteral("format")); QStringLiteral("format"));
parser.addOption(informat); parser.addOption(informat);
QCommandLineOption outformat( QCommandLineOption outformat(QStringList() << QStringLiteral("o") << QStringLiteral("outformat"),
QStringList() << QStringLiteral("o") << QStringLiteral("outformat"),
QStringLiteral("Image format for output file"), QStringLiteral("Image format for output file"),
QStringLiteral("format")); QStringLiteral("format"));
parser.addOption(outformat); parser.addOption(outformat);
QCommandLineOption listformats( QCommandLineOption listformats(QStringList() << QStringLiteral("l") << QStringLiteral("list"), QStringLiteral("List supported image formats"));
QStringList() << QStringLiteral("l") << QStringLiteral("list"),
QStringLiteral("List supported image formats"));
parser.addOption(listformats); parser.addOption(listformats);
parser.process(app); parser.process(app);

View File

@ -10,10 +10,10 @@
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QImageReader>
#include <QFile> #include <QFile>
#include <QMetaObject> #include <QImageReader>
#include <QMetaEnum> #include <QMetaEnum>
#include <QMetaObject>
#include <QTextStream> #include <QTextStream>
#include "format-enum.h" #include "format-enum.h"
@ -31,26 +31,21 @@ int main(int argc, char **argv)
parser.addVersionOption(); parser.addVersionOption();
parser.addPositionalArgument(QStringLiteral("image"), QStringLiteral("image file")); parser.addPositionalArgument(QStringLiteral("image"), QStringLiteral("image file"));
parser.addPositionalArgument(QStringLiteral("datafile"), QStringLiteral("file QImage data should be written to")); parser.addPositionalArgument(QStringLiteral("datafile"), QStringLiteral("file QImage data should be written to"));
QCommandLineOption informat( QCommandLineOption informat(QStringList() << QStringLiteral("f") << QStringLiteral("file-format"),
QStringList() << QStringLiteral("f") << QStringLiteral("file-format"),
QStringLiteral("Image file format"), QStringLiteral("Image file format"),
QStringLiteral("format")); QStringLiteral("format"));
parser.addOption(informat); parser.addOption(informat);
QCommandLineOption qimgformat( QCommandLineOption qimgformat(QStringList() << QStringLiteral("q") << QStringLiteral("qimage-format"),
QStringList() << QStringLiteral("q") << QStringLiteral("qimage-format"),
QStringLiteral("QImage data format"), QStringLiteral("QImage data format"),
QStringLiteral("format")); QStringLiteral("format"));
parser.addOption(qimgformat); parser.addOption(qimgformat);
QCommandLineOption listformats( QCommandLineOption listformats(QStringList() << QStringLiteral("l") << QStringLiteral("list-file-formats"),
QStringList() << QStringLiteral("l") << QStringLiteral("list-file-formats"),
QStringLiteral("List supported image file formats")); QStringLiteral("List supported image file formats"));
parser.addOption(listformats); parser.addOption(listformats);
QCommandLineOption listmimetypes( QCommandLineOption listmimetypes(QStringList() << QStringLiteral("m") << QStringLiteral("list-mime-types"),
QStringList() << QStringLiteral("m") << QStringLiteral("list-mime-types"),
QStringLiteral("List supported image mime types")); QStringLiteral("List supported image mime types"));
parser.addOption(listmimetypes); parser.addOption(listmimetypes);
QCommandLineOption listqformats( QCommandLineOption listqformats(QStringList() << QStringLiteral("p") << QStringLiteral("list-qimage-formats"),
QStringList() << QStringLiteral("p") << QStringLiteral("list-qimage-formats"),
QStringLiteral("List supported QImage data formats")); QStringLiteral("List supported QImage data formats"));
parser.addOption(listqformats); parser.addOption(listqformats);
@ -93,35 +88,29 @@ int main(int argc, char **argv)
QImageReader reader(files.at(0), parser.value(informat).toLatin1()); QImageReader reader(files.at(0), parser.value(informat).toLatin1());
QImage img = reader.read(); QImage img = reader.read();
if (img.isNull()) { if (img.isNull()) {
QTextStream(stderr) << "Could not read image: " QTextStream(stderr) << "Could not read image: " << reader.errorString() << '\n';
<< reader.errorString() << '\n';
return 2; return 2;
} }
QFile output(files.at(1)); QFile output(files.at(1));
if (!output.open(QIODevice::WriteOnly)) { if (!output.open(QIODevice::WriteOnly)) {
QTextStream(stderr) << "Could not open " << files.at(1) QTextStream(stderr) << "Could not open " << files.at(1) << " for writing: " << output.errorString() << '\n';
<< " for writing: "
<< output.errorString() << '\n';
return 3; return 3;
} }
if (parser.isSet(qimgformat)) { if (parser.isSet(qimgformat)) {
QImage::Format qformat = formatFromString(parser.value(qimgformat)); QImage::Format qformat = formatFromString(parser.value(qimgformat));
if (qformat == QImage::Format_Invalid) { if (qformat == QImage::Format_Invalid) {
QTextStream(stderr) << "Unknown QImage data format " QTextStream(stderr) << "Unknown QImage data format " << parser.value(qimgformat) << '\n';
<< parser.value(qimgformat) << '\n';
return 4; return 4;
} }
img = img.convertToFormat(qformat); img = img.convertToFormat(qformat);
} }
qint64 written = output.write(reinterpret_cast<const char *>(img.bits()), img.sizeInBytes()); qint64 written = output.write(reinterpret_cast<const char *>(img.bits()), img.sizeInBytes());
if (written != img.sizeInBytes()) { if (written != img.sizeInBytes()) {
QTextStream(stderr) << "Could not write image data to " << files.at(1) QTextStream(stderr) << "Could not write image data to " << files.at(1) << ":" << output.errorString() << "\n";
<< ":" << output.errorString() << "\n";
return 5; return 5;
} }
QTextStream(stdout) << "Created " << files.at(1) << " with data format " QTextStream(stdout) << "Created " << files.at(1) << " with data format " << formatToString(img.format()) << "\n";
<< formatToString(img.format()) << "\n";
return 0; return 0;
} }