Esempio n. 1
0
tuplehash
pnm_computetupletablehash(struct pam * const pamP, 
                          tupletable   const tupletable,
                          unsigned int const tupletableSize) {
/*----------------------------------------------------------------------------
   Create a tuple hash containing indices into the tuple table
   'tupletable'.  The hash index for the hash is the value of a tuple;
   the hash value is the tuple table index for the element in the
   tuple table that contains that tuple value.

   Assume there are no duplicate tuple values in the tuple table.

   We allocate space for the main hash table and all the elements of the
   hash chains.
-----------------------------------------------------------------------------*/
    tuplehash tupletablehash;
    unsigned int i;
    bool fits;
    
    tupletablehash = pnm_createtuplehash();

    fits = TRUE;  /* initial assumption */
    for (i = 0; i < tupletableSize && fits; ++i) {
        pnm_addtotuplehash(pamP, tupletablehash, 
                           tupletable[i]->tuple, i, &fits);
    }
    if (!fits) {
        pnm_destroytuplehash(tupletablehash);
        pm_error("Out of memory computing tuple hash from tuple table");
    }
    return tupletablehash;
}
Esempio n. 2
0
static void
computehashrecoverable(struct pam *   const pamP,
                       tuple **       const tupleArray, 
                       unsigned int   const maxsize, 
                       sample         const newMaxval,
                       unsigned int * const sizeP,
                       tuplehash *    const tuplefreqhashP,
                       tuple **       const rowbufferP,
                       tuple *        const colorP) {
/*----------------------------------------------------------------------------
   This is computetuplefreqhash(), only it leaves a trail so that if it
   happens to longjmp out because of a failed memory allocation, the
   setjmp'er can cleanup whatever it had done so far.
-----------------------------------------------------------------------------*/
    unsigned int row;
    struct pam freqPam;
    bool full;

    freqPam = *pamP;
    freqPam.maxval = newMaxval;

    *tuplefreqhashP = pnm_createtuplehash();
    *sizeP = 0;   /* initial value */
    
    *rowbufferP = pnm_allocpamrow(pamP);
    
    *colorP = pnm_allocpamtuple(&freqPam);
    
    full = FALSE;  /* initial value */
    
    /* Go through the entire raster, building a hash table of
       tuple values. 
    */
    for (row = 0; row < pamP->height && !full; ++row) {
        int col;
        const tuple * tuplerow;  /* The row of tuples we are processing */
        
        if (tupleArray)
            tuplerow = tupleArray[row];
        else {
            pnm_readpamrow(pamP, *rowbufferP);
            tuplerow = *rowbufferP;
        }
        for (col = 0; col < pamP->width && !full; ++col) {
            pnm_scaletuple(pamP, *colorP, tuplerow[col], freqPam.maxval);
            addColorOccurrenceToHash(
                *colorP, *tuplefreqhashP, &freqPam, maxsize, sizeP, &full);
        }
    }

    pnm_freepamtuple(*colorP); *colorP = NULL;
    pnm_freepamrow(*rowbufferP); *rowbufferP = NULL;

    if (full) {
        pnm_destroytuplehash(*tuplefreqhashP);
        *tuplefreqhashP = NULL;
    }
}
Esempio n. 3
0
static void
makeReverseLookupHash(struct pam * const lookuppamP,
                      tuple **     const lookup,
                      tuplehash *  const hashP) {
/*----------------------------------------------------------------------------
   Create a tuple hash that maps each tuple values in the first row of
   'lookup' to the number of the column in which it appears.

   Abort the program with an error if the same tuple value occurs in two
   columns of the first row.
-----------------------------------------------------------------------------*/
    tuplehash hash;
    unsigned int col;

    hash = pnm_createtuplehash();

    for (col = 0; col < lookuppamP->width; ++col) {
        tuple const thisValue = lookup[0][col];
        
        int found;
        int priorValue;

        pnm_lookuptuple(lookuppamP, hash, thisValue, &found, &priorValue);

        if (found)
            pm_error("Same tuple value occurs in both Column %u and "
                     "Column %u of the lookup image", priorValue, col);
        else {
            int fits;
            pnm_addtotuplehash(lookuppamP, hash, lookup[0][col], col, &fits);

            if (!fits)
                pm_error("Out of memory constructing hash of lookup table");
        }
    }

    *hashP = hash;
}
Esempio n. 4
0
static void
copyRaster(struct pam *       const inpamP, 
           struct pam *       const outpamP,
           tupletable         const colormap, 
           unsigned int       const colormapSize,
           bool               const floyd, 
           bool               const randomize,
           tuple              const defaultColor, 
           unsigned int *     const missingCountP) {

    tuplehash const colorhash = pnm_createtuplehash();

    tuple * inrow;
    tuple * outrow;
    struct pam workpam;
        /* This is for work space we use for building up the output
           pixels.  To save time and memory, we modify them in place in a
           buffer, which ultimately holds the output pixels.  This pam
           structure is thus the same as the *outpamP, but with a tuple
           allocation depth large enough to handle intermediate results.
        */
    depthAdjustment depthAdjustment;
    struct colormapFinder * colorFinderP;
    bool usehash;
    struct fserr fserr;
    int row;

    workpam = *outpamP;
    workpam.allocation_depth = MAX(workpam.depth, inpamP->depth);
    workpam.size             = sizeof(workpam);
    workpam.len              = PAM_STRUCT_SIZE(allocation_depth);

    inrow  = pnm_allocpamrow(inpamP);
    outrow = pnm_allocpamrow(&workpam);

    if (outpamP->maxval != inpamP->maxval && defaultColor)
        pm_error("The maxval of the colormap (%u) is not equal to the "
                 "maxval of the input image (%u).  This is allowable only "
                 "if you are doing an approximate mapping (i.e. you don't "
                 "specify -firstisdefault or -missingcolor)",
                 (unsigned int)outpamP->maxval, (unsigned int)inpamP->maxval);

    selectDepthAdjustment(inpamP, outpamP->depth, &depthAdjustment);

    usehash = TRUE;

    createColormapFinder(outpamP, colormap, colormapSize, &colorFinderP);

    if (floyd)
        initFserr(inpamP, &fserr, randomize);

    *missingCountP = 0;  /* initial value */

    for (row = 0; row < inpamP->height; ++row) {
        unsigned int missingCount;

        pnm_readpamrow(inpamP, inrow);

        convertRow(inpamP, &workpam, inrow,
                   depthAdjustment, colormap, colorFinderP, colorhash,
                   &usehash, floyd, defaultColor,
                   &fserr,  outrow, &missingCount);
        
        *missingCountP += missingCount;
        
        pnm_writepamrow(outpamP, outrow);
    }
    destroyColormapFinder(colorFinderP);
    pnm_freepamrow(inrow);
    pnm_freepamrow(outrow);
    pnm_destroytuplehash(colorhash);
}
Esempio n. 5
0
static void
computeHistogram(FILE *         const ifP,
                 int *          const formatP,
                 struct pam *   const freqPamP,
                 tupletable2 *  const colorfreqtableP) {
/*----------------------------------------------------------------------------
  Make a histogram of the colors in the image stream in the file '*ifP'.
  
  Return as *freqPamP a description of the tuple values in the histogram.
  Only the fields of *freqPamP that describe individual tuples are
  meaningful (depth, maxval, tuple type);

  As a fringe benefit, also return the format of the input file as
  *formatP.
----------------------------------------------------------------------------*/
    unsigned int imageSeq;
    struct pam firstPam;
    tuplehash tuplehash;
    unsigned int colorCount;
    int eof;
    
    pm_message("making histogram...");

    tuplehash = pnm_createtuplehash();
    colorCount = 0;

    eof = FALSE;

    for (imageSeq = 0; !eof; ++imageSeq) {
        struct pam inpam;
        
        pm_message("Scanning image %u", imageSeq);

        pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));

        if (imageSeq == 0)
            firstPam = inpam;
        else
            validateCompatibleImage(&inpam, &firstPam, imageSeq);
    
        addImageColorsToHash(&inpam, tuplehash, &colorCount);

        pm_message("%u colors so far", colorCount);

        pnm_nextimage(ifP, &eof);
    }
    colorfreqtableP->table =
        pnm_tuplehashtotable(&firstPam, tuplehash, colorCount);
    colorfreqtableP->size = colorCount;

    pnm_destroytuplehash(tuplehash);

    pm_message("%u colors found", colorfreqtableP->size);
    
    freqPamP->size   = sizeof(*freqPamP);
    freqPamP->len    = PAM_STRUCT_SIZE(tuple_type);
    freqPamP->maxval = firstPam.maxval;
    freqPamP->bytes_per_sample = pnm_bytespersample(freqPamP->maxval);
    freqPamP->depth  = firstPam.depth;
    STRSCPY(freqPamP->tuple_type, firstPam.tuple_type);
    
    *formatP = firstPam.format;
}