Ejemplo n.º 1
0
static sample
composeComponents(sample           const compA, 
                  sample           const compB,
                  float            const distrib,
                  float            const aFactor,
                  float            const composedFactor,
                  sample           const maxval,
                  enum sampleScale const sampleScale) {
/*----------------------------------------------------------------------------
  Compose a single color component of each of two pixels, with 'distrib' being
  the fraction of 'compA' in the result, 1-distrib the fraction of 'compB'.
  Note that this does not apply to an opacity component.

  'sampleScale' tells in what domain the 'distrib' fraction applies:
  brightness or light intensity (gamma-adjusted or not).

  'aFactor' is a factor in [0,1] to apply to 'compA' first.

  'composedFactor' is a factor to apply to the result.

  See above for explanation of why 'aFactor' and 'composedFactor' are
  useful.

  The inputs and result are based on a maxval of 'maxval'.
  
  Note that while 'distrib' in the straightforward case is always in
  [0,1], it can in fact be negative or greater than 1.  We clip the
  result as required to return a legal sample value.
-----------------------------------------------------------------------------*/
    sample retval;

    if (fabs(distrib) > .999 && aFactor > .999 && composedFactor > .999)
        /* Fast path for common case */
        retval = compA;
    else {
        if (sampleScale == INTENSITY_SAMPLE) {
            sample const mix = 
                ROUNDU(compA * aFactor * distrib + compB * (1.0 - distrib));
            retval = MIN(maxval, MAX(0, mix));
        } else {
            float const compANormalized = (float)compA/maxval;
            float const compBNormalized = (float)compB/maxval;
            float const compALinear = pm_ungamma709(compANormalized);
            float const compBLinear = pm_ungamma709(compBNormalized);
            float const compALinearAdj = compALinear * aFactor;
            float const mix = 
                compALinearAdj * distrib + compBLinear * (1.0 - distrib)
                * composedFactor;
            sample const sampleValue = ROUNDU(pm_gamma709(mix) * maxval);
            retval = MIN(maxval, MAX(0, sampleValue));
        }
    }
    return retval;
}
Ejemplo n.º 2
0
static sample
composeComponents(sample           const compA, 
                  sample           const compB,
                  float            const distrib,
                  sample           const maxval,
                  enum sampleScale const sampleScale) {
/*----------------------------------------------------------------------------
  Compose a single component of each of two pixels, with 'distrib' being
  the fraction of 'compA' in the result, 1-distrib the fraction of 'compB'.
  
  The inputs and result are based on a maxval of 'maxval'.
  
  Note that while 'distrib' in the straightforward case is always in
  [0,1], it can in fact be negative or greater than 1.  We clip the
  result as required to return a legal sample value.
-----------------------------------------------------------------------------*/
    sample retval;

    if (fabs(1.0-distrib) < .001)
        /* Fast path for common case */
        retval = compA;
    else {
        if (sampleScale == INTENSITY_SAMPLE) {
            sample const mix = 
                ROUNDU(compA * distrib + compB * (1.0 - distrib));
            retval = MIN(maxval, MAX(0, mix));
        } else {
            float const compANormalized = (float)compA/maxval;
            float const compBNormalized = (float)compB/maxval;
            float const compALinear = pm_ungamma709(compANormalized);
            float const compBLinear = pm_ungamma709(compBNormalized);
            float const mix = 
                compALinear * distrib + compBLinear * (1.0 - distrib);
            sample const sampleValue = ROUNDU(pm_gamma709(mix) * maxval);
            retval = MIN(maxval, MAX(0, sampleValue));
        }
    }
    return retval;
}
Ejemplo n.º 3
0
static struct converter
createClusterConverter(struct pam *    const graypamP,
                       enum ditherType const ditherType,
                       unsigned int    const radius) {
    
    /* TODO: We create a floating point normalized, gamma-adjusted
       dither matrix from the old integer dither matrices that were 
       developed for use with integer arithmetic.  We really should
       just change the literal values in dither.h instead of computing
       the matrix from the integer literal values here.
    */
    
    int const clusterNormalizer = radius * radius * 2;
    unsigned int const diameter = 2 * radius;

    struct converter converter;
    struct clusterState * stateP;
    unsigned int row;

    converter.cols       = graypamP->width;
    converter.convertRow = &clusterConvertRow;
    converter.destroy    = &clusterDestroy;

    MALLOCVAR_NOFAIL(stateP);

    stateP->radius = radius;

    MALLOCARRAY_NOFAIL(stateP->clusterMatrix, diameter);
    for (row = 0; row < diameter; ++row) {
        unsigned int col;

        MALLOCARRAY_NOFAIL(stateP->clusterMatrix[row], diameter);
        
        for (col = 0; col < diameter; ++col) {
            switch (ditherType) {
            case DT_REGULAR: 
                switch (radius) {
                case 8: 
                    stateP->clusterMatrix[row][col] = 
                        pm_gamma709((float)dither8[row][col] / 256);
                    break;
                default: 
                    pm_error("INTERNAL ERROR: invalid radius");
                }
                break;
            case DT_CLUSTER: {
                int val;
                switch (radius) {
                case 3: val = cluster3[row][col]; break;
                case 4: val = cluster4[row][col]; break;
                case 8: val = cluster8[row][col]; break;
                default:
                    pm_error("INTERNAL ERROR: invalid radius");
                }
                stateP->clusterMatrix[row][col] = 
                    pm_gamma709((float)val / clusterNormalizer);
            }
            break;
            }
        }
    }            

    converter.stateP = stateP;

    return converter;
}