Пример #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);
}
Пример #2
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);
}
Пример #3
0
static void
extractOneImage(FILE * const infileP,
                FILE * const outfileP) {
/*----------------------------------------------------------------------------
  Copy a complete image from input stream *infileP to output stream
  *outfileP.

  But if outfileP == NULL, just read the image and discard it.
-----------------------------------------------------------------------------*/
    struct pam inpam;
    struct pam outpam;
    enum pm_check_code checkRetval;
    
    unsigned int row;
    tuple * tuplerow;

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

    pnm_checkpam(&inpam, PM_CHECK_BASIC, &checkRetval);

    outpam = inpam;
    outpam.file = outfileP;

    if (outfileP)
        pnm_writepaminit(&outpam);

    tuplerow = pnm_allocpamrow(&inpam);
    for (row = 0; row < inpam.height; ++row) {
        pnm_readpamrow(&inpam, tuplerow);
        if (outfileP)
            pnm_writepamrow(&outpam, tuplerow);
    }
    pnm_freepamrow(tuplerow);
}
Пример #4
0
static void
writePam(struct pam *       const outpamP,
         unsigned int       const nfiles,
         const coord *      const coords,
         const struct pam * const imgs) {

    tuple *tuplerow;
    int i;
  
    pnm_writepaminit(outpamP);

    tuplerow = pnm_allocpamrow(outpamP);

    for (i = 0; i < outpamP->height; ++i) {
        int j;
        for (j = 0; j < nfiles; ++j) {
            if (coords[j].y <= i && i < coords[j].y + imgs[j].height) {
                pnm_readpamrow(&imgs[j], &tuplerow[coords[j].x]);
                adjustDepth(tuplerow, &imgs[j], outpamP, coords[j]);

                adjustMaxval(tuplerow, &imgs[j], outpamP, coords[j]);

            }
        }
        pnm_writepamrow(outpamP, tuplerow);
    }
    pnm_freepamrow(tuplerow);
}
Пример #5
0
static void
extractOneImage(FILE * const infileP,
                FILE * const outfileP) {

    struct pam inpam;
    struct pam outpam;
    enum pm_check_code checkRetval;
    
    unsigned int row;
    tuple * tuplerow;

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

    pnm_checkpam(&inpam, PM_CHECK_BASIC, &checkRetval);

    outpam = inpam;
    outpam.file = outfileP;

    pnm_writepaminit(&outpam);

    tuplerow = pnm_allocpamrow(&inpam);
    for (row = 0; row < inpam.height; ++row) {
        pnm_readpamrow(&inpam, tuplerow);
        pnm_writepamrow(&outpam, tuplerow);
    }
    pnm_freepamrow(tuplerow);
}
Пример #6
0
static void
wipeoutLr(FILE * const ifP,
          FILE * const ofP) {
    
    /* left-right we can read row-by-row */

    struct pam inpam, outpam;
    tuple ** tuples;
    tuple * tuplerow;
    unsigned int row;

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

    outpam = inpam;
    outpam.file = ofP;

    pnm_writepaminit(&outpam);

    tuplerow = pnm_allocpamrow(&inpam);

    for (row = 0; row < inpam.height; ++row) {
        pnm_readpamrow(&inpam, tuplerow);

        wipeRowByCol(inpam, tuples, tuplerow);

        pnm_writepamrow(&outpam, tuplerow);
    }

    pnm_freepamrow(tuplerow);
}
Пример #7
0
static void
initPi(unsigned char **   const pi,
       const struct pam * const pamP,
       tuple              const backgroundColor) {
/*----------------------------------------------------------------------------
  Set the initial info about every pixel in pi[][].

  Read through the image in the file described by *inpamP and set each
  pixel which is not of background color, and therefore obviously
  foreground, to type PT_FG.  Set every other pixel to PT_UNKNOWN.
-----------------------------------------------------------------------------*/
    tuple * tuplerow;
    unsigned int row;

    tuplerow  = pnm_allocpamrow(pamP);

    for (row = 0; row < pamP->height; ++row) {
        unsigned int col;

        pnm_readpamrow(pamP, tuplerow);

        for (col = 0; col < pamP->width; ++col) {
            pi[row][col] =
                pnm_tupleequal(pamP, tuplerow[col], backgroundColor) ?
                PT_UNKNOWN : PT_FG;
        }
    }
    pnm_freepamrow(tuplerow);
}
Пример #8
0
static void
addImageColorsToHash(struct pam *   const pamP,
                     tuplehash      const tuplehash,
                     unsigned int * const colorCountP) {

    tuple * tuplerow;
    unsigned int row;
    
    tuplerow = pnm_allocpamrow(pamP);

    for (row = 0; row < pamP->height; ++row) {
        unsigned int col;

        pnm_readpamrow(pamP, tuplerow);

        for (col = 0; col < pamP->width; ++col) {
            int firstOccurrence;

            pnm_addtuplefreqoccurrence(pamP, tuplerow[col], tuplehash,
                                       &firstOccurrence);

            if (firstOccurrence)
                ++(*colorCountP);
        }
    }
    pnm_freepamrow(tuplerow);
}
Пример #9
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;
    }
}
Пример #10
0
int
main(int argc, char *argv[]) {

    FILE * ifP;
    tuple * tuplerow;   /* Row from input image */
    unsigned int row;
    struct cmdlineInfo cmdline;
    struct pam inpam;  
    struct pam outpam;

    pnm_init( &argc, argv );

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFilespec);
    
    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));

    tuplerow = pnm_allocpamrow(&inpam);

    outpam = inpam;    /* Initial value -- most fields should be same */
    outpam.file = stdout;
    if (inpam.height % 2 == 0)
        outpam.height = inpam.height / 2;
    else {
        if (cmdline.rowsToTake == ODD)
            outpam.height = inpam.height / 2;
        else
            outpam.height = inpam.height / 2 + 1;
    }

    pnm_writepaminit(&outpam);

    {
        unsigned int modulusToTake;
            /* The row number mod 2 of the rows that are supposed to go into
               the output.
            */

        switch (cmdline.rowsToTake) {
        case EVEN: modulusToTake = 0; break;
        case ODD:  modulusToTake = 1; break;
        default: pm_error("INTERNAL ERROR: invalid rowsToTake");
        }

        /* Read input and write out rows extracted from it */
        for (row = 0; row < inpam.height; row++) {
            pnm_readpamrow(&inpam, tuplerow);
            if (row % 2 == modulusToTake)
                pnm_writepamrow(&outpam, tuplerow);
        }
    }
    pnm_freepamrow(tuplerow);
    pm_close(inpam.file);
    pm_close(outpam.file);
    
    return 0;
}
Пример #11
0
int
main(int argc, char *argv[]) {

    struct cmdlineInfo cmdline;
    FILE* ifP;
    struct pam inpam;   /* Input PAM image */
    struct pam outpam;  /* Output PNM image */

    pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFilespec);

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

    validateTupleType(inpam, cmdline.assume);

    outpam = inpam;
    outpam.file = stdout;
    
    if (inpam.depth < 3) {
        outpam.depth = 1;
        if (inpam.maxval == 1)
            outpam.format = PBM_FORMAT;
        else 
            outpam.format = PGM_FORMAT;
    } else {
        outpam.depth = 3;
        outpam.format = PPM_FORMAT;
    }

    pnm_writepaminit(&outpam);

    {
        tuple *tuplerow;
        
        tuplerow = pnm_allocpamrow(&inpam);      
        { 
            int row;
            
            for (row = 0; row < inpam.height; row++) {
                pnm_readpamrow(&inpam, tuplerow);
                pnm_writepamrow(&outpam, tuplerow);
            }
        }
        pnm_freepamrow(tuplerow);        
    }
    return 0;
}
Пример #12
0
static void
makeImageRows(const struct pam * const inPamP,
              outGenerator *     const outputGeneratorP,
              double             const depthOfField,
              double             const eyesep,
              unsigned int       const dpi,
              bool               const crossEyed,
              bool               const makeMask) {

    tuple * inRow;     /* One row of pixels read from the height-map file */
    tuple * outRow;    /* One row of pixels to write to the height-map file */
    int * same;
    /* Array: same[N] is the column number of a pixel to the right forced
       to have the same color as the one in column N
    */
    int row;           /* Current row in the input and output files */

    inRow = pnm_allocpamrow(inPamP);
    outRow = pnm_allocpamrow(&outputGeneratorP->pam);
    MALLOCARRAY(same, inPamP->width);
    if (same == NULL)
        pm_error("Unable to allocate space for \"same\" array.");

    /* See the paper cited above for code comments.  All I (Scott) did was
     * transcribe the code and make minimal changes for Netpbm.  And some
     * style changes by Bryan to match Netpbm style.
     */
    for (row = 0; row < inPamP->height; ++row) {
        pnm_readpamrow(inPamP, inRow);
        if (crossEyed)
            /* Invert heights for cross-eyed (as opposed to wall-eyed)
               people.
            */
            invertHeightRow(inPamP, inRow);

        /* Determine color constraints. */
        makeStereoRow(inPamP, inRow, same, depthOfField, eyesep, dpi);

        if (makeMask)
            makeMaskRow(&outputGeneratorP->pam, same, outRow);
        else
            makeImageRow(outputGeneratorP, row, same, outRow);

        /* Write the resulting row. */
        pnm_writepamrow(&outputGeneratorP->pam, outRow);
    }
    free(same);
    pnm_freepamrow(outRow);
    pnm_freepamrow(inRow);
}
Пример #13
0
static void
extractRowsGen(const struct pam * const inpamP,
               const struct pam * const outpamP,
               int                const leftcol,
               int                const rightcol,
               int                const toprow,
               int                const bottomrow) {

    struct rowCutter * rowCutterP;
    int row;

    /* Write out top padding */
    if (0 - toprow > 0)
        writeBlackRows(outpamP, 0 - toprow);

    createRowCutter(inpamP, outpamP, leftcol, rightcol, &rowCutterP);

    /* Read input and write out rows extracted from it */
    for (row = 0; row < inpamP->height; ++row) {
        if (row >= toprow && row <= bottomrow){
            pnm_readpamrow(inpamP, rowCutterP->inputPointers);
            pnm_writepamrow(outpamP, rowCutterP->outputPointers);
        } else  /* row < toprow || row > bottomrow */
            pnm_readpamrow(inpamP, NULL);
        
        /* Note that we may be tempted just to quit after reaching the bottom
           of the extracted image, but that would cause a broken pipe problem
           for the process that's feeding us the image.
        */
    }

    destroyRowCutter(rowCutterP);
    
    /* Write out bottom padding */
    if ((bottomrow - (inpamP->height-1)) > 0)
        writeBlackRows(outpamP, bottomrow - (inpamP->height-1));
}
Пример #14
0
static void
ditherImage(struct pam *           const inpamP,
            const scaler *         const scalerP,
            unsigned int           const dithPower,
            struct colorResolution const colorRes,
            struct pam *           const outpamP,
            tuple ***              const outTuplesP) {

    unsigned int const dithDim = 1 << dithPower;
    unsigned int const ditherMatrixArea = SQR(dithDim);

    unsigned int const modMask = (dithDim - 1);
       /* And this into N to compute N % dithDim cheaply, since we
          know (though the compiler doesn't) that dithDim is a power of 2
       */
    unsigned int ** const ditherMatrix = dithMatrix(dithPower);

    tuple * inrow;
    tuple ** outTuples;
    unsigned int row; 
    struct pam ditherPam;
        /* Describes the tuples that ditherRow() sees */

    assert(dithPower < sizeof(unsigned int) * 8);
    assert(UINT_MAX / dithDim >= dithDim);
    
    validateNoDitherOverflow(ditherMatrixArea, inpamP, colorRes);

    inrow = pnm_allocpamrow(inpamP);

    outTuples = pnm_allocpamarray(outpamP);

    /* We will modify the input to promote it to depth 3 */
    ditherPam = *inpamP;
    ditherPam.depth = 3;

    for (row = 0; row < inpamP->height; ++row) {
        pnm_readpamrow(inpamP, inrow);

        pnm_makerowrgb(inpamP, inrow);

        ditherRow(&ditherPam, inrow, scalerP, ditherMatrix, ditherMatrixArea,
                  colorRes, row, modMask,
                  outpamP, outTuples[row]);
    }
    free(ditherMatrix);
    pnm_freepamrow(inrow);
    *outTuplesP = outTuples;
}
Пример #15
0
static void
doUnlookup(struct pam * const inpamP,
           tuplehash    const lookupHash,
           sample       const maxIndex,
           FILE *       const ofP) {

    struct pam outpam;
    unsigned int row;
    tuple * inrow;
    tuple * outrow;

    inrow = pnm_allocpamrow(inpamP);

    outpam.size = sizeof(outpam);
    outpam.len = PAM_STRUCT_SIZE(tuple_type);
    outpam.file = ofP;
    outpam.format = PAM_FORMAT;
    outpam.height = inpamP->height;
    outpam.width = inpamP->width;
    outpam.depth = 1;
    outpam.maxval = maxIndex + 1;  /* +1 for missing color */
    strcpy(outpam.tuple_type, "INDEX");

    pnm_writepaminit(&outpam);

    outrow = pnm_allocpamrow(&outpam);

    for (row = 0; row < inpamP->height; ++row) {
        unsigned int col;
        
        pnm_readpamrow(inpamP, inrow);

        for (col = 0; col < inpamP->width; ++col) {
            int found;
            int index;
            pnm_lookuptuple(inpamP, lookupHash, inrow[col], &found, &index);

            if (found) {
                assert(index <= outpam.maxval);
                outrow[col][0] = index;
            } else
                outrow[col][0] = maxIndex + 1;
        }
        pnm_writepamrow(&outpam, outrow);
    }

    pnm_freepamrow(outrow);
    pnm_freepamrow(inrow);
}
Пример #16
0
static void
load(const struct pam * const pamP,
     unsigned int       const hstep,
     sample ***         const pixelsP,
     unsigned int *     const hsamplesP) {
/*----------------------------------------------------------------------------
  read file into memory, returning array of rows
-----------------------------------------------------------------------------*/
    unsigned int const hsamples = 1 + (pamP->width - 1) / hstep;
        /* use only this many cols */

    unsigned int row;
    tuple *  tuplerow;
    sample ** pixels;

    tuplerow = pnm_allocpamrow(pamP);
    
    MALLOCARRAY(pixels, pamP->height);
    if (pixels == NULL)
        pm_error("Unable to allocate array of %u pixel rows",
                 pamP->height);

    if (pixels == NULL)
        pm_error("Unable to allocate array of %u rows", pamP->height);

    for (row = 0; row < pamP->height; ++row) {
        unsigned int i;
        unsigned int col;

        pnm_readpamrow(pamP, tuplerow);

        MALLOCARRAY(pixels[row], hsamples);
        if (pixels[row] == NULL)
            pm_error("Unable to allocate %u-sample array for Row %u",
                     hsamples, row);

        /* save every hstep'th column */
        for (i = col = 0; i < hsamples; ++i, col += hstep)
            pixels[row][i] = tuplerow[col][0];
    }

    pnm_freepamrow(tuplerow);

    *hsamplesP = hsamples;
    *pixelsP   = pixels;
}
Пример #17
0
static void
doOneImage(const char * const name,
           unsigned int const imageDoneCount,
           FILE *       const fileP,
           bool         const allimages,
           bool         const justCount,
           bool         const wantComments,
           bool *       const eofP) {
                    
    struct pam pam;
    const char * comments;
    enum pm_check_code checkRetval;

    pam.comment_p = &comments;

    pnm_readpaminit(fileP, &pam, PAM_STRUCT_SIZE(comment_p));
        
    if (!justCount) {
        if (allimages)
            printf("%s:\tImage %d:\t", name, imageDoneCount);
        else 
            printf("%s:\t", name);
            
        dumpHeader(pam);
        if (wantComments)
            dumpComments(comments);
    }
    strfree(comments);

    pnm_checkpam(&pam, PM_CHECK_BASIC, &checkRetval);
    if (allimages) {
        tuple * tuplerow;
        unsigned int row;
        
        tuplerow = pnm_allocpamrow(&pam);
        
        for (row = 0; row < pam.height; ++row) 
            pnm_readpamrow(&pam, tuplerow);
        
        pnm_freepamrow(tuplerow);
        
        pnm_nextimage(fileP, eofP);
    }
}
Пример #18
0
static void
writePam(struct pam *       const outpamP,
         unsigned int       const imgCt,
         const Coord *      const coords,
         const struct pam * const imgs) {
/*----------------------------------------------------------------------------
   Write the entire composite image.  There are 'imgCt' source images,
   described by imgs[].  Their placement in the output is coords[].
   Properties of the output image, including where to write it
   and its dimensions are *outpamP.
-----------------------------------------------------------------------------*/
    tuple * tuplerow;
    unsigned int row;  /* Row number in the output image */
  
    pnm_writepaminit(outpamP);

    tuplerow = pnm_allocpamrow(outpamP);

    for (row = 0; row < outpamP->height; ++row) {
        unsigned int imgIdx;
        
        makeRowBlack(outpamP, tuplerow);  /* initial value */

        for (imgIdx = 0; imgIdx < imgCt; ++imgIdx) {
            const Coord *      const imgCoordP = &coords[imgIdx];
            const struct pam * const imgPamP   = &imgs[imgIdx];

            if (imgCoordP->y <= row && row < imgCoordP->y + imgPamP->height) {
                pnm_readpamrow(imgPamP, &tuplerow[imgCoordP->x]);

                adjustDepth(tuplerow, imgPamP, outpamP, *imgCoordP);

                adjustMaxval(tuplerow, imgPamP, outpamP, *imgCoordP);
            }
        }
        pnm_writepamrow(outpamP, tuplerow);
    }
    pnm_freepamrow(tuplerow);
}
Пример #19
0
static void
convertPage(FILE * const ifP, 
            int    const turnflag, 
            int    const turnokflag, 
            bool   const psfilter,
            bool   const rle, 
            bool   const flate,
            bool   const ascii85,
            bool   const setpage,
            bool   const showpage,
            bool   const center, 
            float  const scale,
            int    const dpiX, 
            int    const dpiY, 
            int    const pagewid, 
            int    const pagehgt,
            int    const imagewidth, 
            int    const imageheight, 
            bool   const equalpixels,
            char   const name[],
            bool   const dict,
            bool   const vmreclaim,
            bool   const levelIsGiven,
            bool   const levelGiven) {
    
    struct pam inpam;
    tuple* tuplerow;
    unsigned int padright;
        /* Number of bits we must add to the right end of each Postscript
           output line in order to have an integral number of bytes of output.
           E.g. at 2 bits per sample with 10 columns, this would be 4.
        */
    int row;
    unsigned int ps_maxval;
        /* The maxval of the Postscript program */
    float scols, srows;
    float llx, lly;
    bool turned;
    bool color;
    unsigned int postscriptLevel;
    struct bmepsoe * bmepsoeP;

    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
    
    if (!STRSEQ(inpam.tuple_type, PAM_PBM_TUPLETYPE) &&
        !STRSEQ(inpam.tuple_type, PAM_PGM_TUPLETYPE) &&
        !STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE))
        pm_error("Unrecognized tuple type %s.  This program accepts only "
                 "PBM, PGM, PPM, and equivalent PAM input images", 
                 inpam.tuple_type);

    color = STRSEQ(inpam.tuple_type, PAM_PPM_TUPLETYPE);
    
    selectPostscriptLevel(levelIsGiven, levelGiven, color, 
                          dict, flate, ascii85, &postscriptLevel);
    
    if (color)
        pm_message("generating color Postscript program.");

    computeDepth(inpam.maxval, &bitspersample, &ps_maxval);
    {
        unsigned int const realBitsPerLine = inpam.width * bitspersample;
        unsigned int const paddedBitsPerLine = ((realBitsPerLine + 7) / 8) * 8;
        padright = (paddedBitsPerLine - realBitsPerLine) / bitspersample;
    }
    /* In positioning/scaling the image, we treat the input image as if
       it has a density of 72 pixels per inch.
    */
    computeImagePosition(dpiX, dpiY, inpam.width, inpam.height, 
                         turnflag, turnokflag, center,
                         pagewid, pagehgt, scale, imagewidth, imageheight,
                         equalpixels,
                         &scols, &srows, &llx, &lly, &turned);
    
    putinit(postscriptLevel, name, inpam.width, inpam.height, 
            scols, srows, llx, lly, padright, bitspersample, 
            pagewid, pagehgt, color,
            turned, rle, flate, ascii85, setpage, psfilter, dict);

    createBmepsOutputEncoder(&bmepsoeP, stdout, rle, flate, ascii85);
    initNativeOutputEncoder(rle, bitspersample);

    tuplerow = pnm_allocpamrow(&inpam);

    for (row = 0; row < inpam.height; ++row) {
        pnm_readpamrow(&inpam, tuplerow);
        if (psfilter)
            convertRowPsFilter(&inpam, tuplerow, bmepsoeP);
        else
            convertRowNative(&inpam, tuplerow, ps_maxval, rle, padright);
    }

    pnm_freepamrow(tuplerow);

    if (psfilter)
        flushBmepsOutput(bmepsoeP);
    else
        flushNativeOutput(rle);

    destroyBmepsOutputEncoder(bmepsoeP);

    putEnd(showpage, psfilter, ascii85, dict, vmreclaim);
}
Пример #20
0
int main(int argc, char** args) {
    int argchar;
	char* infn = NULL;
	char* outfn = NULL;
	unsigned int row;
	int bits;
	FILE* fid = stdin;
	FILE* fout = stdout;
	int loglvl = LOG_MSG;
	char* progname = args[0];
	int bzero = 0;
	int outformat;
	qfits_header* hdr;
	unsigned int plane;
	off_t datastart;
	anbool onepass = FALSE;
	bl* pixcache = NULL;

#if HAVE_NETPBM
	struct pam img;
	tuple * tuplerow;
#else
	void* rowbuf;
#endif
	int W, H, depth, maxval;

    while ((argchar = getopt (argc, args, OPTIONS)) != -1)
        switch (argchar) {
		case '?':
		case 'h':
			printHelp(progname);
			exit(0);
		case 'v':
			loglvl++;
			break;
		case 'q':
			loglvl--;
			break;
		case 'o':
			outfn = optarg;
			break;
		}

	log_init(loglvl);
	log_to(stderr);
	fits_use_error_system();

	if (optind == argc) {
		// ok, stdin to stdout.
	} else if (optind == argc-1) {
		infn = args[optind];
	} else if (optind == argc-2) {
		infn = args[optind];
		outfn = args[optind+1];
	} else {
		printHelp(progname);
		exit(-1);
	}

	if (infn && !streq(infn, "-")) {
		fid = fopen(infn, "rb");
		if (!fid) {
			SYSERROR("Failed to open input file %s", infn);
			exit(-1);
		}
	}
	if (outfn) {
		fout = fopen(outfn, "wb");
		if (!fid) {
			SYSERROR("Failed to open output file %s", outfn);
			exit(-1);
		}
	} else
		outfn = "stdout";

#if HAVE_NETPBM
	pm_init(args[0], 0);
	pnm_readpaminit(fid, &img, 
					// PAM_STRUCT_SIZE isn't defined until Netpbm 10.23 (July 2004)
#if defined(PAM_STRUCT_SIZE)
					PAM_STRUCT_SIZE(tuple_type)
#else
					sizeof(struct pam)
#endif
);
	W = img.width;
	H = img.height;
	depth = img.depth;
	maxval = img.maxval;

	tuplerow = pnm_allocpamrow(&img);
	bits = pm_maxvaltobits(img.maxval); 
	bits = (bits <= 8) ? 8 : 16;

#else // No NETPBM

	if (parse_pnm_header(fid, &W, &H, &depth, &maxval)) {
		ERROR("Failed to parse PNM header from file: %s\n", infn ? infn : "<stdin>");
		exit(-1);
	}
	bits = 8 * maxval_to_bytes(maxval);

	rowbuf = malloc(W * depth * (bits/8));

#endif

	logmsg("Read file %s: %i x %i pixels x %i color(s); maxval %i\n",
		   infn ? infn : "stdin", W, H, depth, maxval);
	if (bits == 8)
		outformat = BPP_8_UNSIGNED;
	else {
		outformat = BPP_16_SIGNED;
		if (maxval >= INT16_MAX)
			bzero = 0x8000;
	}
	logmsg("Using %i-bit output\n", bits);

	hdr = fits_get_header_for_image3(W, H, outformat, depth, NULL);
	if (bzero)
		fits_header_add_int(hdr, "BZERO", bzero, "Number that has been subtracted from pixel values");
	if (qfits_header_dump(hdr, fout)) {
		ERROR("Failed to write FITS header to file %s", outfn);
		exit(-1);
	}
	qfits_header_destroy(hdr);

	datastart = ftello(fid);
	// Figure out if we can seek backward in this input file...
	if ((fid == stdin) ||
		(fseeko(fid, 0, SEEK_SET) ||
		 fseeko(fid, datastart, SEEK_SET)))
		// Nope!
		onepass = TRUE;
	if (onepass && depth > 1) {
		logmsg("Reading in one pass\n");
		pixcache = bl_new(16384, bits/8);
	}

	for (plane=0; plane<depth; plane++) {
		if (plane > 0) {
			if (fseeko(fid, datastart, SEEK_SET)) {
				SYSERROR("Failed to seek back to start of image data");
				exit(-1);
			}
		}
		for (row = 0; row<H; row++) {
			unsigned int column;

#if HAVE_NETPBM
			pnm_readpamrow(&img, tuplerow);
#else
			read_pnm_row(fid, W, depth, maxval, rowbuf);
#endif

			for (column = 0; column<W; column++) {
				int rtn;
				int pixval;

#if HAVE_NETPBM
				pixval = tuplerow[column][plane];
#else
				pixval = (bits == 8 ?
						  ((uint8_t *)rowbuf)[column*depth + plane] :
						  ((uint16_t*)rowbuf)[column*depth + plane]);
#endif
				if (outformat == BPP_8_UNSIGNED)
					rtn = fits_write_data_B(fout, pixval);
				else
					rtn = fits_write_data_I(fout, pixval-bzero, TRUE);
				if (rtn) {
					ERROR("Failed to write FITS pixel");
					exit(-1);
				}
			}
			if (onepass && depth > 1) {
				for (column = 0; column<W; column++) {
					for (plane=1; plane<depth; plane++) {
						int pixval;
#if HAVE_NETPBM
						pixval = tuplerow[column][plane];
#else
						pixval = (bits == 8 ?
								  ((uint8_t *)rowbuf)[column*depth + plane] :
								  ((uint16_t*)rowbuf)[column*depth + plane]);
#endif
						if (outformat == BPP_8_UNSIGNED) {
							uint8_t pix = pixval;
							bl_append(pixcache, &pix);
						} else {
							int16_t pix = pixval - bzero;
							bl_append(pixcache, &pix);
						}
					}
				}
			}
		}
	}
	
#if HAVE_NETPBM
	pnm_freepamrow(tuplerow);
#else
	free(rowbuf);
#endif

	if (pixcache) {
		int i, j;
		int step = (depth - 1);
		logverb("Writing %zu queued pixels\n", bl_size(pixcache));
		for (plane=1; plane<depth; plane++) {
			j = (plane - 1);
			for (i=0; i<(W * H); i++) {
				int rtn;
				if (outformat == BPP_8_UNSIGNED) {
					uint8_t* pix = bl_access(pixcache, j);
					rtn = fits_write_data_B(fout, *pix);
				} else {
					int16_t* pix = bl_access(pixcache, j);
					rtn = fits_write_data_I(fout, *pix, TRUE);
				}
				if (rtn) {
					ERROR("Failed to write FITS pixel");
					exit(-1);
				}
				j += step;
			}
		}
		bl_free(pixcache);
	}

	if (fid != stdin)
		fclose(fid);

	if (fits_pad_file(fout)) {
		ERROR("Failed to pad output file \"%s\"", outfn);
		return -1;
	}

	if (fout != stdout)
		if (fclose(fout)) {
			SYSERROR("Failed to close output file %s", outfn);
			exit(-1);
		}

	return 0;
}
Пример #21
0
static void
extractRowsPBM(const struct pam * const inpamP,
               const struct pam * const outpamP,
               int                const leftcol,
               int                const rightcol,
               int                const toprow,
               int                const bottomrow) {

    unsigned char * bitrow;
    int             readOffset, writeOffset;
    int             row;
    unsigned int    totalWidth;

    assert(leftcol <= rightcol);
    assert(toprow <= bottomrow);

    if (leftcol > 0) {
        totalWidth = MAX(rightcol+1, inpamP->width) + 7;
        if (totalWidth > INT_MAX)
            /* Prevent overflows in pbm_allocrow_packed() */
            pm_error("Specified right edge is too far "
                     "from the right end of input image");
        
        readOffset  = 0;
        writeOffset = leftcol;
    } else {
        totalWidth = -leftcol + MAX(rightcol+1, inpamP->width);
        if (totalWidth > INT_MAX)
            pm_error("Specified left/right edge is too far "
                     "from the left/right end of input image");
        
        readOffset = -leftcol;
        writeOffset = 0;
    }

    bitrow = pbm_allocrow_packed(totalWidth);

    if (toprow < 0 || leftcol < 0 || rightcol >= inpamP->width){
        makeBlackPBMRow(bitrow, totalWidth);
        if (toprow < 0) {
            int row;
            for (row=0; row < 0 - toprow; ++row)
                pbm_writepbmrow_packed(outpamP->file, bitrow,
                                       outpamP->width, 0);
        }
    }

    for (row = 0; row < inpamP->height; ++row){
        if (row >= toprow && row <= bottomrow) {
            pbm_readpbmrow_bitoffset(inpamP->file, bitrow, inpamP->width,
                                     inpamP->format, readOffset);

            pbm_writepbmrow_bitoffset(outpamP->file, bitrow, outpamP->width,
                                      0, writeOffset);
  
            if (rightcol >= inpamP->width)
                /* repair right padding */
                bitrow[writeOffset/8 + pbm_packed_bytes(outpamP->width) - 1] =
                    0xff * PBM_BLACK;
        } else
            pnm_readpamrow(inpamP, NULL);    /* read and discard */
    }

    if (bottomrow - (inpamP->height-1) > 0) {
        int row;
        makeBlackPBMRow(bitrow, outpamP->width);
        for (row = 0; row < bottomrow - (inpamP->height-1); ++row)
            pbm_writepbmrow_packed(outpamP->file, bitrow, outpamP->width, 0);
    }
    pbm_freerow_packed(bitrow);
}
Пример #22
0
int 
main(int argc, char *argv[]) {
    FILE *ifP;
    struct cmdlineInfo cmdline;
    struct pam inpam, outpam;
    unsigned int row;
    tuple * inrow;
    tuple * outrow;
    tuple * prevrow;

    pnm_init( &argc, argv );

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFilespec);

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

    outpam = inpam;
    outpam.file = stdout;
    outpam.format = PAM_FORMAT;
    strcpy(outpam.tuple_type, "hdiff");

    pnm_writepaminit(&outpam);

    inrow = pnm_allocpamrow(&inpam);
    outrow = pnm_allocpamrow(&outpam);
    prevrow = pnm_allocpamrow(&inpam);

    pnm_setpamrow(&inpam, prevrow, 0);

    /* All arithmetic in this operation and in the reverse operation
       (to recover the image) is done modulus the maxval+1 (the hdiff
       PAM and the image have the same maxval) in order to produce
       legal PAM samples (which must be in the range 0..maxval).  This
       might seem to throw away information, but it doesn't.  Example:
       maxval is 99.  Intensity goes from 90 in Row 0 to 10 in Row 1.
       The difference is -80.  -80 mod 100 is 20, so 20 goes in the
       hdiff output.  On reconstructing the image, the interpreter
       knows the "20" can't be +20, because that would create the
       sample 90 + 20 = 110, and violate maxval.  So it must be -80.
       Modulus arithmetic by the interpreter effectively makes that
       decision.  
    */


    /* The bias is just to make it easier to look at the output visually.
       If you display the values as intensities, and your differences are
       all +/- half of maxval, you can see positive transitions as bright
       spots and negative transitions as dark spots.
    */
    
    {
        unsigned int const bias = outpam.maxval/2;
        for (row = 0; row < inpam.height; ++row) {
            unsigned int col;
            pnm_readpamrow(&inpam, inrow);
            for (col = 0; col < inpam.width; ++col) {
            unsigned int plane;
            for (plane = 0; plane < inpam.depth; ++plane) {
                
                sample const sampleValue = inrow[col][plane];
                int const difference = sampleValue - prevrow[col][plane];
                outrow[col][plane] = (difference + bias) % (outpam.maxval+1);
                prevrow[col][plane] = sampleValue;
            }
        }
            pnm_writepamrow(&outpam, outrow);
        }
    }
    pnm_freepamrow(prevrow);
    pnm_freepamrow(outrow);
    pnm_freepamrow(inrow);

    exit(0);
}
Пример #23
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);
}
Пример #24
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);
}
Пример #25
0
static void
writeScanLines(struct pam *   const pamP,
               TIFF *         const tif, 
               tuplehash      const cht,
               unsigned short const tiffMaxval,
               unsigned short const bitspersample, 
               unsigned short const photometric,
               int            const bytesperrow, 
               int            const fillorder) {
/*----------------------------------------------------------------------------
   Write out the raster for the input image described by 'pamP', whose
   file is positioned to the raster of the image.
-----------------------------------------------------------------------------*/
    tuple * tuplerow;  /* malloc'ed */
    unsigned char * buf; /* malloc'ed */
    int row;

    /* The man page for TIFFWriteScanLine doesn't tell the format of
       it's 'buf' parameter, but here it is: Its format depends on the
       bits per pixel of the TIFF image.  If it's 16, 'buf' is an
       array of short (16 bit) integers, one per raster column.  If
       it's 8, 'buf' is an array of characters (8 bit integers), one
       per image column.  If it's less than 8, it's an array of characters,
       each of which represents 1-8 raster columns, packed
       into it in the order specified by the TIFF image's fill order,
       with don't-care bits on the right such that each byte contains only
       whole pixels.

       In all cases, the array elements are in order left to right going
       from low array indices to high array indices.
    */
    MALLOCARRAY(buf, bytesperrow);

    if (buf == NULL)
        pm_error("can't allocate memory for row buffer");

    tuplerow = pnm_allocpamrow(pamP);
    
    for (row = 0; row < pamP->height; ++row) {
        int col;

        pnm_readpamrow(pamP, tuplerow);

        if (cht == NULL) {
            /* It's a direct, non-colormapped raster */

            if (bitspersample == 8 || bitspersample == 16)
                fillRowOfWholeBytePixels(pamP, tuplerow, buf, photometric,
                                         tiffMaxval, bitspersample);
            else
                fillRowOfSubBytePixels(pamP, tuplerow, buf,
                                       tiffMaxval, photometric,
                                       fillorder, bitspersample, NULL);
        } else {
            /* It's a colormapped raster */
            if (bitspersample == 8) {
                for (col = 0; col < pamP->width; ++col) {
                    int si;
                    int found;
                    
                    pnm_lookuptuple(pamP, cht, tuplerow[col], &found, &si);
                    
                    if (!found)
                        pm_error("INTERNAL ERROR.  We made a color map, and a "
                                 "color map we need is not in it!  "
                                 "col=%d  r=%lu g=%lu b=%lu",
                                 col, tuplerow[col][0], tuplerow[col][1],
                                 tuplerow[col][2]);
                    buf[col] = (unsigned char) si;
                }
            } else {
                fillRowOfSubBytePixels(pamP, tuplerow, buf, 0, 0, fillorder,
                                       bitspersample, cht);
            }
        }
        if (TIFFWriteScanline(tif, buf, row, 0) < 0)
            pm_error("failed a scanline write on row %d", row);
    }
    pnm_freepamrow(tuplerow);
    free(buf);
}
Пример #26
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);
}
Пример #27
0
static void
createJasperRaster(struct pam *  const inpamP, 
                   jas_image_t * const jasperP) {

    jas_matrix_t ** matrix;  /* malloc'ed */
        /* matrix[X] is the data for Plane X of the current row */
    unsigned int plane;
    unsigned int row;
    tuple * tuplerow;
    bool oddMaxval;
    sample jasperMaxval;

    matrix = malloc(inpamP->depth * sizeof(jas_matrix_t *));
    if (matrix == NULL)
        pm_error("Out of memory");

    for (plane = 0; plane < inpamP->depth; ++plane) {
        matrix[plane] = jas_matrix_create(1, inpamP->width);

        if (matrix[plane] == NULL)
            pm_error("Unable to create matrix for plane %u.  "
                     "jas_matrix_create() failed.", plane);
    }   
    tuplerow = pnm_allocpamrow(inpamP);

    jasperMaxval = pm_bitstomaxval(pm_maxvaltobits(inpamP->maxval));
    oddMaxval = jasperMaxval != inpamP->maxval;

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

        pnm_readpamrow(inpamP, tuplerow);

        for (col = 0; col < inpamP->width; ++col) {
            unsigned int plane;
            for (plane = 0; plane < inpamP->depth; ++plane) {
                unsigned int jasperSample;

                if (oddMaxval)
                    jasperSample = tuplerow[col][plane] * 
                        jasperMaxval / inpamP->maxval;
                else
                    jasperSample = tuplerow[col][plane];

                jas_matrix_set(matrix[plane], 0, col, jasperSample);
            }
        }
        { 
            unsigned int plane;

            for (plane = 0; plane < inpamP->depth; ++plane) {
                int rc;
                rc = jas_image_writecmpt(jasperP, plane, 0, row, 
                                         inpamP->width, 1,
                                         matrix[plane]);
                if (rc != 0)
                    pm_error("jas_image_writecmpt() of plane %u failed.", 
                             plane);
            }
        }
    }

    pnm_freepamrow(tuplerow);
    for (plane = 0; plane < inpamP->depth; ++plane)
        jas_matrix_destroy(matrix[plane]);
    
    free(matrix);
}