From 79e8e183eb566453bd8b5bfcbdd27724fd1fde6a Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Mon, 28 Aug 2023 18:02:02 +0000 Subject: [PATCH] ras: code revamped - Progressive load from file - Added support for 1-bit image - Images with palette are now Index (instead of RGB32) - Added options support (Size, Format) - Added some test cases - Improved performance by directly accessing the scanline - Support for more RAS extension (taken from GIMP) The code should works "as is" also on KF5. --- autotests/read/ras/rgb-gimp-2.10-1bit.png | Bin 0 -> 192 bytes autotests/read/ras/rgb-gimp-2.10-1bit.ras | Bin 0 -> 160 bytes autotests/read/ras/rgb-gimp-2.10-gray.png | Bin 0 -> 470 bytes autotests/read/ras/rgb-gimp-2.10-gray.ras | Bin 0 -> 1824 bytes autotests/read/ras/rgb-gimp-2.10-pal16.png | Bin 0 -> 338 bytes autotests/read/ras/rgb-gimp-2.10-pal16.ras | Bin 0 -> 1104 bytes autotests/read/ras/rgb24.png | Bin 0 -> 7289 bytes autotests/read/ras/rgb24.ras | Bin 0 -> 9692 bytes src/imageformats/ras.cpp | 302 ++++++++++++--------- src/imageformats/ras.json | 4 +- src/imageformats/ras_p.h | 3 + 11 files changed, 185 insertions(+), 124 deletions(-) create mode 100644 autotests/read/ras/rgb-gimp-2.10-1bit.png create mode 100644 autotests/read/ras/rgb-gimp-2.10-1bit.ras create mode 100644 autotests/read/ras/rgb-gimp-2.10-gray.png create mode 100644 autotests/read/ras/rgb-gimp-2.10-gray.ras create mode 100644 autotests/read/ras/rgb-gimp-2.10-pal16.png create mode 100644 autotests/read/ras/rgb-gimp-2.10-pal16.ras create mode 100644 autotests/read/ras/rgb24.png create mode 100644 autotests/read/ras/rgb24.ras diff --git a/autotests/read/ras/rgb-gimp-2.10-1bit.png b/autotests/read/ras/rgb-gimp-2.10-1bit.png new file mode 100644 index 0000000000000000000000000000000000000000..4f0a3ad3e907f58d918c04120e79cf476087a9d4 GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T!Hle|NocXoPQU{VodUO zcVXyYmGuB}I14-?iy0XB6G519h5hnOpdfpRr>`sfa}H59R+e{L6(xW|4xTQKAsp9} zfAF*LcpSO^`@iJA|5|I)f9wtaXE!05S7^0+DAS{V%*C$*cW{(u=xlgnzahyW+rF!k gWAVQQUJQ&37mdqPcV(^(2b#s;>FVdQ&MBb@04_&6%>V!Z literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb-gimp-2.10-1bit.ras b/autotests/read/ras/rgb-gimp-2.10-1bit.ras new file mode 100644 index 0000000000000000000000000000000000000000..11cfdea844427c5a6396a43c4dff2365adf6cdd1 GIT binary patch literal 160 zcma!CmNk`ufk6R^8G&>I5QAt;z@)&y!P?cp;`Bg)fvJUofvEwZ2E+#I0@5%xOdgpA WsbK`E0nrXX0t#SynH^vvU>X1#`wHCv literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb-gimp-2.10-gray.png b/autotests/read/ras/rgb-gimp-2.10-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..9d1dbd9f107c9d36afdd88584950959fbbf77bc6 GIT binary patch literal 470 zcmV;{0V)28P)D zMnT&&9r-+r1 zfnsAqi398kR=Ni_>-T5Uvh2?Ry4^qs*?Wgx@G#axZq^`Fl3`na0SP;L|B0uEasU7T M07*qoM6N<$f*Hcb>;M1& literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb-gimp-2.10-gray.ras b/autotests/read/ras/rgb-gimp-2.10-gray.ras new file mode 100644 index 0000000000000000000000000000000000000000..faf75d7a432f9be0b404bd95cb734523d3beb7ac GIT binary patch literal 1824 zcma!CmNk`ufk6R^IT#pNfJ_EP2xbPdn3!2u+1NQaxwv_F`S=9{g@i>!#l$5frKDwK z<>VC*^aCo0?l% z+uA!iySjUN`}!wLoHTjL)M?Xa%$zlQ&fIzP7c5+~c*)Xb%U7&iwR+9kb?Y~5+_ZVi z)@|E&?A*0`&)$9e4;(yn_{h;?$4{I*b^6TNbLTHyyma}>)oa&p+`M)B&fR`*cke%Z{Pg+D*Kgl{{QUL%&)mFa0&4p6`|n>MAL2fw0Qhp~@b*W4kp$3~KW|^T`58?NnfrZT$KJ2V0%+_HQ!A#v zMiWEke%`Wh?K2ElAyj->mECt2kNe(rCgz<52MR(DGV8;VX_Kz~K^8$}f8DcW%NsoQ ze?7SS06zbHzkcS%PgEn3dH+5vPhW#i|I1?U!iRY5f8AQxhR=WRW=)uO_y@9;sO)b$ z=PWpeNB;Mnt5@&g3BNy2&z*aUC;a|AI&tC=9{FDv`uZ;XLUj`|@B7w>h^^m|MNrv) W9xPq@0FU|q|9t(5Pa4%UFb@D8ok#-! literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb-gimp-2.10-pal16.png b/autotests/read/ras/rgb-gimp-2.10-pal16.png new file mode 100644 index 0000000000000000000000000000000000000000..968696cfeb6c1b723cb171c7d5c872192ce2954f GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvg8-ip*Yv;_+u}}THE%qc+xxoO zrG9qdr8)CY?EilCXmjS<);TxdR=zsEQ zL70(Y)*K0-AbW|YuPgg=4iPa0!!P+CPXdLudb&7}(a$Eafol)5;D3-IaykK} z-_E@&UU_!r=4*Q_{>o{5nEU$O*}1_}o0Qe(cFx@^r(+VUk*WWvwE12NEx$J9|N#oql7g%ony1>%&_99EnpNlM$K3`;EIeL-B=gdWx zsNWawZj=vwaQ|*~29xiLZ3Z6}b82KR04u-%NwH{p9;N%Z-v=2yvm6+! i6sAvq+?$iaz;Nm71(78ZSA2mUVDNPHb6Mw<&;$UBl9z`7 literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb-gimp-2.10-pal16.ras b/autotests/read/ras/rgb-gimp-2.10-pal16.ras new file mode 100644 index 0000000000000000000000000000000000000000..7ceae8e943bca85a5c05099167d08804aebd65c7 GIT binary patch literal 1104 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 T-pZ-?00000NkvXXu0mjfuqJ;> literal 0 HcmV?d00001 diff --git a/autotests/read/ras/rgb24.ras b/autotests/read/ras/rgb24.ras new file mode 100644 index 0000000000000000000000000000000000000000..95438242b0180be7124291a06e4602268493076f GIT binary patch literal 9692 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 SPDX-FileCopyrightText: 2004 Ignacio CastaƱo SPDX-FileCopyrightText: 2010 Troy Unrau + SPDX-FileCopyrightText: 2023 Mirco Miranda SPDX-License-Identifier: LGPL-2.0-or-later */ @@ -80,152 +81,161 @@ static bool IsSupported(const RasHeader &head) return false; } // check for an appropriate depth - // we support 8bit+palette, 24bit and 32bit ONLY! - // TODO: add support for 1bit - if (!((head.Depth == 8 && head.ColorMapType == 1) || head.Depth == 24 || head.Depth == 32)) { + if (head.Depth != 1 && head.Depth != 8 && head.Depth != 24 && head.Depth != 32) { + return false; + } + if (head.Width == 0 || head.Height == 0) { return false; } // the Type field adds support for RLE(BGR), RGB and other encodings // we support Type 1: Normal(BGR) and Type 3: Normal(RGB) ONLY! // TODO: add support for Type 2: RLE(BGR) & Type 4,5: TIFF/IFF - if (!(head.Type == 1 || head.Type == 3)) { - return false; - } - // Old files didn't have Length set - reject them for now - // TODO: add length recalculation to support old files - if (!head.Length) { + if (!(head.Type == RAS_TYPE_STANDARD || head.Type == RAS_TYPE_RGB_FORMAT)) { return false; } return true; } +static QImage::Format imageFormat(const RasHeader &header) +{ + if (header.ColorMapType == RAS_COLOR_MAP_TYPE_RGB) { + return QImage::Format_Indexed8; + } + if (header.Depth == 8 && header.ColorMapType == RAS_COLOR_MAP_TYPE_NONE) { + return QImage::Format_Grayscale8; + } + if (header.Depth == 1) { + return QImage::Format_Mono; + } + return QImage::Format_RGB32; +} + static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img) { s.device()->seek(RasHeader::SIZE); - if (ras.ColorMapLength > kMaxQVectorSize) { - qWarning() << "LoadRAS() unsupported image color map length in file header" << ras.ColorMapLength; + // The width of a scan line is always a multiple of 16 bits, padded when necessary. + auto rasLineSize = (qint64(ras.Width) * ras.Depth + 7) / 8; + if (rasLineSize & 1) + ++rasLineSize; + if (rasLineSize > kMaxQVectorSize) { + qWarning() << "LoadRAS() unsupported line size" << rasLineSize; return false; } - // Read palette if needed. - QVector palette(ras.ColorMapLength); - if (ras.ColorMapType == 1) { - for (quint32 i = 0; i < ras.ColorMapLength; ++i) { - s >> palette[i]; - } - } - - const int bpp = ras.Depth / 8; - if (ras.Height == 0) { - return false; - } - if (bpp == 0) { - return false; - } - if (ras.Length / ras.Height / bpp < ras.Width) { - qWarning() << "LoadRAS() mistmatch between height and width" << ras.Width << ras.Height << ras.Length << ras.Depth; - return false; - } - if (ras.Length > kMaxQVectorSize) { - qWarning() << "LoadRAS() unsupported image length in file header" << ras.Length; - return false; - } - - // each line must be a factor of 16 bits, so they may contain padding - // this will be 1 if padding required, 0 otherwise - const int paddingrequired = (ras.Width * bpp % 2); - - // qDebug() << "paddingrequired: " << paddingrequired; - // don't trust ras.Length - QVector input(ras.Length); - - int i = 0; - while (!s.atEnd() && i < input.size()) { - s >> input[i]; - // I guess we need to find out if we're at the end of a line - if (paddingrequired && i != 0 && !(i % (ras.Width * bpp))) { - s >> input[i]; - } - i++; - } - // Allocate image - img = imageAlloc(ras.Width, ras.Height, QImage::Format_ARGB32); + img = imageAlloc(ras.Width, ras.Height, imageFormat(ras)); if (img.isNull()) { return false; } - // Reconstruct image from RGB palette if we have a palette - // TODO: make generic so it works with 24bit or 32bit palettes - if (ras.ColorMapType == 1 && ras.Depth == 8) { - quint8 red; - quint8 green; - quint8 blue; - for (quint32 y = 0; y < ras.Height; y++) { - for (quint32 x = 0; x < ras.Width; x++) { - red = palette.value((int)input[y * ras.Width + x]); - green = palette.value((int)input[y * ras.Width + x] + (ras.ColorMapLength / 3)); - blue = palette.value((int)input[y * ras.Width + x] + 2 * (ras.ColorMapLength / 3)); - img.setPixel(x, y, qRgb(red, green, blue)); - } + // Read palette if needed. + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_RGB) { + QVector palette(ras.ColorMapLength); + for (quint32 i = 0; i < ras.ColorMapLength; ++i) { + s >> palette[i]; + } + QList colorTable; + for (quint32 i = 0, n = ras.ColorMapLength / 3; i < n; ++i) { + colorTable << qRgb(palette.at(i), palette.at(i + n), palette.at(i + 2 * n)); + } + for (; colorTable.size() < 256;) { + colorTable << qRgb(255, 255, 255); + } + img.setColorTable(colorTable); + if (s.status() != QDataStream::Ok) { + return false; } } - if (ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) { - quint8 red; - quint8 green; - quint8 blue; - for (quint32 y = 0; y < ras.Height; y++) { - for (quint32 x = 0; x < ras.Width; x++) { - red = input[y * 3 * ras.Width + x * 3 + 2]; - green = input[y * 3 * ras.Width + x * 3 + 1]; - blue = input[y * 3 * ras.Width + x * 3]; - img.setPixel(x, y, qRgb(red, green, blue)); - } + QByteArray rasLine(rasLineSize, 0); + auto bytesPerLine = std::min(img.bytesPerLine(), rasLine.size()); + for (quint32 y = 0; y < ras.Height; ++y) { + auto read = s.readRawData(rasLine.data(), rasLine.size()); + if (read != rasLine.size()) { + qWarning() << "LoadRAS() unable to read line" << y << ": the seems corrupted!"; + return false; } - } - if (ras.ColorMapType == 0 && ras.Depth == 24 && ras.Type == 3) { - quint8 red; - quint8 green; - quint8 blue; - for (quint32 y = 0; y < ras.Height; y++) { - for (quint32 x = 0; x < ras.Width; x++) { - red = input[y * 3 * ras.Width + x * 3]; - green = input[y * 3 * ras.Width + x * 3 + 1]; - blue = input[y * 3 * ras.Width + x * 3 + 2]; - img.setPixel(x, y, qRgb(red, green, blue)); + // Grayscale 1-bit / Grayscale 8-bit (never seen) + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_NONE && (ras.Depth == 1 || ras.Depth == 8)) { + for (auto &&b : rasLine) { + b = ~b; } + std::memcpy(img.scanLine(y), rasLine.constData(), bytesPerLine); + continue; } - } - if (ras.ColorMapType == 0 && ras.Depth == 32 && (ras.Type == 1 || ras.Type == 2)) { - quint8 red; - quint8 green; - quint8 blue; - for (quint32 y = 0; y < ras.Height; y++) { - for (quint32 x = 0; x < ras.Width; x++) { - red = input[y * 4 * ras.Width + x * 4 + 3]; - green = input[y * 4 * ras.Width + x * 4 + 2]; - blue = input[y * 4 * ras.Width + x * 4 + 1]; - img.setPixel(x, y, qRgb(red, green, blue)); - } + // Image with palette + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_RGB && (ras.Depth == 1 || ras.Depth == 8)) { + std::memcpy(img.scanLine(y), rasLine.constData(), bytesPerLine); + continue; } - } - if (ras.ColorMapType == 0 && ras.Depth == 32 && ras.Type == 3) { - quint8 red; - quint8 green; - quint8 blue; - for (quint32 y = 0; y < ras.Height; y++) { + // BGR 24-bit + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_NONE && ras.Depth == 24 && (ras.Type == RAS_TYPE_STANDARD || ras.Type == RAS_TYPE_BYTE_ENCODED)) { + quint8 red; + quint8 green; + quint8 blue; + auto scanLine = reinterpret_cast(img.scanLine(y)); for (quint32 x = 0; x < ras.Width; x++) { - red = input[y * 4 * ras.Width + x * 4 + 1]; - green = input[y * 4 * ras.Width + x * 4 + 2]; - blue = input[y * 4 * ras.Width + x * 4 + 3]; - img.setPixel(x, y, qRgb(red, green, blue)); + red = rasLine.at(x * 3 + 2); + green = rasLine.at(x * 3 + 1); + blue = rasLine.at(x * 3); + *(scanLine + x) = qRgb(red, green, blue); } + continue; } + + // RGB 24-bit + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_NONE && ras.Depth == 24 && ras.Type == RAS_TYPE_RGB_FORMAT) { + quint8 red; + quint8 green; + quint8 blue; + auto scanLine = reinterpret_cast(img.scanLine(y)); + for (quint32 x = 0; x < ras.Width; x++) { + red = rasLine.at(x * 3); + green = rasLine.at(x * 3 + 1); + blue = rasLine.at(x * 3 + 2); + *(scanLine + x) = qRgb(red, green, blue); + } + continue; + } + + // BGR 32-bit (not tested: test case missing) + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_NONE && ras.Depth == 32 && (ras.Type == RAS_TYPE_STANDARD || ras.Type == RAS_TYPE_BYTE_ENCODED)) { + quint8 red; + quint8 green; + quint8 blue; + auto scanLine = reinterpret_cast(img.scanLine(y)); + for (quint32 x = 0; x < ras.Width; x++) { + red = rasLine.at(x * 4 + 3); + green = rasLine.at(x * 4 + 2); + blue = rasLine.at(x * 4 + 1); + *(scanLine + x) = qRgb(red, green, blue); + } + + continue; + } + + // RGB 32-bit (tested: test case missing due to image too large) + if (ras.ColorMapType == RAS_COLOR_MAP_TYPE_NONE && ras.Depth == 32 && ras.Type == RAS_TYPE_RGB_FORMAT) { + quint8 red; + quint8 green; + quint8 blue; + auto scanLine = reinterpret_cast(img.scanLine(y)); + for (quint32 x = 0; x < ras.Width; x++) { + red = rasLine.at(x * 4 + 1); + green = rasLine.at(x * 4 + 2); + blue = rasLine.at(x * 4 + 3); + *(scanLine + x) = qRgb(red, green, blue); + } + continue; + } + + qWarning() << "LoadRAS() unsupported format!" + << "ColorMapType:" << ras.ColorMapType << "Type:" << ras.Type << "Depth:" << ras.Depth; + return false; } return true; @@ -283,16 +293,8 @@ bool RASHandler::read(QImage *outImage) RasHeader ras; s >> ras; - if (ras.ColorMapLength > std::numeric_limits::max()) { - return false; - } - - // TODO: add support for old versions of RAS where Length may be zero in header - s.device()->seek(RasHeader::SIZE + ras.Length + ras.ColorMapLength); - - // Check image file format. Type 2 is RLE, which causing seeking to be silly. - if (!s.atEnd() && ras.Type != 2) { - // qDebug() << "This RAS file is not valid, or an older version of the format."; + if (ras.ColorMapLength > kMaxQVectorSize) { + qWarning() << "LoadRAS() unsupported image color map length in file header" << ras.ColorMapLength; return false; } @@ -314,9 +316,65 @@ bool RASHandler::read(QImage *outImage) return true; } +bool RASHandler::supportsOption(ImageOption option) const +{ + if (option == QImageIOHandler::Size) { + return true; + } + if (option == QImageIOHandler::ImageFormat) { + return true; + } + return false; +} + +QVariant RASHandler::option(ImageOption option) const +{ + QVariant v; + + if (option == QImageIOHandler::Size) { + if (auto d = device()) { + // transactions works on both random and sequential devices + d->startTransaction(); + auto ba = d->read(RasHeader::SIZE); + d->rollbackTransaction(); + + QDataStream s(ba); + s.setByteOrder(QDataStream::BigEndian); + + RasHeader header; + s >> header; + + if (s.status() == QDataStream::Ok && IsSupported(header)) { + v = QVariant::fromValue(QSize(header.Width, header.Height)); + } + } + } + + if (option == QImageIOHandler::ImageFormat) { + if (auto d = device()) { + // transactions works on both random and sequential devices + d->startTransaction(); + auto ba = d->read(RasHeader::SIZE); + d->rollbackTransaction(); + + QDataStream s(ba); + s.setByteOrder(QDataStream::BigEndian); + + RasHeader header; + s >> header; + + if (s.status() == QDataStream::Ok && IsSupported(header)) { + v = QVariant::fromValue(imageFormat(header)); + } + } + } + + return v; +} + QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const { - if (format == "ras") { + if (format == "im1" || format == "im8" || format == "im24" || format == "im32" || format == "ras" || format == "sun") { return Capabilities(CanRead); } if (!format.isEmpty()) { diff --git a/src/imageformats/ras.json b/src/imageformats/ras.json index 31a9f6a..1d58077 100644 --- a/src/imageformats/ras.json +++ b/src/imageformats/ras.json @@ -1,4 +1,4 @@ { - "Keys": [ "ras" ], - "MimeTypes": [ "image/x-sun-raster" ] + "Keys": [ "im1", "im8", "im24", "im32", "ras", "sun" ], + "MimeTypes": [ "image/x-sun-raster", "image/x-sun-raster", "image/x-sun-raster", "image/x-sun-raster", "image/x-sun-raster", "image/x-sun-raster" ] } diff --git a/src/imageformats/ras_p.h b/src/imageformats/ras_p.h index 044e1e8..99a82a0 100644 --- a/src/imageformats/ras_p.h +++ b/src/imageformats/ras_p.h @@ -19,6 +19,9 @@ public: bool canRead() const override; bool read(QImage *image) override; + bool supportsOption(QImageIOHandler::ImageOption option) const override; + QVariant option(QImageIOHandler::ImageOption option) const override; + static bool canRead(QIODevice *device); };