about summary refs log tree commit diff
path: root/editor/pnmcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/pnmcat.c')
-rw-r--r--editor/pnmcat.c874
1 files changed, 0 insertions, 874 deletions
diff --git a/editor/pnmcat.c b/editor/pnmcat.c
deleted file mode 100644
index 565ecceb..00000000
--- a/editor/pnmcat.c
+++ /dev/null
@@ -1,874 +0,0 @@
-/* pnmcat.c - concatenate PNM images
-**
-** Copyright (C) 1989, 1991 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-*/
-
-#include <assert.h>
-
-#include "pm_c_util.h"
-#include "mallocvar.h"
-#include "shhopt.h"
-#include "bitarith.h"
-#include "nstring.h"
-#include "pnm.h"
-
-#define LEFTBITS pm_byteLeftBits
-#define RIGHTBITS pm_byteRightBits
-
-enum backcolor {BACK_WHITE, BACK_BLACK, BACK_AUTO};
-
-enum orientation {TOPBOTTOM, LEFTRIGHT};
-
-enum justification {JUST_CENTER, JUST_MIN, JUST_MAX};
-
-struct imgInfo {
-    /* This obviously should be a struct pam.  We should convert this
-       to 'pamcat'.
-    */
-    FILE * ifP;
-    int    cols;
-    int    rows;
-    int    format;
-    xelval maxval;
-};
-
-
-
-struct cmdlineInfo {
-    /* All the information the user supplied in the command line,
-       in a form easy for the program to use.
-    */
-    const char ** inputFilespec;
-    unsigned int nfiles;
-    enum backcolor backcolor;
-    enum orientation orientation;
-    enum justification justification;
-};
-
-
-
-static void
-parseCommandLine(int argc, const char ** const argv,
-                 struct cmdlineInfo * const cmdlineP) {
-/*----------------------------------------------------------------------------
-   Note that the file spec array we return is stored in the storage that
-   was passed to us as the argv array.
------------------------------------------------------------------------------*/
-    optEntry * option_def;
-        /* Instructions to OptParseOptions3() on how to parse our options.
-         */
-    optStruct3 opt;
-
-    unsigned int option_def_index;
-
-    unsigned int leftright, topbottom, black, white, jtop, jbottom,
-        jleft, jright, jcenter;
-
-    MALLOCARRAY_NOFAIL(option_def, 100);
-
-    option_def_index = 0;   /* incremented by OPTENTRY */
-    OPTENT3(0, "leftright",  OPT_FLAG,   NULL, &leftright,   0);
-    OPTENT3(0, "lr",         OPT_FLAG,   NULL, &leftright,   0);
-    OPTENT3(0, "topbottom",  OPT_FLAG,   NULL, &topbottom,   0);
-    OPTENT3(0, "tb",         OPT_FLAG,   NULL, &topbottom,   0);
-    OPTENT3(0, "black",      OPT_FLAG,   NULL, &black,       0);
-    OPTENT3(0, "white",      OPT_FLAG,   NULL, &white,       0);
-    OPTENT3(0, "jtop",       OPT_FLAG,   NULL, &jtop,        0);
-    OPTENT3(0, "jbottom",    OPT_FLAG,   NULL, &jbottom,     0);
-    OPTENT3(0, "jleft",      OPT_FLAG,   NULL, &jleft,       0);
-    OPTENT3(0, "jright",     OPT_FLAG,   NULL, &jright,      0);
-    OPTENT3(0, "jcenter",    OPT_FLAG,   NULL, &jcenter,     0);
-
-    opt.opt_table = option_def;
-    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
-    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
-
-    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
-        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
-
-    free(option_def);
-
-    if (leftright + topbottom > 1)
-        pm_error("You may specify only one of -topbottom (-tb) and "
-                 "-leftright (-lr)");
-    else if (leftright)
-        cmdlineP->orientation = LEFTRIGHT;
-    else if (topbottom)
-        cmdlineP->orientation = TOPBOTTOM;
-    else
-        pm_error("You must specify either -leftright or -topbottom");
-
-    if (black + white > 1)
-        pm_error("You may specify only one of -black and -white");
-    else if (black)
-        cmdlineP->backcolor = BACK_BLACK;
-    else if (white)
-        cmdlineP->backcolor = BACK_WHITE;
-    else
-        cmdlineP->backcolor = BACK_AUTO;
-
-    if (jtop + jbottom + jleft + jright + jcenter > 1)
-        pm_error("You may specify onlyone of -jtop, -jbottom, "
-                 "-jleft, and -jright");
-    else {
-        switch (cmdlineP->orientation) {
-        case LEFTRIGHT:
-            if (jleft)
-                pm_error("-jleft is invalid with -leftright");
-            if (jright)
-                pm_error("-jright is invalid with -leftright");
-            if (jtop)
-                cmdlineP->justification = JUST_MIN;
-            else if (jbottom)
-                cmdlineP->justification = JUST_MAX;
-            else if (jcenter)
-                cmdlineP->justification = JUST_CENTER;
-            else
-                cmdlineP->justification = JUST_CENTER;
-            break;
-        case TOPBOTTOM:
-            if (jtop)
-                pm_error("-jtop is invalid with -topbottom");
-            if (jbottom)
-                pm_error("-jbottom is invalid with -topbottom");
-            if (jleft)
-                cmdlineP->justification = JUST_MIN;
-            else if (jright)
-                cmdlineP->justification = JUST_MAX;
-            else if (jcenter)
-                cmdlineP->justification = JUST_CENTER;
-            else
-                cmdlineP->justification = JUST_CENTER;
-            break;
-        }
-    }
-
-    if (argc-1 < 1) {
-        MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, 1);
-        cmdlineP->inputFilespec[0] = "-";
-        cmdlineP->nfiles = 1;
-    } else {
-        unsigned int i;
-        unsigned int stdinCt;
-            /* Number of input files user specified as Standard Input */
-
-        MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, argc-1);
-
-        for (i = 0, stdinCt = 0; i < argc-1; ++i) {
-            cmdlineP->inputFilespec[i] = argv[1+i];
-            if (streq(argv[1+i], "-"))
-                ++stdinCt;
-        }
-        cmdlineP->nfiles = argc-1;
-        if (stdinCt > 1)
-            pm_error("At most one input image can come from Standard Input.  "
-                     "You specified %u", stdinCt);
-    }
-}
-
-
-
-static void
-computeOutputParms(unsigned int     const nfiles,
-                   enum orientation const orientation,
-                   struct imgInfo   const img[],
-                   unsigned int *   const newcolsP,
-                   unsigned int *   const newrowsP,
-                   xelval *         const newmaxvalP,
-                   int *            const newformatP) {
-
-    double newcols, newrows;
-    int newformat;
-    xelval newmaxval;
-
-    unsigned int i;
-
-    newcols = 0;
-    newrows = 0;
-
-    for (i = 0; i < nfiles; ++i) {
-        const struct imgInfo * const imgP = &img[i];
-
-        if (i == 0) {
-            newmaxval = imgP->maxval;
-            newformat = imgP->format;
-        } else {
-            if (PNM_FORMAT_TYPE(imgP->format) > PNM_FORMAT_TYPE(newformat))
-                newformat = imgP->format;
-            if (imgP->maxval > newmaxval)
-                newmaxval = imgP->maxval;
-        }
-        switch (orientation) {
-        case LEFTRIGHT:
-            newcols += imgP->cols;
-            if (imgP->rows > newrows)
-                newrows = imgP->rows;
-            break;
-        case TOPBOTTOM:
-            newrows += imgP->rows;
-            if (imgP->cols > newcols)
-                newcols = imgP->cols;
-            break;
-        }
-    }
-
-    /* Note that while 'double' is not in general a precise numerical type,
-       in the case of a sum of integers which is less than INT_MAX, it
-       is exact, because double's precision is greater than int's.
-    */
-    if (newcols > INT_MAX)
-       pm_error("Output width too large: %.0f.", newcols);
-    if (newrows > INT_MAX)
-       pm_error("Output height too large: %.0f.", newrows);
-
-    *newrowsP   = (unsigned int)newrows;
-    *newcolsP   = (unsigned int)newcols;
-    *newmaxvalP = newmaxval;
-    *newformatP = newformat;
-}
-
-
-
-static void
-copyBitrow(const unsigned char * const source,
-           unsigned char *       const destBitrow,
-           unsigned int          const cols,
-           unsigned int          const offset) {
-/*----------------------------------------------------------------------------
-  Copy from source to destBitrow, without shifting.  Preserve
-  surrounding image data.
------------------------------------------------------------------------------*/
-    unsigned char * const dest = & destBitrow[ offset/8 ];
-        /* Copy destination, with leading full bytes ignored. */
-    unsigned int const rs = offset % 8;
-        /* The "little offset", as measured from start of dest.  Source
-           is already shifted by this value.
-        */
-    unsigned int const trs = (cols + rs) % 8;
-        /* The number of partial bits in the final char. */
-    unsigned int const colByteCnt = pbm_packed_bytes(cols + rs);
-        /* # bytes to process, including partial ones on both ends. */
-    unsigned int const last = colByteCnt - 1;
-
-    unsigned char const origHead = dest[0];
-    unsigned char const origEnd  = dest[last];
-
-    unsigned int i;
-
-    assert(colByteCnt >= 1);
-
-    for (i = 0; i < colByteCnt; ++i)
-        dest[i] = source[i];
-
-    if (rs > 0)
-        dest[0] = LEFTBITS(origHead, rs) | RIGHTBITS(dest[0], 8-rs);
-
-    if (trs > 0)
-        dest[last] = LEFTBITS(dest[last], trs) | RIGHTBITS(origEnd, 8-trs);
-}
-
-
-
-static void
-padFillBitrow(unsigned char * const destBitrow,
-              unsigned char   const padColor,
-              unsigned int    const cols,
-              unsigned int    const offset) {
-/*----------------------------------------------------------------------------
-   Fill destBitrow, starting at offset, with padColor.  padColor is a
-   byte -- 0x00 or 0xff -- not a single bit.
------------------------------------------------------------------------------*/
-    unsigned char * const dest = &destBitrow[offset/8];
-    unsigned int const rs = offset % 8;
-    unsigned int const trs = (cols + rs) % 8;
-    unsigned int const colByteCnt = pbm_packed_bytes(cols + rs);
-    unsigned int const last = colByteCnt - 1;
-
-    unsigned char const origHead = dest[0];
-    unsigned char const origEnd  = dest[last];
-
-    unsigned int i;
-
-    assert(colByteCnt > 0);
-
-    for (i = 0; i < colByteCnt; ++i)
-        dest[i] = padColor;
-
-    if (rs > 0)
-        dest[0] = LEFTBITS(origHead, rs) | RIGHTBITS(dest[0], 8-rs);
-
-    if (trs > 0)
-        dest[last] = LEFTBITS(dest[last], trs) | RIGHTBITS(origEnd, 8-trs);
-}
-
-
-
-/* concatenateLeftRightPBM() and concatenateLeftRightGen()
-   employ almost identical algorithms.
-   The difference is in the data types and functions.
-
-   Same for concatenateTopBottomPBM() and concatenateTopBottomGen().
-*/
-
-
-struct imgInfoPbm2 {
-    /* Information about one image */
-    unsigned char * proberow;
-        /* Top row of image, when background color is
-           auto-determined.
-        */
-    unsigned int offset;
-        /* start position of image, in bits, counting from left
-           edge
-        */
-    unsigned char background;
-        /* Background color.  0x00 means white; 0xff means black */
-    unsigned int padtop;
-        /* Top padding amount */
-};
-
-
-
-static void
-getPbmImageInfo(struct imgInfo        const img[],
-                unsigned int          const nfiles,
-                unsigned int          const newrows,
-                enum justification    const justification,
-                enum backcolor        const backcolor,
-                struct imgInfoPbm2 ** const img2P) {
-/*----------------------------------------------------------------------------
-   Read the first row of each image in img[] and return that and additional
-   information about images as *img2P.
------------------------------------------------------------------------------*/
-    struct imgInfoPbm2 * img2;
-    unsigned int i;
-
-    MALLOCARRAY_NOFAIL(img2, nfiles);
-
-    for (i = 0; i < nfiles; ++i) {
-        switch (justification) {
-        case JUST_MIN:    img2[i].padtop = 0;                           break;
-        case JUST_MAX:    img2[i].padtop = newrows - img[i].rows;       break;
-        case JUST_CENTER: img2[i].padtop = (newrows - img[i].rows) / 2; break;
-        }
-
-        img2[i].offset = (i == 0) ? 0 : img2[i-1].offset + img[i-1].cols;
-
-        if (img[i].rows == newrows)  /* no padding */
-            img2[i].proberow = NULL;
-        else {                   /* determine pad color for image i */
-            switch (backcolor) {
-            case BACK_AUTO: {
-                bit bgBit;
-                img2[i].proberow = pbm_allocrow_packed(img[i].cols+7);
-                pbm_readpbmrow_bitoffset(
-                    img[i].ifP, img2[i].proberow,
-                    img[i].cols, img[i].format, img2[i].offset % 8);
-
-                bgBit = pbm_backgroundbitrow(
-                    img2[i].proberow, img[i].cols, img2[i].offset % 8);
-
-                img2[i].background = bgBit == PBM_BLACK ? 0xff : 0x00;
-            } break;
-            case BACK_BLACK:
-                img2[i].proberow   = NULL;
-                img2[i].background = 0xff;
-                break;
-            case BACK_WHITE:
-                img2[i].proberow   = NULL;
-                img2[i].background = 0x00;
-                break;
-            }
-        }
-    }
-    *img2P = img2;
-}
-
-
-
-static void
-destroyPbmImg2(struct imgInfoPbm2 * const img2,
-               unsigned int         const nfiles) {
-
-    unsigned int i;
-
-    for (i = 0; i < nfiles; ++i) {
-        if (img2[i].proberow)
-            free(img2[i].proberow);
-    }
-    free(img2);
-}
-
-
-
-static void
-concatenateLeftRightPbm(FILE *             const ofP,
-                        unsigned int       const nfiles,
-                        unsigned int       const newcols,
-                        unsigned int       const newrows,
-                        enum justification const justification,
-                        struct imgInfo     const img[],
-                        enum backcolor     const backcolor) {
-
-    unsigned char * const outrow = pbm_allocrow_packed(newcols);
-        /* We use just one outrow.  All padding and image data (with the
-           exception of following img2.proberow) goes directly into this
-           packed PBM row.
-        */
-
-    struct imgInfoPbm2 * img2;
-        /* malloc'ed array, one element per image.  Shadows img[] */
-    unsigned int row;
-
-    getPbmImageInfo(img, nfiles, newrows, justification, backcolor, &img2);
-
-    outrow[pbm_packed_bytes(newcols)-1] = 0x00;
-
-    for (row = 0; row < newrows; ++row) {
-        unsigned int i;
-
-        for (i = 0; i < nfiles; ++i) {
-
-            if ((row == 0 && img2[i].padtop > 0) ||
-                row == img2[i].padtop + img[i].rows) {
-
-                /* This row begins a run of padding, either above or below
-                   file 'i', so set 'outrow' to padding.
-                */
-                padFillBitrow(outrow, img2[i].background, img[i].cols,
-                              img2[i].offset);
-            }
-
-            if (row == img2[i].padtop && img2[i].proberow != NULL) {
-                /* Top row has been read to proberow[] to determine
-                   background.  Copy it to outrow[].
-                */
-                copyBitrow(img2[i].proberow, outrow,
-                           img[i].cols, img2[i].offset);
-            } else if (row >= img2[i].padtop &&
-                       row < img2[i].padtop + img[i].rows) {
-                pbm_readpbmrow_bitoffset(
-                    img[i].ifP, outrow, img[i].cols, img[i].format,
-                    img2[i].offset);
-            } else {
-                /* It's a row of padding, so outrow[] is already set
-                   appropriately.
-                */
-            }
-        }
-        pbm_writepbmrow_packed(ofP, outrow, newcols, 0);
-    }
-
-    destroyPbmImg2(img2, nfiles);
-
-    pbm_freerow_packed(outrow);
-}
-
-
-
-static void
-concatenateTopBottomPbm(FILE *             const ofP,
-                        unsigned int       const nfiles,
-                        int                const newcols,
-                        int                const newrows,
-                        enum justification const justification,
-                        struct imgInfo     const img[],
-                        enum backcolor     const backcolor) {
-
-    unsigned char * const outrow = pbm_allocrow_packed(newcols);
-        /* Like the left-right PBM case, all padding and image data
-           goes directly into outrow.  There is no proberow.
-        */
-    unsigned char background, backgroundPrev;
-        /* 0x00 means white; 0xff means black */
-    unsigned int  padleft;
-    bool          backChange;
-        /* Background color is different from that of the previous
-           input image.
-        */
-
-    unsigned int i;
-    unsigned int row, startRow;
-
-    outrow[pbm_packed_bytes(newcols)-1] = 0x00;
-
-    switch (backcolor){
-    case BACK_AUTO:   /* do nothing */    break;
-    case BACK_BLACK:  background = 0xff;  break;
-    case BACK_WHITE:  background = 0x00;  break;
-    }
-
-    for (i = 0; i < nfiles; ++i) {
-        if (img[i].cols == newcols) {
-            /* No padding */
-            startRow = 0;
-            backChange = FALSE;
-            padleft = 0;
-            outrow[pbm_packed_bytes(newcols)-1] = 0x00;
-        } else {
-            /* Determine amount of padding and color */
-            switch (justification) {
-            case JUST_MIN:     padleft = 0;                           break;
-            case JUST_MAX:     padleft = newcols - img[i].cols;       break;
-            case JUST_CENTER:  padleft = (newcols - img[i].cols) / 2; break;
-            }
-
-            switch (backcolor) {
-            case BACK_AUTO: {
-                bit bgBit;
-
-                startRow = 1;
-
-                pbm_readpbmrow_bitoffset(img[i].ifP,
-                                         outrow, img[i].cols, img[i].format,
-                                         padleft);
-
-                bgBit = pbm_backgroundbitrow(outrow, img[i].cols, padleft);
-                background = bgBit == PBM_BLACK ? 0xff : 0x00;
-
-                backChange = (i == 0 || background != backgroundPrev);
-            } break;
-            case BACK_WHITE:
-            case BACK_BLACK:
-                startRow = 0;
-                backChange = (i==0);
-                break;
-            }
-
-            if (backChange || (i > 0 && img[i-1].cols > img[i].cols)) {
-                unsigned int const padright = newcols - padleft - img[i].cols;
-
-                if (padleft > 0)
-                    padFillBitrow(outrow, background, padleft, 0);
-
-                if (padright > 0)
-                    padFillBitrow(outrow, background, padright,
-                                  padleft + img[i].cols);
-
-            }
-        }
-
-        if (startRow == 1)
-            /* Top row already read for auto background color
-               determination.  Write it out.
-            */
-            pbm_writepbmrow_packed(ofP, outrow, newcols, 0);
-
-        for (row = startRow; row < img[i].rows; ++row) {
-            pbm_readpbmrow_bitoffset(img[i].ifP, outrow, img[i].cols,
-                                     img[i].format, padleft);
-            pbm_writepbmrow_packed(ofP, outrow, newcols, 0);
-        }
-
-        backgroundPrev = background;
-    }
-    pbm_freerow_packed(outrow);
-}
-
-
-
-struct imgGen2 {
-    xel * xelrow;
-    xel * inrow;
-    xel   background;
-    int   padtop;
-};
-
-
-
-static void
-getGenImgInfo(struct imgInfo     const img[],
-              unsigned int       const nfiles,
-              xel *              const newxelrow,
-              unsigned int       const newrows,
-              xelval             const newmaxval,
-              int                const newformat,
-              enum justification const justification,
-              enum backcolor     const backcolor,
-              struct imgGen2 **  const img2P) {
-
-    struct imgGen2 * img2;
-    unsigned int i;
-
-    MALLOCARRAY_NOFAIL(img2, nfiles);
-
-    for (i = 0; i < nfiles; ++i) {
-        switch (justification) {  /* Determine top padding */
-            case JUST_MIN:
-                img2[i].padtop = 0;
-                break;
-            case JUST_MAX:
-                img2[i].padtop = newrows - img[i].rows;
-                break;
-            case JUST_CENTER:
-                img2[i].padtop = (newrows - img[i].rows) / 2;
-                break;
-        }
-
-        img2[i].inrow =
-            (i == 0 ? &newxelrow[0] : img2[i-1].inrow + img[i-1].cols);
-
-        if (img[i].rows == newrows)  /* no padding */
-            img2[i].xelrow = NULL;
-        else {
-            /* Determine pad color */
-            switch (backcolor){
-            case BACK_AUTO:
-                img2[i].xelrow = pnm_allocrow(img[i].cols);
-                pnm_readpnmrow(img[i].ifP, img2[i].xelrow,
-                               img[i].cols, img[i].maxval, img[i].format);
-                pnm_promoteformatrow(img2[i].xelrow, img[i].cols,
-                                     img[i].maxval, img[i].format,
-                                     newmaxval, newformat);
-                img2[i].background = pnm_backgroundxelrow(
-                    img2[i].xelrow, img[i].cols, newmaxval, newformat);
-                break;
-            case BACK_BLACK:
-                img2[i].xelrow = NULL;
-                img2[i].background = pnm_blackxel(newmaxval, newformat);
-                break;
-            case BACK_WHITE:
-                img2[i].xelrow = NULL;
-                img2[i].background = pnm_whitexel(newmaxval, newformat);
-                break;
-            }
-        }
-    }
-    *img2P = img2;
-}
-
-
-
-static void
-concatenateLeftRightGen(FILE *             const ofP,
-                        unsigned int       const nfiles,
-                        unsigned int       const newcols,
-                        unsigned int       const newrows,
-                        xelval             const newmaxval,
-                        int                const newformat,
-                        enum justification const justification,
-                        struct imgInfo     const img[],
-                        enum backcolor     const backcolor) {
-
-    xel * const outrow = pnm_allocrow(newcols);
-    struct imgGen2 * img2;
-    unsigned int row;
-
-    getGenImgInfo(img, nfiles, outrow, newrows,
-                  newmaxval, newformat, justification, backcolor, &img2);
-
-    for (row = 0; row < newrows; ++row) {
-        unsigned int i;
-
-        for (i = 0; i < nfiles; ++i) {
-            if ((row == 0 && img2[i].padtop > 0) ||
-                row == img2[i].padtop + img[i].rows) {
-                /* This row begins a run of padding, either above or below
-                   file 'i', so set 'outrow' to padding.
-                */
-                unsigned int col;
-                for (col = 0; col < img[i].cols; ++col)
-                    img2[i].inrow[col] = img2[i].background;
-            }
-            if (row == img2[i].padtop && img2[i].xelrow) {
-                /* We're at the top row of file 'i', and that row
-                   has already been read to xelrow[] to determine
-                   background.  Copy it to 'outrow'.
-                */
-                unsigned int col;
-                for (col = 0; col < img[i].cols; ++col)
-                    img2[i].inrow[col] = img2[i].xelrow[col];
-
-                free(img2[i].xelrow);
-            } else if (row >= img2[i].padtop &&
-                       row < img2[i].padtop + img[i].rows) {
-                pnm_readpnmrow(
-                    img[i].ifP, img2[i].inrow, img[i].cols, img[i].maxval,
-                    img[i].format);
-                pnm_promoteformatrow(
-                    img2[i].inrow, img[i].cols, img[i].maxval,
-                    img[i].format, newmaxval, newformat);
-            } else {
-                /* It's a row of padding, so outrow[] is already set
-                   appropriately.
-                */
-            }
-        }
-        pnm_writepnmrow(ofP, outrow, newcols, newmaxval, newformat, 0);
-    }
-    pnm_freerow(outrow);
-}
-
-
-
-static void
-concatenateTopBottomGen(FILE *             const ofP,
-                        unsigned int       const nfiles,
-                        int                const newcols,
-                        int                const newrows,
-                        xelval             const newmaxval,
-                        int                const newformat,
-                        enum justification const justification,
-                        struct imgInfo     const img[],
-                        enum backcolor     const backcolor) {
-
-    xel * const newxelrow = pnm_allocrow(newcols);
-    xel * inrow;
-    unsigned int padleft;
-    unsigned int i;
-    unsigned int row, startRow;
-    xel background, backgroundPrev;
-    bool backChange;
-        /* The background color is different from that of the previous
-           input image.
-        */
-
-    switch (backcolor) {
-    case BACK_AUTO: /* do nothing now, determine at start of each image */
-                     break;
-    case BACK_BLACK: background = pnm_blackxel(newmaxval, newformat);
-                     break;
-    case BACK_WHITE: background = pnm_whitexel(newmaxval, newformat);
-                     break;
-    }
-
-    for ( i = 0; i < nfiles; ++i, backgroundPrev = background) {
-        if (img[i].cols == newcols) {
-            /* no padding */
-            startRow = 0;
-            backChange = FALSE;
-            inrow = newxelrow;
-        } else { /* Calculate left padding amount */
-            switch (justification) {
-            case JUST_MIN:    padleft = 0;                            break;
-            case JUST_MAX:    padleft = newcols - img[i].cols;        break;
-            case JUST_CENTER: padleft = (newcols - img[i].cols) / 2;  break;
-            }
-
-            if (backcolor == BACK_AUTO) {
-                /* Determine background color */
-
-                startRow = 1;
-                inrow = &newxelrow[padleft];
-
-                pnm_readpnmrow(img[i].ifP, inrow,
-                               img[i].cols, img[i].maxval, img[i].format);
-                pnm_promoteformatrow(inrow, img[i].cols, img[i].maxval,
-                                     img[i].format,
-                                     newmaxval, newformat);
-                background = pnm_backgroundxelrow(
-                    inrow, img[i].cols, newmaxval, newformat);
-
-                backChange = i==0 || !PNM_EQUAL(background, backgroundPrev);
-            } else {
-                /* background color is constant: black or white */
-                startRow = 0;
-                inrow = &newxelrow[padleft];
-                backChange = (i==0);
-            }
-
-            if (backChange || (i > 0 && img[i-1].cols > img[i].cols)) {
-                unsigned int col;
-
-                for (col = 0; col < padleft; ++col)
-                    newxelrow[col] = background;
-                for (col = padleft + img[i].cols; col < newcols; ++col)
-                    newxelrow[col] = background;
-            }
-        }
-
-        if (startRow == 1)
-            /* Top row already read for auto background
-               color determination.  Write it out. */
-            pnm_writepnmrow(ofP, newxelrow, newcols, newmaxval, newformat, 0);
-
-        for (row = startRow; row < img[i].rows; ++row) {
-            pnm_readpnmrow(img[i].ifP,
-                           inrow, img[i].cols, img[i].maxval, img[i].format);
-            pnm_promoteformatrow(
-                inrow, img[i].cols, img[i].maxval, img[i].format,
-                newmaxval, newformat);
-
-            pnm_writepnmrow(ofP, newxelrow, newcols, newmaxval, newformat, 0);
-        }
-    }
-    pnm_freerow(newxelrow);
-}
-
-
-
-int
-main(int           argc,
-     const char ** argv) {
-
-    struct cmdlineInfo cmdline;
-    struct imgInfo * img;  /* malloc'ed array */
-    xelval newmaxval;
-    int newformat;
-    unsigned int i;
-    unsigned int newrows, newcols;
-
-    pm_proginit(&argc, argv);
-
-    parseCommandLine(argc, argv, &cmdline);
-
-    MALLOCARRAY_NOFAIL(img, cmdline.nfiles);
-
-    for (i = 0; i < cmdline.nfiles; ++i) {
-        img[i].ifP = pm_openr(cmdline.inputFilespec[i]);
-        pnm_readpnminit(img[i].ifP, &img[i].cols, &img[i].rows,
-                        &img[i].maxval, &img[i].format);
-    }
-
-    computeOutputParms(cmdline.nfiles, cmdline.orientation, img,
-                       &newcols, &newrows, &newmaxval, &newformat);
-
-    pnm_writepnminit(stdout, newcols, newrows, newmaxval, newformat, 0);
-
-    if (PNM_FORMAT_TYPE(newformat) == PBM_TYPE) {
-        switch (cmdline.orientation) {
-        case LEFTRIGHT:
-            concatenateLeftRightPbm(stdout, cmdline.nfiles,
-                                    newcols, newrows, cmdline.justification,
-                                    img, cmdline.backcolor);
-            break;
-        case TOPBOTTOM:
-            concatenateTopBottomPbm(stdout, cmdline.nfiles,
-                                    newcols, newrows, cmdline.justification,
-                                    img, cmdline.backcolor);
-            break;
-        }
-    } else {
-        switch (cmdline.orientation) {
-        case LEFTRIGHT:
-            concatenateLeftRightGen(stdout, cmdline.nfiles,
-                                    newcols, newrows, newmaxval, newformat,
-                                    cmdline.justification, img,
-                                    cmdline.backcolor);
-            break;
-        case TOPBOTTOM:
-            concatenateTopBottomGen(stdout, cmdline.nfiles,
-                                    newcols, newrows, newmaxval, newformat,
-                                    cmdline.justification, img,
-                                    cmdline.backcolor);
-            break;
-        }
-    }
-    for (i = 0; i < cmdline.nfiles; ++i)
-        pm_close(img[i].ifP);
-    free(cmdline.inputFilespec);
-    free(img);
-    pm_close(stdout);
-
-    return 0;
-}
-
-
-