ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

jpegtran.c
Go to the documentation of this file.
00001 /*
00002  * jpegtran.c
00003  *
00004  * Copyright (C) 1995-2010, Thomas G. Lane, Guido Vollbeding.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains a command-line user interface for JPEG transcoding.
00009  * It is very similar to cjpeg.c, and partly to djpeg.c, but provides
00010  * lossless transcoding between different JPEG file formats.  It also
00011  * provides some lossless and sort-of-lossless transformations of JPEG data.
00012  */
00013 
00014 #include "cdjpeg.h"     /* Common decls for cjpeg/djpeg applications */
00015 #include "transupp.h"       /* Support routines for jpegtran */
00016 #include "jversion.h"       /* for version message */
00017 
00018 #ifdef USE_CCOMMAND     /* command-line reader for Macintosh */
00019 #ifdef __MWERKS__
00020 #include <SIOUX.h>              /* Metrowerks needs this */
00021 #include <console.h>        /* ... and this */
00022 #endif
00023 #ifdef THINK_C
00024 #include <console.h>        /* Think declares it here */
00025 #endif
00026 #endif
00027 
00028 
00029 /*
00030  * Argument-parsing code.
00031  * The switch parser is designed to be useful with DOS-style command line
00032  * syntax, ie, intermixed switches and file names, where only the switches
00033  * to the left of a given file name affect processing of that file.
00034  * The main program in this file doesn't actually use this capability...
00035  */
00036 
00037 
00038 static const char * progname;   /* program name for error messages */
00039 static char * outfilename;  /* for -outfile switch */
00040 static char * scaleoption;  /* -scale switch */
00041 static JCOPY_OPTION copyoption; /* -copy switch */
00042 static jpeg_transform_info transformoption; /* image transformation options */
00043 
00044 
00045 LOCAL(void)
00046 usage (void)
00047 /* complain about bad command line */
00048 {
00049   fprintf(stderr, "usage: %s [switches] ", progname);
00050 #ifdef TWO_FILE_COMMANDLINE
00051   fprintf(stderr, "inputfile outputfile\n");
00052 #else
00053   fprintf(stderr, "[inputfile]\n");
00054 #endif
00055 
00056   fprintf(stderr, "Switches (names may be abbreviated):\n");
00057   fprintf(stderr, "  -copy none     Copy no extra markers from source file\n");
00058   fprintf(stderr, "  -copy comments Copy only comment markers (default)\n");
00059   fprintf(stderr, "  -copy all      Copy all extra markers\n");
00060 #ifdef ENTROPY_OPT_SUPPORTED
00061   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
00062 #endif
00063 #ifdef C_PROGRESSIVE_SUPPORTED
00064   fprintf(stderr, "  -progressive   Create progressive JPEG file\n");
00065 #endif
00066   fprintf(stderr, "Switches for modifying the image:\n");
00067 #if TRANSFORMS_SUPPORTED
00068   fprintf(stderr, "  -crop WxH+X+Y  Crop to a rectangular subarea\n");
00069   fprintf(stderr, "  -grayscale     Reduce to grayscale (omit color data)\n");
00070   fprintf(stderr, "  -flip [horizontal|vertical]  Mirror image (left-right or top-bottom)\n");
00071   fprintf(stderr, "  -perfect       Fail if there is non-transformable edge blocks\n");
00072   fprintf(stderr, "  -rotate [90|180|270]         Rotate image (degrees clockwise)\n");
00073 #endif
00074   fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
00075 #if TRANSFORMS_SUPPORTED
00076   fprintf(stderr, "  -transpose     Transpose image\n");
00077   fprintf(stderr, "  -transverse    Transverse transpose image\n");
00078   fprintf(stderr, "  -trim          Drop non-transformable edge blocks\n");
00079 #endif
00080   fprintf(stderr, "Switches for advanced users:\n");
00081   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
00082   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
00083   fprintf(stderr, "  -outfile name  Specify name for output file\n");
00084   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
00085   fprintf(stderr, "Switches for wizards:\n");
00086 #ifdef C_ARITH_CODING_SUPPORTED
00087   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
00088 #endif
00089 #ifdef C_MULTISCAN_FILES_SUPPORTED
00090   fprintf(stderr, "  -scans file    Create multi-scan JPEG per script file\n");
00091 #endif
00092   exit(EXIT_FAILURE);
00093 }
00094 
00095 
00096 LOCAL(void)
00097 select_transform (JXFORM_CODE transform)
00098 /* Silly little routine to detect multiple transform options,
00099  * which we can't handle.
00100  */
00101 {
00102 #if TRANSFORMS_SUPPORTED
00103   if (transformoption.transform == JXFORM_NONE ||
00104       transformoption.transform == transform) {
00105     transformoption.transform = transform;
00106   } else {
00107     fprintf(stderr, "%s: can only do one image transformation at a time\n",
00108         progname);
00109     usage();
00110   }
00111 #else
00112   fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
00113       progname);
00114   exit(EXIT_FAILURE);
00115 #endif
00116 }
00117 
00118 
00119 LOCAL(int)
00120 parse_switches (j_compress_ptr cinfo, int argc, char **argv,
00121         int last_file_arg_seen, boolean for_real)
00122 /* Parse optional switches.
00123  * Returns argv[] index of first file-name argument (== argc if none).
00124  * Any file names with indexes <= last_file_arg_seen are ignored;
00125  * they have presumably been processed in a previous iteration.
00126  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
00127  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
00128  * processing.
00129  */
00130 {
00131   int argn;
00132   char * arg;
00133   boolean simple_progressive;
00134   char * scansarg = NULL;   /* saves -scans parm if any */
00135 
00136   /* Set up default JPEG parameters. */
00137   simple_progressive = FALSE;
00138   outfilename = NULL;
00139   scaleoption = NULL;
00140   copyoption = JCOPYOPT_DEFAULT;
00141   transformoption.transform = JXFORM_NONE;
00142   transformoption.perfect = FALSE;
00143   transformoption.trim = FALSE;
00144   transformoption.force_grayscale = FALSE;
00145   transformoption.crop = FALSE;
00146   cinfo->err->trace_level = 0;
00147 
00148   /* Scan command line options, adjust parameters */
00149 
00150   for (argn = 1; argn < argc; argn++) {
00151     arg = argv[argn];
00152     if (*arg != '-') {
00153       /* Not a switch, must be a file name argument */
00154       if (argn <= last_file_arg_seen) {
00155     outfilename = NULL; /* -outfile applies to just one input file */
00156     continue;       /* ignore this name if previously processed */
00157       }
00158       break;            /* else done parsing switches */
00159     }
00160     arg++;          /* advance past switch marker character */
00161 
00162     if (keymatch(arg, "arithmetic", 1)) {
00163       /* Use arithmetic coding. */
00164 #ifdef C_ARITH_CODING_SUPPORTED
00165       cinfo->arith_code = TRUE;
00166 #else
00167       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
00168           progname);
00169       exit(EXIT_FAILURE);
00170 #endif
00171 
00172     } else if (keymatch(arg, "copy", 2)) {
00173       /* Select which extra markers to copy. */
00174       if (++argn >= argc)   /* advance to next argument */
00175     usage();
00176       if (keymatch(argv[argn], "none", 1)) {
00177     copyoption = JCOPYOPT_NONE;
00178       } else if (keymatch(argv[argn], "comments", 1)) {
00179     copyoption = JCOPYOPT_COMMENTS;
00180       } else if (keymatch(argv[argn], "all", 1)) {
00181     copyoption = JCOPYOPT_ALL;
00182       } else
00183     usage();
00184 
00185     } else if (keymatch(arg, "crop", 2)) {
00186       /* Perform lossless cropping. */
00187 #if TRANSFORMS_SUPPORTED
00188       if (++argn >= argc)   /* advance to next argument */
00189     usage();
00190       if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
00191     fprintf(stderr, "%s: bogus -crop argument '%s'\n",
00192         progname, argv[argn]);
00193     exit(EXIT_FAILURE);
00194       }
00195 #else
00196       select_transform(JXFORM_NONE);    /* force an error */
00197 #endif
00198 
00199     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
00200       /* Enable debug printouts. */
00201       /* On first -d, print version identification */
00202       static boolean printed_version = FALSE;
00203 
00204       if (! printed_version) {
00205     fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
00206         JVERSION, JCOPYRIGHT);
00207     printed_version = TRUE;
00208       }
00209       cinfo->err->trace_level++;
00210 
00211     } else if (keymatch(arg, "flip", 1)) {
00212       /* Mirror left-right or top-bottom. */
00213       if (++argn >= argc)   /* advance to next argument */
00214     usage();
00215       if (keymatch(argv[argn], "horizontal", 1))
00216     select_transform(JXFORM_FLIP_H);
00217       else if (keymatch(argv[argn], "vertical", 1))
00218     select_transform(JXFORM_FLIP_V);
00219       else
00220     usage();
00221 
00222     } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
00223       /* Force to grayscale. */
00224 #if TRANSFORMS_SUPPORTED
00225       transformoption.force_grayscale = TRUE;
00226 #else
00227       select_transform(JXFORM_NONE);    /* force an error */
00228 #endif
00229 
00230     } else if (keymatch(arg, "maxmemory", 3)) {
00231       /* Maximum memory in Kb (or Mb with 'm'). */
00232       long lval;
00233       char ch = 'x';
00234 
00235       if (++argn >= argc)   /* advance to next argument */
00236     usage();
00237       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
00238     usage();
00239       if (ch == 'm' || ch == 'M')
00240     lval *= 1000L;
00241       cinfo->mem->max_memory_to_use = lval * 1000L;
00242 
00243     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
00244       /* Enable entropy parm optimization. */
00245 #ifdef ENTROPY_OPT_SUPPORTED
00246       cinfo->optimize_coding = TRUE;
00247 #else
00248       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
00249           progname);
00250       exit(EXIT_FAILURE);
00251 #endif
00252 
00253     } else if (keymatch(arg, "outfile", 4)) {
00254       /* Set output file name. */
00255       if (++argn >= argc)   /* advance to next argument */
00256     usage();
00257       outfilename = argv[argn]; /* save it away for later use */
00258 
00259     } else if (keymatch(arg, "perfect", 2)) {
00260       /* Fail if there is any partial edge MCUs that the transform can't
00261        * handle. */
00262       transformoption.perfect = TRUE;
00263 
00264     } else if (keymatch(arg, "progressive", 2)) {
00265       /* Select simple progressive mode. */
00266 #ifdef C_PROGRESSIVE_SUPPORTED
00267       simple_progressive = TRUE;
00268       /* We must postpone execution until num_components is known. */
00269 #else
00270       fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
00271           progname);
00272       exit(EXIT_FAILURE);
00273 #endif
00274 
00275     } else if (keymatch(arg, "restart", 1)) {
00276       /* Restart interval in MCU rows (or in MCUs with 'b'). */
00277       long lval;
00278       char ch = 'x';
00279 
00280       if (++argn >= argc)   /* advance to next argument */
00281     usage();
00282       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
00283     usage();
00284       if (lval < 0 || lval > 65535L)
00285     usage();
00286       if (ch == 'b' || ch == 'B') {
00287     cinfo->restart_interval = (unsigned int) lval;
00288     cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
00289       } else {
00290     cinfo->restart_in_rows = (int) lval;
00291     /* restart_interval will be computed during startup */
00292       }
00293 
00294     } else if (keymatch(arg, "rotate", 2)) {
00295       /* Rotate 90, 180, or 270 degrees (measured clockwise). */
00296       if (++argn >= argc)   /* advance to next argument */
00297     usage();
00298       if (keymatch(argv[argn], "90", 2))
00299     select_transform(JXFORM_ROT_90);
00300       else if (keymatch(argv[argn], "180", 3))
00301     select_transform(JXFORM_ROT_180);
00302       else if (keymatch(argv[argn], "270", 3))
00303     select_transform(JXFORM_ROT_270);
00304       else
00305     usage();
00306 
00307     } else if (keymatch(arg, "scale", 4)) {
00308       /* Scale the output image by a fraction M/N. */
00309       if (++argn >= argc)   /* advance to next argument */
00310     usage();
00311       scaleoption = argv[argn];
00312       /* We must postpone processing until decompression startup. */
00313 
00314     } else if (keymatch(arg, "scans", 1)) {
00315       /* Set scan script. */
00316 #ifdef C_MULTISCAN_FILES_SUPPORTED
00317       if (++argn >= argc)   /* advance to next argument */
00318     usage();
00319       scansarg = argv[argn];
00320       /* We must postpone reading the file in case -progressive appears. */
00321 #else
00322       fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
00323           progname);
00324       exit(EXIT_FAILURE);
00325 #endif
00326 
00327     } else if (keymatch(arg, "transpose", 1)) {
00328       /* Transpose (across UL-to-LR axis). */
00329       select_transform(JXFORM_TRANSPOSE);
00330 
00331     } else if (keymatch(arg, "transverse", 6)) {
00332       /* Transverse transpose (across UR-to-LL axis). */
00333       select_transform(JXFORM_TRANSVERSE);
00334 
00335     } else if (keymatch(arg, "trim", 3)) {
00336       /* Trim off any partial edge MCUs that the transform can't handle. */
00337       transformoption.trim = TRUE;
00338 
00339     } else {
00340       usage();          /* bogus switch */
00341     }
00342   }
00343 
00344   /* Post-switch-scanning cleanup */
00345 
00346   if (for_real) {
00347 
00348 #ifdef C_PROGRESSIVE_SUPPORTED
00349     if (simple_progressive) /* process -progressive; -scans can override */
00350       jpeg_simple_progression(cinfo);
00351 #endif
00352 
00353 #ifdef C_MULTISCAN_FILES_SUPPORTED
00354     if (scansarg != NULL)   /* process -scans if it was present */
00355       if (! read_scan_script(cinfo, scansarg))
00356     usage();
00357 #endif
00358   }
00359 
00360   return argn;          /* return index of next arg (file name) */
00361 }
00362 
00363 
00364 /*
00365  * The main program.
00366  */
00367 
00368 int
00369 main (int argc, char **argv)
00370 {
00371   struct jpeg_decompress_struct srcinfo;
00372   struct jpeg_compress_struct dstinfo;
00373   struct jpeg_error_mgr jsrcerr, jdsterr;
00374 #ifdef PROGRESS_REPORT
00375   struct cdjpeg_progress_mgr progress;
00376 #endif
00377   jvirt_barray_ptr * src_coef_arrays;
00378   jvirt_barray_ptr * dst_coef_arrays;
00379   int file_index;
00380   /* We assume all-in-memory processing and can therefore use only a
00381    * single file pointer for sequential input and output operation. 
00382    */
00383   FILE * fp;
00384 
00385   /* On Mac, fetch a command line. */
00386 #ifdef USE_CCOMMAND
00387   argc = ccommand(&argv);
00388 #endif
00389 
00390   progname = argv[0];
00391   if (progname == NULL || progname[0] == 0)
00392     progname = "jpegtran";  /* in case C library doesn't provide it */
00393 
00394   /* Initialize the JPEG decompression object with default error handling. */
00395   srcinfo.err = jpeg_std_error(&jsrcerr);
00396   jpeg_create_decompress(&srcinfo);
00397   /* Initialize the JPEG compression object with default error handling. */
00398   dstinfo.err = jpeg_std_error(&jdsterr);
00399   jpeg_create_compress(&dstinfo);
00400 
00401   /* Now safe to enable signal catcher.
00402    * Note: we assume only the decompression object will have virtual arrays.
00403    */
00404 #ifdef NEED_SIGNAL_CATCHER
00405   enable_signal_catcher((j_common_ptr) &srcinfo);
00406 #endif
00407 
00408   /* Scan command line to find file names.
00409    * It is convenient to use just one switch-parsing routine, but the switch
00410    * values read here are mostly ignored; we will rescan the switches after
00411    * opening the input file.  Also note that most of the switches affect the
00412    * destination JPEG object, so we parse into that and then copy over what
00413    * needs to affects the source too.
00414    */
00415 
00416   file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
00417   jsrcerr.trace_level = jdsterr.trace_level;
00418   srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
00419 
00420 #ifdef TWO_FILE_COMMANDLINE
00421   /* Must have either -outfile switch or explicit output file name */
00422   if (outfilename == NULL) {
00423     if (file_index != argc-2) {
00424       fprintf(stderr, "%s: must name one input and one output file\n",
00425           progname);
00426       usage();
00427     }
00428     outfilename = argv[file_index+1];
00429   } else {
00430     if (file_index != argc-1) {
00431       fprintf(stderr, "%s: must name one input and one output file\n",
00432           progname);
00433       usage();
00434     }
00435   }
00436 #else
00437   /* Unix style: expect zero or one file name */
00438   if (file_index < argc-1) {
00439     fprintf(stderr, "%s: only one input file\n", progname);
00440     usage();
00441   }
00442 #endif /* TWO_FILE_COMMANDLINE */
00443 
00444   /* Open the input file. */
00445   if (file_index < argc) {
00446     if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
00447       fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]);
00448       exit(EXIT_FAILURE);
00449     }
00450   } else {
00451     /* default input file is stdin */
00452     fp = read_stdin();
00453   }
00454 
00455 #ifdef PROGRESS_REPORT
00456   start_progress_monitor((j_common_ptr) &dstinfo, &progress);
00457 #endif
00458 
00459   /* Specify data source for decompression */
00460   jpeg_stdio_src(&srcinfo, fp);
00461 
00462   /* Enable saving of extra markers that we want to copy */
00463   jcopy_markers_setup(&srcinfo, copyoption);
00464 
00465   /* Read file header */
00466   (void) jpeg_read_header(&srcinfo, TRUE);
00467 
00468   /* Adjust default decompression parameters */
00469   if (scaleoption != NULL)
00470     if (sscanf(scaleoption, "%d/%d",
00471     &srcinfo.scale_num, &srcinfo.scale_denom) < 1)
00472       usage();
00473 
00474   /* Any space needed by a transform option must be requested before
00475    * jpeg_read_coefficients so that memory allocation will be done right.
00476    */
00477 #if TRANSFORMS_SUPPORTED
00478   /* Fail right away if -perfect is given and transformation is not perfect.
00479    */
00480   if (!jtransform_request_workspace(&srcinfo, &transformoption)) {
00481     fprintf(stderr, "%s: transformation is not perfect\n", progname);
00482     exit(EXIT_FAILURE);
00483   }
00484 #endif
00485 
00486   /* Read source file as DCT coefficients */
00487   src_coef_arrays = jpeg_read_coefficients(&srcinfo);
00488 
00489   /* Initialize destination compression parameters from source values */
00490   jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
00491 
00492   /* Adjust destination parameters if required by transform options;
00493    * also find out which set of coefficient arrays will hold the output.
00494    */
00495 #if TRANSFORMS_SUPPORTED
00496   dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
00497                          src_coef_arrays,
00498                          &transformoption);
00499 #else
00500   dst_coef_arrays = src_coef_arrays;
00501 #endif
00502 
00503   /* Close input file, if we opened it.
00504    * Note: we assume that jpeg_read_coefficients consumed all input
00505    * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
00506    * only consume more while (! cinfo->inputctl->eoi_reached).
00507    * We cannot call jpeg_finish_decompress here since we still need the
00508    * virtual arrays allocated from the source object for processing.
00509    */
00510   if (fp != stdin)
00511     fclose(fp);
00512 
00513   /* Open the output file. */
00514   if (outfilename != NULL) {
00515     if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
00516       fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename);
00517       exit(EXIT_FAILURE);
00518     }
00519   } else {
00520     /* default output file is stdout */
00521     fp = write_stdout();
00522   }
00523 
00524   /* Adjust default compression parameters by re-parsing the options */
00525   file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
00526 
00527   /* Specify data destination for compression */
00528   jpeg_stdio_dest(&dstinfo, fp);
00529 
00530   /* Start compressor (note no image data is actually written here) */
00531   jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
00532 
00533   /* Copy to the output file any extra markers that we want to preserve */
00534   jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
00535 
00536   /* Execute image transformation, if any */
00537 #if TRANSFORMS_SUPPORTED
00538   jtransform_execute_transformation(&srcinfo, &dstinfo,
00539                     src_coef_arrays,
00540                     &transformoption);
00541 #endif
00542 
00543   /* Finish compression and release memory */
00544   jpeg_finish_compress(&dstinfo);
00545   jpeg_destroy_compress(&dstinfo);
00546   (void) jpeg_finish_decompress(&srcinfo);
00547   jpeg_destroy_decompress(&srcinfo);
00548 
00549   /* Close output file, if we opened it */
00550   if (fp != stdout)
00551     fclose(fp);
00552 
00553 #ifdef PROGRESS_REPORT
00554   end_progress_monitor((j_common_ptr) &dstinfo);
00555 #endif
00556 
00557   /* All done. */
00558   exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
00559   return 0;         /* suppress no-return-value warnings */
00560 }

Generated on Sun May 27 2012 04:19:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.