static void
writeAnaglyph( FILE *       const ofP,
               gray **      const grayArray,
               gray         const maxGrayVal,
               int          const eyeSep,
               int          const swapEyes,
               struct pam * const pamP) {
/*----------------------------------------------------------------------
  Output an anaglyphic stereogram from the given grayscale array and
  eye-separation value.
------------------------------------------------------------------------*/
    struct pam   outPam;
    tuple      * tuplerow;

    outPam.size        = sizeof(struct pam);
    outPam.len         = PAM_STRUCT_SIZE(tuple_type);
    outPam.file        = ofP;
    outPam.format      = PAM_FORMAT;
    outPam.plainformat = 0;
    outPam.height      = pamP->height;
    outPam.width       = pamP->width - eyeSep;
        /* Avoid color bands on the left/right edges. */
    outPam.depth       = 3;
    outPam.maxval      = (sample) maxGrayVal;
    strcpy(outPam.tuple_type, PAM_PPM_TUPLETYPE);

    pnm_writepaminit( &outPam );

    tuplerow = pnm_allocpamrow( &outPam );

    if (swapEyes) {
        unsigned int row;

        for (row = 0; row < outPam.height; ++row) {
            unsigned int col;
            for (col = 0; col < outPam.width; ++col) {
                tuplerow[col][PAM_RED_PLANE] = grayArray[row][col+eyeSep];
                tuplerow[col][PAM_GRN_PLANE] = grayArray[row][col];
                tuplerow[col][PAM_BLU_PLANE] = grayArray[row][col];
            }
            pnm_writepamrow( &outPam, tuplerow );
        }
    } else {
        unsigned int row;
        for (row = 0; row < outPam.height; ++row) {
            unsigned int col;
            for (col = 0; col < outPam.width; ++col) {
                tuplerow[col][PAM_RED_PLANE] = grayArray[row][col];
                tuplerow[col][PAM_GRN_PLANE] = grayArray[row][col+eyeSep];
                tuplerow[col][PAM_BLU_PLANE] = grayArray[row][col+eyeSep];
            }
            pnm_writepamrow( &outPam, tuplerow );
        }
    }
    pnm_freepamrow( tuplerow );
}
Esempio n. 2
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);
}
Esempio n. 3
0
static void
writeOutput(const struct pam *            const inpamP,
            const unsigned char * const * const pi) {

    tuple black, white;
    tuple * outputTuplerow;
        /* This is not a normal tuplerow; it is just pointers to either
           'black' or 'white'
        */
    unsigned int row;
    struct pam outpam;

    initOutpam(inpamP, &outpam);

    allocateOutputPointerRow(outpam.width, &outputTuplerow);
    pnm_createBlackTuple(&outpam, &black);
    createWhiteTuple(&outpam, &white);

    pnm_writepaminit(&outpam);

    for (row = 0; row < outpam.height; ++row) {
        unsigned int col;
        for (col = 0; col < outpam.width; ++col)
            outputTuplerow[col] = pi[row][col] == PT_BG ? white : black;

        pnm_writepamrow(&outpam, outputTuplerow);
    }
    pnm_freepamtuple(white);
    pnm_freepamtuple(black);
    free(outputTuplerow);
}
Esempio n. 4
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);
}
Esempio n. 5
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);
}
Esempio n. 6
0
static void
thresholdSimple(struct pam * const inpamP,
                struct pam * const outpamP,
                float        const threshold) {

    tuplen * inrow;    /* normalized input row */
    tuple * outrow;    /* raw output row */
    unsigned int row;  /* number of the current row */

    inrow  = pnm_allocpamrown(inpamP);
    outrow = pnm_allocpamrow(outpamP);

    /* do the simple thresholding */
    for (row = 0; row < inpamP->height; ++row) {
        unsigned int col;
        pnm_readpamrown(inpamP, inrow);
        for (col = 0; col < inpamP->width; ++col) {
            thresholdPixel(outpamP, inrow[col], outrow[col], threshold);
        }
        pnm_writepamrow(outpamP, outrow);
    }

    pnm_freepamrow(inrow);
    pnm_freepamrow(outrow);
}
Esempio n. 7
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);
}
Esempio n. 8
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;
}
Esempio n. 9
0
int
main(int argc, char *argv[]) {

    struct cmdlineInfo cmdline;
    struct pam pam;
    tuple * tupleRow;
    tuple * leftEdge;
    tuple * rightEdge;
    unsigned int row;
    
    pnm_init(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    pam.size             = sizeof pam;
    pam.len              = PAM_STRUCT_SIZE(tuple_type);
    pam.file             = stdout;
    pam.plainformat      = 0;
    pam.width            = cmdline.cols;
    pam.height           = cmdline.rows;
    pam.maxval           = cmdline.maxval;
    pam.bytes_per_sample = pnm_bytespersample(pam.maxval);
    pam.format           = PAM_FORMAT;
    if (isgray(&pam, cmdline.colorTopLeft)
            && isgray(&pam, cmdline.colorTopRight)
            && isgray(&pam, cmdline.colorBottomLeft)
            && isgray(&pam, cmdline.colorBottomRight)) {
        pam.depth = 1;
        strcpy(pam.tuple_type, PAM_PGM_TUPLETYPE);
    } else {
        pam.depth = 3;
        strcpy(pam.tuple_type, PAM_PPM_TUPLETYPE);
    }

    pnm_writepaminit(&pam);
    
    tupleRow = pnm_allocpamrow(&pam);

    leftEdge  = createEdge(&pam,
                           cmdline.colorTopLeft, cmdline.colorBottomLeft);
    rightEdge = createEdge(&pam,
                           cmdline.colorTopRight, cmdline.colorBottomRight);

    /* interpolate each row between the left edge and the right edge */
    for (row = 0; row < pam.height; ++row) {
        interpolate(&pam, tupleRow, leftEdge[row], rightEdge[row]);
        pnm_writepamrow(&pam, tupleRow); 
    }

    pm_close(stdout);
    pnm_freepamrow(rightEdge);
    pnm_freepamrow(leftEdge);
    pnm_freepamrow(tupleRow);

    freeCmdline(cmdline);

    return 0;
}
Esempio n. 10
0
static void
writeRowCopies(const struct pam *  const outPamP,
               const tuple *       const outrow,
               unsigned int        const copyCount) {

    unsigned int i;
    for (i = 0; i < copyCount; ++i)
        pnm_writepamrow(outPamP, outrow);
}
Esempio n. 11
0
static void
convertToPamPnm(struct pam *  const outpamP,
                jas_image_t * const jasperP,
                int           const jasperCmptNo[]) {

    jas_matrix_t ** matrix;  /* malloc'ed */
        /* matrix[X] is the data for Plane X of the current row */
    sample * jasperMaxval;
    unsigned int row;
    tuple * tuplerow;
    jas_seqent_t ** jasperRow;   /* malloc'ed */
       /* A row of a plane of the raster from the Jasper library 
          This is an array of pointers into the 'matrix' data structures.
       */
    bool singleMaxval;

    createMatrices(outpamP, &matrix);

    computeComponentMaxval(outpamP, jasperP, jasperCmptNo,
                           &jasperMaxval, &singleMaxval);

    MALLOCARRAY(jasperRow, outpamP->depth);
    if (jasperRow == NULL)
        pm_error("Out of memory");

    tuplerow = pnm_allocpamrow(outpamP);

    for (row = 0; row < outpamP->height; ++row) {
        unsigned int plane;

        for (plane = 0; plane < outpamP->depth; ++plane) {
            int rc;
            rc = jas_image_readcmpt(jasperP, jasperCmptNo[plane], 0, row,
                                    outpamP->width, 1,
                                    matrix[plane]);
            if (rc != 0)
                pm_error("jas_image_readcmpt() of row %u plane %u "
                         "failed.", 
                         row, plane);
            jasperRow[plane] = jas_matrix_getref(matrix[plane], 0, 0);
        }
        if (singleMaxval) 
            copyRowSingleMaxval(jasperRow, tuplerow, outpamP);
        else
            copyRowAnyMaxval(jasperRow, tuplerow, outpamP, jasperMaxval);

        pnm_writepamrow(outpamP, tuplerow);
    }
    pnm_freepamrow(tuplerow);

    destroyMatrices(outpamP, matrix);

    free(jasperRow);
    free(jasperMaxval);
}
Esempio n. 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);
}
Esempio n. 13
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;
}
Esempio n. 14
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);
}
Esempio n. 15
0
static void
writeImgPam(IPDB * const pdbP,
            FILE * const ofP) {

    struct pam pam;
    tuple * tupleRow;
    unsigned int row;
    uint8_t * imgRow;

    MALLOCARRAY(imgRow, ipdb_width(pdbP));

    pam.size             = sizeof(pam);
    pam.len              = PAM_STRUCT_SIZE(tuple_type);
    pam.file             = ofP;
    pam.plainformat      = 0;
    pam.width            = ipdb_width(pdbP);
    pam.height           = ipdb_height(pdbP);
    pam.depth            = 1;
    pam.maxval           = ipdb_type(pdbP) == IMG_MONO ? 1 : 255;
    pam.bytes_per_sample = pnm_bytespersample(pam.maxval);
    pam.format           = PAM_FORMAT;
    strcpy(pam.tuple_type,
           ipdb_type(pdbP) == IMG_MONO ?
           PAM_PBM_TUPLETYPE : PAM_PGM_TUPLETYPE);

    pnm_writepaminit(&pam);
    
    tupleRow = pnm_allocpamrow(&pam);

    for (row = 0; row < pam.height; ++row) {
        unsigned int col;


        if (ipdb_type(pdbP) == IMG_MONO)
            mrow(pdbP, row, imgRow);
        else if (ipdb_type(pdbP) == IMG_GRAY)
            grow(pdbP, row, imgRow);
        else
            g16row(pdbP, row, imgRow);

        for (col = 0; col < pam.width; ++col)
            tupleRow[col][0] = imgRow[col];
        
        pnm_writepamrow(&pam, tupleRow);
    }
    pnm_freepamrow(tupleRow);

    free(imgRow);
}
Esempio n. 16
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);
}
Esempio n. 17
0
static void
writePam(FILE *   const ofP,
         canvas * const canvasP) {

    unsigned int row;
    struct pam pam;
    tuple * tuplerow;

    pam.size             = sizeof(pam);
    pam.len              = PAM_STRUCT_SIZE(tuple_type);
    pam.file             = ofP;
    pam.format           = PAM_FORMAT;
    pam.plainformat      = 0;
    pam.width            = canvasP->width;
    pam.height           = canvasP->height;
    pam.depth            = 3;
    pam.maxval           = OUTPUT_MAXVAL;
    strcpy(pam.tuple_type, PAM_PPM_TUPLETYPE);
    
    pnm_writepaminit(&pam);

    tuplerow = pnm_allocpamrow(&pam);

    for (row = 0; row < (unsigned)pam.height; ++row) {
        pixel * const pixelrow = canvasP->pixels[row];
        unsigned int col;

        for (col = 0; col < (unsigned)pam.width; ++col) {
            pixel const thisPixel = pixelrow[col];
            assert(pam.depth >= 3);

            tuplerow[col][PAM_RED_PLANE] = PPM_GETR(thisPixel);
            tuplerow[col][PAM_GRN_PLANE] = PPM_GETG(thisPixel);
            tuplerow[col][PAM_BLU_PLANE] = PPM_GETB(thisPixel);
        }
        pnm_writepamrow(&pam, tuplerow);
    }
    pnm_freepamrow(tuplerow);
}
Esempio n. 18
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));
}
Esempio n. 19
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);
}
Esempio n. 20
0
static void
thresholdLocal(struct pam *       const inpamP,
               struct pam *       const outpamP,
               struct cmdlineInfo const cmdline) {
/*----------------------------------------------------------------------------
  Threshold the image described by *inpamP, whose file is positioned to the
  raster, and output the resulting raster to the image described by
  *outpamP.

  Use local adaptive thresholding aka dynamic thresholding or dual
  thresholding (global for low contrast areas, LAT otherwise)
-----------------------------------------------------------------------------*/
    struct range globalRange; /* Range of sample values in entire image */
    tuplen ** inrows;
        /* vertical window of image containing the local area.  This is
           a ring of 'windowHeight' rows.  Row R of the image, when it is
           in the window, is inrows[R % windowHeight].
        */
    unsigned int windowHeight;  /* size of 'inrows' window */
    unsigned int nextRowToRead;
        /* Number of the next row to be read from the file into the inrows[]
           buffer.
        */
    tuple * outrow;           /* raw output row */
    unsigned int row;
        /* Number of the current row.  The current row is normally the
           one in the center of the inrows[] buffer (which has an actual
           center row because it is of odd height), but when near the top
           and bottom edge of the image, it is not.
        */
    const unsigned int * histogram;
    samplen globalThreshold;
        /* This is a threshold based on the entire image, to use in areas
           where the contrast is too small to use a locally-derived threshold.
        */
    unsigned int oddLocalWidth;
    unsigned int oddLocalHeight;
    unsigned int i;
    
    /* use a subimage with odd width and height to have a middle pixel */

    if (cmdline.width % 2 == 0)
        oddLocalWidth = cmdline.width + 1;
    else 
        oddLocalWidth = cmdline.width;
    if (cmdline.height % 2 == 0)
        oddLocalHeight = cmdline.height + 1;
    else
        oddLocalHeight = cmdline.height;

    windowHeight = MIN(oddLocalHeight, inpamP->height);

    /* global information is needed for dual thresholding */
    if (cmdline.dual) {
        analyzeDistribution(inpamP, cmdline.verbose, &histogram, &globalRange);
        computeGlobalThreshold(inpamP, histogram, globalRange,
                               &globalThreshold);
    } else {
        histogram = NULL;
        initRange(&globalRange);
        globalThreshold = 1.0;
    }

    outrow = pnm_allocpamrow(outpamP);

    MALLOCARRAY(inrows, windowHeight);

    if (inrows == NULL)
        pm_error("Unable to allocate memory for a %u-row array", windowHeight);

    for (i = 0; i < windowHeight; ++i)
        inrows[i] = pnm_allocpamrown(inpamP);

    /* Fill the vertical window buffer */
    nextRowToRead = 0;

    while (nextRowToRead < windowHeight)
        pnm_readpamrown(inpamP, inrows[nextRowToRead++ % windowHeight]);

    for (row = 0; row < inpamP->height; ++row) {
        thresholdLocalRow(inpamP, inrows, oddLocalWidth, windowHeight, row,
                          cmdline, globalRange, globalThreshold,
                          outpamP, outrow);

        pnm_writepamrow(outpamP, outrow);
        
        /* read next image line if available and necessary */
        if (row + windowHeight / 2 >= nextRowToRead &&
            nextRowToRead < inpamP->height)
            pnm_readpamrown(inpamP, inrows[nextRowToRead++ % windowHeight]);
    }

    free((void*)histogram);
    for (i = 0; i < windowHeight; ++i)
        pnm_freepamrow(inrows[i]);
    free(inrows);
    pnm_freepamrow(outrow);
}
Esempio n. 21
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);
}
Esempio n. 22
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);
}
Esempio n. 23
0
static void
copyRaster(struct pam *       const inpamP, 
           struct pam *       const outpamP,
           tupletable         const colormap, 
           unsigned int       const colormapSize,
           bool               const floyd, 
           bool               const randomize,
           tuple              const defaultColor, 
           unsigned int *     const missingCountP) {

    tuplehash const colorhash = pnm_createtuplehash();

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

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

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

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

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

    usehash = TRUE;

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

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

    *missingCountP = 0;  /* initial value */

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

        pnm_readpamrow(inpamP, inrow);

        convertRow(inpamP, &workpam, inrow,
                   depthAdjustment, colormap, colorFinderP, colorhash,
                   &usehash, floyd, defaultColor,
                   &fserr,  outrow, &missingCount);
        
        *missingCountP += missingCount;
        
        pnm_writepamrow(outpamP, outrow);
    }
    destroyColormapFinder(colorFinderP);
    pnm_freepamrow(inrow);
    pnm_freepamrow(outrow);
    pnm_destroytuplehash(colorhash);
}
Esempio n. 24
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;
}