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; } }
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); }
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)); } }
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; }