00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "cdjpeg.h"
00015 #include "transupp.h"
00016 #include "jversion.h"
00017
00018 #ifdef USE_CCOMMAND
00019 #ifdef __MWERKS__
00020 #include <SIOUX.h>
00021 #include <console.h>
00022 #endif
00023 #ifdef THINK_C
00024 #include <console.h>
00025 #endif
00026 #endif
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 static const char * progname;
00039 static char * outfilename;
00040 static char * scaleoption;
00041 static JCOPY_OPTION copyoption;
00042 static jpeg_transform_info transformoption;
00043
00044
00045 LOCAL(void)
00046 usage (void)
00047
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
00099
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
00123
00124
00125
00126
00127
00128
00129
00130 {
00131 int argn;
00132 char * arg;
00133 boolean simple_progressive;
00134 char * scansarg = NULL;
00135
00136
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
00149
00150 for (argn = 1; argn < argc; argn++) {
00151 arg = argv[argn];
00152 if (*arg != '-') {
00153
00154 if (argn <= last_file_arg_seen) {
00155 outfilename = NULL;
00156 continue;
00157 }
00158 break;
00159 }
00160 arg++;
00161
00162 if (keymatch(arg, "arithmetic", 1)) {
00163
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
00174 if (++argn >= argc)
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
00187 #if TRANSFORMS_SUPPORTED
00188 if (++argn >= argc)
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);
00197 #endif
00198
00199 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
00200
00201
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
00213 if (++argn >= argc)
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
00224 #if TRANSFORMS_SUPPORTED
00225 transformoption.force_grayscale = TRUE;
00226 #else
00227 select_transform(JXFORM_NONE);
00228 #endif
00229
00230 } else if (keymatch(arg, "maxmemory", 3)) {
00231
00232 long lval;
00233 char ch = 'x';
00234
00235 if (++argn >= argc)
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
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
00255 if (++argn >= argc)
00256 usage();
00257 outfilename = argv[argn];
00258
00259 } else if (keymatch(arg, "perfect", 2)) {
00260
00261
00262 transformoption.perfect = TRUE;
00263
00264 } else if (keymatch(arg, "progressive", 2)) {
00265
00266 #ifdef C_PROGRESSIVE_SUPPORTED
00267 simple_progressive = TRUE;
00268
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
00277 long lval;
00278 char ch = 'x';
00279
00280 if (++argn >= argc)
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;
00289 } else {
00290 cinfo->restart_in_rows = (int) lval;
00291
00292 }
00293
00294 } else if (keymatch(arg, "rotate", 2)) {
00295
00296 if (++argn >= argc)
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
00309 if (++argn >= argc)
00310 usage();
00311 scaleoption = argv[argn];
00312
00313
00314 } else if (keymatch(arg, "scans", 1)) {
00315
00316 #ifdef C_MULTISCAN_FILES_SUPPORTED
00317 if (++argn >= argc)
00318 usage();
00319 scansarg = argv[argn];
00320
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
00329 select_transform(JXFORM_TRANSPOSE);
00330
00331 } else if (keymatch(arg, "transverse", 6)) {
00332
00333 select_transform(JXFORM_TRANSVERSE);
00334
00335 } else if (keymatch(arg, "trim", 3)) {
00336
00337 transformoption.trim = TRUE;
00338
00339 } else {
00340 usage();
00341 }
00342 }
00343
00344
00345
00346 if (for_real) {
00347
00348 #ifdef C_PROGRESSIVE_SUPPORTED
00349 if (simple_progressive)
00350 jpeg_simple_progression(cinfo);
00351 #endif
00352
00353 #ifdef C_MULTISCAN_FILES_SUPPORTED
00354 if (scansarg != NULL)
00355 if (! read_scan_script(cinfo, scansarg))
00356 usage();
00357 #endif
00358 }
00359
00360 return argn;
00361 }
00362
00363
00364
00365
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
00381
00382
00383 FILE * fp;
00384
00385
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";
00393
00394
00395 srcinfo.err = jpeg_std_error(&jsrcerr);
00396 jpeg_create_decompress(&srcinfo);
00397
00398 dstinfo.err = jpeg_std_error(&jdsterr);
00399 jpeg_create_compress(&dstinfo);
00400
00401
00402
00403
00404 #ifdef NEED_SIGNAL_CATCHER
00405 enable_signal_catcher((j_common_ptr) &srcinfo);
00406 #endif
00407
00408
00409
00410
00411
00412
00413
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
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
00438 if (file_index < argc-1) {
00439 fprintf(stderr, "%s: only one input file\n", progname);
00440 usage();
00441 }
00442 #endif
00443
00444
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
00452 fp = read_stdin();
00453 }
00454
00455 #ifdef PROGRESS_REPORT
00456 start_progress_monitor((j_common_ptr) &dstinfo, &progress);
00457 #endif
00458
00459
00460 jpeg_stdio_src(&srcinfo, fp);
00461
00462
00463 jcopy_markers_setup(&srcinfo, copyoption);
00464
00465
00466 (void) jpeg_read_header(&srcinfo, TRUE);
00467
00468
00469 if (scaleoption != NULL)
00470 if (sscanf(scaleoption, "%d/%d",
00471 &srcinfo.scale_num, &srcinfo.scale_denom) < 1)
00472 usage();
00473
00474
00475
00476
00477 #if TRANSFORMS_SUPPORTED
00478
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
00487 src_coef_arrays = jpeg_read_coefficients(&srcinfo);
00488
00489
00490 jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
00491
00492
00493
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
00504
00505
00506
00507
00508
00509
00510 if (fp != stdin)
00511 fclose(fp);
00512
00513
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
00521 fp = write_stdout();
00522 }
00523
00524
00525 file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
00526
00527
00528 jpeg_stdio_dest(&dstinfo, fp);
00529
00530
00531 jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
00532
00533
00534 jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
00535
00536
00537 #if TRANSFORMS_SUPPORTED
00538 jtransform_execute_transformation(&srcinfo, &dstinfo,
00539 src_coef_arrays,
00540 &transformoption);
00541 #endif
00542
00543
00544 jpeg_finish_compress(&dstinfo);
00545 jpeg_destroy_compress(&dstinfo);
00546 (void) jpeg_finish_decompress(&srcinfo);
00547 jpeg_destroy_decompress(&srcinfo);
00548
00549
00550 if (fp != stdout)
00551 fclose(fp);
00552
00553 #ifdef PROGRESS_REPORT
00554 end_progress_monitor((j_common_ptr) &dstinfo);
00555 #endif
00556
00557
00558 exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
00559 return 0;
00560 }