jpegtran.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * jpegtran.c
  3. *
  4. * Copyright (C) 1995, Thomas G. Lane.
  5. * This file is part of the Independent JPEG Group's software.
  6. * For conditions of distribution and use, see the accompanying README file.
  7. *
  8. * This file contains a command-line user interface for JPEG transcoding.
  9. * It is very similar to cjpeg.c, but provides lossless transcoding between
  10. * different JPEG file formats.
  11. */
  12. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  13. #include "jversion.h" /* for version message */
  14. #ifdef USE_CCOMMAND /* command-line reader for Macintosh */
  15. #ifdef __MWERKS__
  16. #include <SIOUX.h> /* Metrowerks declares it here */
  17. #endif
  18. #ifdef THINK_C
  19. #include <console.h> /* Think declares it here */
  20. #endif
  21. #endif
  22. /*
  23. * Argument-parsing code.
  24. * The switch parser is designed to be useful with DOS-style command line
  25. * syntax, ie, intermixed switches and file names, where only the switches
  26. * to the left of a given file name affect processing of that file.
  27. * The main program in this file doesn't actually use this capability...
  28. */
  29. static const char * progname; /* program name for error messages */
  30. static char * outfilename; /* for -outfile switch */
  31. LOCAL void
  32. usage( void ) {
  33. /* complain about bad command line */
  34. fprintf( stderr, "usage: %s [switches] ", progname );
  35. #ifdef TWO_FILE_COMMANDLINE
  36. fprintf( stderr, "inputfile outputfile\n" );
  37. #else
  38. fprintf( stderr, "[inputfile]\n" );
  39. #endif
  40. fprintf( stderr, "Switches (names may be abbreviated):\n" );
  41. #ifdef ENTROPY_OPT_SUPPORTED
  42. fprintf( stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n" );
  43. #endif
  44. #ifdef C_PROGRESSIVE_SUPPORTED
  45. fprintf( stderr, " -progressive Create progressive JPEG file\n" );
  46. #endif
  47. fprintf( stderr, "Switches for advanced users:\n" );
  48. fprintf( stderr, " -restart N Set restart interval in rows, or in blocks with B\n" );
  49. fprintf( stderr, " -maxmemory N Maximum memory to use (in kbytes)\n" );
  50. fprintf( stderr, " -outfile name Specify name for output file\n" );
  51. fprintf( stderr, " -verbose or -debug Emit debug output\n" );
  52. fprintf( stderr, "Switches for wizards:\n" );
  53. #ifdef C_ARITH_CODING_SUPPORTED
  54. fprintf( stderr, " -arithmetic Use arithmetic coding\n" );
  55. #endif
  56. #ifdef C_MULTISCAN_FILES_SUPPORTED
  57. fprintf( stderr, " -scans file Create multi-scan JPEG per script file\n" );
  58. #endif
  59. exit( EXIT_FAILURE );
  60. }
  61. LOCAL int
  62. parse_switches( j_compress_ptr cinfo, int argc, char ** argv,
  63. int last_file_arg_seen, boolean for_real ) {
  64. /* Parse optional switches.
  65. * Returns argv[] index of first file-name argument (== argc if none).
  66. * Any file names with indexes <= last_file_arg_seen are ignored;
  67. * they have presumably been processed in a previous iteration.
  68. * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  69. * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  70. * processing.
  71. */
  72. int argn;
  73. char * arg;
  74. boolean simple_progressive;
  75. char * scansarg = NULL; /* saves -scans parm if any */
  76. /* Set up default JPEG parameters. */
  77. simple_progressive = FALSE;
  78. outfilename = NULL;
  79. cinfo->err->trace_level = 0;
  80. /* Scan command line options, adjust parameters */
  81. for ( argn = 1; argn < argc; argn++ ) {
  82. arg = argv[argn];
  83. if ( *arg != '-' ) {
  84. /* Not a switch, must be a file name argument */
  85. if ( argn <= last_file_arg_seen ) {
  86. outfilename = NULL;/* -outfile applies to just one input file */
  87. continue; /* ignore this name if previously processed */
  88. }
  89. break; /* else done parsing switches */
  90. }
  91. arg++; /* advance past switch marker character */
  92. if ( keymatch( arg, "arithmetic", 1 ) ) {
  93. /* Use arithmetic coding. */
  94. #ifdef C_ARITH_CODING_SUPPORTED
  95. cinfo->arith_code = TRUE;
  96. #else
  97. fprintf( stderr, "%s: sorry, arithmetic coding not supported\n",
  98. progname );
  99. exit( EXIT_FAILURE );
  100. #endif
  101. } else if ( keymatch( arg, "debug", 1 ) || keymatch( arg, "verbose", 1 ) ) {
  102. /* Enable debug printouts. */
  103. /* On first -d, print version identification */
  104. static boolean printed_version = FALSE;
  105. if ( !printed_version ) {
  106. fprintf( stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
  107. JVERSION, JCOPYRIGHT );
  108. printed_version = TRUE;
  109. }
  110. cinfo->err->trace_level++;
  111. } else if ( keymatch( arg, "maxmemory", 3 ) ) {
  112. /* Maximum memory in Kb (or Mb with 'm'). */
  113. long lval;
  114. char ch = 'x';
  115. if ( ++argn >= argc ) {/* advance to next argument */
  116. usage();
  117. }
  118. if ( sscanf( argv[argn], "%ld%c", &lval, &ch ) < 1 ) {
  119. usage();
  120. }
  121. if ( ( ch == 'm' ) || ( ch == 'M' ) ) {
  122. lval *= 1000L;
  123. }
  124. cinfo->mem->max_memory_to_use = lval * 1000L;
  125. } else if ( keymatch( arg, "optimize", 1 ) || keymatch( arg, "optimise", 1 ) ) {
  126. /* Enable entropy parm optimization. */
  127. #ifdef ENTROPY_OPT_SUPPORTED
  128. cinfo->optimize_coding = TRUE;
  129. #else
  130. fprintf( stderr, "%s: sorry, entropy optimization was not compiled\n",
  131. progname );
  132. exit( EXIT_FAILURE );
  133. #endif
  134. } else if ( keymatch( arg, "outfile", 4 ) ) {
  135. /* Set output file name. */
  136. if ( ++argn >= argc ) {/* advance to next argument */
  137. usage();
  138. }
  139. outfilename = argv[argn];/* save it away for later use */
  140. } else if ( keymatch( arg, "progressive", 1 ) ) {
  141. /* Select simple progressive mode. */
  142. #ifdef C_PROGRESSIVE_SUPPORTED
  143. simple_progressive = TRUE;
  144. /* We must postpone execution until num_components is known. */
  145. #else
  146. fprintf( stderr, "%s: sorry, progressive output was not compiled\n",
  147. progname );
  148. exit( EXIT_FAILURE );
  149. #endif
  150. } else if ( keymatch( arg, "restart", 1 ) ) {
  151. /* Restart interval in MCU rows (or in MCUs with 'b'). */
  152. long lval;
  153. char ch = 'x';
  154. if ( ++argn >= argc ) {/* advance to next argument */
  155. usage();
  156. }
  157. if ( sscanf( argv[argn], "%ld%c", &lval, &ch ) < 1 ) {
  158. usage();
  159. }
  160. if ( ( lval < 0 ) || ( lval > 65535L ) ) {
  161. usage();
  162. }
  163. if ( ( ch == 'b' ) || ( ch == 'B' ) ) {
  164. cinfo->restart_interval = (unsigned int) lval;
  165. cinfo->restart_in_rows = 0;/* else prior '-restart n' overrides me */
  166. } else {
  167. cinfo->restart_in_rows = (int) lval;
  168. /* restart_interval will be computed during startup */
  169. }
  170. } else if ( keymatch( arg, "scans", 2 ) ) {
  171. /* Set scan script. */
  172. #ifdef C_MULTISCAN_FILES_SUPPORTED
  173. if ( ++argn >= argc ) {/* advance to next argument */
  174. usage();
  175. }
  176. scansarg = argv[argn];
  177. /* We must postpone reading the file in case -progressive appears. */
  178. #else
  179. fprintf( stderr, "%s: sorry, multi-scan output was not compiled\n",
  180. progname );
  181. exit( EXIT_FAILURE );
  182. #endif
  183. } else {
  184. usage(); /* bogus switch */
  185. }
  186. }
  187. /* Post-switch-scanning cleanup */
  188. if ( for_real ) {
  189. #ifdef C_PROGRESSIVE_SUPPORTED
  190. if ( simple_progressive ) {/* process -progressive; -scans can override */
  191. jpeg_simple_progression( cinfo );
  192. }
  193. #endif
  194. #ifdef C_MULTISCAN_FILES_SUPPORTED
  195. if ( scansarg != NULL ) {/* process -scans if it was present */
  196. if ( !read_scan_script( cinfo, scansarg ) ) {
  197. usage();
  198. }
  199. }
  200. #endif
  201. }
  202. return argn; /* return index of next arg (file name) */
  203. }
  204. /*
  205. * The main program.
  206. */
  207. GLOBAL int
  208. main( int argc, char ** argv ) {
  209. struct jpeg_decompress_struct srcinfo;
  210. struct jpeg_compress_struct dstinfo;
  211. struct jpeg_error_mgr jsrcerr, jdsterr;
  212. #ifdef PROGRESS_REPORT
  213. struct cdjpeg_progress_mgr progress;
  214. #endif
  215. jvirt_barray_ptr * coef_arrays;
  216. int file_index;
  217. FILE * input_file;
  218. FILE * output_file;
  219. /* On Mac, fetch a command line. */
  220. #ifdef USE_CCOMMAND
  221. argc = ccommand( &argv );
  222. #endif
  223. progname = argv[0];
  224. if ( ( progname == NULL ) || ( progname[0] == 0 ) ) {
  225. progname = "jpegtran";
  226. } /* in case C library doesn't provide it */
  227. /* Initialize the JPEG decompression object with default error handling. */
  228. srcinfo.err = jpeg_std_error( &jsrcerr );
  229. jpeg_create_decompress( &srcinfo );
  230. /* Initialize the JPEG compression object with default error handling. */
  231. dstinfo.err = jpeg_std_error( &jdsterr );
  232. jpeg_create_compress( &dstinfo );
  233. /* Now safe to enable signal catcher.
  234. * Note: we assume only the decompression object will have virtual arrays.
  235. */
  236. #ifdef NEED_SIGNAL_CATCHER
  237. enable_signal_catcher( ( j_common_ptr ) & srcinfo );
  238. #endif
  239. /* Scan command line to find file names.
  240. * It is convenient to use just one switch-parsing routine, but the switch
  241. * values read here are ignored; we will rescan the switches after opening
  242. * the input file.
  243. */
  244. file_index = parse_switches( &dstinfo, argc, argv, 0, FALSE );
  245. jsrcerr.trace_level = jdsterr.trace_level;
  246. #ifdef TWO_FILE_COMMANDLINE
  247. /* Must have either -outfile switch or explicit output file name */
  248. if ( outfilename == NULL ) {
  249. if ( file_index != argc - 2 ) {
  250. fprintf( stderr, "%s: must name one input and one output file\n",
  251. progname );
  252. usage();
  253. }
  254. outfilename = argv[file_index + 1];
  255. } else {
  256. if ( file_index != argc - 1 ) {
  257. fprintf( stderr, "%s: must name one input and one output file\n",
  258. progname );
  259. usage();
  260. }
  261. }
  262. #else
  263. /* Unix style: expect zero or one file name */
  264. if ( file_index < argc - 1 ) {
  265. fprintf( stderr, "%s: only one input file\n", progname );
  266. usage();
  267. }
  268. #endif /* TWO_FILE_COMMANDLINE */
  269. /* Open the input file. */
  270. if ( file_index < argc ) {
  271. if ( ( input_file = fopen( argv[file_index], READ_BINARY ) ) == NULL ) {
  272. fprintf( stderr, "%s: can't open %s\n", progname, argv[file_index] );
  273. exit( EXIT_FAILURE );
  274. }
  275. } else {
  276. /* default input file is stdin */
  277. input_file = read_stdin();
  278. }
  279. /* Open the output file. */
  280. if ( outfilename != NULL ) {
  281. if ( ( output_file = fopen( outfilename, WRITE_BINARY ) ) == NULL ) {
  282. fprintf( stderr, "%s: can't open %s\n", progname, outfilename );
  283. exit( EXIT_FAILURE );
  284. }
  285. } else {
  286. /* default output file is stdout */
  287. output_file = write_stdout();
  288. }
  289. #ifdef PROGRESS_REPORT
  290. start_progress_monitor( ( j_common_ptr ) & dstinfo, &progress );
  291. #endif
  292. /* Specify data source for decompression */
  293. jpeg_stdio_src( &srcinfo, input_file );
  294. /* Read file header */
  295. (void) jpeg_read_header( &srcinfo, TRUE );
  296. /* Read source file as DCT coefficients */
  297. coef_arrays = jpeg_read_coefficients( &srcinfo );
  298. /* Initialize destination compression parameters from source values */
  299. jpeg_copy_critical_parameters( &srcinfo, &dstinfo );
  300. /* Adjust default compression parameters by re-parsing the options */
  301. file_index = parse_switches( &dstinfo, argc, argv, 0, TRUE );
  302. /* Specify data destination for compression */
  303. jpeg_stdio_dest( &dstinfo, output_file );
  304. /* Start compressor */
  305. jpeg_write_coefficients( &dstinfo, coef_arrays );
  306. /* ought to copy source comments here... */
  307. /* Finish compression and release memory */
  308. jpeg_finish_compress( &dstinfo );
  309. jpeg_destroy_compress( &dstinfo );
  310. (void) jpeg_finish_decompress( &srcinfo );
  311. jpeg_destroy_decompress( &srcinfo );
  312. /* Close files, if we opened them */
  313. if ( input_file != stdin ) {
  314. fclose( input_file );
  315. }
  316. if ( output_file != stdout ) {
  317. fclose( output_file );
  318. }
  319. #ifdef PROGRESS_REPORT
  320. end_progress_monitor( ( j_common_ptr ) & dstinfo );
  321. #endif
  322. /* All done. */
  323. exit( jsrcerr.num_warnings + jdsterr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS );
  324. return 0; /* suppress no-return-value warnings */
  325. }