JXR: Fixed image reading on sequential devices

The following changes are done:
- Fixed an error when copying image from sequential device
- Return error when the image exceed 4GB size on writing*
- Enabled JXR tests

(*) Note that when writing an image larger than 4GiB, the JXRLib does not give any error but the resulting saved image id wrong.
This commit is contained in:
Mirco Miranda 2024-10-09 21:34:32 +00:00 committed by Albert Astals Cid
parent 97120b2537
commit ac1006cc66
3 changed files with 22 additions and 14 deletions

View File

@ -7,3 +7,4 @@ Dependencies:
Options:
test-before-installing: True
require-passing-tests-on: [ 'Linux', 'FreeBSD', 'Windows' ]
cmake-options: "-DKIMAGEFORMATS_JXR=ON"

View File

@ -117,7 +117,7 @@ plugin ('n/a' means no limit, i.e. the limit depends on the format encoding).
- HDR: n/a (large image)
- HEIF: n/a
- JXL: 65,535 x 65,535 pixels, in any case no larger than 256 megapixels
- JXR: n/a
- JXR: n/a, in any case no larger than 4 GB
- PCX: 65,535 x 65,535 pixels
- PFM: n/a (large image)
- PIC: 65,535 x 65,535 pixels

View File

@ -484,11 +484,13 @@ public:
qi = qi.convertToFormat(alpha ? QImage::Format_RGBA8888 : QImage::Format_RGB888);
}
#ifndef JXR_DENY_FLOAT_IMAGE
// clang-format off
} else if (qi.format() == QImage::Format_RGBA16FPx4 ||
qi.format() == QImage::Format_RGBX16FPx4 ||
qi.format() == QImage::Format_RGBA32FPx4 ||
qi.format() == QImage::Format_RGBA32FPx4_Premultiplied ||
qi.format() == QImage::Format_RGBX32FPx4) {
// clang-format on
auto cs = qi.colorSpace();
if (cs.isValid() && cs.transferFunction() != QColorSpace::TransferFunction::Linear) {
qi = qi.convertedToColorSpace(QColorSpace(QColorSpace::SRgbLinear));
@ -670,9 +672,12 @@ private:
return false;
}
QByteArray buff(32768 * 4, char());
for (; !source->atEnd();) {
for (;;) {
auto read = source->read(buff.data(), buff.size());
if (read < 1) {
if (read == 0) {
break;
}
if (read < 0) {
return false;
}
if (target->write(buff.data(), read) != read) {
@ -880,6 +885,13 @@ bool JXRHandler::read(QImage *outImage)
bool JXRHandler::write(const QImage &image)
{
// JXR is stored in a TIFF V6 container that is limited to 4GiB. The size
// is limited to 4GB to leave room for IFDs, Metadata, etc...
if (qint64(image.sizeInBytes()) > 4000000000ll) {
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() image too large: the image cannot exceed 4GB.";
return false;
}
if (!d->initForWriting()) {
return false;
}
@ -1064,11 +1076,6 @@ bool JXRHandler::canRead(QIODevice *device)
return false;
}
// Some tests on sequential devices fail: I reject them for now
if (device->isSequential()) {
return false;
}
// JPEG XR image data is stored in TIFF-like container format (II and 0xBC01 version)
if (device->peek(4) == QByteArray::fromRawData("\x49\x49\xbc\x01", 4)) {
return true;