static void overlayPixel(tuple const overlayTuple, struct pam * const overlayPamP, tuple const underlayTuple, struct pam * const underlayPamP, tuplen const alphaTuplen, bool const invertAlpha, bool const overlayHasOpacity, unsigned int const opacityPlane, tuple const composedTuple, struct pam * const composedPamP, float const masterOpacity, enum sampleScale const sampleScale) { float overlayWeight; overlayWeight = masterOpacity; /* initial value */ if (overlayHasOpacity) overlayWeight *= (float) overlayTuple[opacityPlane] / overlayPamP->maxval; if (alphaTuplen) { float const alphaval = invertAlpha ? (1.0 - alphaTuplen[0]) : alphaTuplen[0]; overlayWeight *= alphaval; } { unsigned int plane; for (plane = 0; plane < composedPamP->depth; ++plane) composedTuple[plane] = composeComponents(overlayTuple[plane], underlayTuple[plane], overlayWeight, composedPamP->maxval, sampleScale); } }
static void overlayPixel(tuple const overlayTuple, struct pam * const overlayPamP, tuple const underlayTuple, struct pam * const underlayPamP, tuplen const alphaTuplen, bool const invertAlpha, tuple const composedTuple, struct pam * const composedPamP, float const masterOpacity, enum sampleScale const sampleScale, enum alphaMix const alphaMix) { /*---------------------------------------------------------------------------- Generate the result of overlaying one pixel with another, taking opacity into account, viz overlaying 'underlayTuple' with 'overlayTuple'. 'overlayPamP' and 'underlayPamP', respectively, describe those tuples. We always assume the underlay pixel is opaque. We use the following declarations of the opacity of the overlay pixel in deciding how much of the underlay pixel should show through. The product of all the indicated opacity factors is the overall opacity factor, where an opacity factor is a real number from 0 to 1 and 1 means none of the underlay pixel shows through and 0 means the overlay pixel is invisible and the underlay pixel shows through in full force. if *overlayPamP may indicate that 'overlayTuple' has an opacity component. 'alphaTuplen' is a normalized tuple whose first sample is the opacity factor, except that iff 'invertAlpha' is true, it is a transparency factor instead (opacity = 1 - transparency). 'masterOpacity' is a direct opacity factor 'sampleScale' tells whether the samples in the tuples are proportional to brightness or light intensity (gamma-adjusted or not). Opacity factors apply to brightness (.5 means half the brightness of the result comes from the underlay pixel, half comes from the overlay). 'alphaMix' tells how to determine the opacity of the result pixel. Return the result as 'composedTuple', which has the form described by 'composedPamP'. -----------------------------------------------------------------------------*/ float overlayWeight; float underlayWeight; /* Part of formula for AM_OVERLAY -- see explanation above */ float composedWeight; /* Part of formula for AM_OVERLAY -- see explanation above */ overlayWeight = masterOpacity; /* initial value */ if (overlayPamP->have_opacity) overlayWeight *= (float) overlayTuple[overlayPamP->opacity_plane] / overlayPamP->maxval; if (alphaTuplen) { float const alphaval = invertAlpha ? (1.0 - alphaTuplen[0]) : alphaTuplen[0]; overlayWeight *= alphaval; } if (underlayPamP->have_opacity && alphaMix == AM_OVERLAY) { struct pam * const uPamP = underlayPamP; struct pam * const oPamP = overlayPamP; sample const uOpacity = underlayTuple[uPamP->opacity_plane]; sample const oOpacity = overlayTuple[oPamP->opacity_plane]; sample const uMaxval = uPamP->maxval; sample const oMaxval = oPamP->maxval; float const uOpacityN = uOpacity / uMaxval; float const oOpacityN = oOpacity / oMaxval; float const composedTrans = (1.0 - uOpacityN) * (1.0 * oOpacityN); if (composedTrans > .999) { underlayWeight = 1.0; composedWeight = 1.0; } else { underlayWeight = uOpacityN; composedWeight = 1.0 / (1.0 - composedTrans); } } else { underlayWeight = 1.0; composedWeight = 1.0; } { unsigned int plane; for (plane = 0; plane < composedPamP->color_depth; ++plane) composedTuple[plane] = composeComponents(overlayTuple[plane], underlayTuple[plane], overlayWeight, underlayWeight, composedWeight, composedPamP->maxval, sampleScale); if (composedPamP->have_opacity) composedTuple[composedPamP->opacity_plane] = composedOpacity(underlayTuple, underlayPamP, overlayTuple, overlayPamP, composedPamP, alphaMix); } }