about summary refs log tree commit diff
path: root/converter/other/jpegtopnm.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/jpegtopnm.c')
-rw-r--r--converter/other/jpegtopnm.c153
1 files changed, 90 insertions, 63 deletions
diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c
index 60ae7e42..07a7dfb0 100644
--- a/converter/other/jpegtopnm.c
+++ b/converter/other/jpegtopnm.c
@@ -61,6 +61,8 @@
    itself, but doesn't.
 */
 #include <jpeglib.h>
+
+#include "pm_c_util.h"
 #include "pnm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
@@ -109,6 +111,7 @@ struct cmdlineInfo {
     unsigned int comments;
     unsigned int dumpexif;
     unsigned int multiple;
+    unsigned int repair;
 };
 
 
@@ -116,9 +119,9 @@ static bool displayComments;
     /* User wants comments from the JPEG to be displayed */
 
 static void 
-interpret_maxmemory (bool         const maxmemorySpec,
-                     const char * const maxmemory, 
-                     long int *   const max_memory_to_use_p) { 
+interpret_maxmemory(bool         const maxmemorySpec,
+                    const char * const maxmemory, 
+                    long int *   const max_memory_to_use_p) { 
 /*----------------------------------------------------------------------------
    Interpret the "maxmemory" command line option.
 -----------------------------------------------------------------------------*/
@@ -157,8 +160,9 @@ interpret_adobe(const int adobe, const int notadobe,
 
 
 static void
-parse_command_line(const int argc, char ** argv,
-                   struct cmdlineInfo *cmdlineP) {
+parseCommandLine(int                  const argc,
+                 char **              const argv,
+                 struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
    *cmdlineP structure are actually in the supplied argv array.  And
@@ -173,10 +177,10 @@ parse_command_line(const int argc, char ** argv,
          */
     optStruct3 opt;
 
-    int i;  /* local loop variable */
+    unsigned int i;  /* local loop variable */
 
-    char *maxmemory;
-    char *dctval;
+    const char * maxmemory;
+    const char * dctval;
     unsigned int adobe, notadobe;
 
     unsigned int tracelevelSpec, exifSpec, dctvalSpec, maxmemorySpec;
@@ -206,6 +210,7 @@ parse_command_line(const int argc, char ** argv,
             &exifSpec, 0);
     OPTENT3(0, "dumpexif",    OPT_FLAG,   NULL, &cmdlineP->dumpexif,      0);
     OPTENT3(0, "multiple",    OPT_FLAG,   NULL, &cmdlineP->multiple,      0);
+    OPTENT3(0, "repair",      OPT_FLAG,   NULL, &cmdlineP->repair,        0);
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
@@ -213,7 +218,8 @@ parse_command_line(const int argc, char ** argv,
 
     /* Make private copy of arguments for optParseOptions to corrupt */
     argc_parse = argc;
-    for (i=0; i < argc; i++) argv_parse[i] = argv[i];
+    for (i=0; i < argc; ++i)
+        argv_parse[i] = argv[i];
 
     optParseOptions3( &argc_parse, argv_parse, opt, sizeof(opt), 0);
         /* Uses and sets argc_parse, argv_parse, 
@@ -236,11 +242,11 @@ parse_command_line(const int argc, char ** argv,
     if (!dctvalSpec)
         cmdlineP->dct_method = JDCT_DEFAULT;
     else {
-        if (STREQ(dctval, "int"))
+        if (streq(dctval, "int"))
             cmdlineP->dct_method = JDCT_ISLOW;
-        else if (STREQ(dctval, "fast"))
+        else if (streq(dctval, "fast"))
             cmdlineP->dct_method = JDCT_IFAST;
-        else if (STREQ(dctval, "float"))
+        else if (streq(dctval, "float"))
             cmdlineP->dct_method = JDCT_FLOAT;
         else pm_error("Invalid value for the --dct option: '%s'.", dctval);
     }
@@ -458,32 +464,34 @@ read_rgb(JSAMPLE *ptr, const enum colorspace color_space,
    copy_pixel_row().  But it would be impractical to allocate and free
    the storage with every call to copy_pixel_row().
 */
-static xel *pnmbuffer;      /* Output buffer.  Input to pnm_writepnmrow() */
+static xel * pnmbuffer;      /* Output buffer.  Input to pnm_writepnmrow() */
 
 static void
-copy_pixel_row(const JSAMPROW jpegbuffer, const int width, 
-               const unsigned int samples_per_pixel, 
-               const enum colorspace color_space,
-               const unsigned int maxval,
-               FILE * const output_file, const int output_type) {
-  JSAMPLE *ptr;
-  unsigned int output_cursor;     /* Cursor into output buffer 'pnmbuffer' */
-
-  ptr = jpegbuffer;  /* Start at beginning of input row */
-
-  for (output_cursor = 0; output_cursor < width; output_cursor++) {
-      xel current_pixel;
-      if (samples_per_pixel >= 3) {
-          const rgb_type * const rgb_p = read_rgb(ptr, color_space, maxval);
-          PPM_ASSIGN(current_pixel, rgb_p->r, rgb_p->g, rgb_p->b);
-      } else {
-          PNM_ASSIGN1(current_pixel, GETJSAMPLE(*ptr));
-      }
-      ptr += samples_per_pixel;  /* move to next pixel of input */
-      pnmbuffer[output_cursor] = current_pixel;
-  }
-  pnm_writepnmrow(output_file, pnmbuffer, width,
-                  maxval, output_type, FALSE);
+copyPixelRow(JSAMPROW        const jpegbuffer,
+             unsigned int    const width, 
+             unsigned int    const samplesPerPixel, 
+             enum colorspace const colorSpace,
+             FILE *          const ofP,
+             int             const format,
+             xelval          const maxval) {
+
+    JSAMPLE * ptr;
+    unsigned int outputCursor;     /* Cursor into output buffer 'pnmbuffer' */
+
+    ptr = &jpegbuffer[0];  /* Start at beginning of input row */
+    
+    for (outputCursor = 0; outputCursor < width; ++outputCursor) {
+        xel currentPixel;
+        if (samplesPerPixel >= 3) {
+            const rgb_type * const rgb_p = read_rgb(ptr, colorSpace, maxval);
+            PPM_ASSIGN(currentPixel, rgb_p->r, rgb_p->g, rgb_p->b);
+        } else {
+            PNM_ASSIGN1(currentPixel, GETJSAMPLE(*ptr));
+        }
+        ptr += samplesPerPixel;  /* move to next pixel of input */
+        pnmbuffer[outputCursor] = currentPixel;
+    }
+    pnm_writepnmrow(ofP, pnmbuffer, width, maxval, format, FALSE);
 }
 
 
@@ -796,17 +804,42 @@ computeColorSpace(struct jpeg_decompress_struct * const cinfoP,
 
 
 static void
+convertRaster(struct jpeg_decompress_struct * const cinfoP,
+              enum colorspace                 const color_space,
+              FILE *                          const ofP,
+              xelval                          const format,
+              unsigned int                    const maxval) {
+              
+    JSAMPROW jpegbuffer;  /* Input buffer.  Filled by jpeg_scanlines() */
+
+    jpegbuffer = ((*cinfoP->mem->alloc_sarray)
+                  ((j_common_ptr) cinfoP, JPOOL_IMAGE,
+                   cinfoP->output_width * cinfoP->output_components, 
+                   (JDIMENSION) 1)
+        )[0];
+
+    while (cinfoP->output_scanline < cinfoP->output_height) {
+        jpeg_read_scanlines(cinfoP, &jpegbuffer, 1);
+        if (ofP)
+            copyPixelRow(jpegbuffer, cinfoP->output_width, 
+                         cinfoP->out_color_components,
+                         color_space, ofP, format, maxval);
+    }
+}
+
+
+
+static void
 convertImage(FILE *                          const ofP, 
              struct cmdlineInfo              const cmdline,
              struct jpeg_decompress_struct * const cinfoP) {
 
-    int output_type;
+    int format;
         /* The type of output file, PGM or PPM.  Value is either PPM_TYPE
            or PGM_TYPE, which conveniently also pass as format values
            PPM_FORMAT and PGM_FORMAT.
         */
-    JSAMPROW jpegbuffer;  /* Input buffer.  Filled by jpeg_scanlines() */
-    unsigned int maxval;  
+    xelval maxval;  
         /* The maximum value of a sample (color component), both in the input
            and the output.
         */
@@ -817,43 +850,30 @@ convertImage(FILE *                          const ofP,
                    cmdline.dct_method, 
                    cmdline.max_memory_to_use, cmdline.nosmooth);
                    
-    set_color_spaces(cinfoP->jpeg_color_space, &output_type, 
+    set_color_spaces(cinfoP->jpeg_color_space, &format,
                      &cinfoP->out_color_space);
 
-    maxval = (1 << cinfoP->data_precision) - 1;
+    maxval = pm_bitstomaxval(cinfoP->data_precision);
 
     if (cmdline.verbose) 
-        tellDetails(*cinfoP, maxval, output_type);
+        tellDetails(*cinfoP, maxval, format);
 
     /* Calculate output image dimensions so we can allocate space */
     jpeg_calc_output_dimensions(cinfoP);
 
-    jpegbuffer = ((*cinfoP->mem->alloc_sarray)
-                  ((j_common_ptr) cinfoP, JPOOL_IMAGE,
-                   cinfoP->output_width * cinfoP->output_components, 
-                   (JDIMENSION) 1)
-        )[0];
-
     /* Start decompressor */
     jpeg_start_decompress(cinfoP);
 
     if (ofP)
         /* Write pnm output header */
         pnm_writepnminit(ofP, cinfoP->output_width, cinfoP->output_height,
-                         maxval, output_type, FALSE);
+                         maxval, format, FALSE);
 
     pnmbuffer = pnm_allocrow(cinfoP->output_width);
     
     color_space = computeColorSpace(cinfoP, cmdline.inklevel);
-
-    /* Process data */
-    while (cinfoP->output_scanline < cinfoP->output_height) {
-        jpeg_read_scanlines(cinfoP, &jpegbuffer, 1);
-        if (ofP)
-            copy_pixel_row(jpegbuffer, cinfoP->output_width, 
-                           cinfoP->out_color_components,
-                           color_space, maxval, ofP, output_type);
-    }
+    
+    convertRaster(cinfoP, color_space, ofP, format, maxval);
 
     if (cmdline.comments)
         print_comments(*cinfoP);
@@ -905,17 +925,25 @@ convertImages(FILE *                          const ofP,
             convertImage(ofP, cmdline, cinfoP);
         }
     } else {
-        if (dsDataLeft(sourceManagerP))
+        if (dsDataLeft(sourceManagerP)) {
             convertImage(ofP, cmdline, cinfoP);
-        else
+        } else
             pm_error("Input stream is empty");
     }
+    if (dsPrematureEof(sourceManagerP)) {
+        if (cmdline.repair)
+            pm_message("Premature EOF on input; repaired by padding end "
+                       "of image.");
+        else
+            pm_error("Premature EOF on input.  Use -repair to salvage.");
+    }
 }
 
 
 
 int
 main(int argc, char **argv) {
+
     FILE * ofP;
     struct cmdlineInfo cmdline;
     struct jpeg_decompress_struct cinfo;
@@ -924,9 +952,9 @@ main(int argc, char **argv) {
 
     pnm_init(&argc, argv);
 
-    parse_command_line(argc, argv, &cmdline);
+    parseCommandLine(argc, argv, &cmdline);
 
-    if (cmdline.exif_filespec && STREQ(cmdline.exif_filespec, "-"))
+    if (cmdline.exif_filespec && streq(cmdline.exif_filespec, "-"))
         /* He's got exif going to stdout, so there can be no image output */
         ofP = NULL;
     else
@@ -967,4 +995,3 @@ main(int argc, char **argv) {
   
     exit(jerr.num_warnings > 0 ? EXIT_WARNING : EXIT_SUCCESS);
 }
-