djpegalt.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /*
  2. * alternate djpeg.c
  3. *
  4. * Copyright (C) 1991-1997, Thomas G. Lane.
  5. * Modified 2009-2023 by Guido Vollbeding.
  6. * This file is part of the Independent JPEG Group's software.
  7. * For conditions of distribution and use, see the accompanying README file.
  8. *
  9. * This file contains an alternate user interface for the JPEG decompressor.
  10. * One or more input files are named on the command line, and output file
  11. * names are created by substituting an appropriate extension.
  12. */
  13. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  14. #include "jversion.h" /* for version message */
  15. #include <ctype.h> /* to declare isprint() */
  16. #ifdef USE_CCOMMAND /* command-line reader for Macintosh */
  17. #ifdef __MWERKS__
  18. #include <SIOUX.h> /* Metrowerks needs this */
  19. #include <console.h> /* ... and this */
  20. #endif
  21. #ifdef THINK_C
  22. #include <console.h> /* Think declares it here */
  23. #endif
  24. #endif
  25. #ifndef PATH_MAX /* ANSI maximum-pathname-length constant */
  26. #define PATH_MAX 256
  27. #endif
  28. /* Create the add-on message string table. */
  29. #define JMESSAGE(code,string) string ,
  30. static const char * const cdjpeg_message_table[] = {
  31. #include "cderror.h"
  32. NULL
  33. };
  34. /*
  35. * Automatic determination of available memory.
  36. */
  37. static long default_maxmem; /* saves value determined at startup, or 0 */
  38. #ifndef FREE_MEM_ESTIMATE /* may be defined from command line */
  39. #ifdef MSDOS /* For MS-DOS (unless flat-memory model) */
  40. #include <dos.h> /* for access to intdos() call */
  41. LOCAL(long)
  42. unused_dos_memory (void)
  43. /* Obtain total amount of unallocated DOS memory */
  44. {
  45. union REGS regs;
  46. long nparas;
  47. regs.h.ah = 0x48; /* DOS function Allocate Memory Block */
  48. regs.x.bx = 0xFFFF; /* Ask for more memory than DOS can have */
  49. (void) intdos(&regs, &regs);
  50. /* DOS will fail and return # of paragraphs actually available in BX. */
  51. nparas = (unsigned int) regs.x.bx;
  52. /* Times 16 to convert to bytes. */
  53. return nparas << 4;
  54. }
  55. /* The default memory setting is 95% of the available space. */
  56. #define FREE_MEM_ESTIMATE ((unused_dos_memory() * 95L) / 100L)
  57. #endif /* MSDOS */
  58. #ifdef ATARI /* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
  59. #include <ext.h>
  60. /* The default memory setting is 90% of the available space. */
  61. #define FREE_MEM_ESTIMATE (((long) coreleft() * 90L) / 100L)
  62. #endif /* ATARI */
  63. /* Add memory-estimation procedures for other operating systems here,
  64. * with appropriate #ifdef's around them.
  65. */
  66. #endif /* !FREE_MEM_ESTIMATE */
  67. /*
  68. * This list defines the known output image formats
  69. * (not all of which need be supported by a given version).
  70. * You can change the default output format by defining DEFAULT_FMT;
  71. * indeed, you had better do so if you undefine PPM_SUPPORTED.
  72. */
  73. typedef enum {
  74. FMT_BMP, /* BMP format (Windows flavor) */
  75. FMT_GIF, /* GIF format (LZW compressed) */
  76. FMT_GIF0, /* GIF format (uncompressed) */
  77. FMT_OS2, /* BMP format (OS/2 flavor) */
  78. FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
  79. FMT_RLE, /* RLE format */
  80. FMT_TARGA, /* Targa format */
  81. FMT_TIFF /* TIFF format */
  82. } IMAGE_FORMATS;
  83. #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
  84. #define DEFAULT_FMT FMT_BMP
  85. #endif
  86. static IMAGE_FORMATS requested_fmt;
  87. /*
  88. * Argument-parsing code.
  89. * The switch parser is designed to be useful with DOS-style command line
  90. * syntax, ie, intermixed switches and file names, where only the switches
  91. * to the left of a given file name affect processing of that file.
  92. */
  93. static const char * progname; /* program name for error messages */
  94. static char * outfilename; /* for -outfile switch */
  95. LOCAL(void)
  96. usage (void)
  97. /* complain about bad command line */
  98. {
  99. fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
  100. fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
  101. fprintf(stderr, "Output filename is same as input filename except for extension\n");
  102. fprintf(stderr, "Switches (names may be abbreviated):\n");
  103. fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
  104. fprintf(stderr, " -fast Fast, low-quality processing\n");
  105. fprintf(stderr, " -grayscale Force grayscale output\n");
  106. fprintf(stderr, " -rgb Force RGB output\n");
  107. #ifdef IDCT_SCALING_SUPPORTED
  108. fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
  109. #endif
  110. #ifdef BMP_SUPPORTED
  111. fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
  112. (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
  113. #endif
  114. #ifdef GIF_SUPPORTED
  115. fprintf(stderr, " -gif Select GIF output format (LZW compressed)%s\n",
  116. (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
  117. fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n",
  118. (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
  119. #endif
  120. #ifdef BMP_SUPPORTED
  121. fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
  122. (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
  123. #endif
  124. #ifdef PPM_SUPPORTED
  125. fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
  126. (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
  127. #endif
  128. #ifdef RLE_SUPPORTED
  129. fprintf(stderr, " -rle Select Utah RLE output format%s\n",
  130. (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
  131. #endif
  132. #ifdef TARGA_SUPPORTED
  133. fprintf(stderr, " -targa Select Targa output format%s\n",
  134. (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
  135. #endif
  136. fprintf(stderr, "Switches for advanced users:\n");
  137. #ifdef DCT_ISLOW_SUPPORTED
  138. fprintf(stderr, " -dct int Use integer DCT method%s\n",
  139. (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  140. #endif
  141. #ifdef DCT_IFAST_SUPPORTED
  142. fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
  143. (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  144. #endif
  145. #ifdef DCT_FLOAT_SUPPORTED
  146. fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
  147. (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  148. #endif
  149. fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
  150. fprintf(stderr, " -dither none Don't use dithering in quantization\n");
  151. fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
  152. #ifdef QUANT_2PASS_SUPPORTED
  153. fprintf(stderr, " -map FILE Map to colors used in named image file\n");
  154. #endif
  155. fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
  156. #ifdef QUANT_1PASS_SUPPORTED
  157. fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
  158. #endif
  159. #ifndef FREE_MEM_ESTIMATE
  160. fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
  161. #endif
  162. fprintf(stderr, " -outfile name Specify name for output file\n");
  163. fprintf(stderr, " -verbose or -debug Emit debug output\n");
  164. exit(EXIT_FAILURE);
  165. }
  166. LOCAL(int)
  167. parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
  168. int last_file_arg_seen, boolean for_real)
  169. /* Parse optional switches.
  170. * Returns argv[] index of first file-name argument (== argc if none).
  171. * Any file names with indexes <= last_file_arg_seen are ignored;
  172. * they have presumably been processed in a previous iteration.
  173. * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  174. * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  175. * processing.
  176. */
  177. {
  178. int argn;
  179. char * arg;
  180. /* Set up default JPEG parameters. */
  181. requested_fmt = DEFAULT_FMT; /* set default output file format */
  182. outfilename = NULL;
  183. cinfo->err->trace_level = 0;
  184. if (default_maxmem > 0) /* override library's default value */
  185. cinfo->mem->max_memory_to_use = default_maxmem;
  186. /* Scan command line options, adjust parameters */
  187. for (argn = 1; argn < argc; argn++) {
  188. arg = argv[argn];
  189. if (*arg != '-') {
  190. /* Not a switch, must be a file name argument */
  191. if (argn <= last_file_arg_seen) {
  192. outfilename = NULL; /* -outfile applies to just one input file */
  193. continue; /* ignore this name if previously processed */
  194. }
  195. break; /* else done parsing switches */
  196. }
  197. arg++; /* advance past switch marker character */
  198. if (keymatch(arg, "bmp", 1)) {
  199. /* BMP output format (Windows flavor). */
  200. requested_fmt = FMT_BMP;
  201. } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
  202. keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
  203. /* Do color quantization. */
  204. int val;
  205. if (++argn >= argc) /* advance to next argument */
  206. usage();
  207. if (sscanf(argv[argn], "%d", &val) != 1)
  208. usage();
  209. cinfo->desired_number_of_colors = val;
  210. cinfo->quantize_colors = TRUE;
  211. } else if (keymatch(arg, "dct", 2)) {
  212. /* Select IDCT algorithm. */
  213. if (++argn >= argc) /* advance to next argument */
  214. usage();
  215. if (keymatch(argv[argn], "int", 1)) {
  216. cinfo->dct_method = JDCT_ISLOW;
  217. } else if (keymatch(argv[argn], "fast", 2)) {
  218. cinfo->dct_method = JDCT_IFAST;
  219. } else if (keymatch(argv[argn], "float", 2)) {
  220. cinfo->dct_method = JDCT_FLOAT;
  221. } else
  222. usage();
  223. } else if (keymatch(arg, "dither", 2)) {
  224. /* Select dithering algorithm. */
  225. if (++argn >= argc) /* advance to next argument */
  226. usage();
  227. if (keymatch(argv[argn], "fs", 2)) {
  228. cinfo->dither_mode = JDITHER_FS;
  229. } else if (keymatch(argv[argn], "none", 2)) {
  230. cinfo->dither_mode = JDITHER_NONE;
  231. } else if (keymatch(argv[argn], "ordered", 2)) {
  232. cinfo->dither_mode = JDITHER_ORDERED;
  233. } else
  234. usage();
  235. } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  236. /* Enable debug printouts. */
  237. /* On first -d, print version identification */
  238. static boolean printed_version = FALSE;
  239. if (! printed_version) {
  240. fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
  241. JVERSION, JCOPYRIGHT);
  242. printed_version = TRUE;
  243. }
  244. cinfo->err->trace_level++;
  245. } else if (keymatch(arg, "fast", 1)) {
  246. /* Select recommended processing options for quick-and-dirty output. */
  247. cinfo->two_pass_quantize = FALSE;
  248. cinfo->dither_mode = JDITHER_ORDERED;
  249. if (! cinfo->quantize_colors) /* don't override an earlier -colors */
  250. cinfo->desired_number_of_colors = 216;
  251. cinfo->dct_method = JDCT_FASTEST;
  252. cinfo->do_fancy_upsampling = FALSE;
  253. } else if (keymatch(arg, "gif", 1)) {
  254. /* GIF output format (LZW compressed). */
  255. requested_fmt = FMT_GIF;
  256. } else if (keymatch(arg, "gif0", 4)) {
  257. /* GIF output format (uncompressed). */
  258. requested_fmt = FMT_GIF0;
  259. } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  260. /* Force monochrome output. */
  261. cinfo->out_color_space = JCS_GRAYSCALE;
  262. } else if (keymatch(arg, "rgb", 3)) {
  263. /* Force RGB output. */
  264. cinfo->out_color_space = JCS_RGB;
  265. } else if (keymatch(arg, "map", 3)) {
  266. /* Quantize to a color map taken from an input file. */
  267. if (++argn >= argc) /* advance to next argument */
  268. usage();
  269. if (for_real) { /* too expensive to do twice! */
  270. #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
  271. FILE * mapfile;
  272. if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
  273. fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
  274. exit(EXIT_FAILURE);
  275. }
  276. read_color_map(cinfo, mapfile);
  277. fclose(mapfile);
  278. cinfo->quantize_colors = TRUE;
  279. #else
  280. ERREXIT(cinfo, JERR_NOT_COMPILED);
  281. #endif
  282. }
  283. } else if (keymatch(arg, "maxmemory", 3)) {
  284. /* Maximum memory in Kb (or Mb with 'm'). */
  285. long lval;
  286. char ch = 'x';
  287. if (++argn >= argc) /* advance to next argument */
  288. usage();
  289. if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  290. usage();
  291. if (ch == 'm' || ch == 'M')
  292. lval *= 1000L;
  293. cinfo->mem->max_memory_to_use = lval * 1000L;
  294. } else if (keymatch(arg, "nosmooth", 3)) {
  295. /* Suppress fancy upsampling. */
  296. cinfo->do_fancy_upsampling = FALSE;
  297. } else if (keymatch(arg, "onepass", 3)) {
  298. /* Use fast one-pass quantization. */
  299. cinfo->two_pass_quantize = FALSE;
  300. } else if (keymatch(arg, "os2", 3)) {
  301. /* BMP output format (OS/2 flavor). */
  302. requested_fmt = FMT_OS2;
  303. } else if (keymatch(arg, "outfile", 4)) {
  304. /* Set output file name. */
  305. if (++argn >= argc) /* advance to next argument */
  306. usage();
  307. outfilename = argv[argn]; /* save it away for later use */
  308. } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
  309. /* PPM/PGM output format. */
  310. requested_fmt = FMT_PPM;
  311. } else if (keymatch(arg, "rle", 1)) {
  312. /* RLE output format. */
  313. requested_fmt = FMT_RLE;
  314. } else if (keymatch(arg, "scale", 1)) {
  315. /* Scale the output image by a fraction M/N. */
  316. if (++argn >= argc) /* advance to next argument */
  317. usage();
  318. if (sscanf(argv[argn], "%u/%u",
  319. &cinfo->scale_num, &cinfo->scale_denom) < 1)
  320. usage();
  321. } else if (keymatch(arg, "targa", 1)) {
  322. /* Targa output format. */
  323. requested_fmt = FMT_TARGA;
  324. } else {
  325. usage(); /* bogus switch */
  326. }
  327. }
  328. return argn; /* return index of next arg (file name) */
  329. }
  330. /*
  331. * Marker processor for COM and interesting APPn markers.
  332. * This replaces the library's built-in processor, which just skips the marker.
  333. * We want to print out the marker as text, to the extent possible.
  334. * Note this code relies on a non-suspending data source.
  335. */
  336. LOCAL(unsigned int)
  337. jpeg_getc (j_decompress_ptr cinfo)
  338. /* Read next byte */
  339. {
  340. struct jpeg_source_mgr * datasrc = cinfo->src;
  341. if (datasrc->bytes_in_buffer == 0) {
  342. if (! (*datasrc->fill_input_buffer) (cinfo))
  343. ERREXIT(cinfo, JERR_CANT_SUSPEND);
  344. }
  345. datasrc->bytes_in_buffer--;
  346. return GETJOCTET(*datasrc->next_input_byte++);
  347. }
  348. METHODDEF(boolean)
  349. print_text_marker (j_decompress_ptr cinfo)
  350. {
  351. boolean traceit = (cinfo->err->trace_level >= 1);
  352. INT32 length;
  353. unsigned int ch;
  354. unsigned int lastch = 0;
  355. length = jpeg_getc(cinfo) << 8;
  356. length += jpeg_getc(cinfo);
  357. length -= 2; /* discount the length word itself */
  358. if (traceit) {
  359. if (cinfo->unread_marker == JPEG_COM)
  360. fprintf(stderr, "Comment, length %ld:\n", (long) length);
  361. else /* assume it is an APPn otherwise */
  362. fprintf(stderr, "APP%d, length %ld:\n",
  363. cinfo->unread_marker - JPEG_APP0, (long) length);
  364. }
  365. while (--length >= 0) {
  366. ch = jpeg_getc(cinfo);
  367. if (traceit) {
  368. /* Emit the character in a readable form.
  369. * Nonprintables are converted to \nnn form,
  370. * while \ is converted to \\.
  371. * Newlines in CR, CR/LF, or LF form will be printed as one newline.
  372. */
  373. if (ch == '\r') {
  374. fprintf(stderr, "\n");
  375. } else if (ch == '\n') {
  376. if (lastch != '\r')
  377. fprintf(stderr, "\n");
  378. } else if (ch == '\\') {
  379. fprintf(stderr, "\\\\");
  380. } else if (isprint(ch)) {
  381. putc(ch, stderr);
  382. } else {
  383. fprintf(stderr, "\\%03o", ch);
  384. }
  385. lastch = ch;
  386. }
  387. }
  388. if (traceit)
  389. fprintf(stderr, "\n");
  390. return TRUE;
  391. }
  392. /*
  393. * Check for overwrite of an existing file; clear it with user
  394. */
  395. #ifndef NO_OVERWRITE_CHECK
  396. LOCAL(boolean)
  397. is_write_ok (char * outfname)
  398. {
  399. FILE * ofile;
  400. int ch;
  401. ofile = fopen(outfname, READ_BINARY);
  402. if (ofile == NULL)
  403. return TRUE; /* not present */
  404. fclose(ofile); /* oops, it is present */
  405. for (;;) {
  406. fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
  407. outfname);
  408. fflush(stderr);
  409. ch = getc(stdin);
  410. if (ch != '\n') /* flush rest of line */
  411. while (getc(stdin) != '\n')
  412. /* nothing */;
  413. switch (ch) {
  414. case 'Y':
  415. case 'y':
  416. return TRUE;
  417. case 'N':
  418. case 'n':
  419. return FALSE;
  420. /* otherwise, ask again */
  421. }
  422. }
  423. }
  424. #endif
  425. /*
  426. * Process a single input file name, and return its index in argv[].
  427. * File names at or to left of old_file_index have been processed already.
  428. */
  429. LOCAL(int)
  430. process_one_file (int argc, char **argv, int old_file_index)
  431. {
  432. struct jpeg_decompress_struct cinfo;
  433. struct jpeg_error_mgr jerr;
  434. char *infilename;
  435. char workfilename[PATH_MAX];
  436. const char *default_extension = NULL;
  437. #ifdef PROGRESS_REPORT
  438. struct cdjpeg_progress_mgr progress;
  439. #endif
  440. int file_index;
  441. djpeg_dest_ptr dest_mgr = NULL;
  442. FILE * input_file = NULL;
  443. FILE * output_file = NULL;
  444. JDIMENSION num_scanlines;
  445. /* Initialize the JPEG decompression object with default error handling. */
  446. cinfo.err = jpeg_std_error(&jerr);
  447. jpeg_create_decompress(&cinfo);
  448. /* Add some application-specific error messages (from cderror.h) */
  449. jerr.addon_message_table = cdjpeg_message_table;
  450. jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  451. jerr.last_addon_message = JMSG_LASTADDONCODE;
  452. /* Insert custom marker processor for COM and APP12.
  453. * APP12 is used by some digital camera makers for textual info,
  454. * so we provide the ability to display it as text.
  455. * If you like, additional APPn marker types can be selected for display,
  456. * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
  457. */
  458. jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
  459. jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
  460. /* Now safe to enable signal catcher. */
  461. #ifdef NEED_SIGNAL_CATCHER
  462. enable_signal_catcher((j_common_ptr) &cinfo);
  463. #endif
  464. /* Scan command line to find next file name.
  465. * It is convenient to use just one switch-parsing routine, but the switch
  466. * values read here are ignored; we will rescan the switches after opening
  467. * the input file.
  468. * (Exception: tracing level set here controls verbosity for COM markers
  469. * found during jpeg_read_header...)
  470. */
  471. file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
  472. if (file_index >= argc) {
  473. fprintf(stderr, "%s: missing input file name\n", progname);
  474. usage();
  475. }
  476. /* Open the input file. */
  477. infilename = argv[file_index];
  478. if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
  479. fprintf(stderr, "%s: can't open %s\n", progname, infilename);
  480. goto fail;
  481. }
  482. #ifdef PROGRESS_REPORT
  483. start_progress_monitor((j_common_ptr) &cinfo, &progress);
  484. #endif
  485. /* Specify data source for decompression */
  486. jpeg_stdio_src(&cinfo, input_file);
  487. /* Read file header, set default decompression parameters */
  488. (void) jpeg_read_header(&cinfo, TRUE);
  489. /* Adjust default decompression parameters by re-parsing the options */
  490. file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
  491. /* Initialize the output module now to let it override any crucial
  492. * option settings (for instance, GIF wants to force color quantization).
  493. */
  494. switch (requested_fmt) {
  495. #ifdef BMP_SUPPORTED
  496. case FMT_BMP:
  497. dest_mgr = jinit_write_bmp(&cinfo, FALSE);
  498. default_extension = ".bmp";
  499. break;
  500. case FMT_OS2:
  501. dest_mgr = jinit_write_bmp(&cinfo, TRUE);
  502. default_extension = ".bmp";
  503. break;
  504. #endif
  505. #ifdef GIF_SUPPORTED
  506. case FMT_GIF:
  507. dest_mgr = jinit_write_gif(&cinfo, TRUE);
  508. default_extension = ".gif";
  509. break;
  510. case FMT_GIF0:
  511. dest_mgr = jinit_write_gif(&cinfo, FALSE);
  512. default_extension = ".gif";
  513. break;
  514. #endif
  515. #ifdef PPM_SUPPORTED
  516. case FMT_PPM:
  517. dest_mgr = jinit_write_ppm(&cinfo);
  518. default_extension = ".ppm";
  519. break;
  520. #endif
  521. #ifdef RLE_SUPPORTED
  522. case FMT_RLE:
  523. dest_mgr = jinit_write_rle(&cinfo);
  524. default_extension = ".rle";
  525. break;
  526. #endif
  527. #ifdef TARGA_SUPPORTED
  528. case FMT_TARGA:
  529. dest_mgr = jinit_write_targa(&cinfo);
  530. default_extension = ".tga";
  531. break;
  532. #endif
  533. default:
  534. ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
  535. }
  536. /* If user didn't supply -outfile switch, select output file name. */
  537. if (outfilename == NULL) {
  538. int i;
  539. outfilename = workfilename;
  540. /* Make outfilename be infilename with appropriate extension */
  541. strcpy(outfilename, infilename);
  542. for (i = (int)strlen(outfilename)-1; i >= 0; i--) {
  543. switch (outfilename[i]) {
  544. case ':':
  545. case '/':
  546. case '\\':
  547. i = 0; /* stop scanning */
  548. break;
  549. case '.':
  550. outfilename[i] = '\0'; /* lop off existing extension */
  551. i = 0; /* stop scanning */
  552. break;
  553. default:
  554. break; /* keep scanning */
  555. }
  556. }
  557. strcat(outfilename, default_extension);
  558. }
  559. fprintf(stderr, "Decompressing %s => %s\n", infilename, outfilename);
  560. #ifndef NO_OVERWRITE_CHECK
  561. if (! is_write_ok(outfilename))
  562. goto fail;
  563. #endif
  564. /* Open the output file. */
  565. if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  566. fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
  567. goto fail;
  568. }
  569. dest_mgr->output_file = output_file;
  570. /* Start decompressor */
  571. (void) jpeg_start_decompress(&cinfo);
  572. /* Write output file header */
  573. (*dest_mgr->start_output) (&cinfo, dest_mgr);
  574. /* Process data */
  575. while (cinfo.output_scanline < cinfo.output_height) {
  576. num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  577. dest_mgr->buffer_height);
  578. (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  579. }
  580. #ifdef PROGRESS_REPORT
  581. /* Hack: count final pass as done in case finish_output does an extra pass.
  582. * The library won't have updated completed_passes.
  583. */
  584. progress.pub.completed_passes = progress.pub.total_passes;
  585. #endif
  586. /* Finish decompression and release memory.
  587. * I must do it in this order because output module has allocated memory
  588. * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
  589. */
  590. (*dest_mgr->finish_output) (&cinfo, dest_mgr);
  591. (void) jpeg_finish_decompress(&cinfo);
  592. /* Clean up and exit */
  593. fail:
  594. jpeg_destroy_decompress(&cinfo);
  595. if (input_file != NULL) fclose(input_file);
  596. if (output_file != NULL) fclose(output_file);
  597. #ifdef PROGRESS_REPORT
  598. end_progress_monitor((j_common_ptr) &cinfo);
  599. #endif
  600. /* Disable signal catcher. */
  601. #ifdef NEED_SIGNAL_CATCHER
  602. enable_signal_catcher((j_common_ptr) NULL);
  603. #endif
  604. return file_index;
  605. }
  606. /*
  607. * The main program.
  608. */
  609. int
  610. main (int argc, char **argv)
  611. {
  612. int file_index;
  613. /* On Mac, fetch a command line. */
  614. #ifdef USE_CCOMMAND
  615. argc = ccommand(&argv);
  616. #endif
  617. #ifdef MSDOS
  618. progname = "djpeg"; /* DOS tends to be too verbose about argv[0] */
  619. #else
  620. progname = argv[0];
  621. if (progname == NULL || progname[0] == 0)
  622. progname = "djpeg"; /* in case C library doesn't provide it */
  623. #endif
  624. /* The default maxmem must be computed only once at program startup,
  625. * since releasing memory with free() won't give it back to the OS.
  626. */
  627. #ifdef FREE_MEM_ESTIMATE
  628. default_maxmem = FREE_MEM_ESTIMATE;
  629. #else
  630. default_maxmem = 0;
  631. #endif
  632. /* Scan command line, parse switches and locate input file names */
  633. if (argc < 2)
  634. usage(); /* nothing on the command line?? */
  635. file_index = 0;
  636. while (file_index < argc-1)
  637. file_index = process_one_file(argc, argv, file_index);
  638. /* All done. */
  639. exit(EXIT_SUCCESS);
  640. return 0; /* suppress no-return-value warnings */
  641. }