[ros-kernel] new RLE code
Jonathan Wilson
jonwil at tpgi.com.au
Tue Nov 18 12:09:42 CET 2003
This does fix some problems that we found.
But its still having the same crash errors.
I wrote a program that uses the decompress8bpp function from this patch to
decompress the bitmaps from welcome.exe and all the RLE compressed bitmaps
decompress fine in the test app (produce the same decompressed output as
Paint Shop Pro does)
-------------- next part --------------
Index: subsys/win32k/eng/surface.c
===================================================================
RCS file: /CVS/ReactOS/reactos/subsys/win32k/eng/surface.c,v
retrieving revision 1.26
diff -u -w -r1.26 surface.c
--- subsys/win32k/eng/surface.c 30 Oct 2003 08:56:38 -0000 1.26
+++ subsys/win32k/eng/surface.c 18 Nov 2003 04:04:14 -0000
@@ -43,6 +43,13 @@
#define NDEBUG
#include <win32k/debug1.h>
+enum Rle_EscapeCodes
+{
+ RLE_EOL = 0, /* End of line */
+ RLE_END = 1, /* End of bitmap */
+ RLE_DELTA = 2 /* Delta */
+};
+
INT FASTCALL BitsPerFormat(ULONG Format)
{
switch(Format)
@@ -161,6 +168,119 @@
return NewBitmap;
}
+VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
+{
+ int x = 0;
+ int y = Size.cy - 1;
+ int c;
+ int length;
+ int width = ((Size.cx+1)/2);
+ int height = Size.cy - 1;
+ BYTE *begin = CompressedBits;
+ BYTE *bits = CompressedBits;
+ BYTE *temp;
+ while (y >= 0)
+ {
+ length = *bits++ / 2;
+ if (length)
+ {
+ c = *bits++;
+ while (length--)
+ {
+ if (x >= width) break;
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ } else {
+ length = *bits++;
+ switch (length)
+ {
+ case RLE_EOL:
+ x = 0;
+ y--;
+ break;
+ case RLE_END:
+ return;
+ case RLE_DELTA:
+ x += (*bits++)/2;
+ y -= (*bits++)/2;
+ break;
+ default:
+ length /= 2;
+ while (length--)
+ {
+ c = *bits++;
+ if (x < width)
+ {
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ }
+ if ((bits - begin) & 1)
+ bits++;
+ }
+ }
+ }
+}
+
+VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta)
+{
+ int x = 0;
+ int y = Size.cy - 1;
+ int c;
+ int length;
+ int width = Size.cx;
+ int height = Size.cy - 1;
+ BYTE *begin = CompressedBits;
+ BYTE *bits = CompressedBits;
+ BYTE *temp;
+ while (y >= 0)
+ {
+ length = *bits++;
+ if (length)
+ {
+ c = *bits++;
+ while (length--)
+ {
+ if (x >= width) break;
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ } else {
+ length = *bits++;
+ switch (length)
+ {
+ case RLE_EOL:
+ x = 0;
+ y--;
+ break;
+ case RLE_END:
+ return;
+ case RLE_DELTA:
+ x += *bits++;
+ y -= *bits++;
+ break;
+ default:
+ while (length--)
+ {
+ c = *bits++;
+ if (x < width)
+ {
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ }
+ if ((bits - begin) & 1)
+ bits++;
+ }
+ }
+ }
+}
+
/*
* @implemented
*/
@@ -174,6 +294,8 @@
HBITMAP NewBitmap;
SURFOBJ *SurfObj;
SURFGDI *SurfGDI;
+ PVOID UncompressedBits;
+ ULONG UncompressedFormat;
NewBitmap = (PVOID)CreateGDIHandle(sizeof(SURFGDI), sizeof(SURFOBJ));
if( !ValidEngHandle( NewBitmap ) )
@@ -185,12 +307,30 @@
ASSERT( SurfGDI );
SurfGDI->BitsPerPixel = BitsPerFormat(Format);
+ if (Format == BMF_4RLE) {
+ SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
+ SurfObj->cjBits = SurfObj->lDelta * Size.cy;
+ UncompressedFormat = BMF_4BPP;
+ UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
+ Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, Width);
+ } else {
+ if (Format == BMF_8RLE) {
+ SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
+ SurfObj->cjBits = SurfObj->lDelta * Size.cy;
+ UncompressedFormat = BMF_8BPP;
+ UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0);
+ Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, Width);
+ } else {
SurfObj->lDelta = Width;
SurfObj->cjBits = SurfObj->lDelta * Size.cy;
+ UncompressedBits = Bits;
+ UncompressedFormat = Format;
+ }
+ }
- if(Bits!=NULL)
+ if(UncompressedBits!=NULL)
{
- SurfObj->pvBits = Bits;
+ SurfObj->pvBits = UncompressedBits;
} else
{
if(Flags & BMF_USERMEM)
@@ -209,12 +349,12 @@
SurfObj->dhsurf = 0; // device managed surface
SurfObj->hsurf = 0;
SurfObj->sizlBitmap = Size;
- SurfObj->iBitmapFormat = Format;
+ SurfObj->iBitmapFormat = UncompressedFormat;
SurfObj->iType = STYPE_BITMAP;
SurfObj->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
SurfObj->pvScan0 = SurfObj->pvBits;
- InitializeFuncs(SurfGDI, Format);
+ InitializeFuncs(SurfGDI, UncompressedFormat);
// Use flags to determine bitmap type -- TOP_DOWN or whatever
More information about the Ros-kernel
mailing list