diff options
Diffstat (limited to 'editor/specialty')
-rw-r--r-- | editor/specialty/pamdeinterlace.c | 27 | ||||
-rw-r--r-- | editor/specialty/pamoil.c | 233 | ||||
-rw-r--r-- | editor/specialty/pnmindex.c | 338 |
3 files changed, 371 insertions, 227 deletions
diff --git a/editor/specialty/pamdeinterlace.c b/editor/specialty/pamdeinterlace.c index 666daa16..a21484a9 100644 --- a/editor/specialty/pamdeinterlace.c +++ b/editor/specialty/pamdeinterlace.c @@ -8,6 +8,8 @@ Contributed to the public domain. ******************************************************************************/ +#include <stdbool.h> + #include "pm_c_util.h" #include "pam.h" #include "shhopt.h" @@ -15,7 +17,7 @@ enum evenodd {EVEN, ODD}; -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -24,9 +26,10 @@ struct cmdlineInfo { }; + static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo *cmdlineP) { +parseCommandLine(int argc, const char ** 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. @@ -44,10 +47,10 @@ parseCommandLine(int argc, char ** argv, OPTENT3(0, "takeodd", OPT_FLAG, NULL, &takeodd, 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 */ + 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, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ free(option_def); @@ -65,26 +68,24 @@ parseCommandLine(int argc, char ** argv, else if (argc-1 == 1) cmdlineP->inputFilespec = argv[1]; else - pm_error("You specified too many arguments (%d). The only " - "argument is the optional input file specification.", + pm_error("You specified too many arguments (%u). The only " + "possible argument is the optional input file specification.", argc-1); } - - int -main(int argc, char *argv[]) { +main(int argc, const char ** argv) { FILE * ifP; tuple * tuplerow; /* Row from input image */ unsigned int row; - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; struct pam inpam; struct pam outpam; - pnm_init( &argc, argv ); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); diff --git a/editor/specialty/pamoil.c b/editor/specialty/pamoil.c index 2618ac12..d7b76e85 100644 --- a/editor/specialty/pamoil.c +++ b/editor/specialty/pamoil.c @@ -1,4 +1,4 @@ -/* pgmoil.c - read a portable pixmap and turn into an oil painting +/* pgmoil.c - read a PPM image and turn into an oil painting ** ** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com) ** Shamelessly butchered into a color version by Chris Sheppard @@ -12,60 +12,153 @@ ** implied warranty. */ +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include "pam.h" + #include "mallocvar.h" +#include "shhopt.h" +#include "pam.h" + + + +struct CmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileNm; + unsigned int n; +}; + + + +static void +parseCommandLine(int argc, const char ** 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. +-----------------------------------------------------------------------------*/ + optStruct3 opt; /* set by OPTENT3 */ + optEntry * option_def; + unsigned int option_def_index; + + unsigned int nSpec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "n", OPT_UINT, &cmdlineP->n, &nSpec, 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 (!nSpec) + cmdlineP->n = 3; + + if (argc-1 < 1) + cmdlineP->inputFileNm = "-"; + else if (argc-1 == 1) + cmdlineP->inputFileNm = argv[1]; + else + pm_error("You specified too many arguments (%u). The only " + "possible argument is the optional input file specification.", + argc-1); +} + + + +static void +computeRowHist(struct pam const inpam, + tuple ** const tuples, + unsigned int const smearFactor, + unsigned int const plane, + unsigned int const row, + unsigned int const col, + sample * const hist) { +/*---------------------------------------------------------------------------- + Compute hist[] - frequencies, in the neighborhood of row 'row', column + 'col', in plane 'plane', of each sample value +-----------------------------------------------------------------------------*/ + sample i; + int drow; + + for (i = 0; i <= inpam.maxval; ++i) + hist[i] = 0; + + for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) { + if (drow >= 0 && drow < inpam.height) { + int dcol; + + for (dcol = col - smearFactor; + dcol <= col + smearFactor; + ++dcol) { + if (dcol >= 0 && dcol < inpam.width) + ++hist[tuples[drow][dcol][plane]]; + } + } + } +} + + + +static sample +modalValue(sample * const hist, + sample const maxval) { +/*---------------------------------------------------------------------------- + The sample value that occurs most often according to histogram hist[]. +-----------------------------------------------------------------------------*/ + sample modalval; + unsigned int maxfreq; + sample sampleval; + + for (sampleval = 0, maxfreq = 0, modalval = 0; + sampleval <= maxval; + ++sampleval) { + + if (hist[sampleval] > maxfreq) { + maxfreq = hist[sampleval]; + modalval = sampleval; + } + } + return modalval; +} + + static void -convertRow(struct pam const inpam, tuple ** const tuples, - tuple * const tuplerow, int const row, int const smearFactor, - int * const hist) { +convertRow(struct pam const inpam, + tuple ** const tuples, + tuple * const tuplerow, + unsigned int const row, + unsigned int const smearFactor, + sample * const hist) { +/*---------------------------------------------------------------------------- + 'hist' is a working buffer inpam.width wide. +-----------------------------------------------------------------------------*/ + unsigned int plane; + + for (plane = 0; plane < inpam.depth; plane++) { + unsigned int col; - int sample; - for (sample = 0; sample < inpam.depth; sample++) { - int col; for (col = 0; col < inpam.width; ++col) { - int i; - int drow; - int modalval; + sample modalval; /* The sample value that occurs most often in the neighborhood - of the pixel being examined + of column 'col' of row 'row', in plane 'plane'. */ - /* Compute hist[] - frequencies, in the neighborhood, of each - sample value - */ - for (i = 0; i <= inpam.maxval; ++i) hist[i] = 0; - - for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) { - if (drow >= 0 && drow < inpam.height) { - int dcol; - for (dcol = col - smearFactor; - dcol <= col + smearFactor; - ++dcol) { - if ( dcol >= 0 && dcol < inpam.width ) - ++hist[tuples[drow][dcol][sample]]; - } - } - } - { - /* Compute modalval */ - int sampleval; - int maxfreq; - - maxfreq = 0; - modalval = 0; - - for (sampleval = 0; sampleval <= inpam.maxval; ++sampleval) { - if (hist[sampleval] > maxfreq) { - maxfreq = hist[sampleval]; - modalval = sampleval; - } - } - } - tuplerow[col][sample] = modalval; + computeRowHist(inpam, tuples, smearFactor, plane, row, col, hist); + + modalval = modalValue(hist, inpam.maxval); + + tuplerow[col][plane] = modalval; } } } @@ -73,44 +166,24 @@ convertRow(struct pam const inpam, tuple ** const tuples, int -main(int argc, char *argv[] ) { +main(int argc, const char ** argv) { + struct pam inpam, outpam; - FILE* ifp; - tuple ** tuples; - tuple * tuplerow; - int * hist; + FILE * ifP; + tuple ** tuples; /* malloc'ed */ + tuple * tuplerow; /* malloc'ed */ + sample * hist; /* malloc'ed */ /* A buffer for the convertRow subroutine to use */ - int argn; int row; - int smearFactor; - const char* const usage = "[-n <n>] [ppmfile]"; - - ppm_init( &argc, argv ); - - argn = 1; - smearFactor = 3; /* DEFAULT VALUE */ - - /* Check for options. */ - if ( argn < argc && argv[argn][0] == '-' ) { - if ( argv[argn][1] == 'n' ) { - ++argn; - if ( argn == argc || sscanf(argv[argn], "%d", &smearFactor) != 1 ) - pm_usage( usage ); - } else - pm_usage( usage ); - ++argn; - } - if ( argn < argc ) { - ifp = pm_openr( argv[argn] ); - ++argn; - } else - ifp = stdin; + struct CmdlineInfo cmdline; + + pm_proginit(&argc, argv); - if ( argn != argc ) - pm_usage( usage ); + parseCommandLine(argc, argv, &cmdline); - tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type)); - pm_close(ifp); + ifP = pm_openr(cmdline.inputFileNm); + + tuples = pnm_readpam(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); MALLOCARRAY(hist, inpam.maxval + 1); if (hist == NULL) @@ -123,7 +196,7 @@ main(int argc, char *argv[] ) { tuplerow = pnm_allocpamrow(&inpam); for (row = 0; row < inpam.height; ++row) { - convertRow(inpam, tuples, tuplerow, row, smearFactor, hist); + convertRow(inpam, tuples, tuplerow, row, cmdline.n, hist); pnm_writepamrow(&outpam, tuplerow); } @@ -131,7 +204,9 @@ main(int argc, char *argv[] ) { free(hist); pnm_freepamarray(tuples, &inpam); + pm_close(ifP); pm_close(stdout); - exit(0); + return 0; } + diff --git a/editor/specialty/pnmindex.c b/editor/specialty/pnmindex.c index dcb183ef..0214ee8b 100644 --- a/editor/specialty/pnmindex.c +++ b/editor/specialty/pnmindex.c @@ -2,7 +2,7 @@ pnmindex ============================================================================== - build a visual index of a bunch of PNM images + Build a visual index of a bunch of PNM images. This used to be a C shell program, and then a BASH program. Neither were portable enough, and the program is too complex for either of @@ -32,6 +32,7 @@ #include "shhopt.h" #include "mallocvar.h" #include "nstring.h" +#include "pm_system.h" #include "pnm.h" struct CmdlineInfo { @@ -53,57 +54,6 @@ static bool verbose; -static void PM_GNU_PRINTF_ATTR(1,2) -systemf(const char * const fmt, - ...) { - - va_list varargs; - - size_t dryRunLen; - - va_start(varargs, fmt); - - dryRunLen = vsnprintf(NULL, 0, fmt, varargs); - - va_end(varargs); - - if (dryRunLen + 1 < dryRunLen) - /* arithmetic overflow */ - pm_error("Command way too long"); - else { - size_t const allocSize = dryRunLen + 1; - char * shellCommand; - shellCommand = malloc(allocSize); - if (shellCommand == NULL) - pm_error("Can't get storage for %u-character command", - (unsigned)allocSize); - else { - va_list varargs; - size_t realLen; - int rc; - - va_start(varargs, fmt); - - realLen = vsnprintf(shellCommand, allocSize, fmt, varargs); - - assert(realLen == dryRunLen); - va_end(varargs); - - if (verbose) - pm_message("shell cmd: %s", shellCommand); - - rc = system(shellCommand); - if (rc != 0) - pm_error("shell command '%s' failed. rc %d", - shellCommand, rc); - - pm_strfree(shellCommand); - } - } -} - - - static const char * shellQuote(const char * const arg) { /*---------------------------------------------------------------------------- @@ -170,7 +120,7 @@ shellQuote(const char * const arg) { static void -parseCommandLine(int argc, char ** argv, +parseCommandLine(int argc, const char ** argv, struct CmdlineInfo * const cmdlineP) { unsigned int option_def_index; @@ -206,19 +156,28 @@ parseCommandLine(int argc, char ** argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ if (quant && cmdlineP->noquant) - pm_error("You can't specify both -quant and -noquat"); + pm_error("You can't specify both -quant and -noquant"); - if (!colorsSpec) + if (colorsSpec) { + if (cmdlineP->colors == 0) + pm_error("-colors value must be positive"); + } else cmdlineP->colors = 256; - if (!sizeSpec) + if (sizeSpec) { + if (cmdlineP->size == 0) + pm_error("-size value must be positive"); + } else cmdlineP->size = 100; - if (!acrossSpec) + if (acrossSpec) { + if (cmdlineP->across == 0) + pm_error("-across value must be positive"); + } else cmdlineP->across = 6; if (!titleSpec) @@ -340,85 +299,118 @@ static void makeTitle(const char * const title, unsigned int const rowNumber, bool const blackBackground, - const char * const tempDir) { + const char * const dirNm) { +/*---------------------------------------------------------------------------- + Create a PBM file containing the text 'title'. + + If 'blackBackground' is true, make it white on black; otherwise, black + on white. + Name the file like a thumbnail row file for row number 'rowNumber', + in directory named 'dirNm'. +-----------------------------------------------------------------------------*/ const char * const invertStage = blackBackground ? "| pnminvert " : ""; - const char * const titleToken = shellQuote(title); const char * fileName; + FILE * outFP; + struct bufferDesc titleBuf; + const char * shellCommand; + int termStatus; - fileName = rowFileName(tempDir, rowNumber); - - /* This quoting is not adequate. We really should do this without - a shell at all. - */ - systemf("pbmtext %s %s > %s", - titleToken, invertStage, fileName); + titleBuf.size = strlen(title); + titleBuf.buffer = (unsigned char *)title; + titleBuf.bytesTransferredP = NULL; + fileName = rowFileName(dirNm, rowNumber); + outFP = pm_openw(fileName); pm_strfree(fileName); - pm_strfree(titleToken); + + pm_asprintf(&shellCommand, "pbmtext %s", invertStage); + + pm_system2(&pm_feed_from_memory, &titleBuf, + &pm_accept_to_filestream, outFP, + shellCommand, &termStatus); + + pm_strfree(shellCommand); + + if (termStatus != 0) + pm_error("Failed to generate title image"); + + pm_close(outFP); } static void -copyImage(const char * const inputFileName, - const char * const outputFileName) { +copyImage(const char * const inputFileNm, + const char * const outputFileNm) { - const char * const inputFileNmToken = shellQuote(inputFileName); + int termStatus; - systemf("cat %s > %s", inputFileNmToken, outputFileName); + pm_system2_lp("cat", + &pm_feed_from_file, (void*)inputFileNm, + &pm_accept_to_file, (void*)outputFileNm, + &termStatus, + "cat", NULL); - pm_strfree(inputFileNmToken); + if (termStatus != 0) + pm_error("'cat' to copy image '%s' to '%s' failed, " + "termination status = %d", + inputFileNm, outputFileNm, termStatus); } static void -copyScaleQuantImage(const char * const inputFileName, - const char * const outputFileName, +copyScaleQuantImage(const char * const inputFileNm, + const char * const outputFileNm, int const format, unsigned int const size, unsigned int const quant, - unsigned int const colors) { - - const char * const inputFileNmToken = shellQuote(inputFileName); + unsigned int const colorCt) { const char * scaleCommand; + int termStatus; switch (PNM_FORMAT_TYPE(format)) { case PBM_TYPE: pm_asprintf(&scaleCommand, - "pamscale -quiet -xysize %u %u %s " - "| pgmtopbm > %s", - size, size, inputFileNmToken, outputFileName); + "pamscale -quiet -xysize %u %u " + "| pamditherbw", + size, size); break; case PGM_TYPE: pm_asprintf(&scaleCommand, - "pamscale -quiet -xysize %u %u %s >%s", - size, size, inputFileNmToken, outputFileName); + "pamscale -quiet -xysize %u %u", + size, size); break; case PPM_TYPE: if (quant) pm_asprintf(&scaleCommand, - "pamscale -quiet -xysize %u %u %s " - "| pnmquant -quiet %u > %s", - size, size, inputFileNmToken, colors, outputFileName); + "pamscale -quiet -xysize %u %u " + "| pnmquant -quiet %u ", + size, size, colorCt); else pm_asprintf(&scaleCommand, - "pamscale -quiet -xysize %u %u %s >%s", - size, size, inputFileNmToken, outputFileName); + "pamscale -quiet -xysize %u %u ", + size, size); break; default: pm_error("Unrecognized Netpbm format: %d", format); } - systemf("%s", scaleCommand); + pm_system2(pm_feed_from_file, (void*)inputFileNm, + pm_accept_to_file, (void*)outputFileNm, + scaleCommand, + &termStatus); + + if (termStatus != 0) + pm_message("Shell command '%s' failed. Termination status=%d", + scaleCommand, termStatus); pm_strfree(scaleCommand); - pm_strfree(inputFileNmToken); } @@ -485,10 +477,10 @@ thumbnailFileList(const char * const dirName, static void -makeImageFile(const char * const thumbnailFileName, - const char * const inputFileName, +makeImageFile(const char * const thumbnailFileNm, + const char * const inputFileNm, bool const blackBackground, - const char * const outputFileName) { + const char * const outputFileNm) { /*---------------------------------------------------------------------------- Create one thumbnail image. It consists of the image in the file named 'thumbnailFileName' with text of that name appended to the bottom. @@ -501,15 +493,34 @@ makeImageFile(const char * const thumbnailFileName, -----------------------------------------------------------------------------*/ const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; const char * const invertStage = blackBackground ? "| pnminvert " : ""; - const char * inputFileNmToken = shellQuote(inputFileName); - - systemf("pbmtext %s %s" - "| pamcat %s -topbottom %s - " - "> %s", - inputFileNmToken, invertStage, blackWhiteOpt, - thumbnailFileName, outputFileName); - - pm_strfree(inputFileNmToken); + const char * const thumbnailFileNmToken = shellQuote(thumbnailFileNm); + + struct bufferDesc fileNmBuf; + const char * shellCommand; + int termStatus; + + fileNmBuf.size = strlen(inputFileNm); + fileNmBuf.buffer = (unsigned char *)inputFileNm; + fileNmBuf.bytesTransferredP = NULL; + + pm_asprintf(&shellCommand, + "pbmtext " + "%s" + "| pamcat %s -topbottom %s - ", + invertStage, blackWhiteOpt, thumbnailFileNmToken); + + pm_system2(&pm_feed_from_memory, &fileNmBuf, + &pm_accept_to_file, (void*)outputFileNm, + shellCommand, + &termStatus); + + if (termStatus != 0) + pm_error("Shell command '%s' to add file name to thumbnail image " + "of file '%s' failed, termination Status = %d", + shellCommand, inputFileNm, termStatus); + + pm_strfree(thumbnailFileNmToken); + pm_strfree(shellCommand); } @@ -519,17 +530,18 @@ makeThumbnail(const char * const inputFileName, unsigned int const size, bool const black, bool const quant, - unsigned int const colors, + unsigned int const colorCt, const char * const tempDir, unsigned int const row, unsigned int const col, int * const formatP) { + const char * const fileName = thumbnailFileName(tempDir, row, col); + FILE * ifP; int imageCols, imageRows, format; xelval maxval; const char * tmpfile; - const char * fileName; ifP = pm_openr(inputFileName); pnm_readpnminit(ifP, &imageCols, &imageRows, &maxval, &format); @@ -541,9 +553,7 @@ makeThumbnail(const char * const inputFileName, copyImage(inputFileName, tmpfile); else copyScaleQuantImage(inputFileName, tmpfile, format, - size, quant, colors); - - fileName = thumbnailFileName(tempDir, row, col); + size, quant, colorCt); makeImageFile(tmpfile, inputFileName, black, fileName); @@ -594,40 +604,66 @@ unlinkRowFiles(const char * const dirName, static void combineIntoRowAndDelete(unsigned int const row, - unsigned int const cols, + unsigned int const colCt, int const maxFormatType, bool const blackBackground, bool const quant, - unsigned int const colors, + unsigned int const colorCt, const char * const tempDir) { +/*---------------------------------------------------------------------------- + Combine the 'colCt' thumbnails for row 'row' into a PNM file in directory + 'tempDir'. + + Each thumbnail is from a specially named file in 'tempDir' whose name + indicates its position in the row, and the output is also specially named + with a name indicating it is row 'row'. + + Where the thumnails are different heights, pad with black if + 'blackBackground' is true; white otherwise. + If 'quant', color-quantize the result to have no more than 'colorCt' + colors, choosing the colors that best represent all the pixels in the + result. + + 'maxFormatType' is the most expressive format of all the thumbnail files; + results are undefined if it is not. +-----------------------------------------------------------------------------*/ const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; + const char * const fileNm = rowFileName(tempDir, row); - const char * fileName; const char * quantStage; const char * fileList; + const char * shellCommand; + int termStatus; - fileName = rowFileName(tempDir, row); - - unlink(fileName); + unlink(fileNm); if (maxFormatType == PPM_TYPE && quant) - pm_asprintf(&quantStage, "| pnmquant -quiet %u ", colors); + pm_asprintf(&quantStage, "| pnmquant -quiet %u ", colorCt); else quantStage = strdup(""); - fileList = thumbnailFileList(tempDir, row, cols); + fileList = thumbnailFileList(tempDir, row, colCt); + + pm_asprintf(&shellCommand, "pamcat %s -leftright -jbottom %s " + "%s", + blackWhiteOpt, fileList, quantStage); - systemf("pamcat %s -leftright -jbottom %s " - "%s" - ">%s", - blackWhiteOpt, fileList, quantStage, fileName); + pm_system2(&pm_feed_null, NULL, + &pm_accept_to_file, (void*)fileNm, + shellCommand, + &termStatus); + + if (termStatus != 0) + pm_error("Shell command '%s' to create row of thumbnails failed. " + "Termination status = %d", shellCommand, termStatus); pm_strfree(fileList); pm_strfree(quantStage); - pm_strfree(fileName); + pm_strfree(fileNm); + pm_strfree(shellCommand); - unlinkThumbnailFiles(tempDir, row, cols); + unlinkThumbnailFiles(tempDir, row, colCt); } @@ -666,38 +702,70 @@ rowFileList(const char * const dirName, static void -writeRowsAndDelete(unsigned int const rows, +writeRowsAndDelete(unsigned int const rowCt, int const maxFormatType, bool const blackBackground, bool const quant, - unsigned int const colors, + unsigned int const colorCt, const char * const tempDir) { +/*---------------------------------------------------------------------------- + Write the PNM image containing the 'rowCt' rows of thumbnails to Standard + Output. Take each row of thumbnails from a specially named PNM file in + directory 'tempDir', and unlink it from that directory. + + Where the rows are different widths, pad with black if 'blackBackground' + is true; white otherwise. + + If 'quant', color-quantize the result to have no more than 'colorCt' + colors, choosing the colors that best represent all the pixels in the + result. + 'maxFormatType' is the most expressive format of all the row files; results + are undefined if it is not. +-----------------------------------------------------------------------------*/ const char * const blackWhiteOpt = blackBackground ? "-black" : "-white"; + const char * const plainOpt = pm_plain_output ? "-plain" : ""; const char * quantStage; const char * fileList; + const char * shellCommand; + int termStatus; if (maxFormatType == PPM_TYPE && quant) - pm_asprintf(&quantStage, "| pnmquant -quiet %u ", colors); + pm_asprintf(&quantStage, "| pnmquant -quiet %u ", colorCt); else quantStage = strdup(""); - fileList = rowFileList(tempDir, rows); + fileList = rowFileList(tempDir, rowCt); + + pm_asprintf(&shellCommand, "pamcat %s %s -topbottom %s %s", + plainOpt, blackWhiteOpt, fileList, quantStage); + + /* Do pamcat/pnmquant command with no Standard Input and writing to + our Standard Output + */ + pm_system2(&pm_feed_null, NULL, + NULL, NULL, + shellCommand, + &termStatus); - systemf("pamcat %s -topbottom %s %s", - blackWhiteOpt, fileList, quantStage); + if (termStatus != 0) + pm_error("Shell command '%s' to assemble %u rows of thumbnails and " + "write them out failed; termination status = %d", + shellCommand, rowCt, termStatus); + pm_strfree(shellCommand); pm_strfree(fileList); pm_strfree(quantStage); - unlinkRowFiles(tempDir, rows); + unlinkRowFiles(tempDir, rowCt); } int -main(int argc, char *argv[]) { +main(int argc, const char ** argv) { + struct CmdlineInfo cmdline; const char * tempDir; int maxFormatType; @@ -705,7 +773,7 @@ main(int argc, char *argv[]) { unsigned int rowsDone; unsigned int i; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -713,14 +781,15 @@ main(int argc, char *argv[]) { makeTempDir(&tempDir); - maxFormatType = PBM_TYPE; - colsInRow = 0; - rowsDone = 0; + rowsDone = 0; /* initial value */ if (cmdline.title) makeTitle(cmdline.title, rowsDone++, cmdline.black, tempDir); - for (i = 0; i < cmdline.inputFileCount; ++i) { + for (i = 0, colsInRow = 0, maxFormatType = PBM_TYPE; + i < cmdline.inputFileCount; + ++i) { + const char * const inputFileName = cmdline.inputFileName[i]; int format; @@ -755,4 +824,3 @@ main(int argc, char *argv[]) { } - |