Compare commits

...

7 Commits

Author SHA1 Message Date
f6bb59228e GIT_SILENT Upgrade ECM and KF version requirements for 5.111.0 release. 2023-10-07 10:20:46 +00:00
ee381958b2 avif: support repetition count
and minor performance optimizations.
2023-10-06 12:52:48 +02:00
478e49b8a6 raw: fix multi image load
Fixes not loading a second image in the file. This patch allow code like the following.

QImageReader r(file);
do {
    auto qi = r.read();
    if (!qi.isNull()) {
        qi.save(QString("/tmp/%1_%2.tif")
                .arg(QFileInfo(file).baseName())
                .arg(r.currentImageNumber()));
    }
}
while (r.jumpToNextImage());

m_startPos is used to reposition the device if you decide to do a subsequent read: libraw wants it to be at the beginning of the RAW stream

(cherry picked from commit 18ea0492bc)
2023-09-25 22:56:39 +02:00
c3daf86079 hdr: fix oss-fuzz issue 62197
Fixes the following error:

| /src/kimageformats/src/imageformats/hdr.cpp:56:31: runtime error: shift exponent 32 is too large for 32-bit type 'int' |
|------------------------------------------------------------------------------------------------------------------------|
2023-09-11 09:07:53 +00:00
a981cefdd2 hdr: fix crash (oss-fuzz)
This patch Fixes crash when RLE data is corrupted (test cases attached).

Should also fixes (no test cases available):
- Issue 62044 in oss-fuzz: kimageformats:kimgio_hdr_fuzzer: Undefined-shift in RGBE_To_QRgbLine
- Issue 62057 in oss-fuzz: kimageformats:kimgio_hdr_fuzzer: Heap-buffer-overflow in Read_Old_Line


[crash-646a4364479f54278ff8c30c69b0c9665e5869af.hdr](/uploads/44760f0286cde4236feab8e352493556/crash-646a4364479f54278ff8c30c69b0c9665e5869af.hdr)

[crash-88c33e2b49e57e6d1d4ec6945476f605f00e714a.hdr](/uploads/e35bf53ee717134a796c4b17cfacca42/crash-88c33e2b49e57e6d1d4ec6945476f605f00e714a.hdr)
2023-09-07 16:22:33 +00:00
723f72930b xcf: fix crash (oss-fuzz issue 62075) 2023-09-07 16:13:18 +00:00
99bb24803a xcf: fix oss-fuzz issue
May fix possible crash on QPainter.
2023-09-05 10:17:22 +00:00
6 changed files with 64 additions and 14 deletions

View File

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

View File

@ -330,6 +330,10 @@ bool QAVIFHandler::decode_one_frame()
avifRGBImage rgb;
avifRGBImageSetDefaults(&rgb, m_decoder->image);
#if AVIF_VERSION >= 1000000
rgb.maxThreads = m_decoder->maxThreads;
#endif
if (m_decoder->image->depth > 8) {
rgb.depth = 16;
rgb.format = AVIF_RGB_FORMAT_RGBA;
@ -714,9 +718,9 @@ bool QAVIFHandler::write(const QImage &image)
if (save_depth == 8) {
save_depth = 10;
if (tmpcolorimage.hasAlphaChannel()) {
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBA64);
tmpcolorimage.convertTo(QImage::Format_RGBA64);
} else {
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBX64);
tmpcolorimage.convertTo(QImage::Format_RGBX64);
}
}
@ -1039,6 +1043,11 @@ int QAVIFHandler::loopCount() const
return 0;
}
#if AVIF_VERSION >= 1000000
if (m_decoder->repetitionCount >= 0) {
return m_decoder->repetitionCount;
}
#endif
// Endless loop to work around https://github.com/AOMediaCodec/libavif/issues/347
return -1;
}

View File

@ -40,6 +40,7 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
int rshift = 0;
int i;
uchar *start = image;
while (width > 0) {
s >> image[0];
s >> image[1];
@ -51,7 +52,14 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
}
if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1)) {
for (i = image[3] << rshift; i > 0; i--) {
// NOTE: we don't have an image sample that cover this code
if (rshift > 31) {
return false;
}
for (i = image[3] << rshift; i > 0 && width > 0; i--) {
if (image == start) {
return false; // you cannot be here at the first run
}
// memcpy(image, image-4, 4);
(uint &)image[0] = (uint &)image[0 - 4];
image += 4;
@ -72,7 +80,7 @@ static void RGBE_To_QRgbLine(uchar *image, QRgb *scanline, int width)
for (int j = 0; j < width; j++) {
// v = ldexp(1.0, int(image[3]) - 128);
float v;
int e = int(image[3]) - 128;
int e = qBound(-31, int(image[3]) - 128, 31);
if (e > 0) {
v = float(1 << e);
} else {
@ -146,7 +154,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
}
// read each component
for (int i = 0; i < 4; i++) {
for (int i = 0, len = int(lineArray.size()); i < 4; i++) {
for (int j = 0; j < width;) {
s >> code;
if (s.atEnd()) {
@ -158,14 +166,20 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
code &= 127;
s >> val;
while (code != 0) {
image[i + j * 4] = val;
auto idx = i + j * 4;
if (idx < len) {
image[idx] = val;
}
j++;
code--;
}
} else {
// non-run
while (code != 0) {
s >> image[i + j * 4];
auto idx = i + j * 4;
if (idx < len) {
s >> image[idx];
}
j++;
code--;
}

View File

@ -443,7 +443,9 @@ void setParams(QImageIOHandler *handler, LibRaw *rawProcessor)
auto &&rawparams = rawProcessor->imgdata.rawparams;
#endif
// Select one raw image from input file (0 - first, ...)
rawparams.shot_select = handler->currentImageNumber();
if (handler->currentImageNumber() > -1) {
rawparams.shot_select = handler->currentImageNumber();
}
// *** Set processing parameters
@ -723,6 +725,7 @@ RAWHandler::RAWHandler()
: m_imageNumber(0)
, m_imageCount(0)
, m_quality(-1)
, m_startPos(-1)
{
}
@ -739,6 +742,15 @@ bool RAWHandler::read(QImage *image)
{
auto dev = device();
// set the image position after the first run.
if (!dev->isSequential()) {
if (m_startPos < 0) {
m_startPos = dev->pos();
} else {
dev->seek(m_startPos);
}
}
// Check image file format.
if (dev->atEnd()) {
return false;
@ -820,7 +832,7 @@ bool RAWHandler::jumpToNextImage()
bool RAWHandler::jumpToImage(int imageNumber)
{
if (imageNumber >= imageCount()) {
if (imageNumber < 0 || imageNumber >= imageCount()) {
return false;
}
m_imageNumber = imageNumber;

View File

@ -78,6 +78,12 @@ private:
* @note It is safe to set both W and A: W is used if camera white balance is found, otherwise A is used.
*/
qint32 m_quality;
/*!
* \brief m_startPos
* The initial device position to allow multi image load (cache value).
*/
qint64 m_startPos;
};
class RAWPlugin : public QImageIOPlugin

View File

@ -2048,7 +2048,7 @@ bool XCFImageFormat::loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp, co
switch (layer.compression) {
case COMPRESS_NONE: {
if (xcf_io.version() > 11) {
if (xcf_io.version() > 11 || size_t(bpp) > sizeof(QRgba64)) {
qCDebug(XCFPLUGIN) << "Component reading not supported yet";
return false;
}
@ -2784,7 +2784,10 @@ void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
QPainter painter(&image);
painter.setOpacity(layer.opacity / 255.0);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
}
continue;
}
@ -3184,7 +3187,10 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
uint x = i * TILE_WIDTH;
QImage &tile = layer.image_tiles[j][i];
painter.drawImage(x + layer.x_offset, y + layer.y_offset, tile);
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, tile);
}
}
}
@ -3233,7 +3239,10 @@ void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
QPainter painter(&image);
painter.setOpacity(layer.opacity / 255.0);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
y + layer.y_offset < MAX_IMAGE_HEIGHT) {
painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
}
continue;
}