cjpeg.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*
  2. * cjpeg.c
  3. *
  4. * This file was part of the Independent JPEG Group's software:
  5. * Copyright (C) 1991-1998, Thomas G. Lane.
  6. * Modified 2003-2011 by Guido Vollbeding.
  7. * libjpeg-turbo Modifications:
  8. * Copyright (C) 2010, 2013-2014, 2017, D. R. Commander.
  9. * For conditions of distribution and use, see the accompanying README.ijg
  10. * file.
  11. *
  12. * This file contains a command-line user interface for the JPEG compressor.
  13. * It should work on any system with Unix- or MS-DOS-style command lines.
  14. *
  15. * Two different command line styles are permitted, depending on the
  16. * compile-time switch TWO_FILE_COMMANDLINE:
  17. * cjpeg [options] inputfile outputfile
  18. * cjpeg [options] [inputfile]
  19. * In the second style, output is always to standard output, which you'd
  20. * normally redirect to a file or pipe to some other program. Input is
  21. * either from a named file or from standard input (typically redirected).
  22. * The second style is convenient on Unix but is unhelpful on systems that
  23. * don't support pipes. Also, you MUST use the first style if your system
  24. * doesn't do binary I/O to stdin/stdout.
  25. * To simplify script writing, the "-outfile" switch is provided. The syntax
  26. * cjpeg [options] -outfile outputfile inputfile
  27. * works regardless of which command line style is used.
  28. */
  29. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  30. #include "jversion.h" /* for version message */
  31. #include "jconfigint.h"
  32. #ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
  33. extern void *malloc(size_t size);
  34. extern void free(void *ptr);
  35. #endif
  36. #ifdef USE_CCOMMAND /* command-line reader for Macintosh */
  37. #ifdef __MWERKS__
  38. #include <SIOUX.h> /* Metrowerks needs this */
  39. #include <console.h> /* ... and this */
  40. #endif
  41. #ifdef THINK_C
  42. #include <console.h> /* Think declares it here */
  43. #endif
  44. #endif
  45. /* Create the add-on message string table. */
  46. #define JMESSAGE(code, string) string,
  47. static const char * const cdjpeg_message_table[] = {
  48. #include "cderror.h"
  49. NULL
  50. };
  51. /*
  52. * This routine determines what format the input file is,
  53. * and selects the appropriate input-reading module.
  54. *
  55. * To determine which family of input formats the file belongs to,
  56. * we may look only at the first byte of the file, since C does not
  57. * guarantee that more than one character can be pushed back with ungetc.
  58. * Looking at additional bytes would require one of these approaches:
  59. * 1) assume we can fseek() the input file (fails for piped input);
  60. * 2) assume we can push back more than one character (works in
  61. * some C implementations, but unportable);
  62. * 3) provide our own buffering (breaks input readers that want to use
  63. * stdio directly, such as the RLE library);
  64. * or 4) don't put back the data, and modify the input_init methods to assume
  65. * they start reading after the start of file (also breaks RLE library).
  66. * #1 is attractive for MS-DOS but is untenable on Unix.
  67. *
  68. * The most portable solution for file types that can't be identified by their
  69. * first byte is to make the user tell us what they are. This is also the
  70. * only approach for "raw" file types that contain only arbitrary values.
  71. * We presently apply this method for Targa files. Most of the time Targa
  72. * files start with 0x00, so we recognize that case. Potentially, however,
  73. * a Targa file could start with any byte value (byte 0 is the length of the
  74. * seldom-used ID field), so we provide a switch to force Targa input mode.
  75. */
  76. static boolean is_targa; /* records user -targa switch */
  77. LOCAL(cjpeg_source_ptr)
  78. select_file_type(j_compress_ptr cinfo, FILE *infile)
  79. {
  80. int c;
  81. if (is_targa) {
  82. #ifdef TARGA_SUPPORTED
  83. return jinit_read_targa(cinfo);
  84. #else
  85. ERREXIT(cinfo, JERR_TGA_NOTCOMP);
  86. #endif
  87. }
  88. if ((c = getc(infile)) == EOF)
  89. ERREXIT(cinfo, JERR_INPUT_EMPTY);
  90. if (ungetc(c, infile) == EOF)
  91. ERREXIT(cinfo, JERR_UNGETC_FAILED);
  92. switch (c) {
  93. #ifdef BMP_SUPPORTED
  94. case 'B':
  95. return jinit_read_bmp(cinfo, TRUE);
  96. #endif
  97. #ifdef GIF_SUPPORTED
  98. case 'G':
  99. return jinit_read_gif(cinfo);
  100. #endif
  101. #ifdef PPM_SUPPORTED
  102. case 'P':
  103. return jinit_read_ppm(cinfo);
  104. #endif
  105. #ifdef RLE_SUPPORTED
  106. case 'R':
  107. return jinit_read_rle(cinfo);
  108. #endif
  109. #ifdef TARGA_SUPPORTED
  110. case 0x00:
  111. return jinit_read_targa(cinfo);
  112. #endif
  113. default:
  114. ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
  115. break;
  116. }
  117. return NULL; /* suppress compiler warnings */
  118. }
  119. /*
  120. * Argument-parsing code.
  121. * The switch parser is designed to be useful with DOS-style command line
  122. * syntax, ie, intermixed switches and file names, where only the switches
  123. * to the left of a given file name affect processing of that file.
  124. * The main program in this file doesn't actually use this capability...
  125. */
  126. static const char *progname; /* program name for error messages */
  127. static char *icc_filename; /* for -icc switch */
  128. static char *outfilename; /* for -outfile switch */
  129. boolean memdst; /* for -memdst switch */
  130. LOCAL(void)
  131. usage(void)
  132. /* complain about bad command line */
  133. {
  134. fprintf(stderr, "usage: %s [switches] ", progname);
  135. #ifdef TWO_FILE_COMMANDLINE
  136. fprintf(stderr, "inputfile outputfile\n");
  137. #else
  138. fprintf(stderr, "[inputfile]\n");
  139. #endif
  140. fprintf(stderr, "Switches (names may be abbreviated):\n");
  141. fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is most useful range,\n");
  142. fprintf(stderr, " default is 75)\n");
  143. fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
  144. fprintf(stderr, " -rgb Create RGB JPEG file\n");
  145. #ifdef ENTROPY_OPT_SUPPORTED
  146. fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
  147. #endif
  148. #ifdef C_PROGRESSIVE_SUPPORTED
  149. fprintf(stderr, " -progressive Create progressive JPEG file\n");
  150. #endif
  151. #ifdef TARGA_SUPPORTED
  152. fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
  153. #endif
  154. fprintf(stderr, "Switches for advanced users:\n");
  155. #ifdef C_ARITH_CODING_SUPPORTED
  156. fprintf(stderr, " -arithmetic Use arithmetic coding\n");
  157. #endif
  158. #ifdef DCT_ISLOW_SUPPORTED
  159. fprintf(stderr, " -dct int Use integer DCT method%s\n",
  160. (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  161. #endif
  162. #ifdef DCT_IFAST_SUPPORTED
  163. fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
  164. (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  165. #endif
  166. #ifdef DCT_FLOAT_SUPPORTED
  167. fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
  168. (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  169. #endif
  170. fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n");
  171. fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
  172. #ifdef INPUT_SMOOTHING_SUPPORTED
  173. fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
  174. #endif
  175. fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
  176. fprintf(stderr, " -outfile name Specify name for output file\n");
  177. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  178. fprintf(stderr, " -memdst Compress to memory instead of file (useful for benchmarking)\n");
  179. #endif
  180. fprintf(stderr, " -verbose or -debug Emit debug output\n");
  181. fprintf(stderr, " -version Print version information and exit\n");
  182. fprintf(stderr, "Switches for wizards:\n");
  183. fprintf(stderr, " -baseline Force baseline quantization tables\n");
  184. fprintf(stderr, " -qtables FILE Use quantization tables given in FILE\n");
  185. fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
  186. fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
  187. #ifdef C_MULTISCAN_FILES_SUPPORTED
  188. fprintf(stderr, " -scans FILE Create multi-scan JPEG per script FILE\n");
  189. #endif
  190. exit(EXIT_FAILURE);
  191. }
  192. LOCAL(int)
  193. parse_switches(j_compress_ptr cinfo, int argc, char **argv,
  194. int last_file_arg_seen, boolean for_real)
  195. /* Parse optional switches.
  196. * Returns argv[] index of first file-name argument (== argc if none).
  197. * Any file names with indexes <= last_file_arg_seen are ignored;
  198. * they have presumably been processed in a previous iteration.
  199. * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  200. * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  201. * processing.
  202. */
  203. {
  204. int argn;
  205. char *arg;
  206. boolean force_baseline;
  207. boolean simple_progressive;
  208. char *qualityarg = NULL; /* saves -quality parm if any */
  209. char *qtablefile = NULL; /* saves -qtables filename if any */
  210. char *qslotsarg = NULL; /* saves -qslots parm if any */
  211. char *samplearg = NULL; /* saves -sample parm if any */
  212. char *scansarg = NULL; /* saves -scans parm if any */
  213. /* Set up default JPEG parameters. */
  214. force_baseline = FALSE; /* by default, allow 16-bit quantizers */
  215. simple_progressive = FALSE;
  216. is_targa = FALSE;
  217. icc_filename = NULL;
  218. outfilename = NULL;
  219. memdst = FALSE;
  220. cinfo->err->trace_level = 0;
  221. /* Scan command line options, adjust parameters */
  222. for (argn = 1; argn < argc; argn++) {
  223. arg = argv[argn];
  224. if (*arg != '-') {
  225. /* Not a switch, must be a file name argument */
  226. if (argn <= last_file_arg_seen) {
  227. outfilename = NULL; /* -outfile applies to just one input file */
  228. continue; /* ignore this name if previously processed */
  229. }
  230. break; /* else done parsing switches */
  231. }
  232. arg++; /* advance past switch marker character */
  233. if (keymatch(arg, "arithmetic", 1)) {
  234. /* Use arithmetic coding. */
  235. #ifdef C_ARITH_CODING_SUPPORTED
  236. cinfo->arith_code = TRUE;
  237. #else
  238. fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  239. progname);
  240. exit(EXIT_FAILURE);
  241. #endif
  242. } else if (keymatch(arg, "baseline", 1)) {
  243. /* Force baseline-compatible output (8-bit quantizer values). */
  244. force_baseline = TRUE;
  245. } else if (keymatch(arg, "dct", 2)) {
  246. /* Select DCT algorithm. */
  247. if (++argn >= argc) /* advance to next argument */
  248. usage();
  249. if (keymatch(argv[argn], "int", 1)) {
  250. cinfo->dct_method = JDCT_ISLOW;
  251. } else if (keymatch(argv[argn], "fast", 2)) {
  252. cinfo->dct_method = JDCT_IFAST;
  253. } else if (keymatch(argv[argn], "float", 2)) {
  254. cinfo->dct_method = JDCT_FLOAT;
  255. } else
  256. usage();
  257. } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  258. /* Enable debug printouts. */
  259. /* On first -d, print version identification */
  260. static boolean printed_version = FALSE;
  261. if (!printed_version) {
  262. fprintf(stderr, "%s version %s (build %s)\n",
  263. PACKAGE_NAME, VERSION, BUILD);
  264. fprintf(stderr, "%s\n\n", JCOPYRIGHT);
  265. fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
  266. JVERSION);
  267. printed_version = TRUE;
  268. }
  269. cinfo->err->trace_level++;
  270. } else if (keymatch(arg, "version", 4)) {
  271. fprintf(stderr, "%s version %s (build %s)\n",
  272. PACKAGE_NAME, VERSION, BUILD);
  273. exit(EXIT_SUCCESS);
  274. } else if (keymatch(arg, "grayscale", 2) ||
  275. keymatch(arg, "greyscale", 2)) {
  276. /* Force a monochrome JPEG file to be generated. */
  277. jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
  278. } else if (keymatch(arg, "rgb", 3)) {
  279. /* Force an RGB JPEG file to be generated. */
  280. jpeg_set_colorspace(cinfo, JCS_RGB);
  281. } else if (keymatch(arg, "icc", 1)) {
  282. /* Set ICC filename. */
  283. if (++argn >= argc) /* advance to next argument */
  284. usage();
  285. icc_filename = argv[argn];
  286. } else if (keymatch(arg, "maxmemory", 3)) {
  287. /* Maximum memory in Kb (or Mb with 'm'). */
  288. long lval;
  289. char ch = 'x';
  290. if (++argn >= argc) /* advance to next argument */
  291. usage();
  292. if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  293. usage();
  294. if (ch == 'm' || ch == 'M')
  295. lval *= 1000L;
  296. cinfo->mem->max_memory_to_use = lval * 1000L;
  297. } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  298. /* Enable entropy parm optimization. */
  299. #ifdef ENTROPY_OPT_SUPPORTED
  300. cinfo->optimize_coding = TRUE;
  301. #else
  302. fprintf(stderr, "%s: sorry, entropy optimization was not compiled in\n",
  303. progname);
  304. exit(EXIT_FAILURE);
  305. #endif
  306. } else if (keymatch(arg, "outfile", 4)) {
  307. /* Set output file name. */
  308. if (++argn >= argc) /* advance to next argument */
  309. usage();
  310. outfilename = argv[argn]; /* save it away for later use */
  311. } else if (keymatch(arg, "progressive", 1)) {
  312. /* Select simple progressive mode. */
  313. #ifdef C_PROGRESSIVE_SUPPORTED
  314. simple_progressive = TRUE;
  315. /* We must postpone execution until num_components is known. */
  316. #else
  317. fprintf(stderr, "%s: sorry, progressive output was not compiled in\n",
  318. progname);
  319. exit(EXIT_FAILURE);
  320. #endif
  321. } else if (keymatch(arg, "memdst", 2)) {
  322. /* Use in-memory destination manager */
  323. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  324. memdst = TRUE;
  325. #else
  326. fprintf(stderr, "%s: sorry, in-memory destination manager was not compiled in\n",
  327. progname);
  328. exit(EXIT_FAILURE);
  329. #endif
  330. } else if (keymatch(arg, "quality", 1)) {
  331. /* Quality ratings (quantization table scaling factors). */
  332. if (++argn >= argc) /* advance to next argument */
  333. usage();
  334. qualityarg = argv[argn];
  335. } else if (keymatch(arg, "qslots", 2)) {
  336. /* Quantization table slot numbers. */
  337. if (++argn >= argc) /* advance to next argument */
  338. usage();
  339. qslotsarg = argv[argn];
  340. /* Must delay setting qslots until after we have processed any
  341. * colorspace-determining switches, since jpeg_set_colorspace sets
  342. * default quant table numbers.
  343. */
  344. } else if (keymatch(arg, "qtables", 2)) {
  345. /* Quantization tables fetched from file. */
  346. if (++argn >= argc) /* advance to next argument */
  347. usage();
  348. qtablefile = argv[argn];
  349. /* We postpone actually reading the file in case -quality comes later. */
  350. } else if (keymatch(arg, "restart", 1)) {
  351. /* Restart interval in MCU rows (or in MCUs with 'b'). */
  352. long lval;
  353. char ch = 'x';
  354. if (++argn >= argc) /* advance to next argument */
  355. usage();
  356. if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  357. usage();
  358. if (lval < 0 || lval > 65535L)
  359. usage();
  360. if (ch == 'b' || ch == 'B') {
  361. cinfo->restart_interval = (unsigned int)lval;
  362. cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
  363. } else {
  364. cinfo->restart_in_rows = (int)lval;
  365. /* restart_interval will be computed during startup */
  366. }
  367. } else if (keymatch(arg, "sample", 2)) {
  368. /* Set sampling factors. */
  369. if (++argn >= argc) /* advance to next argument */
  370. usage();
  371. samplearg = argv[argn];
  372. /* Must delay setting sample factors until after we have processed any
  373. * colorspace-determining switches, since jpeg_set_colorspace sets
  374. * default sampling factors.
  375. */
  376. } else if (keymatch(arg, "scans", 4)) {
  377. /* Set scan script. */
  378. #ifdef C_MULTISCAN_FILES_SUPPORTED
  379. if (++argn >= argc) /* advance to next argument */
  380. usage();
  381. scansarg = argv[argn];
  382. /* We must postpone reading the file in case -progressive appears. */
  383. #else
  384. fprintf(stderr, "%s: sorry, multi-scan output was not compiled in\n",
  385. progname);
  386. exit(EXIT_FAILURE);
  387. #endif
  388. } else if (keymatch(arg, "smooth", 2)) {
  389. /* Set input smoothing factor. */
  390. int val;
  391. if (++argn >= argc) /* advance to next argument */
  392. usage();
  393. if (sscanf(argv[argn], "%d", &val) != 1)
  394. usage();
  395. if (val < 0 || val > 100)
  396. usage();
  397. cinfo->smoothing_factor = val;
  398. } else if (keymatch(arg, "targa", 1)) {
  399. /* Input file is Targa format. */
  400. is_targa = TRUE;
  401. } else {
  402. usage(); /* bogus switch */
  403. }
  404. }
  405. /* Post-switch-scanning cleanup */
  406. if (for_real) {
  407. /* Set quantization tables for selected quality. */
  408. /* Some or all may be overridden if -qtables is present. */
  409. if (qualityarg != NULL) /* process -quality if it was present */
  410. if (!set_quality_ratings(cinfo, qualityarg, force_baseline))
  411. usage();
  412. if (qtablefile != NULL) /* process -qtables if it was present */
  413. if (!read_quant_tables(cinfo, qtablefile, force_baseline))
  414. usage();
  415. if (qslotsarg != NULL) /* process -qslots if it was present */
  416. if (!set_quant_slots(cinfo, qslotsarg))
  417. usage();
  418. if (samplearg != NULL) /* process -sample if it was present */
  419. if (!set_sample_factors(cinfo, samplearg))
  420. usage();
  421. #ifdef C_PROGRESSIVE_SUPPORTED
  422. if (simple_progressive) /* process -progressive; -scans can override */
  423. jpeg_simple_progression(cinfo);
  424. #endif
  425. #ifdef C_MULTISCAN_FILES_SUPPORTED
  426. if (scansarg != NULL) /* process -scans if it was present */
  427. if (!read_scan_script(cinfo, scansarg))
  428. usage();
  429. #endif
  430. }
  431. return argn; /* return index of next arg (file name) */
  432. }
  433. /*
  434. * The main program.
  435. */
  436. int
  437. main(int argc, char **argv)
  438. {
  439. struct jpeg_compress_struct cinfo;
  440. struct jpeg_error_mgr jerr;
  441. #ifdef PROGRESS_REPORT
  442. struct cdjpeg_progress_mgr progress;
  443. #endif
  444. int file_index;
  445. cjpeg_source_ptr src_mgr;
  446. FILE *input_file;
  447. FILE *icc_file;
  448. JOCTET *icc_profile = NULL;
  449. long icc_len = 0;
  450. FILE *output_file = NULL;
  451. unsigned char *outbuffer = NULL;
  452. unsigned long outsize = 0;
  453. JDIMENSION num_scanlines;
  454. /* On Mac, fetch a command line. */
  455. #ifdef USE_CCOMMAND
  456. argc = ccommand(&argv);
  457. #endif
  458. progname = argv[0];
  459. if (progname == NULL || progname[0] == 0)
  460. progname = "cjpeg"; /* in case C library doesn't provide it */
  461. /* Initialize the JPEG compression object with default error handling. */
  462. cinfo.err = jpeg_std_error(&jerr);
  463. jpeg_create_compress(&cinfo);
  464. /* Add some application-specific error messages (from cderror.h) */
  465. jerr.addon_message_table = cdjpeg_message_table;
  466. jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  467. jerr.last_addon_message = JMSG_LASTADDONCODE;
  468. /* Initialize JPEG parameters.
  469. * Much of this may be overridden later.
  470. * In particular, we don't yet know the input file's color space,
  471. * but we need to provide some value for jpeg_set_defaults() to work.
  472. */
  473. cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
  474. jpeg_set_defaults(&cinfo);
  475. /* Scan command line to find file names.
  476. * It is convenient to use just one switch-parsing routine, but the switch
  477. * values read here are ignored; we will rescan the switches after opening
  478. * the input file.
  479. */
  480. file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  481. #ifdef TWO_FILE_COMMANDLINE
  482. if (!memdst) {
  483. /* Must have either -outfile switch or explicit output file name */
  484. if (outfilename == NULL) {
  485. if (file_index != argc - 2) {
  486. fprintf(stderr, "%s: must name one input and one output file\n",
  487. progname);
  488. usage();
  489. }
  490. outfilename = argv[file_index + 1];
  491. } else {
  492. if (file_index != argc - 1) {
  493. fprintf(stderr, "%s: must name one input and one output file\n",
  494. progname);
  495. usage();
  496. }
  497. }
  498. }
  499. #else
  500. /* Unix style: expect zero or one file name */
  501. if (file_index < argc - 1) {
  502. fprintf(stderr, "%s: only one input file\n", progname);
  503. usage();
  504. }
  505. #endif /* TWO_FILE_COMMANDLINE */
  506. /* Open the input file. */
  507. if (file_index < argc) {
  508. if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  509. fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  510. exit(EXIT_FAILURE);
  511. }
  512. } else {
  513. /* default input file is stdin */
  514. input_file = read_stdin();
  515. }
  516. /* Open the output file. */
  517. if (outfilename != NULL) {
  518. if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  519. fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  520. exit(EXIT_FAILURE);
  521. }
  522. } else if (!memdst) {
  523. /* default output file is stdout */
  524. output_file = write_stdout();
  525. }
  526. if (icc_filename != NULL) {
  527. if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) {
  528. fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
  529. exit(EXIT_FAILURE);
  530. }
  531. if (fseek(icc_file, 0, SEEK_END) < 0 ||
  532. (icc_len = ftell(icc_file)) < 1 ||
  533. fseek(icc_file, 0, SEEK_SET) < 0) {
  534. fprintf(stderr, "%s: can't determine size of %s\n", progname,
  535. icc_filename);
  536. exit(EXIT_FAILURE);
  537. }
  538. if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) {
  539. fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname);
  540. fclose(icc_file);
  541. exit(EXIT_FAILURE);
  542. }
  543. if (fread(icc_profile, icc_len, 1, icc_file) < 1) {
  544. fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
  545. icc_filename);
  546. free(icc_profile);
  547. fclose(icc_file);
  548. exit(EXIT_FAILURE);
  549. }
  550. fclose(icc_file);
  551. }
  552. #ifdef PROGRESS_REPORT
  553. start_progress_monitor((j_common_ptr)&cinfo, &progress);
  554. #endif
  555. /* Figure out the input file format, and set up to read it. */
  556. src_mgr = select_file_type(&cinfo, input_file);
  557. src_mgr->input_file = input_file;
  558. /* Read the input file header to obtain file size & colorspace. */
  559. (*src_mgr->start_input) (&cinfo, src_mgr);
  560. /* Now that we know input colorspace, fix colorspace-dependent defaults */
  561. jpeg_default_colorspace(&cinfo);
  562. /* Adjust default compression parameters by re-parsing the options */
  563. file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  564. /* Specify data destination for compression */
  565. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  566. if (memdst)
  567. jpeg_mem_dest(&cinfo, &outbuffer, &outsize);
  568. else
  569. #endif
  570. jpeg_stdio_dest(&cinfo, output_file);
  571. /* Start compressor */
  572. jpeg_start_compress(&cinfo, TRUE);
  573. if (icc_profile != NULL)
  574. jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len);
  575. /* Process data */
  576. while (cinfo.next_scanline < cinfo.image_height) {
  577. num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
  578. (void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
  579. }
  580. /* Finish compression and release memory */
  581. (*src_mgr->finish_input) (&cinfo, src_mgr);
  582. jpeg_finish_compress(&cinfo);
  583. jpeg_destroy_compress(&cinfo);
  584. /* Close files, if we opened them */
  585. if (input_file != stdin)
  586. fclose(input_file);
  587. if (output_file != stdout && output_file != NULL)
  588. fclose(output_file);
  589. #ifdef PROGRESS_REPORT
  590. end_progress_monitor((j_common_ptr)&cinfo);
  591. #endif
  592. if (memdst) {
  593. fprintf(stderr, "Compressed size: %lu bytes\n", outsize);
  594. free(outbuffer);
  595. }
  596. free(icc_profile);
  597. /* All done. */
  598. exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  599. return 0; /* suppress no-return-value warnings */
  600. }