00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "cdjpeg.h"
00028 #include "jversion.h"
00029
00030 #ifdef USE_CCOMMAND
00031 #ifdef __MWERKS__
00032 #include <SIOUX.h>
00033 #include <console.h>
00034 #endif
00035 #ifdef THINK_C
00036 #include <console.h>
00037 #endif
00038 #endif
00039
00040
00041
00042
00043 #define JMESSAGE(code,string) string ,
00044
00045 static const char * const cdjpeg_message_table[] = {
00046 #include "cderror.h"
00047 NULL
00048 };
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 static boolean is_targa;
00078
00079
00080 LOCAL(cjpeg_source_ptr)
00081 select_file_type (j_compress_ptr cinfo, FILE * infile)
00082 {
00083 int c;
00084
00085 if (is_targa) {
00086 #ifdef TARGA_SUPPORTED
00087 return jinit_read_targa(cinfo);
00088 #else
00089 ERREXIT(cinfo, JERR_TGA_NOTCOMP);
00090 #endif
00091 }
00092
00093 if ((c = getc(infile)) == EOF)
00094 ERREXIT(cinfo, JERR_INPUT_EMPTY);
00095 if (ungetc(c, infile) == EOF)
00096 ERREXIT(cinfo, JERR_UNGETC_FAILED);
00097
00098 switch (c) {
00099 #ifdef BMP_SUPPORTED
00100 case 'B':
00101 return jinit_read_bmp(cinfo);
00102 #endif
00103 #ifdef GIF_SUPPORTED
00104 case 'G':
00105 return jinit_read_gif(cinfo);
00106 #endif
00107 #ifdef PPM_SUPPORTED
00108 case 'P':
00109 return jinit_read_ppm(cinfo);
00110 #endif
00111 #ifdef RLE_SUPPORTED
00112 case 'R':
00113 return jinit_read_rle(cinfo);
00114 #endif
00115 #ifdef TARGA_SUPPORTED
00116 case 0x00:
00117 return jinit_read_targa(cinfo);
00118 #endif
00119 default:
00120 ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
00121 break;
00122 }
00123
00124 return NULL;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static const char * progname;
00138 static char * outfilename;
00139
00140
00141 LOCAL(void)
00142 usage (void)
00143
00144 {
00145 fprintf(stderr, "usage: %s [switches] ", progname);
00146 #ifdef TWO_FILE_COMMANDLINE
00147 fprintf(stderr, "inputfile outputfile\n");
00148 #else
00149 fprintf(stderr, "[inputfile]\n");
00150 #endif
00151
00152 fprintf(stderr, "Switches (names may be abbreviated):\n");
00153 fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n");
00154 fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
00155 #ifdef ENTROPY_OPT_SUPPORTED
00156 fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
00157 #endif
00158 #ifdef C_PROGRESSIVE_SUPPORTED
00159 fprintf(stderr, " -progressive Create progressive JPEG file\n");
00160 #endif
00161 #ifdef DCT_SCALING_SUPPORTED
00162 fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\n");
00163 #endif
00164 #ifdef TARGA_SUPPORTED
00165 fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
00166 #endif
00167 fprintf(stderr, "Switches for advanced users:\n");
00168 #ifdef DCT_ISLOW_SUPPORTED
00169 fprintf(stderr, " -dct int Use integer DCT method%s\n",
00170 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
00171 #endif
00172 #ifdef DCT_IFAST_SUPPORTED
00173 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
00174 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
00175 #endif
00176 #ifdef DCT_FLOAT_SUPPORTED
00177 fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
00178 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
00179 #endif
00180 fprintf(stderr, " -nosmooth Don't use high-quality downsampling\n");
00181 fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
00182 #ifdef INPUT_SMOOTHING_SUPPORTED
00183 fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
00184 #endif
00185 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
00186 fprintf(stderr, " -outfile name Specify name for output file\n");
00187 fprintf(stderr, " -verbose or -debug Emit debug output\n");
00188 fprintf(stderr, "Switches for wizards:\n");
00189 #ifdef C_ARITH_CODING_SUPPORTED
00190 fprintf(stderr, " -arithmetic Use arithmetic coding\n");
00191 #endif
00192 fprintf(stderr, " -baseline Force baseline quantization tables\n");
00193 fprintf(stderr, " -qtables file Use quantization tables given in file\n");
00194 fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
00195 fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
00196 #ifdef C_MULTISCAN_FILES_SUPPORTED
00197 fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
00198 #endif
00199 exit(EXIT_FAILURE);
00200 }
00201
00202
00203 LOCAL(int)
00204 parse_switches (j_compress_ptr cinfo, int argc, char **argv,
00205 int last_file_arg_seen, boolean for_real)
00206
00207
00208
00209
00210
00211
00212
00213
00214 {
00215 int argn;
00216 char * arg;
00217 boolean force_baseline;
00218 boolean simple_progressive;
00219 char * qualityarg = NULL;
00220 char * qtablefile = NULL;
00221 char * qslotsarg = NULL;
00222 char * samplearg = NULL;
00223 char * scansarg = NULL;
00224
00225
00226
00227 force_baseline = FALSE;
00228 simple_progressive = FALSE;
00229 is_targa = FALSE;
00230 outfilename = NULL;
00231 cinfo->err->trace_level = 0;
00232
00233
00234
00235 for (argn = 1; argn < argc; argn++) {
00236 arg = argv[argn];
00237 if (*arg != '-') {
00238
00239 if (argn <= last_file_arg_seen) {
00240 outfilename = NULL;
00241 continue;
00242 }
00243 break;
00244 }
00245 arg++;
00246
00247 if (keymatch(arg, "arithmetic", 1)) {
00248
00249 #ifdef C_ARITH_CODING_SUPPORTED
00250 cinfo->arith_code = TRUE;
00251 #else
00252 fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
00253 progname);
00254 exit(EXIT_FAILURE);
00255 #endif
00256
00257 } else if (keymatch(arg, "baseline", 1)) {
00258
00259 force_baseline = TRUE;
00260
00261 } else if (keymatch(arg, "dct", 2)) {
00262
00263 if (++argn >= argc)
00264 usage();
00265 if (keymatch(argv[argn], "int", 1)) {
00266 cinfo->dct_method = JDCT_ISLOW;
00267 } else if (keymatch(argv[argn], "fast", 2)) {
00268 cinfo->dct_method = JDCT_IFAST;
00269 } else if (keymatch(argv[argn], "float", 2)) {
00270 cinfo->dct_method = JDCT_FLOAT;
00271 } else
00272 usage();
00273
00274 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
00275
00276
00277 static boolean printed_version = FALSE;
00278
00279 if (! printed_version) {
00280 fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
00281 JVERSION, JCOPYRIGHT);
00282 printed_version = TRUE;
00283 }
00284 cinfo->err->trace_level++;
00285
00286 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
00287
00288 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
00289
00290 } else if (keymatch(arg, "maxmemory", 3)) {
00291
00292 long lval;
00293 char ch = 'x';
00294
00295 if (++argn >= argc)
00296 usage();
00297 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
00298 usage();
00299 if (ch == 'm' || ch == 'M')
00300 lval *= 1000L;
00301 cinfo->mem->max_memory_to_use = lval * 1000L;
00302
00303 } else if (keymatch(arg, "nosmooth", 3)) {
00304
00305 cinfo->do_fancy_downsampling = FALSE;
00306
00307 } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
00308
00309 #ifdef ENTROPY_OPT_SUPPORTED
00310 cinfo->optimize_coding = TRUE;
00311 #else
00312 fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
00313 progname);
00314 exit(EXIT_FAILURE);
00315 #endif
00316
00317 } else if (keymatch(arg, "outfile", 4)) {
00318
00319 if (++argn >= argc)
00320 usage();
00321 outfilename = argv[argn];
00322
00323 } else if (keymatch(arg, "progressive", 1)) {
00324
00325 #ifdef C_PROGRESSIVE_SUPPORTED
00326 simple_progressive = TRUE;
00327
00328 #else
00329 fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
00330 progname);
00331 exit(EXIT_FAILURE);
00332 #endif
00333
00334 } else if (keymatch(arg, "quality", 1)) {
00335
00336 if (++argn >= argc)
00337 usage();
00338 qualityarg = argv[argn];
00339
00340 } else if (keymatch(arg, "qslots", 2)) {
00341
00342 if (++argn >= argc)
00343 usage();
00344 qslotsarg = argv[argn];
00345
00346
00347
00348
00349
00350 } else if (keymatch(arg, "qtables", 2)) {
00351
00352 if (++argn >= argc)
00353 usage();
00354 qtablefile = argv[argn];
00355
00356
00357 } else if (keymatch(arg, "restart", 1)) {
00358
00359 long lval;
00360 char ch = 'x';
00361
00362 if (++argn >= argc)
00363 usage();
00364 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
00365 usage();
00366 if (lval < 0 || lval > 65535L)
00367 usage();
00368 if (ch == 'b' || ch == 'B') {
00369 cinfo->restart_interval = (unsigned int) lval;
00370 cinfo->restart_in_rows = 0;
00371 } else {
00372 cinfo->restart_in_rows = (int) lval;
00373
00374 }
00375
00376 } else if (keymatch(arg, "sample", 2)) {
00377
00378 if (++argn >= argc)
00379 usage();
00380 samplearg = argv[argn];
00381
00382
00383
00384
00385
00386 } else if (keymatch(arg, "scale", 4)) {
00387
00388 if (++argn >= argc)
00389 usage();
00390 if (sscanf(argv[argn], "%d/%d",
00391 &cinfo->scale_num, &cinfo->scale_denom) != 2)
00392 usage();
00393
00394 } else if (keymatch(arg, "scans", 4)) {
00395
00396 #ifdef C_MULTISCAN_FILES_SUPPORTED
00397 if (++argn >= argc)
00398 usage();
00399 scansarg = argv[argn];
00400
00401 #else
00402 fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
00403 progname);
00404 exit(EXIT_FAILURE);
00405 #endif
00406
00407 } else if (keymatch(arg, "smooth", 2)) {
00408
00409 int val;
00410
00411 if (++argn >= argc)
00412 usage();
00413 if (sscanf(argv[argn], "%d", &val) != 1)
00414 usage();
00415 if (val < 0 || val > 100)
00416 usage();
00417 cinfo->smoothing_factor = val;
00418
00419 } else if (keymatch(arg, "targa", 1)) {
00420
00421 is_targa = TRUE;
00422
00423 } else {
00424 usage();
00425 }
00426 }
00427
00428
00429
00430 if (for_real) {
00431
00432
00433
00434 if (qualityarg != NULL)
00435 if (! set_quality_ratings(cinfo, qualityarg, force_baseline))
00436 usage();
00437
00438 if (qtablefile != NULL)
00439 if (! read_quant_tables(cinfo, qtablefile, force_baseline))
00440 usage();
00441
00442 if (qslotsarg != NULL)
00443 if (! set_quant_slots(cinfo, qslotsarg))
00444 usage();
00445
00446 if (samplearg != NULL)
00447 if (! set_sample_factors(cinfo, samplearg))
00448 usage();
00449
00450 #ifdef C_PROGRESSIVE_SUPPORTED
00451 if (simple_progressive)
00452 jpeg_simple_progression(cinfo);
00453 #endif
00454
00455 #ifdef C_MULTISCAN_FILES_SUPPORTED
00456 if (scansarg != NULL)
00457 if (! read_scan_script(cinfo, scansarg))
00458 usage();
00459 #endif
00460 }
00461
00462 return argn;
00463 }
00464
00465
00466
00467
00468
00469
00470 int
00471 main (int argc, char **argv)
00472 {
00473 struct jpeg_compress_struct cinfo;
00474 struct jpeg_error_mgr jerr;
00475 #ifdef PROGRESS_REPORT
00476 struct cdjpeg_progress_mgr progress;
00477 #endif
00478 int file_index;
00479 cjpeg_source_ptr src_mgr;
00480 FILE * input_file;
00481 FILE * output_file;
00482 JDIMENSION num_scanlines;
00483
00484
00485 #ifdef USE_CCOMMAND
00486 argc = ccommand(&argv);
00487 #endif
00488
00489 progname = argv[0];
00490 if (progname == NULL || progname[0] == 0)
00491 progname = "cjpeg";
00492
00493
00494 cinfo.err = jpeg_std_error(&jerr);
00495 jpeg_create_compress(&cinfo);
00496
00497 jerr.addon_message_table = cdjpeg_message_table;
00498 jerr.first_addon_message = JMSG_FIRSTADDONCODE;
00499 jerr.last_addon_message = JMSG_LASTADDONCODE;
00500
00501
00502 #ifdef NEED_SIGNAL_CATCHER
00503 enable_signal_catcher((j_common_ptr) &cinfo);
00504 #endif
00505
00506
00507
00508
00509
00510
00511
00512 cinfo.in_color_space = JCS_RGB;
00513 jpeg_set_defaults(&cinfo);
00514
00515
00516
00517
00518
00519
00520
00521 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
00522
00523 #ifdef TWO_FILE_COMMANDLINE
00524
00525 if (outfilename == NULL) {
00526 if (file_index != argc-2) {
00527 fprintf(stderr, "%s: must name one input and one output file\n",
00528 progname);
00529 usage();
00530 }
00531 outfilename = argv[file_index+1];
00532 } else {
00533 if (file_index != argc-1) {
00534 fprintf(stderr, "%s: must name one input and one output file\n",
00535 progname);
00536 usage();
00537 }
00538 }
00539 #else
00540
00541 if (file_index < argc-1) {
00542 fprintf(stderr, "%s: only one input file\n", progname);
00543 usage();
00544 }
00545 #endif
00546
00547
00548 if (file_index < argc) {
00549 if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
00550 fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
00551 exit(EXIT_FAILURE);
00552 }
00553 } else {
00554
00555 input_file = read_stdin();
00556 }
00557
00558
00559 if (outfilename != NULL) {
00560 if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
00561 fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
00562 exit(EXIT_FAILURE);
00563 }
00564 } else {
00565
00566 output_file = write_stdout();
00567 }
00568
00569 #ifdef PROGRESS_REPORT
00570 start_progress_monitor((j_common_ptr) &cinfo, &progress);
00571 #endif
00572
00573
00574 src_mgr = select_file_type(&cinfo, input_file);
00575 src_mgr->input_file = input_file;
00576
00577
00578 (*src_mgr->start_input) (&cinfo, src_mgr);
00579
00580
00581 jpeg_default_colorspace(&cinfo);
00582
00583
00584 file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
00585
00586
00587 jpeg_stdio_dest(&cinfo, output_file);
00588
00589
00590 jpeg_start_compress(&cinfo, TRUE);
00591
00592
00593 while (cinfo.next_scanline < cinfo.image_height) {
00594 num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
00595 (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
00596 }
00597
00598
00599 (*src_mgr->finish_input) (&cinfo, src_mgr);
00600 jpeg_finish_compress(&cinfo);
00601 jpeg_destroy_compress(&cinfo);
00602
00603
00604 if (input_file != stdin)
00605 fclose(input_file);
00606 if (output_file != stdout)
00607 fclose(output_file);
00608
00609 #ifdef PROGRESS_REPORT
00610 end_progress_monitor((j_common_ptr) &cinfo);
00611 #endif
00612
00613
00614 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
00615 return 0;
00616 }