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