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 }