Esempio n. 1
0
static void
analyzeDistribution(struct pam *          const inpamP,
                    bool                  const verbose,
                    const unsigned int ** const histogramP,
                    struct range *        const rangeP) {
/*----------------------------------------------------------------------------
   Find the distribution of the sample values -- minimum, maximum, and
   how many of each value -- in input image *inpamP, whose file is
   positioned to the raster.

   Return the minimum and maximum as *rangeP and the frequency
   distribution as *histogramP, an array such that histogram[i] is the
   number of pixels that have sample value i.

   Assume the file is positioned to the raster upon entry and leave
   it positioned at the same place.
-----------------------------------------------------------------------------*/
    unsigned int row;
    tuple * inrow;
    tuplen * inrown;
    unsigned int * histogram;  /* malloced array */
    unsigned int i;

    pm_filepos rasterPos;      /* Position in input file of the raster */

    pm_tell2(inpamP->file, &rasterPos, sizeof(rasterPos));

    inrow = pnm_allocpamrow(inpamP);
    inrown = pnm_allocpamrown(inpamP);
    MALLOCARRAY(histogram, inpamP->maxval+1);
    if (histogram == NULL)
        pm_error("Unable to allocate space for %lu-entry histogram",
                 inpamP->maxval+1);

    /* Initialize histogram -- zero occurrences of everything */
    for (i = 0; i <= inpamP->maxval; ++i)
        histogram[i] = 0;

    initRange(rangeP);

    for (row = 0; row < inpamP->height; ++row) {
        unsigned int col;
        pnm_readpamrow(inpamP, inrow);
        pnm_normalizeRow(inpamP, inrow, NULL, inrown);
        for (col = 0; col < inpamP->width; ++col) {
            ++histogram[inrow[col][0]];
            addToRange(rangeP, inrown[col][0]);
        }
    }
    *histogramP = histogram;

    pnm_freepamrow(inrow);
    pnm_freepamrown(inrown);

    pm_seek2(inpamP->file, &rasterPos, sizeof(rasterPos));

    if (verbose)
        pm_message("Pixel values range from %f to %f",
                   rangeP->min, rangeP->max);
}
Esempio n. 2
0
int
main(int argc, char **argv) {

    struct cmdlineInfo cmdline;
    struct pam pam;
    int row;
    double normalizer;
    tuplen * tuplerown;
    
    pnm_init(&argc, argv);
   
    parseCommandLine(argc, argv, &cmdline);

    pam.size        = sizeof(pam);
    pam.len         = PAM_STRUCT_SIZE(tuple_type);
    pam.file        = stdout;
    pam.format      = PAM_FORMAT;
    pam.plainformat = 0;
    pam.width       = cmdline.width;
    pam.height      = cmdline.height;
    pam.depth       = 1;
    pam.maxval      = cmdline.maxval;
    strcpy(pam.tuple_type, cmdline.tupletype);

    normalizer = imageNormalizer(&pam, cmdline.sigma);
    
    pnm_writepaminit(&pam);
   
    tuplerown = pnm_allocpamrown(&pam);

    for (row = 0; row < pam.height; ++row) {
        int col;
        for (col = 0; col < pam.width; ++col) {
            double const gauss1 = gauss(distFromCenter(&pam, col, row),
                                        cmdline.sigma);

            tuplerown[col][0] = gauss1 * normalizer;
        }
        pnm_writepamrown(&pam, tuplerown);
    }
    
    pnm_freepamrown(tuplerown);

    return 0;
}
Esempio n. 3
0
static void
composite(int          const originleft, 
          int          const origintop, 
          struct pam * const underlayPamP,
          struct pam * const overlayPamP,
          struct pam * const alphaPamP,
          bool         const invertAlpha,
          float        const masterOpacity,
          struct pam * const composedPamP,
          bool         const assumeLinear,
          bool         const mixTransparency) {
/*----------------------------------------------------------------------------
   Overlay the overlay image in the array 'overlayImage', described by
   *overlayPamP, onto the underlying image from the input image file
   as described by *underlayPamP, output the composite to the image
   file as described by *composedPamP.

   Apply the overlay image with transparency described by the array
   'alpha' and *alphaPamP.

   The underlying image is positioned after its header.

   'originleft' and 'origintop' are the coordinates in the underlying
   image plane where the top left corner of the overlay image is to
   go.  It is not necessarily inside the underlying image (in fact,
   may be negative).  Only the part of the overlay that actually
   intersects the underlying image, if any, gets into the output.

   We assume that the span from the topmost row of the two images to
   the bottommost row is less than INT_MAX.
-----------------------------------------------------------------------------*/
    enum sampleScale const sampleScale = 
        assumeLinear ? INTENSITY_SAMPLE : GAMMA_SAMPLE;
    enum alphaMix const alphaMix =
        mixTransparency ? AM_OVERLAY : AM_KEEPUNDER;

    int underlayRow;  /* NB may be negative */
    int overlayRow;   /* NB may be negative */
    tuple * composedTuplerow;
    tuple * underlayTuplerow;
    struct pam adaptUnderlayPam;
    tuple * overlayTuplerow;
    struct pam adaptOverlayPam;
    tuplen * alphaTuplerown;

    composedTuplerow = pnm_allocpamrow(composedPamP);
    underlayTuplerow = pnm_allocpamrow(underlayPamP);
    overlayTuplerow  = pnm_allocpamrow(overlayPamP);
    if (alphaPamP)
        alphaTuplerown = pnm_allocpamrown(alphaPamP);
    else
        alphaTuplerown = NULL;

    determineInputAdaptations(underlayPamP, overlayPamP, composedPamP,
                              &adaptUnderlayPam, &adaptOverlayPam);

    pnm_writepaminit(composedPamP);

    assert(INT_MAX - overlayPamP->height > origintop); /* arg constraint */

    for (underlayRow = MIN(0, origintop), overlayRow = MIN(0, -origintop);
         underlayRow < MAX(underlayPamP->height, 
                           origintop + overlayPamP->height);
         ++underlayRow, ++overlayRow) {

        if (overlayRow >= 0 && overlayRow < overlayPamP->height) {
            pnm_readpamrow(overlayPamP, overlayTuplerow);
            adaptRowFormat(overlayPamP, &adaptOverlayPam, overlayTuplerow);
            if (alphaPamP)
                pnm_readpamrown(alphaPamP, alphaTuplerown);
        }
        if (underlayRow >= 0 && underlayRow < underlayPamP->height) {
            pnm_readpamrow(underlayPamP, underlayTuplerow);
            adaptRowFormat(underlayPamP, &adaptUnderlayPam, underlayTuplerow);
            if (underlayRow < origintop || 
                underlayRow >= origintop + overlayPamP->height) {
            
                /* Overlay image does not touch this underlay row. */

                pnm_writepamrow(composedPamP, underlayTuplerow);
            } else {
                composeRow(originleft, &adaptUnderlayPam, &adaptOverlayPam,
                           invertAlpha, masterOpacity, 
                           composedPamP, sampleScale, alphaMix,
                           underlayTuplerow, overlayTuplerow, alphaTuplerown,
                           composedTuplerow);
                
                pnm_writepamrow(composedPamP, composedTuplerow);
            }
        }
    }
    pnm_freepamrow(composedTuplerow);
    pnm_freepamrow(underlayTuplerow);
    pnm_freepamrow(overlayTuplerow);
    if (alphaPamP)
        pnm_freepamrown(alphaTuplerown);
}
Esempio n. 4
0
static void
composite(int          const originleft, 
          int          const origintop, 
          struct pam * const underlayPamP,
          struct pam * const overlayPamP,
          struct pam * const alphaPamP,
          bool         const invertAlpha,
          float        const masterOpacity,
          struct pam * const composedPamP,
          bool         const assumeLinear) {
/*----------------------------------------------------------------------------
   Overlay the overlay image in the array 'overlayImage', described by
   *overlayPamP, onto the underlying image from the input image file
   as described by *underlayPamP, output the composite to the image
   file as described by *composedPamP.

   Apply the overlay image with transparency described by the array
   'alpha' and *alphaPamP.

   The underlying image is positioned after its header.

   'originleft' and 'origintop' are the coordinates in the underlying
   image plane where the top left corner of the overlay image is to
   go.  It is not necessarily inside the underlying image (in fact,
   may be negative).  Only the part of the overlay that actually
   intersects the underlying image, if any, gets into the output.
-----------------------------------------------------------------------------*/
    enum sampleScale const sampleScale = 
        assumeLinear ? INTENSITY_SAMPLE : GAMMA_SAMPLE;

    int underlayRow;  /* NB may be negative */
    int overlayRow;   /* NB may be negative */
    tuple * composedTuplerow;
    tuple * underlayTuplerow;
    tuple * overlayTuplerow;
    tuplen * alphaTuplerown;
    bool overlayHasOpacity;
    unsigned int opacityPlane;

    pnm_getopacity(overlayPamP, &overlayHasOpacity, &opacityPlane);

    composedTuplerow = pnm_allocpamrow(composedPamP);
    underlayTuplerow = pnm_allocpamrow(underlayPamP);
    overlayTuplerow  = pnm_allocpamrow(overlayPamP);
    if (alphaPamP)
        alphaTuplerown = pnm_allocpamrown(alphaPamP);

    pnm_writepaminit(composedPamP);

    for (underlayRow = MIN(0, origintop), overlayRow = MIN(0, -origintop);
         underlayRow < MAX(underlayPamP->height, 
                           origintop + overlayPamP->height);
         ++underlayRow, ++overlayRow) {

        if (overlayRow >= 0 && overlayRow < overlayPamP->height) {
            pnm_readpamrow(overlayPamP, overlayTuplerow);
            adaptRowToOutputFormat(overlayPamP, overlayTuplerow, composedPamP);
            if (alphaPamP)
                pnm_readpamrown(alphaPamP, alphaTuplerown);
        }
        if (underlayRow >= 0 && underlayRow < underlayPamP->height) {
            pnm_readpamrow(underlayPamP, underlayTuplerow);
            adaptRowToOutputFormat(underlayPamP, underlayTuplerow, 
                                   composedPamP);

            if (underlayRow < origintop || 
                underlayRow >= origintop + overlayPamP->height) {
            
                /* Overlay image does not touch this underlay row. */

                pnm_writepamrow(composedPamP, underlayTuplerow);
            } else {
                unsigned int col;
                for (col = 0; col < composedPamP->width; ++col) {
                    int const ovlcol = col - originleft;

                    if (ovlcol >= 0 && ovlcol < overlayPamP->width) {
                        tuplen const alphaTuplen = 
                            alphaPamP ? alphaTuplerown[ovlcol] : NULL;

                        overlayPixel(overlayTuplerow[ovlcol], overlayPamP,
                                     underlayTuplerow[col], underlayPamP,
                                     alphaTuplen, invertAlpha,
                                     overlayHasOpacity, opacityPlane,
                                     composedTuplerow[col], composedPamP,
                                     masterOpacity, sampleScale);
                    } else
                        /* Overlay image does not touch this column. */
                        pnm_assigntuple(composedPamP, composedTuplerow[col],
                                        underlayTuplerow[col]);
                }
                pnm_writepamrow(composedPamP, composedTuplerow);
            }
        }
    }
    pnm_freepamrow(composedTuplerow);
    pnm_freepamrow(underlayTuplerow);
    pnm_freepamrow(overlayTuplerow);
    if (alphaPamP)
        pnm_freepamrown(alphaTuplerown);
}