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 #include <ctype.h>
00031
00032 #ifdef USE_CCOMMAND
00033 #ifdef __MWERKS__
00034 #include <SIOUX.h>
00035 #include <console.h>
00036 #endif
00037 #ifdef THINK_C
00038 #include <console.h>
00039 #endif
00040 #endif
00041
00042
00043
00044
00045 #define JMESSAGE(code,string) string ,
00046
00047 static const char * const cdjpeg_message_table[] = {
00048 #include "cderror.h"
00049 NULL
00050 };
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 typedef enum {
00061 FMT_BMP,
00062 FMT_GIF,
00063 FMT_OS2,
00064 FMT_PPM,
00065 FMT_RLE,
00066 FMT_TARGA,
00067 FMT_TIFF
00068 } IMAGE_FORMATS;
00069
00070 #ifndef DEFAULT_FMT
00071 #define DEFAULT_FMT FMT_PPM
00072 #endif
00073
00074 static IMAGE_FORMATS requested_fmt;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static const char * progname;
00087 static char * outfilename;
00088
00089
00090 LOCAL(void)
00091 usage (void)
00092
00093 {
00094 fprintf(stderr, "usage: %s [switches] ", progname);
00095 #ifdef TWO_FILE_COMMANDLINE
00096 fprintf(stderr, "inputfile outputfile\n");
00097 #else
00098 fprintf(stderr, "[inputfile]\n");
00099 #endif
00100
00101 fprintf(stderr, "Switches (names may be abbreviated):\n");
00102 fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
00103 fprintf(stderr, " -fast Fast, low-quality processing\n");
00104 fprintf(stderr, " -grayscale Force grayscale output\n");
00105 #ifdef IDCT_SCALING_SUPPORTED
00106 fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
00107 #endif
00108 #ifdef BMP_SUPPORTED
00109 fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
00110 (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
00111 #endif
00112 #ifdef GIF_SUPPORTED
00113 fprintf(stderr, " -gif Select GIF output format%s\n",
00114 (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
00115 #endif
00116 #ifdef BMP_SUPPORTED
00117 fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
00118 (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
00119 #endif
00120 #ifdef PPM_SUPPORTED
00121 fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
00122 (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
00123 #endif
00124 #ifdef RLE_SUPPORTED
00125 fprintf(stderr, " -rle Select Utah RLE output format%s\n",
00126 (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
00127 #endif
00128 #ifdef TARGA_SUPPORTED
00129 fprintf(stderr, " -targa Select Targa output format%s\n",
00130 (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
00131 #endif
00132 fprintf(stderr, "Switches for advanced users:\n");
00133 #ifdef DCT_ISLOW_SUPPORTED
00134 fprintf(stderr, " -dct int Use integer DCT method%s\n",
00135 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
00136 #endif
00137 #ifdef DCT_IFAST_SUPPORTED
00138 fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
00139 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
00140 #endif
00141 #ifdef DCT_FLOAT_SUPPORTED
00142 fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
00143 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
00144 #endif
00145 fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
00146 fprintf(stderr, " -dither none Don't use dithering in quantization\n");
00147 fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
00148 #ifdef QUANT_2PASS_SUPPORTED
00149 fprintf(stderr, " -map FILE Map to colors used in named image file\n");
00150 #endif
00151 fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
00152 #ifdef QUANT_1PASS_SUPPORTED
00153 fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
00154 #endif
00155 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
00156 fprintf(stderr, " -outfile name Specify name for output file\n");
00157 fprintf(stderr, " -verbose or -debug Emit debug output\n");
00158 exit(EXIT_FAILURE);
00159 }
00160
00161
00162 LOCAL(int)
00163 parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
00164 int last_file_arg_seen, boolean for_real)
00165
00166
00167
00168
00169
00170
00171
00172
00173 {
00174 int argn;
00175 char * arg;
00176
00177
00178 requested_fmt = DEFAULT_FMT;
00179 outfilename = NULL;
00180 cinfo->err->trace_level = 0;
00181
00182
00183
00184 for (argn = 1; argn < argc; argn++) {
00185 arg = argv[argn];
00186 if (*arg != '-') {
00187
00188 if (argn <= last_file_arg_seen) {
00189 outfilename = NULL;
00190 continue;
00191 }
00192 break;
00193 }
00194 arg++;
00195
00196 if (keymatch(arg, "bmp", 1)) {
00197
00198 requested_fmt = FMT_BMP;
00199
00200 } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
00201 keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
00202
00203 int val;
00204
00205 if (++argn >= argc)
00206 usage();
00207 if (sscanf(argv[argn], "%d", &val) != 1)
00208 usage();
00209 cinfo->desired_number_of_colors = val;
00210 cinfo->quantize_colors = TRUE;
00211
00212 } else if (keymatch(arg, "dct", 2)) {
00213
00214 if (++argn >= argc)
00215 usage();
00216 if (keymatch(argv[argn], "int", 1)) {
00217 cinfo->dct_method = JDCT_ISLOW;
00218 } else if (keymatch(argv[argn], "fast", 2)) {
00219 cinfo->dct_method = JDCT_IFAST;
00220 } else if (keymatch(argv[argn], "float", 2)) {
00221 cinfo->dct_method = JDCT_FLOAT;
00222 } else
00223 usage();
00224
00225 } else if (keymatch(arg, "dither", 2)) {
00226
00227 if (++argn >= argc)
00228 usage();
00229 if (keymatch(argv[argn], "fs", 2)) {
00230 cinfo->dither_mode = JDITHER_FS;
00231 } else if (keymatch(argv[argn], "none", 2)) {
00232 cinfo->dither_mode = JDITHER_NONE;
00233 } else if (keymatch(argv[argn], "ordered", 2)) {
00234 cinfo->dither_mode = JDITHER_ORDERED;
00235 } else
00236 usage();
00237
00238 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
00239
00240
00241 static boolean printed_version = FALSE;
00242
00243 if (! printed_version) {
00244 fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
00245 JVERSION, JCOPYRIGHT);
00246 printed_version = TRUE;
00247 }
00248 cinfo->err->trace_level++;
00249
00250 } else if (keymatch(arg, "fast", 1)) {
00251
00252 cinfo->two_pass_quantize = FALSE;
00253 cinfo->dither_mode = JDITHER_ORDERED;
00254 if (! cinfo->quantize_colors)
00255 cinfo->desired_number_of_colors = 216;
00256 cinfo->dct_method = JDCT_FASTEST;
00257 cinfo->do_fancy_upsampling = FALSE;
00258
00259 } else if (keymatch(arg, "gif", 1)) {
00260
00261 requested_fmt = FMT_GIF;
00262
00263 } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
00264
00265 cinfo->out_color_space = JCS_GRAYSCALE;
00266
00267 } else if (keymatch(arg, "map", 3)) {
00268
00269 if (++argn >= argc)
00270 usage();
00271 if (for_real) {
00272 #ifdef QUANT_2PASS_SUPPORTED
00273 FILE * mapfile;
00274
00275 if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
00276 fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
00277 exit(EXIT_FAILURE);
00278 }
00279 read_color_map(cinfo, mapfile);
00280 fclose(mapfile);
00281 cinfo->quantize_colors = TRUE;
00282 #else
00283 ERREXIT(cinfo, JERR_NOT_COMPILED);
00284 #endif
00285 }
00286
00287 } else if (keymatch(arg, "maxmemory", 3)) {
00288
00289 long lval;
00290 char ch = 'x';
00291
00292 if (++argn >= argc)
00293 usage();
00294 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
00295 usage();
00296 if (ch == 'm' || ch == 'M')
00297 lval *= 1000L;
00298 cinfo->mem->max_memory_to_use = lval * 1000L;
00299
00300 } else if (keymatch(arg, "nosmooth", 3)) {
00301
00302 cinfo->do_fancy_upsampling = FALSE;
00303
00304 } else if (keymatch(arg, "onepass", 3)) {
00305
00306 cinfo->two_pass_quantize = FALSE;
00307
00308 } else if (keymatch(arg, "os2", 3)) {
00309
00310 requested_fmt = FMT_OS2;
00311
00312 } else if (keymatch(arg, "outfile", 4)) {
00313
00314 if (++argn >= argc)
00315 usage();
00316 outfilename = argv[argn];
00317
00318 } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
00319
00320 requested_fmt = FMT_PPM;
00321
00322 } else if (keymatch(arg, "rle", 1)) {
00323
00324 requested_fmt = FMT_RLE;
00325
00326 } else if (keymatch(arg, "scale", 1)) {
00327
00328 if (++argn >= argc)
00329 usage();
00330 if (sscanf(argv[argn], "%d/%d",
00331 &cinfo->scale_num, &cinfo->scale_denom) < 1)
00332 usage();
00333
00334 } else if (keymatch(arg, "targa", 1)) {
00335
00336 requested_fmt = FMT_TARGA;
00337
00338 } else {
00339 usage();
00340 }
00341 }
00342
00343 return argn;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 LOCAL(unsigned int)
00355 jpeg_getc (j_decompress_ptr cinfo)
00356
00357 {
00358 struct jpeg_source_mgr * datasrc = cinfo->src;
00359
00360 if (datasrc->bytes_in_buffer == 0) {
00361 if (! (*datasrc->fill_input_buffer) (cinfo))
00362 ERREXIT(cinfo, JERR_CANT_SUSPEND);
00363 }
00364 datasrc->bytes_in_buffer--;
00365 return GETJOCTET(*datasrc->next_input_byte++);
00366 }
00367
00368
00369 METHODDEF(boolean)
00370 print_text_marker (j_decompress_ptr cinfo)
00371 {
00372 boolean traceit = (cinfo->err->trace_level >= 1);
00373 INT32 length;
00374 unsigned int ch;
00375 unsigned int lastch = 0;
00376
00377 length = jpeg_getc(cinfo) << 8;
00378 length += jpeg_getc(cinfo);
00379 length -= 2;
00380
00381 if (traceit) {
00382 if (cinfo->unread_marker == JPEG_COM)
00383 fprintf(stderr, "Comment, length %ld:\n", (long) length);
00384 else
00385 fprintf(stderr, "APP%d, length %ld:\n",
00386 cinfo->unread_marker - JPEG_APP0, (long) length);
00387 }
00388
00389 while (--length >= 0) {
00390 ch = jpeg_getc(cinfo);
00391 if (traceit) {
00392
00393
00394
00395
00396
00397 if (ch == '\r') {
00398 fprintf(stderr, "\n");
00399 } else if (ch == '\n') {
00400 if (lastch != '\r')
00401 fprintf(stderr, "\n");
00402 } else if (ch == '\\') {
00403 fprintf(stderr, "\\\\");
00404 } else if (isprint(ch)) {
00405 putc(ch, stderr);
00406 } else {
00407 fprintf(stderr, "\\%03o", ch);
00408 }
00409 lastch = ch;
00410 }
00411 }
00412
00413 if (traceit)
00414 fprintf(stderr, "\n");
00415
00416 return TRUE;
00417 }
00418
00419
00420
00421
00422
00423
00424 int
00425 main (int argc, char **argv)
00426 {
00427 struct jpeg_decompress_struct cinfo;
00428 struct jpeg_error_mgr jerr;
00429 #ifdef PROGRESS_REPORT
00430 struct cdjpeg_progress_mgr progress;
00431 #endif
00432 int file_index;
00433 djpeg_dest_ptr dest_mgr = NULL;
00434 FILE * input_file;
00435 FILE * output_file;
00436 JDIMENSION num_scanlines;
00437
00438
00439 #ifdef USE_CCOMMAND
00440 argc = ccommand(&argv);
00441 #endif
00442
00443 progname = argv[0];
00444 if (progname == NULL || progname[0] == 0)
00445 progname = "djpeg";
00446
00447
00448 cinfo.err = jpeg_std_error(&jerr);
00449 jpeg_create_decompress(&cinfo);
00450
00451 jerr.addon_message_table = cdjpeg_message_table;
00452 jerr.first_addon_message = JMSG_FIRSTADDONCODE;
00453 jerr.last_addon_message = JMSG_LASTADDONCODE;
00454
00455
00456
00457
00458
00459
00460
00461 jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
00462 jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
00463
00464
00465 #ifdef NEED_SIGNAL_CATCHER
00466 enable_signal_catcher((j_common_ptr) &cinfo);
00467 #endif
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
00478
00479 #ifdef TWO_FILE_COMMANDLINE
00480
00481 if (outfilename == NULL) {
00482 if (file_index != argc-2) {
00483 fprintf(stderr, "%s: must name one input and one output file\n",
00484 progname);
00485 usage();
00486 }
00487 outfilename = argv[file_index+1];
00488 } else {
00489 if (file_index != argc-1) {
00490 fprintf(stderr, "%s: must name one input and one output file\n",
00491 progname);
00492 usage();
00493 }
00494 }
00495 #else
00496
00497 if (file_index < argc-1) {
00498 fprintf(stderr, "%s: only one input file\n", progname);
00499 usage();
00500 }
00501 #endif
00502
00503
00504 if (file_index < argc) {
00505 if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
00506 fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
00507 exit(EXIT_FAILURE);
00508 }
00509 } else {
00510
00511 input_file = read_stdin();
00512 }
00513
00514
00515 if (outfilename != NULL) {
00516 if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
00517 fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
00518 exit(EXIT_FAILURE);
00519 }
00520 } else {
00521
00522 output_file = write_stdout();
00523 }
00524
00525 #ifdef PROGRESS_REPORT
00526 start_progress_monitor((j_common_ptr) &cinfo, &progress);
00527 #endif
00528
00529
00530 jpeg_stdio_src(&cinfo, input_file);
00531
00532
00533 (void) jpeg_read_header(&cinfo, TRUE);
00534
00535
00536 file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
00537
00538
00539
00540
00541 switch (requested_fmt) {
00542 #ifdef BMP_SUPPORTED
00543 case FMT_BMP:
00544 dest_mgr = jinit_write_bmp(&cinfo, FALSE);
00545 break;
00546 case FMT_OS2:
00547 dest_mgr = jinit_write_bmp(&cinfo, TRUE);
00548 break;
00549 #endif
00550 #ifdef GIF_SUPPORTED
00551 case FMT_GIF:
00552 dest_mgr = jinit_write_gif(&cinfo);
00553 break;
00554 #endif
00555 #ifdef PPM_SUPPORTED
00556 case FMT_PPM:
00557 dest_mgr = jinit_write_ppm(&cinfo);
00558 break;
00559 #endif
00560 #ifdef RLE_SUPPORTED
00561 case FMT_RLE:
00562 dest_mgr = jinit_write_rle(&cinfo);
00563 break;
00564 #endif
00565 #ifdef TARGA_SUPPORTED
00566 case FMT_TARGA:
00567 dest_mgr = jinit_write_targa(&cinfo);
00568 break;
00569 #endif
00570 default:
00571 ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
00572 break;
00573 }
00574 dest_mgr->output_file = output_file;
00575
00576
00577 (void) jpeg_start_decompress(&cinfo);
00578
00579
00580 (*dest_mgr->start_output) (&cinfo, dest_mgr);
00581
00582
00583 while (cinfo.output_scanline < cinfo.output_height) {
00584 num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
00585 dest_mgr->buffer_height);
00586 (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
00587 }
00588
00589 #ifdef PROGRESS_REPORT
00590
00591
00592
00593 progress.pub.completed_passes = progress.pub.total_passes;
00594 #endif
00595
00596
00597
00598
00599
00600 (*dest_mgr->finish_output) (&cinfo, dest_mgr);
00601 (void) jpeg_finish_decompress(&cinfo);
00602 jpeg_destroy_decompress(&cinfo);
00603
00604
00605 if (input_file != stdin)
00606 fclose(input_file);
00607 if (output_file != stdout)
00608 fclose(output_file);
00609
00610 #ifdef PROGRESS_REPORT
00611 end_progress_monitor((j_common_ptr) &cinfo);
00612 #endif
00613
00614
00615 exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
00616 return 0;
00617 }