From 5e406e76ba3a78c9521e238e5c578c2ff8b3ddf5 Mon Sep 17 00:00:00 2001 From: Ana Bobillo Date: Tue, 27 Oct 2026 10:39:33 +0100 Subject: [PATCH] PCX: set every pixel of each line Images are allocated without being initialized, so a reader must write every pixel of every line. The PCX reader did not always: - readImage2() and readImage4v2() decoded width / 4 and width / 2 bytes, so the last pixels of lines whose width is not a multiple of 4 (2 bits) or 2 (4 bits) were not set. They now decode every pixel. - With a BytesPerLine smaller than a line of pixels, readImage1(), readImage8() and readImage24() left the end of each line unset: such headers are now refused by isSupported(), which replaces the check readImage4() had. Added the read tests indexed2_w13.pcx and indexed4_w13.pcx, which fail without this change. --- autotests/read/pcx/indexed2_w13.pcx | Bin 0 -> 151 bytes autotests/read/pcx/indexed2_w13.png | Bin 0 -> 123 bytes autotests/read/pcx/indexed4_w13.pcx | Bin 0 -> 198 bytes autotests/read/pcx/indexed4_w13.png | Bin 0 -> 160 bytes src/imageformats/pcx.cpp | 21 +++++---------------- 5 files changed, 5 insertions(+), 16 deletions(-) create mode 100644 autotests/read/pcx/indexed2_w13.pcx create mode 100644 autotests/read/pcx/indexed2_w13.png create mode 100644 autotests/read/pcx/indexed4_w13.pcx create mode 100644 autotests/read/pcx/indexed4_w13.png diff --git a/autotests/read/pcx/indexed2_w13.pcx b/autotests/read/pcx/indexed2_w13.pcx new file mode 100644 index 0000000000000000000000000000000000000000..77616d6b8c84017f3967dbd11a835b902b1b7494 GIT binary patch literal 151 zcmd;LWn^Li0v-l71`i-qa5!+lz`$UE!-E3~4GI$!Hf;FNAdrxdFyTT%fPjHOK*5EA y1qBWQ3l@BEXmHq&5Wv95!oUbJfJ|^$+TrlVhQrba4;3?$dd>30Gto&cW^R|SUy2Mi1h7C1aOps=9w zWjat?%hSa%q+$;1K}SXg1%bmG!Wfyp*=4?PWMx{$;;q7V?2vJRt_<_-Lq-PjDQ{Rk URz+Ns0qSD#boFyt=akR{0R8SEod5s; literal 0 HcmV?d00001 diff --git a/autotests/read/pcx/indexed4_w13.pcx b/autotests/read/pcx/indexed4_w13.pcx new file mode 100644 index 0000000000000000000000000000000000000000..b2438d736cdd61ad85577a4a20f503dffae0d5ce GIT binary patch literal 198 zcmd;LWn^Ih0v-l71`i-qa5!+lz`$UE!-E3~4GI$!Hf;FNAdrxdFyTT%fPjHOK*5EA z1qBWQ3l@BEXmHq&5Wv95!N3SIfK0%s?3&)W`rriy2z~b80|v0b*@N#7eqaDe0a=U! W3{Zx$0s}-u+0}pnECtl(zyJU@1UGj8 literal 0 HcmV?d00001 diff --git a/autotests/read/pcx/indexed4_w13.png b/autotests/read/pcx/indexed4_w13.png new file mode 100644 index 0000000000000000000000000000000000000000..b9016fe27fa5087d0267dca9482883041f7fde76 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp@K+Mj<3?vofZfOE3g8-ipR|SUy2Mi1h7C1aOpwOT& zL1Dv&4-End2?-M}Bm@W;2m};dC|FS7Ah2M;2ZsiS4G95jdRH9;>ecpiaSW-Lqk3{9 zCxZeHgF)0TZCk|$|Jl19T+nn@I^dabT_SmX(>Ed8`#a>fXs}PS*~HBP)W+cH>gTe~ HDWM4fmSr?E literal 0 HcmV?d00001 diff --git a/src/imageformats/pcx.cpp b/src/imageformats/pcx.cpp index af453a3..c5818c7 100644 --- a/src/imageformats/pcx.cpp +++ b/src/imageformats/pcx.cpp @@ -91,7 +91,7 @@ public: */ inline bool isSupported() const { - return isValid() && format() != QImage::Format_Invalid; + return isValid() && format() != QImage::Format_Invalid && BytesPerLine >= (width() * Bpp + 7) / 8; } inline QImage::Format format() const { @@ -370,11 +370,6 @@ static bool readImage4(QImage &img, QDataStream &s, const PCXHEADER &header) return false; } - if (header.BytesPerLine < (header.width() + 7) / 8) { - qCWarning(LOG_PCXPLUGIN) << "PCX image has invalid BytesPerLine value"; - return false; - } - for (int y = 0; y < header.height(); ++y) { if (s.atEnd()) { return false; @@ -437,12 +432,8 @@ static bool readImage2(QImage &img, QDataStream &s, const PCXHEADER &header) return false; } - const unsigned int bpl = std::min(header.BytesPerLine, static_cast(header.width() / 4)); - for (unsigned int x = 0; x < bpl; ++x) { - p[x * 4] = (buf[x] >> 6) & 3; - p[x * 4 + 1] = (buf[x] >> 4) & 3; - p[x * 4 + 2] = (buf[x] >> 2) & 3; - p[x * 4 + 3] = buf[x] & 3; + for (int x = 0; x < header.width(); ++x) { + p[x] = (quint8(buf.at(x / 4)) >> (6 - 2 * (x % 4))) & 3; } } @@ -480,10 +471,8 @@ static bool readImage4v2(QImage &img, QDataStream &s, const PCXHEADER &header) return false; } - const unsigned int bpl = std::min(header.BytesPerLine, static_cast(header.width() / 2)); - for (unsigned int x = 0; x < bpl; ++x) { - p[x * 2] = (buf[x] & 240) >> 4; - p[x * 2 + 1] = buf[x] & 15; + for (int x = 0; x < header.width(); ++x) { + p[x] = (quint8(buf.at(x / 2)) >> (x % 2 ? 0 : 4)) & 15; } }