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.
This commit is contained in:
Ana Bobillo
2026-10-28 07:43:33 +01:00
committed by Mirco Miranda
parent 32ff79442c
commit 5e406e76ba
5 changed files with 5 additions and 16 deletions
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

+5 -16
View File
@@ -91,7 +91,7 @@ public:
*/ */
inline bool isSupported() const 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 inline QImage::Format format() const
{ {
@@ -370,11 +370,6 @@ static bool readImage4(QImage &img, QDataStream &s, const PCXHEADER &header)
return false; 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) { for (int y = 0; y < header.height(); ++y) {
if (s.atEnd()) { if (s.atEnd()) {
return false; return false;
@@ -437,12 +432,8 @@ static bool readImage2(QImage &img, QDataStream &s, const PCXHEADER &header)
return false; return false;
} }
const unsigned int bpl = std::min(header.BytesPerLine, static_cast<quint16>(header.width() / 4)); for (int x = 0; x < header.width(); ++x) {
for (unsigned int x = 0; x < bpl; ++x) { p[x] = (quint8(buf.at(x / 4)) >> (6 - 2 * (x % 4))) & 3;
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;
} }
} }
@@ -480,10 +471,8 @@ static bool readImage4v2(QImage &img, QDataStream &s, const PCXHEADER &header)
return false; return false;
} }
const unsigned int bpl = std::min(header.BytesPerLine, static_cast<quint16>(header.width() / 2)); for (int x = 0; x < header.width(); ++x) {
for (unsigned int x = 0; x < bpl; ++x) { p[x] = (quint8(buf.at(x / 2)) >> (x % 2 ? 0 : 4)) & 15;
p[x * 2] = (buf[x] & 240) >> 4;
p[x * 2 + 1] = buf[x] & 15;
} }
} }