mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-18 03:54:18 -04:00
Fix image allocation with Qt 6
To make the plugins fail to allocate if the image size is greater than QImageReader::allocationLimit() it is necessary to allocate the image with QImageIOHandler::allocateImage(). Note that not all plugins have been changed and some others are not tested in the CI (maybe due to missing libraries). PS: the following message is printed by QImageIOHandler::allocateImage() if the size is exceeded: "qt.gui.imageio: QImageIOHandler: Rejecting image as it exceeds the current allocation limit of XXX megabytes"
This commit is contained in:
committed by
Albert Astals Cid
parent
dfbc6e0f8c
commit
feb6d9b20f
@ -6,6 +6,7 @@
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "util_p.h"
|
||||
#include "xcf_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
@ -17,6 +18,9 @@
|
||||
#include <QVector>
|
||||
#include <QtEndian>
|
||||
#include <QColorSpace>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QImageReader>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -1099,6 +1103,18 @@ bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Qt 6 image allocation limit calculation: we have to check the limit here because the image is splitted in
|
||||
// tiles of 64x64 pixels. The required memory to build the image is at least doubled because tiles are loaded
|
||||
// and then the final image is created by copying the tiles inside it.
|
||||
// NOTE: on Windows to open a 10GiB image the plugin uses 28GiB of RAM
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
qint64 channels = 1 + (layer.type == RGB_GIMAGE ? 2 : 0) + (layer.type == RGBA_GIMAGE ? 3 : 0);
|
||||
if (qint64(layer.width) * qint64(layer.height) * channels * 2ll / 1024ll / 1024ll > QImageReader::allocationLimit()) {
|
||||
qCDebug(XCFPLUGIN) << "Rejecting image as it exceeds the current allocation limit of" << QImageReader::allocationLimit() << "megabytes";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
layer.image_tiles.resize(layer.nrows);
|
||||
|
||||
if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
|
||||
@ -1917,7 +1933,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
switch (layer.type) {
|
||||
case RGB_GIMAGE:
|
||||
if (layer.opacity == OPAQUE_OPACITY) {
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_RGB32);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_RGB32);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
}
|
||||
@ -1926,7 +1942,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
} // else, fall through to 32-bit representation
|
||||
Q_FALLTHROUGH();
|
||||
case RGBA_GIMAGE:
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
}
|
||||
@ -1935,7 +1951,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
|
||||
case GRAY_GIMAGE:
|
||||
if (layer.opacity == OPAQUE_OPACITY) {
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image.setColorCount(256);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
@ -1946,7 +1962,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
} // else, fall through to 32-bit representation
|
||||
Q_FALLTHROUGH();
|
||||
case GRAYA_GIMAGE:
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
}
|
||||
@ -1967,7 +1983,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
// or two-color palette. Have to ask about this...
|
||||
|
||||
if (xcf_image.num_colors <= 2) {
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
|
||||
image.setColorCount(xcf_image.num_colors);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
@ -1975,7 +1991,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
image.fill(0);
|
||||
setPalette(xcf_image, image);
|
||||
} else if (xcf_image.num_colors <= 256) {
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image.setColorCount(xcf_image.num_colors);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
@ -1993,7 +2009,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
xcf_image.palette[1] = xcf_image.palette[0];
|
||||
xcf_image.palette[0] = qRgba(255, 255, 255, 0);
|
||||
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
|
||||
image.setColorCount(xcf_image.num_colors);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
@ -2009,7 +2025,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
}
|
||||
|
||||
xcf_image.palette[0] = qRgba(255, 255, 255, 0);
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
|
||||
image.setColorCount(xcf_image.num_colors);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
@ -2020,7 +2036,7 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
// No room for a transparent color, so this has to be promoted to
|
||||
// true color. (There is no equivalent PNG representation output
|
||||
// from The GIMP as of v1.2.)
|
||||
image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
image = imageAlloc(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
|
||||
if (image.isNull()) {
|
||||
return false;
|
||||
}
|
||||
@ -2031,11 +2047,11 @@ bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
|
||||
|
||||
if (xcf_image.x_resolution > 0 && xcf_image.y_resolution > 0) {
|
||||
const float dpmx = xcf_image.x_resolution * INCHESPERMETER;
|
||||
if (dpmx > std::numeric_limits<int>::max()) {
|
||||
if (dpmx > float(std::numeric_limits<int>::max())) {
|
||||
return false;
|
||||
}
|
||||
const float dpmy = xcf_image.y_resolution * INCHESPERMETER;
|
||||
if (dpmy > std::numeric_limits<int>::max()) {
|
||||
if (dpmy > float(std::numeric_limits<int>::max())) {
|
||||
return false;
|
||||
}
|
||||
image.setDotsPerMeterX((int)dpmx);
|
||||
|
Reference in New Issue
Block a user