Unified maximum pixel value for large image plugins

This commit is contained in:
Mirco Miranda
2025-08-23 14:17:04 +02:00
parent 5a067130af
commit 59089855fa
12 changed files with 129 additions and 35 deletions

View File

@ -7,6 +7,10 @@
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "exr_p.h"
#include "scanlineconverter_p.h"
#include "util_p.h"
/* *** EXR_CONVERT_TO_SRGB ***
* If defined, the linear data is converted to sRGB on read to accommodate
* programs that do not support color profiles.
@ -28,7 +32,7 @@
* The maximum size in pixel allowed by the plugin.
*/
#ifndef EXR_MAX_IMAGE_WIDTH
#define EXR_MAX_IMAGE_WIDTH 300000
#define EXR_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef EXR_MAX_IMAGE_HEIGHT
#define EXR_MAX_IMAGE_HEIGHT EXR_MAX_IMAGE_WIDTH
@ -50,10 +54,6 @@
#define EXR_LINES_PER_BLOCK 128
#endif
#include "exr_p.h"
#include "scanlineconverter_p.h"
#include "util_p.h"
#include <IexThrowErrnoExc.h>
#include <ImathBox.h>
#include <ImfArray.h>

View File

@ -23,6 +23,16 @@
*/
//#define HDR_HALF_QUALITY // default commented -> you should define it in your cmake file
/* *** HDR_MAX_IMAGE_WIDTH and HDR_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef HDR_MAX_IMAGE_WIDTH
#define HDR_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef HDR_MAX_IMAGE_HEIGHT
#define HDR_MAX_IMAGE_HEIGHT HDR_MAX_IMAGE_WIDTH
#endif
typedef unsigned char uchar;
Q_LOGGING_CATEGORY(HDRPLUGIN, "kf.imageformats.plugins.hdr", QtWarningMsg)
@ -42,7 +52,10 @@ public:
Header(const Header&) = default;
Header& operator=(const Header&) = default;
bool isValid() const { return width() > 0 && height() > 0; }
bool isValid() const
{
return width() > 0 && height() > 0 && width() <= HDR_MAX_IMAGE_WIDTH && height() <= HDR_MAX_IMAGE_HEIGHT;
}
qint32 width() const { return(m_size.width()); }
qint32 height() const { return(m_size.height()); }
QString software() const { return(m_software); }

View File

@ -21,7 +21,7 @@
* The maximum size in pixel allowed by the plugin.
*/
#ifndef JP2_MAX_IMAGE_WIDTH
#define JP2_MAX_IMAGE_WIDTH 300000
#define JP2_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef JP2_MAX_IMAGE_HEIGHT
#define JP2_MAX_IMAGE_HEIGHT JP2_MAX_IMAGE_WIDTH

View File

@ -74,6 +74,16 @@ Q_LOGGING_CATEGORY(LOG_JXRPLUGIN, "kf.imageformats.plugins.jxr", QtWarningMsg)
// #define JXR_ENABLE_ADVANCED_METADATA
/* *** JXR_MAX_IMAGE_WIDTH and JXR_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef JXR_MAX_IMAGE_WIDTH
#define JXR_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef JXR_MAX_IMAGE_HEIGHT
#define JXR_MAX_IMAGE_HEIGHT JXR_MAX_IMAGE_WIDTH
#endif
#ifndef JXR_MAX_METADATA_SIZE
/*!
* XMP and EXIF maximum size.
@ -386,6 +396,11 @@ public:
if (pDecoder) {
qint32 w, h;
pDecoder->GetSize(pDecoder, &w, &h);
if (w > JXR_MAX_IMAGE_WIDTH || h > JXR_MAX_IMAGE_HEIGHT || w < 1 || h < 1) {
qCCritical(LOG_JXRPLUGIN) << "JXRHandlerPrivate::imageSize() Maximum image size is limited to" << JXR_MAX_IMAGE_WIDTH << "x"
<< JXR_MAX_IMAGE_HEIGHT << "pixels";
return {};
}
return QSize(w, h);
}
return {};
@ -1053,6 +1068,10 @@ bool JXRHandler::write(const QImage &image)
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() image too large: the image cannot exceed 4GB.";
return false;
}
if (image.width() > JXR_MAX_IMAGE_WIDTH || image.height() > JXR_MAX_IMAGE_HEIGHT) {
qCCritical(LOG_JXRPLUGIN) << "JXRHandler::write() Maximum image size is limited to" << JXR_MAX_IMAGE_WIDTH << "x" << JXR_MAX_IMAGE_HEIGHT << "pixels";
return {};
}
if (!d->initForWriting()) {
return false;

View File

@ -22,6 +22,16 @@
Q_DECLARE_LOGGING_CATEGORY(LOG_PFMPLUGIN)
Q_LOGGING_CATEGORY(LOG_PFMPLUGIN, "kf.imageformats.plugins.pfm", QtWarningMsg)
/* *** PFM_MAX_IMAGE_WIDTH and PFM_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef PFM_MAX_IMAGE_WIDTH
#define PFM_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef PFM_MAX_IMAGE_HEIGHT
#define PFM_MAX_IMAGE_HEIGHT PFM_MAX_IMAGE_WIDTH
#endif
class PFMHeader
{
private:
@ -80,7 +90,7 @@ public:
bool isValid() const
{
return (m_width > 0 && m_height > 0);
return (m_width > 0 && m_height > 0 && m_width <= PFM_MAX_IMAGE_WIDTH && m_height <= PFM_MAX_IMAGE_HEIGHT);
}
bool isBlackAndWhite() const

View File

@ -72,6 +72,16 @@ typedef quint8 uchar;
*/
// #define PSD_FORCE_RGBA
/* *** PSD_MAX_IMAGE_WIDTH and PSD_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef PSD_MAX_IMAGE_WIDTH
#define PSD_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef PSD_MAX_IMAGE_HEIGHT
#define PSD_MAX_IMAGE_HEIGHT PSD_MAX_IMAGE_WIDTH
#endif
namespace // Private.
{
@ -678,7 +688,7 @@ static bool IsValid(const PSDHeader &header)
qDebug() << "PSD header: invalid number of channels" << header.channel_count;
return false;
}
if (header.width > 300000 || header.height > 300000) {
if (header.width > std::min(300000, PSD_MAX_IMAGE_WIDTH) || header.height > std::min(300000, PSD_MAX_IMAGE_HEIGHT)) {
qDebug() << "PSD header: invalid image size" << header.width << "x" << header.height;
return false;
}

View File

@ -15,6 +15,16 @@
#include <QIODevice>
#include <QImage>
/* *** QOI_MAX_IMAGE_WIDTH and QOI_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef QOI_MAX_IMAGE_WIDTH
#define QOI_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef QOI_MAX_IMAGE_HEIGHT
#define QOI_MAX_IMAGE_HEIGHT QOI_MAX_IMAGE_WIDTH
#endif
namespace // Private
{
@ -92,7 +102,7 @@ static bool IsSupported(const QoiHeader &head)
return false;
}
// Set a reasonable upper limit
if (head.Width > 300000 || head.Height > 300000) {
if (head.Width > QOI_MAX_IMAGE_WIDTH || head.Height > QOI_MAX_IMAGE_HEIGHT) {
return false;
}
return true;

View File

@ -15,6 +15,16 @@
#include <QDebug>
#include <QImage>
/* *** RAS_MAX_IMAGE_WIDTH and RAS_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef RAS_MAX_IMAGE_WIDTH
#define RAS_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef RAS_MAX_IMAGE_HEIGHT
#define RAS_MAX_IMAGE_HEIGHT RAS_MAX_IMAGE_WIDTH
#endif
namespace // Private.
{
// format info from http://www.fileformat.info/format/sunraster/egff.htm
@ -84,9 +94,10 @@ static bool IsSupported(const RasHeader &head)
if (head.Depth != 1 && head.Depth != 8 && head.Depth != 24 && head.Depth != 32) {
return false;
}
if (head.Width == 0 || head.Height == 0) {
if (head.Width == 0 || head.Height == 0 || head.Width > RAS_MAX_IMAGE_WIDTH || head.Height > RAS_MAX_IMAGE_HEIGHT) {
return false;
}
// the Type field adds support for RLE(BGR), RGB and other encodings
// we support Type 1: Normal(BGR), Type 2: RLE(BGR) and Type 3: Normal(RGB) ONLY!
// TODO: add support for Type 4,5: TIFF/IFF
@ -388,7 +399,7 @@ bool RASHandler::read(QImage *outImage)
s >> ras;
if (ras.ColorMapLength > kMaxQVectorSize) {
qWarning() << "LoadRAS() unsupported image color map length in file header" << ras.ColorMapLength;
qWarning() << "read() unsupported image color map length in file header" << ras.ColorMapLength;
return false;
}

View File

@ -19,6 +19,16 @@
Q_LOGGING_CATEGORY(LOG_SCTPLUGIN, "kf.imageformats.plugins.scitex", QtWarningMsg)
/* *** SCT_MAX_IMAGE_WIDTH and SCT_MAX_IMAGE_HEIGHT ***
* The maximum size in pixel allowed by the plugin.
*/
#ifndef SCT_MAX_IMAGE_WIDTH
#define SCT_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef SCT_MAX_IMAGE_HEIGHT
#define SCT_MAX_IMAGE_HEIGHT SCT_MAX_IMAGE_WIDTH
#endif
#define CTRLBLOCK_SIZE 256
#define PRMSBLOCK_SIZE_CT 256
@ -139,7 +149,7 @@ public:
return false;
}
// Set a reasonable upper limit
if (width() > 300000 || height() > 300000) {
if (width() > SCT_MAX_IMAGE_WIDTH || height() > SCT_MAX_IMAGE_HEIGHT) {
return false;
}
return m_cb.fileType() == QStringLiteral(FILETYPE_CT) && format() != QImage::Format_Invalid;

View File

@ -13,6 +13,11 @@
#include <QImage>
#include <QImageIOHandler>
// Default maximum width and height for the large image plugins.
#ifndef KIF_LARGE_IMAGE_PIXEL_LIMIT
#define KIF_LARGE_IMAGE_PIXEL_LIMIT 300000
#endif
// Image metadata keys to use in plugins (so they are consistent)
#define META_KEY_ALTITUDE "Altitude"
#define META_KEY_AUTHOR "Author"

View File

@ -26,12 +26,16 @@
#define USE_FLOAT_IMAGES // default uncommented
// Let's set a "reasonable" maximum size
#define MAX_IMAGE_WIDTH 300000
#define MAX_IMAGE_HEIGHT 300000
#ifndef XCF_MAX_IMAGE_WIDTH
#define XCF_MAX_IMAGE_WIDTH KIF_LARGE_IMAGE_PIXEL_LIMIT
#endif
#ifndef XCF_MAX_IMAGE_HEIGHT
#define XCF_MAX_IMAGE_HEIGHT XCF_MAX_IMAGE_WIDTH
#endif
#else
// While it is possible to have images larger than 32767 pixels, QPainter seems unable to go beyond this threshold using Qt 5.
#define MAX_IMAGE_WIDTH 32767
#define MAX_IMAGE_HEIGHT 32767
#define XCF_MAX_IMAGE_WIDTH 32767
#define XCF_MAX_IMAGE_HEIGHT 32767
#endif
#ifdef USE_FLOAT_IMAGES
@ -844,8 +848,8 @@ bool XCFImageFormat::readXCFHeader(QDataStream &xcf_io, XCFImage::Header *header
return false;
}
if (header->width > MAX_IMAGE_WIDTH || header->height > MAX_IMAGE_HEIGHT) {
qCWarning(XCFPLUGIN) << "The maximum image size is limited to" << MAX_IMAGE_WIDTH << "x" << MAX_IMAGE_HEIGHT << "px";
if (header->width > XCF_MAX_IMAGE_WIDTH || header->height > XCF_MAX_IMAGE_HEIGHT) {
qCWarning(XCFPLUGIN) << "The maximum image size is limited to" << XCF_MAX_IMAGE_WIDTH << "x" << XCF_MAX_IMAGE_HEIGHT << "px";
return false;
}
@ -1364,8 +1368,8 @@ bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
qCWarning(XCFPLUGIN) << "On 32-bits programs the maximum layer size is limited to" << 16384 << "x" << 16384 << "px";
return false;
}
if (layer.width > MAX_IMAGE_WIDTH || layer.height > MAX_IMAGE_HEIGHT) {
qCWarning(XCFPLUGIN) << "The maximum layer size is limited to" << MAX_IMAGE_WIDTH << "x" << MAX_IMAGE_HEIGHT << "px";
if (layer.width > XCF_MAX_IMAGE_WIDTH || layer.height > XCF_MAX_IMAGE_HEIGHT) {
qCWarning(XCFPLUGIN) << "The maximum layer size is limited to" << XCF_MAX_IMAGE_WIDTH << "x" << XCF_MAX_IMAGE_HEIGHT << "px";
return false;
}
@ -2793,8 +2797,7 @@ void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
QPainter painter(&image);
painter.setOpacity(layer.opacity / 255.0);
painter.setCompositionMode(QPainter::CompositionMode_Source);
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
if (x + layer.x_offset < XCF_MAX_IMAGE_WIDTH && y + layer.y_offset < XCF_MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
}
continue;
@ -3196,8 +3199,7 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
qint32 x = qint32(i * TILE_WIDTH);
QImage &tile = layer.image_tiles[j][i];
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
if (x + layer.x_offset < XCF_MAX_IMAGE_WIDTH && y + layer.y_offset < XCF_MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, tile);
}
}
@ -3248,8 +3250,7 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
QPainter painter(&image);
painter.setOpacity(layer.opacity / 255.0);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
if (x + layer.x_offset < XCF_MAX_IMAGE_WIDTH && y + layer.y_offset < XCF_MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
}
continue;