djpeg.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /*
  2. * djpeg.c
  3. *
  4. * This file was part of the Independent JPEG Group's software:
  5. * Copyright (C) 1991-1997, Thomas G. Lane.
  6. * Modified 2013-2019 by Guido Vollbeding.
  7. * libjpeg-turbo Modifications:
  8. * Copyright (C) 2010-2011, 2013-2017, 2019-2020, 2022, D. R. Commander.
  9. * Copyright (C) 2015, Google, Inc.
  10. * For conditions of distribution and use, see the accompanying README.ijg
  11. * file.
  12. *
  13. * This file contains a command-line user interface for the JPEG decompressor.
  14. * It should work on any system with Unix- or MS-DOS-style command lines.
  15. *
  16. * Two different command line styles are permitted, depending on the
  17. * compile-time switch TWO_FILE_COMMANDLINE:
  18. * djpeg [options] inputfile outputfile
  19. * djpeg [options] [inputfile]
  20. * In the second style, output is always to standard output, which you'd
  21. * normally redirect to a file or pipe to some other program. Input is
  22. * either from a named file or from standard input (typically redirected).
  23. * The second style is convenient on Unix but is unhelpful on systems that
  24. * don't support pipes. Also, you MUST use the first style if your system
  25. * doesn't do binary I/O to stdin/stdout.
  26. * To simplify script writing, the "-outfile" switch is provided. The syntax
  27. * djpeg [options] -outfile outputfile inputfile
  28. * works regardless of which command line style is used.
  29. */
  30. #ifdef _MSC_VER
  31. #define _CRT_SECURE_NO_DEPRECATE
  32. #endif
  33. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  34. #include "jversion.h" /* for version message */
  35. #include "jconfigint.h"
  36. #include <ctype.h> /* to declare isprint() */
  37. /* Create the add-on message string table. */
  38. #define JMESSAGE(code, string) string,
  39. static const char * const cdjpeg_message_table[] = {
  40. #include "cderror.h"
  41. NULL
  42. };
  43. /*
  44. * This list defines the known output image formats
  45. * (not all of which need be supported by a given version).
  46. * You can change the default output format by defining DEFAULT_FMT;
  47. * indeed, you had better do so if you undefine PPM_SUPPORTED.
  48. */
  49. typedef enum {
  50. FMT_BMP, /* BMP format (Windows flavor) */
  51. FMT_GIF, /* GIF format (LZW-compressed) */
  52. FMT_GIF0, /* GIF format (uncompressed) */
  53. FMT_OS2, /* BMP format (OS/2 flavor) */
  54. FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
  55. FMT_TARGA, /* Targa format */
  56. FMT_TIFF /* TIFF format */
  57. } IMAGE_FORMATS;
  58. #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
  59. #define DEFAULT_FMT FMT_PPM
  60. #endif
  61. static IMAGE_FORMATS requested_fmt;
  62. /*
  63. * Argument-parsing code.
  64. * The switch parser is designed to be useful with DOS-style command line
  65. * syntax, ie, intermixed switches and file names, where only the switches
  66. * to the left of a given file name affect processing of that file.
  67. * The main program in this file doesn't actually use this capability...
  68. */
  69. static const char *progname; /* program name for error messages */
  70. static char *icc_filename; /* for -icc switch */
  71. JDIMENSION max_scans; /* for -maxscans switch */
  72. static char *outfilename; /* for -outfile switch */
  73. boolean memsrc; /* for -memsrc switch */
  74. boolean report; /* for -report switch */
  75. boolean skip, crop;
  76. JDIMENSION skip_start, skip_end;
  77. JDIMENSION crop_x, crop_y, crop_width, crop_height;
  78. boolean strict; /* for -strict switch */
  79. #define INPUT_BUF_SIZE 4096
  80. LOCAL(void)
  81. usage(void)
  82. /* complain about bad command line */
  83. {
  84. fprintf(stderr, "usage: %s [switches] ", progname);
  85. #ifdef TWO_FILE_COMMANDLINE
  86. fprintf(stderr, "inputfile outputfile\n");
  87. #else
  88. fprintf(stderr, "[inputfile]\n");
  89. #endif
  90. fprintf(stderr, "Switches (names may be abbreviated):\n");
  91. fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
  92. fprintf(stderr, " -fast Fast, low-quality processing\n");
  93. fprintf(stderr, " -grayscale Force grayscale output\n");
  94. fprintf(stderr, " -rgb Force RGB output\n");
  95. fprintf(stderr, " -rgb565 Force RGB565 output\n");
  96. #ifdef IDCT_SCALING_SUPPORTED
  97. fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
  98. #endif
  99. #ifdef BMP_SUPPORTED
  100. fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
  101. (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
  102. #endif
  103. #ifdef GIF_SUPPORTED
  104. fprintf(stderr, " -gif Select GIF output format (LZW-compressed)%s\n",
  105. (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
  106. fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n",
  107. (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
  108. #endif
  109. #ifdef BMP_SUPPORTED
  110. fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
  111. (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
  112. #endif
  113. #ifdef PPM_SUPPORTED
  114. fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
  115. (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
  116. #endif
  117. #ifdef TARGA_SUPPORTED
  118. fprintf(stderr, " -targa Select Targa output format%s\n",
  119. (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
  120. #endif
  121. fprintf(stderr, "Switches for advanced users:\n");
  122. #ifdef DCT_ISLOW_SUPPORTED
  123. fprintf(stderr, " -dct int Use accurate integer DCT method%s\n",
  124. (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  125. #endif
  126. #ifdef DCT_IFAST_SUPPORTED
  127. fprintf(stderr, " -dct fast Use less accurate integer DCT method [legacy feature]%s\n",
  128. (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  129. #endif
  130. #ifdef DCT_FLOAT_SUPPORTED
  131. fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n",
  132. (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  133. #endif
  134. fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
  135. fprintf(stderr, " -dither none Don't use dithering in quantization\n");
  136. fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
  137. fprintf(stderr, " -icc FILE Extract ICC profile to FILE\n");
  138. #ifdef QUANT_2PASS_SUPPORTED
  139. fprintf(stderr, " -map FILE Map to colors used in named image file\n");
  140. #endif
  141. fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
  142. #ifdef QUANT_1PASS_SUPPORTED
  143. fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
  144. #endif
  145. fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
  146. fprintf(stderr, " -maxscans N Maximum number of scans to allow in input file\n");
  147. fprintf(stderr, " -outfile name Specify name for output file\n");
  148. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  149. fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
  150. #endif
  151. fprintf(stderr, " -report Report decompression progress\n");
  152. fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n");
  153. fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n");
  154. fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n");
  155. fprintf(stderr, " -strict Treat all warnings as fatal\n");
  156. fprintf(stderr, " -verbose or -debug Emit debug output\n");
  157. fprintf(stderr, " -version Print version information and exit\n");
  158. exit(EXIT_FAILURE);
  159. }
  160. LOCAL(int)
  161. parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
  162. int last_file_arg_seen, boolean for_real)
  163. /* Parse optional switches.
  164. * Returns argv[] index of first file-name argument (== argc if none).
  165. * Any file names with indexes <= last_file_arg_seen are ignored;
  166. * they have presumably been processed in a previous iteration.
  167. * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  168. * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  169. * processing.
  170. */
  171. {
  172. int argn;
  173. char *arg;
  174. /* Set up default JPEG parameters. */
  175. requested_fmt = DEFAULT_FMT; /* set default output file format */
  176. icc_filename = NULL;
  177. max_scans = 0;
  178. outfilename = NULL;
  179. memsrc = FALSE;
  180. report = FALSE;
  181. skip = FALSE;
  182. crop = FALSE;
  183. strict = FALSE;
  184. cinfo->err->trace_level = 0;
  185. /* Scan command line options, adjust parameters */
  186. for (argn = 1; argn < argc; argn++) {
  187. arg = argv[argn];
  188. if (*arg != '-') {
  189. /* Not a switch, must be a file name argument */
  190. if (argn <= last_file_arg_seen) {
  191. outfilename = NULL; /* -outfile applies to just one input file */
  192. continue; /* ignore this name if previously processed */
  193. }
  194. break; /* else done parsing switches */
  195. }
  196. arg++; /* advance past switch marker character */
  197. if (keymatch(arg, "bmp", 1)) {
  198. /* BMP output format (Windows flavor). */
  199. requested_fmt = FMT_BMP;
  200. } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
  201. keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
  202. /* Do color quantization. */
  203. int val;
  204. if (++argn >= argc) /* advance to next argument */
  205. usage();
  206. if (sscanf(argv[argn], "%d", &val) != 1)
  207. usage();
  208. cinfo->desired_number_of_colors = val;
  209. cinfo->quantize_colors = TRUE;
  210. } else if (keymatch(arg, "dct", 2)) {
  211. /* Select IDCT algorithm. */
  212. if (++argn >= argc) /* advance to next argument */
  213. usage();
  214. if (keymatch(argv[argn], "int", 1)) {
  215. cinfo->dct_method = JDCT_ISLOW;
  216. } else if (keymatch(argv[argn], "fast", 2)) {
  217. cinfo->dct_method = JDCT_IFAST;
  218. } else if (keymatch(argv[argn], "float", 2)) {
  219. cinfo->dct_method = JDCT_FLOAT;
  220. } else
  221. usage();
  222. } else if (keymatch(arg, "dither", 2)) {
  223. /* Select dithering algorithm. */
  224. if (++argn >= argc) /* advance to next argument */
  225. usage();
  226. if (keymatch(argv[argn], "fs", 2)) {
  227. cinfo->dither_mode = JDITHER_FS;
  228. } else if (keymatch(argv[argn], "none", 2)) {
  229. cinfo->dither_mode = JDITHER_NONE;
  230. } else if (keymatch(argv[argn], "ordered", 2)) {
  231. cinfo->dither_mode = JDITHER_ORDERED;
  232. } else
  233. usage();
  234. } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  235. /* Enable debug printouts. */
  236. /* On first -d, print version identification */
  237. static boolean printed_version = FALSE;
  238. if (!printed_version) {
  239. fprintf(stderr, "%s version %s (build %s)\n",
  240. PACKAGE_NAME, VERSION, BUILD);
  241. fprintf(stderr, "%s\n\n", JCOPYRIGHT);
  242. fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
  243. JVERSION);
  244. printed_version = TRUE;
  245. }
  246. cinfo->err->trace_level++;
  247. } else if (keymatch(arg, "version", 4)) {
  248. fprintf(stderr, "%s version %s (build %s)\n",
  249. PACKAGE_NAME, VERSION, BUILD);
  250. exit(EXIT_SUCCESS);
  251. } else if (keymatch(arg, "fast", 1)) {
  252. /* Select recommended processing options for quick-and-dirty output. */
  253. cinfo->two_pass_quantize = FALSE;
  254. cinfo->dither_mode = JDITHER_ORDERED;
  255. if (!cinfo->quantize_colors) /* don't override an earlier -colors */
  256. cinfo->desired_number_of_colors = 216;
  257. cinfo->dct_method = JDCT_FASTEST;
  258. cinfo->do_fancy_upsampling = FALSE;
  259. } else if (keymatch(arg, "gif", 1)) {
  260. /* GIF output format (LZW-compressed). */
  261. requested_fmt = FMT_GIF;
  262. } else if (keymatch(arg, "gif0", 4)) {
  263. /* GIF output format (uncompressed). */
  264. requested_fmt = FMT_GIF0;
  265. } else if (keymatch(arg, "grayscale", 2) ||
  266. keymatch(arg, "greyscale", 2)) {
  267. /* Force monochrome output. */
  268. cinfo->out_color_space = JCS_GRAYSCALE;
  269. } else if (keymatch(arg, "rgb", 2)) {
  270. /* Force RGB output. */
  271. cinfo->out_color_space = JCS_RGB;
  272. } else if (keymatch(arg, "rgb565", 2)) {
  273. /* Force RGB565 output. */
  274. cinfo->out_color_space = JCS_RGB565;
  275. } else if (keymatch(arg, "icc", 1)) {
  276. /* Set ICC filename. */
  277. if (++argn >= argc) /* advance to next argument */
  278. usage();
  279. icc_filename = argv[argn];
  280. jpeg_save_markers(cinfo, JPEG_APP0 + 2, 0xFFFF);
  281. } else if (keymatch(arg, "map", 3)) {
  282. /* Quantize to a color map taken from an input file. */
  283. if (++argn >= argc) /* advance to next argument */
  284. usage();
  285. if (for_real) { /* too expensive to do twice! */
  286. #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
  287. FILE *mapfile;
  288. if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
  289. fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
  290. exit(EXIT_FAILURE);
  291. }
  292. read_color_map(cinfo, mapfile);
  293. fclose(mapfile);
  294. cinfo->quantize_colors = TRUE;
  295. #else
  296. ERREXIT(cinfo, JERR_NOT_COMPILED);
  297. #endif
  298. }
  299. } else if (keymatch(arg, "maxmemory", 3)) {
  300. /* Maximum memory in Kb (or Mb with 'm'). */
  301. long lval;
  302. char ch = 'x';
  303. if (++argn >= argc) /* advance to next argument */
  304. usage();
  305. if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  306. usage();
  307. if (ch == 'm' || ch == 'M')
  308. lval *= 1000L;
  309. cinfo->mem->max_memory_to_use = lval * 1000L;
  310. } else if (keymatch(arg, "maxscans", 4)) {
  311. if (++argn >= argc) /* advance to next argument */
  312. usage();
  313. if (sscanf(argv[argn], "%u", &max_scans) != 1)
  314. usage();
  315. } else if (keymatch(arg, "nosmooth", 3)) {
  316. /* Suppress fancy upsampling */
  317. cinfo->do_fancy_upsampling = FALSE;
  318. } else if (keymatch(arg, "onepass", 3)) {
  319. /* Use fast one-pass quantization. */
  320. cinfo->two_pass_quantize = FALSE;
  321. } else if (keymatch(arg, "os2", 3)) {
  322. /* BMP output format (OS/2 flavor). */
  323. requested_fmt = FMT_OS2;
  324. } else if (keymatch(arg, "outfile", 4)) {
  325. /* Set output file name. */
  326. if (++argn >= argc) /* advance to next argument */
  327. usage();
  328. outfilename = argv[argn]; /* save it away for later use */
  329. } else if (keymatch(arg, "memsrc", 2)) {
  330. /* Use in-memory source manager */
  331. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  332. memsrc = TRUE;
  333. #else
  334. fprintf(stderr, "%s: sorry, in-memory source manager was not compiled in\n",
  335. progname);
  336. exit(EXIT_FAILURE);
  337. #endif
  338. } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
  339. /* PPM/PGM output format. */
  340. requested_fmt = FMT_PPM;
  341. } else if (keymatch(arg, "report", 2)) {
  342. report = TRUE;
  343. } else if (keymatch(arg, "scale", 2)) {
  344. /* Scale the output image by a fraction M/N. */
  345. if (++argn >= argc) /* advance to next argument */
  346. usage();
  347. if (sscanf(argv[argn], "%u/%u",
  348. &cinfo->scale_num, &cinfo->scale_denom) != 2)
  349. usage();
  350. } else if (keymatch(arg, "skip", 2)) {
  351. if (++argn >= argc)
  352. usage();
  353. if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 ||
  354. skip_start > skip_end)
  355. usage();
  356. skip = TRUE;
  357. } else if (keymatch(arg, "crop", 2)) {
  358. char c;
  359. if (++argn >= argc)
  360. usage();
  361. if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height,
  362. &crop_x, &crop_y) != 5 ||
  363. (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1)
  364. usage();
  365. crop = TRUE;
  366. } else if (keymatch(arg, "strict", 2)) {
  367. strict = TRUE;
  368. } else if (keymatch(arg, "targa", 1)) {
  369. /* Targa output format. */
  370. requested_fmt = FMT_TARGA;
  371. } else {
  372. usage(); /* bogus switch */
  373. }
  374. }
  375. return argn; /* return index of next arg (file name) */
  376. }
  377. /*
  378. * Marker processor for COM and interesting APPn markers.
  379. * This replaces the library's built-in processor, which just skips the marker.
  380. * We want to print out the marker as text, to the extent possible.
  381. * Note this code relies on a non-suspending data source.
  382. */
  383. LOCAL(unsigned int)
  384. jpeg_getc(j_decompress_ptr cinfo)
  385. /* Read next byte */
  386. {
  387. struct jpeg_source_mgr *datasrc = cinfo->src;
  388. if (datasrc->bytes_in_buffer == 0) {
  389. if (!(*datasrc->fill_input_buffer) (cinfo))
  390. ERREXIT(cinfo, JERR_CANT_SUSPEND);
  391. }
  392. datasrc->bytes_in_buffer--;
  393. return *datasrc->next_input_byte++;
  394. }
  395. METHODDEF(boolean)
  396. print_text_marker(j_decompress_ptr cinfo)
  397. {
  398. boolean traceit = (cinfo->err->trace_level >= 1);
  399. long length;
  400. unsigned int ch;
  401. unsigned int lastch = 0;
  402. length = jpeg_getc(cinfo) << 8;
  403. length += jpeg_getc(cinfo);
  404. length -= 2; /* discount the length word itself */
  405. if (traceit) {
  406. if (cinfo->unread_marker == JPEG_COM)
  407. fprintf(stderr, "Comment, length %ld:\n", (long)length);
  408. else /* assume it is an APPn otherwise */
  409. fprintf(stderr, "APP%d, length %ld:\n",
  410. cinfo->unread_marker - JPEG_APP0, (long)length);
  411. }
  412. while (--length >= 0) {
  413. ch = jpeg_getc(cinfo);
  414. if (traceit) {
  415. /* Emit the character in a readable form.
  416. * Nonprintables are converted to \nnn form,
  417. * while \ is converted to \\.
  418. * Newlines in CR, CR/LF, or LF form will be printed as one newline.
  419. */
  420. if (ch == '\r') {
  421. fprintf(stderr, "\n");
  422. } else if (ch == '\n') {
  423. if (lastch != '\r')
  424. fprintf(stderr, "\n");
  425. } else if (ch == '\\') {
  426. fprintf(stderr, "\\\\");
  427. } else if (isprint(ch)) {
  428. putc(ch, stderr);
  429. } else {
  430. fprintf(stderr, "\\%03o", ch);
  431. }
  432. lastch = ch;
  433. }
  434. }
  435. if (traceit)
  436. fprintf(stderr, "\n");
  437. return TRUE;
  438. }
  439. METHODDEF(void)
  440. my_emit_message(j_common_ptr cinfo, int msg_level)
  441. {
  442. if (msg_level < 0) {
  443. /* Treat warning as fatal */
  444. cinfo->err->error_exit(cinfo);
  445. } else {
  446. if (cinfo->err->trace_level >= msg_level)
  447. cinfo->err->output_message(cinfo);
  448. }
  449. }
  450. /*
  451. * The main program.
  452. */
  453. int
  454. main(int argc, char **argv)
  455. {
  456. struct jpeg_decompress_struct cinfo;
  457. struct jpeg_error_mgr jerr;
  458. struct cdjpeg_progress_mgr progress;
  459. int file_index;
  460. djpeg_dest_ptr dest_mgr = NULL;
  461. FILE *input_file;
  462. FILE *output_file;
  463. unsigned char *inbuffer = NULL;
  464. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  465. unsigned long insize = 0;
  466. #endif
  467. JDIMENSION num_scanlines;
  468. progname = argv[0];
  469. if (progname == NULL || progname[0] == 0)
  470. progname = "djpeg"; /* in case C library doesn't provide it */
  471. /* Initialize the JPEG decompression object with default error handling. */
  472. cinfo.err = jpeg_std_error(&jerr);
  473. jpeg_create_decompress(&cinfo);
  474. /* Add some application-specific error messages (from cderror.h) */
  475. jerr.addon_message_table = cdjpeg_message_table;
  476. jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  477. jerr.last_addon_message = JMSG_LASTADDONCODE;
  478. /* Insert custom marker processor for COM and APP12.
  479. * APP12 is used by some digital camera makers for textual info,
  480. * so we provide the ability to display it as text.
  481. * If you like, additional APPn marker types can be selected for display,
  482. * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
  483. */
  484. jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
  485. jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 12, print_text_marker);
  486. /* Scan command line to find file names. */
  487. /* It is convenient to use just one switch-parsing routine, but the switch
  488. * values read here are ignored; we will rescan the switches after opening
  489. * the input file.
  490. * (Exception: tracing level set here controls verbosity for COM markers
  491. * found during jpeg_read_header...)
  492. */
  493. file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  494. if (strict)
  495. jerr.emit_message = my_emit_message;
  496. #ifdef TWO_FILE_COMMANDLINE
  497. /* Must have either -outfile switch or explicit output file name */
  498. if (outfilename == NULL) {
  499. if (file_index != argc - 2) {
  500. fprintf(stderr, "%s: must name one input and one output file\n",
  501. progname);
  502. usage();
  503. }
  504. outfilename = argv[file_index + 1];
  505. } else {
  506. if (file_index != argc - 1) {
  507. fprintf(stderr, "%s: must name one input and one output file\n",
  508. progname);
  509. usage();
  510. }
  511. }
  512. #else
  513. /* Unix style: expect zero or one file name */
  514. if (file_index < argc - 1) {
  515. fprintf(stderr, "%s: only one input file\n", progname);
  516. usage();
  517. }
  518. #endif /* TWO_FILE_COMMANDLINE */
  519. /* Open the input file. */
  520. if (file_index < argc) {
  521. if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  522. fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  523. exit(EXIT_FAILURE);
  524. }
  525. } else {
  526. /* default input file is stdin */
  527. input_file = read_stdin();
  528. }
  529. /* Open the output file. */
  530. if (outfilename != NULL) {
  531. if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  532. fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  533. exit(EXIT_FAILURE);
  534. }
  535. } else {
  536. /* default output file is stdout */
  537. output_file = write_stdout();
  538. }
  539. if (report || max_scans != 0) {
  540. start_progress_monitor((j_common_ptr)&cinfo, &progress);
  541. progress.report = report;
  542. progress.max_scans = max_scans;
  543. }
  544. /* Specify data source for decompression */
  545. #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
  546. if (memsrc) {
  547. size_t nbytes;
  548. do {
  549. inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
  550. if (inbuffer == NULL) {
  551. fprintf(stderr, "%s: memory allocation failure\n", progname);
  552. exit(EXIT_FAILURE);
  553. }
  554. nbytes = fread(&inbuffer[insize], 1, INPUT_BUF_SIZE, input_file);
  555. if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
  556. if (file_index < argc)
  557. fprintf(stderr, "%s: can't read from %s\n", progname,
  558. argv[file_index]);
  559. else
  560. fprintf(stderr, "%s: can't read from stdin\n", progname);
  561. }
  562. insize += (unsigned long)nbytes;
  563. } while (nbytes == INPUT_BUF_SIZE);
  564. fprintf(stderr, "Compressed size: %lu bytes\n", insize);
  565. jpeg_mem_src(&cinfo, inbuffer, insize);
  566. } else
  567. #endif
  568. jpeg_stdio_src(&cinfo, input_file);
  569. /* Read file header, set default decompression parameters */
  570. (void)jpeg_read_header(&cinfo, TRUE);
  571. /* Adjust default decompression parameters by re-parsing the options */
  572. file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  573. /* Initialize the output module now to let it override any crucial
  574. * option settings (for instance, GIF wants to force color quantization).
  575. */
  576. switch (requested_fmt) {
  577. #ifdef BMP_SUPPORTED
  578. case FMT_BMP:
  579. dest_mgr = jinit_write_bmp(&cinfo, FALSE, TRUE);
  580. break;
  581. case FMT_OS2:
  582. dest_mgr = jinit_write_bmp(&cinfo, TRUE, TRUE);
  583. break;
  584. #endif
  585. #ifdef GIF_SUPPORTED
  586. case FMT_GIF:
  587. dest_mgr = jinit_write_gif(&cinfo, TRUE);
  588. break;
  589. case FMT_GIF0:
  590. dest_mgr = jinit_write_gif(&cinfo, FALSE);
  591. break;
  592. #endif
  593. #ifdef PPM_SUPPORTED
  594. case FMT_PPM:
  595. dest_mgr = jinit_write_ppm(&cinfo);
  596. break;
  597. #endif
  598. #ifdef TARGA_SUPPORTED
  599. case FMT_TARGA:
  600. dest_mgr = jinit_write_targa(&cinfo);
  601. break;
  602. #endif
  603. default:
  604. ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
  605. break;
  606. }
  607. dest_mgr->output_file = output_file;
  608. /* Start decompressor */
  609. (void)jpeg_start_decompress(&cinfo);
  610. /* Skip rows */
  611. if (skip) {
  612. JDIMENSION tmp;
  613. /* Check for valid skip_end. We cannot check this value until after
  614. * jpeg_start_decompress() is called. Note that we have already verified
  615. * that skip_start <= skip_end.
  616. */
  617. if (skip_end > cinfo.output_height - 1) {
  618. fprintf(stderr, "%s: skip region exceeds image height %u\n", progname,
  619. cinfo.output_height);
  620. exit(EXIT_FAILURE);
  621. }
  622. /* Write output file header. This is a hack to ensure that the destination
  623. * manager creates an output image of the proper size.
  624. */
  625. tmp = cinfo.output_height;
  626. cinfo.output_height -= (skip_end - skip_start + 1);
  627. (*dest_mgr->start_output) (&cinfo, dest_mgr);
  628. cinfo.output_height = tmp;
  629. /* Process data */
  630. while (cinfo.output_scanline < skip_start) {
  631. num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  632. dest_mgr->buffer_height);
  633. (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  634. }
  635. if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
  636. skip_end - skip_start + 1) {
  637. fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
  638. progname, tmp, skip_end - skip_start + 1);
  639. exit(EXIT_FAILURE);
  640. }
  641. while (cinfo.output_scanline < cinfo.output_height) {
  642. num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  643. dest_mgr->buffer_height);
  644. (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  645. }
  646. /* Decompress a subregion */
  647. } else if (crop) {
  648. JDIMENSION tmp;
  649. /* Check for valid crop dimensions. We cannot check these values until
  650. * after jpeg_start_decompress() is called.
  651. */
  652. if (crop_x + crop_width > cinfo.output_width ||
  653. crop_y + crop_height > cinfo.output_height) {
  654. fprintf(stderr, "%s: crop dimensions exceed image dimensions %u x %u\n",
  655. progname, cinfo.output_width, cinfo.output_height);
  656. exit(EXIT_FAILURE);
  657. }
  658. jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
  659. if (dest_mgr->calc_buffer_dimensions)
  660. (*dest_mgr->calc_buffer_dimensions) (&cinfo, dest_mgr);
  661. else
  662. ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
  663. /* Write output file header. This is a hack to ensure that the destination
  664. * manager creates an output image of the proper size.
  665. */
  666. tmp = cinfo.output_height;
  667. cinfo.output_height = crop_height;
  668. (*dest_mgr->start_output) (&cinfo, dest_mgr);
  669. cinfo.output_height = tmp;
  670. /* Process data */
  671. if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) {
  672. fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
  673. progname, tmp, crop_y);
  674. exit(EXIT_FAILURE);
  675. }
  676. while (cinfo.output_scanline < crop_y + crop_height) {
  677. num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  678. dest_mgr->buffer_height);
  679. (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  680. }
  681. if ((tmp =
  682. jpeg_skip_scanlines(&cinfo,
  683. cinfo.output_height - crop_y - crop_height)) !=
  684. cinfo.output_height - crop_y - crop_height) {
  685. fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
  686. progname, tmp, cinfo.output_height - crop_y - crop_height);
  687. exit(EXIT_FAILURE);
  688. }
  689. /* Normal full-image decompress */
  690. } else {
  691. /* Write output file header */
  692. (*dest_mgr->start_output) (&cinfo, dest_mgr);
  693. /* Process data */
  694. while (cinfo.output_scanline < cinfo.output_height) {
  695. num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  696. dest_mgr->buffer_height);
  697. (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  698. }
  699. }
  700. /* Hack: count final pass as done in case finish_output does an extra pass.
  701. * The library won't have updated completed_passes.
  702. */
  703. if (report || max_scans != 0)
  704. progress.pub.completed_passes = progress.pub.total_passes;
  705. if (icc_filename != NULL) {
  706. FILE *icc_file;
  707. JOCTET *icc_profile;
  708. unsigned int icc_len;
  709. if ((icc_file = fopen(icc_filename, WRITE_BINARY)) == NULL) {
  710. fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
  711. exit(EXIT_FAILURE);
  712. }
  713. if (jpeg_read_icc_profile(&cinfo, &icc_profile, &icc_len)) {
  714. if (fwrite(icc_profile, icc_len, 1, icc_file) < 1) {
  715. fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
  716. icc_filename);
  717. free(icc_profile);
  718. fclose(icc_file);
  719. exit(EXIT_FAILURE);
  720. }
  721. free(icc_profile);
  722. fclose(icc_file);
  723. } else if (cinfo.err->msg_code != JWRN_BOGUS_ICC)
  724. fprintf(stderr, "%s: no ICC profile data in JPEG file\n", progname);
  725. }
  726. /* Finish decompression and release memory.
  727. * I must do it in this order because output module has allocated memory
  728. * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
  729. */
  730. (*dest_mgr->finish_output) (&cinfo, dest_mgr);
  731. (void)jpeg_finish_decompress(&cinfo);
  732. jpeg_destroy_decompress(&cinfo);
  733. /* Close files, if we opened them */
  734. if (input_file != stdin)
  735. fclose(input_file);
  736. if (output_file != stdout)
  737. fclose(output_file);
  738. if (report || max_scans != 0)
  739. end_progress_monitor((j_common_ptr)&cinfo);
  740. if (memsrc)
  741. free(inbuffer);
  742. /* All done. */
  743. exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  744. return 0; /* suppress no-return-value warnings */
  745. }