Compare commits

..

1 Commits

Author SHA1 Message Date
0ee63388c8 Fix condition for installing desktop files
(cherry picked from commit 9ad82ed608)
2022-11-07 13:41:41 +00:00
17 changed files with 470 additions and 620 deletions

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
project(KImageFormats)
include(FeatureSummary)
find_package(ECM 5.103.0 NO_MODULE)
find_package(ECM 5.100.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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -93,6 +93,7 @@ endif()
if (LibHeif_FOUND)
kimageformats_add_plugin(kimg_heif SOURCES heif.cpp)
target_link_libraries(kimg_heif PkgConfig::LibHeif)
kde_target_enable_exceptions(kimg_heif PRIVATE)
if (QT_MAJOR_VERSION STREQUAL "5")
install(FILES heif.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)

View File

@ -63,7 +63,7 @@ bool QAVIFHandler::canRead(QIODevice *device)
}
avifROData input;
input.data = reinterpret_cast<const uint8_t *>(header.constData());
input.data = (const uint8_t *)header.constData();
input.size = header.size();
if (avifPeekCompatibleFileType(&input)) {
@ -116,7 +116,7 @@ bool QAVIFHandler::ensureDecoder()
m_rawData = device()->readAll();
m_rawAvifData.data = reinterpret_cast<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) {
@ -1057,26 +1057,12 @@ QPointF QAVIFHandler::CompatibleChromacity(qreal chrX, qreal chrY)
QImageIOPlugin::Capabilities QAVIFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
static const bool isAvifDecoderAvailable(avifCodecName(AVIF_CODEC_CHOICE_AUTO, AVIF_CODEC_FLAG_CAN_DECODE) != nullptr);
static const bool isAvifEncoderAvailable(avifCodecName(AVIF_CODEC_CHOICE_AUTO, AVIF_CODEC_FLAG_CAN_ENCODE) != nullptr);
if (format == "avif") {
Capabilities format_cap;
if (isAvifDecoderAvailable) {
format_cap |= CanRead;
}
if (isAvifEncoderAvailable) {
format_cap |= CanWrite;
}
return format_cap;
return Capabilities(CanRead | CanWrite);
}
if (format == "avifs") {
Capabilities format_cap;
if (isAvifDecoderAvailable) {
format_cap |= CanRead;
}
return format_cap;
return Capabilities(CanRead);
}
if (!format.isEmpty()) {
@ -1087,10 +1073,10 @@ QImageIOPlugin::Capabilities QAVIFPlugin::capabilities(QIODevice *device, const
}
Capabilities cap;
if (device->isReadable() && QAVIFHandler::canRead(device) && isAvifDecoderAvailable) {
if (device->isReadable() && QAVIFHandler::canRead(device)) {
cap |= CanRead;
}
if (device->isWritable() && isAvifEncoderAvailable) {
if (device->isWritable()) {
cap |= CanWrite;
}
return cap;

View File

@ -1,35 +0,0 @@
/*
Approximated math functions used into conversions.
SPDX-FileCopyrightText: Edward Kmett
SPDX-FileCopyrightText: 2023 Mirco Miranda <mircomir@outlook.com>
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FASTMATH_P_H
#define FASTMATH_P_H
#include <QtGlobal>
/*!
* \brief fastPow
* Based on Edward Kmett code released into the public domain.
* See also: https://github.com/ekmett/approximate
*/
inline double fastPow(double x, double y)
{
union {
double d;
qint32 i[2];
} u = {x};
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
u.i[1] = qint32(y * (u.i[1] - 1072632447) + 1072632447);
u.i[0] = 0;
#else // never tested
u.i[0] = qint32(y * (u.i[0] - 1072632447) + 1072632447);
u.i[1] = 0;
#endif
return u.d;
}
#endif // FASTMATH_P_H

View File

@ -8,49 +8,55 @@
*/
#include "heif_p.h"
#include "libheif/heif_cxx.h"
#include "util_p.h"
#include <libheif/heif.h>
#include <QColorSpace>
#include <QDebug>
#include <QPointF>
#include <QSysInfo>
#include <limits>
#include <string.h>
namespace // Private.
{
struct HeifQIODeviceWriter : public heif::Context::Writer {
HeifQIODeviceWriter(QIODevice *device)
: m_ioDevice(device)
{
}
heif_error write(const void *data, size_t size) override
{
heif_error error;
error.code = heif_error_Ok;
error.subcode = heif_suberror_Unspecified;
error.message = errorOkMessage;
qint64 bytesWritten = m_ioDevice->write(static_cast<const char *>(data), size);
if (bytesWritten < static_cast<qint64>(size)) {
error.code = heif_error_Encoding_error;
error.message = QIODeviceWriteErrorMessage;
error.subcode = heif_suberror_Cannot_write_output_data;
}
return error;
}
static constexpr const char *errorOkMessage = "Success";
static constexpr const char *QIODeviceWriteErrorMessage = "Bytes written to QIODevice are smaller than input data size";
private:
QIODevice *m_ioDevice;
};
} // namespace
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;
extern "C" {
static struct heif_error heifhandler_write_callback(struct heif_context * /* ctx */, const void *data, size_t size, void *userdata)
{
heif_error error;
error.code = heif_error_Ok;
error.subcode = heif_suberror_Unspecified;
error.message = "Success";
if (!userdata || !data || size == 0) {
error.code = heif_error_Usage_error;
error.subcode = heif_suberror_Null_pointer_argument;
error.message = "Wrong parameters!";
return error;
}
QIODevice *ioDevice = static_cast<QIODevice *>(userdata);
qint64 bytesWritten = ioDevice->write(static_cast<const char *>(data), size);
if (bytesWritten < static_cast<qint64>(size)) {
error.code = heif_error_Encoding_error;
error.message = "Bytes written to QIODevice are smaller than input data size";
error.subcode = heif_suberror_Cannot_write_output_data;
}
return error;
}
}
HEIFHandler::HEIFHandler()
: m_parseState(ParseHeicNotParsed)
, m_quality(100)
@ -147,25 +153,20 @@ bool HEIFHandler::write_helper(const QImage &image)
const QImage tmpimage = image.convertToFormat(tmpformat);
struct heif_context *context = heif_context_alloc();
struct heif_error err;
struct heif_image *h_image = nullptr;
err = heif_image_create(tmpimage.width(), tmpimage.height(), heif_colorspace_RGB, chroma, &h_image);
if (err.code) {
qWarning() << "heif_image_create error:" << err.message;
heif_context_free(context);
return false;
}
try {
heif::Context ctx;
heif::Image heifImage;
heifImage.create(tmpimage.width(), tmpimage.height(), heif_colorspace_RGB, chroma);
QByteArray iccprofile = tmpimage.colorSpace().iccProfile();
if (iccprofile.size() > 0) {
heif_image_set_raw_color_profile(h_image, "prof", iccprofile.constData(), iccprofile.size());
std::vector<uint8_t> rawProfile(iccprofile.begin(), iccprofile.end());
heifImage.set_raw_color_profile(heif_color_profile_type_prof, rawProfile);
}
heif_image_add_plane(h_image, heif_channel_interleaved, image.width(), image.height(), save_depth);
heifImage.add_plane(heif_channel_interleaved, image.width(), image.height(), save_depth);
int stride = 0;
uint8_t *const dst = heif_image_get_plane(h_image, heif_channel_interleaved, &stride);
uint8_t *const dst = heifImage.get_plane(heif_channel_interleaved, &stride);
size_t rowbytes;
switch (save_depth) {
@ -233,70 +234,42 @@ bool HEIFHandler::write_helper(const QImage &image)
break;
default:
qWarning() << "Unsupported depth:" << save_depth;
heif_image_release(h_image);
heif_context_free(context);
return false;
break;
}
struct heif_encoder *encoder = nullptr;
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);
heif_context_free(context);
return false;
}
heif::Encoder encoder(heif_compression_HEVC);
heif_encoder_set_lossy_quality(encoder, m_quality);
encoder.set_lossy_quality(m_quality);
if (m_quality > 90) {
if (m_quality == 100) {
heif_encoder_set_lossless(encoder, true);
encoder.set_lossless(true);
}
heif_encoder_set_parameter_string(encoder, "chroma", "444");
encoder.set_string_parameter("chroma", "444");
}
struct heif_encoding_options *encoder_options = heif_encoding_options_alloc();
encoder_options->save_alpha_channel = save_alpha;
heif::Context::EncodingOptions encodingOptions;
encodingOptions.save_alpha_channel = save_alpha;
if ((tmpimage.width() % 2 == 1) || (tmpimage.height() % 2 == 1)) {
qWarning() << "Image has odd dimension!\nUse even-numbered dimension(s) for better compatibility with other HEIF implementations.";
if (save_alpha) {
// This helps to save alpha channel when image has odd dimension
encoder_options->macOS_compatibility_workaround = 0;
encodingOptions.macOS_compatibility_workaround = 0;
}
}
err = heif_context_encode_image(context, h_image, encoder, encoder_options, nullptr);
ctx.encode_image(heifImage, encoder, encodingOptions);
if (encoder_options) {
heif_encoding_options_free(encoder_options);
}
HeifQIODeviceWriter writer(device());
if (err.code) {
qWarning() << "heif_context_encode_image failed:" << err.message;
heif_encoder_release(encoder);
heif_image_release(h_image);
heif_context_free(context);
ctx.write(writer);
} catch (const heif::Error &err) {
qWarning() << "libheif error:" << err.get_message().c_str();
return false;
}
struct heif_writer writer;
writer.writer_api_version = 1;
writer.write = heifhandler_write_callback;
err = heif_context_write(context, &writer, device());
heif_encoder_release(encoder);
heif_image_release(h_image);
if (err.code) {
qWarning() << "Writing HEIF image failed:" << err.message;
heif_context_free(context);
return false;
}
heif_context_free(context);
return true;
}
@ -430,35 +403,14 @@ bool HEIFHandler::ensureDecoder()
return false;
}
struct heif_context *ctx = heif_context_alloc();
struct heif_error err = heif_context_read_from_memory(ctx, static_cast<const void *>(buffer.constData()), buffer.size(), nullptr);
try {
heif::Context ctx;
ctx.read_from_memory_without_copy(static_cast<const void *>(buffer.constData()), buffer.size());
if (err.code) {
qWarning() << "heif_context_read_from_memory error:" << err.message;
heif_context_free(ctx);
m_parseState = ParseHeicError;
return false;
}
heif::ImageHandle handle = ctx.get_primary_image_handle();
struct heif_image_handle *handle = nullptr;
err = heif_context_get_primary_image_handle(ctx, &handle);
if (err.code) {
qWarning() << "heif_context_get_primary_image_handle error:" << err.message;
heif_context_free(ctx);
m_parseState = ParseHeicError;
return false;
}
if ((heif_image_handle_get_width(handle) == 0) || (heif_image_handle_get_height(handle) == 0)) {
m_parseState = ParseHeicError;
heif_image_handle_release(handle);
heif_context_free(ctx);
qWarning() << "HEIC image has zero dimension";
return false;
}
const bool hasAlphaChannel = heif_image_handle_has_alpha_channel(handle);
const int bit_depth = heif_image_handle_get_luma_bits_per_pixel(handle);
const bool hasAlphaChannel = handle.has_alpha_channel();
const int bit_depth = handle.get_luma_bits_per_pixel();
heif_chroma chroma;
QImage::Format target_image_format;
@ -481,8 +433,6 @@ bool HEIFHandler::ensureDecoder()
}
} else {
m_parseState = ParseHeicError;
heif_image_handle_release(handle);
heif_context_free(ctx);
if (bit_depth > 0) {
qWarning() << "Unsupported bit depth:" << bit_depth;
} else {
@ -491,48 +441,23 @@ bool HEIFHandler::ensureDecoder()
return false;
}
struct heif_decoding_options *decoder_option = heif_decoding_options_alloc();
heif::Image img = handle.decode_image(heif_colorspace_RGB, chroma);
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
decoder_option->strict_decoding = 1;
#endif
struct heif_image *img = nullptr;
err = heif_decode_image(handle, &img, heif_colorspace_RGB, chroma, decoder_option);
if (decoder_option) {
heif_decoding_options_free(decoder_option);
}
if (err.code) {
qWarning() << "heif_decode_image error:" << err.message;
heif_image_handle_release(handle);
heif_context_free(ctx);
m_parseState = ParseHeicError;
return false;
}
const int imageWidth = heif_image_get_width(img, heif_channel_interleaved);
const int imageHeight = heif_image_get_height(img, heif_channel_interleaved);
const int imageWidth = img.get_width(heif_channel_interleaved);
const int imageHeight = img.get_height(heif_channel_interleaved);
QSize imageSize(imageWidth, imageHeight);
if (!imageSize.isValid()) {
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
m_parseState = ParseHeicError;
qWarning() << "HEIC image size invalid:" << imageSize;
return false;
}
int stride = 0;
const uint8_t *const src = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
const uint8_t *const src = img.get_plane(heif_channel_interleaved, &stride);
if (!src || stride <= 0) {
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
m_parseState = ParseHeicError;
qWarning() << "HEIC data pixels information not valid!";
return false;
@ -540,9 +465,6 @@ bool HEIFHandler::ensureDecoder()
m_current_image = imageAlloc(imageSize, target_image_format);
if (m_current_image.isNull()) {
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
m_parseState = ParseHeicError;
qWarning() << "Unable to allocate memory!";
return false;
@ -706,21 +628,19 @@ bool HEIFHandler::ensureDecoder()
}
break;
default:
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
m_parseState = ParseHeicError;
qWarning() << "Unsupported bit depth:" << bit_depth;
return false;
break;
}
heif_color_profile_type profileType = heif_image_handle_get_color_profile_type(handle);
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) {
size_t rawProfileSize = heif_image_handle_get_raw_color_profile_size(handle);
if (rawProfileSize > 0 && rawProfileSize < std::numeric_limits<int>::max()) {
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, ba.data());
err = heif_image_handle_get_raw_color_profile(handle.get_raw_image_handle(), ba.data());
if (err.code) {
qWarning() << "icc profile loading failed";
} else {
@ -730,12 +650,12 @@ bool HEIFHandler::ensureDecoder()
}
}
} else {
qWarning() << "icc profile is empty or above limits";
qWarning() << "icc profile is empty";
}
} else if (profileType == heif_color_profile_type_nclx) {
struct heif_color_profile_nclx *nclx = nullptr;
err = heif_image_handle_get_nclx_color_profile(handle, &nclx);
err = heif_image_handle_get_nclx_color_profile(handle.get_raw_image_handle(), &nclx);
if (err.code || !nclx) {
qWarning() << "nclx profile loading failed";
} else {
@ -796,9 +716,12 @@ bool HEIFHandler::ensureDecoder()
m_current_image.setColorSpace(QColorSpace(QColorSpace::SRgb));
}
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
} catch (const heif::Error &err) {
m_parseState = ParseHeicError;
qWarning() << "libheif error:" << err.get_message().c_str();
return false;
}
m_parseState = ParseHeicSuccess;
return true;
}

View File

@ -3,7 +3,7 @@
SPDX-FileCopyrightText: 2003 Ignacio Castaño <castano@ludicon.com>
SPDX-FileCopyrightText: 2015 Alex Merry <alex.merry@kde.org>
SPDX-FileCopyrightText: 2022-2023 Mirco Miranda <mircomir@outlook.com>
SPDX-FileCopyrightText: 2022 Mirco Miranda <mircomir@outlook.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
@ -21,6 +21,7 @@
/*
* Limitations of the current code:
* - 32-bit float image are converted to 16-bit integer image.
* NOTE: Qt 6.2 allow 32-bit float images (RGB only)
* - Other color spaces cannot directly be read due to lack of QImage support for
* color spaces other than RGB (and Grayscale). Where possible, a conversion
* to RGB is done:
@ -32,7 +33,6 @@
* color management engine (e.g. LittleCMS).
*/
#include "fastmath_p.h"
#include "psd_p.h"
#include "util_p.h"
@ -51,7 +51,7 @@ typedef quint8 uchar;
* This should not be a problem because the Qt's QColorSpace supports the linear
* sRgb colorspace.
*
* Using linear conversion, the loading speed is slightly improved. Anyway, if you are using
* Using linear conversion, the loading speed is improved by 4x. Anyway, if you are using
* an software that discard color info, you should comment it.
*
* At the time I'm writing (07/2022), Gwenview and Krita supports linear sRgb but KDE
@ -646,9 +646,6 @@ static bool IsValid(const PSDHeader &header)
// Check that the header is supported by this plugin.
static bool IsSupported(const PSDHeader &header)
{
if (!IsValid(header)) {
return false;
}
if (header.version != 1 && header.version != 2) {
return false;
}
@ -663,15 +660,10 @@ static bool IsSupported(const PSDHeader &header)
header.color_mode != CM_INDEXED &&
header.color_mode != CM_DUOTONE &&
header.color_mode != CM_CMYK &&
header.color_mode != CM_MULTICHANNEL &&
header.color_mode != CM_LABCOLOR &&
header.color_mode != CM_BITMAP) {
return false;
}
if (header.color_mode == CM_MULTICHANNEL &&
header.channel_count < 4) {
return false;
}
return true;
}
@ -737,8 +729,7 @@ static QImage::Format imageFormat(const PSDHeader &header, bool alpha)
else
format = header.channel_count < 4 || !alpha ? QImage::Format_RGB888 : QImage::Format_RGBA8888;
break;
case CM_MULTICHANNEL: // Treat MCH as CMYK (number of channel check is done in IsSupported())
case CM_CMYK: // Photoshop supports CMYK/MCH 8-bits and 16-bits only
case CM_CMYK: // Photoshop supports CMYK 8-bits and 16-bits only
if (header.depth == 16)
format = header.channel_count < 5 || !alpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
else if (header.depth == 8)
@ -845,7 +836,6 @@ inline void cmykToRgb(uchar *target, qint32 targetChannels, const char *source,
auto s = reinterpret_cast<const T*>(source);
auto t = reinterpret_cast<T*>(target);
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!";
@ -854,10 +844,10 @@ inline void cmykToRgb(uchar *target, qint32 targetChannels, const char *source,
for (qint32 w = 0; w < width; ++w) {
auto ps = s + sourceChannels * w;
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 C = 1 - *(ps + 0) / max;
auto M = 1 - *(ps + 1) / max;
auto Y = 1 - *(ps + 2) / max;
auto K = 1 - *(ps + 3) / max;
auto pt = t + targetChannels * w;
*(pt + 0) = T(std::min(max - (C * (1 - K) + K) * max + 0.5, max));
@ -882,9 +872,8 @@ inline double gammaCorrection(double linear)
#ifdef PSD_FAST_LAB_CONVERSION
return linear;
#else
// Replacing fastPow with std::pow the conversion time is 2/3 times longer: using fastPow
// there are minimal differences in the conversion that are not visually noticeable.
return (linear > 0.0031308 ? 1.055 * fastPow(linear, 1.0 / 2.4) - 0.055 : 12.92 * linear);
// NOTE: pow() slow down the performance by a 4 factor :(
return (linear > 0.0031308 ? 1.055 * std::pow(linear, 1.0 / 2.4) - 0.055 : 12.92 * linear);
#endif
}
@ -894,7 +883,6 @@ inline void labToRgb(uchar *target, qint32 targetChannels, const char *source, q
auto s = reinterpret_cast<const T*>(source);
auto t = reinterpret_cast<T*>(target);
auto max = double(std::numeric_limits<T>::max());
auto invmax = 1.0 / max;
if (sourceChannels < 3) {
qDebug() << "labToRgb: image is not a valid LAB!";
@ -903,14 +891,14 @@ inline void labToRgb(uchar *target, qint32 targetChannels, const char *source, q
for (qint32 w = 0; w < width; ++w) {
auto ps = s + sourceChannels * w;
auto L = (*(ps + 0) * invmax) * 100.0;
auto A = (*(ps + 1) * invmax) * 255.0 - 128.0;
auto B = (*(ps + 2) * invmax) * 255.0 - 128.0;
auto L = (*(ps + 0) / max) * 100.0;
auto A = (*(ps + 1) / max) * 255.0 - 128.0;
auto B = (*(ps + 2) / max) * 255.0 - 128.0;
// converting LAB to XYZ (D65 illuminant)
auto Y = (L + 16.0) * (1.0 / 116.0);
auto X = A * (1.0 / 500.0) + Y;
auto Z = Y - B * (1.0 / 200.0);
auto Y = (L + 16.0) / 116.0;
auto X = A / 500.0 + Y;
auto Z = Y - B / 200.0;
// NOTE: use the constants of the illuminant of the target RGB color space
X = finv(X) * 0.9504; // D50: * 0.9642
@ -1090,7 +1078,7 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
}
// Conversion to RGB
if (header.color_mode == CM_CMYK || header.color_mode == CM_MULTICHANNEL) {
if (header.color_mode == CM_CMYK) {
if (header.depth == 8)
cmykToRgb<quint8>(img.scanLine(y), imgChannels, psdScanline.data(), header.channel_count, header.width, alpha);
else
@ -1269,7 +1257,7 @@ bool PSDHandler::canRead(QIODevice *device)
}
}
return IsSupported(header);
return IsValid(header);
}
QImageIOPlugin::Capabilities PSDPlugin::capabilities(QIODevice *device, const QByteArray &format) const

View File

@ -45,6 +45,7 @@ const auto supported_formats = QSet<QByteArray>{
"dcs", "dc2", "dcr", "dng", "drf", "dxo",
"eip", "erf",
"fff",
"hdr",
"iiq",
"k25", "kc2", "kdc",
"mdc", "mef", "mfw", "mos", "mrw",
@ -110,20 +111,10 @@ public:
}
virtual int read(void *ptr, size_t sz, size_t nmemb) override
{
qint64 read = 0;
if (sz == 0) {
auto read = m_device->read(reinterpret_cast<char *>(ptr), sz * nmemb);
if (read < 1) {
return 0;
}
auto data = reinterpret_cast<char*>(ptr);
for (qint64 r = 0, size = sz * nmemb; read < size; read += r) {
if (m_device->atEnd()) {
break;
}
r = m_device->read(data + read, size - read);
if (r < 1) {
break;
}
}
return read / sz;
}
virtual int eof() override
@ -140,7 +131,7 @@ public:
if (whence == SEEK_END) {
pos = size + o;
}
if (pos < 0 || m_device->isSequential()) {
if (pos < 0 || pos > size || m_device->isSequential()) {
return -1;
}
return m_device->seek(pos) ? 0 : -1;
@ -675,9 +666,6 @@ bool LoadRAW(QImageIOHandler *handler, QImage &img)
if (params.output_color == 4) {
img.setColorSpace(QColorSpace(QColorSpace::ProPhotoRgb));
}
if (params.output_color == 7) {
img.setColorSpace(QColorSpace(QColorSpace::DisplayP3));
}
}
// *** Set the metadata

View File

@ -7,6 +7,7 @@
"dcs", "dc2", "dcr", "dng", "drf", "dxo",
"eip", "erf",
"fff",
"hdr",
"iiq",
"k25", "kdc", "kc2",
"mdc", "mef", "mfw", "mos", "mrw",
@ -26,6 +27,7 @@
"image/x-kodak-dcs", "image/x-dc2", "image/x-kodak-dcr", "image/x-adobe-dng", "image/x-drf", "image/x-dxo",
"image/x-epson-eip", "image/x-epson-erf",
"image/x-fff",
"image/x-hdr",
"image/x-iiq",
"image/x-kodak-k25", "image/x-kodak-kdc", "image/x-kodak-kc2",
"image/x-minolta-mdc", "image/x-mamiya-mef", "image/x-mfw", "image/x-aptus-mos", "image/x-minolta-mrw",

View File

@ -430,9 +430,6 @@ bool TGAHandler::write(const QImage &image)
const QImage &img = image;
const bool hasAlpha = (img.format() == QImage::Format_ARGB32);
static constexpr quint8 originTopLeft = TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT; // 0x20
static constexpr quint8 alphaChannel8Bits = 0x08;
for (int i = 0; i < 12; i++) {
s << targaMagic[i];
}
@ -441,7 +438,7 @@ bool TGAHandler::write(const QImage &image)
s << quint16(img.width()); // width
s << quint16(img.height()); // height
s << quint8(hasAlpha ? 32 : 24); // depth (24 bit RGB + 8 bit alpha)
s << quint8(hasAlpha ? originTopLeft + alphaChannel8Bits : originTopLeft); // top left image (0x20) + 8 bit alpha (0x8)
s << quint8(hasAlpha ? 0x24 : 0x20); // top left image (0x20) + 8 bit alpha (0x4)
for (int y = 0; y < img.height(); y++) {
for (int x = 0; x < img.width(); x++) {