Author: fireball
Date: Wed Mar 3 23:33:50 2010
New Revision: 45810
URL:
http://svn.reactos.org/svn/reactos?rev=45810&view=rev
Log:
- GetBitmapBits and SetBitmapBits should get/set bitmaps bits in a particular format
described in MSDN, not in the format they are stored in internally. Reimplement them based
on winex11.drv implementation. Could use some optimisation, but they are deprecated non
time-critical functions. Thanks to Maarten Kroese for finding this problem. Fixes issue
#28 in Arwinss wiki.
Modified:
branches/arwinss/reactos/subsystems/win32/win32k/gre/surfobj.c
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gre/surfobj.c
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/gre/surfobj.c [iso-8859-1]
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/gre/surfobj.c [iso-8859-1] Wed Mar 3
23:33:50 2010
@@ -257,27 +257,224 @@
LONG FASTCALL
GreGetBitmapBits(PSURFACE pSurf, ULONG ulBytes, PVOID pBits)
{
- /* Don't copy more bytes than the buffer has */
- ulBytes = min(ulBytes, pSurf->SurfObj.cjBits);
-
- /* Copy actual bits */
- RtlCopyMemory(pBits, pSurf->SurfObj.pvBits, ulBytes);
-
- /* Return amount copied */
+ LONG height, width, bytewidth;
+ LPBYTE tbuf, startline;
+ int h, w;
+ COLORREF cr;
+ PFN_DIB_GetPixel DibGetPixel;
+
+ DPRINT("(bmp=%p, buffer=%p, count=0x%x)\n", pSurf, pBits, ulBytes);
+
+ /* Check ulBytes */
+ if (!ulBytes) return 0;
+
+ bytewidth = pSurf->SurfObj.lDelta;
+ if (bytewidth < 0) bytewidth = -bytewidth;
+
+ height = ulBytes / bytewidth;
+ width = pSurf->SurfObj.sizlBitmap.cx;
+
+ /* Get getpixel routine address */
+ DibGetPixel =
DibFunctionsForBitmapFormat[pSurf->SurfObj.iBitmapFormat].DIB_GetPixel;
+
+ /* copy bitmap to 16 bit padded image buffer with real bitsperpixel */
+ startline = pBits;
+ switch (BitsPerFormat(pSurf->SurfObj.iBitmapFormat))
+ {
+ case 1:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ *tbuf = 0;
+ for (w=0;w<width;w++)
+ {
+ if ((w%8) == 0)
+ *tbuf = 0;
+ cr = DibGetPixel(&pSurf->SurfObj, w, h);
+ *tbuf |= cr<<(7-(w&7));
+ if ((w&7) == 7) ++tbuf;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 4:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ if (!(w & 1))
+ *tbuf = DibGetPixel(&pSurf->SurfObj, w, h) << 4;
+ else
+ *tbuf++ |= DibGetPixel(&pSurf->SurfObj, w, h) & 0x0f;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 8:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ for (w=0;w<width;w++)
+ *tbuf++ = DibGetPixel(&pSurf->SurfObj, w, h);
+ startline += bytewidth;
+ }
+ break;
+ case 15:
+ case 16:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ long pixel = DibGetPixel(&pSurf->SurfObj, w, h);
+
+ *tbuf++ = pixel & 0xff;
+ *tbuf++ = (pixel>>8) & 0xff;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 24:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ long pixel = DibGetPixel(&pSurf->SurfObj, w, h);
+
+ *tbuf++ = pixel & 0xff;
+ *tbuf++ = (pixel>> 8) & 0xff;
+ *tbuf++ = (pixel>>16) & 0xff;
+ }
+ startline += bytewidth;
+ }
+ break;
+
+ case 32:
+ for (h=0;h<height;h++)
+ {
+ tbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ long pixel = DibGetPixel(&pSurf->SurfObj, w, h);
+
+ *tbuf++ = pixel & 0xff;
+ *tbuf++ = (pixel>> 8) & 0xff;
+ *tbuf++ = (pixel>>16) & 0xff;
+ *tbuf++ = (pixel>>24) & 0xff;
+ }
+ startline += bytewidth;
+ }
+ break;
+ default:
+ DPRINT1("Unhandled bits:%d\n",
BitsPerFormat(pSurf->SurfObj.iBitmapFormat));
+ }
return ulBytes;
}
LONG FASTCALL
GreSetBitmapBits(PSURFACE pSurf, ULONG ulBytes, PVOID pBits)
{
+ LONG height, width, bytewidth;
+ const BYTE *sbuf, *startline;
+ int h, w;
+ PFN_DIB_PutPixel DibPutPixel;
+
/* Check ulBytes */
if (!ulBytes) return 0;
- /* Don't copy more bytes than the surface has */
- ulBytes = min(ulBytes, pSurf->SurfObj.cjBits);
-
- /* Copy actual bits */
- RtlCopyMemory(pSurf->SurfObj.pvBits, pBits, ulBytes);
+ DPRINT("(bmp=%p, buffer=%p, count=0x%x)\n", pSurf, pBits, ulBytes);
+
+ bytewidth = pSurf->SurfObj.lDelta;
+ if (bytewidth < 0) bytewidth = -bytewidth;
+
+ height = ulBytes / bytewidth;
+ width = pSurf->SurfObj.sizlBitmap.cx;
+
+ /* Get getpixel routine address */
+ DibPutPixel =
DibFunctionsForBitmapFormat[pSurf->SurfObj.iBitmapFormat].DIB_PutPixel;
+
+ /* copy bitmap to 16 bit padded image buffer with real bitsperpixel */
+ startline = pBits;
+ switch (BitsPerFormat(pSurf->SurfObj.iBitmapFormat))
+ {
+ case 1:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ DibPutPixel(&pSurf->SurfObj, w, h, (sbuf[0]>>(7-(w&7)))
& 1);
+ if ((w&7) == 7)
+ sbuf++;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 4:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ if (!(w & 1))
+ DibPutPixel(&pSurf->SurfObj, w, h, *sbuf >> 4);
+ else
+ DibPutPixel(&pSurf->SurfObj, w, h, *sbuf++ & 0xf);
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 8:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ DibPutPixel(&pSurf->SurfObj, w, h, *sbuf++);
+ startline += bytewidth;
+ }
+ break;
+ case 15:
+ case 16:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ DibPutPixel(&pSurf->SurfObj, w, h, sbuf[1]*256+sbuf[0]);
+ sbuf+=2;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 24:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ DibPutPixel(&pSurf->SurfObj, w, h,
(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
+ sbuf += 3;
+ }
+ startline += bytewidth;
+ }
+ break;
+ case 32:
+ for (h=0;h<height;h++)
+ {
+ sbuf = startline;
+ for (w=0;w<width;w++)
+ {
+ DibPutPixel(&pSurf->SurfObj, w, h,
(sbuf[3]<<24)+(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
+ sbuf += 4;
+ }
+ startline += bytewidth;
+ }
+ break;
+ default:
+ DPRINT1("Unhandled bits:%d\n",
BitsPerFormat(pSurf->SurfObj.iBitmapFormat));
+ }
/* Return amount copied */
return ulBytes;