Compare commits

..

7 Commits

Author SHA1 Message Date
bcb5308545 GIT_SILENT Upgrade ECM and KF version requirements for 5.109.0 release. 2023-08-05 12:37:26 +00:00
c3a91c3bc6 psd: Fix UB type punning
BUGS: 471829
2023-07-16 08:03:58 +00:00
034b8f331b Treat 3-channel MCH images as CMY images
(cherry picked from commit 6559bf8994)
2023-07-03 23:26:50 +02:00
ed6a3c520d Add explicit moc includes to sources for moc-covered headers
* speeds up incremental builds as changes to a header will not always
  need the full mocs_compilation.cpp for all the target's headers rebuild,
  while having a moc file sourced into a source file only adds minor
  extra costs, due to small own code and the used headers usually
  already covered by the source file, being for the same class/struct
* seems to not slow down clean builds, due to empty mocs_compilation.cpp
  resulting in those quickly processed, while the minor extra cost of the
  sourced moc files does not outweigh that in summary.
  Measured times actually improved by some percent points.
  (ideally CMake would just skip empty mocs_compilation.cpp & its object
  file one day)
* enables compiler to see all methods of a class in same compilation unit
  to do some sanity checks
* potentially more inlining in general, due to more in the compilation unit
* allows to keep using more forward declarations in the header, as with the
  moc code being sourced into the cpp file there definitions can be ensured
  and often are already for the needs of the normal class methods

(cherry picked from commit 34ed3bad27)
2023-07-02 11:55:33 +02:00
bf1c7e8508 GIT_SILENT Upgrade ECM and KF version requirements for 5.108.0 release. 2023-07-01 09:58:24 +00:00
3cb6519dcc jxl: add support for libjxl v0.9, drop support for old 0.6.1 2023-06-27 23:05:15 +00:00
6cbf7529ee Remove qt6 CI builds
The Qt6 builds for kf5 are no longer needed
2023-06-27 18:33:03 +02:00
24 changed files with 82 additions and 37 deletions

View File

@ -6,9 +6,5 @@ include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-static.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-static.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-qt6.yml

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
project(KImageFormats)
include(FeatureSummary)
find_package(ECM 5.107.0 NO_MODULE)
find_package(ECM 5.109.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)
@ -65,8 +65,8 @@ add_feature_info(LibHeif LibHeif_FOUND "required for the QImage plugin for HEIF/
option(KIMAGEFORMATS_JXL "Enable plugin for JPEG XL format" ON)
if(KIMAGEFORMATS_JXL)
pkg_check_modules(LibJXL IMPORTED_TARGET libjxl>=0.6.1)
pkg_check_modules(LibJXLThreads IMPORTED_TARGET libjxl_threads>=0.6.1)
pkg_check_modules(LibJXL IMPORTED_TARGET libjxl>=0.7.0)
pkg_check_modules(LibJXLThreads IMPORTED_TARGET libjxl_threads>=0.7.0)
endif()
add_feature_info(LibJXL LibJXL_FOUND "required for the QImage plugin for JPEG XL images")

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

View File

@ -104,9 +104,6 @@ endif()
if (LibJXL_FOUND AND LibJXLThreads_FOUND)
kimageformats_add_plugin(kimg_jxl SOURCES jxl.cpp)
target_link_libraries(kimg_jxl PkgConfig::LibJXL PkgConfig::LibJXLThreads)
if (LibJXL_VERSION VERSION_GREATER_EQUAL "0.7.0")
target_compile_definitions(kimg_jxl PRIVATE KIMG_JXL_API_VERSION=70)
endif()
if (QT_MAJOR_VERSION STREQUAL "5")
install(FILES jxl.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -150,9 +150,7 @@ bool QJpegXLHandler::ensureDecoder()
return false;
}
#ifdef KIMG_JXL_API_VERSION
JxlDecoderCloseInput(m_decoder);
#endif
JxlDecoderStatus status = JxlDecoderSubscribeEvents(m_decoder, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FRAME);
if (status == JXL_DEC_ERROR) {
@ -269,18 +267,31 @@ bool QJpegXLHandler::countALLFrames()
}
}
status = JxlDecoderGetColorAsEncodedProfile(m_decoder, &m_input_pixel_format, JXL_COLOR_PROFILE_TARGET_DATA, &color_encoding);
status = JxlDecoderGetColorAsEncodedProfile(m_decoder,
#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
&m_input_pixel_format,
#endif
JXL_COLOR_PROFILE_TARGET_DATA,
&color_encoding);
if (status == JXL_DEC_SUCCESS && color_encoding.color_space == JXL_COLOR_SPACE_RGB && color_encoding.white_point == JXL_WHITE_POINT_D65
&& color_encoding.primaries == JXL_PRIMARIES_SRGB && color_encoding.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) {
m_colorspace = QColorSpace(QColorSpace::SRgb);
} else {
size_t icc_size = 0;
if (JxlDecoderGetICCProfileSize(m_decoder, &m_input_pixel_format, JXL_COLOR_PROFILE_TARGET_DATA, &icc_size) == JXL_DEC_SUCCESS) {
if (JxlDecoderGetICCProfileSize(m_decoder,
#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
&m_input_pixel_format,
#endif
JXL_COLOR_PROFILE_TARGET_DATA,
&icc_size)
== JXL_DEC_SUCCESS) {
if (icc_size > 0) {
QByteArray icc_data(icc_size, 0);
if (JxlDecoderGetColorAsICCProfile(m_decoder,
#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
&m_input_pixel_format,
#endif
JXL_COLOR_PROFILE_TARGET_DATA,
reinterpret_cast<uint8_t *>(icc_data.data()),
icc_data.size())
@ -534,9 +545,7 @@ bool QJpegXLHandler::write(const QImage &image)
if (save_depth == 16 && (image.hasAlphaChannel() || output_info.uses_original_profile)) {
output_info.have_container = JXL_TRUE;
JxlEncoderUseContainer(encoder, JXL_TRUE);
#ifdef KIMG_JXL_API_VERSION
JxlEncoderSetCodestreamLevel(encoder, 10);
#endif
}
void *runner = nullptr;
@ -650,19 +659,11 @@ bool QJpegXLHandler::write(const QImage &image)
}
}
#ifdef KIMG_JXL_API_VERSION
JxlEncoderFrameSettings *encoder_options = JxlEncoderFrameSettingsCreate(encoder, nullptr);
JxlEncoderSetFrameDistance(encoder_options, (100.0f - m_quality) / 10.0f);
JxlEncoderSetFrameLossless(encoder_options, (m_quality == 100) ? JXL_TRUE : JXL_FALSE);
#else
JxlEncoderOptions *encoder_options = JxlEncoderOptionsCreate(encoder, nullptr);
JxlEncoderOptionsSetDistance(encoder_options, (100.0f - m_quality) / 10.0f);
JxlEncoderOptionsSetLossless(encoder_options, (m_quality == 100) ? JXL_TRUE : JXL_FALSE);
#endif
if (image.hasAlphaChannel() || ((save_depth == 8) && (xsize % 4 == 0))) {
status = JxlEncoderAddImageFrame(encoder_options, &pixel_format, static_cast<const void *>(tmpimage.constBits()), buffer_size);
@ -957,9 +958,7 @@ bool QJpegXLHandler::rewind()
return false;
}
#ifdef KIMG_JXL_API_VERSION
JxlDecoderCloseInput(m_decoder);
#endif
if (m_basicinfo.uses_original_profile) {
if (JxlDecoderSubscribeEvents(m_decoder, JXL_DEC_FULL_IMAGE) != JXL_DEC_SUCCESS) {
@ -1021,3 +1020,5 @@ QImageIOHandler *QJpegXLPlugin::create(QIODevice *device, const QByteArray &form
handler->setFormat(format);
return handler;
}
#include "moc_jxl_p.cpp"

View File

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

View File

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

View File

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

View File

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

View File

@ -42,6 +42,7 @@
#include <QColorSpace>
#include <cmath>
#include <cstring>
typedef quint32 uint;
typedef quint16 ushort;
@ -669,7 +670,7 @@ static bool IsSupported(const PSDHeader &header)
return false;
}
if (header.color_mode == CM_MULTICHANNEL &&
header.channel_count < 4) {
header.channel_count < 3) {
return false;
}
return true;
@ -808,6 +809,26 @@ inline quint32 xchg(quint32 v) {
#endif
}
inline float xchg(float v)
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
# ifdef Q_CC_MSVC
float *pf = &v;
quint32 f = xchg(*reinterpret_cast<quint32*>(pf));
quint32 *pi = &f;
return *reinterpret_cast<float*>(pi);
# else
quint32 t;
std::memcpy(&t, &v, sizeof(quint32));
t = xchg(t);
std::memcpy(&v, &t, sizeof(quint32));
return v;
# endif
#else
return v; // never tested
#endif
}
template<class T>
inline void planarToChunchy(uchar *target, const char *source, qint32 width, qint32 c, qint32 cn)
{
@ -818,15 +839,13 @@ inline void planarToChunchy(uchar *target, const char *source, qint32 width, qin
}
}
template<class T, T min = 0, T max = 1>
inline void planarToChunchyFloat(uchar *target, const char *source, qint32 width, qint32 c, qint32 cn)
template<class T>
inline void planarToChunchyFloatToUInt16(uchar *target, const char *source, qint32 width, qint32 c, qint32 cn)
{
auto s = reinterpret_cast<const T*>(source);
auto t = reinterpret_cast<quint16*>(target);
for (qint32 x = 0; x < width; ++x) {
auto tmp = xchg(s[x]);
auto ftmp = (*reinterpret_cast<float*>(&tmp) - double(min)) / (double(max) - double(min));
t[x * cn + c] = quint16(std::min(ftmp * std::numeric_limits<quint16>::max() + 0.5, double(std::numeric_limits<quint16>::max())));
t[x * cn + c] = quint16(std::min(xchg(s[x]) * std::numeric_limits<quint16>::max() + 0.5, double(std::numeric_limits<quint16>::max())));
}
}
@ -896,8 +915,8 @@ inline void cmykToRgb(uchar *target, qint32 targetChannels, const char *source,
auto max = double(std::numeric_limits<T>::max());
auto invmax = 1.0 / max; // speed improvements by ~10%
if (sourceChannels < 4) {
qDebug() << "cmykToRgb: image is not a valid CMYK!";
if (sourceChannels < 3) {
qDebug() << "cmykToRgb: image is not a valid CMY/CMYK!";
return;
}
@ -906,7 +925,7 @@ inline void cmykToRgb(uchar *target, qint32 targetChannels, const char *source,
auto C = 1 - *(ps + 0) * invmax;
auto M = 1 - *(ps + 1) * invmax;
auto Y = 1 - *(ps + 2) * invmax;
auto K = 1 - *(ps + 3) * invmax;
auto K = sourceChannels > 3 ? 1 - *(ps + 3) * invmax : 0.0;
auto pt = t + targetChannels * w;
*(pt + 0) = T(std::min(max - (C * (1 - K) + K) * max + 0.5, max));
@ -1140,7 +1159,7 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
} else if (header.depth == 16) {
planarToChunchy<quint16>(scanLine, rawStride.data(), header.width, c, header.channel_count);
} else if (header.depth == 32) {
planarToChunchyFloat<quint32>(scanLine, rawStride.data(), header.width, c, header.channel_count);
planarToChunchyFloatToUInt16<float>(scanLine, rawStride.data(), header.width, c, header.channel_count);
}
}
@ -1204,7 +1223,7 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
} else if (header.depth == 16) { // 16-bits integer images: Grayscale, RGB/RGBA
planarToChunchy<quint16>(scanLine, rawStride.data(), header.width, c, imgChannels);
} else if (header.depth == 32) { // 32-bits float images: Grayscale, RGB/RGBA (coverted to equivalent integer 16-bits)
planarToChunchyFloat<quint32>(scanLine, rawStride.data(), header.width, c, imgChannels);
planarToChunchyFloatToUInt16<float>(scanLine, rawStride.data(), header.width, c, imgChannels);
}
}
}
@ -1380,3 +1399,5 @@ QImageIOHandler *PSDPlugin::create(QIODevice *device, const QByteArray &format)
handler->setFormat(format);
return handler;
}
#include "moc_psd_p.cpp"

View File

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

View File

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

View File

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

View File

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

View File

@ -3400,3 +3400,5 @@ QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format)
// Just so I can get enum values printed
#include "xcf.moc"
#include "moc_xcf_p.cpp"