Compare commits

..

1 Commits

Author SHA1 Message Date
a33446f86a Use of heif_context_add_XMP_metadata instead
heif_context_add_XMP_metadata2

(cherry picked from commit 245c835d92)
2025-03-11 11:32:12 +01:00
46 changed files with 18 additions and 189 deletions

View File

@ -7,5 +7,5 @@ Dependencies:
Options:
test-before-installing: True
require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows']
cmake-options: "-DKIMAGEFORMATS_DDS=ON -DKIMAGEFORMATS_JXR=ON -DKIMAGEFORMATS_HEIF=ON"
cmake-options: "-DKIMAGEFORMATS_DDS=ON -DKIMAGEFORMATS_JXR=ON"
per-test-timeout: 90

View File

@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.16)
set(KF_VERSION "6.13.0") # handled by release scripts
set(KF_DEP_VERSION "6.13.0") # handled by release scripts
set(KF_VERSION "6.12.0") # handled by release scripts
set(KF_DEP_VERSION "6.12.0") # handled by release scripts
project(KImageFormats VERSION ${KF_VERSION})
include(FeatureSummary)
find_package(ECM 6.13.0 NO_MODULE)
find_package(ECM 6.12.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)
@ -99,8 +99,8 @@ endif()
add_feature_info(LibJXR LibJXR_FOUND "required for the QImage plugin for JPEG XR images")
ecm_set_disabled_deprecation_versions(
QT 6.9.0
KF 6.12.0
QT 6.8.0
KF 6.11.0
)
add_subdirectory(src)

View File

@ -122,12 +122,9 @@ if (LibHeif_FOUND)
kimageformats_read_tests(FUZZ 1
hej2
)
kimageformats_write_tests(FUZZ 1
hej2-nodatacheck-lossless
)
endif()
if (LibHeif_VERSION VERSION_GREATER_EQUAL "1.19.6")
if (LibHeif_VERSION VERSION_GREATER_EQUAL "1.19.0")
kimageformats_read_tests(FUZZ 4
avci
)

View File

@ -258,15 +258,6 @@ int main(int argc, char **argv)
});
QTextStream(stdout) << "QImageReader::supportedImageFormats: " << formatStrings.join(", ") << "\n";
if (!formats.contains(format)) {
if (format == "avci" || format == "heif" || format == "hej2") {
QTextStream(stdout) << "WARNING : " << suffix << " is not supported with current libheif configuration!\n"
<< "********* "
<< "Finished basic read tests for " << suffix << " images *********\n";
return 0;
}
}
const QFileInfoList lstImgDir = imgdir.entryInfoList();
// Launch 2 runs for each test: first run on a random access device, second run on a sequential access device
for (int seq = 0; seq < 2; ++seq) {
@ -332,12 +323,7 @@ int main(int argc, char **argv)
OptionTest optionTest;
if (!optionTest.store(&inputReader)) {
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while reading options\n";
if (format == "heif") {
// libheif + ffmpeg decoder is unable to load all HEIF files.
++skipped;
} else {
++failed;
}
++failed;
continue;
}

View File

@ -1,65 +0,0 @@
{
"format" : "hej2",
"metadata" : [
{
"key" : "CreationDate",
"value" : "2025-01-14T13:53:32+01:00"
},
{
"key" : "Direction",
"value" : "123.7"
},
{
"key" : "ModificationDate",
"value" : "2025-02-14T15:58:44+01:00"
},
{
"key" : "Software" ,
"value" : "Adobe Photoshop 26.2 (Windows)"
},
{
"key" : "Altitude",
"value" : "34"
},
{
"key" : "Author",
"value" : "KDE Project"
},
{
"key" : "Copyright",
"value" : "@2025 KDE Project"
},
{
"key" : "Description",
"value" : "TV broadcast test image."
},
{
"key" : "Latitude",
"value" : "44.6478"
},
{
"key" : "LensManufacturer",
"value" : "KDE Glasses"
},
{
"key" : "LensModel",
"value" : "A1234"
},
{
"key" : "Longitude",
"value" : "10.9254"
},
{
"key" : "Manufacturer",
"value" : "KFramework"
},
{
"key" : "Model",
"value" : "KImageFormats"
}
],
"resolution" : {
"dotsPerMeterX" : 11811,
"dotsPerMeterY" : 11812
}
}

View File

@ -370,12 +370,7 @@ int formatTest(const QString &suffix, bool createTemplates)
QBuffer buffer(&ba);
auto writtenImage = QImageReader(&buffer, suffix.toLatin1()).read();
if (writtenImage.isNull()) {
if (suffix.toLatin1() == "heif") {
// libheif + ffmpeg decoder is unable to load all HEIF files.
++skipped;
} else {
++failed;
}
++failed;
QTextStream(stdout) << "FAIL : error while reading the image " << formatName << "\n";
continue;
}
@ -627,28 +622,8 @@ int main(int argc, char **argv)
}
}
auto suffix = args.at(0);
// skip test if libheif configuration is obviously incomplete
QByteArray format = suffix.toLatin1();
const QList<QByteArray> read_formats = QImageReader::supportedImageFormats();
const QList<QByteArray> write_formats = QImageWriter::supportedImageFormats();
if (!read_formats.contains(format)) {
if (format == "heif" || format == "hej2") {
QTextStream(stdout) << "WARNING : libheif configuration is missing necessary decoder(s)!\n";
return 0;
}
}
if (!write_formats.contains(format)) {
if (format == "heif" || format == "hej2") {
QTextStream(stdout) << "WARNING : libheif configuration is missing necessary encoder(s)!\n";
return 0;
}
}
// run test
auto suffix = args.at(0);
auto ret = basicTest(suffix, parser.isSet(lossless), parser.isSet(ignoreDataCheck), parser.isSet(skipOptTest), fuzzarg);
if (ret == 0) {
ret = formatTest(suffix, parser.isSet(createFormatTempates));

View File

@ -2557,5 +2557,3 @@ QImageIOHandler *QDDSPlugin::create(QIODevice *device, const QByteArray &format)
handler->setFormat(format);
return handler;
}
#include "moc_dds_p.cpp"

View File

@ -16,8 +16,8 @@
#include <QDebug>
#include <QPointF>
#include <QSysInfo>
#include <cstring>
#include <limits>
#include <string.h>
#ifndef HEIF_MAX_METADATA_SIZE
/*!
@ -26,12 +26,12 @@
#define HEIF_MAX_METADATA_SIZE (4 * 1024 * 1024)
#endif
size_t HEIFHandler::m_initialized_count = 0;
bool HEIFHandler::m_plugins_queried = false;
bool HEIFHandler::m_heif_decoder_available = false;
bool HEIFHandler::m_heif_encoder_available = false;
bool HEIFHandler::m_hej2_decoder_available = false;
bool HEIFHandler::m_hej2_encoder_available = false;
bool HEIFHandler::m_avci_decoder_available = false;
extern "C" {
@ -155,14 +155,6 @@ bool HEIFHandler::write_helper(const QImage &image)
break;
}
heif_compression_format encoder_codec = heif_compression_HEVC;
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
if (format() == "hej2") {
encoder_codec = heif_compression_JPEG2000;
save_depth = 8; // for compatibility reasons
}
#endif
heif_chroma chroma;
if (save_depth > 8) {
if (save_alpha) {
@ -295,7 +287,7 @@ bool HEIFHandler::write_helper(const QImage &image)
}
struct heif_encoder *encoder = nullptr;
err = heif_context_get_encoder_for_format(context, encoder_codec, &encoder);
err = heif_context_get_encoder_for_format(context, heif_compression_HEVC, &encoder);
if (err.code) {
qWarning() << "Unable to get an encoder instance:" << err.message;
heif_image_release(h_image);
@ -322,7 +314,7 @@ bool HEIFHandler::write_helper(const QImage &image)
}
}
struct heif_image_handle *handle;
struct heif_image_handle* handle;
err = heif_context_encode_image(context, h_image, encoder, encoder_options, &handle);
// exif metadata
@ -562,7 +554,7 @@ bool HEIFHandler::ensureDecoder()
QImage::Format target_image_format;
if (bit_depth == 10 || bit_depth == 12 || bit_depth == 16) {
if (bit_depth == 10 || bit_depth == 12) {
if (hasAlphaChannel) {
chroma = (QSysInfo::ByteOrder == QSysInfo::LittleEndian) ? heif_chroma_interleaved_RRGGBBAA_LE : heif_chroma_interleaved_RRGGBBAA_BE;
target_image_format = QImage::Format_RGBA64;
@ -654,35 +646,6 @@ bool HEIFHandler::ensureDecoder()
}
switch (bit_depth) {
case 16:
if (hasAlphaChannel) {
for (int y = 0; y < imageHeight; y++) {
memcpy(m_current_image.scanLine(y), src + (y * stride), 8 * size_t(imageWidth));
}
} 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++) {
// R
*dest_data = *src_word;
src_word++;
dest_data++;
// G
*dest_data = *src_word;
src_word++;
dest_data++;
// B
*dest_data = *src_word;
src_word++;
dest_data++;
// X = 0xffff
*dest_data = 0xffff;
dest_data++;
}
}
}
break;
case 12:
if (hasAlphaChannel) {
for (int y = 0; y < imageHeight; y++) {
@ -1028,13 +991,6 @@ bool HEIFHandler::isHej2DecoderAvailable()
return m_hej2_decoder_available;
}
bool HEIFHandler::isHej2EncoderAvailable()
{
HEIFHandler::queryHeifLib();
return m_hej2_encoder_available;
}
bool HEIFHandler::isAVCIDecoderAvailable()
{
HEIFHandler::queryHeifLib();
@ -1057,9 +1013,8 @@ void HEIFHandler::queryHeifLib()
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
m_hej2_encoder_available = heif_have_encoder_for_format(heif_compression_JPEG2000);
#endif
#if LIBHEIF_HAVE_VERSION(1, 19, 6)
#if LIBHEIF_HAVE_VERSION(1, 19, 0)
m_avci_decoder_available = heif_have_decoder_for_format(heif_compression_AVC);
#endif
m_plugins_queried = true;
@ -1126,9 +1081,6 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
if (HEIFHandler::isHej2DecoderAvailable()) {
format_cap |= CanRead;
}
if (HEIFHandler::isHej2EncoderAvailable()) {
format_cap |= CanWrite;
}
return format_cap;
}
@ -1158,7 +1110,7 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
}
}
if (device->isWritable() && (HEIFHandler::isHeifEncoderAvailable() || HEIFHandler::isHej2EncoderAvailable())) {
if (device->isWritable() && HEIFHandler::isHeifEncoderAvailable()) {
cap |= CanWrite;
}
return cap;

View File

@ -31,7 +31,6 @@ public:
static bool isHeifDecoderAvailable();
static bool isHeifEncoderAvailable();
static bool isHej2DecoderAvailable();
static bool isHej2EncoderAvailable();
static bool isAVCIDecoderAvailable();
static bool isSupportedBMFFType(const QByteArray &header);
@ -63,7 +62,6 @@ private:
static bool m_heif_decoder_available;
static bool m_heif_encoder_available;
static bool m_hej2_decoder_available;
static bool m_hej2_encoder_available;
static bool m_avci_decoder_available;
static QMutex &getHEIFHandlerMutex();

View File

@ -1504,18 +1504,7 @@ bool PSDHandler::read(QImage *image)
img.setColorSpace(QColorSpace(QColorSpace::SRgb));
#endif
} else if (!setColorSpace(img, irs)) {
// Float images are used by Photoshop as linear: if no color space
// is present, a linear one should be chosen.
if (header.color_mode == CM_RGB && header.depth == 32) {
img.setColorSpace(QColorSpace(QColorSpace::SRgbLinear));
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
if (header.color_mode == CM_GRAYSCALE && header.depth == 32) {
auto qs = QColorSpace(QPointF(0.3127, 0.3291), QColorSpace::TransferFunction::Linear);
qs.setDescription(QStringLiteral("Linear grayscale"));
img.setColorSpace(qs);
}
#endif
// qDebug() << "No colorspace info set!";
}
// XMP data

View File

@ -457,4 +457,3 @@ QImageIOHandler *ScitexPlugin::create(QIODevice *device, const QByteArray &forma
return handler;
}
#include "moc_sct_p.cpp"