[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