You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.3 KiB
223 lines
5.3 KiB
/**************************************************************************\
|
|
*
|
|
* Copyright (c) 1999-2000 Microsoft Corporation
|
|
*
|
|
* Module name:
|
|
*
|
|
* The "AlphaMultiply" and "AlphaDivide" scan operations.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* See Gdiplus\Specs\ScanOperation.doc for an overview.
|
|
*
|
|
* These scan operations multiply/divide the color components by the alpha
|
|
* component. API-level input colors are (usually) specified in
|
|
* 'non-premultiplied'. Given a non-premultiplied
|
|
* color (R, G, B, A), its 'premultiplied' form is (RA, GA, BA, A).
|
|
*
|
|
* Notes:
|
|
*
|
|
* Since "AlphaMultiply" loses information, "AlphaDivide" is not a true
|
|
* inverse operation. (But it is an inverse if all pixels have an alpha of 1.)
|
|
*
|
|
* If the alpha is 0, "AlphaDivide" won't cause a divide-by-zero exception or
|
|
* do anything drastic. But it may do something random. Currently, the pixel
|
|
* value is unchanged. It could, instead, set the pixel to 0.
|
|
*
|
|
* Revision History:
|
|
*
|
|
* 12/14/1999 agodfrey
|
|
* Created it.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hpp"
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* Operation Description:
|
|
*
|
|
* AlphaMultiply/AlphaDivide: Convert between premultiplied and
|
|
* non-premultiplied alpha.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* dst - The destination scan
|
|
* src - The source scan
|
|
* count - The length of the scan, in pixels
|
|
* otherParams - Additional data. (Ignored.)
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
* Notes:
|
|
*
|
|
* !!![agodfrey] Currently we use 'Unpremultiply' from imgutils.cpp.
|
|
* While we may keep the tables and lookup in imgutils.cpp,
|
|
* it needs better naming, and we want the alpha=0 and alpha=255 cases in
|
|
* here, not out-of-line in imgutils.cpp.
|
|
*
|
|
* History:
|
|
*
|
|
* 12/14/1999 agodfrey
|
|
* Created it.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
ARGB Unpremultiply(ARGB argb);
|
|
|
|
// AlphaDivide from 32bpp PARGB
|
|
|
|
VOID FASTCALL
|
|
ScanOperation::AlphaDivide_sRGB(
|
|
VOID *dst,
|
|
const VOID *src,
|
|
INT count,
|
|
const OtherParams *otherParams
|
|
)
|
|
{
|
|
DEFINE_POINTERS(ARGB, ARGB)
|
|
|
|
while (count--)
|
|
{
|
|
sRGB::sRGBColor c;
|
|
c.argb = *s;
|
|
if (sRGB::isTranslucent(c.argb))
|
|
{
|
|
c.argb = Unpremultiply(c.argb);
|
|
}
|
|
*d = c.argb;
|
|
d++;
|
|
s++;
|
|
}
|
|
}
|
|
|
|
// !!![agodfrey] This should be sorted out. It should be out-of-line, and kept
|
|
// with its mates in imgutils.cpp (which should maybe move), but it
|
|
// shouldn't have a translucency check (we want to do that in
|
|
// AlphaMultiply_sRGB).
|
|
|
|
ARGB MyPremultiply(ARGB argb)
|
|
{
|
|
ARGB a = (argb >> ALPHA_SHIFT);
|
|
|
|
ARGB _000000gg = (argb >> 8) & 0x000000ff;
|
|
ARGB _00rr00bb = (argb & 0x00ff00ff);
|
|
|
|
ARGB _0000gggg = _000000gg * a + 0x00000080;
|
|
_0000gggg += (_0000gggg >> 8);
|
|
|
|
ARGB _rrrrbbbb = _00rr00bb * a + 0x00800080;
|
|
_rrrrbbbb += ((_rrrrbbbb >> 8) & 0x00ff00ff);
|
|
|
|
return (a << ALPHA_SHIFT) |
|
|
(_0000gggg & 0x0000ff00) |
|
|
((_rrrrbbbb >> 8) & 0x00ff00ff);
|
|
}
|
|
|
|
// AlphaMultiply from 32bpp ARGB
|
|
|
|
VOID FASTCALL
|
|
ScanOperation::AlphaMultiply_sRGB(
|
|
VOID *dst,
|
|
const VOID *src,
|
|
INT count,
|
|
const OtherParams *otherParams
|
|
)
|
|
{
|
|
DEFINE_POINTERS(ARGB, ARGB)
|
|
|
|
while (count--)
|
|
{
|
|
sRGB::sRGBColor c;
|
|
c.argb = *s;
|
|
ARGB alpha = c.argb & 0xff000000;
|
|
|
|
if (alpha != 0xff000000)
|
|
{
|
|
if (alpha != 0x00000000)
|
|
{
|
|
c.argb = MyPremultiply(c.argb);
|
|
}
|
|
else
|
|
{
|
|
c.argb = 0;
|
|
}
|
|
}
|
|
*d = c.argb;
|
|
d++;
|
|
s++;
|
|
}
|
|
}
|
|
|
|
// !!![agodfrey] We may want to round off, in both AlphaDivide_sRGB64 and
|
|
// AlphaMultiply_sRGB64.
|
|
|
|
// AlphaDivide from 64bpp PARGB
|
|
|
|
VOID FASTCALL
|
|
ScanOperation::AlphaDivide_sRGB64(
|
|
VOID *dst,
|
|
const VOID *src,
|
|
INT count,
|
|
const OtherParams *otherParams
|
|
)
|
|
{
|
|
DEFINE_POINTERS(ARGB64, ARGB64)
|
|
|
|
while (count--)
|
|
{
|
|
using namespace sRGB;
|
|
|
|
sRGB64Color c;
|
|
c.argb = *s;
|
|
if (isTranslucent64(c.a))
|
|
{
|
|
c.r = ((INT) c.r << SRGB_FRACTIONBITS) / c.a;
|
|
c.g = ((INT) c.g << SRGB_FRACTIONBITS) / c.a;
|
|
c.b = ((INT) c.b << SRGB_FRACTIONBITS) / c.a;
|
|
}
|
|
*d = c.argb;
|
|
d++;
|
|
s++;
|
|
}
|
|
}
|
|
|
|
// AlphaMultiply from 64bpp ARGB
|
|
|
|
VOID FASTCALL
|
|
ScanOperation::AlphaMultiply_sRGB64(
|
|
VOID *dst,
|
|
const VOID *src,
|
|
INT count,
|
|
const OtherParams *otherParams
|
|
)
|
|
{
|
|
DEFINE_POINTERS(ARGB64, ARGB64)
|
|
|
|
while (count--)
|
|
{
|
|
using namespace sRGB;
|
|
|
|
sRGB64Color c;
|
|
c.argb = *s;
|
|
if (c.a != SRGB_ONE)
|
|
{
|
|
if (c.a != 0)
|
|
{
|
|
c.r = ((INT) c.r * c.a) >> SRGB_FRACTIONBITS;
|
|
c.g = ((INT) c.g * c.a) >> SRGB_FRACTIONBITS;
|
|
c.b = ((INT) c.b * c.a) >> SRGB_FRACTIONBITS;
|
|
}
|
|
else
|
|
{
|
|
c.argb = 0;
|
|
}
|
|
}
|
|
*d = c.argb;
|
|
d++;
|
|
s++;
|
|
}
|
|
}
|
|
|