Exemple #1
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);
}
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);
}
Exemple #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);
}
Exemple #4
0
static void
readRelevantPixels(const char *   const inputFilename,
                   unsigned int   const hstepReq,
                   unsigned int   const vstepReq,
                   unsigned int * const hstepP,
                   unsigned int * const vstepP,
                   sample ***     const pixelsP,
                   struct pam *   const pamP,
                   unsigned int * const hsamplesP) {
/*----------------------------------------------------------------------------
  load the image, saving only the pixels we might actually inspect
-----------------------------------------------------------------------------*/
    FILE * ifP;
    unsigned int hstep;
    unsigned int vstep;

    ifP = pm_openr(inputFilename);
    pnm_readpaminit(ifP, pamP, PAM_STRUCT_SIZE(tuple_type));
    computeSteps(pamP, hstepReq, vstepReq, &hstep, &vstep);

    load(pamP, hstep, pixelsP, hsamplesP);

    *hstepP = hstep;
    *vstepP = vstep;
    
    pm_close(ifP);
}
int
main(int argc, char **argv) {

    FILE * ifP; 
    struct cmdlineInfo cmdline;
    struct pam inpam, outpam;
    int eof;  /* No more images in input stream */

    pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    if (cmdline.simple || cmdline.local)
        ifP = pm_openr(cmdline.inputFileName);
    else
        ifP = pm_openr_seekable(cmdline.inputFileName);

    /* Threshold each image in the PAM file */
    eof = FALSE;
    while (!eof) {
        pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));

        /* Set output image parameters for a bilevel image */
        outpam.size        = sizeof(outpam);
        outpam.len         = PAM_STRUCT_SIZE(tuple_type);
        outpam.file        = stdout;
        outpam.format      = PAM_FORMAT;
        outpam.plainformat = 0;
        outpam.height      = inpam.height;
        outpam.width       = inpam.width;
        outpam.maxval      = 1;
        outpam.bytes_per_sample = 1;

        if (inpam.depth > 1) {
            strcpy(outpam.tuple_type, "BLACKANDWHITE_ALPHA");
            outpam.depth = 2;
        } else {
            strcpy(outpam.tuple_type, "BLACKANDWHITE");
            outpam.depth = 1;
        }

        pnm_writepaminit(&outpam);

        /* Do the thresholding */

        if (cmdline.simple)
            thresholdSimple(&inpam, &outpam, cmdline.threshold);
        else if (cmdline.local || cmdline.dual)
            thresholdLocal(&inpam, &outpam, cmdline);
        else
            thresholdIterative(&inpam, &outpam, cmdline.verbose);

        pnm_nextimage(ifP, &eof);
    }

    pm_close(ifP);

    return 0;
}
Exemple #6
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;
}
static void
readFileHeaders(struct pam * const imgPam,
                unsigned int const fileCt) {

    unsigned int i;

    for (i = 0; i < fileCt; ++i)
        pnm_readpaminit(imgPam[i].file, &imgPam[i],
                        PAM_STRUCT_SIZE(tuple_type));
}
Exemple #8
0
static void
remap(FILE *             const ifP,
      const struct pam * const outpamCommonP,
      tupletable         const colormap, 
      unsigned int       const colormapSize,
      bool               const floyd,
      bool               const randomize,
      tuple              const defaultColor,
      bool               const verbose) {
/*----------------------------------------------------------------------------
   Remap the pixels from the raster on *ifP to the 'colormapSize' colors in
   'colormap'.

   Where the input pixel's color is in the map, just use that for the output.
   Where it isn't, use 'defaultColor', except if that is NULL, use the
   closest color in the map to the input color.

   But if 'floyd' is true and 'defaultColor' is NULL, also do Floyd-Steinberg
   dithering on the output so the aggregate color of a region is about the
   same as that of the input even though the individual pixels have different
   colors.
-----------------------------------------------------------------------------*/
    int eof;
    eof = FALSE;
    while (!eof) {
        struct pam inpam, outpam;
        unsigned int missingCount;
            /* Number of pixels that were mapped to 'defaultColor' because
               they weren't present in the color map.
            */

        pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(allocation_depth));
    
        outpam = *outpamCommonP;
        outpam.width  = inpam.width;
        outpam.height = inpam.height;

        pnm_writepaminit(&outpam);

        /* Set up so input buffers have extra space as needed to
           convert the input to the output depth.
        */
        pnm_setminallocationdepth(&inpam, outpam.depth);
    
        copyRaster(&inpam, &outpam, colormap, colormapSize, floyd,
                   randomize, defaultColor, &missingCount);
        
        if (verbose)
            pm_message("%u pixels not matched in color map", missingCount);
        
        pnm_nextimage(ifP, &eof);
    }
}
int
main(int           argc,
     const char ** argv) {

    struct cmdlineInfo cmdline;
    FILE * ifP;
    tuple ** outTuples;        /* Output image */
    scaler * scalerP;
    struct pam inpam;
    struct pam outpam;

    pm_proginit(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFileName);

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

    pnm_setminallocationdepth(&inpam, 3);
    
    outpam.size               = sizeof(outpam);
    outpam.len                = PAM_STRUCT_SIZE(tuple_type);
    outpam.file               = stdout;
    outpam.width              = inpam.width;
    outpam.height             = inpam.height;
    outpam.depth              = 3;
    outpam.maxval             =
        pm_lcm(cmdline.colorRes.c[RED]-1,
               cmdline.colorRes.c[GRN]-1,
               cmdline.colorRes.c[BLU]-1,
               PPM_MAXMAXVAL);
    outpam.bytes_per_sample   = inpam.bytes_per_sample;
    STRSCPY(outpam.tuple_type, "RGB");
    outpam.format             = RPPM_FORMAT;
    outpam.plainformat        = false;

    scaler_create(outpam.maxval, cmdline.colorRes, &scalerP);

    ditherImage(&inpam, scalerP, cmdline.dim, cmdline.colorRes,
                &outpam, &outTuples);

    pnm_writepam(&outpam, outTuples);

    scaler_destroy(scalerP);

    pnm_freepamarray(outTuples, &outpam);

    pm_close(ifP);

    return 0;
}
Exemple #10
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;
}
Exemple #11
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);
    }
}
Exemple #12
0
int
main(int argc, const char ** const argv) {

    struct CmdlineInfo cmdline;
    struct pam inpam;
    FILE * ifP;
    struct pam lookuppam;
    tuple ** lookup;

    tuplehash lookupHash;
    
    pm_proginit(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFileName);

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

    getLookup(cmdline.lookupfile, &lookup, &lookuppam);

    if (inpam.depth != lookuppam.depth)
        pm_error("The lookup image has depth %u, but the input image "
                 "has depth %u.  They must be the same",
                 lookuppam.depth, inpam.depth);
    if (!streq(inpam.tuple_type, lookuppam.tuple_type))
        pm_error("The lookup image has tupel type '%s', "
                 "but the input image "
                 "has tuple type '%s'.  They must be the same",
                 lookuppam.tuple_type, inpam.tuple_type);

    makeReverseLookupHash(&lookuppam, lookup, &lookupHash);

    doUnlookup(&inpam, lookupHash, lookuppam.width-1, stdout);

    pm_close(ifP);

    pnm_destroytuplehash(lookupHash);
    pnm_freepamarray(lookup, &lookuppam);
    
    return 0;
}
Exemple #13
0
static void
initAlphaFile(struct cmdlineInfo const cmdline,
              struct pam *       const overlayPamP,
              FILE **            const filePP,
              struct pam *       const pamP) {

    FILE * fileP;
    
    if (cmdline.alphaFilespec) {
        fileP = pm_openr(cmdline.alphaFilespec);
        pamP->comment_p = NULL;
        pnm_readpaminit(fileP, pamP, PAM_STRUCT_SIZE(opacity_plane));

        if (overlayPamP->width != pamP->width || 
            overlayPamP->height != pamP->height)
            pm_error("Opacity map and overlay image are not the same size");
    } else
        fileP = NULL;

    *filePP = fileP;
}
Exemple #14
0
int
main(int argc, char **argv)
{
    struct cmdlineInfo cmdline;
    FILE *ifP;
    struct pam inpam;
    jas_image_t * jasperP;

    pnm_init(&argc, argv);
    
    parseCommandLine(argc, argv, &cmdline);
    
    { 
        int rc;
        
        rc = jas_init();
        if ( rc != 0 )
            pm_error("Failed to initialize Jasper library.  "
                     "jas_init() returns rc %d", rc );
    }
    
    jas_setdbglevel(cmdline.debuglevel);
    
    ifP = pm_openr(cmdline.inputFilename);
    
    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
    
    convertToJasperImage(&inpam, &jasperP);
    
    writeJpc(jasperP, cmdline, stdout);
    
	jas_image_destroy(jasperP);

    pm_close(ifP);

    pm_close(stdout);
    
    return 0;
}
Exemple #15
0
static void
produceStereogram(FILE *             const ifP,
                  struct cmdlineInfo const cmdline) {

    struct pam inPam;    /* PAM information for the height-map file */
    outGenerator * outputGeneratorP;
    /* Handle of an object that generates background pixels */

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

    createoutputGenerator(cmdline, &inPam, &outputGeneratorP);

    if (cmdline.verbose) {
        reportImageParameters("Input (height map) file", &inPam);
        if (inPam.depth > 1)
            pm_message("Ignoring all but the first plane of input.");
        reportImageParameters("Output (stereogram) file",
                              &outputGeneratorP->pam);
    }

    pnm_writepaminit(&outputGeneratorP->pam);

    /* Draw guide boxes at the top, if desired. */
    if (cmdline.guidesize < 0)
        drawguides(-cmdline.guidesize, &outputGeneratorP->pam,
                   cmdline.eyesep,
                   cmdline.dpi, cmdline.depth);

    makeImageRows(&inPam, outputGeneratorP,
                  cmdline.depth, cmdline.eyesep, cmdline.dpi,
                  cmdline.crosseyed, cmdline.makemask);

    /* Draw guide boxes at the bottom, if desired. */
    if (cmdline.guidesize > 0)
        drawguides(cmdline.guidesize, &outputGeneratorP->pam,
                   cmdline.eyesep, cmdline.dpi, cmdline.depth);

    destroyoutputGenerator(outputGeneratorP);
}
Exemple #16
0
static void
cutOneImage(FILE *             const ifP,
            struct cmdlineInfo const cmdline,
            FILE *             const ofP) {

    int leftcol, rightcol, toprow, bottomrow;
    struct pam inpam;   /* Input PAM image */
    struct pam outpam;  /* Output PAM image */

    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
    
    computeCutBounds(inpam.width, inpam.height, 
                     cmdline.left, cmdline.right, 
                     cmdline.top, cmdline.bottom, 
                     cmdline.width, cmdline.height, 
                     &leftcol, &rightcol, &toprow, &bottomrow);

    rejectOutOfBounds(inpam.width, inpam.height, leftcol, rightcol, 
                      toprow, bottomrow, cmdline.pad);

    if (cmdline.verbose) {
        pm_message("Image goes from Row 0, Column 0 through Row %u, Column %u",
                   inpam.height-1, inpam.width-1);
        pm_message("Cutting from Row %d, Column %d through Row %d Column %d",
                   toprow, leftcol, bottomrow, rightcol);
    }

    outpam = inpam;    /* Initial value -- most fields should be same */
    outpam.file   = ofP;
    outpam.width  = rightcol - leftcol + 1;
    outpam.height = bottomrow - toprow + 1;

    pnm_writepaminit(&outpam);

    if (PNM_FORMAT_TYPE(outpam.format) == PBM_TYPE)
        extractRowsPBM(&inpam, &outpam, leftcol, rightcol, toprow, bottomrow);
    else
        extractRowsGen(&inpam, &outpam, leftcol, rightcol, toprow, bottomrow);
}
Exemple #17
0
int
main(int argc, char *argv[]) {

    struct cmdlineInfo cmdline;
    struct pam inpam;
    FILE * ifP;
    pm_filepos rasterpos;
    tuple backgroundColor;
    const unsigned char * const * pi;
    
    pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr_seekable(cmdline.inputFileName);

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

    pm_tell2(ifP, &rasterpos, sizeof(rasterpos));

    determineBackgroundColor(&inpam, cmdline.verbose, &backgroundColor);

    pm_seek2(ifP, &rasterpos, sizeof(rasterpos));

    findBackgroundPixels(&inpam, backgroundColor, cmdline.verbose, &pi);

    writeOutput(&inpam, pi);

    destroyPi(pi, inpam.height);

    pm_close(ifP);

    pnm_freepamtuple(backgroundColor);
    
    return 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);
}
Exemple #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);
}
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;
}
Exemple #21
0
int
main(int argc, char *argv[]) {

    struct cmdlineInfo cmdline;
    FILE * underlayFileP;
    FILE * overlayFileP;
    FILE * alphaFileP;
    struct pam underlayPam;
    struct pam overlayPam;
    struct pam alphaPam;
    struct pam composedPam;
    int originLeft, originTop;

    pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    overlayFileP = pm_openr(cmdline.overlayFilespec);
    pnm_readpaminit(overlayFileP, &overlayPam, 
                    PAM_STRUCT_SIZE(allocation_depth));
    if (cmdline.alphaFilespec) {
        alphaFileP = pm_openr(cmdline.alphaFilespec);
        pnm_readpaminit(alphaFileP, &alphaPam, 
                        PAM_STRUCT_SIZE(allocation_depth));

        if (overlayPam.width != alphaPam.width || 
            overlayPam.height != alphaPam.height)
            pm_error("Opacity map and overlay image are not the same size");
    } else
        alphaFileP = NULL;

    underlayFileP = pm_openr(cmdline.underlyingFilespec);

    pnm_readpaminit(underlayFileP, &underlayPam, 
                    PAM_STRUCT_SIZE(allocation_depth));

    computeOverlayPosition(underlayPam.width, underlayPam.height, 
                           overlayPam.width,  overlayPam.height,
                           cmdline, &originLeft, &originTop);

    composedPam.size             = sizeof(composedPam);
    composedPam.len              = PAM_STRUCT_SIZE(allocation_depth);
    composedPam.allocation_depth = 0;
    composedPam.file             = pm_openw(cmdline.outputFilespec);

    determineOutputType(&composedPam, &underlayPam, &overlayPam);

    pnm_setminallocationdepth(&underlayPam, composedPam.depth);
    pnm_setminallocationdepth(&overlayPam,  composedPam.depth);
    
    composite(originLeft, originTop,
              &underlayPam, &overlayPam, alphaFileP ? &alphaPam : NULL,
              cmdline.alphaInvert, cmdline.opacity,
              &composedPam, cmdline.linear);

    if (alphaFileP)
        pm_close(alphaFileP);
    pm_close(overlayFileP);
    pm_close(underlayFileP);
    pm_close(composedPam.file);

    /* If the program failed, it previously aborted with nonzero completion
       code, via various function calls.
    */
    return 0;
}
Exemple #22
0
int
main(int argc, const char *argv[]) {

    struct cmdlineInfo cmdline;
    FILE * underlayFileP;
    FILE * overlayFileP;
    FILE * alphaFileP;
    struct pam underlayPam;
    struct pam overlayPam;
    struct pam alphaPam;
    struct pam composedPam;
    int originLeft, originTop;

    pm_proginit(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    overlayFileP = pm_openr(cmdline.overlayFilespec);

    overlayPam.comment_p = NULL;
    pnm_readpaminit(overlayFileP, &overlayPam, 
                    PAM_STRUCT_SIZE(opacity_plane));

    if (overlayPam.len < PAM_STRUCT_SIZE(opacity_plane))
        pm_error("Libnetpbm is too old.  This program requires libnetpbm from "
                 "Netpbm 10.56 (September 2011) or newer");

    if (!overlayPam.visual)
        pm_error("Overlay image has tuple type '%s', which is not a "
                 "standard visual type.  We don't know how to compose.",
                 overlayPam.tuple_type);

    initAlphaFile(cmdline, &overlayPam, &alphaFileP, &alphaPam);

    underlayFileP = pm_openr(cmdline.underlyingFilespec);

    underlayPam.comment_p = NULL;
    pnm_readpaminit(underlayFileP, &underlayPam, 
                    PAM_STRUCT_SIZE(opacity_plane));

    assert(underlayPam.len >= PAM_STRUCT_SIZE(opacity_plane));

    if (!overlayPam.visual)
        pm_error("Overlay image has tuple type '%s', which is not a "
                 "standard visual type.  We don't know how to compose.",
                 overlayPam.tuple_type);
    
    computeOverlayPosition(underlayPam.width, underlayPam.height, 
                           overlayPam.width,  overlayPam.height,
                           cmdline, &originLeft, &originTop);

    composedPam.size             = PAM_STRUCT_SIZE(opacity_plane);
    composedPam.len              = PAM_STRUCT_SIZE(allocation_depth);
    composedPam.allocation_depth = 0;
    composedPam.file             = pm_openw(cmdline.outputFilespec);
    composedPam.comment_p        = NULL;

    determineOutputType(&underlayPam, &overlayPam, &composedPam);

    pnm_setminallocationdepth(&underlayPam, composedPam.depth);
    pnm_setminallocationdepth(&overlayPam,  composedPam.depth);
    
    composite(originLeft, originTop,
              &underlayPam, &overlayPam, alphaFileP ? &alphaPam : NULL,
              cmdline.alphaInvert, cmdline.opacity,
              &composedPam, cmdline.linear, cmdline.mixtransparency);

    if (alphaFileP)
        pm_close(alphaFileP);
    pm_close(overlayFileP);
    pm_close(underlayFileP);
    pm_close(composedPam.file);

    /* If the program failed, it previously aborted with nonzero completion
       code, via various function calls.
    */
    return 0;
}
Exemple #23
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;
}
Exemple #24
0
int 
main(int argc, char **argv)
{
  struct pam *imgs;
  struct pam outimg;
  struct pam p;
  int nfiles;
  int i, j;
  unsigned int q[10];
  coord *coords;
  const char *headfname = NULL;
  const char *datafname = NULL;
  const char *prefix = "";
  FILE *header;
  FILE *data;
  char **names;
  char *c;

  optEntry *option_def = malloc(100*sizeof(optEntry));
      /* Instructions to OptParseOptions3 on how to parse our options.
       */
  optStruct3 opt;

  unsigned int option_def_index;

  option_def_index = 0;   /* incremented by OPTENTRY */
  OPTENT3( 0,  "data",    OPT_STRING, &datafname, NULL, 0);
  OPTENT3( 0,  "header",  OPT_STRING, &headfname, NULL, 0);
  OPTENT3('q', "quality", OPT_UINT,   &qfactor,   NULL, 0);
  OPTENT3('p', "prefix",  OPT_STRING, &prefix,    NULL, 0);
  OPTENT3('0', "0",       OPT_FLAG,   NULL, &q[0],      0);
  OPTENT3('1', "1",       OPT_FLAG,   NULL, &q[1],      0);
  OPTENT3('2', "2",       OPT_FLAG,   NULL, &q[2],      0);
  OPTENT3('3', "3",       OPT_FLAG,   NULL, &q[3],      0);
  OPTENT3('4', "4",       OPT_FLAG,   NULL, &q[4],      0);
  OPTENT3('5', "5",       OPT_FLAG,   NULL, &q[5],      0);
  OPTENT3('6', "6",       OPT_FLAG,   NULL, &q[6],      0);
  OPTENT3('7', "7",       OPT_FLAG,   NULL, &q[7],      0);
  OPTENT3('8', "8",       OPT_FLAG,   NULL, &q[8],      0);
  OPTENT3('9', "9",       OPT_FLAG,   NULL, &q[9],      0);

  opt.opt_table = option_def;
  opt.short_allowed = FALSE;
  opt.allowNegNum = FALSE;

  pnm_init(&argc, argv);

  /* Check for flags. */
  optParseOptions3(&argc, argv, opt, sizeof(opt), 0);

  if (headfname)
    header = pm_openw(headfname);

  if (datafname)
    data = pm_openw(datafname);

  for (i = 0; i < 10; ++i)
  {
    if (q[i])
    {
      quality = i;
      switch (quality)
      {
        case 0: case 1: break;
        case 2: case 3: case 4: case 5: case 6: 
            qfactor = 100 * (8 - quality); 
            break;
        case 7: qfactor = 150; break;
        case 8: qfactor = 125; break;
        case 9: qfactor = 100; break;
      }
    }
  }

  if (1 < argc)
    nfiles = argc - 1;
  else
    nfiles = 1;

  MALLOCARRAY(imgs, nfiles);
  MALLOCARRAY(coords, nfiles);
  MALLOCARRAY(names, nfiles);
  
  if (!imgs || !coords || !names)
    pm_error("out of memory");

  if (1 < argc)
  {
    for (i = 0; i < nfiles; ++i)
    {
      if (strchr(argv[i+1], ':'))
      {
        imgs[i].file = pm_openr(strchr(argv[i+1], ':') + 1);
        *strchr(argv[i+1], ':') = 0;
        names[i] = argv[i+1];
      }
      else
      {
        imgs[i].file = pm_openr(argv[i+1]);
        names[i] = argv[i+1];
      }
    }
  }
  else
  {
    imgs[0].file = stdin;
  }

  pnm_readpaminit(imgs[0].file, &imgs[0], PAM_STRUCT_SIZE(tuple_type));
  outimg.maxval = imgs[0].maxval;
  outimg.format = imgs[0].format;
  memcpy(outimg.tuple_type, imgs[0].tuple_type, sizeof(imgs[0].tuple_type));
  outimg.depth = imgs[0].depth;

  for (i = 1; i < nfiles; ++i)
  {
    pnm_readpaminit(imgs[i].file, &imgs[i], PAM_STRUCT_SIZE(tuple_type));
    if (PAM_FORMAT_TYPE(imgs[i].format) > PAM_FORMAT_TYPE(outimg.format))
      outimg.format = imgs[i].format,
      memcpy(outimg.tuple_type, imgs[i].tuple_type, 
             sizeof(imgs[i].tuple_type));
    outimg.maxval = imax(imgs[i].maxval, outimg.maxval);
    outimg.depth = imax(imgs[i].depth, outimg.depth);
  }

  for (i = 0; i < nfiles - 1; ++i)
    for (j = i + 1; j < nfiles; ++j)
      if (imgs[j].width * imgs[j].height > imgs[i].width * imgs[i].height)
        p = imgs[i], imgs[i] = imgs[j], imgs[j] = p,
        c = names[i], names[i] = names[j], names[j] = c;

  findpack(imgs, nfiles, coords);

  outimg.height = outimg.width = 0;
  for (i = 0; i < nfiles; ++i)
  {
    outimg.width = imax(outimg.width, imgs[i].width + coords[i].x);
    outimg.height = imax(outimg.height, imgs[i].height + coords[i].y);
  }

  outimg.size = sizeof(outimg);
  outimg.len = sizeof(outimg);
  outimg.file = stdout;
  outimg.bytes_per_sample = 0;
  for (i = outimg.maxval; i; i >>= 8)
    ++outimg.bytes_per_sample;

  writePam(&outimg, nfiles, coords, imgs);

  if (datafname)
  {
    fprintf(data, ":0:0:%u:%u\n", outimg.width, outimg.height);

    for (i = 0; i < nfiles; ++i)
    {
      fprintf(data, "%s:%u:%u:%u:%u\n", names[i], coords[i].x,
          coords[i].y, imgs[i].width, imgs[i].height);
    }
  }

  if (headfname)
  {
    fprintf(header, "#define %sOVERALLX %u\n"
                    "#define %sOVERALLY %u\n"
                    "\n",
                    prefix, outimg.width,
                    prefix, outimg.height);

    for (i = 0; i < nfiles; ++i)
    {
      *strchr(names[i], '.') = 0;
      for (j = 0; names[i][j]; ++j)
      {
        if (ISLOWER(names[i][j]))
          names[i][j] = TOUPPER(names[i][j]);
      }
      fprintf(header, "#define %s%sX %u\n"
                      "#define %s%sY %u\n"
                      "#define %s%sSZX %u\n"
                      "#define %s%sSZY %u\n"
                      "\n",
                      prefix, names[i], coords[i].x,
                      prefix, names[i], coords[i].y,
                      prefix, names[i], imgs[i].width,
                      prefix, names[i], imgs[i].height);
    }
  }

  for (i = 0; i < nfiles; ++i)
    pm_close(imgs[i].file);
  pm_close(stdout);

  if (headfname)
    pm_close(header);

  if (datafname)
    pm_close(data);

  return 0;
}
int
main(int argc, char *argv[]) {

    struct cmdlineInfo cmdline;
    FILE* ifP;

    pgm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    srand(cmdline.randomseedSpec ? cmdline.randomseed : pm_randseed());

    ifP = pm_openr(cmdline.inputFilespec);

    if (cmdline.halftone == QT_HILBERT)
        doHilbert(ifP, cmdline.clumpSize);
    else {
        struct converter converter;
        struct pam graypam;
        struct pam bitpam;
        tuplen * grayrow;
        tuple * bitrow;
        int row;

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

        bitpam = makeOutputPam(graypam.width, graypam.height);
        
        pnm_writepaminit(&bitpam);

        switch (cmdline.halftone) {
        case QT_FS:
            converter = createFsConverter(&graypam, cmdline.threshval);
            break;
        case QT_ATKINSON:
            converter = createAtkinsonConverter(&graypam, cmdline.threshval);
            break;
        case QT_THRESH:
            converter = createThreshConverter(&graypam, cmdline.threshval);
            break;
        case QT_DITHER8: 
            converter = createClusterConverter(&graypam, DT_REGULAR, 8); 
            break;
        case QT_CLUSTER: 
            converter = createClusterConverter(&graypam, 
                                               DT_CLUSTER, 
                                               cmdline.clusterRadius);
            break;
        case QT_HILBERT: 
                pm_error("INTERNAL ERROR: halftone is QT_HILBERT where it "
                         "shouldn't be.");
                break;
        }

        grayrow = pnm_allocpamrown(&graypam);
        bitrow  = pnm_allocpamrow(&bitpam);

        for (row = 0; row < graypam.height; ++row) {
            pnm_readpamrown(&graypam, grayrow);

            converter.convertRow(&converter, row, grayrow, bitrow);
            
            pnm_writepamrow(&bitpam, bitrow);
        }
        pnm_freepamrow(bitrow);
        pnm_freepamrow(grayrow);

        if (converter.destroy)
            converter.destroy(&converter);
    }

    pm_close(ifP);

    return 0;
}
Exemple #26
0
static void
convertImage(FILE *             const ifP,
             TIFF *             const tifP,
             const char *       const inputFileDescription,
             struct cmdlineInfo const cmdline) {

    tupletable chv;
    tuplehash cht;
    unsigned short ** tiffColorMap;  /* malloc'ed */
    struct pam pam;
    unsigned int colors;
    bool grayscale;
    unsigned short photometric;
    unsigned short samplesperpixel;
    unsigned short bitspersample;
    unsigned short tiff_maxval;
    /* This is the maxval of the samples in the tiff file.  It is 
       determined solely by the bits per sample ('bitspersample').
       */
    int bytesperrow;
    pm_filepos rasterPos;

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

    pm_tell2(ifP, &rasterPos, sizeof(rasterPos));

    analyzeColors(&pam, cmdline, MAXCOLORS, &chv, &colors, &grayscale);

    /* Go back to beginning of raster */
    pm_seek2(ifP, &rasterPos, sizeof(rasterPos));  

    /* Figure out TIFF parameters. */

    computeRasterParm(&pam, chv, colors, grayscale, 
                      cmdline.compression,
                      cmdline.minisblack, cmdline.miniswhite,
                      cmdline.indexsizeAllowed,
                      &samplesperpixel, &bitspersample, &photometric,
                      &bytesperrow);

    tiff_maxval = pm_bitstomaxval(bitspersample);

    if (!chv) {
        cht = NULL;
        tiffColorMap = NULL;
    } else {
        createTiffColorMap(&pam, bitspersample, chv, colors, &tiffColorMap);

        /* Convert color vector to color hash table, for fast lookup. */
        cht = pnm_computetupletablehash(&pam, chv, colors);
        pnm_freetupletable(&pam, chv);
    }

    setTiffFields(tifP, cmdline, &pam, bitspersample, photometric,
                  samplesperpixel, tiffColorMap, inputFileDescription,
                  cmdline.taglist);

    writeScanLines(&pam, tifP, cht,
                   tiff_maxval, bitspersample, photometric, bytesperrow, 
                   cmdline.fillorder);

    if (tiffColorMap)
        destroyTiffColorMap(&pam, tiffColorMap);
}