From 5332ed4663fa774cfaa574cb7dbc5d4ce9cd3319 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Wed, 26 Oct 2022 11:40:37 +0200 Subject: [PATCH] [0.4.11][WIN32SS] Fix RLE4 bitmap decoding (#1188) CORE-10553 fix picked from 0.4.12-dev-189-g 968c8f37f14cf90fba994082274671b85f14764e It fixes: CORE-10553 'WinRar SFX have corrupted image' CORE-11399 'Microsoft paint (from XPSP3) does not show bitmaps on the tools' Please note, that MS mspaint.exe does not start in all older rls-branches yet for unrelated reasons, it did start and render properly in releases/0.4.11, but does not start in releases/0.4.7 yet. Still I marked the ticket CORE-11399 as resolved in all of them as that has nothing to do with the RLE stuff. The WinRAR SFX worked properly in all of them. --- win32ss/gdi/eng/rlecomp.c | 73 +++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/win32ss/gdi/eng/rlecomp.c b/win32ss/gdi/eng/rlecomp.c index ea90c4219bf..50f5e911abd 100644 --- a/win32ss/gdi/eng/rlecomp.c +++ b/win32ss/gdi/eng/rlecomp.c @@ -18,40 +18,52 @@ enum Rle_EscapeCodes RLE_DELTA = 2 /* Delta */ }; -VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format, ULONG cjSizeImage) +VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, + LONG Delta, ULONG Format, ULONG cjSizeImage) { - INT x = 0; - INT y = Size.cy - 1; - INT c; - INT length; - INT width; - INT height = y; + INT x = 0, y = Size.cy - 1; + INT i, c, c2, length; + INT width = Size.cx, height = y; BYTE *begin = CompressedBits; BYTE *bits = CompressedBits; BYTE *temp; - INT shift = 0; + BOOL is4bpp = FALSE; if ((Format == BMF_4RLE) || (Format == BMF_4BPP)) - shift = 1; + is4bpp = TRUE; else if ((Format != BMF_8RLE) && (Format != BMF_8BPP)) return; - width = ((Size.cx + shift) >> shift); - _SEH2_TRY { while (y >= 0 && (bits - begin) <= cjSizeImage) { - length = (*bits++) >> shift; + length = *bits++; if (length) { c = *bits++; - while (length--) + for (i = 0; i < length; i++) { if (x >= width) break; - temp = UncompressedBits + (((height - y) * Delta) + x); + temp = UncompressedBits + (height - y) * Delta; + if (is4bpp) + { + temp += x / 2; + if (i & 1) + c2 = c & 0x0F; + else + c2 = c >> 4; + if (x & 1) + *temp |= c2; + else + *temp |= c2 << 4; + } + else + { + temp += x; + *temp = c; + } x++; - *temp = c; } } else @@ -66,19 +78,36 @@ VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, case RLE_END: _SEH2_YIELD(return); case RLE_DELTA: - x += (*bits++) >> shift; - y -= (*bits++) >> shift; + x += *bits++; + y -= *bits++; break; default: - length = length >> shift; - while (length--) + for (i = 0; i < length; i++) { - c = *bits++; + if (!(is4bpp && i & 1)) + c = *bits++; + if (x < width) { - temp = UncompressedBits + (((height - y) * Delta) + x); + temp = UncompressedBits + (height - y) * Delta; + if (is4bpp) + { + temp += x / 2; + if (i & 1) + c2 = c & 0x0F; + else + c2 = c >> 4; + if (x & 1) + *temp |= c2; + else + *temp |= c2 << 4; + } + else + { + temp += x; + *temp = c; + } x++; - *temp = c; } } if ((bits - begin) & 1)