about summary refs log tree commit diff
path: root/converter/ppm/ppmtolj.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtolj.c')
-rw-r--r--converter/ppm/ppmtolj.c415
1 files changed, 240 insertions, 175 deletions
diff --git a/converter/ppm/ppmtolj.c b/converter/ppm/ppmtolj.c
index 7ed814ed..e2e03ac5 100644
--- a/converter/ppm/ppmtolj.c
+++ b/converter/ppm/ppmtolj.c
@@ -10,13 +10,12 @@
 ** implied warranty.
 */
 
+#include <stdbool.h>
+#include <limits.h>
 #include <string.h>
 
 #include "ppm.h"
 
-static int compress_row_delta (unsigned char *op, unsigned char *prev_op, 
-                               unsigned char *cp, int bufsize);
-
 #define C_RESET                 "\033E"
 #define C_PRESENTATION          "\033*r%dF"
 #define C_PRESENTATION_LOGICAL  0
@@ -44,103 +43,269 @@ static int compress_row_delta (unsigned char *op, unsigned char *prev_op,
 #define C_Y_OFFSET              "\033*b%dY"
 
 
+
+static void
+printHeader(FILE *       const ofP,
+            int          const resets,
+            bool         const floating,
+            int          const resolution,
+            unsigned int const rows,
+            unsigned int const cols,
+            int          const mode,
+            int          const gamma) {
+
+    char const CID[6] =  { 0, 3, 0, 8, 8, 8 };
+        /*data for the configure image data command*/
+
+    if (resets & 0x1) {
+        /* Printer reset. */
+        fprintf(ofP, C_RESET);
+    }
+
+    if (!floating) {
+        /* Ensure top margin is zero */
+        fprintf(ofP, "\033&l0E");
+    }
+
+    /*Set Presentation mode*/
+    fprintf(ofP, C_PRESENTATION, C_PRESENTATION_PHYSICAL);
+    /* Set the resolution */
+    fprintf(ofP, C_RESOLUTION, resolution);
+    /* Set raster height*/
+    fprintf(ofP, C_IMAGE_HEIGHT, rows);
+    /* Set raster width*/
+    fprintf(ofP, C_IMAGE_WIDTH, cols);
+    /* set left margin to current x pos*/
+    /*(void) fprintf(ofP, C_LEFT_MARGIN, 1);*/
+    /* set the correct color mode */
+    fprintf(ofP, C_CONFIG_IMAGE_DATA);
+    fwrite(CID, 1, 6, ofP);
+    /* Start raster graphics */
+    fprintf(ofP, C_BEGIN_RASTER, C_BEGIN_RASTER_CUR);  /*posscale);*/
+    /* set Y offset to 0 */
+    fprintf(ofP, C_Y_OFFSET, 0);
 /*
- * delta encoding. 
- */
-/*
-op row buffer
-prev_op     previous row buffer
-bufsize     length of row
-cp          buffer for compressed data
+    if (xoff)
+        fprintf(ofP, C_MOVE_X, xoff);
+    if (yoff)
+        fprintf(ofP, C_MOVE_Y, yoff);
 */
+    /* Set raster compression */
+    fprintf(ofP, C_TRANS_MODE, mode);
+
+    if (gamma)
+        fprintf(ofP, C_GAMMA,   gamma);
+}
+
+
+
 static int
-compress_row_delta(op, prev_op, cp, bufsize)
-unsigned char *op, *prev_op, *cp;
-int bufsize;
-{
-    int burstStart, burstEnd, burstCode, mustBurst, ptr, skip, skipped, code;
-    int deltaBufferIndex = 0;
-    if (memcmp(op, prev_op , bufsize/*rowBufferIndex*/) == 0) 
+compressRowDelta(unsigned char * const op,
+                 unsigned char * const prevOp,
+                 unsigned char * const cp,
+                 unsigned int    const bufsize) {
+/*----------------------------------------------------------------------------
+
+  delta encoding.
+
+
+  op:      row buffer
+  prevOp:  previous row buffer
+  bufsize: length of row
+  cp:       buffer for compressed data
+-----------------------------------------------------------------------------*/
+    int burstStart, burstEnd, burstCode, ptr, skipped, code;
+    bool mustBurst;
+    int deltaBufferIndex;
+
+    if (memcmp(op, prevOp , bufsize/*rowBufferIndex*/) == 0)
         return 0; /* exact match, no deltas required */
 
-    ptr = 0;
-    skipped = 0;
-    burstStart = -1;
-    burstEnd = -1;
-    mustBurst = 0;
-    while (ptr < bufsize/*rowBufferIndex*/) 
-    {
-        skip = 0;
-        if (ptr == 0 || skipped == 30 || op[ptr] != prev_op[ptr] ||
-            (burstStart != -1 && ptr == bufsize - 1)) 
-        {
+    deltaBufferIndex = 0;  /* initial value */
+    ptr = 0;               /* initial value */
+    skipped = 0;           /* initial value */
+    burstStart = -1;       /* initial value */
+    burstEnd = -1;         /* initial value */
+    mustBurst = false;     /* initial value */
+
+    while (ptr < bufsize/*rowBufferIndex*/) {
+        bool mustSkip;
+
+        mustSkip = false;  /* initial assumption */
+
+        if (ptr == 0 || skipped == 30 || op[ptr] != prevOp[ptr] ||
+            (burstStart != -1 && ptr == bufsize - 1)) {
             /* we want to output this byte... */
-            if (burstStart == -1) 
-            {
+            if (burstStart == -1) {
                 burstStart = ptr;
             }
-            if (ptr - burstStart == 7 || ptr == bufsize - 1) 
-            {
+            if (ptr - burstStart == 7 || ptr == bufsize - 1) {
                 /* we have to output it now... */
                 burstEnd = ptr;
-                mustBurst = 1;
+                mustBurst = true;
             }
-        } 
-        else 
-        {
+        } else {
             /* duplicate byte, we can skip it */
-            if (burstStart != -1) 
+            if (burstStart != -1)
             {
                 burstEnd = ptr - 1;
-                mustBurst = 1;
+                mustBurst = true;
             }
-            skip = 1;
+            mustSkip = true;
         }
-        if (mustBurst) 
-        {
+        if (mustBurst) {
             burstCode = burstEnd - burstStart; /* 0-7 means 1-8 bytes follow */
             code = (burstCode << 5) | skipped;
             cp[deltaBufferIndex++] = (char) code;
-            memcpy(cp+deltaBufferIndex, op+burstStart, burstCode + 1);
+            memcpy(cp + deltaBufferIndex, op + burstStart, burstCode + 1);
             deltaBufferIndex += burstCode + 1;
             burstStart = -1;
             burstEnd = -1;
-            mustBurst = 0;
+            mustBurst = false;
             skipped = 0;
         }
-        if (skip) 
-        {
-            skipped ++;
-        }
-        ptr ++;
+        if (mustSkip)
+            ++skipped;
+        ++ptr;
     }
     return deltaBufferIndex;
 }
 
 
-int main(int argc, char *argv[]) {
+
+static void
+printTrailer(FILE * const ofP,
+             int    const resets) {
+
+    fprintf(ofP, C_END_RASTER, C_END_RASTER_UNUSED);
+
+    if (resets & 0x2) {
+        /* Printer reset. */
+        fprintf(ofP, C_RESET);
+    }
+}
+
+
+
+static void
+printRaster(FILE *       const ifP,
+            unsigned int const rows,
+            unsigned int const cols,
+            int          const maxval,
+            int          const format,
+            int          const mode,
+            FILE *       const ofP) {
+
+    unsigned char * obuf; /* malloc'ed */
+    unsigned char * cbuf; /* malloc'ed */
+    unsigned char * previousObuf;  /* malloc'ed */
+    unsigned int uncompOutRowSz;
+    unsigned int outRowSz;
+    int currentmode;
     pixel * pixelrow;
-    FILE *ifp;
-    int argn, rows, cols, r, c, k;
-    pixval maxval;
-    unsigned char *obuf, *op, *cbuf, *previous_obuf;
-    int format;
-    int gamma = 0;
-    int mode = C_TRANS_MODE_STD;
-    int currentmode = 0;
-    int floating = 0;  /* suppress the ``ESC & l 0 E'' ? */
-    int resets = 3;    /* bit mask for when to emit printer reset seq */
+    unsigned int row;
 
-    int resolution = C_RESOLUTION_300DPI;
+    pixelrow = ppm_allocrow(cols);
 
-    char CID[6] =  { 0, 3, 0, 8, 8, 8 }; 
-        /*data for the configure image data command*/
+    if (cols > UINT_MAX/6) {
+        /* We may need a row buffer of up to cols * 6 bytes for compression */
+        pm_error("Image is uncomputably wide (%u columns)", cols);
+    }
+
+    obuf = (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
+    cbuf = (unsigned char *) pm_allocrow(cols * 6, sizeof(unsigned char));
+
+    if (mode == C_TRANS_MODE_DELTA) {
+        previousObuf =
+            (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
+        memset(previousObuf, 0, cols * 3);
+    } else
+        previousObuf = NULL;
+
+    currentmode = mode;  /* initial value */
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        const unsigned char * op;
+
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
+
+        /* get a row of data with 3 bytes per pixel */
+        for (col = 0; col < cols; ++col) {
+            obuf[3*col + 0] = (PPM_GETR(pixelrow[col])*255)/maxval;
+            obuf[3*col + 1] = (PPM_GETG(pixelrow[col])*255)/maxval;
+            obuf[3*col + 2] = (PPM_GETB(pixelrow[col])*255)/maxval;
+        }
+        uncompOutRowSz = 3 * cols;
+
+        /*compress the row if required*/
+        switch (mode) {
+        case C_TRANS_MODE_STD: /*no compression*/
+            op = obuf;
+            outRowSz = uncompOutRowSz;
+            break;
+        case C_TRANS_MODE_DELTA: {   /*delta compression*/
+            int const deltasize =
+                compressRowDelta(obuf, previousObuf, cbuf, uncompOutRowSz);
+
+            int newmode;
+
+            newmode = 0;  /* initial value */
+
+            if (deltasize >= uncompOutRowSz) {
+                /*normal is best?*/
+                op = obuf;
+                outRowSz = uncompOutRowSz;
+            } else {
+                /*delta is best*/
+                op = cbuf;
+                outRowSz = deltasize;
+                newmode = C_TRANS_MODE_DELTA;
+            }
+            memcpy(previousObuf, obuf, cols*3);
+
+            if (currentmode != newmode) {
+                fprintf(ofP, C_TRANS_MODE, newmode);
+                currentmode = newmode;
+            }
+        }
+        }
+        fprintf(ofP, C_SEND_ROW, outRowSz);
+        fwrite(op, 1, outRowSz, ofP);
+    }
+    free(cbuf);
+    free(obuf);
+    if (previousObuf)
+        free(previousObuf);
+    ppm_freerow(pixelrow);
+}
+
+
+
+int
+main(int argc, const char **argv) {
+    FILE * ifP;
+    int argn, rows, cols;
+    pixval maxval;
+    int format;
+    int gamma;
+    int mode;
+    bool floating;
+        /* suppress the ``ESC & l 0 E'' ? */
+    int resets;
+        /* bit mask for when to emit printer reset seq */
+    int resolution;
 
     const char * const usage = "[-noreset][-float][-delta][-gamma <val>] [-resolution N] "
         "[ppmfile]\n\tresolution = [75|100|150|300|600] (dpi)";
 
-    ppm_init( &argc, argv );
+    pm_proginit(&argc, argv);
 
+    gamma = 0; /* initial value */
+    mode = C_TRANS_MODE_STD;  /* initial value */
+    resolution = C_RESOLUTION_300DPI;  /* initial value */
+    floating = false;  /* initial value */
+    resets = 0x3;  /* initial value */
     argn = 1;
     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
     {
@@ -159,9 +324,9 @@ int main(int argc, char *argv[]) {
         else if (pm_keymatch(argv[argn],"-delta",2))
             mode = C_TRANS_MODE_DELTA;
         else if (pm_keymatch(argv[argn],"-float",2))
-            floating = 1;
+            floating = true;
         else if (pm_keymatch(argv[argn],"-noreset",2))
-            resets = 0;
+            resets = 0x0;
 
         else
             pm_usage( usage );
@@ -170,128 +335,28 @@ int main(int argc, char *argv[]) {
 
     if ( argn < argc )
     {
-        ifp = pm_openr( argv[argn] );
+        ifP = pm_openr( argv[argn] );
         ++argn;
     }
     else
-        ifp = stdin;
+        ifP = stdin;
 
     if ( argn != argc )
         pm_usage( usage );
 
-    ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
-    pixelrow = ppm_allocrow( cols );
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
 
-    obuf = (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
-    cbuf = (unsigned char *) pm_allocrow(cols * 6, sizeof(unsigned char));
-    if (mode == C_TRANS_MODE_DELTA)
-    {
-        previous_obuf = 
-            (unsigned char *) pm_allocrow(cols * 3, sizeof(unsigned char));
-        memset(previous_obuf, 0, cols * 3);
-    }
+    printHeader(stdout, resets, floating, resolution, rows, cols,
+                mode, gamma);
 
-    if(resets & 1)
-    {
-        /* Printer reset. */
-        printf(C_RESET);
-    }
+    printRaster(ifP, rows, cols, maxval, format, mode, stdout);
 
-    if(!floating)
-    {
-        /* Ensure top margin is zero */
-        printf("\033&l0E");
-    }
+    printTrailer(stdout, resets);
 
-    /*Set Presentation mode*/
-    (void) printf(C_PRESENTATION, C_PRESENTATION_PHYSICAL);
-    /* Set the resolution */
-    (void) printf(C_RESOLUTION, resolution);
-    /* Set raster height*/
-    (void) printf(C_IMAGE_HEIGHT, rows);
-    /* Set raster width*/
-    (void) printf(C_IMAGE_WIDTH, cols);
-    /* set left margin to current x pos*/
-    /*(void) printf(C_LEFT_MARGIN, 1);*/
-    /* set the correct color mode */
-    (void) printf(C_CONFIG_IMAGE_DATA);
-    (void) fwrite(CID, 1, 6, stdout);
-    /* Start raster graphics */
-    (void) printf(C_BEGIN_RASTER, C_BEGIN_RASTER_CUR);  /*posscale);*/
-    /* set Y offset to 0 */
-    (void) printf(C_Y_OFFSET, 0);
-/*  
-    if (xoff)
-        (void) printf(C_MOVE_X, xoff);
-    if (yoff)
-        (void) printf(C_MOVE_Y, yoff);
-*/
-    /* Set raster compression */
-    (void) printf(C_TRANS_MODE, mode);
-    currentmode = mode;
-    
-    if(gamma)
-        (void) printf(C_GAMMA,   gamma);
-    
-    for (r = 0; r < rows; r++)
-    {
-        ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
-
-        /* get a row of data with 3 bytes per pixel */
-        for (c = 0, op = &obuf[-1]; c < cols; c++)
-        {
-            ++op;
-            *op = (PPM_GETR(pixelrow[c])*255)/maxval;
-            ++op;
-            *op = (PPM_GETG(pixelrow[c])*255)/maxval;
-            ++op;
-            *op = (PPM_GETB(pixelrow[c])*255)/maxval;
-        }
-        ++op;
-        k = op - obuf; /*size of row*/
-        /*compress the row if required*/
-        if(mode == C_TRANS_MODE_STD)
-        {/*no compression*/
-            op = obuf;
-        }
+    pm_close(ifP);
 
-        if(mode ==  C_TRANS_MODE_DELTA)
-        {/*delta compression*/
-            int newmode = 0;
-            int deltasize = 
-                compress_row_delta(obuf, previous_obuf, cbuf, cols*3);
-            if(deltasize >= k)/*normal is best?*/
-            {
-                op = obuf;
-            }
-            else /*delta is best*/
-            {
-                k = deltasize;
-                op = cbuf;
-                newmode = C_TRANS_MODE_DELTA;
-            }
-            memcpy(previous_obuf, obuf, cols*3);
-
-            if(currentmode != newmode)
-            {
-                (void) printf(C_TRANS_MODE, newmode);
-                currentmode = newmode;
-            }
-        }
+    return 0;
+}
 
-        (void) printf(C_SEND_ROW, k);
-        (void) fwrite(op, 1, k, stdout);
-        
-    }
 
-    (void) printf(C_END_RASTER, C_END_RASTER_UNUSED);
-    if(resets & 2)
-    {
-        /* Printer reset. */
-        printf(C_RESET);
-    }
-    pm_close( ifp );
-    ppm_freerow(pixelrow);
 
-    return 0;
-}