Evgeniy Boltik <bstsoft@narod.ru>
authorAleksey Bragin <aleksey@reactos.org>
Tue, 17 Mar 2009 18:00:28 +0000 (18:00 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Tue, 17 Mar 2009 18:00:28 +0000 (18:00 +0000)
- Rework 16bit DIB alphablend to do alpha operations in source's palette (32bpp) to obtain much better output quality without data loss.
See issue #3708 for more details.

svn path=/trunk/; revision=40074

reactos/subsystems/win32/win32k/dib/dib16bpp.c

index 5d33ef8..61f0506 100644 (file)
@@ -540,6 +540,12 @@ Clamp5(ULONG val)
     return (val > 31) ? 31 : val;
 }
 
+static __inline UCHAR
+Clamp8(ULONG val)
+{
+    return (val > 255) ? 255 : val;
+}
+
 static __inline UCHAR
 Clamp6(ULONG val)
 {
@@ -555,9 +561,13 @@ DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
     register PUSHORT Dst;
     ULONG DstDelta;
     BLENDFUNCTION BlendFunc;
-    register NICEPIXEL16 DstPixel;
-    register NICEPIXEL32 SrcPixel;
+    register NICEPIXEL16 SrcPixel16;
+    register NICEPIXEL16 DstPixel16;
+    register NICEPIXEL32 SrcPixel32;
+    register NICEPIXEL32 DstPixel32;
     UCHAR Alpha, SrcBpp;
+    XLATEGDI* XlateGDI;
+    XLATEOBJ* SrcXlateObj;
 
     DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
            SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
@@ -589,6 +599,21 @@ DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
         return FALSE;
     }
 
+    if (!ColorTranslation)
+    {
+        DPRINT1("ColorTranslation must not be NULL!\n");
+        return FALSE;
+    }
+
+    XlateGDI = ObjToGDI(ColorTranslation, XLATE);
+    SrcXlateObj = IntEngCreateXlate(0, 0, XlateGDI->SourcePal, XlateGDI->DestPal);
+
+    if (!SrcXlateObj)
+    {
+        DPRINT1("IntEngCreateXlate failed\n");
+        return FALSE;
+    }
+
     Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
           (DestRect->left << 1));
     DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
@@ -604,52 +629,61 @@ DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
         {
             if (SrcBpp <= 16)
             {
-                DstPixel.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
-                SrcPixel.col.red = (DstPixel.col.red << 3) | (DstPixel.col.red >> 2);
+                SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
+                SrcPixel32.col.red = (SrcPixel16.col.red << 3);
+                SrcPixel32.col.green = (SrcPixel16.col.green << 2);
+                SrcPixel32.col.blue = (SrcPixel16.col.blue << 3);
 
-                SrcPixel.col.green = (DstPixel.col.green << 2) |
-                                     (DstPixel.col.green >> 4);
+                SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
+                SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
+                SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
+                SrcPixel32.col.alpha = (SrcBpp == 32) ?
+                    (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
+                    BlendFunc.SourceConstantAlpha;
 
-                SrcPixel.col.blue = (DstPixel.col.blue << 3) | (DstPixel.col.blue >> 2);
-            }
-            else
-            {
-                SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
-            }
-            SrcPixel.col.red = SrcPixel.col.red *
-                               BlendFunc.SourceConstantAlpha / 255;
-
-            SrcPixel.col.green = SrcPixel.col.green *
-                                 BlendFunc.SourceConstantAlpha / 255;
-
-            SrcPixel.col.blue = SrcPixel.col.blue *
-                                BlendFunc.SourceConstantAlpha / 255;
-
-            SrcPixel.col.alpha = (SrcBpp == 32) ?
-                                 (SrcPixel.col.alpha *
-                                 BlendFunc.SourceConstantAlpha / 255) :
-                                 BlendFunc.SourceConstantAlpha;
+                Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
+                    SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
 
-            Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-                    SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
+                DstPixel16.us = *Dst;
+                DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
+                                   (SrcPixel32.col.red >> 3));
 
-         DstPixel.us = *Dst;
-         DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 +
-                                   (SrcPixel.col.red >> 3));
+                DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
+                                     (SrcPixel32.col.green >> 2));
 
-         DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 +
-                                     (SrcPixel.col.green >> 2));
+                DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
+                                    (SrcPixel32.col.blue >> 3));
 
-         DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 +
-                                    (SrcPixel.col.blue >> 3));
-
-         *Dst++ = DstPixel.us;
+                *Dst++ = DstPixel16.us;
+            }
+            else
+            {
+                SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
+
+                SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha  / 255;
+                SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha  / 255;
+                SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
+                SrcPixel32.col.alpha = (SrcBpp == 32) ?
+                    (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
+                    BlendFunc.SourceConstantAlpha;     
+
+                Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
+                    SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
+
+                DstPixel32.ul = XLATEOBJ_iXlate(SrcXlateObj, *Dst);
+                SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
+                SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
+                SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 +  SrcPixel32.col.blue);
+                *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
+            }
       }
 
       Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
       SrcY++;
     }
 
+    if (SrcXlateObj) EngDeleteXlate(SrcXlateObj);
+
     return TRUE;
 }