Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenjpegtran.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
1.7.6.1
|