Пример #1
0
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);
    }
}
Пример #2
0
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);
    }
}