Evgeniy Boltik <bstsoft@narod.ru>

- 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
This commit is contained in:
Aleksey Bragin 2009-03-17 18:00:28 +00:00
parent cf3d6a794f
commit 64b42346d2

View 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);
Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
DstPixel16.us = *Dst;
DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
(SrcPixel32.col.red >> 3));
DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
(SrcPixel32.col.green >> 2));
DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
(SrcPixel32.col.blue >> 3));
*Dst++ = DstPixel16.us;
}
else
{
SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
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);
}
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) ?
SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
DstPixel.us = *Dst;
DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 +
(SrcPixel.col.red >> 3));
DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 +
(SrcPixel.col.green >> 2));
DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 +
(SrcPixel.col.blue >> 3));
*Dst++ = DstPixel.us;
}
Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
SrcY++;
}
if (SrcXlateObj) EngDeleteXlate(SrcXlateObj);
return TRUE;
}