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