mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-05-28 00:30:23 -04:00
Run clang-format on all cpp/h files
NO_CHANGELOG
This commit is contained in:
parent
04e276dcb3
commit
1169859b07
@ -35,61 +35,27 @@ private:
|
||||
QTest::addColumn<QImage::Format>("pngformat");
|
||||
QTest::addColumn<bool>("compress");
|
||||
|
||||
QTest::newRow("4x4 no alpha RLE")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< QString()
|
||||
<< false
|
||||
<< QImage::Format_RGB32
|
||||
<< true;
|
||||
QTest::newRow("4x4 no alpha RLE") << QFINDTESTDATA("pic/4x4-simple-color.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString() << false
|
||||
<< QImage::Format_RGB32 << true;
|
||||
|
||||
QTest::newRow("4x4 no alpha raw")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color-uncompressed.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< QString()
|
||||
<< false
|
||||
<< QImage::Format_RGB32
|
||||
<< false;
|
||||
QTest::newRow("4x4 no alpha raw") << QFINDTESTDATA("pic/4x4-simple-color-uncompressed.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString()
|
||||
<< false << QImage::Format_RGB32 << false;
|
||||
|
||||
QTest::newRow("Short comment")
|
||||
<< QFINDTESTDATA("pic/short-comment.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< QStringLiteral("Test comment value")
|
||||
<< false
|
||||
<< QImage::Format_RGB32
|
||||
<< true;
|
||||
QTest::newRow("Short comment") << QFINDTESTDATA("pic/short-comment.pic") << QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< QStringLiteral("Test comment value") << false << QImage::Format_RGB32 << true;
|
||||
|
||||
QTest::newRow("Long comment")
|
||||
<< QFINDTESTDATA("pic/long-comment.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< 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 comment") << QFINDTESTDATA("pic/long-comment.pic") << QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< 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")
|
||||
<< QFINDTESTDATA("pic/long-runs.pic")
|
||||
<< QFINDTESTDATA("pic/long-runs.png")
|
||||
<< QString()
|
||||
<< false
|
||||
<< QImage::Format_RGB32
|
||||
<< true;
|
||||
QTest::newRow("Long run-lengths") << QFINDTESTDATA("pic/long-runs.pic") << QFINDTESTDATA("pic/long-runs.png") << QString() << false
|
||||
<< QImage::Format_RGB32 << true;
|
||||
|
||||
QTest::newRow("4x4 with alpha RLE")
|
||||
<< QFINDTESTDATA("pic/4x4-alpha.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-alpha.png")
|
||||
<< QString()
|
||||
<< true
|
||||
<< QImage::Format_ARGB32
|
||||
<< true;
|
||||
QTest::newRow("4x4 with alpha RLE") << QFINDTESTDATA("pic/4x4-alpha.pic") << QFINDTESTDATA("pic/4x4-alpha.png") << QString() << true
|
||||
<< QImage::Format_ARGB32 << true;
|
||||
|
||||
QTest::newRow("4x4 with alpha raw")
|
||||
<< QFINDTESTDATA("pic/4x4-alpha-uncompressed.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-alpha.png")
|
||||
<< QString()
|
||||
<< true
|
||||
<< QImage::Format_ARGB32
|
||||
<< false;
|
||||
QTest::newRow("4x4 with alpha raw") << QFINDTESTDATA("pic/4x4-alpha-uncompressed.pic") << QFINDTESTDATA("pic/4x4-alpha.png") << QString() << true
|
||||
<< QImage::Format_ARGB32 << false;
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
@ -106,13 +72,8 @@ private Q_SLOTS:
|
||||
// so there is no actual data loss in converting to RGB16.
|
||||
// This just tests that the pic plugin can deal with different
|
||||
// input formats.
|
||||
QTest::newRow("altered format")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.pic")
|
||||
<< QFINDTESTDATA("pic/4x4-simple-color.png")
|
||||
<< QString()
|
||||
<< false
|
||||
<< QImage::Format_RGB16
|
||||
<< true;
|
||||
QTest::newRow("altered format") << QFINDTESTDATA("pic/4x4-simple-color.pic") << QFINDTESTDATA("pic/4x4-simple-color.png") << QString() << false
|
||||
<< QImage::Format_RGB16 << true;
|
||||
}
|
||||
|
||||
void testRead_data()
|
||||
@ -148,17 +109,12 @@ private Q_SLOTS:
|
||||
imgWriter.write(pngImage);
|
||||
|
||||
if (expData != picData) {
|
||||
QString fileNameBase = QUuid::createUuid().toString()
|
||||
.remove(QLatin1Char('{'))
|
||||
.remove(QLatin1Char('}'));
|
||||
QString fileNameBase = QUuid::createUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
|
||||
QFile dumpFile(fileNameBase + QStringLiteral(".pic"));
|
||||
QVERIFY2(dumpFile.open(QIODevice::WriteOnly), qPrintable(dumpFile.errorString()));
|
||||
dumpFile.write(picData);
|
||||
QString msg = QStringLiteral("Written data (")
|
||||
+ dumpFile.fileName()
|
||||
+ QStringLiteral(") differed from expected data (")
|
||||
+ picfile
|
||||
+ QLatin1Char(')');
|
||||
QString msg =
|
||||
QStringLiteral("Written data (") + dumpFile.fileName() + QStringLiteral(") differed from expected data (") + picfile + QLatin1Char(')');
|
||||
QFAIL(qPrintable(msg));
|
||||
}
|
||||
}
|
||||
@ -182,29 +138,20 @@ private Q_SLOTS:
|
||||
QCOMPARE(inputImage.width(), expImage.width());
|
||||
QCOMPARE(inputImage.height(), expImage.height());
|
||||
QCOMPARE(inputImage.hasAlphaChannel(), alpha);
|
||||
QCOMPARE(inputImage.format(), alpha ? QImage::Format_ARGB32
|
||||
: QImage::Format_RGB32);
|
||||
QCOMPARE(inputImage.format(), alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
|
||||
expImage = expImage.convertToFormat(pngformat);
|
||||
expImage = expImage.convertToFormat(alpha ? QImage::Format_ARGB32
|
||||
: QImage::Format_RGB32);
|
||||
expImage = expImage.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
if (inputImage != expImage) {
|
||||
QString fileNameBase = QUuid::createUuid().toString()
|
||||
.remove(QLatin1Char('{'))
|
||||
.remove(QLatin1Char('}'));
|
||||
QString fileNameBase = QUuid::createUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
|
||||
QFile picDumpFile(fileNameBase + QStringLiteral("-expected.data"));
|
||||
QVERIFY2(picDumpFile.open(QIODevice::WriteOnly), qPrintable(picDumpFile.errorString()));
|
||||
picDumpFile.write(reinterpret_cast<const char *>(inputImage.bits()),
|
||||
inputImage.sizeInBytes());
|
||||
picDumpFile.write(reinterpret_cast<const char *>(inputImage.bits()), inputImage.sizeInBytes());
|
||||
QFile pngDumpFile(fileNameBase + QStringLiteral("-actual.data"));
|
||||
QVERIFY2(pngDumpFile.open(QIODevice::WriteOnly), qPrintable(pngDumpFile.errorString()));
|
||||
pngDumpFile.write(reinterpret_cast<const char *>(expImage.bits()),
|
||||
expImage.sizeInBytes());
|
||||
QString msg = QStringLiteral("Read image (")
|
||||
+ picDumpFile.fileName()
|
||||
+ QStringLiteral(") differed from expected image (")
|
||||
+ pngDumpFile.fileName()
|
||||
+ QLatin1Char(')');
|
||||
pngDumpFile.write(reinterpret_cast<const char *>(expImage.bits()), expImage.sizeInBytes());
|
||||
QString msg = QStringLiteral("Read image (") + picDumpFile.fileName() + QStringLiteral(") differed from expected image (") + pngDumpFile.fileName()
|
||||
+ QLatin1Char(')');
|
||||
QFAIL(qPrintable(msg));
|
||||
}
|
||||
}
|
||||
@ -252,8 +199,7 @@ private Q_SLOTS:
|
||||
|
||||
QImageReader inputReader(picfile, "pic");
|
||||
|
||||
QCOMPARE(inputReader.imageFormat(),
|
||||
alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
QCOMPARE(inputReader.imageFormat(), alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -22,17 +22,12 @@ static void writeImageData(const char *name, const QString &filename, const QIma
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
qint64 written = file.write(reinterpret_cast<const char *>(image.bits()), image.sizeInBytes());
|
||||
if (written == image.sizeInBytes()) {
|
||||
QTextStream(stdout) << " " << name
|
||||
<< " written to " << filename << "\n";
|
||||
QTextStream(stdout) << " " << name << " written to " << filename << "\n";
|
||||
} else {
|
||||
QTextStream(stdout) << " could not write " << name
|
||||
<< " to " << filename << ":"
|
||||
<< file.errorString() << "\n";
|
||||
QTextStream(stdout) << " could not write " << name << " to " << filename << ":" << file.errorString() << "\n";
|
||||
}
|
||||
} else {
|
||||
QTextStream(stdout) << " could not open "
|
||||
<< filename << ":"
|
||||
<< file.errorString() << "\n";
|
||||
QTextStream(stdout) << " could not open " << filename << ":" << file.errorString() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,8 +40,8 @@ static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
||||
const int height = im1.height();
|
||||
const int width = im1.width();
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const Trait *line1 = reinterpret_cast<const Trait*>(im1.scanLine(i));
|
||||
const Trait *line2 = reinterpret_cast<const Trait*>(im2.scanLine(i));
|
||||
const Trait *line1 = reinterpret_cast<const Trait *>(im1.scanLine(i));
|
||||
const Trait *line2 = reinterpret_cast<const Trait *>(im2.scanLine(i));
|
||||
for (int j = 0; j < width; ++j) {
|
||||
if (line1[j] > line2[j]) {
|
||||
if (line1[j] - line2[j] > fuzziness)
|
||||
@ -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
|
||||
static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
||||
{
|
||||
return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness)
|
||||
: fuzzyeq<quint8>(im1, im2, fuzziness);
|
||||
return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness) : fuzzyeq<quint8>(im1, im2, fuzziness);
|
||||
}
|
||||
|
||||
// Returns the original format if we support, or returns
|
||||
@ -84,7 +78,7 @@ static QImage::Format preferredFormat(QImage::Format fmt)
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication::removeLibraryPath(QStringLiteral(PLUGIN_DIR));
|
||||
@ -97,10 +91,9 @@ int main(int argc, char ** argv)
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test"));
|
||||
QCommandLineOption fuzz(
|
||||
QStringList() << QStringLiteral("f") << QStringLiteral("fuzz"),
|
||||
QStringLiteral("Allow for some deviation in ARGB data."),
|
||||
QStringLiteral("max"));
|
||||
QCommandLineOption fuzz(QStringList() << QStringLiteral("f") << QStringLiteral("fuzz"),
|
||||
QStringLiteral("Allow for some deviation in ARGB data."),
|
||||
QStringLiteral("max"));
|
||||
parser.addOption(fuzz);
|
||||
|
||||
parser.process(app);
|
||||
@ -136,13 +129,14 @@ int main(int argc, char ** argv)
|
||||
int failed = 0;
|
||||
|
||||
QTextStream(stdout) << "********* "
|
||||
<< "Starting basic read tests for "
|
||||
<< suffix << " images *********\n";
|
||||
<< "Starting basic read tests for " << suffix << " images *********\n";
|
||||
|
||||
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||
QStringList formatStrings;
|
||||
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";
|
||||
|
||||
const QFileInfoList lstImgDir = imgdir.entryInfoList();
|
||||
@ -159,40 +153,27 @@ int main(int argc, char ** argv)
|
||||
QImage expImage;
|
||||
|
||||
if (!expReader.read(&expImage)) {
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName()
|
||||
<< ": could not load " << expfilename
|
||||
<< ": " << expReader.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << expfilename << ": " << expReader.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
if (!inputReader.canRead()) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": failed can read: "
|
||||
<< inputReader.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed can read: " << inputReader.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
if (!inputReader.read(&inputImage)) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": failed to load: "
|
||||
<< inputReader.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to load: " << inputReader.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
if (expImage.width() != inputImage.width()) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": width was " << inputImage.width()
|
||||
<< " but " << expfilename << " width was "
|
||||
<< expImage.width() << "\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": width was " << inputImage.width() << " but " << expfilename << " width was "
|
||||
<< expImage.width() << "\n";
|
||||
++failed;
|
||||
} else if (expImage.height() != inputImage.height()) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": height was " << inputImage.height()
|
||||
<< " but " << expfilename << " height was "
|
||||
<< expImage.height() << "\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": height was " << inputImage.height() << " but " << expfilename << " height was "
|
||||
<< expImage.height() << "\n";
|
||||
++failed;
|
||||
} else {
|
||||
QImage::Format inputFormat = preferredFormat(inputImage.format());
|
||||
@ -200,42 +181,30 @@ int main(int argc, char ** argv)
|
||||
QImage::Format cmpFormat = inputFormat == expFormat ? inputFormat : QImage::Format_ARGB32;
|
||||
|
||||
if (inputImage.format() != cmpFormat) {
|
||||
QTextStream(stdout) << "INFO : " << fi.fileName()
|
||||
<< ": converting " << fi.fileName()
|
||||
<< " from " << formatToString(inputImage.format())
|
||||
<< " to " << formatToString(cmpFormat) << '\n';
|
||||
QTextStream(stdout) << "INFO : " << fi.fileName() << ": converting " << fi.fileName() << " from " << formatToString(inputImage.format())
|
||||
<< " to " << formatToString(cmpFormat) << '\n';
|
||||
inputImage = inputImage.convertToFormat(cmpFormat);
|
||||
}
|
||||
if (expImage.format() != cmpFormat) {
|
||||
QTextStream(stdout) << "INFO : " << fi.fileName()
|
||||
<< ": converting " << expfilename
|
||||
<< " from " << formatToString(expImage.format())
|
||||
<< " to " << formatToString(cmpFormat) << '\n';
|
||||
QTextStream(stdout) << "INFO : " << fi.fileName() << ": converting " << expfilename << " from " << formatToString(expImage.format()) << " to "
|
||||
<< formatToString(cmpFormat) << '\n';
|
||||
expImage = expImage.convertToFormat(cmpFormat);
|
||||
}
|
||||
if (fuzzyeq(inputImage, expImage, fuzziness)) {
|
||||
QTextStream(stdout) << "PASS : " << fi.fileName() << "\n";
|
||||
++passed;
|
||||
} else {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": differs from " << expfilename << "\n";
|
||||
writeImageData("expected data",
|
||||
fi.fileName() + QLatin1String("-expected.data"),
|
||||
expImage);
|
||||
writeImageData("actual data",
|
||||
fi.fileName() + QLatin1String("-actual.data"),
|
||||
inputImage);
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": differs from " << expfilename << "\n";
|
||||
writeImageData("expected data", fi.fileName() + QLatin1String("-expected.data"), expImage);
|
||||
writeImageData("actual data", fi.fileName() + QLatin1String("-actual.data"), inputImage);
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QTextStream(stdout) << "Totals: "
|
||||
<< passed << " passed, "
|
||||
<< failed << " failed\n";
|
||||
QTextStream(stdout) << "Totals: " << passed << " passed, " << failed << " failed\n";
|
||||
QTextStream(stdout) << "********* "
|
||||
<< "Finished basic read tests for "
|
||||
<< suffix << " images *********\n";
|
||||
<< "Finished basic read tests for " << suffix << " images *********\n";
|
||||
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <QImageWriter>
|
||||
#include <QTextStream>
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication::removeLibraryPath(QStringLiteral(PLUGIN_DIR));
|
||||
@ -29,9 +29,8 @@ int main(int argc, char ** argv)
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument(QStringLiteral("format"), QStringLiteral("format to test."));
|
||||
QCommandLineOption lossless(
|
||||
QStringList() << QStringLiteral("l") << QStringLiteral("lossless"),
|
||||
QStringLiteral("Check that reading back the data gives the same image."));
|
||||
QCommandLineOption lossless(QStringList() << QStringLiteral("l") << QStringLiteral("lossless"),
|
||||
QStringLiteral("Check that reading back the data gives the same image."));
|
||||
parser.addOption(lossless);
|
||||
|
||||
parser.process(app);
|
||||
@ -56,8 +55,7 @@ int main(int argc, char ** argv)
|
||||
int failed = 0;
|
||||
|
||||
QTextStream(stdout) << "********* "
|
||||
<< "Starting basic write tests for "
|
||||
<< suffix << " images *********\n";
|
||||
<< "Starting basic write tests for " << suffix << " images *********\n";
|
||||
const QFileInfoList lstImgDir = imgdir.entryInfoList();
|
||||
for (const QFileInfo &fi : lstImgDir) {
|
||||
int suffixPos = fi.filePath().count() - suffix.count();
|
||||
@ -67,20 +65,14 @@ int main(int argc, char ** argv)
|
||||
QImageReader pngReader(pngfile, "png");
|
||||
QImage pngImage;
|
||||
if (!pngReader.read(&pngImage)) {
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName()
|
||||
<< ": could not load " << pngfilename
|
||||
<< ": " << pngReader.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << pngfilename << ": " << pngReader.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
|
||||
QFile expFile(fi.filePath());
|
||||
if (!expFile.open(QIODevice::ReadOnly)) {
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName()
|
||||
<< ": could not open " << fi.fileName()
|
||||
<< ": " << expFile.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not open " << fi.fileName() << ": " << expFile.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
@ -91,10 +83,7 @@ int main(int argc, char ** argv)
|
||||
char buf[1];
|
||||
qint64 result = expFile.read(buf, 1);
|
||||
if (result < 0) {
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName()
|
||||
<< ": could not load " << fi.fileName()
|
||||
<< ": " << expFile.errorString()
|
||||
<< "\n";
|
||||
QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not load " << fi.fileName() << ": " << expFile.errorString() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
@ -105,16 +94,14 @@ int main(int argc, char ** argv)
|
||||
QBuffer buffer(&writtenData);
|
||||
QImageWriter imgWriter(&buffer, format.constData());
|
||||
if (!imgWriter.write(pngImage)) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": failed to write image data\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed to write image data\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (expData != writtenData) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": written data differs from " << fi.fileName() << "\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": written data differs from " << fi.fileName() << "\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
@ -124,8 +111,7 @@ int main(int argc, char ** argv)
|
||||
QBuffer buffer(&writtenData);
|
||||
QImageReader imgReader(&buffer, format.constData());
|
||||
if (!imgReader.read(&reReadImage)) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": could not read back the written data\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": could not read back the written data\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
@ -134,8 +120,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
if (parser.isSet(lossless)) {
|
||||
if (pngImage != reReadImage) {
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName()
|
||||
<< ": re-reading the data resulted in a different image\n";
|
||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": re-reading the data resulted in a different image\n";
|
||||
++failed;
|
||||
continue;
|
||||
}
|
||||
@ -145,12 +130,9 @@ int main(int argc, char ** argv)
|
||||
++passed;
|
||||
}
|
||||
|
||||
QTextStream(stdout) << "Totals: "
|
||||
<< passed << " passed, "
|
||||
<< failed << " failed\n";
|
||||
QTextStream(stdout) << "Totals: " << passed << " passed, " << failed << " failed\n";
|
||||
QTextStream(stdout) << "********* "
|
||||
<< "Finished basic write tests for "
|
||||
<< suffix << " images *********\n";
|
||||
<< "Finished basic write tests for " << suffix << " images *********\n";
|
||||
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
|
@ -9,12 +9,11 @@
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
#include <QScopeGuard>
|
||||
#include <QtEndian>
|
||||
#include <QVariant>
|
||||
#include <QtEndian>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ChunkHeader {
|
||||
char magic[4];
|
||||
quint32_le size;
|
||||
@ -33,16 +32,16 @@ struct AniHeader {
|
||||
};
|
||||
|
||||
struct CurHeader {
|
||||
quint16_le wReserved; // always 0
|
||||
quint16_le wResID; // always 2
|
||||
quint16_le wNumImages;
|
||||
quint16_le wReserved; // always 0
|
||||
quint16_le wResID; // always 2
|
||||
quint16_le wNumImages;
|
||||
};
|
||||
|
||||
struct CursorDirEntry {
|
||||
quint8 bWidth;
|
||||
quint8 bHeight;
|
||||
quint8 bColorCount;
|
||||
quint8 bReserved; // always 0
|
||||
quint8 bReserved; // always 0
|
||||
quint16_le wHotspotX;
|
||||
quint16_le wHotspotY;
|
||||
quint32_le dwBytesInImage;
|
||||
@ -64,8 +63,7 @@ bool ANIHandler::canRead() const
|
||||
const QByteArray nextFrame = device()->peek(sizeof(ChunkHeader));
|
||||
if (nextFrame.size() == sizeof(ChunkHeader)) {
|
||||
const auto *header = reinterpret_cast<const ChunkHeader *>(nextFrame.data());
|
||||
if (qstrncmp(header->magic, "icon", sizeof(header->magic)) == 0
|
||||
&& header->size > 0) {
|
||||
if (qstrncmp(header->magic, "icon", sizeof(header->magic)) == 0 && header->size > 0) {
|
||||
setFormat("ani");
|
||||
return true;
|
||||
}
|
||||
@ -377,8 +375,7 @@ bool ANIHandler::ensureScanned() const
|
||||
mutableThis->m_displayRate = aniHeader->iDispRate;
|
||||
} else if (chunkId == "rate" || chunkId == "seq ") {
|
||||
const QByteArray data = device()->read(chunkSize);
|
||||
if (static_cast<quint32_le>(data.size()) != chunkSize
|
||||
|| data.size() % sizeof(quint32_le) != 0) {
|
||||
if (static_cast<quint32_le>(data.size()) != chunkSize || data.size() % sizeof(quint32_le) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -407,8 +404,8 @@ bool ANIHandler::ensureScanned() const
|
||||
mutableThis->m_imageSequence = list;
|
||||
}
|
||||
}
|
||||
// IART and INAM are technically inside LIST->INFO but "INFO" is supposedly optional
|
||||
// so just handle those two attributes wherever we encounter them
|
||||
// IART and INAM are technically inside LIST->INFO but "INFO" is supposedly optional
|
||||
// so just handle those two attributes wherever we encounter them
|
||||
} else if (chunkId == "INAM" || chunkId == "IART") {
|
||||
const QByteArray value = device()->read(chunkSize);
|
||||
|
||||
@ -455,8 +452,7 @@ bool ANIHandler::ensureScanned() const
|
||||
const QByteArray curHeaderData = device()->read(sizeof(CurHeader));
|
||||
const QByteArray cursorDirEntryData = device()->read(sizeof(CursorDirEntry));
|
||||
|
||||
if (curHeaderData.length() == sizeof(CurHeader)
|
||||
&& cursorDirEntryData.length() == sizeof(CursorDirEntry)) {
|
||||
if (curHeaderData.length() == sizeof(CurHeader) && cursorDirEntryData.length() == sizeof(CursorDirEntry)) {
|
||||
auto *cursorDirEntry = reinterpret_cast<const CursorDirEntry *>(cursorDirEntryData.data());
|
||||
mutableThis->m_size = QSize(cursorDirEntry->bWidth, cursorDirEntry->bHeight);
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ private:
|
||||
QString m_name;
|
||||
QString m_artist;
|
||||
QSize m_size;
|
||||
|
||||
};
|
||||
|
||||
class ANIPlugin : public QImageIOPlugin
|
||||
|
@ -6,23 +6,22 @@
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QThread>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <QColorSpace>
|
||||
|
||||
#include "avif_p.h"
|
||||
#include <cfloat>
|
||||
|
||||
|
||||
QAVIFHandler::QAVIFHandler() :
|
||||
m_parseState(ParseAvifNotParsed),
|
||||
m_quality(52),
|
||||
m_container_width(0),
|
||||
m_container_height(0),
|
||||
m_rawAvifData(AVIF_DATA_EMPTY),
|
||||
m_decoder(nullptr),
|
||||
m_must_jump_to_next_image(false)
|
||||
QAVIFHandler::QAVIFHandler()
|
||||
: m_parseState(ParseAvifNotParsed)
|
||||
, m_quality(52)
|
||||
, m_container_width(0)
|
||||
, m_container_height(0)
|
||||
, m_rawAvifData(AVIF_DATA_EMPTY)
|
||||
, m_decoder(nullptr)
|
||||
, m_must_jump_to_next_image(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,7 +56,7 @@ bool QAVIFHandler::canRead(QIODevice *device)
|
||||
}
|
||||
|
||||
avifROData input;
|
||||
input.data = (const uint8_t *) header.constData();
|
||||
input.data = (const uint8_t *)header.constData();
|
||||
input.size = header.size();
|
||||
|
||||
if (avifPeekCompatibleFileType(&input)) {
|
||||
@ -88,7 +87,7 @@ bool QAVIFHandler::ensureDecoder()
|
||||
|
||||
m_rawData = device()->readAll();
|
||||
|
||||
m_rawAvifData.data = (const uint8_t *) m_rawData.constData();
|
||||
m_rawAvifData.data = (const uint8_t *)m_rawData.constData();
|
||||
m_rawAvifData.size = m_rawData.size();
|
||||
|
||||
if (avifPeekCompatibleFileType(&m_rawAvifData) == AVIF_FALSE) {
|
||||
@ -96,7 +95,6 @@ bool QAVIFHandler::ensureDecoder()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_decoder = avifDecoderCreate();
|
||||
|
||||
avifResult decodeResult;
|
||||
@ -124,7 +122,6 @@ bool QAVIFHandler::ensureDecoder()
|
||||
decodeResult = avifDecoderNextImage(m_decoder);
|
||||
|
||||
if (decodeResult == AVIF_RESULT_OK) {
|
||||
|
||||
m_container_width = m_decoder->image->width;
|
||||
m_container_height = m_decoder->image->height;
|
||||
|
||||
@ -194,12 +191,12 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
|
||||
if (m_decoder->image->icc.data && (m_decoder->image->icc.size > 0)) {
|
||||
result.setColorSpace(QColorSpace::fromIccProfile(QByteArray::fromRawData((const char *) m_decoder->image->icc.data, (int) m_decoder->image->icc.size)));
|
||||
if (! result.colorSpace().isValid()) {
|
||||
result.setColorSpace(QColorSpace::fromIccProfile(QByteArray::fromRawData((const char *)m_decoder->image->icc.data, (int)m_decoder->image->icc.size)));
|
||||
if (!result.colorSpace().isValid()) {
|
||||
qWarning("Invalid QColorSpace created from ICC!");
|
||||
}
|
||||
} else {
|
||||
float prim[8] = { 0.64f, 0.33f, 0.3f, 0.6f, 0.15f, 0.06f, 0.3127f, 0.329f };
|
||||
float prim[8] = {0.64f, 0.33f, 0.3f, 0.6f, 0.15f, 0.06f, 0.3127f, 0.329f};
|
||||
// outPrimaries: rX, rY, gX, gY, bX, bY, wX, wY
|
||||
avifColorPrimariesGetValues(m_decoder->image->colorPrimaries, prim);
|
||||
|
||||
@ -208,7 +205,6 @@ bool QAVIFHandler::decode_one_frame()
|
||||
const QPointF bluePoint(QAVIFHandler::CompatibleChromacity(prim[4], prim[5]));
|
||||
const QPointF whitePoint(QAVIFHandler::CompatibleChromacity(prim[6], prim[7]));
|
||||
|
||||
|
||||
QColorSpace::TransferFunction q_trc = QColorSpace::TransferFunction::Custom;
|
||||
float q_trc_gamma = 0.0f;
|
||||
|
||||
@ -231,16 +227,17 @@ bool QAVIFHandler::decode_one_frame()
|
||||
case 0:
|
||||
case 2: /* AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED */
|
||||
case 13:
|
||||
q_trc = QColorSpace::TransferFunction::SRgb;
|
||||
q_trc = QColorSpace::TransferFunction::SRgb;
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (q_trc != QColorSpace::TransferFunction::Custom) { //we create new colorspace using Qt
|
||||
if (q_trc != QColorSpace::TransferFunction::Custom) { // we create new colorspace using Qt
|
||||
switch (m_decoder->image->colorPrimaries) {
|
||||
/* AVIF_COLOR_PRIMARIES_BT709 */
|
||||
case 0:
|
||||
@ -258,7 +255,7 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
}
|
||||
|
||||
if (! result.colorSpace().isValid()) {
|
||||
if (!result.colorSpace().isValid()) {
|
||||
qWarning("Invalid QColorSpace created from NCLX/CICP!");
|
||||
}
|
||||
}
|
||||
@ -303,11 +300,11 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
|
||||
if (m_decoder->image->transformFlags & AVIF_TRANSFORM_CLAP) {
|
||||
if ((m_decoder->image->clap.widthD > 0) && (m_decoder->image->clap.heightD > 0) &&
|
||||
(m_decoder->image->clap.horizOffD > 0) && (m_decoder->image->clap.vertOffD > 0)) {
|
||||
int new_width, new_height, offx, offy;
|
||||
if ((m_decoder->image->clap.widthD > 0) && (m_decoder->image->clap.heightD > 0) && (m_decoder->image->clap.horizOffD > 0)
|
||||
&& (m_decoder->image->clap.vertOffD > 0)) {
|
||||
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);
|
||||
if (new_width > result.width()) {
|
||||
new_width = result.width();
|
||||
}
|
||||
@ -318,17 +315,14 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
|
||||
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) {
|
||||
offx = 0;
|
||||
} else if (offx > (result.width() - new_width)) {
|
||||
offx = result.width() - new_width;
|
||||
}
|
||||
|
||||
offy = ((double)((int32_t) m_decoder->image->clap.vertOffN)) / (m_decoder->image->clap.vertOffD) +
|
||||
(result.height() - new_height) / 2.0 + 0.5;
|
||||
offy = ((double)((int32_t)m_decoder->image->clap.vertOffN)) / (m_decoder->image->clap.vertOffD) + (result.height() - new_height) / 2.0 + 0.5;
|
||||
if (offy < 0) {
|
||||
offy = 0;
|
||||
} else if (offy > (result.height() - new_height)) {
|
||||
@ -339,7 +333,7 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
}
|
||||
|
||||
else { //Zero values, we need to avoid 0 divide.
|
||||
else { // Zero values, we need to avoid 0 divide.
|
||||
qWarning("ERROR: Wrong values in avifCleanApertureBox");
|
||||
}
|
||||
}
|
||||
@ -364,10 +358,10 @@ bool QAVIFHandler::decode_one_frame()
|
||||
|
||||
if (m_decoder->image->transformFlags & AVIF_TRANSFORM_IMIR) {
|
||||
switch (m_decoder->image->imir.axis) {
|
||||
case 0: //vertical
|
||||
case 0: // vertical
|
||||
result = result.mirrored(false, true);
|
||||
break;
|
||||
case 1: //horizontal
|
||||
case 1: // horizontal
|
||||
result = result.mirrored(true, false);
|
||||
break;
|
||||
}
|
||||
@ -417,13 +411,13 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
int maxQuantizerAlpha = 0;
|
||||
avifResult res;
|
||||
|
||||
bool save_grayscale; //true - monochrome, false - colors
|
||||
int save_depth; //8 or 10bit per channel
|
||||
QImage::Format tmpformat; //format for temporary image
|
||||
bool save_grayscale; // true - monochrome, false - colors
|
||||
int save_depth; // 8 or 10bit per channel
|
||||
QImage::Format tmpformat; // format for temporary image
|
||||
|
||||
avifImage *avif = nullptr;
|
||||
|
||||
//grayscale detection
|
||||
// grayscale detection
|
||||
switch (image.format()) {
|
||||
case QImage::Format_Mono:
|
||||
case QImage::Format_MonoLSB:
|
||||
@ -439,7 +433,7 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
break;
|
||||
}
|
||||
|
||||
//depth detection
|
||||
// depth detection
|
||||
switch (image.format()) {
|
||||
case QImage::Format_BGR30:
|
||||
case QImage::Format_A2BGR30_Premultiplied:
|
||||
@ -460,15 +454,15 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
break;
|
||||
}
|
||||
|
||||
//quality settings
|
||||
// quality settings
|
||||
if (maxQuantizer > 20) {
|
||||
minQuantizer = maxQuantizer - 20;
|
||||
if (maxQuantizer > 40) { //we decrease quality of alpha channel here
|
||||
if (maxQuantizer > 40) { // we decrease quality of alpha channel here
|
||||
maxQuantizerAlpha = maxQuantizer - 40;
|
||||
}
|
||||
}
|
||||
|
||||
if (save_grayscale && !image.hasAlphaChannel()) { //we are going to save grayscale image without alpha channel
|
||||
if (save_grayscale && !image.hasAlphaChannel()) { // we are going to save grayscale image without alpha channel
|
||||
if (save_depth > 8) {
|
||||
tmpformat = QImage::Format_Grayscale16;
|
||||
} else {
|
||||
@ -496,7 +490,6 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
/* AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (save_depth > 8) { // QImage::Format_Grayscale16
|
||||
@ -504,7 +497,7 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
const uint16_t *src16bit = reinterpret_cast<const uint16_t *>(tmpgrayimage.constScanLine(y));
|
||||
uint16_t *dest16bit = reinterpret_cast<uint16_t *>(avif->yuvPlanes[0] + y * avif->yuvRowBytes[0]);
|
||||
for (int x = 0; x < tmpgrayimage.width(); x++) {
|
||||
int tmp_pixelval = (int)(((float)(*src16bit) / 65535.0f) * 1023.0f + 0.5f); //downgrade to 10 bits
|
||||
int tmp_pixelval = (int)(((float)(*src16bit) / 65535.0f) * 1023.0f + 0.5f); // downgrade to 10 bits
|
||||
*dest16bit = qBound(0, tmp_pixelval, 1023);
|
||||
dest16bit++;
|
||||
src16bit++;
|
||||
@ -522,14 +515,14 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
}
|
||||
}
|
||||
|
||||
} else { //we are going to save color image
|
||||
} else { // we are going to save color image
|
||||
if (save_depth > 8) {
|
||||
if (image.hasAlphaChannel()) {
|
||||
tmpformat = QImage::Format_RGBA64;
|
||||
} else {
|
||||
tmpformat = QImage::Format_RGBX64;
|
||||
}
|
||||
} else { //8bit depth
|
||||
} else { // 8bit depth
|
||||
if (image.hasAlphaChannel()) {
|
||||
tmpformat = QImage::Format_RGBA8888;
|
||||
} else {
|
||||
@ -542,13 +535,13 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
avifPixelFormat pixel_format = AVIF_PIXEL_FORMAT_YUV420;
|
||||
if (maxQuantizer < 20) {
|
||||
if (maxQuantizer < 10) {
|
||||
pixel_format = AVIF_PIXEL_FORMAT_YUV444; //best quality
|
||||
pixel_format = AVIF_PIXEL_FORMAT_YUV444; // best quality
|
||||
} else {
|
||||
pixel_format = AVIF_PIXEL_FORMAT_YUV422; //high quality
|
||||
pixel_format = AVIF_PIXEL_FORMAT_YUV422; // high quality
|
||||
}
|
||||
}
|
||||
|
||||
avifMatrixCoefficients matrix_to_save = (avifMatrixCoefficients)1; //default for Qt 5.12 and 5.13;
|
||||
avifMatrixCoefficients matrix_to_save = (avifMatrixCoefficients)1; // default for Qt 5.12 and 5.13;
|
||||
|
||||
avifColorPrimaries primaries_to_save = (avifColorPrimaries)2;
|
||||
avifTransferCharacteristics transfer_to_save = (avifTransferCharacteristics)2;
|
||||
@ -602,11 +595,9 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
break;
|
||||
}
|
||||
|
||||
//in case primaries or trc were not identified
|
||||
if ((primaries_to_save == 2) ||
|
||||
(transfer_to_save == 2)) {
|
||||
|
||||
//upgrade image to higher bit depth
|
||||
// in case primaries or trc were not identified
|
||||
if ((primaries_to_save == 2) || (transfer_to_save == 2)) {
|
||||
// upgrade image to higher bit depth
|
||||
if (save_depth == 8) {
|
||||
save_depth = 10;
|
||||
if (tmpcolorimage.hasAlphaChannel()) {
|
||||
@ -616,8 +607,7 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
}
|
||||
}
|
||||
|
||||
if ((primaries_to_save == 2) &&
|
||||
(transfer_to_save != 2)) { //other primaries but known trc
|
||||
if ((primaries_to_save == 2) && (transfer_to_save != 2)) { // other primaries but known trc
|
||||
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
||||
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
||||
|
||||
@ -636,11 +626,10 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
transfer_to_save = (avifTransferCharacteristics)13;
|
||||
break;
|
||||
}
|
||||
} else if ((primaries_to_save != 2) &&
|
||||
(transfer_to_save == 2)) { //recognized primaries but other trc
|
||||
} else if ((primaries_to_save != 2) && (transfer_to_save == 2)) { // recognized primaries but other trc
|
||||
transfer_to_save = (avifTransferCharacteristics)13;
|
||||
tmpcolorimage.convertToColorSpace(tmpcolorimage.colorSpace().withTransferFunction(QColorSpace::TransferFunction::SRgb));
|
||||
} else { //unrecognized profile
|
||||
} else { // unrecognized profile
|
||||
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
||||
transfer_to_save = (avifTransferCharacteristics)13;
|
||||
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
||||
@ -659,7 +648,7 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
rgb.rowBytes = tmpcolorimage.bytesPerLine();
|
||||
rgb.pixels = const_cast<uint8_t *>(tmpcolorimage.constBits());
|
||||
|
||||
if (save_depth > 8) { //10bit depth
|
||||
if (save_depth > 8) { // 10bit depth
|
||||
rgb.depth = 16;
|
||||
|
||||
if (tmpcolorimage.hasAlphaChannel()) {
|
||||
@ -669,7 +658,7 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
}
|
||||
|
||||
rgb.format = AVIF_RGB_FORMAT_RGBA;
|
||||
} else { //8bit depth
|
||||
} else { // 8bit depth
|
||||
rgb.depth = 8;
|
||||
|
||||
if (tmpcolorimage.hasAlphaChannel()) {
|
||||
@ -721,7 +710,6 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QVariant QAVIFHandler::option(ImageOption option) const
|
||||
{
|
||||
if (option == Quality) {
|
||||
@ -765,9 +753,7 @@ void QAVIFHandler::setOption(ImageOption option, const QVariant &value)
|
||||
|
||||
bool QAVIFHandler::supportsOption(ImageOption option) const
|
||||
{
|
||||
return option == Quality
|
||||
|| option == Size
|
||||
|| option == Animation;
|
||||
return option == Quality || option == Size || option == Animation;
|
||||
}
|
||||
|
||||
int QAVIFHandler::imageCount() const
|
||||
@ -805,7 +791,7 @@ bool QAVIFHandler::jumpToNextImage()
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_decoder->imageIndex >= m_decoder->imageCount - 1) { //start from begining
|
||||
if (m_decoder->imageIndex >= m_decoder->imageCount - 1) { // start from begining
|
||||
avifDecoderReset(m_decoder);
|
||||
}
|
||||
|
||||
@ -817,11 +803,12 @@ bool QAVIFHandler::jumpToNextImage()
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_container_width != m_decoder->image->width) ||
|
||||
(m_container_height != m_decoder->image->height)) {
|
||||
if ((m_container_width != m_decoder->image->width) || (m_container_height != m_decoder->image->height)) {
|
||||
qWarning("Decoded image sequence size (%dx%d) do not match first image size (%dx%d)!",
|
||||
m_decoder->image->width, m_decoder->image->height,
|
||||
m_container_width, m_container_height);
|
||||
m_decoder->image->width,
|
||||
m_decoder->image->height,
|
||||
m_container_width,
|
||||
m_container_height);
|
||||
|
||||
m_parseState = ParseAvifError;
|
||||
return false;
|
||||
@ -833,7 +820,6 @@ bool QAVIFHandler::jumpToNextImage()
|
||||
m_parseState = ParseAvifError;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool QAVIFHandler::jumpToImage(int imageNumber)
|
||||
@ -842,7 +828,7 @@ bool QAVIFHandler::jumpToImage(int imageNumber)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_decoder->imageCount < 2) { //not an animation
|
||||
if (m_decoder->imageCount < 2) { // not an animation
|
||||
if (imageNumber == 0) {
|
||||
return true;
|
||||
} else {
|
||||
@ -850,11 +836,11 @@ bool QAVIFHandler::jumpToImage(int imageNumber)
|
||||
}
|
||||
}
|
||||
|
||||
if (imageNumber < 0 || imageNumber >= m_decoder->imageCount) { //wrong index
|
||||
if (imageNumber < 0 || imageNumber >= m_decoder->imageCount) { // wrong index
|
||||
return false;
|
||||
}
|
||||
|
||||
if (imageNumber == m_decoder->imageCount) { // we are here already
|
||||
if (imageNumber == m_decoder->imageCount) { // we are here already
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -866,11 +852,12 @@ bool QAVIFHandler::jumpToImage(int imageNumber)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_container_width != m_decoder->image->width) ||
|
||||
(m_container_height != m_decoder->image->height)) {
|
||||
if ((m_container_width != m_decoder->image->width) || (m_container_height != m_decoder->image->height)) {
|
||||
qWarning("Decoded image sequence size (%dx%d) do not match declared container size (%dx%d)!",
|
||||
m_decoder->image->width, m_decoder->image->height,
|
||||
m_container_width, m_container_height);
|
||||
m_decoder->image->width,
|
||||
m_decoder->image->height,
|
||||
m_container_width,
|
||||
m_container_height);
|
||||
|
||||
m_parseState = ParseAvifError;
|
||||
return false;
|
||||
|
@ -9,74 +9,74 @@
|
||||
#ifndef KIMG_AVIF_P_H
|
||||
#define KIMG_AVIF_P_H
|
||||
|
||||
#include <QImage>
|
||||
#include <QVariant>
|
||||
#include <qimageiohandler.h>
|
||||
#include <QImageIOPlugin>
|
||||
#include <QByteArray>
|
||||
#include <QImage>
|
||||
#include <QImageIOPlugin>
|
||||
#include <QPointF>
|
||||
#include <QVariant>
|
||||
#include <avif/avif.h>
|
||||
#include <qimageiohandler.h>
|
||||
|
||||
class QAVIFHandler : public QImageIOHandler
|
||||
{
|
||||
public:
|
||||
QAVIFHandler();
|
||||
~QAVIFHandler();
|
||||
QAVIFHandler();
|
||||
~QAVIFHandler();
|
||||
|
||||
bool canRead() const override;
|
||||
bool read (QImage *image) override;
|
||||
bool write (const QImage &image) override;
|
||||
bool canRead() const override;
|
||||
bool read(QImage *image) override;
|
||||
bool write(const QImage &image) override;
|
||||
|
||||
static bool canRead (QIODevice *device);
|
||||
static bool canRead(QIODevice *device);
|
||||
|
||||
QVariant option (ImageOption option) const override;
|
||||
void setOption (ImageOption option, const QVariant &value) override;
|
||||
bool supportsOption (ImageOption option) const override;
|
||||
QVariant option(ImageOption option) const override;
|
||||
void setOption(ImageOption option, const QVariant &value) override;
|
||||
bool supportsOption(ImageOption option) const override;
|
||||
|
||||
int imageCount() const override;
|
||||
int currentImageNumber() const override;
|
||||
bool jumpToNextImage() override;
|
||||
bool jumpToImage (int imageNumber) override;
|
||||
int imageCount() const override;
|
||||
int currentImageNumber() const override;
|
||||
bool jumpToNextImage() override;
|
||||
bool jumpToImage(int imageNumber) override;
|
||||
|
||||
int nextImageDelay() const override;
|
||||
int nextImageDelay() const override;
|
||||
|
||||
int loopCount() const override;
|
||||
|
||||
int loopCount() const override;
|
||||
private:
|
||||
static QPointF CompatibleChromacity(qreal chrX, qreal chrY);
|
||||
bool ensureParsed() const;
|
||||
bool ensureDecoder();
|
||||
bool decode_one_frame();
|
||||
static QPointF CompatibleChromacity(qreal chrX, qreal chrY);
|
||||
bool ensureParsed() const;
|
||||
bool ensureDecoder();
|
||||
bool decode_one_frame();
|
||||
|
||||
enum ParseAvifState
|
||||
{
|
||||
ParseAvifError = -1,
|
||||
ParseAvifNotParsed = 0,
|
||||
ParseAvifSuccess = 1,
|
||||
};
|
||||
enum ParseAvifState {
|
||||
ParseAvifError = -1,
|
||||
ParseAvifNotParsed = 0,
|
||||
ParseAvifSuccess = 1,
|
||||
};
|
||||
|
||||
ParseAvifState m_parseState;
|
||||
int m_quality;
|
||||
ParseAvifState m_parseState;
|
||||
int m_quality;
|
||||
|
||||
uint32_t m_container_width;
|
||||
uint32_t m_container_height;
|
||||
uint32_t m_container_width;
|
||||
uint32_t m_container_height;
|
||||
|
||||
QByteArray m_rawData;
|
||||
avifROData m_rawAvifData;
|
||||
QByteArray m_rawData;
|
||||
avifROData m_rawAvifData;
|
||||
|
||||
avifDecoder *m_decoder;
|
||||
QImage m_current_image;
|
||||
avifDecoder *m_decoder;
|
||||
QImage m_current_image;
|
||||
|
||||
bool m_must_jump_to_next_image;
|
||||
bool m_must_jump_to_next_image;
|
||||
};
|
||||
|
||||
class QAVIFPlugin : public QImageIOPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA (IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "avif.json")
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "avif.json")
|
||||
|
||||
public:
|
||||
Capabilities capabilities (QIODevice *device, const QByteArray &format) const override;
|
||||
QImageIOHandler *create (QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||
Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
|
||||
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||
};
|
||||
|
||||
#endif // KIMG_AVIF_P_H
|
||||
|
@ -9,13 +9,13 @@
|
||||
*/
|
||||
#include "eps_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QPainter>
|
||||
#include <QPrinter>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
#include <QCoreApplication>
|
||||
|
||||
// logging category for this framework, default: log stuff >= warning
|
||||
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;
|
||||
}
|
||||
ps_offset // Offset is in little endian
|
||||
= qint64(((unsigned char)buf[0])
|
||||
+ ((unsigned char)buf[1] << 8)
|
||||
+ ((unsigned char)buf[2] << 16)
|
||||
+ ((unsigned char)buf[3] << 24));
|
||||
= qint64(((unsigned char)buf[0]) + ((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.
|
||||
qCDebug(EPSPLUGIN) << "cannot read size of MS-DOS EPS file";
|
||||
return false;
|
||||
}
|
||||
ps_size // Size is in little endian
|
||||
= qint64(((unsigned char)buf[0])
|
||||
+ ((unsigned char)buf[1] << 8)
|
||||
+ ((unsigned char)buf[2] << 16)
|
||||
+ ((unsigned char)buf[3] << 24));
|
||||
= qint64(((unsigned char)buf[0]) + ((unsigned char)buf[1] << 8) + ((unsigned char)buf[2] << 16) + ((unsigned char)buf[3] << 24));
|
||||
qCDebug(EPSPLUGIN) << "Offset: " << ps_offset << " Size: " << ps_size;
|
||||
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";
|
||||
@ -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
|
||||
// We don't support that currently, but at least we parse it
|
||||
float _x1, _y1, _x2, _y2;
|
||||
if (sscanf(buf, "%*s %f %f %f %f",
|
||||
&_x1, &_y1, &_x2, &_y2) == 4) {
|
||||
if (sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4) {
|
||||
qCDebug(EPSPLUGIN) << "BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2;
|
||||
*x1 = int(_x1);
|
||||
*y1 = int(_y1);
|
||||
@ -177,23 +170,17 @@ bool EPSHandler::read(QImage *image)
|
||||
// create GS command line
|
||||
|
||||
QStringList gsArgs;
|
||||
gsArgs << QLatin1String("-sOutputFile=") + tmpFile.fileName()
|
||||
<< QStringLiteral("-q")
|
||||
<< QStringLiteral("-g%1x%2").arg(wantedWidth).arg(wantedHeight)
|
||||
<< QStringLiteral("-dSAFER")
|
||||
<< QStringLiteral("-dPARANOIDSAFER")
|
||||
<< QStringLiteral("-dNOPAUSE")
|
||||
<< QStringLiteral("-sDEVICE=ppm")
|
||||
gsArgs << QLatin1String("-sOutputFile=") + tmpFile.fileName() << QStringLiteral("-q") << QStringLiteral("-g%1x%2").arg(wantedWidth).arg(wantedHeight)
|
||||
<< QStringLiteral("-dSAFER") << QStringLiteral("-dPARANOIDSAFER") << QStringLiteral("-dNOPAUSE") << QStringLiteral("-sDEVICE=ppm")
|
||||
<< QStringLiteral("-c")
|
||||
<< QStringLiteral("0 0 moveto "
|
||||
"1000 0 lineto "
|
||||
"1000 1000 lineto "
|
||||
"0 1000 lineto "
|
||||
"1 1 254 255 div setrgbcolor fill "
|
||||
"0 0 0 setrgbcolor")
|
||||
<< QStringLiteral("-")
|
||||
<< QStringLiteral("-c")
|
||||
<< QStringLiteral("showpage quit");
|
||||
<< QStringLiteral(
|
||||
"0 0 moveto "
|
||||
"1000 0 lineto "
|
||||
"1000 1000 lineto "
|
||||
"0 1000 lineto "
|
||||
"1 1 254 255 div setrgbcolor fill "
|
||||
"0 0 0 setrgbcolor")
|
||||
<< QStringLiteral("-") << QStringLiteral("-c") << QStringLiteral("showpage quit");
|
||||
qCDebug(EPSPLUGIN) << "Running gs with args" << gsArgs;
|
||||
|
||||
QProcess converter;
|
||||
@ -277,24 +264,16 @@ bool EPSHandler::write(const QImage &image)
|
||||
|
||||
// pdftops comes with Poppler and produces much smaller EPS files than GhostScript
|
||||
QStringList pdftopsArgs;
|
||||
pdftopsArgs << QStringLiteral("-eps")
|
||||
<< tmpFile.fileName()
|
||||
<< QStringLiteral("-");
|
||||
pdftopsArgs << QStringLiteral("-eps") << tmpFile.fileName() << QStringLiteral("-");
|
||||
qCDebug(EPSPLUGIN) << "Running pdftops with args" << pdftopsArgs;
|
||||
converter.start(QStringLiteral("pdftops"), pdftopsArgs);
|
||||
|
||||
if (!converter.waitForStarted()) {
|
||||
// GhostScript produces huge files, and takes a long time doing so
|
||||
QStringList gsArgs;
|
||||
gsArgs << QStringLiteral("-q") << QStringLiteral("-P-")
|
||||
<< QStringLiteral("-dNOPAUSE") << QStringLiteral("-dBATCH")
|
||||
<< QStringLiteral("-dSAFER")
|
||||
<< QStringLiteral("-sDEVICE=epswrite")
|
||||
<< QStringLiteral("-sOutputFile=-")
|
||||
<< QStringLiteral("-c")
|
||||
<< QStringLiteral("save") << QStringLiteral("pop")
|
||||
<< QStringLiteral("-f")
|
||||
<< tmpFile.fileName();
|
||||
gsArgs << QStringLiteral("-q") << QStringLiteral("-P-") << QStringLiteral("-dNOPAUSE") << QStringLiteral("-dBATCH") << QStringLiteral("-dSAFER")
|
||||
<< 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;
|
||||
converter.start(QStringLiteral("gs"), gsArgs);
|
||||
|
||||
|
@ -35,4 +35,3 @@ public:
|
||||
Q_DECLARE_LOGGING_CATEGORY(EPSPLUGIN)
|
||||
|
||||
#endif // KIMG_EPS_P_H
|
||||
|
||||
|
@ -9,39 +9,40 @@
|
||||
|
||||
#include "exr_p.h"
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfStandardAttributes.h>
|
||||
#include <IexThrowErrnoExc.h>
|
||||
#include <ImathBox.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfBoxAttribute.h>
|
||||
#include <ImfChannelListAttribute.h>
|
||||
#include <ImfCompressionAttribute.h>
|
||||
#include <ImfConvert.h>
|
||||
#include <ImfFloatAttribute.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfIntAttribute.h>
|
||||
#include <ImfLineOrderAttribute.h>
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfStandardAttributes.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfVecAttribute.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfConvert.h>
|
||||
#include <ImfVersion.h>
|
||||
#include <IexThrowErrnoExc.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QImage>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
#include <QImageIOPlugin>
|
||||
|
||||
class K_IStream: public Imf::IStream
|
||||
class K_IStream : public Imf::IStream
|
||||
{
|
||||
public:
|
||||
K_IStream(QIODevice *dev, const QByteArray &fileName):
|
||||
IStream(fileName.data()), m_dev(dev)
|
||||
K_IStream(QIODevice *dev, const QByteArray &fileName)
|
||||
: IStream(fileName.data())
|
||||
, m_dev(dev)
|
||||
{
|
||||
}
|
||||
|
||||
bool read(char c[], int n) override;
|
||||
bool read(char c[], int n) override;
|
||||
Imf::Int64 tellg() override;
|
||||
void seekg(Imf::Int64 pos) override;
|
||||
void clear() override;
|
||||
@ -128,19 +129,19 @@ QRgb RgbaToQrgba(struct Imf::Rgba &imagePixel)
|
||||
if (a > 1.0) {
|
||||
a = 1.0 + Imath::Math<float>::log((a - 1.0) * 0.184874 + 1) / 0.184874;
|
||||
}
|
||||
//
|
||||
// 5) Gamma-correct the pixel values, assuming that the
|
||||
// screen's gamma is 0.4545 (or 1/2.2).
|
||||
//
|
||||
// 5) Gamma-correct the pixel values, assuming that the
|
||||
// screen's gamma is 0.4545 (or 1/2.2).
|
||||
r = Imath::Math<float>::pow(r, 0.4545);
|
||||
g = Imath::Math<float>::pow(g, 0.4545);
|
||||
b = Imath::Math<float>::pow(b, 0.4545);
|
||||
a = Imath::Math<float>::pow(a, 0.4545);
|
||||
|
||||
// 6) Scale the values such that pixels middle gray
|
||||
// pixels are mapped to 84.66 (or 3.5 f-stops below
|
||||
// the display's maximum intensity).
|
||||
//
|
||||
// 7) Clamp the values to [0, 255].
|
||||
// 6) Scale the values such that pixels middle gray
|
||||
// pixels are mapped to 84.66 (or 3.5 f-stops below
|
||||
// the display's maximum intensity).
|
||||
//
|
||||
// 7) Clamp the values to [0, 255].
|
||||
return qRgba((unsigned char)(Imath::clamp(r * 84.66f, 0.f, 255.f)),
|
||||
(unsigned char)(Imath::clamp(g * 84.66f, 0.f, 255.f)),
|
||||
(unsigned char)(Imath::clamp(b * 84.66f, 0.f, 255.f)),
|
||||
@ -169,7 +170,7 @@ bool EXRHandler::read(QImage *outImage)
|
||||
Imf::RgbaInputFile file(istr);
|
||||
Imath::Box2i dw = file.dataWindow();
|
||||
|
||||
width = dw.max.x - dw.min.x + 1;
|
||||
width = dw.max.x - dw.min.x + 1;
|
||||
height = dw.max.y - dw.min.y + 1;
|
||||
|
||||
QImage image(width, height, QImage::Format_RGB32);
|
||||
@ -196,7 +197,7 @@ bool EXRHandler::read(QImage *outImage)
|
||||
|
||||
return true;
|
||||
} catch (const std::exception &exc) {
|
||||
// qDebug() << exc.what();
|
||||
// qDebug() << exc.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,13 @@ typedef unsigned char uchar;
|
||||
// From GIMP "tile.h" v1.2
|
||||
|
||||
const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file.
|
||||
const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
|
||||
const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
|
||||
|
||||
// From GIMP "paint_funcs.c" v1.2
|
||||
|
||||
const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table.
|
||||
const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table.
|
||||
const double EPSILON = 0.0001; //!< Roundup in alpha blending.
|
||||
const double EPSILON = 0.0001; //!< Roundup in alpha blending.
|
||||
|
||||
// From GIMP "paint_funcs.h" v1.2
|
||||
|
||||
@ -44,7 +44,6 @@ typedef enum {
|
||||
INDEXED,
|
||||
} GimpImageBaseType;
|
||||
|
||||
|
||||
// From GIMP "libgimp/gimpenums.h" v2.4
|
||||
|
||||
//! Effect to apply when layers are merged together.
|
||||
@ -74,7 +73,6 @@ typedef enum {
|
||||
GRAIN_MERGE_MODE
|
||||
} LayerModeEffects;
|
||||
|
||||
|
||||
// From GIMP "paint_funcs.c" v1.2
|
||||
|
||||
/*!
|
||||
@ -163,9 +161,9 @@ static void RGBTOHSV(uchar &red, uchar &green, uchar &blue)
|
||||
}
|
||||
}
|
||||
|
||||
red = (uchar)h;
|
||||
red = (uchar)h;
|
||||
green = (uchar)s;
|
||||
blue = (uchar)v;
|
||||
blue = (uchar)v;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -177,9 +175,9 @@ static void RGBTOHSV(uchar &red, uchar &green, uchar &blue)
|
||||
static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
|
||||
{
|
||||
if (saturation == 0) {
|
||||
hue = value;
|
||||
hue = value;
|
||||
saturation = value;
|
||||
//value = value;
|
||||
// value = value;
|
||||
} else {
|
||||
double h = hue * 6. / 255.;
|
||||
double s = saturation / 255.;
|
||||
@ -195,34 +193,34 @@ static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
|
||||
|
||||
switch ((int)h) {
|
||||
case 0:
|
||||
hue = (uchar)(v * 255);
|
||||
hue = (uchar)(v * 255);
|
||||
saturation = (uchar)(t * 255);
|
||||
value = (uchar)(p * 255);
|
||||
value = (uchar)(p * 255);
|
||||
break;
|
||||
case 1:
|
||||
hue = (uchar)(q * 255);
|
||||
hue = (uchar)(q * 255);
|
||||
saturation = (uchar)(v * 255);
|
||||
value = (uchar)(p * 255);
|
||||
value = (uchar)(p * 255);
|
||||
break;
|
||||
case 2:
|
||||
hue = (uchar)(p * 255);
|
||||
hue = (uchar)(p * 255);
|
||||
saturation = (uchar)(v * 255);
|
||||
value = (uchar)(t * 255);
|
||||
value = (uchar)(t * 255);
|
||||
break;
|
||||
case 3:
|
||||
hue = (uchar)(p * 255);
|
||||
hue = (uchar)(p * 255);
|
||||
saturation = (uchar)(q * 255);
|
||||
value = (uchar)(v * 255);
|
||||
value = (uchar)(v * 255);
|
||||
break;
|
||||
case 4:
|
||||
hue = (uchar)(t * 255);
|
||||
hue = (uchar)(t * 255);
|
||||
saturation = (uchar)(p * 255);
|
||||
value = (uchar)(v * 255);
|
||||
value = (uchar)(v * 255);
|
||||
break;
|
||||
case 5:
|
||||
hue = (uchar)(v * 255);
|
||||
hue = (uchar)(v * 255);
|
||||
saturation = (uchar)(p * 255);
|
||||
value = (uchar)(q * 255);
|
||||
value = (uchar)(q * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -282,9 +280,9 @@ static void RGBTOHLS(uchar &red, uchar &green, uchar &blue)
|
||||
}
|
||||
}
|
||||
|
||||
red = (uchar)h;
|
||||
red = (uchar)h;
|
||||
green = (uchar)l;
|
||||
blue = (uchar)s;
|
||||
blue = (uchar)s;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -330,8 +328,8 @@ static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation)
|
||||
double s = saturation;
|
||||
|
||||
if (s == 0) {
|
||||
hue = (uchar)l;
|
||||
lightness = (uchar)l;
|
||||
hue = (uchar)l;
|
||||
lightness = (uchar)l;
|
||||
saturation = (uchar)l;
|
||||
} else {
|
||||
double m1, m2;
|
||||
@ -344,8 +342,8 @@ static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation)
|
||||
|
||||
m1 = (l / 127.5) - m2;
|
||||
|
||||
hue = HLSVALUE(m1, m2, h + 85);
|
||||
lightness = HLSVALUE(m1, m2, h);
|
||||
hue = HLSVALUE(m1, m2, h + 85);
|
||||
lightness = HLSVALUE(m1, m2, h);
|
||||
saturation = HLSVALUE(m1, m2, h - 85);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
#include "hdr_p.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QDataStream>
|
||||
#include <QImage>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpressionMatch>
|
||||
|
||||
@ -19,19 +19,18 @@ typedef unsigned char uchar;
|
||||
|
||||
Q_LOGGING_CATEGORY(HDRPLUGIN, "kf.imageformats.plugins.hdr", QtWarningMsg)
|
||||
|
||||
namespace // Private.
|
||||
namespace // Private.
|
||||
{
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define MINELEN 8 // minimum scanline length for encoding
|
||||
#define MAXELEN 0x7fff // maximum scanline length for encoding
|
||||
#define MAXLINE 1024
|
||||
#define MINELEN 8 // minimum scanline length for encoding
|
||||
#define MAXELEN 0x7fff // maximum scanline length for encoding
|
||||
|
||||
static inline uchar ClipToByte(float value)
|
||||
{
|
||||
if (value > 255.0f) {
|
||||
return 255;
|
||||
}
|
||||
//else if (value < 0.0f) return 0; // we know value is positive.
|
||||
// else if (value < 0.0f) return 0; // we know value is positive.
|
||||
return uchar(value);
|
||||
}
|
||||
|
||||
@ -39,8 +38,8 @@ static inline uchar ClipToByte(float value)
|
||||
// if 'first' is true the first byte is already read
|
||||
static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
{
|
||||
int rshift = 0;
|
||||
int i;
|
||||
int rshift = 0;
|
||||
int i;
|
||||
|
||||
while (width > 0) {
|
||||
s >> image[0];
|
||||
@ -54,7 +53,7 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
|
||||
if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1)) {
|
||||
for (i = image[3] << rshift; i > 0; i--) {
|
||||
//memcpy(image, image-4, 4);
|
||||
// memcpy(image, image-4, 4);
|
||||
(uint &)image[0] = (uint &)image[0 - 4];
|
||||
image += 4;
|
||||
width--;
|
||||
@ -81,9 +80,7 @@ static void RGBE_To_QRgbLine(uchar *image, QRgb *scanline, int width)
|
||||
v = 1.0f / float(1 << -e);
|
||||
}
|
||||
|
||||
scanline[j] = qRgb(ClipToByte(float(image[0]) * v),
|
||||
ClipToByte(float(image[1]) * v),
|
||||
ClipToByte(float(image[2]) * v));
|
||||
scanline[j] = qRgb(ClipToByte(float(image[0]) * v), ClipToByte(float(image[1]) * v), ClipToByte(float(image[2]) * v));
|
||||
|
||||
image += 4;
|
||||
}
|
||||
@ -103,10 +100,10 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
|
||||
QByteArray lineArray;
|
||||
lineArray.resize(4 * width);
|
||||
uchar *image = (uchar *) lineArray.data();
|
||||
uchar *image = (uchar *)lineArray.data();
|
||||
|
||||
for (int cline = 0; cline < height; cline++) {
|
||||
QRgb *scanline = (QRgb *) img.scanLine(cline);
|
||||
QRgb *scanline = (QRgb *)img.scanLine(cline);
|
||||
|
||||
// determine scanline type
|
||||
if ((width < MINELEN) || (MAXELEN < width)) {
|
||||
@ -168,7 +165,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
} else {
|
||||
// non-run
|
||||
while (code != 0) {
|
||||
s >> image[i + j * 4];
|
||||
s >> image[i + j * 4];
|
||||
j++;
|
||||
code--;
|
||||
}
|
||||
@ -228,8 +225,7 @@ bool HDRHandler::read(QImage *outImage)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( (match.captured(1).at(1) != u'Y') ||
|
||||
(match.captured(3).at(1) != u'X') ) {
|
||||
if ((match.captured(1).at(1) != u'Y') || (match.captured(3).at(1) != u'X')) {
|
||||
qCDebug(HDRPLUGIN) << "Unsupported image orientation in HDR file.";
|
||||
return false;
|
||||
}
|
||||
|
@ -10,17 +10,19 @@
|
||||
#include "heif_p.h"
|
||||
#include "libheif/heif_cxx.h"
|
||||
|
||||
#include <QPointF>
|
||||
#include <QColorSpace>
|
||||
#include <QDebug>
|
||||
#include <QPointF>
|
||||
#include <QSysInfo>
|
||||
#include <string.h>
|
||||
|
||||
namespace // Private.
|
||||
namespace // Private.
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
@ -49,9 +51,9 @@ private:
|
||||
|
||||
} // namespace
|
||||
|
||||
HEIFHandler::HEIFHandler() :
|
||||
m_parseState(ParseHeicNotParsed),
|
||||
m_quality(100)
|
||||
HEIFHandler::HEIFHandler()
|
||||
: m_parseState(ParseHeicNotParsed)
|
||||
, m_quality(100)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,8 +87,8 @@ bool HEIFHandler::write(const QImage &image)
|
||||
return false;
|
||||
}
|
||||
|
||||
int save_depth; //8 or 10bit per channel
|
||||
QImage::Format tmpformat; //format for temporary image
|
||||
int save_depth; // 8 or 10bit per channel
|
||||
QImage::Format tmpformat; // format for temporary image
|
||||
const bool save_alpha = image.hasAlphaChannel();
|
||||
|
||||
switch (image.format()) {
|
||||
@ -126,7 +128,6 @@ bool HEIFHandler::write(const QImage &image)
|
||||
tmpformat = QImage::Format_RGB888;
|
||||
chroma = heif_chroma_interleaved_RGB;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const QImage tmpimage = image.convertToFormat(tmpformat);
|
||||
@ -157,50 +158,50 @@ bool HEIFHandler::write(const QImage &image)
|
||||
uint16_t *dest_word = reinterpret_cast<uint16_t *>(dst + (y * stride));
|
||||
for (int x = 0; x < tmpimage.width(); x++) {
|
||||
int tmp_pixelval;
|
||||
//R
|
||||
// R
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//G
|
||||
// G
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//B
|
||||
// B
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//A
|
||||
// A
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
}
|
||||
}
|
||||
} else { //no alpha channel
|
||||
} else { // no alpha channel
|
||||
for (int y = 0; y < tmpimage.height(); y++) {
|
||||
const uint16_t *src_word = reinterpret_cast<const uint16_t *>(tmpimage.constScanLine(y));
|
||||
uint16_t *dest_word = reinterpret_cast<uint16_t *>(dst + (y * stride));
|
||||
for (int x = 0; x < tmpimage.width(); x++) {
|
||||
int tmp_pixelval;
|
||||
//R
|
||||
// R
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//G
|
||||
// G
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//B
|
||||
// B
|
||||
tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
|
||||
*dest_word = qBound(0, tmp_pixelval, 1023);
|
||||
src_word++;
|
||||
dest_word++;
|
||||
//X
|
||||
// X
|
||||
src_word++;
|
||||
}
|
||||
}
|
||||
@ -342,8 +343,7 @@ void HEIFHandler::setOption(ImageOption option, const QVariant &value)
|
||||
|
||||
bool HEIFHandler::supportsOption(ImageOption option) const
|
||||
{
|
||||
return option == Quality
|
||||
|| option == Size;
|
||||
return option == Quality || option == Size;
|
||||
}
|
||||
|
||||
bool HEIFHandler::ensureParsed() const
|
||||
@ -376,8 +376,7 @@ bool HEIFHandler::ensureDecoder()
|
||||
|
||||
try {
|
||||
heif::Context ctx;
|
||||
ctx.read_from_memory_without_copy((const void *)(buffer.constData()),
|
||||
buffer.size());
|
||||
ctx.read_from_memory_without_copy((const void *)(buffer.constData()), buffer.size());
|
||||
|
||||
heif::ImageHandle handle = ctx.get_primary_image_handle();
|
||||
|
||||
@ -413,7 +412,6 @@ bool HEIFHandler::ensureDecoder()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
heif::Image img = handle.decode_image(heif_colorspace_RGB, chroma);
|
||||
|
||||
const int imageWidth = img.get_width(heif_channel_interleaved);
|
||||
@ -451,57 +449,57 @@ bool HEIFHandler::ensureDecoder()
|
||||
uint16_t *dest_data = reinterpret_cast<uint16_t *>(m_current_image.scanLine(y));
|
||||
for (int x = 0; x < imageWidth; x++) {
|
||||
int tmpvalue;
|
||||
//R
|
||||
// R
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//G
|
||||
// G
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//B
|
||||
// B
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//A
|
||||
// A
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
}
|
||||
}
|
||||
} else { //no alpha channel
|
||||
} else { // no alpha channel
|
||||
for (int y = 0; y < imageHeight; y++) {
|
||||
const uint16_t *src_word = reinterpret_cast<const uint16_t *>(src + (y * stride));
|
||||
uint16_t *dest_data = reinterpret_cast<uint16_t *>(m_current_image.scanLine(y));
|
||||
for (int x = 0; x < imageWidth; x++) {
|
||||
int tmpvalue;
|
||||
//R
|
||||
// R
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//G
|
||||
// G
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//B
|
||||
// B
|
||||
tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//X = 0xffff
|
||||
// X = 0xffff
|
||||
*dest_data = 0xffff;
|
||||
dest_data++;
|
||||
}
|
||||
@ -515,57 +513,57 @@ bool HEIFHandler::ensureDecoder()
|
||||
uint16_t *dest_data = reinterpret_cast<uint16_t *>(m_current_image.scanLine(y));
|
||||
for (int x = 0; x < imageWidth; x++) {
|
||||
int tmpvalue;
|
||||
//R
|
||||
// R
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//G
|
||||
// G
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//B
|
||||
// B
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//A
|
||||
// A
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
}
|
||||
}
|
||||
} else { //no alpha channel
|
||||
} else { // no alpha channel
|
||||
for (int y = 0; y < imageHeight; y++) {
|
||||
const uint16_t *src_word = reinterpret_cast<const uint16_t *>(src + (y * stride));
|
||||
uint16_t *dest_data = reinterpret_cast<uint16_t *>(m_current_image.scanLine(y));
|
||||
for (int x = 0; x < imageWidth; x++) {
|
||||
int tmpvalue;
|
||||
//R
|
||||
// R
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//G
|
||||
// G
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//B
|
||||
// B
|
||||
tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
|
||||
tmpvalue = qBound(0, tmpvalue, 65535);
|
||||
*dest_data = (uint16_t) tmpvalue;
|
||||
*dest_data = (uint16_t)tmpvalue;
|
||||
src_word++;
|
||||
dest_data++;
|
||||
//X = 0xffff
|
||||
// X = 0xffff
|
||||
*dest_data = 0xffff;
|
||||
dest_data++;
|
||||
}
|
||||
@ -586,7 +584,7 @@ bool HEIFHandler::ensureDecoder()
|
||||
dest_pixel++;
|
||||
}
|
||||
}
|
||||
} else { //no alpha channel
|
||||
} else { // no alpha channel
|
||||
for (int y = 0; y < imageHeight; y++) {
|
||||
const uint8_t *src_byte = src + (y * stride);
|
||||
uint32_t *dest_pixel = reinterpret_cast<uint32_t *>(m_current_image.scanLine(y));
|
||||
@ -598,7 +596,6 @@ bool HEIFHandler::ensureDecoder()
|
||||
dest_pixel++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -611,7 +608,7 @@ bool HEIFHandler::ensureDecoder()
|
||||
heif_color_profile_type profileType = heif_image_handle_get_color_profile_type(handle.get_raw_image_handle());
|
||||
struct heif_error err;
|
||||
if (profileType == heif_color_profile_type_prof || profileType == heif_color_profile_type_rICC) {
|
||||
int rawProfileSize = (int) heif_image_handle_get_raw_color_profile_size(handle.get_raw_image_handle());
|
||||
int rawProfileSize = (int)heif_image_handle_get_raw_color_profile_size(handle.get_raw_image_handle());
|
||||
if (rawProfileSize > 0) {
|
||||
QByteArray ba(rawProfileSize, 0);
|
||||
err = heif_image_handle_get_raw_color_profile(handle.get_raw_image_handle(), ba.data());
|
||||
@ -655,16 +652,17 @@ bool HEIFHandler::ensureDecoder()
|
||||
break;
|
||||
case 2:
|
||||
case 13:
|
||||
q_trc = QColorSpace::TransferFunction::SRgb;
|
||||
q_trc = QColorSpace::TransferFunction::SRgb;
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (q_trc != QColorSpace::TransferFunction::Custom) { //we create new colorspace using Qt
|
||||
if (q_trc != QColorSpace::TransferFunction::Custom) { // we create new colorspace using Qt
|
||||
switch (nclx->color_primaries) {
|
||||
case 1:
|
||||
case 2:
|
||||
@ -683,7 +681,6 @@ bool HEIFHandler::ensureDecoder()
|
||||
if (!m_current_image.colorSpace().isValid()) {
|
||||
qWarning() << "invalid color profile created from NCLX";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
QVariant option(ImageOption option) const override;
|
||||
void setOption(ImageOption option, const QVariant &value) override;
|
||||
bool supportsOption(ImageOption option) const override;
|
||||
|
||||
private:
|
||||
static bool isSupportedBMFFType(const QByteArray &header);
|
||||
bool ensureParsed() const;
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
#include <kzip.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QIODevice>
|
||||
#include <QFile>
|
||||
#include <QIODevice>
|
||||
#include <QImage>
|
||||
|
||||
static constexpr char s_magic[] = "application/x-krita";
|
||||
static constexpr int s_magic_size = sizeof(s_magic) - 1; // -1 to remove the last \0
|
||||
@ -35,12 +35,14 @@ bool KraHandler::canRead() const
|
||||
bool KraHandler::read(QImage *image)
|
||||
{
|
||||
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"));
|
||||
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);
|
||||
|
||||
image->loadFromData(fileZipEntry->data(), "PNG");
|
||||
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
KraHandler();
|
||||
|
||||
bool canRead() const override;
|
||||
bool read(QImage *image) override;
|
||||
bool read(QImage *image) override;
|
||||
|
||||
static bool canRead(QIODevice *device);
|
||||
};
|
||||
@ -31,6 +31,4 @@ public:
|
||||
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -34,12 +34,14 @@ bool OraHandler::canRead() const
|
||||
bool OraHandler::read(QImage *image)
|
||||
{
|
||||
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"));
|
||||
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);
|
||||
|
||||
image->loadFromData(fileZipEntry->data(), "PNG");
|
||||
|
||||
|
@ -16,12 +16,11 @@ public:
|
||||
OraHandler();
|
||||
|
||||
bool canRead() const override;
|
||||
bool read(QImage *image) override;
|
||||
bool read(QImage *image) override;
|
||||
|
||||
static bool canRead(QIODevice *device);
|
||||
};
|
||||
|
||||
|
||||
class OraPlugin : public QImageIOPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -31,6 +30,4 @@ public:
|
||||
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
#pragma pack(push, 1)
|
||||
class RGB
|
||||
{
|
||||
public:
|
||||
@ -29,7 +28,6 @@ public:
|
||||
c.b = qBlue(color);
|
||||
return c;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Palette
|
||||
@ -37,7 +35,7 @@ class Palette
|
||||
public:
|
||||
void setColor(int i, const QRgb color)
|
||||
{
|
||||
RGB &c = rgb[ i ];
|
||||
RGB &c = rgb[i];
|
||||
c.r = qRed(color);
|
||||
c.g = qGreen(color);
|
||||
c.b = qBlue(color);
|
||||
@ -45,10 +43,10 @@ public:
|
||||
|
||||
QRgb color(int i) const
|
||||
{
|
||||
return qRgb(rgb[ i ].r, rgb[ i ].g, rgb[ i ].b);
|
||||
return qRgb(rgb[i].r, rgb[i].g, rgb[i].b);
|
||||
}
|
||||
|
||||
class RGB rgb[ 16 ];
|
||||
class RGB rgb[16];
|
||||
};
|
||||
|
||||
class PCXHEADER
|
||||
@ -69,8 +67,8 @@ public:
|
||||
return (Encoding == 1);
|
||||
}
|
||||
|
||||
quint8 Manufacturer; // Constant Flag, 10 = ZSoft .pcx
|
||||
quint8 Version; // Version information·
|
||||
quint8 Manufacturer; // Constant Flag, 10 = ZSoft .pcx
|
||||
quint8 Version; // Version information·
|
||||
// 0 = Version 2.5 of PC Paintbrush·
|
||||
// 2 = Version 2.8 w/palette information·
|
||||
// 3 = Version 2.8 w/o palette information·
|
||||
@ -80,8 +78,8 @@ public:
|
||||
// and PC Paintbrush +, includes
|
||||
// Publisher's Paintbrush . Includes
|
||||
// 24-bit .PCX files·
|
||||
quint8 Encoding; // 1 = .PCX run length encoding
|
||||
quint8 Bpp; // Number of bits to represent a pixel
|
||||
quint8 Encoding; // 1 = .PCX run length encoding
|
||||
quint8 Bpp; // Number of bits to represent a pixel
|
||||
// (per Plane) - 1, 2, 4, or 8·
|
||||
quint16 XMin;
|
||||
quint16 YMin;
|
||||
@ -89,17 +87,17 @@ public:
|
||||
quint16 YMax;
|
||||
quint16 HDpi;
|
||||
quint16 YDpi;
|
||||
Palette ColorMap;
|
||||
quint8 Reserved; // Should be set to 0.
|
||||
quint8 NPlanes; // Number of color planes
|
||||
quint16 BytesPerLine; // Number of bytes to allocate for a scanline
|
||||
Palette ColorMap;
|
||||
quint8 Reserved; // Should be set to 0.
|
||||
quint8 NPlanes; // Number of color planes
|
||||
quint16 BytesPerLine; // Number of bytes to allocate for a scanline
|
||||
// plane. MUST be an EVEN number. Do NOT
|
||||
// calculate from Xmax-Xmin.·
|
||||
quint16 PaletteInfo; // How to interpret palette- 1 = Color/BW,
|
||||
quint16 PaletteInfo; // How to interpret palette- 1 = Color/BW,
|
||||
// 2 = Grayscale ( ignored in PB IV/ IV + )·
|
||||
quint16 HScreenSize; // Horizontal screen size in pixels. New field
|
||||
quint16 HScreenSize; // Horizontal screen size in pixels. New field
|
||||
// found only in PB IV/IV Plus
|
||||
quint16 VScreenSize; // Vertical screen size in pixels. New field
|
||||
quint16 VScreenSize; // Vertical screen size in pixels. New field
|
||||
// found only in PB IV/IV Plus
|
||||
};
|
||||
|
||||
@ -120,7 +118,7 @@ static QDataStream &operator>>(QDataStream &s, RGB &rgb)
|
||||
static QDataStream &operator>>(QDataStream &s, Palette &pal)
|
||||
{
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
s >> pal.rgb[ i ];
|
||||
s >> pal.rgb[i];
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -151,12 +149,16 @@ static QDataStream &operator>>(QDataStream &s, PCXHEADER &ph)
|
||||
ph.Reserved = res;
|
||||
ph.NPlanes = np;
|
||||
quint16 bytesperline;
|
||||
s >> bytesperline; ph.BytesPerLine = bytesperline;
|
||||
s >> bytesperline;
|
||||
ph.BytesPerLine = bytesperline;
|
||||
quint16 paletteinfo;
|
||||
s >> paletteinfo; ph.PaletteInfo = paletteinfo;
|
||||
s >> paletteinfo;
|
||||
ph.PaletteInfo = paletteinfo;
|
||||
quint16 hscreensize, vscreensize;
|
||||
s >> hscreensize; ph.HScreenSize = hscreensize;
|
||||
s >> vscreensize; ph.VScreenSize = vscreensize;
|
||||
s >> hscreensize;
|
||||
ph.HScreenSize = hscreensize;
|
||||
s >> vscreensize;
|
||||
ph.VScreenSize = vscreensize;
|
||||
|
||||
// Skip the rest of the header
|
||||
quint8 byte;
|
||||
@ -177,7 +179,7 @@ static QDataStream &operator<<(QDataStream &s, const RGB rgb)
|
||||
static QDataStream &operator<<(QDataStream &s, const Palette &pal)
|
||||
{
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
s << pal.rgb[ i ];
|
||||
s << pal.rgb[i];
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -232,14 +234,14 @@ static void readLine(QDataStream &s, QByteArray &buf, const PCXHEADER &header)
|
||||
s >> byte;
|
||||
}
|
||||
while (count-- && i < size) {
|
||||
buf[ i++ ] = byte;
|
||||
buf[i++] = byte;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Image is not compressed (possible?)
|
||||
while (i < size) {
|
||||
s >> byte;
|
||||
buf[ i++ ] = byte;
|
||||
buf[i++] = byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +268,7 @@ static void readImage1(QImage &img, QDataStream &s, const PCXHEADER &header)
|
||||
uchar *p = img.scanLine(y);
|
||||
unsigned int bpl = qMin((quint16)((header.width() + 7) / 8), header.BytesPerLine);
|
||||
for (unsigned int x = 0; x < bpl; ++x) {
|
||||
p[ x ] = buf[x];
|
||||
p[x] = buf[x];
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,8 +301,8 @@ static void readImage4(QImage &img, QDataStream &s, const PCXHEADER &header)
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quint32 offset = i * header.BytesPerLine;
|
||||
for (int x = 0; x < header.width(); ++x)
|
||||
if (buf[ offset + (x / 8) ] & (128 >> (x % 8))) {
|
||||
pixbuf[ x ] = (int)(pixbuf[ x ]) + (1 << i);
|
||||
if (buf[offset + (x / 8)] & (128 >> (x % 8))) {
|
||||
pixbuf[x] = (int)(pixbuf[x]) + (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,7 +311,7 @@ static void readImage4(QImage &img, QDataStream &s, const PCXHEADER &header)
|
||||
qWarning() << "Failed to get scanline for" << y << "might be out of bounds";
|
||||
}
|
||||
for (int x = 0; x < header.width(); ++x) {
|
||||
p[ x ] = pixbuf[ x ];
|
||||
p[x] = pixbuf[x];
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,13 +348,13 @@ static void readImage8(QImage &img, QDataStream &s, const PCXHEADER &header)
|
||||
|
||||
unsigned int bpl = qMin(header.BytesPerLine, (quint16)header.width());
|
||||
for (unsigned int x = 0; x < bpl; ++x) {
|
||||
p[ x ] = buf[ x ];
|
||||
p[x] = buf[x];
|
||||
}
|
||||
}
|
||||
|
||||
quint8 flag;
|
||||
s >> flag;
|
||||
// qDebug() << "Palette Flag: " << flag;
|
||||
// qDebug() << "Palette Flag: " << flag;
|
||||
|
||||
if (flag == 12 && (header.Version == 5 || header.Version == 2)) {
|
||||
// Read the palette
|
||||
@ -389,7 +391,7 @@ static void readImage24(QImage &img, QDataStream &s, const PCXHEADER &header)
|
||||
|
||||
uint *p = (uint *)img.scanLine(y);
|
||||
for (int x = 0; x < header.width(); ++x) {
|
||||
p[ x ] = qRgb(r_buf[ x ], g_buf[ x ], b_buf[ x ]);
|
||||
p[x] = qRgb(r_buf[x], g_buf[x], b_buf[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -403,9 +405,9 @@ static void writeLine(QDataStream &s, QByteArray &buf)
|
||||
|
||||
while (i < size) {
|
||||
count = 1;
|
||||
byte = buf[ i++ ];
|
||||
byte = buf[i++];
|
||||
|
||||
while ((i < size) && (byte == buf[ i ]) && (count < 63)) {
|
||||
while ((i < size) && (byte == buf[i]) && (count < 63)) {
|
||||
++i;
|
||||
++count;
|
||||
}
|
||||
@ -438,7 +440,7 @@ static void writeImage1(QImage &img, QDataStream &s, PCXHEADER &header)
|
||||
|
||||
// Invert as QImage uses reverse palette for monochrome images?
|
||||
for (int i = 0; i < header.BytesPerLine; ++i) {
|
||||
buf[ i ] = ~p[ i ];
|
||||
buf[i] = ~p[i];
|
||||
}
|
||||
|
||||
writeLine(s, buf);
|
||||
@ -457,28 +459,28 @@ static void writeImage4(QImage &img, QDataStream &s, PCXHEADER &header)
|
||||
|
||||
s << header;
|
||||
|
||||
QByteArray buf[ 4 ];
|
||||
QByteArray buf[4];
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
buf[ i ].resize(header.BytesPerLine);
|
||||
buf[i].resize(header.BytesPerLine);
|
||||
}
|
||||
|
||||
for (int y = 0; y < header.height(); ++y) {
|
||||
quint8 *p = img.scanLine(y);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
buf[ i ].fill(0);
|
||||
buf[i].fill(0);
|
||||
}
|
||||
|
||||
for (int x = 0; x < header.width(); ++x) {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (*(p + x) & (1 << i)) {
|
||||
buf[ i ][ x / 8 ] = (int)(buf[ i ][ x / 8 ]) | 1 << (7 - x % 8);
|
||||
buf[i][x / 8] = (int)(buf[i][x / 8]) | 1 << (7 - x % 8);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
writeLine(s, buf[ i ]);
|
||||
writeLine(s, buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -497,7 +499,7 @@ static void writeImage8(QImage &img, QDataStream &s, PCXHEADER &header)
|
||||
quint8 *p = img.scanLine(y);
|
||||
|
||||
for (int i = 0; i < header.BytesPerLine; ++i) {
|
||||
buf[ i ] = p[ i ];
|
||||
buf[i] = p[i];
|
||||
}
|
||||
|
||||
writeLine(s, buf);
|
||||
@ -530,9 +532,9 @@ static void writeImage24(QImage &img, QDataStream &s, PCXHEADER &header)
|
||||
|
||||
for (int x = 0; x < header.width(); ++x) {
|
||||
QRgb rgb = *p++;
|
||||
r_buf[ x ] = qRed(rgb);
|
||||
g_buf[ x ] = qGreen(rgb);
|
||||
b_buf[ x ] = qBlue(rgb);
|
||||
r_buf[x] = qRed(rgb);
|
||||
g_buf[x] = qGreen(rgb);
|
||||
b_buf[x] = qBlue(rgb);
|
||||
}
|
||||
|
||||
writeLine(s, r_buf);
|
||||
@ -571,19 +573,19 @@ bool PCXHandler::read(QImage *outImage)
|
||||
return false;
|
||||
}
|
||||
|
||||
// int w = header.width();
|
||||
// int h = header.height();
|
||||
// int w = header.width();
|
||||
// int h = header.height();
|
||||
|
||||
// qDebug() << "Manufacturer: " << header.Manufacturer;
|
||||
// qDebug() << "Version: " << header.Version;
|
||||
// qDebug() << "Encoding: " << header.Encoding;
|
||||
// qDebug() << "Bpp: " << header.Bpp;
|
||||
// qDebug() << "Width: " << w;
|
||||
// qDebug() << "Height: " << h;
|
||||
// qDebug() << "Window: " << header.XMin << "," << header.XMax << ","
|
||||
// << header.YMin << "," << header.YMax << endl;
|
||||
// qDebug() << "BytesPerLine: " << header.BytesPerLine;
|
||||
// qDebug() << "NPlanes: " << header.NPlanes;
|
||||
// qDebug() << "Manufacturer: " << header.Manufacturer;
|
||||
// qDebug() << "Version: " << header.Version;
|
||||
// qDebug() << "Encoding: " << header.Encoding;
|
||||
// qDebug() << "Bpp: " << header.Bpp;
|
||||
// qDebug() << "Width: " << w;
|
||||
// qDebug() << "Height: " << h;
|
||||
// qDebug() << "Window: " << header.XMin << "," << header.XMax << ","
|
||||
// << header.YMin << "," << header.YMax << endl;
|
||||
// qDebug() << "BytesPerLine: " << header.BytesPerLine;
|
||||
// qDebug() << "NPlanes: " << header.NPlanes;
|
||||
|
||||
QImage img;
|
||||
|
||||
@ -597,9 +599,9 @@ bool PCXHandler::read(QImage *outImage)
|
||||
readImage24(img, s, header);
|
||||
}
|
||||
|
||||
// qDebug() << "Image Bytes: " << img.numBytes();
|
||||
// qDebug() << "Image Bytes Per Line: " << img.bytesPerLine();
|
||||
// qDebug() << "Image Depth: " << img.depth();
|
||||
// qDebug() << "Image Bytes: " << img.numBytes();
|
||||
// qDebug() << "Image Bytes Per Line: " << img.bytesPerLine();
|
||||
// qDebug() << "Image Depth: " << img.depth();
|
||||
|
||||
if (!img.isNull()) {
|
||||
*outImage = img;
|
||||
@ -619,11 +621,11 @@ bool PCXHandler::write(const QImage &image)
|
||||
int w = img.width();
|
||||
int h = img.height();
|
||||
|
||||
// qDebug() << "Width: " << w;
|
||||
// qDebug() << "Height: " << h;
|
||||
// qDebug() << "Depth: " << img.depth();
|
||||
// qDebug() << "BytesPerLine: " << img.bytesPerLine();
|
||||
// qDebug() << "Color Count: " << img.colorCount();
|
||||
// qDebug() << "Width: " << w;
|
||||
// qDebug() << "Height: " << h;
|
||||
// qDebug() << "Depth: " << img.depth();
|
||||
// qDebug() << "BytesPerLine: " << img.bytesPerLine();
|
||||
// qDebug() << "Color Count: " << img.colorCount();
|
||||
|
||||
PCXHEADER header;
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
#include <QVariant>
|
||||
#include <qendian.h>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <qendian.h>
|
||||
|
||||
/**
|
||||
* Reads a PIC file header from a data stream.
|
||||
@ -34,7 +34,7 @@
|
||||
*
|
||||
* @relates PicHeader
|
||||
*/
|
||||
static QDataStream &operator>> (QDataStream &s, PicHeader &header)
|
||||
static QDataStream &operator>>(QDataStream &s, PicHeader &header)
|
||||
{
|
||||
s.setFloatingPointPrecision(QDataStream::SinglePrecision);
|
||||
s >> header.magic;
|
||||
@ -71,7 +71,7 @@ static QDataStream &operator>> (QDataStream &s, PicHeader &header)
|
||||
*
|
||||
* @relates PicHeader
|
||||
*/
|
||||
static QDataStream &operator<< (QDataStream &s, const PicHeader &header)
|
||||
static QDataStream &operator<<(QDataStream &s, const PicHeader &header)
|
||||
{
|
||||
s.setFloatingPointPrecision(QDataStream::SinglePrecision);
|
||||
s << header.magic;
|
||||
@ -107,7 +107,7 @@ static QDataStream &operator<< (QDataStream &s, const PicHeader &header)
|
||||
*
|
||||
* @relates PicChannel
|
||||
*/
|
||||
static QDataStream &operator>> (QDataStream &s, QList<PicChannel> &channels)
|
||||
static QDataStream &operator>>(QDataStream &s, QList<PicChannel> &channels)
|
||||
{
|
||||
const unsigned maxChannels = 8;
|
||||
unsigned count = 0;
|
||||
@ -142,7 +142,7 @@ static QDataStream &operator>> (QDataStream &s, QList<PicChannel> &channels)
|
||||
*
|
||||
* @relates PicChannel
|
||||
*/
|
||||
static QDataStream &operator<< (QDataStream &s, const QList<PicChannel> &channels)
|
||||
static QDataStream &operator<<(QDataStream &s, const QList<PicChannel> &channels)
|
||||
{
|
||||
Q_ASSERT(channels.size() > 0);
|
||||
for (int i = 0; i < channels.size() - 1; ++i) {
|
||||
@ -160,8 +160,8 @@ static QDataStream &operator<< (QDataStream &s, const QList<PicChannel> &channel
|
||||
|
||||
static bool readRow(QDataStream &stream, QRgb *row, quint16 width, const QList<PicChannel> &channels)
|
||||
{
|
||||
for(const PicChannel &channel : channels) {
|
||||
auto readPixel = [&] (QDataStream &str) -> QRgb {
|
||||
for (const PicChannel &channel : channels) {
|
||||
auto readPixel = [&](QDataStream &str) -> QRgb {
|
||||
quint8 red = 0;
|
||||
if (channel.code & RED) {
|
||||
str >> red;
|
||||
@ -180,16 +180,14 @@ static bool readRow(QDataStream &stream, QRgb *row, quint16 width, const QList<P
|
||||
}
|
||||
return qRgba(red, green, blue, alpha);
|
||||
};
|
||||
auto updatePixel = [&] (QRgb oldPixel, QRgb newPixel) -> QRgb {
|
||||
return qRgba(
|
||||
qRed((channel.code & RED) ? newPixel : oldPixel),
|
||||
qGreen((channel.code & GREEN) ? newPixel : oldPixel),
|
||||
qBlue((channel.code & BLUE) ? newPixel : oldPixel),
|
||||
qAlpha((channel.code & ALPHA) ? newPixel : oldPixel));
|
||||
auto updatePixel = [&](QRgb oldPixel, QRgb newPixel) -> QRgb {
|
||||
return qRgba(qRed((channel.code & RED) ? newPixel : oldPixel),
|
||||
qGreen((channel.code & GREEN) ? newPixel : oldPixel),
|
||||
qBlue((channel.code & BLUE) ? newPixel : oldPixel),
|
||||
qAlpha((channel.code & ALPHA) ? newPixel : oldPixel));
|
||||
};
|
||||
if (channel.encoding == MixedRLE) {
|
||||
bool success = decodeRLEData(RLEVariant::PIC, stream, row, width,
|
||||
readPixel, updatePixel);
|
||||
bool success = decodeRLEData(RLEVariant::PIC, stream, row, width, readPixel, updatePixel);
|
||||
if (!success) {
|
||||
qDebug() << "decodeRLEData failed";
|
||||
return false;
|
||||
@ -245,10 +243,10 @@ bool SoftimagePICHandler::read(QImage *image)
|
||||
return false;
|
||||
}
|
||||
|
||||
img.fill(qRgb(0,0,0));
|
||||
img.fill(qRgb(0, 0, 0));
|
||||
|
||||
for (int y = 0; y < m_header.height; y++) {
|
||||
QRgb *row = reinterpret_cast<QRgb*>(img.scanLine(y));
|
||||
QRgb *row = reinterpret_cast<QRgb *>(img.scanLine(y));
|
||||
if (!readRow(m_dataStream, row, m_header.width, m_channels)) {
|
||||
qDebug() << "readRow failed";
|
||||
m_state = Error;
|
||||
@ -265,9 +263,7 @@ bool SoftimagePICHandler::read(QImage *image)
|
||||
bool SoftimagePICHandler::write(const QImage &_image)
|
||||
{
|
||||
bool alpha = _image.hasAlphaChannel();
|
||||
const QImage image = _image.convertToFormat(
|
||||
alpha ? QImage::Format_ARGB32
|
||||
: QImage::Format_RGB32);
|
||||
const QImage image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
|
||||
if (image.width() < 0 || image.height() < 0) {
|
||||
qDebug() << "Image size invalid:" << image.width() << image.height();
|
||||
@ -292,22 +288,17 @@ bool SoftimagePICHandler::write(const QImage &_image)
|
||||
stream << channels;
|
||||
|
||||
for (int r = 0; r < image.height(); r++) {
|
||||
const QRgb *row = reinterpret_cast<const QRgb*>(image.scanLine(r));
|
||||
const QRgb *row = reinterpret_cast<const QRgb *>(image.scanLine(r));
|
||||
|
||||
/* Write the RGB part of the scanline */
|
||||
auto rgbEqual = [] (QRgb p1, QRgb p2) -> bool {
|
||||
return qRed(p1) == qRed(p2) &&
|
||||
qGreen(p1) == qGreen(p2) &&
|
||||
qBlue(p1) == qBlue(p2);
|
||||
auto rgbEqual = [](QRgb p1, QRgb p2) -> bool {
|
||||
return qRed(p1) == qRed(p2) && qGreen(p1) == qGreen(p2) && qBlue(p1) == qBlue(p2);
|
||||
};
|
||||
auto writeRgb = [] (QDataStream &str, QRgb pixel) -> void {
|
||||
str << quint8(qRed(pixel))
|
||||
<< quint8(qGreen(pixel))
|
||||
<< quint8(qBlue(pixel));
|
||||
auto writeRgb = [](QDataStream &str, QRgb pixel) -> void {
|
||||
str << quint8(qRed(pixel)) << quint8(qGreen(pixel)) << quint8(qBlue(pixel));
|
||||
};
|
||||
if (m_compression) {
|
||||
encodeRLEData(RLEVariant::PIC, stream, row, image.width(),
|
||||
rgbEqual, writeRgb);
|
||||
encodeRLEData(RLEVariant::PIC, stream, row, image.width(), rgbEqual, writeRgb);
|
||||
} else {
|
||||
for (int i = 0; i < image.width(); ++i) {
|
||||
writeRgb(stream, row[i]);
|
||||
@ -316,15 +307,14 @@ bool SoftimagePICHandler::write(const QImage &_image)
|
||||
|
||||
/* Write the alpha channel */
|
||||
if (alpha) {
|
||||
auto alphaEqual = [] (QRgb p1, QRgb p2) -> bool {
|
||||
auto alphaEqual = [](QRgb p1, QRgb p2) -> bool {
|
||||
return qAlpha(p1) == qAlpha(p2);
|
||||
};
|
||||
auto writeAlpha = [] (QDataStream &str, QRgb pixel) -> void {
|
||||
auto writeAlpha = [](QDataStream &str, QRgb pixel) -> void {
|
||||
str << quint8(qAlpha(pixel));
|
||||
};
|
||||
if (m_compression) {
|
||||
encodeRLEData(RLEVariant::PIC, stream, row, image.width(),
|
||||
alphaEqual, writeAlpha);
|
||||
encodeRLEData(RLEVariant::PIC, stream, row, image.width(), alphaEqual, writeAlpha);
|
||||
} else {
|
||||
for (int i = 0; i < image.width(); ++i) {
|
||||
writeAlpha(stream, row[i]);
|
||||
@ -341,7 +331,7 @@ bool SoftimagePICHandler::canRead(QIODevice *device)
|
||||
if (device->peek(data, 4) != 4) {
|
||||
return false;
|
||||
}
|
||||
return qFromBigEndian<qint32>(reinterpret_cast<uchar*>(data)) == PIC_MAGIC_NUMBER;
|
||||
return qFromBigEndian<qint32>(reinterpret_cast<uchar *>(data)) == PIC_MAGIC_NUMBER;
|
||||
}
|
||||
|
||||
bool SoftimagePICHandler::readHeader()
|
||||
@ -374,67 +364,62 @@ bool SoftimagePICHandler::readChannels()
|
||||
void SoftimagePICHandler::setOption(ImageOption option, const QVariant &value)
|
||||
{
|
||||
switch (option) {
|
||||
case CompressionRatio:
|
||||
m_compression = value.toBool();
|
||||
break;
|
||||
case Description: {
|
||||
m_description.clear();
|
||||
const QStringList entries = value.toString().split(QStringLiteral("\n\n"));
|
||||
for (const QString &entry : entries) {
|
||||
if (entry.startsWith(QStringLiteral("Description: "))) {
|
||||
m_description = entry.mid(13).simplified().toUtf8();
|
||||
}
|
||||
case CompressionRatio:
|
||||
m_compression = value.toBool();
|
||||
break;
|
||||
case Description: {
|
||||
m_description.clear();
|
||||
const QStringList entries = value.toString().split(QStringLiteral("\n\n"));
|
||||
for (const QString &entry : entries) {
|
||||
if (entry.startsWith(QStringLiteral("Description: "))) {
|
||||
m_description = entry.mid(13).simplified().toUtf8();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant SoftimagePICHandler::option(ImageOption option) const
|
||||
{
|
||||
const_cast<SoftimagePICHandler*>(this)->readHeader();
|
||||
const_cast<SoftimagePICHandler *>(this)->readHeader();
|
||||
switch (option) {
|
||||
case Size:
|
||||
if (const_cast<SoftimagePICHandler*>(this)->readHeader()) {
|
||||
return QSize(m_header.width, m_header.height);
|
||||
} else {
|
||||
return QVariant();
|
||||
case Size:
|
||||
if (const_cast<SoftimagePICHandler *>(this)->readHeader()) {
|
||||
return QSize(m_header.width, m_header.height);
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
case CompressionRatio:
|
||||
return m_compression;
|
||||
case Description:
|
||||
if (const_cast<SoftimagePICHandler *>(this)->readHeader()) {
|
||||
QString descStr = QString::fromUtf8(m_header.comment);
|
||||
if (!descStr.isEmpty()) {
|
||||
return QString(QStringLiteral("Description: ") + descStr + QStringLiteral("\n\n"));
|
||||
}
|
||||
case CompressionRatio:
|
||||
return m_compression;
|
||||
case Description:
|
||||
if (const_cast<SoftimagePICHandler*>(this)->readHeader()) {
|
||||
QString descStr = QString::fromUtf8(m_header.comment);
|
||||
if (!descStr.isEmpty()) {
|
||||
return QString(QStringLiteral("Description: ") +
|
||||
descStr +
|
||||
QStringLiteral("\n\n"));
|
||||
}
|
||||
return QString();
|
||||
case ImageFormat:
|
||||
if (const_cast<SoftimagePICHandler *>(this)->readChannels()) {
|
||||
for (const PicChannel &channel : qAsConst(m_channels)) {
|
||||
if (channel.code & ALPHA) {
|
||||
return QImage::Format_ARGB32;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
case ImageFormat:
|
||||
if (const_cast<SoftimagePICHandler*>(this)->readChannels()) {
|
||||
for (const PicChannel &channel : qAsConst(m_channels)) {
|
||||
if (channel.code & ALPHA) {
|
||||
return QImage::Format_ARGB32;
|
||||
}
|
||||
}
|
||||
return QImage::Format_RGB32;
|
||||
}
|
||||
return QVariant();
|
||||
default:
|
||||
return QVariant();
|
||||
return QImage::Format_RGB32;
|
||||
}
|
||||
return QVariant();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool SoftimagePICHandler::supportsOption(ImageOption option) const
|
||||
{
|
||||
return (option == CompressionRatio ||
|
||||
option == Description ||
|
||||
option == ImageFormat ||
|
||||
option == Size);
|
||||
return (option == CompressionRatio || option == Description || option == ImageFormat || option == Size);
|
||||
}
|
||||
|
||||
QImageIOPlugin::Capabilities SoftimagePICPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
|
@ -8,8 +8,8 @@
|
||||
#ifndef KIMG_PIC_P_H
|
||||
#define KIMG_PIC_P_H
|
||||
|
||||
#include <QImageIOPlugin>
|
||||
#include <QDataStream>
|
||||
#include <QImageIOPlugin>
|
||||
|
||||
/**
|
||||
* The magic number at the start of a SoftImage PIC file.
|
||||
@ -70,9 +70,12 @@ struct PicHeader {
|
||||
, height(_height)
|
||||
, ratio(1.0f)
|
||||
, fields(BothScanlines)
|
||||
{}
|
||||
{
|
||||
}
|
||||
/** Construct an invalid header. */
|
||||
PicHeader() {}
|
||||
PicHeader()
|
||||
{
|
||||
}
|
||||
|
||||
quint32 magic; /**< Should be PIC_MAGIC_NUMBER */
|
||||
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.
|
||||
*/
|
||||
bool isValid() const {
|
||||
return magic == PIC_MAGIC_NUMBER
|
||||
&& id == "PICT";
|
||||
bool isValid() const
|
||||
{
|
||||
return magic == PIC_MAGIC_NUMBER && id == "PICT";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +126,8 @@ struct PicChannel {
|
||||
: size(_size)
|
||||
, encoding(_encoding)
|
||||
, code(_code)
|
||||
{}
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Constructs a default channel description for a SoftImage PIC file.
|
||||
*
|
||||
@ -135,7 +139,8 @@ struct PicChannel {
|
||||
*/
|
||||
PicChannel()
|
||||
: size(8)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SoftimagePICHandler : public QImageIOHandler
|
||||
@ -161,7 +166,8 @@ public:
|
||||
SoftimagePICHandler()
|
||||
: m_state(Ready)
|
||||
, m_compression(true)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool readHeader();
|
||||
bool readChannels();
|
||||
|
@ -29,9 +29,8 @@ typedef quint32 uint;
|
||||
typedef quint16 ushort;
|
||||
typedef quint8 uchar;
|
||||
|
||||
namespace // Private.
|
||||
namespace // Private.
|
||||
{
|
||||
|
||||
enum ColorMode {
|
||||
CM_BITMAP = 0,
|
||||
CM_GRAYSCALE = 1,
|
||||
@ -54,7 +53,7 @@ struct PSDHeader {
|
||||
ushort color_mode;
|
||||
};
|
||||
|
||||
static QDataStream &operator>> (QDataStream &s, PSDHeader &header)
|
||||
static QDataStream &operator>>(QDataStream &s, PSDHeader &header)
|
||||
{
|
||||
s >> header.signature;
|
||||
s >> header.version;
|
||||
@ -72,7 +71,7 @@ static QDataStream &operator>> (QDataStream &s, PSDHeader &header)
|
||||
// Check that the header is a valid PSD.
|
||||
static bool IsValid(const PSDHeader &header)
|
||||
{
|
||||
if (header.signature != 0x38425053) { // '8BPS'
|
||||
if (header.signature != 0x38425053) { // '8BPS'
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -104,26 +103,31 @@ static void skip_section(QDataStream &s)
|
||||
s.skipRawData(section_length);
|
||||
}
|
||||
|
||||
template <class Trait>
|
||||
static Trait readPixel(QDataStream &stream) {
|
||||
template<class Trait>
|
||||
static Trait readPixel(QDataStream &stream)
|
||||
{
|
||||
Trait pixel;
|
||||
stream >> 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));
|
||||
}
|
||||
static QRgb updateGreen(QRgb oldPixel, quint8 greenPixel) {
|
||||
static QRgb updateGreen(QRgb oldPixel, quint8 greenPixel)
|
||||
{
|
||||
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));
|
||||
}
|
||||
static QRgb updateAlpha(QRgb oldPixel, quint8 alphaPixel) {
|
||||
static QRgb updateAlpha(QRgb oldPixel, quint8 alphaPixel)
|
||||
{
|
||||
return qRgba(qRed(oldPixel), qGreen(oldPixel), qBlue(oldPixel), alphaPixel);
|
||||
}
|
||||
typedef QRgb(*channelUpdater)(QRgb,quint8);
|
||||
typedef QRgb (*channelUpdater)(QRgb, quint8);
|
||||
|
||||
// Load the PSD image.
|
||||
static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
@ -151,13 +155,11 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
|
||||
quint32 channel_num = header.channel_count;
|
||||
|
||||
QImage::Format fmt = header.depth == 8 ? QImage::Format_RGB32
|
||||
: QImage::Format_RGBX64;
|
||||
QImage::Format fmt = header.depth == 8 ? QImage::Format_RGB32 : QImage::Format_RGBX64;
|
||||
// Clear the image.
|
||||
if (channel_num >= 4) {
|
||||
// Enable alpha.
|
||||
fmt = header.depth == 8 ? QImage::Format_ARGB32
|
||||
: QImage::Format_RGBA64;
|
||||
fmt = header.depth == 8 ? QImage::Format_ARGB32 : QImage::Format_RGBA64;
|
||||
|
||||
// Ignore the other channels.
|
||||
channel_num = 4;
|
||||
@ -168,7 +170,7 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(header.width, header.height);
|
||||
return false;
|
||||
}
|
||||
img.fill(qRgb(0,0,0));
|
||||
img.fill(qRgb(0, 0, 0));
|
||||
|
||||
const quint32 pixel_count = header.height * header.width;
|
||||
const quint32 channel_size = pixel_count * header.depth / 8;
|
||||
@ -179,26 +181,27 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
return false;
|
||||
}
|
||||
|
||||
QRgb *image_data = reinterpret_cast<QRgb*>(img.bits());
|
||||
QRgb *image_data = reinterpret_cast<QRgb *>(img.bits());
|
||||
|
||||
if (!image_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const channelUpdater updaters[4] = {
|
||||
updateRed,
|
||||
updateGreen,
|
||||
updateBlue,
|
||||
updateAlpha
|
||||
};
|
||||
static const channelUpdater updaters[4] = {updateRed, updateGreen, updateBlue, updateAlpha};
|
||||
|
||||
typedef QRgba64(*channelUpdater16)(QRgba64, quint16);
|
||||
static const channelUpdater16 updaters64[4] = {
|
||||
[](QRgba64 oldPixel, quint16 redPixel) {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 alphaPixel){return qRgba64((oldPixel & ~(0xFFFFull << 48)) | (quint64(alphaPixel) << 48));}
|
||||
};
|
||||
typedef QRgba64 (*channelUpdater16)(QRgba64, quint16);
|
||||
static const channelUpdater16 updaters64[4] = {[](QRgba64 oldPixel, quint16 redPixel) {
|
||||
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 alphaPixel) {
|
||||
return qRgba64((oldPixel & ~(0xFFFFull << 48)) | (quint64(alphaPixel) << 48));
|
||||
}};
|
||||
|
||||
if (compression) {
|
||||
// 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++) {
|
||||
bool success = false;
|
||||
if (header.depth == 8) {
|
||||
success = decodeRLEData(RLEVariant::PackBits, stream,
|
||||
image_data, channel_size,
|
||||
&readPixel<quint8>, updaters[channel]);
|
||||
success = decodeRLEData(RLEVariant::PackBits, stream, image_data, channel_size, &readPixel<quint8>, updaters[channel]);
|
||||
} else if (header.depth == 16) {
|
||||
QRgba64 *image_data = reinterpret_cast<QRgba64*>(img.bits());
|
||||
success = decodeRLEData(RLEVariant::PackBits16, stream,
|
||||
image_data, channel_size,
|
||||
&readPixel<quint8>, updaters64[channel]);
|
||||
QRgba64 *image_data = reinterpret_cast<QRgba64 *>(img.bits());
|
||||
success = decodeRLEData(RLEVariant::PackBits16, stream, image_data, channel_size, &readPixel<quint8>, updaters64[channel]);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
@ -232,7 +231,7 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
image_data[i] = updaters[channel](image_data[i], readPixel<quint8>(stream));
|
||||
}
|
||||
} else if (header.depth == 16) {
|
||||
QRgba64 *image_data = reinterpret_cast<QRgba64*>(img.bits());
|
||||
QRgba64 *image_data = reinterpret_cast<QRgba64 *>(img.bits());
|
||||
for (unsigned i = 0; i < pixel_count; ++i) {
|
||||
image_data[i] = updaters64[channel](image_data[i], readPixel<quint16>(stream));
|
||||
}
|
||||
@ -273,19 +272,19 @@ bool PSDHandler::read(QImage *image)
|
||||
|
||||
// Check image file format.
|
||||
if (s.atEnd() || !IsValid(header)) {
|
||||
// qDebug() << "This PSD file is not valid.";
|
||||
// qDebug() << "This PSD file is not valid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it's a supported format.
|
||||
if (!IsSupported(header)) {
|
||||
// qDebug() << "This PSD file is not supported.";
|
||||
// qDebug() << "This PSD file is not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QImage img;
|
||||
if (!LoadPSD(s, header, img)) {
|
||||
// qDebug() << "Error loading PSD file.";
|
||||
// qDebug() << "Error loading PSD file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -32,4 +32,3 @@ public:
|
||||
};
|
||||
|
||||
#endif // KIMG_PSD_P_H
|
||||
|
||||
|
@ -9,11 +9,11 @@
|
||||
|
||||
#include "ras_p.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
|
||||
namespace // Private.
|
||||
namespace // Private.
|
||||
{
|
||||
// format info from http://www.fileformat.info/format/sunraster/egff.htm
|
||||
|
||||
@ -22,19 +22,19 @@ quint32 rasMagicBigEndian = 0x59a66a95;
|
||||
// quint32 rasMagicLittleEndian = 0x956aa659; # used to support wrong encoded files
|
||||
|
||||
enum RASType {
|
||||
RAS_TYPE_OLD = 0x0,
|
||||
RAS_TYPE_STANDARD = 0x1,
|
||||
RAS_TYPE_BYTE_ENCODED = 0x2,
|
||||
RAS_TYPE_RGB_FORMAT = 0x3,
|
||||
RAS_TYPE_TIFF_FORMAT = 0x4,
|
||||
RAS_TYPE_IFF_FORMAT = 0x5,
|
||||
RAS_TYPE_EXPERIMENTAL = 0xFFFF,
|
||||
RAS_TYPE_OLD = 0x0,
|
||||
RAS_TYPE_STANDARD = 0x1,
|
||||
RAS_TYPE_BYTE_ENCODED = 0x2,
|
||||
RAS_TYPE_RGB_FORMAT = 0x3,
|
||||
RAS_TYPE_TIFF_FORMAT = 0x4,
|
||||
RAS_TYPE_IFF_FORMAT = 0x5,
|
||||
RAS_TYPE_EXPERIMENTAL = 0xFFFF,
|
||||
};
|
||||
|
||||
enum RASColorMapType {
|
||||
RAS_COLOR_MAP_TYPE_NONE = 0x0,
|
||||
RAS_COLOR_MAP_TYPE_RGB = 0x1,
|
||||
RAS_COLOR_MAP_TYPE_RAW = 0x2,
|
||||
RAS_COLOR_MAP_TYPE_NONE = 0x0,
|
||||
RAS_COLOR_MAP_TYPE_RGB = 0x1,
|
||||
RAS_COLOR_MAP_TYPE_RAW = 0x2,
|
||||
};
|
||||
|
||||
struct RasHeader {
|
||||
@ -46,10 +46,12 @@ struct RasHeader {
|
||||
quint32 Type;
|
||||
quint32 ColorMapType;
|
||||
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)
|
||||
{
|
||||
s >> head.MagicNumber;
|
||||
s >> head.Width;
|
||||
@ -79,8 +81,7 @@ static bool IsSupported(const RasHeader &head)
|
||||
// check for an appropriate depth
|
||||
// we support 8bit+palette, 24bit and 32bit ONLY!
|
||||
// TODO: add support for 1bit
|
||||
if (!((head.Depth == 8 && head.ColorMapType == 1)
|
||||
|| head.Depth == 24 || head.Depth == 32)) {
|
||||
if (!((head.Depth == 8 && head.ColorMapType == 1) || head.Depth == 24 || head.Depth == 32)) {
|
||||
return false;
|
||||
}
|
||||
// the Type field adds support for RLE(BGR), RGB and other encodings
|
||||
@ -141,7 +142,7 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
|
||||
QVector<quint8> input(ras.Length);
|
||||
|
||||
int i = 0;
|
||||
while (! s.atEnd() && i < input.size()) {
|
||||
while (!s.atEnd() && i < input.size()) {
|
||||
s >> input[i];
|
||||
// I guess we need to find out if we're at the end of a line
|
||||
if (paddingrequired && i != 0 && !(i % (ras.Width * bpp))) {
|
||||
@ -168,7 +169,6 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
|
||||
img.setPixel(x, y, qRgb(red, green, blue));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) {
|
||||
@ -282,13 +282,13 @@ bool RASHandler::read(QImage *outImage)
|
||||
|
||||
// Check image file format. Type 2 is RLE, which causing seeking to be silly.
|
||||
if (!s.atEnd() && ras.Type != 2) {
|
||||
// qDebug() << "This RAS file is not valid, or an older version of the format.";
|
||||
// qDebug() << "This RAS file is not valid, or an older version of the format.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check supported file types.
|
||||
if (!IsSupported(ras)) {
|
||||
// qDebug() << "This RAS file is not supported.";
|
||||
// qDebug() << "This RAS file is not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ bool RASHandler::read(QImage *outImage)
|
||||
bool result = LoadRAS(s, ras, img);
|
||||
|
||||
if (result == false) {
|
||||
// qDebug() << "Error loading RAS file.";
|
||||
// qDebug() << "Error loading RAS file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -306,7 +306,6 @@ bool RASHandler::read(QImage *outImage)
|
||||
|
||||
QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
|
||||
if (format == "ras") {
|
||||
return Capabilities(CanRead);
|
||||
}
|
||||
|
@ -24,14 +24,17 @@
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
||||
#include <QImage>
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
|
||||
class RLEData : public QVector<uchar>
|
||||
{
|
||||
public:
|
||||
RLEData() {}
|
||||
RLEData(const uchar *d, uint l, uint o) : _offset(o)
|
||||
RLEData()
|
||||
{
|
||||
}
|
||||
RLEData(const uchar *d, uint l, uint o)
|
||||
: _offset(o)
|
||||
{
|
||||
for (uint i = 0; i < l; i++) {
|
||||
append(d[i]);
|
||||
@ -51,7 +54,11 @@ private:
|
||||
class RLEMap : public QMap<RLEData, uint>
|
||||
{
|
||||
public:
|
||||
RLEMap() : _counter(0), _offset(0) {}
|
||||
RLEMap()
|
||||
: _counter(0)
|
||||
, _offset(0)
|
||||
{
|
||||
}
|
||||
uint insert(const uchar *d, uint l);
|
||||
QVector<const RLEData *> vector();
|
||||
void setBaseOffset(uint o)
|
||||
@ -74,7 +81,12 @@ public:
|
||||
bool writeImage(const QImage &);
|
||||
|
||||
private:
|
||||
enum { NORMAL, DITHERED, SCREEN, COLORMAP, }; // colormap
|
||||
enum {
|
||||
NORMAL,
|
||||
DITHERED,
|
||||
SCREEN,
|
||||
COLORMAP,
|
||||
}; // colormap
|
||||
QIODevice *_dev;
|
||||
QDataStream _stream;
|
||||
|
||||
@ -108,9 +120,9 @@ private:
|
||||
uchar intensity(uchar);
|
||||
};
|
||||
|
||||
SGIImage::SGIImage(QIODevice *io) :
|
||||
_starttab(nullptr),
|
||||
_lengthtab(nullptr)
|
||||
SGIImage::SGIImage(QIODevice *io)
|
||||
: _starttab(nullptr)
|
||||
, _lengthtab(nullptr)
|
||||
{
|
||||
_dev = io;
|
||||
_stream.setDevice(_dev);
|
||||
@ -249,7 +261,7 @@ bool SGIImage::readImage(QImage &img)
|
||||
qint16 u16;
|
||||
qint32 u32;
|
||||
|
||||
// qDebug() << "reading rgb ";
|
||||
// qDebug() << "reading rgb ";
|
||||
|
||||
// magic
|
||||
_stream >> u16;
|
||||
@ -259,42 +271,42 @@ bool SGIImage::readImage(QImage &img)
|
||||
|
||||
// verbatim/rle
|
||||
_stream >> _rle;
|
||||
// qDebug() << (_rle ? "RLE" : "verbatim");
|
||||
// qDebug() << (_rle ? "RLE" : "verbatim");
|
||||
if (_rle > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// bytes per channel
|
||||
_stream >> _bpc;
|
||||
// qDebug() << "bytes per channel: " << int(_bpc);
|
||||
// qDebug() << "bytes per channel: " << int(_bpc);
|
||||
if (_bpc == 1)
|
||||
;
|
||||
else if (_bpc == 2) {
|
||||
// qDebug() << "dropping least significant byte";
|
||||
// qDebug() << "dropping least significant byte";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// number of dimensions
|
||||
_stream >> _dim;
|
||||
// qDebug() << "dimensions: " << _dim;
|
||||
// qDebug() << "dimensions: " << _dim;
|
||||
if (_dim < 1 || _dim > 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_stream >> _xsize >> _ysize >> _zsize >> _pixmin >> _pixmax >> u32;
|
||||
// qDebug() << "x: " << _xsize;
|
||||
// qDebug() << "y: " << _ysize;
|
||||
// qDebug() << "z: " << _zsize;
|
||||
// qDebug() << "x: " << _xsize;
|
||||
// qDebug() << "y: " << _ysize;
|
||||
// qDebug() << "z: " << _zsize;
|
||||
|
||||
// name
|
||||
_stream.readRawData(_imagename, 80);
|
||||
_imagename[79] = '\0';
|
||||
|
||||
_stream >> _colormap;
|
||||
// qDebug() << "colormap: " << _colormap;
|
||||
// qDebug() << "colormap: " << _colormap;
|
||||
if (_colormap != NORMAL) {
|
||||
return false; // only NORMAL supported
|
||||
return false; // only NORMAL supported
|
||||
}
|
||||
|
||||
for (int i = 0; i < 404; i++) {
|
||||
@ -302,7 +314,7 @@ bool SGIImage::readImage(QImage &img)
|
||||
}
|
||||
|
||||
if (_dim == 1) {
|
||||
// qDebug() << "1-dimensional images aren't supported yet";
|
||||
// qDebug() << "1-dimensional images aren't supported yet";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -316,13 +328,13 @@ bool SGIImage::readImage(QImage &img)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_zsize == 0 )
|
||||
if (_zsize == 0)
|
||||
return false;
|
||||
|
||||
if (_zsize == 2 || _zsize == 4) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32);
|
||||
} else if (_zsize > 4) {
|
||||
// qDebug() << "using first 4 of " << _zsize << " channels";
|
||||
// qDebug() << "using first 4 of " << _zsize << " channels";
|
||||
// Only let this continue if it won't cause a int overflow later
|
||||
// this is most likely a broken file anyway
|
||||
if (_ysize > std::numeric_limits<int>::max() / _zsize)
|
||||
@ -355,12 +367,12 @@ bool SGIImage::readImage(QImage &img)
|
||||
for (uint o = 0; o < _numrows; o++)
|
||||
// don't change to greater-or-equal!
|
||||
if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
|
||||
// qDebug() << "image corrupt (sanity check failed)";
|
||||
// qDebug() << "image corrupt (sanity check failed)";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!readData(img)) {
|
||||
// qDebug() << "image corrupt (incomplete scanline)";
|
||||
// qDebug() << "image corrupt (incomplete scanline)";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -567,7 +579,7 @@ void SGIImage::writeHeader()
|
||||
void SGIImage::writeRle()
|
||||
{
|
||||
_rle = 1;
|
||||
// qDebug() << "writing RLE data";
|
||||
// qDebug() << "writing RLE data";
|
||||
writeHeader();
|
||||
uint i;
|
||||
|
||||
@ -590,7 +602,7 @@ void SGIImage::writeRle()
|
||||
void SGIImage::writeVerbatim(const QImage &img)
|
||||
{
|
||||
_rle = 0;
|
||||
// qDebug() << "writing verbatim data";
|
||||
// qDebug() << "writing verbatim data";
|
||||
writeHeader();
|
||||
|
||||
const QRgb *c;
|
||||
@ -637,7 +649,7 @@ void SGIImage::writeVerbatim(const QImage &img)
|
||||
|
||||
bool SGIImage::writeImage(const QImage &image)
|
||||
{
|
||||
// qDebug() << "writing "; // TODO add filename
|
||||
// qDebug() << "writing "; // TODO add filename
|
||||
QImage img = image;
|
||||
if (img.allGray()) {
|
||||
_dim = 2, _zsize = 1;
|
||||
@ -651,7 +663,7 @@ bool SGIImage::writeImage(const QImage &image)
|
||||
|
||||
img = img.convertToFormat(QImage::Format_RGB32);
|
||||
if (img.isNull()) {
|
||||
// qDebug() << "can't convert image to depth 32";
|
||||
// qDebug() << "can't convert image to depth 32";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -666,7 +678,7 @@ bool SGIImage::writeImage(const QImage &image)
|
||||
_rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
|
||||
|
||||
if (!scanData(img)) {
|
||||
// qDebug() << "this can't happen";
|
||||
// qDebug() << "this can't happen";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -678,11 +690,11 @@ bool SGIImage::writeImage(const QImage &image)
|
||||
rle_size += _rlevector[i]->size();
|
||||
}
|
||||
|
||||
// qDebug() << "minimum intensity: " << _pixmin;
|
||||
// qDebug() << "maximum intensity: " << _pixmax;
|
||||
// qDebug() << "saved scanlines: " << _numrows - _rlemap.size();
|
||||
// qDebug() << "total savings: " << (verbatim_size - rle_size) << " bytes";
|
||||
// qDebug() << "compression: " << (rle_size * 100.0 / verbatim_size) << '%';
|
||||
// qDebug() << "minimum intensity: " << _pixmin;
|
||||
// qDebug() << "maximum intensity: " << _pixmax;
|
||||
// qDebug() << "saved scanlines: " << _numrows - _rlemap.size();
|
||||
// qDebug() << "total savings: " << (verbatim_size - rle_size) << " bytes";
|
||||
// qDebug() << "compression: " << (rle_size * 100.0 / verbatim_size) << '%';
|
||||
|
||||
if (verbatim_size <= rle_size) {
|
||||
writeVerbatim(img);
|
||||
@ -746,8 +758,7 @@ bool RGBHandler::canRead(QIODevice *device)
|
||||
|
||||
QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
if (format == "rgb" || format == "rgba" ||
|
||||
format == "bw" || format == "sgi") {
|
||||
if (format == "rgb" || format == "rgba" || format == "bw" || format == "sgi") {
|
||||
return Capabilities(CanRead | CanWrite);
|
||||
}
|
||||
if (!format.isEmpty()) {
|
||||
|
@ -33,4 +33,3 @@ public:
|
||||
};
|
||||
|
||||
#endif // KIMG_RGB_P_H
|
||||
|
||||
|
@ -8,8 +8,8 @@
|
||||
#ifndef KIMAGEFORMATS_RLE_P_H
|
||||
#define KIMAGEFORMATS_RLE_P_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
||||
/**
|
||||
* The RLEVariant to use.
|
||||
@ -64,12 +64,7 @@ enum class RLEVariant {
|
||||
* into @p buf, @c false otherwise.
|
||||
*/
|
||||
template<typename Item, typename Func1, typename Func2>
|
||||
static inline bool decodeRLEData(RLEVariant variant,
|
||||
QDataStream &stream,
|
||||
Item *dest,
|
||||
quint32 length,
|
||||
Func1 readData,
|
||||
Func2 updateItem)
|
||||
static inline bool decodeRLEData(RLEVariant variant, QDataStream &stream, Item *dest, quint32 length, Func1 readData, Func2 updateItem)
|
||||
{
|
||||
unsigned offset = 0; // in dest
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<typename Item, typename Func1, typename Func2>
|
||||
static inline void encodeRLEData(RLEVariant variant,
|
||||
QDataStream &stream,
|
||||
const Item *data,
|
||||
unsigned length,
|
||||
Func1 itemsEqual,
|
||||
Func2 writeItem)
|
||||
static inline void encodeRLEData(RLEVariant variant, QDataStream &stream, const Item *data, unsigned length, Func1 itemsEqual, Func2 writeItem)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
const unsigned maxEncodableChunk =
|
||||
(variant == RLEVariant::PIC)
|
||||
? 65535u
|
||||
: 128;
|
||||
const unsigned maxEncodableChunk = (variant == RLEVariant::PIC) ? 65535u : 128;
|
||||
while (offset < length) {
|
||||
const Item *chunkStart = data + offset;
|
||||
unsigned maxChunk = qMin(length - offset, maxEncodableChunk);
|
||||
@ -220,10 +206,7 @@ static inline void encodeRLEData(RLEVariant variant,
|
||||
}
|
||||
chunkLength = 1;
|
||||
chunkEnd = chunkStart + 1;
|
||||
while (chunkLength < maxChunk &&
|
||||
(chunkLength + 1u == maxChunk ||
|
||||
!itemsEqual(*chunkEnd, *(chunkEnd+1))))
|
||||
{
|
||||
while (chunkLength < maxChunk && (chunkLength + 1u == maxChunk || !itemsEqual(*chunkEnd, *(chunkEnd + 1)))) {
|
||||
++chunkEnd;
|
||||
++chunkLength;
|
||||
}
|
||||
|
@ -20,27 +20,26 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
|
||||
typedef quint32 uint;
|
||||
typedef quint16 ushort;
|
||||
typedef quint8 uchar;
|
||||
|
||||
namespace // Private.
|
||||
namespace // Private.
|
||||
{
|
||||
|
||||
// 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};
|
||||
|
||||
enum TGAType {
|
||||
TGA_TYPE_INDEXED = 1,
|
||||
TGA_TYPE_RGB = 2,
|
||||
TGA_TYPE_GREY = 3,
|
||||
TGA_TYPE_RLE_INDEXED = 9,
|
||||
TGA_TYPE_RLE_RGB = 10,
|
||||
TGA_TYPE_RLE_GREY = 11,
|
||||
TGA_TYPE_INDEXED = 1,
|
||||
TGA_TYPE_RGB = 2,
|
||||
TGA_TYPE_GREY = 3,
|
||||
TGA_TYPE_RLE_INDEXED = 9,
|
||||
TGA_TYPE_RLE_RGB = 10,
|
||||
TGA_TYPE_RLE_GREY = 11,
|
||||
};
|
||||
|
||||
#define TGA_INTERLEAVE_MASK 0xc0
|
||||
@ -48,11 +47,11 @@ enum TGAType {
|
||||
#define TGA_INTERLEAVE_2WAY 0x40
|
||||
#define TGA_INTERLEAVE_4WAY 0x80
|
||||
|
||||
#define TGA_ORIGIN_MASK 0x30
|
||||
#define TGA_ORIGIN_LEFT 0x00
|
||||
#define TGA_ORIGIN_RIGHT 0x10
|
||||
#define TGA_ORIGIN_LOWER 0x00
|
||||
#define TGA_ORIGIN_UPPER 0x20
|
||||
#define TGA_ORIGIN_MASK 0x30
|
||||
#define TGA_ORIGIN_LEFT 0x00
|
||||
#define TGA_ORIGIN_RIGHT 0x10
|
||||
#define TGA_ORIGIN_LOWER 0x00
|
||||
#define TGA_ORIGIN_UPPER 0x20
|
||||
|
||||
/** Tga Header. */
|
||||
struct TgaHeader {
|
||||
@ -69,10 +68,12 @@ struct TgaHeader {
|
||||
uchar pixel_size;
|
||||
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)
|
||||
{
|
||||
s >> head.id_length;
|
||||
s >> head.colormap_type;
|
||||
@ -88,30 +89,23 @@ static QDataStream &operator>> (QDataStream &s, TgaHeader &head)
|
||||
s >> head.flags;
|
||||
/*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() << "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;
|
||||
}
|
||||
|
||||
static bool IsSupported(const TgaHeader &head)
|
||||
{
|
||||
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_RLE_RGB &&
|
||||
head.image_type != TGA_TYPE_RLE_GREY) {
|
||||
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_RLE_RGB && head.image_type != TGA_TYPE_RLE_GREY) {
|
||||
return false;
|
||||
}
|
||||
if (head.image_type == TGA_TYPE_INDEXED ||
|
||||
head.image_type == TGA_TYPE_RLE_INDEXED) {
|
||||
if (head.image_type == TGA_TYPE_INDEXED || head.image_type == TGA_TYPE_RLE_INDEXED) {
|
||||
if (head.colormap_length > 256 || head.colormap_size != 24 || head.colormap_type != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
if (head.colormap_type != 0) {
|
||||
return false;
|
||||
}
|
||||
@ -119,8 +113,7 @@ static bool IsSupported(const TgaHeader &head)
|
||||
if (head.width == 0 || head.height == 0) {
|
||||
return false;
|
||||
}
|
||||
if (head.pixel_size != 8 && head.pixel_size != 16 &&
|
||||
head.pixel_size != 24 && head.pixel_size != 32) {
|
||||
if (head.pixel_size != 8 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -138,12 +131,16 @@ struct TgaHeaderInfo {
|
||||
bool rgb;
|
||||
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) {
|
||||
case TGA_TYPE_RLE_INDEXED:
|
||||
rle = true;
|
||||
Q_FALLTHROUGH();
|
||||
Q_FALLTHROUGH();
|
||||
// no break is intended!
|
||||
case TGA_TYPE_INDEXED:
|
||||
pal = true;
|
||||
@ -151,7 +148,7 @@ struct TgaHeaderInfo {
|
||||
|
||||
case TGA_TYPE_RLE_RGB:
|
||||
rle = true;
|
||||
Q_FALLTHROUGH();
|
||||
Q_FALLTHROUGH();
|
||||
// no break is intended!
|
||||
case TGA_TYPE_RGB:
|
||||
rgb = true;
|
||||
@ -159,7 +156,7 @@ struct TgaHeaderInfo {
|
||||
|
||||
case TGA_TYPE_RLE_GREY:
|
||||
rle = true;
|
||||
Q_FALLTHROUGH();
|
||||
Q_FALLTHROUGH();
|
||||
// no break is intended!
|
||||
case TGA_TYPE_GREY:
|
||||
grey = true;
|
||||
@ -202,7 +199,7 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
||||
qint64 size = qint64(tga.width) * qint64(tga.height) * pixel_size;
|
||||
|
||||
if (size < 1) {
|
||||
// qDebug() << "This TGA file is broken with size " << size;
|
||||
// qDebug() << "This TGA file is broken with size " << size;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -225,7 +222,7 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
||||
}
|
||||
|
||||
// Allocate image.
|
||||
uchar *const image = reinterpret_cast<uchar*>(malloc(size));
|
||||
uchar *const image = reinterpret_cast<uchar *>(malloc(size));
|
||||
if (!image) {
|
||||
return false;
|
||||
}
|
||||
@ -282,11 +279,11 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ((uint)dataRead < count) {
|
||||
const size_t toCopy = count - dataRead;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -328,7 +325,7 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
||||
uchar *src = image;
|
||||
|
||||
for (int y = y_start; y != y_end; y += y_step) {
|
||||
QRgb *scanline = (QRgb *) img.scanLine(y);
|
||||
QRgb *scanline = (QRgb *)img.scanLine(y);
|
||||
|
||||
if (info.pal) {
|
||||
// Paletted.
|
||||
@ -389,7 +386,7 @@ bool TGAHandler::canRead() const
|
||||
|
||||
bool TGAHandler::read(QImage *outImage)
|
||||
{
|
||||
//qDebug() << "Loading TGA file!";
|
||||
// qDebug() << "Loading TGA file!";
|
||||
|
||||
QDataStream s(device());
|
||||
s.setByteOrder(QDataStream::LittleEndian);
|
||||
@ -401,13 +398,13 @@ bool TGAHandler::read(QImage *outImage)
|
||||
|
||||
// Check image file format.
|
||||
if (s.atEnd()) {
|
||||
// qDebug() << "This TGA file is not valid.";
|
||||
// qDebug() << "This TGA file is not valid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check supported file types.
|
||||
if (!IsSupported(tga)) {
|
||||
// qDebug() << "This TGA file is not supported.";
|
||||
// qDebug() << "This TGA file is not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -415,7 +412,7 @@ bool TGAHandler::read(QImage *outImage)
|
||||
bool result = LoadTGA(s, tga, img);
|
||||
|
||||
if (result == false) {
|
||||
// qDebug() << "Error loading TGA file.";
|
||||
// qDebug() << "Error loading TGA file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -435,10 +432,10 @@ bool TGAHandler::write(const QImage &image)
|
||||
}
|
||||
|
||||
// write header
|
||||
s << quint16(img.width()); // width
|
||||
s << quint16(img.height()); // height
|
||||
s << quint8(hasAlpha ? 32 : 24); // depth (24 bit RGB + 8 bit alpha)
|
||||
s << quint8(hasAlpha ? 0x24 : 0x20); // top left image (0x20) + 8 bit alpha (0x4)
|
||||
s << quint16(img.width()); // width
|
||||
s << quint16(img.height()); // height
|
||||
s << quint8(hasAlpha ? 32 : 24); // depth (24 bit RGB + 8 bit alpha)
|
||||
s << quint8(hasAlpha ? 0x24 : 0x20); // top left image (0x20) + 8 bit alpha (0x4)
|
||||
|
||||
for (int y = 0; y < img.height(); y++)
|
||||
for (int x = 0; x < img.width(); x++) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,8 @@
|
||||
#ifndef FORMAT_ENUM_H
|
||||
#define FORMAT_ENUM_H
|
||||
|
||||
#include <QMetaEnum>
|
||||
#include <QImage>
|
||||
#include <QMetaEnum>
|
||||
|
||||
QImage::Format formatFromString(const QString &str)
|
||||
{
|
||||
|
@ -27,19 +27,15 @@ int main(int argc, char **argv)
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument(QStringLiteral("in"), QStringLiteral("input image file"));
|
||||
parser.addPositionalArgument(QStringLiteral("out"), QStringLiteral("output image file"));
|
||||
QCommandLineOption informat(
|
||||
QStringList() << QStringLiteral("i") << QStringLiteral("informat"),
|
||||
QStringLiteral("Image format for input file"),
|
||||
QStringLiteral("format"));
|
||||
QCommandLineOption informat(QStringList() << QStringLiteral("i") << QStringLiteral("informat"),
|
||||
QStringLiteral("Image format for input file"),
|
||||
QStringLiteral("format"));
|
||||
parser.addOption(informat);
|
||||
QCommandLineOption outformat(
|
||||
QStringList() << QStringLiteral("o") << QStringLiteral("outformat"),
|
||||
QStringLiteral("Image format for output file"),
|
||||
QStringLiteral("format"));
|
||||
QCommandLineOption outformat(QStringList() << QStringLiteral("o") << QStringLiteral("outformat"),
|
||||
QStringLiteral("Image format for output file"),
|
||||
QStringLiteral("format"));
|
||||
parser.addOption(outformat);
|
||||
QCommandLineOption listformats(
|
||||
QStringList() << QStringLiteral("l") << QStringLiteral("list"),
|
||||
QStringLiteral("List supported image formats"));
|
||||
QCommandLineOption listformats(QStringList() << QStringLiteral("l") << QStringLiteral("list"), QStringLiteral("List supported image formats"));
|
||||
parser.addOption(listformats);
|
||||
|
||||
parser.process(app);
|
||||
|
@ -10,10 +10,10 @@
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QImageReader>
|
||||
#include <QFile>
|
||||
#include <QMetaObject>
|
||||
#include <QImageReader>
|
||||
#include <QMetaEnum>
|
||||
#include <QMetaObject>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "format-enum.h"
|
||||
@ -31,27 +31,22 @@ int main(int argc, char **argv)
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument(QStringLiteral("image"), QStringLiteral("image file"));
|
||||
parser.addPositionalArgument(QStringLiteral("datafile"), QStringLiteral("file QImage data should be written to"));
|
||||
QCommandLineOption informat(
|
||||
QStringList() << QStringLiteral("f") << QStringLiteral("file-format"),
|
||||
QStringLiteral("Image file format"),
|
||||
QStringLiteral("format"));
|
||||
QCommandLineOption informat(QStringList() << QStringLiteral("f") << QStringLiteral("file-format"),
|
||||
QStringLiteral("Image file format"),
|
||||
QStringLiteral("format"));
|
||||
parser.addOption(informat);
|
||||
QCommandLineOption qimgformat(
|
||||
QStringList() << QStringLiteral("q") << QStringLiteral("qimage-format"),
|
||||
QStringLiteral("QImage data format"),
|
||||
QStringLiteral("format"));
|
||||
QCommandLineOption qimgformat(QStringList() << QStringLiteral("q") << QStringLiteral("qimage-format"),
|
||||
QStringLiteral("QImage data format"),
|
||||
QStringLiteral("format"));
|
||||
parser.addOption(qimgformat);
|
||||
QCommandLineOption listformats(
|
||||
QStringList() << QStringLiteral("l") << QStringLiteral("list-file-formats"),
|
||||
QStringLiteral("List supported image file formats"));
|
||||
QCommandLineOption listformats(QStringList() << QStringLiteral("l") << QStringLiteral("list-file-formats"),
|
||||
QStringLiteral("List supported image file formats"));
|
||||
parser.addOption(listformats);
|
||||
QCommandLineOption listmimetypes(
|
||||
QStringList() << QStringLiteral("m") << QStringLiteral("list-mime-types"),
|
||||
QStringLiteral("List supported image mime types"));
|
||||
QCommandLineOption listmimetypes(QStringList() << QStringLiteral("m") << QStringLiteral("list-mime-types"),
|
||||
QStringLiteral("List supported image mime types"));
|
||||
parser.addOption(listmimetypes);
|
||||
QCommandLineOption listqformats(
|
||||
QStringList() << QStringLiteral("p") << QStringLiteral("list-qimage-formats"),
|
||||
QStringLiteral("List supported QImage data formats"));
|
||||
QCommandLineOption listqformats(QStringList() << QStringLiteral("p") << QStringLiteral("list-qimage-formats"),
|
||||
QStringLiteral("List supported QImage data formats"));
|
||||
parser.addOption(listqformats);
|
||||
|
||||
parser.process(app);
|
||||
@ -93,35 +88,29 @@ int main(int argc, char **argv)
|
||||
QImageReader reader(files.at(0), parser.value(informat).toLatin1());
|
||||
QImage img = reader.read();
|
||||
if (img.isNull()) {
|
||||
QTextStream(stderr) << "Could not read image: "
|
||||
<< reader.errorString() << '\n';
|
||||
QTextStream(stderr) << "Could not read image: " << reader.errorString() << '\n';
|
||||
return 2;
|
||||
}
|
||||
|
||||
QFile output(files.at(1));
|
||||
if (!output.open(QIODevice::WriteOnly)) {
|
||||
QTextStream(stderr) << "Could not open " << files.at(1)
|
||||
<< " for writing: "
|
||||
<< output.errorString() << '\n';
|
||||
QTextStream(stderr) << "Could not open " << files.at(1) << " for writing: " << output.errorString() << '\n';
|
||||
return 3;
|
||||
}
|
||||
if (parser.isSet(qimgformat)) {
|
||||
QImage::Format qformat = formatFromString(parser.value(qimgformat));
|
||||
if (qformat == QImage::Format_Invalid) {
|
||||
QTextStream(stderr) << "Unknown QImage data format "
|
||||
<< parser.value(qimgformat) << '\n';
|
||||
QTextStream(stderr) << "Unknown QImage data format " << parser.value(qimgformat) << '\n';
|
||||
return 4;
|
||||
}
|
||||
img = img.convertToFormat(qformat);
|
||||
}
|
||||
qint64 written = output.write(reinterpret_cast<const char *>(img.bits()), img.sizeInBytes());
|
||||
if (written != img.sizeInBytes()) {
|
||||
QTextStream(stderr) << "Could not write image data to " << files.at(1)
|
||||
<< ":" << output.errorString() << "\n";
|
||||
QTextStream(stderr) << "Could not write image data to " << files.at(1) << ":" << output.errorString() << "\n";
|
||||
return 5;
|
||||
}
|
||||
QTextStream(stdout) << "Created " << files.at(1) << " with data format "
|
||||
<< formatToString(img.format()) << "\n";
|
||||
QTextStream(stdout) << "Created " << files.at(1) << " with data format " << formatToString(img.format()) << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user