Example #1
0
static void
determineBackgroundColor(struct pam * const pamP,
                         bool         const verbose,
                         tuple *      const bgColorP) {
/*----------------------------------------------------------------------------
   Determine what color is the background color of the image in the
   file represented by *pamP.

   Expect the file to be positioned to the start of the raster, and leave
   it positioned arbitrarily.
-----------------------------------------------------------------------------*/
    unsigned int row;
    tuple * tuplerow;
    tuple ul, ur, ll, lr;
        /* Color of upper left, upper right, lower left, lower right */

    tuplerow  = pnm_allocpamrow(pamP);
    ul = pnm_allocpamtuple(pamP);
    ur = pnm_allocpamtuple(pamP);
    ll = pnm_allocpamtuple(pamP);
    lr = pnm_allocpamtuple(pamP);

    pnm_readpamrow(pamP, tuplerow);

    pnm_assigntuple(pamP, ul, tuplerow[0]);
    pnm_assigntuple(pamP, ur, tuplerow[pamP->width-1]);

    for (row = 1; row < pamP->height; ++row)
        pnm_readpamrow(pamP, tuplerow);

    pnm_assigntuple(pamP, ll, tuplerow[0]);
    pnm_assigntuple(pamP, lr, tuplerow[pamP->width-1]);

    selectBackground(pamP, ul, ur, ll, lr, bgColorP);

    if (verbose) {
        int const hexokTrue = 1;
        const char * const colorname =
            pnm_colorname(pamP, *bgColorP, hexokTrue);
        pm_message("Background color is %s", colorname);

        strfree(colorname);
    }

    pnm_freepamtuple(lr);
    pnm_freepamtuple(ll);
    pnm_freepamtuple(ur);
    pnm_freepamtuple(ul);
    pnm_freepamrow(tuplerow);
}
Example #2
0
static void
getSpecifiedMissingColor(struct pam * const pamP,
                         const char * const colorName,
                         tuple *      const specColorP) {

    tuple specColor;
                             
    specColor = pnm_allocpamtuple(pamP);

    if (colorName) {
        pixel const color = ppm_parsecolor(colorName, pamP->maxval);
        if (pamP->depth == 3) {
            specColor[PAM_RED_PLANE] = PPM_GETR(color);
            specColor[PAM_GRN_PLANE] = PPM_GETG(color);
            specColor[PAM_BLU_PLANE] = PPM_GETB(color);
        } else if (pamP->depth == 1) {
            specColor[0] = ppm_luminosity(color);
        } else {
            pm_error("You may not use -missing with a colormap that is not "
                     "of depth 1 or 3.  Yours has depth %u",
                     pamP->depth);
        }
    }
    *specColorP = specColor;
}
Example #3
0
static void
processMapFile(const char *   const mapFileName,
               struct pam *   const outpamCommonP,
               tupletable *   const colormapP,
               unsigned int * const colormapSizeP,
               tuple *        const firstColorP) {
/*----------------------------------------------------------------------------
   Read a color map from the file named 'mapFileName'.  It's a map that
   associates each color in that file with a unique whole number.  Return the
   map as *colormapP, with the number of entries in it as *colormapSizeP.

   Also determine the first color (top left) in the map file and return that
   as *firstColorP.
-----------------------------------------------------------------------------*/
    FILE * mapfile;
    struct pam mappam;
    tuple ** maptuples;
    tuple firstColor;

    mapfile = pm_openr(mapFileName);
    maptuples = pnm_readpam(mapfile, &mappam, PAM_STRUCT_SIZE(tuple_type));
    pm_close(mapfile);

    computeColorMapFromMap(&mappam, maptuples, colormapP, colormapSizeP);

    firstColor = pnm_allocpamtuple(&mappam);
    pnm_assigntuple(&mappam, firstColor, maptuples[0][0]);
    *firstColorP = firstColor;

    pnm_freepamarray(maptuples, &mappam);

    *outpamCommonP = mappam; 
    outpamCommonP->file = stdout;
}
Example #4
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;
    }
}
Example #5
0
static void
createWhiteTuple(const struct pam * const pamP, 
                 tuple *            const whiteTupleP) {
/*----------------------------------------------------------------------------
   Create a "white" tuple.  By that we mean a tuple all of whose elements
   are zero.  If it's an RGB, grayscale, or b&w pixel, that means it's black.
-----------------------------------------------------------------------------*/
    tuple whiteTuple;
    unsigned int plane;

    whiteTuple = pnm_allocpamtuple(pamP);

    for (plane = 0; plane < pamP->depth; ++plane)
        whiteTuple[plane] = pamP->maxval;

    *whiteTupleP = whiteTuple;
}
Example #6
0
static void
convertRowPsFilter(struct pam *     const pamP,
                   tuple *          const tuplerow,
                   struct bmepsoe * const bmepsoeP) {

    unsigned int const psMaxval = 255;
    unsigned int col;

    tuple scaledTuple;
    
    scaledTuple = pnm_allocpamtuple(pamP);

    for (col = 0; col < pamP->width; ++col) {
        unsigned int plane;
        pnm_scaletuple(pamP, scaledTuple, tuplerow[col], psMaxval);
        
        for (plane = 0; plane < pamP->depth; ++plane)
            outputBmepsSample(bmepsoeP, scaledTuple[plane]);
    }
    pnm_freepamtuple(scaledTuple);
}
Example #7
0
static void
putMapEntry(struct pam * const pamP, 
            tuple        const value, 
            int          const size) {

    if (size == 15 || size == 16) {
        /* 5 bits each of red, green, and blue.  Watch for byte order */

        tuple const tuple31 = pnm_allocpamtuple(pamP);

        pnm_scaletuple(pamP, tuple31, value, 31);
        {
            int const mapentry = 
                tuple31[PAM_BLU_PLANE] << 0 |
                tuple31[PAM_GRN_PLANE] << 5 |
                tuple31[PAM_RED_PLANE] << 10;
            
            putchar(mapentry % 256);
            putchar(mapentry / 256);
        }
        pnm_freepamtuple(tuple31);
    } else if (size == 8)
        putchar(pnm_scalesample(value[0], 
                                pamP->maxval, TGA_MAXVAL));
    else {
        /* Must be 24 or 32 */
        putchar(pnm_scalesample(value[PAM_BLU_PLANE], 
                                pamP->maxval, TGA_MAXVAL));
        putchar(pnm_scalesample(value[PAM_GRN_PLANE], 
                                pamP->maxval, TGA_MAXVAL));
        putchar(pnm_scalesample(value[PAM_RED_PLANE], 
                                    pamP->maxval, TGA_MAXVAL));
        if (size == 32)
            putchar(pnm_scalesample(value[PAM_TRN_PLANE], 
                                    pamP->maxval, TGA_MAXVAL));
    }
}
Example #8
0
static void
selectBackground(struct pam * const pamP,
                 tuple        const ul,
                 tuple        const ur,
                 tuple        const lr,
                 tuple        const ll,
                 tuple *      const bgColorP) {

    tuple bg;  /* Reference to one of ul, ur, ll, lr */

    if (pnm_tupleequal(pamP, ul, ur) &&
        (pnm_tupleequal(pamP, ul, ll) ||
         pnm_tupleequal(pamP, ul, lr)))
        bg = ul;
    else if (pnm_tupleequal(pamP, ll, lr) &&
             pnm_tupleequal(pamP, lr, ul))
        bg = ll;
    else {
        /* No 3 corners are same color; look for 2 corners */
        if (pnm_tupleequal(pamP, ul, ur))  /* top edge */
            bg = ul;
        else if (pnm_tupleequal(pamP, ul, ll)) /* left edge */
            bg = ul;
        else if (pnm_tupleequal(pamP, ur, lr)) /* right edge */
            bg = ur;
        else if (pnm_tupleequal(pamP, ll, lr)) /* bottom edge */
            bg = ll;
        else {
            /* No two corners are same color; just use upper left corner */
            bg = ul;
        }
    }
    
    *bgColorP = pnm_allocpamtuple(pamP);
    pnm_assigntuple(pamP, *bgColorP, bg);
}
Example #9
0
static void
convertRowDither(struct pam *            const inpamP,
                 struct pam *            const outpamP,
                 tuple                   const inrow[],
                 depthAdjustment         const depthAdjustment,
                 tupletable              const colormap,
                 struct colormapFinder * const colorFinderP,
                 tuplehash               const colorhash, 
                 bool *                  const usehashP,
                 tuple                   const defaultColor,
                 struct fserr *          const fserrP,
                 tuple                         outrow[],
                 unsigned int *          const missingCountP) {
/*----------------------------------------------------------------------------
  Like convertRow(), compute outrow[] from inrow[], replacing each pixel with
  the new colors.  Do a Floyd-Steinberg dither, using and updating the error
  accumulator *fserrP.

  Return the number of pixels that were not matched in the color map as
  *missingCountP.

  *colorFinderP is a color finder based on 'colormap' -- it tells us what
  index of 'colormap' corresponds to a certain color.
-----------------------------------------------------------------------------*/
    tuple const ditheredTuple = pnm_allocpamtuple(inpamP);
        /* The input tuple we're converting, adjusted by the dither */
    tuple const normTuple = pnm_allocpamtuple(outpamP);
        /* Same as above, normalized to the maxval of the output file /
           colormap.
        */
    unsigned int missingCount;
    int col;

    floydInitRow(inpamP, fserrP);

    missingCount = 0;  /* initial value */
    
    for (col = fserrP->begCol; col != fserrP->endCol; col += fserrP->step) {
        bool missing;

        floydAdjustColor(inpamP, inrow[col], ditheredTuple, fserrP, col);

        /* Convert tuple to the form of those in the colormap */
        assert(outpamP->allocation_depth >= inpamP->depth);
        pnm_scaletuple(inpamP, normTuple, ditheredTuple, outpamP->maxval);
        adjustDepthTuple(normTuple, depthAdjustment);

        mapTuple(outpamP, normTuple, defaultColor,
                 colormap, colorFinderP,
                 colorhash, usehashP, outrow[col], &missing);

        if (missing)
            ++missingCount;

        /* Convert tuple back to the form of the input, where dithering
           takes place.
        */
        pnm_scaletuple(outpamP, normTuple, outrow[col], inpamP->maxval);
        inverseAdjustDepthTuple(normTuple, depthAdjustment);

        floydPropagateErr(inpamP, fserrP, col, inrow[col], normTuple);
    }

    floydSwitchDir(inpamP, fserrP);

    pnm_freepamtuple(normTuple);
    pnm_freepamtuple(ditheredTuple);

    *missingCountP = missingCount;
}
Example #10
0
static void
createRowCutter(const struct pam *  const inpamP,
                const struct pam *  const outpamP,
                int                 const leftcol,
                int                 const rightcol,
                struct rowCutter ** const rowCutterPP) {

    struct rowCutter * rowCutterP;
    tuple * inputPointers;
    tuple * outputPointers;
    tuple * copyTuples;
    tuple blackTuple;
    tuple discardTuple;
    int col;

    assert(inpamP->depth >= outpamP->depth);
        /* Entry condition.  If this weren't true, we could not simply
           treat an input tuple as an output tuple.
        */

    copyTuples   = pnm_allocpamrow(outpamP);
    discardTuple = pnm_allocpamtuple(inpamP);
    pnm_createBlackTuple(outpamP, &blackTuple);

    MALLOCARRAY_NOFAIL(inputPointers,  inpamP->width);
    MALLOCARRAY_NOFAIL(outputPointers, outpamP->width);

    /* Put in left padding */
    for (col = leftcol; col < 0 && col-leftcol < outpamP->width; ++col)
        outputPointers[col-leftcol] = blackTuple;

    /* Put in extracted columns */
    for (col = MAX(leftcol, 0);
         col <= MIN(rightcol, inpamP->width-1);
         ++col) {
        int const outcol = col - leftcol;

        inputPointers[col] = outputPointers[outcol] = copyTuples[outcol];
    }

    /* Put in right padding */
    for (col = MIN(rightcol, inpamP->width-1) + 1; col <= rightcol; ++col) {
        if (col - leftcol >= 0) {
            outputPointers[col-leftcol] = blackTuple;
        }
    }

    /* Direct input pixels that are getting cut off to the discard tuple */

    for (col = 0; col < MIN(leftcol, inpamP->width); ++col)
        inputPointers[col] = discardTuple;

    for (col = MAX(0, rightcol + 1); col < inpamP->width; ++col)
        inputPointers[col] = discardTuple;

    MALLOCVAR_NOFAIL(rowCutterP);

    rowCutterP->inputWidth     = inpamP->width;
    rowCutterP->outputWidth    = outpamP->width;
    rowCutterP->inputPointers  = inputPointers;
    rowCutterP->outputPointers = outputPointers;
    rowCutterP->copyTuples     = copyTuples;
    rowCutterP->discardTuple   = discardTuple;
    rowCutterP->blackTuple     = blackTuple;

    *rowCutterPP = rowCutterP;
}