|
|
/**************************************************************************\
* * 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++; } }
|