about summary refs log tree commit diff
path: root/other/pamlookup.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /other/pamlookup.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'other/pamlookup.c')
-rw-r--r--other/pamlookup.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/other/pamlookup.c b/other/pamlookup.c
new file mode 100644
index 00000000..2651d596
--- /dev/null
+++ b/other/pamlookup.c
@@ -0,0 +1,299 @@
+/*============================================================================
+                               pamlookup
+==============================================================================
+
+  Look up integers or ordered pairs from an index image in a lookup table and
+  produce a corresponding image containing the results of the lookups.
+  
+  The index image and lookup table are PAM images.  The output image is
+  a PAM image with the width and height of the index image and tuples of
+  the kind in the lookup table.
+
+  By Bryan Henderson, San Jose CA 2002.11.10
+
+============================================================================*/
+
+#include "pam.h"
+#include "shhopt.h"
+#include "pm_system.h"
+#include "nstring.h"
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char *indexFilespec;  
+    char *lookupFilespec;
+    char *missingcolor;  /* -missingcolor value.  null if not specified */
+    unsigned int fit;  /* -fit option */
+};
+
+
+
+static void
+parseCommandLine(int argc, 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 = malloc(100*sizeof(optEntry));
+        /* Instructions to OptParseOptions2 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+    
+    unsigned int lookupfileSpec, missingcolorSpec;
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0, "lookupfile",     OPT_STRING, &cmdlineP->lookupFilespec,  
+            &lookupfileSpec, 0);
+    OPTENT3(0,   "missingcolor", OPT_STRING, 
+            &cmdlineP->missingcolor,   &missingcolorSpec, 0);
+    OPTENT3(0,   "fit", OPT_FLAG, 
+            NULL,   &cmdlineP->fit, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We may have parms that are negative numbers */
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (!lookupfileSpec)
+        pm_error("You must specify the -lookupfile option");
+
+    if (!missingcolorSpec)
+        cmdlineP->missingcolor = NULL;
+
+    if (argc-1 < 1)
+        cmdlineP->indexFilespec = "-";
+    else
+        cmdlineP->indexFilespec = argv[1];
+}        
+
+
+
+static void
+fitLookup(tuple **     const inputLookup, 
+          struct pam   const inputLookuppam,
+          tuple ***    const fitLookupP,
+          struct pam * const fitLookuppamP,
+          unsigned int const cols,
+          unsigned int const rows) {
+/*----------------------------------------------------------------------------
+  Scale the lookup table image so that it has dimensions 'cols' x 'rows'.
+-----------------------------------------------------------------------------*/
+    const char * pamscaleCommand;
+    struct pamtuples inPamtuples;
+    struct pamtuples outPamtuples;
+
+    *fitLookuppamP = inputLookuppam;
+    fitLookuppamP->width = cols;
+    fitLookuppamP->height = rows;
+
+    asprintfN(&pamscaleCommand, "pamscale -width=%u -height=%u", cols, rows);
+
+    inPamtuples.pamP = (struct pam *) &inputLookuppam;
+    inPamtuples.tuplesP = (tuple ***) &inputLookup;
+    outPamtuples.pamP = fitLookuppamP;
+    outPamtuples.tuplesP = fitLookupP;
+    
+    pm_system(&pm_feed_from_pamtuples, &inPamtuples,
+              &pm_accept_to_pamtuples, &outPamtuples,
+              pamscaleCommand);
+
+    strfree(pamscaleCommand);
+}
+
+
+
+static void
+getLookup(const char * const lookupFilespec, 
+          unsigned int const indexDegree,
+          unsigned int const indexMaxval,
+          tuple ***    const lookupP,
+          struct pam * const lookuppamP,
+          bool         const fit) {
+
+    FILE*  lookupfileP;
+
+    struct pam inputLookuppam;
+    tuple** inputLookup;
+
+    lookupfileP = pm_openr(lookupFilespec);
+    inputLookup = pnm_readpam(lookupfileP, 
+                              &inputLookuppam, PAM_STRUCT_SIZE(tuple_type));
+
+    pm_close(lookupfileP);
+    
+    if (fit) {
+        fitLookup(inputLookup, inputLookuppam, lookupP, lookuppamP,
+                  indexMaxval + 1, 
+                  indexDegree > 1 ? indexMaxval + 1 : 1);
+        pnm_freepamarray(inputLookup, &inputLookuppam);
+    } else {
+        *lookupP = inputLookup;
+        *lookuppamP = inputLookuppam;
+    }
+        
+    if (indexDegree == 1 && lookuppamP->height != 1)
+        pm_error("Your index image has integer indices, "
+                 "so the lookup table image must be one row.  "
+                 "Yours is %d rows.", 
+                 lookuppamP->height);
+
+    if (lookuppamP->width - 1 > indexMaxval)
+        pm_message("Warning:  your lookup table image is wider than "
+                   "the maxval of "
+                   "your index message, so the right end of the lookup "
+                   "table image will have no effect on the output.");
+    if (indexDegree == 2 && lookuppamP->height - 1 > indexMaxval)
+        pm_message("Warning: your lookup table image is taller than "
+                   "the maxval of "
+                   "your index message, so the bottom end of the lookup "
+                   "table image has no effect on the output.");
+}
+
+
+
+static void
+computeDefaultTuple(struct cmdlineInfo const cmdline, 
+                    tuple **           const lookup,
+                    struct pam *       const lookuppamP, 
+                    tuple *            const defaultTupleP) {
+
+    tuple retval;
+
+    retval = pnm_allocpamtuple(lookuppamP);
+
+    /* Note: "missing color" really makes sense only for a color
+       lookup, whereas this program allows an arbitrary PAM image as a
+       lookup table.  We should probably check here for a lookup file
+       that has a visual image tuple type, but we don't out of
+       laziness.  The program probably ought to have a generic
+       "missing tuple type" option too.  
+    */
+    if (cmdline.missingcolor) {
+        pixel const color = 
+            ppm_parsecolor(cmdline.missingcolor, lookuppamP->maxval);
+
+        if (lookuppamP->depth >= 3) {
+            retval[PAM_RED_PLANE] = PPM_GETR(color);
+            retval[PAM_GRN_PLANE] = PPM_GETG(color);
+            retval[PAM_BLU_PLANE] = PPM_GETB(color);
+        } else {
+            if (PPM_GETR(color) != PPM_GETG(color) ||
+                PPM_GETR(color) != PPM_GETB(color))
+                pm_error("You specified as a missing color something which "
+                         "is not monochrome, but your lookup table file, "
+                         "and thus your "
+                         "output file, can contain only monochrome values");
+            else
+                retval[0] = PPM_GETR(color);
+        }
+    } else 
+        pnm_assigntuple(lookuppamP, retval, lookup[0][0]);
+
+    *defaultTupleP = retval;
+}
+
+
+
+static void
+doLookup(struct pam const indexpam,
+         struct pam const outpamarg,
+         tuple      const defaultTuple,
+         tuple **   const lookup,
+         struct pam const lookuppam) {
+
+    struct pam outpam;
+    unsigned int row;
+
+    tuple* tuplerowIndex;
+    tuple* tuplerowOut;
+
+    outpam = outpamarg;
+
+    tuplerowIndex = pnm_allocpamrow(&indexpam);
+    tuplerowOut = pnm_allocpamrow(&outpam);
+
+    pnm_writepaminit(&outpam);
+
+    for (row = 0; row < outpam.height; ++row) {
+        unsigned int col;
+        pnm_readpamrow(&indexpam, tuplerowIndex);
+        
+        for (col = 0; col < outpam.width; ++col) {
+            unsigned int indexRow, indexCol;
+            tuple v;
+            
+            if (indexpam.depth < 2) {
+                indexRow = 0;
+                indexCol = tuplerowIndex[col][0];
+            } else {
+                indexRow = tuplerowIndex[col][0];
+                indexCol = tuplerowIndex[col][1];
+            }
+
+            if (indexRow >= lookuppam.height || indexCol >= lookuppam.width)
+                v = defaultTuple;
+            else
+                v = lookup[indexRow][indexCol];
+
+            pnm_assigntuple(&outpam, tuplerowOut[col], v);
+        }
+        pnm_writepamrow(&outpam, tuplerowOut);
+    }
+    pnm_freepamrow(tuplerowIndex);
+    pnm_freepamrow(tuplerowOut);
+}
+
+
+
+int
+main(int argc, char *argv[]) {
+
+    struct cmdlineInfo cmdline;
+    struct pam indexpam;
+    struct pam outpam;
+    FILE*  ifP;
+    struct pam lookuppam;
+    tuple** lookup;
+
+    tuple defaultTuple;
+    
+    pnm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.indexFilespec);
+
+    pnm_readpaminit(ifP, &indexpam, PAM_STRUCT_SIZE(tuple_type));
+
+    if (indexpam.depth != 1 && indexpam.depth != 2)
+        pm_error("The input (index) file must have depth 1 or 2.  "
+                 "Yours has depth %d",
+                 indexpam.depth);
+
+    getLookup(cmdline.lookupFilespec, indexpam.depth, indexpam.maxval, 
+              &lookup, &lookuppam, cmdline.fit);
+
+    computeDefaultTuple(cmdline, lookup, &lookuppam, &defaultTuple);
+
+    outpam = lookuppam;
+    outpam.height = indexpam.height;
+    outpam.width = indexpam.width;
+    outpam.file = stdout;
+    
+    doLookup(indexpam, outpam, defaultTuple, lookup, lookuppam);
+
+    pm_close(ifP);
+
+    pnm_freepamtuple(defaultTuple);
+    pnm_freepamarray(lookup, &lookuppam);
+    
+    exit(0);
+}
+