djpeg.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. Program DJpeg;
  2. { djpeg.c ; Copyright (C) 1991-1997, Thomas G. Lane. }
  3. { This file contains a command-line user interface for the JPEG decompressor.
  4. It should work on any system with Unix- or MS-DOS-style command lines.
  5. Two different command line styles are permitted, depending on the
  6. compile-time switch TWO_FILE_COMMANDLINE:
  7. djpeg [options] inputfile outputfile
  8. djpeg [options] [inputfile]
  9. In the second style, output is always to standard output, which you'd
  10. normally redirect to a file or pipe to some other program. Input is
  11. either from a named file or from standard input (typically redirected).
  12. The second style is convenient on Unix but is unhelpful on systems that
  13. don't support pipes. Also, you MUST use the first style if your system
  14. doesn't do binary I/O to stdin/stdout.
  15. To simplify script writing, the "-outfile" switch is provided. The syntax
  16. djpeg [options] -outfile outputfile inputfile
  17. works regardless of which command line style is used. }
  18. {$I jconfig.inc}
  19. uses
  20. jmorecfg,
  21. jpeglib,
  22. jerror,
  23. RdColMap,
  24. jdeferr,
  25. jdapimin, jdapistd, jdatasrc,
  26. {$ifdef BMP_SUPPORTED} wrbmp, {$endif}
  27. {$ifdef PPM_SUPPORTED} wrppm, {$endif}
  28. {$ifdef TARGA_SUPPORTED} wrtarga, {$endif}
  29. jdmarker,
  30. cdjpeg; { Common decls for cjpeg/djpeg applications }
  31. { for version message }
  32. { This list defines the known output image formats
  33. (not all of which need be supported by a given version).
  34. You can change the default output format by defining DEFAULT_FMT;
  35. indeed, you had better do so if you undefine PPM_SUPPORTED. }
  36. type
  37. IMAGE_FORMATS = (
  38. FMT_BMP, { BMP format (Windows flavor) }
  39. FMT_GIF, { GIF format }
  40. FMT_OS2, { BMP format (OS/2 flavor) }
  41. FMT_PPM, { PPM/PGM (PBMPLUS formats) }
  42. FMT_RLE, { RLE format }
  43. FMT_TARGA, { Targa format }
  44. FMT_TIFF); { TIFF format }
  45. const
  46. DEFAULT_FMT = FMT_PPM;
  47. var
  48. requested_fmt : IMAGE_FORMATS;
  49. { Argument-parsing code.
  50. The switch parser is designed to be useful with DOS-style command line
  51. syntax, ie, intermixed switches and file names, where only the switches
  52. to the left of a given file name affect processing of that file.
  53. The main program in this file doesn't actually use this capability... }
  54. var
  55. progname, { program name for error messages }
  56. outfilename : string[127]; { for -outfile switch }
  57. {LOCAL}
  58. procedure usage;
  59. const
  60. default_txt : array[boolean] of string[30] = ('', ' (default)');
  61. { complain about bad command line }
  62. begin
  63. Write (output, 'usage: ', progname, ' [switches] ');
  64. {$ifdef TWO_FILE_COMMANDLINE}
  65. WriteLn(output, 'inputfile outputfile');
  66. {$else}
  67. WriteLn(output, '[inputfile]');
  68. {$endif}
  69. WriteLn(output, 'Switches (names may be abbreviated):');
  70. WriteLn(output, ' -colors N Reduce image to no more than N colors');
  71. WriteLn(output, ' -fast Fast, low-quality processing');
  72. WriteLn(output, ' -grayscale Force grayscale output');
  73. {$ifdef IDCT_SCALING_SUPPORTED}
  74. WriteLn(output, ' -scale M/N Scale output image by fraction M/N, eg, 1/8');
  75. {$endif}
  76. {$ifdef BMP_SUPPORTED}
  77. WriteLn(output, ' -bmp Select BMP output format (Windows style)',
  78. default_txt[DEFAULT_FMT = FMT_BMP]);
  79. {$endif}
  80. {$ifdef GIF_SUPPORTED}
  81. WriteLn(output, ' -gif Select GIF output format',
  82. default_txt[DEFAULT_FMT = FMT_GIF]);
  83. {$endif}
  84. {$ifdef BMP_SUPPORTED}
  85. WriteLn(output, ' -os2 Select BMP output format (OS/2 style)',
  86. default_txt[DEFAULT_FMT = FMT_OS2]);
  87. {$endif}
  88. {$ifdef PPM_SUPPORTED}
  89. WriteLn(output, ' -pnm Select PBMPLUS (PPM/PGM) output format',
  90. default_txt[DEFAULT_FMT = FMT_PPM]);
  91. {$endif}
  92. {$ifdef RLE_SUPPORTED}
  93. WriteLn(output, ' -rle Select Utah RLE output format',
  94. default_txt[DEFAULT_FMT = FMT_RLE]);
  95. {$endif}
  96. {$ifdef TARGA_SUPPORTED}
  97. WriteLn(output, ' -targa Select Targa output format',
  98. default_txt[DEFAULT_FMT = FMT_TARGA]);
  99. {$endif}
  100. WriteLn(output, 'Switches for advanced users:');
  101. {$ifdef DCT_ISLOW_SUPPORTED}
  102. WriteLn(output, ' -dct int Use integer DCT method',
  103. default_txt[JDCT_DEFAULT = JDCT_ISLOW]);
  104. {$endif}
  105. {$ifdef DCT_IFAST_SUPPORTED}
  106. WriteLn(output, ' -dct fast Use fast integer DCT (less accurate)',
  107. default_txt[JDCT_DEFAULT = JDCT_IFAST]);
  108. {$endif}
  109. {$ifdef DCT_FLOAT_SUPPORTED}
  110. WriteLn(output, ' -dct float Use floating-point DCT method',
  111. default_txt[JDCT_DEFAULT = JDCT_FLOAT]);
  112. {$endif}
  113. WriteLn(output, ' -dither fs Use F-S dithering (default)');
  114. WriteLn(output, ' -dither none Don''t use dithering in quantization');
  115. WriteLn(output, ' -dither ordered Use ordered dither (medium speed, quality)');
  116. {$ifdef QUANT_2PASS_SUPPORTED}
  117. WriteLn(output, ' -map FILE Map to colors used in named image file');
  118. {$endif}
  119. WriteLn(output, ' -nosmooth Don''t use high-quality upsampling');
  120. {$ifdef QUANT_1PASS_SUPPORTED}
  121. WriteLn(output, ' -onepass Use 1-pass quantization (fast, low quality)');
  122. {$endif}
  123. WriteLn(output, ' -maxmemory N Maximum memory to use (in kbytes)');
  124. WriteLn(output, ' -outfile name Specify name for output file');
  125. WriteLn(output, ' -verbose or -debug Emit debug output');
  126. Halt(EXIT_FAILURE);
  127. end;
  128. {LOCAL}
  129. function parse_switches (cinfo : j_decompress_ptr;
  130. last_file_arg_seen : int;
  131. for_real : boolean) : int;
  132. { Parse optional switches.
  133. Returns argv[] index of first file-name argument (== argc if none).
  134. Any file names with indexes <= last_file_arg_seen are ignored;
  135. they have presumably been processed in a previous iteration.
  136. (Pass 0 for last_file_arg_seen on the first or only iteration.)
  137. for_real is FALSE on the first (dummy) pass; we may skip any expensive
  138. processing. }
  139. var
  140. argn,
  141. argc : int;
  142. arg : string;
  143. var
  144. value : int;
  145. code : integer;
  146. {$ifdef QUANT_2PASS_SUPPORTED} { otherwise can't quantize to supplied map }
  147. var
  148. mapfile : file;
  149. {$endif}
  150. const
  151. printed_version : boolean = FALSE;
  152. var
  153. lval : long;
  154. ch : char;
  155. begin
  156. { Set up default JPEG parameters. }
  157. requested_fmt := DEFAULT_FMT; { set default output file format }
  158. outfilename := '';
  159. cinfo^.err^.trace_level := 0;
  160. { Scan command line options, adjust parameters }
  161. argn := 0;
  162. argc := ParamCount;
  163. while argn < argc do
  164. begin
  165. Inc(argn);
  166. arg := ParamStr(argn);
  167. if (arg[1] <> '-') then
  168. begin
  169. { Not a switch, must be a file name argument }
  170. if (argn <= last_file_arg_seen) then
  171. begin
  172. outfilename := ''; { -outfile applies to just one input file }
  173. continue; { ignore this name if previously processed }
  174. end;
  175. break; { else done parsing switches }
  176. end;
  177. {Inc(arg); - advance past switch marker character }
  178. if (keymatch(arg, '-bmp', 2)) then
  179. begin
  180. { BMP output format. }
  181. requested_fmt := FMT_BMP;
  182. end
  183. else
  184. if (keymatch(arg, '-colors', 2)) or (keymatch(arg, '-colours', 2)) or
  185. (keymatch(arg, '-quantize', 2)) or (keymatch(arg, '-quantise', 2)) then
  186. begin { Do color quantization. }
  187. Inc(argn);
  188. if (argn >= argc) then { advance to next argument }
  189. usage;
  190. Val(ParamStr(argn), value, code);
  191. if code <> 0 then
  192. usage;
  193. cinfo^.desired_number_of_colors := value;
  194. cinfo^.quantize_colors := TRUE;
  195. end
  196. else
  197. if (keymatch(arg, '-dct', 3)) then
  198. begin { Select IDCT algorithm. }
  199. Inc(argn);
  200. if (argn >= argc) then { advance to next argument }
  201. usage;
  202. if (keymatch(ParamStr(argn), 'int', 1)) then
  203. cinfo^.dct_method := JDCT_ISLOW
  204. else
  205. if (keymatch(ParamStr(argn), 'fast', 2)) then
  206. cinfo^.dct_method := JDCT_IFAST
  207. else
  208. if (keymatch(ParamStr(argn), 'float', 2)) then
  209. cinfo^.dct_method := JDCT_FLOAT
  210. else
  211. usage;
  212. end
  213. else
  214. if (keymatch(arg, '-dither', 3)) then
  215. begin { Select dithering algorithm. }
  216. Inc(argn);
  217. if (argn >= argc) then { advance to next argument }
  218. usage;
  219. if (keymatch(ParamStr(argn), 'fs', 2)) then
  220. cinfo^.dither_mode := JDITHER_FS
  221. else
  222. if (keymatch(ParamStr(argn), 'none', 2)) then
  223. cinfo^.dither_mode := JDITHER_NONE
  224. else
  225. if (keymatch(ParamStr(argn), 'ordered', 2)) then
  226. cinfo^.dither_mode := JDITHER_ORDERED
  227. else
  228. usage;
  229. end
  230. else
  231. if (keymatch(arg, '-debug', 2)) or (keymatch(arg, '-verbose', 2)) then
  232. begin { Enable debug printouts. }
  233. { On first -d, print version identification }
  234. if (not printed_version) then
  235. begin
  236. WriteLn(output, 'PASJPEG Group''s DJPEG, version ',
  237. JVERSION);
  238. WriteLn(output, JCOPYRIGHT);
  239. WriteLn(output, JNOTICE);
  240. printed_version := TRUE;
  241. end;
  242. Inc(cinfo^.err^.trace_level);
  243. end
  244. else
  245. if (keymatch(arg, '-fast', 2)) then
  246. begin
  247. { Select recommended processing options for quick-and-dirty output. }
  248. cinfo^.two_pass_quantize := FALSE;
  249. cinfo^.dither_mode := JDITHER_ORDERED;
  250. if (not cinfo^.quantize_colors) then { don't override an earlier -colors }
  251. cinfo^.desired_number_of_colors := 216;
  252. cinfo^.dct_method := JDCT_FASTEST;
  253. cinfo^.do_fancy_upsampling := FALSE;
  254. end
  255. else
  256. if (keymatch(arg, '-gif', 2)) then
  257. begin { GIF output format. }
  258. requested_fmt := FMT_GIF;
  259. end
  260. else
  261. if (keymatch(arg, '-grayscale', 3)) or
  262. (keymatch(arg, '-greyscale',3)) then
  263. { Force monochrome output. }
  264. cinfo^.out_color_space := JCS_GRAYSCALE
  265. else
  266. if (keymatch(arg, '-map', 4)) then
  267. begin
  268. { Quantize to a color map taken from an input file. }
  269. Inc(argn);
  270. if (argn >= argc) then { advance to next argument }
  271. usage;
  272. if (for_real) then
  273. begin { too expensive to do twice! }
  274. {$ifdef QUANT_2PASS_SUPPORTED} { otherwise can't quantize to supplied map }
  275. assign(mapfile, ParamStr(argn));
  276. {$push}{$I-}
  277. reset(mapfile, 1);
  278. {$pop}
  279. if (IOresult <> 0) then
  280. begin
  281. WriteLn(output, progname, ': can''t open ', ParamStr(argn));
  282. Halt(EXIT_FAILURE);
  283. end;
  284. read_color_map(cinfo, mapfile);
  285. system.close(mapfile);
  286. cinfo^.quantize_colors := TRUE;
  287. {$else}
  288. ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
  289. {$endif}
  290. end;
  291. end
  292. else
  293. if (keymatch(arg, '-maxmemory', 4)) then
  294. begin
  295. { Maximum memory in Kb (or Mb with 'm'). }
  296. ch := 'x';
  297. Inc(argn);
  298. if (argn >= argc) then { advance to next argument }
  299. usage;
  300. arg := ParamStr(argn);
  301. if (length(arg) > 1) and (arg[length(arg)] in ['m','M']) then
  302. begin
  303. ch := arg[length(arg)];
  304. arg := Copy(arg, 1, Length(arg)-1);
  305. end;
  306. Val(arg, lval, code);
  307. if (code <> 0) then
  308. usage;
  309. if (ch = 'm') or (ch = 'M') then
  310. lval := lval * long(1000);
  311. cinfo^.mem^.max_memory_to_use := lval * long(1000);
  312. end
  313. else
  314. if (keymatch(arg, '-nosmooth', 4)) then
  315. begin
  316. { Suppress fancy upsampling }
  317. cinfo^.do_fancy_upsampling := FALSE;
  318. end
  319. else
  320. if (keymatch(arg, '-onepass', 4)) then
  321. begin
  322. { Use fast one-pass quantization. }
  323. cinfo^.two_pass_quantize := FALSE;
  324. end
  325. else
  326. if (keymatch(arg, '-os2', 4)) then
  327. begin
  328. { BMP output format (OS/2 flavor). }
  329. requested_fmt := FMT_OS2;
  330. end
  331. else
  332. if (keymatch(arg, '-outfile', 5)) then
  333. begin
  334. { Set output file name. }
  335. Inc(argn);
  336. if (argn >= argc) then { advance to next argument }
  337. usage;
  338. outfilename := ParamStr(argn); { save it away for later use }
  339. end
  340. else
  341. if (keymatch(arg, '-pnm', 2)) or
  342. (keymatch(arg, '-ppm', 2)) then
  343. begin
  344. { PPM/PGM output format. }
  345. requested_fmt := FMT_PPM;
  346. end
  347. else
  348. if (keymatch(arg, '-rle', 2)) then
  349. begin
  350. { RLE output format. }
  351. requested_fmt := FMT_RLE;
  352. end
  353. else
  354. if (keymatch(arg, '-scale', 2)) then
  355. begin
  356. { Scale the output image by a fraction M/N. }
  357. Inc(argn);
  358. if (argn >= argc) then { advance to next argument }
  359. usage;
  360. arg := ParamStr(argn);
  361. Val(copy(arg, 1, Pos('/', arg)-1),
  362. cinfo^.scale_num, code);
  363. if code = 0 then
  364. Val(copy(arg, Pos('/', arg)+1,
  365. length(arg)-Pos('/', arg)),
  366. cinfo^.scale_denom, code);
  367. if code <> 0 then
  368. usage;
  369. end
  370. else
  371. if (keymatch(arg, '-targa', 2)) then
  372. begin
  373. { Targa output format. }
  374. requested_fmt := FMT_TARGA;
  375. end
  376. else
  377. usage; { bogus switch }
  378. end;
  379. parse_switches := argn; { return index of next arg (file name) }
  380. end;
  381. { Marker processor for COM and interesting APPn markers.
  382. This replaces the library's built-in processor, which just skips the marker.
  383. We want to print out the marker as text, to the extent possible.
  384. Note this code relies on a non-suspending data source. }
  385. {LOCAL}
  386. function jpeg_getc (cinfo : j_decompress_ptr) : char;
  387. { Read next byte }
  388. var
  389. datasrc : jpeg_source_mgr_ptr;
  390. begin
  391. datasrc := cinfo^.src;
  392. if (datasrc^.bytes_in_buffer = 0) then
  393. begin
  394. if (not datasrc^.fill_input_buffer (cinfo)) then
  395. ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND);
  396. end;
  397. Dec(datasrc^.bytes_in_buffer);
  398. jpeg_getc := char(GETJOCTET(datasrc^.next_input_byte^));
  399. Inc(datasrc^.next_input_byte);
  400. end;
  401. {METHODDEF}
  402. function print_text_marker (cinfo : j_decompress_ptr) : boolean; far;
  403. const
  404. LF = #10;
  405. CR = #13;
  406. var
  407. traceit : boolean;
  408. length : INT32;
  409. ch : char;
  410. lastch : char;
  411. begin
  412. traceit := (cinfo^.err^.trace_level >= 1);
  413. lastch := #0;
  414. length := byte(jpeg_getc(cinfo)) shl 8;
  415. Inc(length, byte(jpeg_getc(cinfo)));
  416. Dec(length, 2); { discount the length word itself }
  417. if (traceit) then
  418. begin
  419. if (cinfo^.unread_marker = JPEG_COM) then
  420. WriteLn('Comment, length ', long(length), ';')
  421. else { assume it is an APPn otherwise }
  422. WriteLn('APP', cinfo^.unread_marker - JPEG_APP0, ' length ',
  423. long(length),':');
  424. end;
  425. while (length > 0) do
  426. begin
  427. Dec(length);
  428. ch := jpeg_getc(cinfo);
  429. if (traceit) then
  430. begin
  431. { Emit the character in a readable form.
  432. Nonprintables are converted to \nnn form,
  433. while \ is converted to \\.
  434. Newlines in CR, CR/LF, or LF form will be printed as one newline. }
  435. if (ch = LF) then
  436. WriteLn(output)
  437. else
  438. if (ch = CR) then
  439. begin
  440. if (lastch <> LF) then
  441. WriteLn(output);
  442. end
  443. else
  444. if (ch >= ' ') and (ch <= #127) then
  445. Write(output, ch)
  446. else
  447. WriteLn(output, '\', byte(ch));
  448. lastch := ch;
  449. end;
  450. end;
  451. if (traceit) then
  452. WriteLn(output);
  453. print_text_marker := TRUE;
  454. end;
  455. { The main program. }
  456. var
  457. cinfo : jpeg_decompress_struct;
  458. jerr : jpeg_error_mgr;
  459. {$ifdef PROGRESS_REPORT}
  460. progress : cdjpeg_progress_mgr;
  461. {$endif}
  462. file_index : int;
  463. dest_mgr : djpeg_dest_ptr;
  464. input_file : FILE;
  465. output_file : FILE;
  466. num_scanlines : JDIMENSION;
  467. var
  468. argc : int;
  469. begin
  470. dest_mgr := NIL;
  471. argc := ParamCount;
  472. progname := ParamStr(0);
  473. { Initialize the JPEG decompression object with default error handling. }
  474. cinfo.err := jpeg_std_error(jerr);
  475. jpeg_create_decompress(@cinfo);
  476. { Add some application-specific error messages (from cderror.h) }
  477. {jerr.addon_message_table := cdjpeg_message_table;}
  478. jerr.first_addon_message := JMSG_FIRSTADDONCODE;
  479. jerr.last_addon_message := JMSG_LASTADDONCODE;
  480. { Insert custom marker processor for COM and APP12.
  481. APP12 is used by some digital camera makers for textual info,
  482. so we provide the ability to display it as text.
  483. If you like, additional APPn marker types can be selected for display,
  484. but don't try to override APP0 or APP14 this way (see libjpeg.doc). }
  485. jpeg_set_marker_processor(@cinfo, JPEG_COM, print_text_marker);
  486. jpeg_set_marker_processor(@cinfo, JPEG_APP0+12, print_text_marker);
  487. { Now safe to enable signal catcher. }
  488. {$ifdef NEED_SIGNAL_CATCHER}
  489. enable_signal_catcher(j_common_ptr (@cinfo));
  490. {$endif}
  491. { Scan command line to find file names. }
  492. { It is convenient to use just one switch-parsing routine, but the switch
  493. values read here are ignored; we will rescan the switches after opening
  494. the input file.
  495. (Exception: tracing level set here controls verbosity for COM markers
  496. found during jpeg_read_header...) }
  497. file_index := parse_switches(@cinfo, 0, FALSE);
  498. {$ifdef TWO_FILE_COMMANDLINE}
  499. { Must have either -outfile switch or explicit output file name }
  500. if (outfilename = '') then
  501. begin
  502. if (file_index <> argc-1) then
  503. begin
  504. WriteLn(output, progname, ': must name one input and one output file');
  505. usage;
  506. end;
  507. outfilename := ParamStr(file_index+1);
  508. end
  509. else
  510. begin
  511. if (file_index <> argc) then
  512. begin
  513. WriteLn(output, progname, ': must name one input and one output file');
  514. usage;
  515. end;
  516. end;
  517. {$else}
  518. { Unix style: expect zero or one file name }
  519. if (file_index < argc-1) then
  520. begin
  521. WriteLn(output, progname, ': only one input file');
  522. usage;
  523. end;
  524. {$endif} { TWO_FILE_COMMANDLINE }
  525. { Open the input file. }
  526. if (file_index < argc) then
  527. begin
  528. assign(input_file, ParamStr(file_index));
  529. {$push}{$I-}
  530. Reset(input_file, 1);
  531. {$pop}
  532. if (IOresult <> 0) then
  533. begin
  534. WriteLn(output, progname, ': can''t open ', ParamStr(file_index));
  535. Halt(EXIT_FAILURE);
  536. end;
  537. end
  538. else
  539. begin
  540. { default input file is stdin }
  541. Assign(input_file, '');
  542. Reset(input_file, 1);
  543. end;
  544. { Open the output file. }
  545. if (outfilename <> '') then
  546. begin
  547. assign(output_file, outfilename);
  548. {$push}{$I-}
  549. rewrite(output_file, 1);
  550. {$pop}
  551. if (IOresult <> 0) then
  552. begin
  553. WriteLn(output, progname, ': can''t open ', outfilename);
  554. Halt(EXIT_FAILURE);
  555. end;
  556. end
  557. else
  558. begin
  559. { default output file is stdout }
  560. assign(output_file, '');
  561. rewrite(output_file, 1);
  562. end;
  563. {$ifdef PROGRESS_REPORT}
  564. start_progress_monitor(j_common_ptr (@cinfo), @progress);
  565. {$endif}
  566. { Specify data source for decompression }
  567. jpeg_stdio_src(@cinfo, @input_file);
  568. { Read file header, set default decompression parameters }
  569. {void} jpeg_read_header(@cinfo, TRUE);
  570. { Adjust default decompression parameters by re-parsing the options }
  571. file_index := parse_switches(@cinfo, 0, TRUE);
  572. { Initialize the output module now to let it override any crucial
  573. option settings (for instance, GIF wants to force color quantization). }
  574. case (requested_fmt) of
  575. {$ifdef BMP_SUPPORTED}
  576. FMT_BMP:
  577. dest_mgr := jinit_write_bmp(@cinfo, FALSE);
  578. FMT_OS2:
  579. dest_mgr := jinit_write_bmp(@cinfo, TRUE);
  580. {$endif}
  581. {$ifdef GIF_SUPPORTED}
  582. FMT_GIF:
  583. dest_mgr := jinit_write_gif(@cinfo);
  584. {$endif}
  585. {$ifdef PPM_SUPPORTED}
  586. FMT_PPM:
  587. dest_mgr := jinit_write_ppm(@cinfo);
  588. {$endif}
  589. {$ifdef RLE_SUPPORTED}
  590. FMT_RLE:
  591. dest_mgr := jinit_write_rle(@cinfo);
  592. {$endif}
  593. {$ifdef TARGA_SUPPORTED}
  594. FMT_TARGA:
  595. dest_mgr := jinit_write_targa(@cinfo);
  596. {$endif}
  597. else
  598. ERREXIT(j_common_ptr(@cinfo), JERR_UNSUPPORTED_FORMAT);
  599. end;
  600. dest_mgr^.output_file := @output_file;
  601. { Start decompressor }
  602. {void} jpeg_start_decompress(@cinfo);
  603. { Write output file header }
  604. dest_mgr^.start_output (@cinfo, dest_mgr);
  605. { Process data }
  606. while (cinfo.output_scanline < cinfo.output_height) do
  607. begin
  608. num_scanlines := jpeg_read_scanlines(@cinfo, dest_mgr^.buffer,
  609. dest_mgr^.buffer_height);
  610. dest_mgr^.put_pixel_rows (@cinfo, dest_mgr, num_scanlines);
  611. end;
  612. {$ifdef PROGRESS_REPORT}
  613. { Hack: count final pass as done in case finish_output does an extra pass.
  614. The library won't have updated completed_passes. }
  615. progress.pub.completed_passes := progress.pub.total_passes;
  616. {$endif}
  617. { Finish decompression and release memory.
  618. I must do it in this order because output module has allocated memory
  619. of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. }
  620. dest_mgr^.finish_output (@cinfo, dest_mgr);
  621. {void} jpeg_finish_decompress(@cinfo);
  622. jpeg_destroy_decompress(@cinfo);
  623. { Close files, if we opened them }
  624. system.close(input_file);
  625. system.close(output_file);
  626. {$ifdef PROGRESS_REPORT}
  627. end_progress_monitor(j_common_ptr (@cinfo));
  628. {$endif}
  629. { All done. }
  630. if jerr.num_warnings <> 0 then
  631. Halt(EXIT_WARNING)
  632. else
  633. Halt(EXIT_SUCCESS);
  634. end.