Compare commits

..

24 Commits

Author SHA1 Message Date
96b40da089 GIT_SILENT Upgrade ECM and KF version requirements for 5.83.0 release. 2021-06-05 08:55:28 +00:00
bf3f94da76 avif: Adjust for libavif breaking change 2021-06-04 14:37:10 +02:00
318dacda75 Remove compiler flags already defined in extra-cmake-modules
-DQT_NO_FOREACH

GIT_SILENT
2021-05-23 17:18:51 +02:00
e358bb0feb Bump required CMake version to 3.16
KF6 task: https://phabricator.kde.org/T14467
2021-05-17 13:21:23 +02:00
dca6e87c89 Enable HEIC plugin to save all ICC profiles 2021-05-14 12:30:28 +02:00
62f9af9a35 Color profile loading/saving fixes
Allow saving Qt-unsupported variants of ICC profiles, they could be
correctly handled by apps with wider color management support.
Change way how QColorSpace is created to avoid
rare problems in some apps.
2021-05-13 16:56:46 +02:00
ff53d3d7e9 xcf: Make sure offsets are not negative
It's not a huge problem since QIODevice::seek() is a noop on negative values but it's
just better to bail out as soon as possible when we realize the file is
broken
2021-05-05 17:23:59 +02:00
780f342825 GIT_SILENT Add auto generated files to .gitignore 2021-05-02 12:48:16 +02:00
297ed9a2fe xcf: Fix Stack-buffer-overflow WRITE on broken files
oss-fuzz/33742
2021-05-02 09:50:50 +00:00
55b4077f2c GIT_SILENT Upgrade ECM and KF version requirements for 5.82.0 release. 2021-05-01 09:42:14 +00:00
2429c95336 Support building with OpenEXR 3
Try to find OpenEXR 3 first via the upstream cmake config and fallback to using our FindOpenEXR
2021-04-24 10:17:25 +00:00
224f892b09 GIT_SILENT increase KF_DISABLE_DEPRECATED_BEFORE_AND_AT 2021-04-11 12:05:38 +02:00
64fa129ed6 GIT_SILENT Add auto generated files to .gitignore 2021-04-07 21:06:01 +02:00
3cb4021afc test: imageconverter: add a way to list mimes instead of formats 2021-04-05 09:44:03 +00:00
95a19a15c3 xcf: fix new[]/delete mismatch, as detected by ASAN 2021-04-04 17:30:52 +02:00
1ba23a1e8e Port away from QPrinter::setPaperSize, deprecated in Qt 5.15
The formula was found in Qt's qt_pixelMultiplier (qpagesize.cpp)
as called by the deprecated setPaperSize method (when the unit is
DevicePixel)

NO_CHANGELOG
2021-04-04 15:56:13 +02:00
bc3c04c7ce GIT_SILENT Upgrade Qt5 version requirement to 5.15.0. 2021-04-04 14:44:40 +02:00
2755f74fbb ani: convert +1 to -1 so we don't do a potential integer overflow
oss-fuzz/32601

runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
2021-04-03 22:46:33 +00:00
3b0c767f82 GIT_SILENT Upgrade ECM and KF version requirements for 5.81.0 release. 2021-04-03 09:33:41 +00:00
e80fcd7c30 GIT_SILENT increase KF_DISABLE_DEPRECATED_BEFORE_AND_AT 2021-03-27 11:37:36 +01:00
a73e3d44dd Add .git-blame-ignore-revs
GIT_SILENT
2021-03-09 02:18:09 +02:00
1169859b07 Run clang-format on all cpp/h files
NO_CHANGELOG
2021-03-08 20:15:33 +02:00
04e276dcb3 Add clang-format bits to CMakeLists.txt
GIT_SILENT
2021-03-08 20:14:48 +02:00
e3ab850712 Add a trailing comma to enum
Should help produce better diffs and clang-format won't squash the enum
on one line.

GIT_SILENT
2021-03-08 20:14:42 +02:00
36 changed files with 1126 additions and 1312 deletions

2
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,2 @@
#clang-format
1169859b07f25c865ee0bfc2a7dc97a431651776

4
.gitignore vendored
View File

@ -22,3 +22,7 @@ CMakeLists.txt.user*
.cmake/
/.clang-format
/compile_commands.json
.clangd
.idea
/cmake-build*
.cache

View File

@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.16)
project(KImageFormats)
set (CMAKE_CXX_STANDARD 14)
include(FeatureSummary)
find_package(ECM 5.80.0 NO_MODULE)
find_package(ECM 5.83.0 NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
@ -15,11 +15,12 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(KDEGitCommitHooks)
include(CheckIncludeFiles)
set(REQUIRED_QT_VERSION 5.14.0)
set(REQUIRED_QT_VERSION 5.15.0)
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
find_package(KF5Archive)
@ -42,7 +43,10 @@ if (UNIX)
endif()
endif()
find_package(OpenEXR)
find_package(OpenEXR 3.0 CONFIG QUIET)
if(NOT OpenEXR_FOUND)
find_package(OpenEXR)
endif()
set_package_properties(OpenEXR PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for the QImage plugin for OpenEXR images"
@ -61,11 +65,10 @@ if(KIMAGEFORMATS_HEIF)
endif()
add_feature_info(LibHeif LibHeif_FOUND "required for the QImage plugin for HEIF/HEIC images")
add_definitions(-DQT_NO_FOREACH)
# 050d00 (5.13) triggers a BIC in qimageiohandler.h, in Qt 5.13, so do not enable that until we can require 5.14
# https://codereview.qt-project.org/c/qt/qtbase/+/279215
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050e00)
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054F00)
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050f00)
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x055100)
add_subdirectory(src)
if (BUILD_TESTING)
add_subdirectory(autotests)
@ -73,3 +76,5 @@ if (BUILD_TESTING)
endif()
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)

View File

@ -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,28 +138,19 @@ 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()
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);
}
};

View File

@ -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,8 +91,7 @@ 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"),
QCommandLineOption fuzz(QStringList() << QStringLiteral("f") << QStringLiteral("fuzz"),
QStringLiteral("Allow for some deviation in ARGB data."),
QStringLiteral("max"));
parser.addOption(fuzz);
@ -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,39 +153,26 @@ 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 "
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 "
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": height was " << inputImage.height() << " but " << expfilename << " height was "
<< expImage.height() << "\n";
++failed;
} else {
@ -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())
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;
}

View File

@ -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,8 +29,7 @@ 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"),
QCommandLineOption lossless(QStringList() << QStringLiteral("l") << QStringLiteral("lossless"),
QStringLiteral("Check that reading back the data gives the same image."));
parser.addOption(lossless);
@ -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;
}

View File

@ -58,7 +58,11 @@ install(FILES jp2.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/qimageioplugi
if(OpenEXR_FOUND)
kimageformats_add_plugin(kimg_exr JSON "exr.json" SOURCES exr.cpp)
if(TARGET OpenEXR::OpenEXR)
target_link_libraries(kimg_exr OpenEXR::OpenEXR)
else()
target_link_libraries(kimg_exr OpenEXR::IlmImf)
endif()
kde_target_enable_exceptions(kimg_exr PRIVATE)
install(FILES exr.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)

View File

@ -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;
@ -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;
}
@ -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);
}
@ -508,7 +504,7 @@ bool ANIHandler::ensureScanned() const
return false;
}
if (!m_frameOffsets.isEmpty() && m_frameOffsets.count() != m_frameCount + 1) {
if (!m_frameOffsets.isEmpty() && m_frameOffsets.count() - 1 != m_frameCount) {
qWarning("ANIHandler: number of actual frames does not match 'nFrames' in anih");
return false;
}

View File

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

View File

@ -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;
@ -193,13 +190,15 @@ bool QAVIFHandler::decode_one_frame()
return false;
}
QColorSpace colorspace;
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()) {
qWarning("Invalid QColorSpace created from ICC!");
const QByteArray icc_data((const char *)m_decoder->image->icc.data, (int)m_decoder->image->icc.size);
colorspace = QColorSpace::fromIccProfile(icc_data);
if (!colorspace.isValid()) {
qWarning("AVIF image has Qt-unsupported or invalid ICC profile!");
}
} 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 +207,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;
@ -235,34 +233,37 @@ bool QAVIFHandler::decode_one_frame()
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:
case 1:
case 2: /* AVIF_COLOR_PRIMARIES_UNSPECIFIED */
result.setColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, q_trc, q_trc_gamma));
colorspace = QColorSpace(QColorSpace::Primaries::SRgb, q_trc, q_trc_gamma);
break;
/* AVIF_COLOR_PRIMARIES_SMPTE432 */
case 12:
result.setColorSpace(QColorSpace(QColorSpace::Primaries::DciP3D65, q_trc, q_trc_gamma));
colorspace = QColorSpace(QColorSpace::Primaries::DciP3D65, q_trc, q_trc_gamma);
break;
default:
result.setColorSpace(QColorSpace(whitePoint, redPoint, greenPoint, bluePoint, q_trc, q_trc_gamma));
colorspace = QColorSpace(whitePoint, redPoint, greenPoint, bluePoint, q_trc, q_trc_gamma);
break;
}
}
if (! result.colorSpace().isValid()) {
qWarning("Invalid QColorSpace created from NCLX/CICP!");
if (!colorspace.isValid()) {
qWarning("AVIF plugin created invalid QColorSpace from NCLX/CICP!");
}
}
result.setColorSpace(colorspace);
avifRGBImage rgb;
avifRGBImageSetDefaults(&rgb, m_decoder->image);
@ -303,8 +304,8 @@ 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)) {
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);
@ -318,17 +319,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 +337,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");
}
}
@ -363,11 +361,15 @@ bool QAVIFHandler::decode_one_frame()
}
if (m_decoder->image->transformFlags & AVIF_TRANSFORM_IMIR) {
#if AVIF_VERSION > 90100
switch (m_decoder->image->imir.mode) {
#else
switch (m_decoder->image->imir.axis) {
case 0: //vertical
#endif
case 0: // top-to-bottom
result = result.mirrored(false, true);
break;
case 1: //horizontal
case 1: // left-to-right
result = result.mirrored(true, false);
break;
}
@ -417,13 +419,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 +441,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 +462,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 +498,6 @@ bool QAVIFHandler::write(const QImage &image)
/* AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED */
break;
}
}
if (save_depth > 8) { // QImage::Format_Grayscale16
@ -504,7 +505,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 +523,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,16 +543,17 @@ 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;
QByteArray iccprofile;
if (tmpcolorimage.colorSpace().isValid()) {
switch (tmpcolorimage.colorSpace().primaries()) {
@ -602,11 +604,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 +616,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,30 +635,39 @@ 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
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::SRgb));
}
}
} else { // profile is unsupported by Qt
iccprofile = tmpcolorimage.colorSpace().iccProfile();
if (iccprofile.size() > 0) {
matrix_to_save = (avifMatrixCoefficients)6;
}
}
avif = avifImageCreate(tmpcolorimage.width(), tmpcolorimage.height(), save_depth, pixel_format);
avif->matrixCoefficients = matrix_to_save;
avif->colorPrimaries = primaries_to_save;
avif->transferCharacteristics = transfer_to_save;
if (iccprofile.size() > 0) {
avifImageSetProfileICC(avif, (const uint8_t *)iccprofile.constData(), iccprofile.size());
}
avifRGBImage rgb;
avifRGBImageSetDefaults(&rgb, avif);
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 +677,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 +729,6 @@ bool QAVIFHandler::write(const QImage &image)
return false;
}
QVariant QAVIFHandler::option(ImageOption option) const
{
if (option == Quality) {
@ -765,9 +772,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 +810,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 +822,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 +839,6 @@ bool QAVIFHandler::jumpToNextImage()
m_parseState = ParseAvifError;
return false;
}
}
bool QAVIFHandler::jumpToImage(int imageNumber)
@ -842,7 +847,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,7 +855,7 @@ 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;
}
@ -866,11 +871,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;

View File

@ -9,13 +9,13 @@
#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
{
@ -24,34 +24,34 @@ public:
~QAVIFHandler();
bool canRead() const override;
bool read (QImage *image) override;
bool write (const QImage &image) 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;
bool jumpToImage(int imageNumber) override;
int nextImageDelay() const override;
int loopCount() const override;
private:
static QPointF CompatibleChromacity(qreal chrX, qreal chrY);
bool ensureParsed() const;
bool ensureDecoder();
bool decode_one_frame();
enum ParseAvifState
{
enum ParseAvifState {
ParseAvifError = -1,
ParseAvifNotParsed = 0,
ParseAvifSuccess = 1
ParseAvifSuccess = 1,
};
ParseAvifState m_parseState;
@ -72,11 +72,11 @@ private:
class QAVIFPlugin : public QImageIOPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA (IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "avif.json")
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

View File

@ -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 "
<< 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("-") << QStringLiteral("-c") << QStringLiteral("showpage quit");
qCDebug(EPSPLUGIN) << "Running gs with args" << gsArgs;
QProcess converter;
@ -264,7 +251,8 @@ bool EPSHandler::write(const QImage &image)
psOut.setOutputFileName(tmpFile.fileName());
psOut.setOutputFormat(QPrinter::PdfFormat);
psOut.setFullPage(true);
psOut.setPaperSize(image.size(), QPrinter::DevicePixel);
const double multiplier = psOut.resolution() <= 0 ? 1.0 : 72.0 / psOut.resolution();
psOut.setPageSize(QPageSize(image.size() * multiplier, QPageSize::Point));
// painting the pixmap to the "printer" which is a file
p.begin(&psOut);
@ -277,24 +265,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);

View File

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

View File

@ -9,35 +9,37 @@
#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 <ImfInt64.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)
{
}
@ -128,19 +130,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)),
@ -196,7 +198,7 @@ bool EXRHandler::read(QImage *outImage)
return true;
} catch (const std::exception &exc) {
// qDebug() << exc.what();
// qDebug() << exc.what();
return false;
}
}

View File

@ -41,10 +41,9 @@ const uchar OPAQUE_OPACITY = 255; //!< Opaque value for 8-bit alpha component.
typedef enum {
RGB,
GRAY,
INDEXED
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
/*!
@ -179,7 +177,7 @@ static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
if (saturation == 0) {
hue = value;
saturation = value;
//value = value;
// value = value;
} else {
double h = hue * 6. / 255.;
double s = saturation / 255.;

View File

@ -8,8 +8,8 @@
#include "hdr_p.h"
#include <QImage>
#include <QDataStream>
#include <QImage>
#include <QLoggingCategory>
#include <QRegularExpressionMatch>
@ -21,7 +21,6 @@ Q_LOGGING_CATEGORY(HDRPLUGIN, "kf.imageformats.plugins.hdr", QtWarningMsg)
namespace // Private.
{
#define MAXLINE 1024
#define MINELEN 8 // minimum scanline length for encoding
#define MAXELEN 0x7fff // maximum scanline length for encoding
@ -31,7 +30,7 @@ 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);
}
@ -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)) {
@ -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;
}

View File

@ -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.
{
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);
@ -136,13 +137,11 @@ bool HEIFHandler::write(const QImage &image)
heif::Image heifImage;
heifImage.create(tmpimage.width(), tmpimage.height(), heif_colorspace_RGB, chroma);
if (tmpimage.colorSpace().isValid()) {
QByteArray iccprofile = tmpimage.colorSpace().iccProfile();
if (iccprofile.size() > 0) {
std::vector<uint8_t> rawProfile(iccprofile.begin(), iccprofile.end());
heifImage.set_raw_color_profile(heif_color_profile_type_prof, rawProfile);
}
}
heifImage.add_plane(heif_channel_interleaved, image.width(), image.height(), save_depth);
int stride = 0;
@ -157,50 +156,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 +341,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 +374,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 +410,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 +447,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 +511,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 +582,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 +594,6 @@ bool HEIFHandler::ensureDecoder()
dest_pixel++;
}
}
}
break;
default:
@ -611,7 +606,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());
@ -620,7 +615,7 @@ bool HEIFHandler::ensureDecoder()
} else {
m_current_image.setColorSpace(QColorSpace::fromIccProfile(ba));
if (!m_current_image.colorSpace().isValid()) {
qWarning() << "icc profile is invalid";
qWarning() << "HEIC image has Qt-unsupported or invalid ICC profile!";
}
}
} else {
@ -659,12 +654,13 @@ bool HEIFHandler::ensureDecoder()
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:
@ -681,9 +677,8 @@ bool HEIFHandler::ensureDecoder()
heif_nclx_color_profile_free(nclx);
if (!m_current_image.colorSpace().isValid()) {
qWarning() << "invalid color profile created from NCLX";
qWarning() << "HEIC plugin created invalid QColorSpace from NCLX!";
}
}
} else {

View File

@ -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;
@ -36,7 +37,7 @@ private:
enum ParseHeicState {
ParseHeicError = -1,
ParseHeicNotParsed = 0,
ParseHeicSuccess = 1
ParseHeicSuccess = 1,
};
ParseHeicState m_parseState;

View File

@ -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");

View File

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

View File

@ -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");

View File

@ -21,7 +21,6 @@ public:
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

View File

@ -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
@ -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;

View File

@ -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),
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()
@ -394,10 +384,10 @@ void SoftimagePICHandler::setOption(ImageOption option, const QVariant &value)
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()) {
if (const_cast<SoftimagePICHandler *>(this)->readHeader()) {
return QSize(m_header.width, m_header.height);
} else {
return QVariant();
@ -405,17 +395,15 @@ QVariant SoftimagePICHandler::option(ImageOption option) const
case CompressionRatio:
return m_compression;
case Description:
if (const_cast<SoftimagePICHandler*>(this)->readHeader()) {
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(QStringLiteral("Description: ") + descStr + QStringLiteral("\n\n"));
}
}
return QString();
case ImageFormat:
if (const_cast<SoftimagePICHandler*>(this)->readChannels()) {
if (const_cast<SoftimagePICHandler *>(this)->readChannels()) {
for (const PicChannel &channel : qAsConst(m_channels)) {
if (channel.code & ALPHA) {
return QImage::Format_ARGB32;
@ -431,10 +419,7 @@ QVariant SoftimagePICHandler::option(ImageOption option) const
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

View File

@ -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.
@ -25,7 +25,7 @@ enum PicFields {
NoPicture = 0, /**< No picture */
OddScanlines = 1, /**< Odd scanlines */
EvenScanlines = 2, /**< Even scanlines */
BothScanlines = 3 /**< Every scanline */
BothScanlines = 3, /**< Every scanline */
};
/**
@ -33,7 +33,7 @@ enum PicFields {
*/
enum PicChannelEncoding {
Uncompressed = 0, /**< Image is uncompressed */
MixedRLE = 2 /**< Run length compression */
MixedRLE = 2, /**< Run length compression */
};
/**
@ -43,7 +43,7 @@ enum PicChannelCode {
RED = 0x80, /**< Red channel */
GREEN = 0x40, /**< Green channel */
BLUE = 0x20, /**< Blue channel */
ALPHA = 0x10 /**< Alpha channel */
ALPHA = 0x10, /**< Alpha channel */
};
/**
@ -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
@ -155,13 +160,14 @@ public:
Error,
Ready,
ReadHeader,
ReadChannels
ReadChannels,
};
SoftimagePICHandler()
: m_state(Ready)
, m_compression(true)
{}
{
}
bool readHeader();
bool readChannels();

View File

@ -31,7 +31,6 @@ typedef quint8 uchar;
namespace // Private.
{
enum ColorMode {
CM_BITMAP = 0,
CM_GRAYSCALE = 1,
@ -40,7 +39,7 @@ enum ColorMode {
CM_CMYK = 4,
CM_MULTICHANNEL = 7,
CM_DUOTONE = 8,
CM_LABCOLOR = 9
CM_LABCOLOR = 9,
};
struct PSDHeader {
@ -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;
@ -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;
}

View File

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

View File

@ -9,9 +9,9 @@
#include "ras_p.h"
#include <QImage>
#include <QDataStream>
#include <QDebug>
#include <QImage>
namespace // Private.
{
@ -28,13 +28,13 @@ enum RASType {
RAS_TYPE_RGB_FORMAT = 0x3,
RAS_TYPE_TIFF_FORMAT = 0x4,
RAS_TYPE_IFF_FORMAT = 0x5,
RAS_TYPE_EXPERIMENTAL = 0xFFFF
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_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);
}

View File

@ -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,40 +271,40 @@ 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
}
@ -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()) {

View File

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

View File

@ -8,8 +8,8 @@
#ifndef KIMAGEFORMATS_RLE_P_H
#define KIMAGEFORMATS_RLE_P_H
#include <QDebug>
#include <QDataStream>
#include <QDebug>
/**
* The RLEVariant to use.
@ -37,7 +37,7 @@ enum class RLEVariant {
* of size 128, 130 of size 127, down to 255 of
* size 2.
*/
PIC
PIC,
};
/**
@ -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;
}

View File

@ -20,9 +20,9 @@
#include <assert.h>
#include <QImage>
#include <QDataStream>
#include <QDebug>
#include <QImage>
typedef quint32 uint;
typedef quint16 ushort;
@ -30,9 +30,8 @@ typedef quint8 uchar;
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,
@ -40,7 +39,7 @@ enum TGAType {
TGA_TYPE_GREY = 3,
TGA_TYPE_RLE_INDEXED = 9,
TGA_TYPE_RLE_RGB = 10,
TGA_TYPE_RLE_GREY = 11
TGA_TYPE_RLE_GREY = 11,
};
#define TGA_INTERLEAVE_MASK 0xc0
@ -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,7 +131,11 @@ 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:
@ -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;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -27,21 +27,20 @@ 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"),
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"),
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);
QCommandLineOption listmimes(QStringList() << QStringLiteral("m") << QStringLiteral("listmime"), QStringLiteral("List supported image mime formats"));
parser.addOption(listmimes);
parser.process(app);
const QStringList files = parser.positionalArguments();
@ -61,6 +60,21 @@ int main(int argc, char **argv)
return 0;
}
if (parser.isSet(listmimes)) {
QTextStream out(stdout);
out << "Input mime formats:\n";
const auto lstReaderSupportedMimes = QImageReader::supportedMimeTypes();
for (const QByteArray &fmt : lstReaderSupportedMimes) {
out << " " << fmt << '\n';
}
out << "Output mime formats:\n";
const auto lstWriterSupportedMimes = QImageWriter::supportedMimeTypes();
for (const QByteArray &fmt : lstWriterSupportedMimes) {
out << " " << fmt << '\n';
}
return 0;
}
if (files.count() != 2) {
QTextStream(stdout) << "Must provide exactly two files\n";
parser.showHelp(1);

View File

@ -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,26 +31,21 @@ 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"),
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"),
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"),
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"),
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"),
QCommandLineOption listqformats(QStringList() << QStringLiteral("p") << QStringLiteral("list-qimage-formats"),
QStringLiteral("List supported QImage data formats"));
parser.addOption(listqformats);
@ -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;
}