home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume34 / jpeg / part08 < prev    next >
Encoding:
Text File  |  1992-12-16  |  57.5 KB  |  1,483 lines

  1. Newsgroups: comp.sources.misc
  2. From: jpeg-info@uunet.uu.net (Independent JPEG Group)
  3. Subject:  v34i062:  jpeg - JPEG image compression, Part08/18
  4. Message-ID: <1992Dec17.041824.23623@sparky.imd.sterling.com>
  5. X-Md4-Signature: 0589d14067732f495aaa5197d4afa5f6
  6. Date: Thu, 17 Dec 1992 04:18:24 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jpeg-info@uunet.uu.net (Independent JPEG Group)
  10. Posting-number: Volume 34, Issue 62
  11. Archive-name: jpeg/part08
  12. Environment: UNIX, VMS, MS-DOS, Mac, Amiga, Atari, Cray
  13. Supersedes: jpeg: Volume 29, Issue 1-18
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  example.c jcarith.c jcpipe.c
  20. # Wrapped by kent@sparky on Wed Dec 16 20:52:27 1992
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 8 (of 18)."'
  24. if test -f 'example.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'example.c'\"
  26. else
  27.   echo shar: Extracting \"'example.c'\" \(26879 characters\)
  28.   sed "s/^X//" >'example.c' <<'END_OF_FILE'
  29. X/*
  30. X * example.c
  31. X *
  32. X * This file is not actually part of the JPEG software.  Rather, it provides
  33. X * a skeleton that may be useful for constructing applications that use the
  34. X * JPEG software as subroutines.  This code will NOT do anything useful as is.
  35. X *
  36. X * This file illustrates how to use the JPEG code as a subroutine library
  37. X * to read or write JPEG image files.  We assume here that you are not
  38. X * merely interested in converting the image to yet another image file format
  39. X * (if you are, you should be adding another I/O module to cjpeg/djpeg, not
  40. X * constructing a new application).  Instead, we show how to pass the
  41. X * decompressed image data into or out of routines that you provide.  For
  42. X * example, a viewer program might use the JPEG decompressor together with
  43. X * routines that write the decompressed image directly to a display.
  44. X *
  45. X * We present these routines in the same coding style used in the JPEG code
  46. X * (ANSI function definitions, etc); but you are of course free to code your
  47. X * routines in a different style if you prefer.
  48. X */
  49. X
  50. X/*
  51. X * Include file for declaring JPEG data structures.
  52. X * This file also includes some system headers like <stdio.h>;
  53. X * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
  54. X */
  55. X
  56. X#include "jinclude.h"
  57. X
  58. X/*
  59. X * <setjmp.h> is used for the optional error recovery mechanism shown in
  60. X * the second part of the example.
  61. X */
  62. X
  63. X#include <setjmp.h>
  64. X
  65. X
  66. X
  67. X/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
  68. X
  69. X/* This half of the example shows how to feed data into the JPEG compressor.
  70. X * We present a minimal version that does not worry about refinements such
  71. X * as error recovery (the JPEG code will just exit() if it gets an error).
  72. X */
  73. X
  74. X
  75. X/*
  76. X * To supply the image data for compression, you must define three routines
  77. X * input_init, get_input_row, and input_term.  These routines will be called
  78. X * from the JPEG compressor via function pointer values that you store in the
  79. X * cinfo data structure; hence they need not be globally visible and the exact
  80. X * names don't matter.  (In fact, the "METHODDEF" macro expands to "static" if
  81. X * you use the unmodified JPEG include files.)
  82. X *
  83. X * The input file reading modules (jrdppm.c, jrdgif.c, jrdtarga.c, etc) may be
  84. X * useful examples of what these routines should actually do, although each of
  85. X * them is encrusted with a lot of specialized code for its own file format.
  86. X */
  87. X
  88. X
  89. XMETHODDEF void
  90. Xinput_init (compress_info_ptr cinfo)
  91. X/* Initialize for input; return image size and component data. */
  92. X{
  93. X  /* This routine must return five pieces of information about the incoming
  94. X   * image, and must do any setup needed for the get_input_row routine.
  95. X   * The image information is returned in fields of the cinfo struct.
  96. X   * (If you don't care about modularity, you could initialize these fields
  97. X   * in the main JPEG calling routine, and make this routine be a no-op.)
  98. X   * We show some example values here.
  99. X   */
  100. X  cinfo->image_width = 640;        /* width in pixels */
  101. X  cinfo->image_height = 480;        /* height in pixels */
  102. X  /* JPEG views an image as being a rectangular array of pixels, with each
  103. X   * pixel having the same number of "component" values (color channels).
  104. X   * You must specify how many components there are and the colorspace
  105. X   * interpretation of the components.  Most applications will use RGB data or
  106. X   * grayscale data.  If you want to use something else, you'll need to study
  107. X   * and perhaps modify jcdeflts.c, jccolor.c, and jdcolor.c.
  108. X   */
  109. X  cinfo->input_components = 3;        /* or 1 for grayscale */
  110. X  cinfo->in_color_space = CS_RGB;    /* or CS_GRAYSCALE for grayscale */
  111. X  cinfo->data_precision = 8;        /* bits per pixel component value */
  112. X  /* In the current JPEG software, data_precision must be set equal to
  113. X   * BITS_IN_JSAMPLE, which is 8 unless you twiddle jconfig.h.  Future
  114. X   * versions might allow you to say either 8 or 12 if compiled with
  115. X   * 12-bit JSAMPLEs, or up to 16 in lossless mode.  In any case,
  116. X   * it is up to you to scale incoming pixel values to the range
  117. X   *   0 .. (1<<data_precision)-1.
  118. X   * If your image data format is fixed at a byte per component,
  119. X   * then saying "8" is probably the best long-term solution.
  120. X   */
  121. X}
  122. X
  123. X
  124. X/*
  125. X * This function is called repeatedly and must supply the next row of pixels
  126. X * on each call.  The rows MUST be returned in top-to-bottom order if you want
  127. X * your JPEG files to be compatible with everyone else's.  (If you cannot
  128. X * readily read your data in that order, you'll need an intermediate array to
  129. X * hold the image.  See jrdtarga.c or jrdrle.c for examples of handling
  130. X * bottom-to-top source data using the JPEG code's portable mechanisms.)
  131. X * The data is to be returned into a 2-D array of JSAMPLEs, indexed as
  132. X *        JSAMPLE pixel_row[component][column]
  133. X * where component runs from 0 to cinfo->input_components-1, and column runs
  134. X * from 0 to cinfo->image_width-1 (column 0 is left edge of image).  Note that
  135. X * this is actually an array of pointers to arrays rather than a true 2D array,
  136. X * since C does not support variable-size multidimensional arrays.
  137. X * JSAMPLE is typically typedef'd as "unsigned char".
  138. X */
  139. X
  140. X
  141. XMETHODDEF void
  142. Xget_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  143. X/* Read next row of pixels into pixel_row[][] */
  144. X{
  145. X  /* This example shows how you might read RGB data (3 components)
  146. X   * from an input file in which the data is stored 3 bytes per pixel
  147. X   * in left-to-right, top-to-bottom order.
  148. X   */
  149. X  register FILE * infile = cinfo->input_file;
  150. X  register JSAMPROW ptr0, ptr1, ptr2;
  151. X  register long col;
  152. X  
  153. X  ptr0 = pixel_row[0];
  154. X  ptr1 = pixel_row[1];
  155. X  ptr2 = pixel_row[2];
  156. X  for (col = 0; col < cinfo->image_width; col++) {
  157. X    *ptr0++ = (JSAMPLE) getc(infile); /* red */
  158. X    *ptr1++ = (JSAMPLE) getc(infile); /* green */
  159. X    *ptr2++ = (JSAMPLE) getc(infile); /* blue */
  160. X  }
  161. X}
  162. X
  163. X
  164. XMETHODDEF void
  165. Xinput_term (compress_info_ptr cinfo)
  166. X/* Finish up at the end of the input */
  167. X{
  168. X  /* This termination routine will very often have no work to do, */
  169. X  /* but you must provide it anyway. */
  170. X  /* Note that the JPEG code will only call it during successful exit; */
  171. X  /* if you want it called during error exit, you gotta do that yourself. */
  172. X}
  173. X
  174. X
  175. X/*
  176. X * That's it for the routines that deal with reading the input image data.
  177. X * Now we have overall control and parameter selection routines.
  178. X */
  179. X
  180. X
  181. X/*
  182. X * This routine must determine what output JPEG file format is to be written,
  183. X * and make any other compression parameter changes that are desirable.
  184. X * This routine gets control after the input file header has been read
  185. X * (i.e., right after input_init has been called).  You could combine its
  186. X * functions into input_init, or even into the main control routine, but
  187. X * if you have several different input_init routines, it's a definite win
  188. X * to keep this separate.  You MUST supply this routine even if it's a no-op.
  189. X */
  190. X
  191. XMETHODDEF void
  192. Xc_ui_method_selection (compress_info_ptr cinfo)
  193. X{
  194. X  /* If the input is gray scale, generate a monochrome JPEG file. */
  195. X  if (cinfo->in_color_space == CS_GRAYSCALE)
  196. X    j_monochrome_default(cinfo);
  197. X  /* For now, always select JFIF output format. */
  198. X  jselwjfif(cinfo);
  199. X}
  200. X
  201. X
  202. X/*
  203. X * OK, here is the main function that actually causes everything to happen.
  204. X * We assume here that the target filename is supplied by the caller of this
  205. X * routine, and that all JPEG compression parameters can be default values.
  206. X */
  207. X
  208. XGLOBAL void
  209. Xwrite_JPEG_file (char * filename)
  210. X{
  211. X  /* These three structs contain JPEG parameters and working data.
  212. X   * They must survive for the duration of parameter setup and one
  213. X   * call to jpeg_compress; typically, making them local data in the
  214. X   * calling routine is the best strategy.
  215. X   */
  216. X  struct Compress_info_struct cinfo;
  217. X  struct Compress_methods_struct c_methods;
  218. X  struct External_methods_struct e_methods;
  219. X
  220. X  /* Initialize the system-dependent method pointers. */
  221. X  cinfo.methods = &c_methods;    /* links to method structs */
  222. X  cinfo.emethods = &e_methods;
  223. X  /* Here we use the default JPEG error handler, which will just print
  224. X   * an error message on stderr and call exit().  See the second half of
  225. X   * this file for an example of more graceful error recovery.
  226. X   */
  227. X  jselerror(&e_methods);    /* select std error/trace message routines */
  228. X  /* Here we use the standard memory manager provided with the JPEG code.
  229. X   * In some cases you might want to replace the memory manager, or at
  230. X   * least the system-dependent part of it, with your own code.
  231. X   */
  232. X  jselmemmgr(&e_methods);    /* select std memory allocation routines */
  233. X  /* If the compressor requires full-image buffers (for entropy-coding
  234. X   * optimization or a noninterleaved JPEG file), it will create temporary
  235. X   * files for anything that doesn't fit within the maximum-memory setting.
  236. X   * (Note that temp files are NOT needed if you use the default parameters.)
  237. X   * You can change the default maximum-memory setting by changing
  238. X   * e_methods.max_memory_to_use after jselmemmgr returns.
  239. X   * On some systems you may also need to set up a signal handler to
  240. X   * ensure that temporary files are deleted if the program is interrupted.
  241. X   * (This is most important if you are on MS-DOS and use the jmemdos.c
  242. X   * memory manager back end; it will try to grab extended memory for
  243. X   * temp files, and that space will NOT be freed automatically.)
  244. X   * See jcmain.c or jdmain.c for an example signal handler.
  245. X   */
  246. X
  247. X  /* Here, set up pointers to your own routines for input data handling
  248. X   * and post-init parameter selection.
  249. X   */
  250. X  c_methods.input_init = input_init;
  251. X  c_methods.get_input_row = get_input_row;
  252. X  c_methods.input_term = input_term;
  253. X  c_methods.c_ui_method_selection = c_ui_method_selection;
  254. X
  255. X  /* Set up default JPEG parameters in the cinfo data structure. */
  256. X  j_c_defaults(&cinfo, 75, FALSE);
  257. X  /* Note: 75 is the recommended default quality level; you may instead pass
  258. X   * a user-specified quality level.  Be aware that values below 25 will cause
  259. X   * non-baseline JPEG files to be created (and a warning message to that
  260. X   * effect to be emitted on stderr).  This won't bother our decoder, but some
  261. X   * commercial JPEG implementations may choke on non-baseline JPEG files.
  262. X   * If you want to force baseline compatibility, pass TRUE instead of FALSE.
  263. X   * (If non-baseline files are fine, but you could do without that warning
  264. X   * message, set e_methods.trace_level to -1.)
  265. X   */
  266. X
  267. X  /* At this point you can modify the default parameters set by j_c_defaults
  268. X   * as needed.  For a minimal implementation, you shouldn't need to change
  269. X   * anything.  See jcmain.c for some examples of what you might change.
  270. X   */
  271. X
  272. X  /* Select the input and output files.
  273. X   * Note that cinfo.input_file is only used if your input reading routines
  274. X   * use it; otherwise, you can just make it NULL.
  275. X   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  276. X   * requires it in order to write binary files.
  277. X   */
  278. X
  279. X  cinfo.input_file = NULL;    /* if no actual input file involved */
  280. X
  281. X  if ((cinfo.output_file = fopen(filename, "wb")) == NULL) {
  282. X    fprintf(stderr, "can't open %s\n", filename);
  283. X    exit(1);
  284. X  }
  285. X
  286. X  /* Here we go! */
  287. X  jpeg_compress(&cinfo);
  288. X
  289. X  /* That's it, son.  Nothin' else to do, except close files. */
  290. X  /* Here we assume only the output file need be closed. */
  291. X  fclose(cinfo.output_file);
  292. X
  293. X  /* Note: if you want to compress more than one image, we recommend you
  294. X   * repeat this whole routine.  You MUST repeat the j_c_defaults()/alter
  295. X   * parameters/jpeg_compress() sequence, as some data structures allocated
  296. X   * in j_c_defaults are freed upon exit from jpeg_compress.
  297. X   */
  298. X}
  299. X
  300. X
  301. X
  302. X/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
  303. X
  304. X/* This half of the example shows how to read data from the JPEG decompressor.
  305. X * It's a little more refined than the above in that we show how to do your
  306. X * own error recovery.  If you don't care about that, you don't need these
  307. X * next two routines.
  308. X */
  309. X
  310. X
  311. X/*
  312. X * These routines replace the default trace/error routines included with the
  313. X * JPEG code.  The example trace_message routine shown here is actually the
  314. X * same as the standard one, but you could modify it if you don't want messages
  315. X * sent to stderr.  The example error_exit routine is set up to return
  316. X * control to read_JPEG_file() rather than calling exit().  You can use the
  317. X * same routines for both compression and decompression error recovery.
  318. X */
  319. X
  320. X/* These static variables are needed by the error routines. */
  321. Xstatic jmp_buf setjmp_buffer;    /* for return to caller */
  322. Xstatic external_methods_ptr emethods; /* needed for access to message_parm */
  323. X
  324. X
  325. X/* This routine is used for any and all trace, debug, or error printouts
  326. X * from the JPEG code.  The parameter is a printf format string; up to 8
  327. X * integer data values for the format string have been stored in the
  328. X * message_parm[] field of the external_methods struct.
  329. X */
  330. X
  331. XMETHODDEF void
  332. Xtrace_message (const char *msgtext)
  333. X{
  334. X  fprintf(stderr, msgtext,
  335. X      emethods->message_parm[0], emethods->message_parm[1],
  336. X      emethods->message_parm[2], emethods->message_parm[3],
  337. X      emethods->message_parm[4], emethods->message_parm[5],
  338. X      emethods->message_parm[6], emethods->message_parm[7]);
  339. X  fprintf(stderr, "\n");    /* there is no \n in the format string! */
  340. X}
  341. X
  342. X/*
  343. X * The error_exit() routine should not return to its caller.  The default
  344. X * routine calls exit(), but here we assume that we want to return to
  345. X * read_JPEG_file, which has set up a setjmp context for the purpose.
  346. X * You should make sure that the free_all method is called, either within
  347. X * error_exit or after the return to the outer-level routine.
  348. X */
  349. X
  350. XMETHODDEF void
  351. Xerror_exit (const char *msgtext)
  352. X{
  353. X  trace_message(msgtext);    /* report the error message */
  354. X  (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  355. X  longjmp(setjmp_buffer, 1);    /* return control to outer routine */
  356. X}
  357. X
  358. X
  359. X
  360. X/*
  361. X * To accept the image data from decompression, you must define four routines
  362. X * output_init, put_color_map, put_pixel_rows, and output_term.
  363. X *
  364. X * You must understand the distinction between full color output mode
  365. X * (N independent color components) and colormapped output mode (a single
  366. X * output component representing an index into a color map).  You should use
  367. X * colormapped mode to write to a colormapped display screen or output file.
  368. X * Colormapped mode is also useful for reducing grayscale output to a small
  369. X * number of gray levels: when using the 1-pass quantizer on grayscale data,
  370. X * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
  371. X * can regard the indexes are directly representing gray levels at reduced
  372. X * precision.  In any other case, you should not depend on the colormap
  373. X * entries having any particular order.
  374. X * To get colormapped output, set cinfo->quantize_colors to TRUE and set
  375. X * cinfo->desired_number_of_colors to the maximum number of entries in the
  376. X * colormap.  This can be done either in your main routine or in
  377. X * d_ui_method_selection.  For grayscale quantization, also set
  378. X * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
  379. X * (presently this is the default, but it may not be so in the future).
  380. X *
  381. X * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
  382. X * useful examples of what these routines should actually do, although each of
  383. X * them is encrusted with a lot of specialized code for its own file format.
  384. X */
  385. X
  386. X
  387. XMETHODDEF void
  388. Xoutput_init (decompress_info_ptr cinfo)
  389. X/* This routine should do any setup required */
  390. X{
  391. X  /* This routine can initialize for output based on the data passed in cinfo.
  392. X   * Useful fields include:
  393. X   *    image_width, image_height    Pretty obvious, I hope.
  394. X   *    data_precision            bits per pixel value; typically 8.
  395. X   *    out_color_space            output colorspace previously requested
  396. X   *    color_out_comps            number of color components in same
  397. X   *    final_out_comps            number of components actually output
  398. X   * final_out_comps is 1 if quantize_colors is true, else it is equal to
  399. X   * color_out_comps.
  400. X   *
  401. X   * If you have requested color quantization, the colormap is NOT yet set.
  402. X   * You may wish to defer output initialization until put_color_map is called.
  403. X   */
  404. X}
  405. X
  406. X
  407. X/*
  408. X * This routine is called if and only if you have set cinfo->quantize_colors
  409. X * to TRUE.  It is given the selected colormap and can complete any required
  410. X * initialization.  This call will occur after output_init and before any
  411. X * calls to put_pixel_rows.  Note that the colormap pointer is also placed
  412. X * in a cinfo field, whence it can be used by put_pixel_rows or output_term.
  413. X * num_colors will be less than or equal to desired_number_of_colors.
  414. X *
  415. X * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
  416. X *        JSAMPLE colormap[component][indexvalue]
  417. X * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
  418. X * runs from 0 to num_colors-1.  Note that this is actually an array of
  419. X * pointers to arrays rather than a true 2D array, since C does not support
  420. X * variable-size multidimensional arrays.
  421. X * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  422. X * to be as portable as the JPEG code proper, you should always access JSAMPLE
  423. X * values with the GETJSAMPLE() macro, which will do the right thing if the
  424. X * machine has only signed chars.
  425. X */
  426. X
  427. XMETHODDEF void
  428. Xput_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  429. X/* Write the color map */
  430. X{
  431. X  /* You need not provide this routine if you always set cinfo->quantize_colors
  432. X   * FALSE; but a safer practice is to provide it and have it just print an
  433. X   * error message, like this:
  434. X   */
  435. X  fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n");
  436. X}
  437. X
  438. X
  439. X/*
  440. X * This function is called repeatedly, with a few more rows of pixels supplied
  441. X * on each call.  With the current JPEG code, some multiple of 8 rows will be
  442. X * passed on each call except the last, but it is extremely bad form to depend
  443. X * on this.  You CAN assume num_rows > 0.
  444. X * The data is supplied in top-to-bottom row order (the standard order within
  445. X * a JPEG file).  If you cannot readily use the data in that order, you'll
  446. X * need an intermediate array to hold the image.  See jwrrle.c for an example
  447. X * of outputting data in bottom-to-top order.
  448. X *
  449. X * The data is supplied as a 3-D array of JSAMPLEs, indexed as
  450. X *        JSAMPLE pixel_data[component][row][column]
  451. X * where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
  452. X * num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
  453. X * left edge of image).  Note that this is actually an array of pointers to
  454. X * pointers to arrays rather than a true 3D array, since C does not support
  455. X * variable-size multidimensional arrays.
  456. X * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  457. X * to be as portable as the JPEG code proper, you should always access JSAMPLE
  458. X * values with the GETJSAMPLE() macro, which will do the right thing if the
  459. X * machine has only signed chars.
  460. X *
  461. X * If quantize_colors is true, then there is only one component, and its values
  462. X * are indexes into the previously supplied colormap.  Otherwise the values
  463. X * are actual data in your selected output colorspace.
  464. X */
  465. X
  466. X
  467. XMETHODDEF void
  468. Xput_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)
  469. X/* Write some rows of output data */
  470. X{
  471. X  /* This example shows how you might write full-color RGB data (3 components)
  472. X   * to an output file in which the data is stored 3 bytes per pixel.
  473. X   */
  474. X  register FILE * outfile = cinfo->output_file;
  475. X  register JSAMPROW ptr0, ptr1, ptr2;
  476. X  register long col;
  477. X  register int row;
  478. X  
  479. X  for (row = 0; row < num_rows; row++) {
  480. X    ptr0 = pixel_data[0][row];
  481. X    ptr1 = pixel_data[1][row];
  482. X    ptr2 = pixel_data[2][row];
  483. X    for (col = 0; col < cinfo->image_width; col++) {
  484. X      putc(GETJSAMPLE(*ptr0), outfile);    /* red */
  485. X      ptr0++;
  486. X      putc(GETJSAMPLE(*ptr1), outfile);    /* green */
  487. X      ptr1++;
  488. X      putc(GETJSAMPLE(*ptr2), outfile);    /* blue */
  489. X      ptr2++;
  490. X    }
  491. X  }
  492. X}
  493. X
  494. X
  495. XMETHODDEF void
  496. Xoutput_term (decompress_info_ptr cinfo)
  497. X/* Finish up at the end of the output */
  498. X{
  499. X  /* This termination routine may not need to do anything. */
  500. X  /* Note that the JPEG code will only call it during successful exit; */
  501. X  /* if you want it called during error exit, you gotta do that yourself. */
  502. X}
  503. X
  504. X
  505. X/*
  506. X * That's it for the routines that deal with writing the output image.
  507. X * Now we have overall control and parameter selection routines.
  508. X */
  509. X
  510. X
  511. X/*
  512. X * This routine gets control after the JPEG file header has been read;
  513. X * at this point the image size and colorspace are known.
  514. X * The routine must determine what output routines are to be used, and make
  515. X * any decompression parameter changes that are desirable.  For example,
  516. X * if it is found that the JPEG file is grayscale, you might want to do
  517. X * things differently than if it is color.  You can also delay setting
  518. X * quantize_colors and associated options until this point. 
  519. X *
  520. X * j_d_defaults initializes out_color_space to CS_RGB.  If you want grayscale
  521. X * output you should set out_color_space to CS_GRAYSCALE.  Note that you can
  522. X * force grayscale output from a color JPEG file (though not vice versa).
  523. X */
  524. X
  525. XMETHODDEF void
  526. Xd_ui_method_selection (decompress_info_ptr cinfo)
  527. X{
  528. X  /* if grayscale input, force grayscale output; */
  529. X  /* else leave the output colorspace as set by main routine. */
  530. X  if (cinfo->jpeg_color_space == CS_GRAYSCALE)
  531. X    cinfo->out_color_space = CS_GRAYSCALE;
  532. X
  533. X  /* select output routines */
  534. X  cinfo->methods->output_init = output_init;
  535. X  cinfo->methods->put_color_map = put_color_map;
  536. X  cinfo->methods->put_pixel_rows = put_pixel_rows;
  537. X  cinfo->methods->output_term = output_term;
  538. X}
  539. X
  540. X
  541. X/*
  542. X * OK, here is the main function that actually causes everything to happen.
  543. X * We assume here that the JPEG filename is supplied by the caller of this
  544. X * routine, and that all decompression parameters can be default values.
  545. X * The routine returns 1 if successful, 0 if not.
  546. X */
  547. X
  548. XGLOBAL int
  549. Xread_JPEG_file (char * filename)
  550. X{
  551. X  /* These three structs contain JPEG parameters and working data.
  552. X   * They must survive for the duration of parameter setup and one
  553. X   * call to jpeg_decompress; typically, making them local data in the
  554. X   * calling routine is the best strategy.
  555. X   */
  556. X  struct Decompress_info_struct cinfo;
  557. X  struct Decompress_methods_struct dc_methods;
  558. X  struct External_methods_struct e_methods;
  559. X
  560. X  /* Select the input and output files.
  561. X   * In this example we want to open the input file before doing anything else,
  562. X   * so that the setjmp() error recovery below can assume the file is open.
  563. X   * Note that cinfo.output_file is only used if your output handling routines
  564. X   * use it; otherwise, you can just make it NULL.
  565. X   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  566. X   * requires it in order to read binary files.
  567. X   */
  568. X
  569. X  if ((cinfo.input_file = fopen(filename, "rb")) == NULL) {
  570. X    fprintf(stderr, "can't open %s\n", filename);
  571. X    return 0;
  572. X  }
  573. X
  574. X  cinfo.output_file = NULL;    /* if no actual output file involved */
  575. X
  576. X  /* Initialize the system-dependent method pointers. */
  577. X  cinfo.methods = &dc_methods;    /* links to method structs */
  578. X  cinfo.emethods = &e_methods;
  579. X  /* Here we supply our own error handler; compare to use of standard error
  580. X   * handler in the previous write_JPEG_file example.
  581. X   */
  582. X  emethods = &e_methods;    /* save struct addr for possible access */
  583. X  e_methods.error_exit = error_exit; /* supply error-exit routine */
  584. X  e_methods.trace_message = trace_message; /* supply trace-message routine */
  585. X  e_methods.trace_level = 0;    /* default = no tracing */
  586. X  e_methods.num_warnings = 0;    /* no warnings emitted yet */
  587. X  e_methods.first_warning_level = 0; /* display first corrupt-data warning */
  588. X  e_methods.more_warning_level = 3; /* but suppress additional ones */
  589. X
  590. X  /* prepare setjmp context for possible exit from error_exit */
  591. X  if (setjmp(setjmp_buffer)) {
  592. X    /* If we get here, the JPEG code has signaled an error.
  593. X     * Memory allocation has already been cleaned up (see free_all call in
  594. X     * error_exit), but we need to close the input file before returning.
  595. X     * You might also need to close an output file, etc.
  596. X     */
  597. X    fclose(cinfo.input_file);
  598. X    return 0;
  599. X  }
  600. X
  601. X  /* Here we use the standard memory manager provided with the JPEG code.
  602. X   * In some cases you might want to replace the memory manager, or at
  603. X   * least the system-dependent part of it, with your own code.
  604. X   */
  605. X  jselmemmgr(&e_methods);    /* select std memory allocation routines */
  606. X  /* If the decompressor requires full-image buffers (for two-pass color
  607. X   * quantization or a noninterleaved JPEG file), it will create temporary
  608. X   * files for anything that doesn't fit within the maximum-memory setting.
  609. X   * You can change the default maximum-memory setting by changing
  610. X   * e_methods.max_memory_to_use after jselmemmgr returns.
  611. X   * On some systems you may also need to set up a signal handler to
  612. X   * ensure that temporary files are deleted if the program is interrupted.
  613. X   * (This is most important if you are on MS-DOS and use the jmemdos.c
  614. X   * memory manager back end; it will try to grab extended memory for
  615. X   * temp files, and that space will NOT be freed automatically.)
  616. X   * See jcmain.c or jdmain.c for an example signal handler.
  617. X   */
  618. X
  619. X  /* Here, set up the pointer to your own routine for post-header-reading
  620. X   * parameter selection.  You could also initialize the pointers to the
  621. X   * output data handling routines here, if they are not dependent on the
  622. X   * image type.
  623. X   */
  624. X  dc_methods.d_ui_method_selection = d_ui_method_selection;
  625. X
  626. X  /* Set up default decompression parameters. */
  627. X  j_d_defaults(&cinfo, TRUE);
  628. X  /* TRUE indicates that an input buffer should be allocated.
  629. X   * In unusual cases you may want to allocate the input buffer yourself;
  630. X   * see jddeflts.c for commentary.
  631. X   */
  632. X
  633. X  /* At this point you can modify the default parameters set by j_d_defaults
  634. X   * as needed; for example, you can request color quantization or force
  635. X   * grayscale output.  See jdmain.c for examples of what you might change.
  636. X   */
  637. X
  638. X  /* Set up to read a JFIF or baseline-JPEG file. */
  639. X  /* This is the only JPEG file format currently supported. */
  640. X  jselrjfif(&cinfo);
  641. X
  642. X  /* Here we go! */
  643. X  jpeg_decompress(&cinfo);
  644. X
  645. X  /* That's it, son.  Nothin' else to do, except close files. */
  646. X  /* Here we assume only the input file need be closed. */
  647. X  fclose(cinfo.input_file);
  648. X
  649. X  /* You might want to test e_methods.num_warnings to see if bad data was
  650. X   * detected.  In this example, we just blindly forge ahead.
  651. X   */
  652. X  return 1;            /* indicate success */
  653. X
  654. X  /* Note: if you want to decompress more than one image, we recommend you
  655. X   * repeat this whole routine.  You MUST repeat the j_d_defaults()/alter
  656. X   * parameters/jpeg_decompress() sequence, as some data structures allocated
  657. X   * in j_d_defaults are freed upon exit from jpeg_decompress.
  658. X   */
  659. X}
  660. END_OF_FILE
  661.   if test 26879 -ne `wc -c <'example.c'`; then
  662.     echo shar: \"'example.c'\" unpacked with wrong size!
  663.   fi
  664.   # end of 'example.c'
  665. fi
  666. if test -f 'jcarith.c' -a "${1}" != "-c" ; then 
  667.   echo shar: Will not clobber existing file \"'jcarith.c'\"
  668. else
  669.   echo shar: Extracting \"'jcarith.c'\" \(1164 characters\)
  670.   sed "s/^X//" >'jcarith.c' <<'END_OF_FILE'
  671. X/*
  672. X * jcarith.c
  673. X *
  674. X * Copyright (C) 1991, 1992, Thomas G. Lane.
  675. X * This file is part of the Independent JPEG Group's software.
  676. X * For conditions of distribution and use, see the accompanying README file.
  677. X *
  678. X * This file contains arithmetic entropy encoding routines.
  679. X * These routines are invoked via the methods entropy_encode,
  680. X * entropy_encode_init/term, and entropy_optimize.
  681. X */
  682. X
  683. X#include "jinclude.h"
  684. X
  685. X#ifdef C_ARITH_CODING_SUPPORTED
  686. X
  687. X
  688. X/*
  689. X * The arithmetic coding option of the JPEG standard specifies Q-coding,
  690. X * which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
  691. X * At this time it does not appear to be legal for the Independent JPEG
  692. X * Group to distribute software that implements arithmetic coding.
  693. X * We have therefore removed arithmetic coding support from the
  694. X * distributed source code.
  695. X *
  696. X * We're not happy about it either.
  697. X */
  698. X
  699. X
  700. X/*
  701. X * The method selection routine for arithmetic entropy encoding.
  702. X */
  703. X
  704. XGLOBAL void
  705. Xjselcarithmetic (compress_info_ptr cinfo)
  706. X{
  707. X  if (cinfo->arith_code) {
  708. X    ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
  709. X  }
  710. X}
  711. X
  712. X#endif /* C_ARITH_CODING_SUPPORTED */
  713. END_OF_FILE
  714.   if test 1164 -ne `wc -c <'jcarith.c'`; then
  715.     echo shar: \"'jcarith.c'\" unpacked with wrong size!
  716.   fi
  717.   # end of 'jcarith.c'
  718. fi
  719. if test -f 'jcpipe.c' -a "${1}" != "-c" ; then 
  720.   echo shar: Will not clobber existing file \"'jcpipe.c'\"
  721. else
  722.   echo shar: Extracting \"'jcpipe.c'\" \(26905 characters\)
  723.   sed "s/^X//" >'jcpipe.c' <<'END_OF_FILE'
  724. X/*
  725. X * jcpipe.c
  726. X *
  727. X * Copyright (C) 1991, 1992, Thomas G. Lane.
  728. X * This file is part of the Independent JPEG Group's software.
  729. X * For conditions of distribution and use, see the accompanying README file.
  730. X *
  731. X * This file contains compression pipeline controllers.
  732. X * These routines are invoked via the c_pipeline_controller method.
  733. X *
  734. X * There are four basic pipeline controllers, one for each combination of:
  735. X *    single-scan JPEG file (single component or fully interleaved)
  736. X *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
  737. X *
  738. X *    optimization of entropy encoding parameters
  739. X *  vs. usage of default encoding parameters.
  740. X *
  741. X * Note that these conditions determine the needs for "big" arrays:
  742. X * multiple scans imply a big array for splitting the color components;
  743. X * entropy encoding optimization needs a big array for the MCU data.
  744. X *
  745. X * All but the simplest controller (single-scan, no optimization) can be
  746. X * compiled out through configuration options, if you need to make a minimal
  747. X * implementation.
  748. X */
  749. X
  750. X#include "jinclude.h"
  751. X
  752. X
  753. X/*
  754. X * About the data structures:
  755. X *
  756. X * The processing chunk size for downsampling is referred to in this file as
  757. X * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
  758. X * any component after downsampling, or Vmax (max_v_samp_factor) unsubsampled
  759. X * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
  760. X * groups of each component in the scan.  In a noninterleaved scan an MCU row
  761. X * is one row of blocks, which might not be an integral number of row groups;
  762. X * for convenience we use a buffer of the same size as in interleaved scans,
  763. X * and process Vk MCU rows in each burst of downsampling.
  764. X * To provide context for the downsampling step, we have to retain the last
  765. X * two row groups of the previous MCU row while reading in the next MCU row
  766. X * (or set of Vk MCU rows).  To do this without copying data about, we create
  767. X * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
  768. X * are allocated, but we create two different sets of pointers to this array.
  769. X * The second set swaps the last two pairs of row groups.  By working
  770. X * alternately with the two sets of pointers, we can access the data in the
  771. X * desired order.
  772. X */
  773. X
  774. X
  775. X
  776. X/*
  777. X * Utility routines: common code for pipeline controllers
  778. X */
  779. X
  780. XLOCAL void
  781. Xinterleaved_scan_setup (compress_info_ptr cinfo)
  782. X/* Compute all derived info for an interleaved (multi-component) scan */
  783. X/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
  784. X{
  785. X  short ci, mcublks;
  786. X  jpeg_component_info *compptr;
  787. X
  788. X  if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
  789. X    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  790. X
  791. X  cinfo->MCUs_per_row = (cinfo->image_width
  792. X             + cinfo->max_h_samp_factor*DCTSIZE - 1)
  793. X            / (cinfo->max_h_samp_factor*DCTSIZE);
  794. X
  795. X  cinfo->MCU_rows_in_scan = (cinfo->image_height
  796. X                 + cinfo->max_v_samp_factor*DCTSIZE - 1)
  797. X                / (cinfo->max_v_samp_factor*DCTSIZE);
  798. X  
  799. X  cinfo->blocks_in_MCU = 0;
  800. X
  801. X  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
  802. X    compptr = cinfo->cur_comp_info[ci];
  803. X    /* for interleaved scan, sampling factors give # of blocks per component */
  804. X    compptr->MCU_width = compptr->h_samp_factor;
  805. X    compptr->MCU_height = compptr->v_samp_factor;
  806. X    compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
  807. X    /* compute physical dimensions of component */
  808. X    compptr->downsampled_width = jround_up(compptr->true_comp_width,
  809. X                       (long) (compptr->MCU_width*DCTSIZE));
  810. X    compptr->downsampled_height = jround_up(compptr->true_comp_height,
  811. X                        (long) (compptr->MCU_height*DCTSIZE));
  812. X    /* Sanity check */
  813. X    if (compptr->downsampled_width !=
  814. X    (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
  815. X      ERREXIT(cinfo->emethods, "I'm confused about the image width");
  816. X    /* Prepare array describing MCU composition */
  817. X    mcublks = compptr->MCU_blocks;
  818. X    if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
  819. X      ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
  820. X    while (mcublks-- > 0) {
  821. X      cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
  822. X    }
  823. X  }
  824. X
  825. X  /* Convert restart specified in rows to actual MCU count. */
  826. X  /* Note that count must fit in 16 bits, so we provide limiting. */
  827. X  if (cinfo->restart_in_rows > 0) {
  828. X    long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
  829. X    cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
  830. X  }
  831. X
  832. X  (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  833. X}
  834. X
  835. X
  836. XLOCAL void
  837. Xnoninterleaved_scan_setup (compress_info_ptr cinfo)
  838. X/* Compute all derived info for a noninterleaved (single-component) scan */
  839. X/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
  840. X{
  841. X  jpeg_component_info *compptr = cinfo->cur_comp_info[0];
  842. X
  843. X  /* for noninterleaved scan, always one block per MCU */
  844. X  compptr->MCU_width = 1;
  845. X  compptr->MCU_height = 1;
  846. X  compptr->MCU_blocks = 1;
  847. X  /* compute physical dimensions of component */
  848. X  compptr->downsampled_width = jround_up(compptr->true_comp_width,
  849. X                     (long) DCTSIZE);
  850. X  compptr->downsampled_height = jround_up(compptr->true_comp_height,
  851. X                      (long) DCTSIZE);
  852. X
  853. X  cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE;
  854. X  cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE;
  855. X
  856. X  /* Prepare array describing MCU composition */
  857. X  cinfo->blocks_in_MCU = 1;
  858. X  cinfo->MCU_membership[0] = 0;
  859. X
  860. X  /* Convert restart specified in rows to actual MCU count. */
  861. X  /* Note that count must fit in 16 bits, so we provide limiting. */
  862. X  if (cinfo->restart_in_rows > 0) {
  863. X    long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
  864. X    cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
  865. X  }
  866. X
  867. X  (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  868. X}
  869. X
  870. X
  871. X
  872. XLOCAL void
  873. Xalloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
  874. X               long fullsize_width)
  875. X/* Create a pre-downsampling data buffer having the desired structure */
  876. X/* (see comments at head of file) */
  877. X{
  878. X  short ci, vs, i;
  879. X
  880. X  vs = cinfo->max_v_samp_factor; /* row group height */
  881. X
  882. X  /* Get top-level space for array pointers */
  883. X  fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  884. X                (cinfo->num_components * SIZEOF(JSAMPARRAY));
  885. X  fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  886. X                (cinfo->num_components * SIZEOF(JSAMPARRAY));
  887. X
  888. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  889. X    /* Allocate the real storage */
  890. X    fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
  891. X                (fullsize_width,
  892. X                (long) (vs * (DCTSIZE+2)));
  893. X    /* Create space for the scrambled-order pointers */
  894. X    fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
  895. X                (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
  896. X    /* Duplicate the first DCTSIZE-2 row groups */
  897. X    for (i = 0; i < vs * (DCTSIZE-2); i++) {
  898. X      fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
  899. X    }
  900. X    /* Copy the last four row groups in swapped order */
  901. X    for (i = 0; i < vs * 2; i++) {
  902. X      fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
  903. X      fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
  904. X    }
  905. X  }
  906. X}
  907. X
  908. X
  909. X#if 0                /* this routine not currently needed */
  910. X
  911. XLOCAL void
  912. Xfree_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
  913. X/* Release a sampling buffer created by alloc_sampling_buffer */
  914. X{
  915. X  short ci;
  916. X
  917. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  918. X    /* Free the real storage */
  919. X    (*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
  920. X    /* Free the scrambled-order pointers */
  921. X    (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
  922. X  }
  923. X
  924. X  /* Free the top-level space */
  925. X  (*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
  926. X  (*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
  927. X}
  928. X
  929. X#endif
  930. X
  931. X
  932. XLOCAL void
  933. Xdownsample (compress_info_ptr cinfo,
  934. X        JSAMPIMAGE fullsize_data, JSAMPIMAGE sampled_data,
  935. X        long fullsize_width,
  936. X        short above, short current, short below, short out)
  937. X/* Do downsampling of a single row group (of each component). */
  938. X/* above, current, below are indexes of row groups in fullsize_data;      */
  939. X/* out is the index of the target row group in sampled_data.              */
  940. X/* Special case: above, below can be -1 to indicate top, bottom of image. */
  941. X{
  942. X  jpeg_component_info *compptr;
  943. X  JSAMPARRAY above_ptr, below_ptr;
  944. X  JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */
  945. X  short ci, vs, i;
  946. X
  947. X  vs = cinfo->max_v_samp_factor; /* row group height */
  948. X
  949. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  950. X    compptr = & cinfo->comp_info[ci];
  951. X
  952. X    if (above >= 0)
  953. X      above_ptr = fullsize_data[ci] + above * vs;
  954. X    else {
  955. X      /* Top of image: make a dummy above-context with copies of 1st row */
  956. X      /* We assume current=0 in this case */
  957. X      for (i = 0; i < vs; i++)
  958. X    dummy[i] = fullsize_data[ci][0];
  959. X      above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  960. X    }
  961. X
  962. X    if (below >= 0)
  963. X      below_ptr = fullsize_data[ci] + below * vs;
  964. X    else {
  965. X      /* Bot of image: make a dummy below-context with copies of last row */
  966. X      for (i = 0; i < vs; i++)
  967. X    dummy[i] = fullsize_data[ci][(current+1)*vs-1];
  968. X      below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  969. X    }
  970. X
  971. X    (*cinfo->methods->downsample[ci])
  972. X        (cinfo, (int) ci,
  973. X         fullsize_width, (int) vs,
  974. X         compptr->downsampled_width, (int) compptr->v_samp_factor,
  975. X         above_ptr,
  976. X         fullsize_data[ci] + current * vs,
  977. X         below_ptr,
  978. X         sampled_data[ci] + out * compptr->v_samp_factor);
  979. X  }
  980. X}
  981. X
  982. X
  983. X/* These variables are initialized by the pipeline controller for use by
  984. X * MCU_output_catcher.
  985. X * To avoid a lot of row-pointer overhead, we cram as many MCUs into each
  986. X * row of whole_scan_MCUs as we can get without exceeding 32Kbytes per row.
  987. X * NOTE: the "arbitrary" constant here must not exceed MAX_ALLOC_CHUNK
  988. X * defined in jmemsys.h, which is 64K-epsilon in most DOS implementations.
  989. X */
  990. X
  991. X#define MAX_WHOLE_ROW_BLOCKS    ((int) (32768L / SIZEOF(JBLOCK))) /* max blocks/row */
  992. X
  993. Xstatic big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
  994. Xstatic int MCUs_in_big_row;    /* # of MCUs in each row of whole_scan_MCUs */
  995. Xstatic long next_whole_row;    /* next row to access in whole_scan_MCUs */
  996. Xstatic int next_MCU_index;    /* next MCU in current row */
  997. X
  998. X
  999. XMETHODDEF void
  1000. XMCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
  1001. X/* Output method for siphoning off extract_MCUs output into a big array */
  1002. X{
  1003. X  static JBLOCKARRAY rowptr;
  1004. X
  1005. X  if (next_MCU_index >= MCUs_in_big_row) {
  1006. X    rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  1007. X                            next_whole_row, TRUE);
  1008. X    next_whole_row++;
  1009. X    next_MCU_index = 0;
  1010. X  }
  1011. X
  1012. X  /*
  1013. X   * note that on 80x86, the cast applied to MCU_data implies
  1014. X   * near to far pointer conversion.
  1015. X   */
  1016. X  jcopy_block_row((JBLOCKROW) MCU_data,
  1017. X          rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
  1018. X          (long) cinfo->blocks_in_MCU);
  1019. X  next_MCU_index++;
  1020. X}
  1021. X
  1022. X
  1023. XMETHODDEF void
  1024. Xdump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
  1025. X/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
  1026. X/* The method may be either the entropy encoder or some routine supplied */
  1027. X/* by the entropy optimizer. */
  1028. X{
  1029. X  /* On an 80x86 machine, the entropy encoder expects the passed data block
  1030. X   * to be in NEAR memory (for performance reasons), so we have to copy it
  1031. X   * back from the big array to a local array.  On less brain-damaged CPUs
  1032. X   * we needn't do that.
  1033. X   */
  1034. X#ifdef NEED_FAR_POINTERS
  1035. X  JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
  1036. X#endif
  1037. X  long mcurow, mcuindex, next_row;
  1038. X  int next_index;
  1039. X  JBLOCKARRAY rowptr = NULL;    /* init only to suppress compiler complaint */
  1040. X
  1041. X  next_row = 0;
  1042. X  next_index = MCUs_in_big_row;
  1043. X
  1044. X  for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
  1045. X    (*cinfo->methods->progress_monitor) (cinfo, mcurow,
  1046. X                     cinfo->MCU_rows_in_scan);
  1047. X    for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
  1048. X      if (next_index >= MCUs_in_big_row) {
  1049. X    rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  1050. X                            next_row, FALSE);
  1051. X    next_row++;
  1052. X    next_index = 0;
  1053. X      }
  1054. X#ifdef NEED_FAR_POINTERS
  1055. X      jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
  1056. X              (JBLOCKROW) MCU_data, /* casts near to far pointer! */
  1057. X              (long) cinfo->blocks_in_MCU);
  1058. X      (*output_method) (cinfo, MCU_data);
  1059. X#else
  1060. X      (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
  1061. X#endif
  1062. X      next_index++;
  1063. X    }
  1064. X  }
  1065. X
  1066. X  cinfo->completed_passes++;
  1067. X}
  1068. X
  1069. X
  1070. X
  1071. X/*
  1072. X * Compression pipeline controller used for single-scan files
  1073. X * with no optimization of entropy parameters.
  1074. X */
  1075. X
  1076. XMETHODDEF void
  1077. Xsingle_ccontroller (compress_info_ptr cinfo)
  1078. X{
  1079. X  int rows_in_mem;        /* # of sample rows in full-size buffers */
  1080. X  long fullsize_width;        /* # of samples per row in full-size buffers */
  1081. X  long cur_pixel_row;        /* counts # of pixel rows processed */
  1082. X  long mcu_rows_output;        /* # of MCU rows actually emitted */
  1083. X  int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  1084. X  /* Work buffer for pre-downsampling data (see comments at head of file) */
  1085. X  JSAMPIMAGE fullsize_data[2];
  1086. X  /* Work buffer for downsampled data */
  1087. X  JSAMPIMAGE sampled_data;
  1088. X  int rows_this_time;
  1089. X  short ci, whichss, i;
  1090. X
  1091. X  /* Prepare for single scan containing all components */
  1092. X  if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  1093. X    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  1094. X  cinfo->comps_in_scan = cinfo->num_components;
  1095. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  1096. X    cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  1097. X  }
  1098. X  if (cinfo->comps_in_scan == 1) {
  1099. X    noninterleaved_scan_setup(cinfo);
  1100. X    /* Vk block rows constitute the same number of MCU rows */
  1101. X    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  1102. X  } else {
  1103. X    interleaved_scan_setup(cinfo);
  1104. X    /* in an interleaved scan, one MCU row contains Vk block rows */
  1105. X    mcu_rows_per_loop = 1;
  1106. X  }
  1107. X  cinfo->total_passes++;
  1108. X
  1109. X  /* Compute dimensions of full-size pixel buffers */
  1110. X  /* Note these are the same whether interleaved or not. */
  1111. X  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  1112. X  fullsize_width = jround_up(cinfo->image_width,
  1113. X                 (long) (cinfo->max_h_samp_factor * DCTSIZE));
  1114. X
  1115. X  /* Allocate working memory: */
  1116. X  /* fullsize_data is sample data before downsampling */
  1117. X  alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  1118. X  /* sampled_data is sample data after downsampling */
  1119. X  sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  1120. X                (cinfo->num_components * SIZEOF(JSAMPARRAY));
  1121. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  1122. X    sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  1123. X            (cinfo->comp_info[ci].downsampled_width,
  1124. X             (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  1125. X  }
  1126. X
  1127. X  /* Tell the memory manager to instantiate big arrays.
  1128. X   * We don't need any big arrays in this controller,
  1129. X   * but some other module (like the input file reader) may need one.
  1130. X   */
  1131. X  (*cinfo->emethods->alloc_big_arrays)
  1132. X    ((long) 0,                /* no more small sarrays */
  1133. X     (long) 0,                /* no more small barrays */
  1134. X     (long) 0);                /* no more "medium" objects */
  1135. X
  1136. X  /* Initialize output file & do per-scan object init */
  1137. X
  1138. X  (*cinfo->methods->write_scan_header) (cinfo);
  1139. X  cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  1140. X  (*cinfo->methods->entropy_encode_init) (cinfo);
  1141. X  (*cinfo->methods->downsample_init) (cinfo);
  1142. X  (*cinfo->methods->extract_init) (cinfo);
  1143. X
  1144. X  /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  1145. X
  1146. X  mcu_rows_output = 0;
  1147. X  whichss = 1;            /* arrange to start with fullsize_data[0] */
  1148. X
  1149. X  for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  1150. X       cur_pixel_row += rows_in_mem) {
  1151. X    (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  1152. X                     cinfo->image_height);
  1153. X
  1154. X    whichss ^= 1;        /* switch to other fullsize_data buffer */
  1155. X    
  1156. X    /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  1157. X    /* Then we have exactly DCTSIZE row groups for downsampling. */   
  1158. X    rows_this_time = (int) MIN((long) rows_in_mem,
  1159. X                   cinfo->image_height - cur_pixel_row);
  1160. X    (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  1161. X                    fullsize_data[whichss]);
  1162. X    (*cinfo->methods->edge_expand) (cinfo,
  1163. X                    cinfo->image_width, rows_this_time,
  1164. X                    fullsize_width, rows_in_mem,
  1165. X                    fullsize_data[whichss]);
  1166. X    
  1167. X    /* Downsample the data (all components) */
  1168. X    /* First time through is a special case */
  1169. X    
  1170. X    if (cur_pixel_row) {
  1171. X      /* Downsample last row group of previous set */
  1172. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1173. X         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  1174. X         (short) (DCTSIZE-1));
  1175. X      /* and dump the previous set's downsampled data */
  1176. X      (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  1177. X                       mcu_rows_per_loop,
  1178. X                       cinfo->methods->entropy_encode);
  1179. X      mcu_rows_output += mcu_rows_per_loop;
  1180. X      /* Downsample first row group of this set */
  1181. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1182. X         (short) (DCTSIZE+1), (short) 0, (short) 1,
  1183. X         (short) 0);
  1184. X    } else {
  1185. X      /* Downsample first row group with dummy above-context */
  1186. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1187. X         (short) (-1), (short) 0, (short) 1,
  1188. X         (short) 0);
  1189. X    }
  1190. X    /* Downsample second through next-to-last row groups of this set */
  1191. X    for (i = 1; i <= DCTSIZE-2; i++) {
  1192. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1193. X         (short) (i-1), (short) i, (short) (i+1),
  1194. X         (short) i);
  1195. X    }
  1196. X  } /* end of outer loop */
  1197. X  
  1198. X  /* Downsample the last row group with dummy below-context */
  1199. X  /* Note whichss points to last buffer side used */
  1200. X  downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1201. X         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  1202. X         (short) (DCTSIZE-1));
  1203. X  /* Dump the remaining data (may be less than full height if uninterleaved) */
  1204. X  (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  1205. X        (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  1206. X        cinfo->methods->entropy_encode);
  1207. X
  1208. X  /* Finish output file */
  1209. X  (*cinfo->methods->extract_term) (cinfo);
  1210. X  (*cinfo->methods->downsample_term) (cinfo);
  1211. X  (*cinfo->methods->entropy_encode_term) (cinfo);
  1212. X  (*cinfo->methods->write_scan_trailer) (cinfo);
  1213. X  cinfo->completed_passes++;
  1214. X
  1215. X  /* Release working memory */
  1216. X  /* (no work -- we let free_all release what's needful) */
  1217. X}
  1218. X
  1219. X
  1220. X/*
  1221. X * Compression pipeline controller used for single-scan files
  1222. X * with optimization of entropy parameters.
  1223. X */
  1224. X
  1225. X#ifdef ENTROPY_OPT_SUPPORTED
  1226. X
  1227. XMETHODDEF void
  1228. Xsingle_eopt_ccontroller (compress_info_ptr cinfo)
  1229. X{
  1230. X  int rows_in_mem;        /* # of sample rows in full-size buffers */
  1231. X  long fullsize_width;        /* # of samples per row in full-size buffers */
  1232. X  long cur_pixel_row;        /* counts # of pixel rows processed */
  1233. X  long mcu_rows_output;        /* # of MCU rows actually emitted */
  1234. X  int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  1235. X  /* Work buffer for pre-downsampling data (see comments at head of file) */
  1236. X  JSAMPIMAGE fullsize_data[2];
  1237. X  /* Work buffer for downsampled data */
  1238. X  JSAMPIMAGE sampled_data;
  1239. X  int rows_this_time;
  1240. X  int blocks_in_big_row;
  1241. X  short ci, whichss, i;
  1242. X
  1243. X  /* Prepare for single scan containing all components */
  1244. X  if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  1245. X    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  1246. X  cinfo->comps_in_scan = cinfo->num_components;
  1247. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  1248. X    cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  1249. X  }
  1250. X  if (cinfo->comps_in_scan == 1) {
  1251. X    noninterleaved_scan_setup(cinfo);
  1252. X    /* Vk block rows constitute the same number of MCU rows */
  1253. X    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  1254. X  } else {
  1255. X    interleaved_scan_setup(cinfo);
  1256. X    /* in an interleaved scan, one MCU row contains Vk block rows */
  1257. X    mcu_rows_per_loop = 1;
  1258. X  }
  1259. X  cinfo->total_passes += 2;    /* entropy encoder must add # passes it uses */
  1260. X
  1261. X  /* Compute dimensions of full-size pixel buffers */
  1262. X  /* Note these are the same whether interleaved or not. */
  1263. X  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  1264. X  fullsize_width = jround_up(cinfo->image_width,
  1265. X                 (long) (cinfo->max_h_samp_factor * DCTSIZE));
  1266. X
  1267. X  /* Allocate working memory: */
  1268. X  /* fullsize_data is sample data before downsampling */
  1269. X  alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  1270. X  /* sampled_data is sample data after downsampling */
  1271. X  sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  1272. X                (cinfo->num_components * SIZEOF(JSAMPARRAY));
  1273. X  for (ci = 0; ci < cinfo->num_components; ci++) {
  1274. X    sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  1275. X            (cinfo->comp_info[ci].downsampled_width,
  1276. X             (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  1277. X  }
  1278. X
  1279. X  /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
  1280. X  MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
  1281. X  blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
  1282. X
  1283. X  /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
  1284. X  whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
  1285. X        ((long) blocks_in_big_row,
  1286. X         (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
  1287. X             + MCUs_in_big_row-1) / MCUs_in_big_row,
  1288. X         1L);        /* unit height is 1 row */
  1289. X
  1290. X  next_whole_row = 0;        /* init output ptr for MCU_output_catcher */
  1291. X  next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
  1292. X
  1293. X  /* Tell the memory manager to instantiate big arrays */
  1294. X  (*cinfo->emethods->alloc_big_arrays)
  1295. X    ((long) 0,                /* no more small sarrays */
  1296. X     (long) 0,                /* no more small barrays */
  1297. X     (long) 0);                /* no more "medium" objects */
  1298. X
  1299. X  /* Do per-scan object init */
  1300. X
  1301. X  (*cinfo->methods->downsample_init) (cinfo);
  1302. X  (*cinfo->methods->extract_init) (cinfo);
  1303. X
  1304. X  /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  1305. X  /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
  1306. X
  1307. X  mcu_rows_output = 0;
  1308. X  whichss = 1;            /* arrange to start with fullsize_data[0] */
  1309. X
  1310. X  for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  1311. X       cur_pixel_row += rows_in_mem) {
  1312. X    (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  1313. X                     cinfo->image_height);
  1314. X
  1315. X    whichss ^= 1;        /* switch to other fullsize_data buffer */
  1316. X    
  1317. X    /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  1318. X    /* Then we have exactly DCTSIZE row groups for downsampling. */   
  1319. X    rows_this_time = (int) MIN((long) rows_in_mem,
  1320. X                   cinfo->image_height - cur_pixel_row);
  1321. X    (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  1322. X                    fullsize_data[whichss]);
  1323. X    (*cinfo->methods->edge_expand) (cinfo,
  1324. X                    cinfo->image_width, rows_this_time,
  1325. X                    fullsize_width, rows_in_mem,
  1326. X                    fullsize_data[whichss]);
  1327. X    
  1328. X    /* Downsample the data (all components) */
  1329. X    /* First time through is a special case */
  1330. X    
  1331. X    if (cur_pixel_row) {
  1332. X      /* Downsample last row group of previous set */
  1333. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1334. X         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  1335. X         (short) (DCTSIZE-1));
  1336. X      /* and dump the previous set's downsampled data */
  1337. X      (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  1338. X                       mcu_rows_per_loop,
  1339. X                       MCU_output_catcher);
  1340. X      mcu_rows_output += mcu_rows_per_loop;
  1341. X      /* Downsample first row group of this set */
  1342. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1343. X         (short) (DCTSIZE+1), (short) 0, (short) 1,
  1344. X         (short) 0);
  1345. X    } else {
  1346. X      /* Downsample first row group with dummy above-context */
  1347. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1348. X         (short) (-1), (short) 0, (short) 1,
  1349. X         (short) 0);
  1350. X    }
  1351. X    /* Downsample second through next-to-last row groups of this set */
  1352. X    for (i = 1; i <= DCTSIZE-2; i++) {
  1353. X      downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1354. X         (short) (i-1), (short) i, (short) (i+1),
  1355. X         (short) i);
  1356. X    }
  1357. X  } /* end of outer loop */
  1358. X  
  1359. X  /* Downsample the last row group with dummy below-context */
  1360. X  /* Note whichss points to last buffer side used */
  1361. X  downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  1362. X         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  1363. X         (short) (DCTSIZE-1));
  1364. X  /* Dump the remaining data (may be less than full height if uninterleaved) */
  1365. X  (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  1366. X        (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  1367. X        MCU_output_catcher);
  1368. X
  1369. X  /* Clean up after that stuff, then find the optimal entropy parameters */
  1370. X
  1371. X  (*cinfo->methods->extract_term) (cinfo);
  1372. X  (*cinfo->methods->downsample_term) (cinfo);
  1373. X
  1374. X  cinfo->completed_passes++;
  1375. X
  1376. X  (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
  1377. X
  1378. X  /* Emit scan to output file */
  1379. X  /* Note: we can't do write_scan_header until entropy parameters are set! */
  1380. X
  1381. X  (*cinfo->methods->write_scan_header) (cinfo);
  1382. X  cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  1383. X  (*cinfo->methods->entropy_encode_init) (cinfo);
  1384. X  dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
  1385. X  (*cinfo->methods->entropy_encode_term) (cinfo);
  1386. X  (*cinfo->methods->write_scan_trailer) (cinfo);
  1387. X
  1388. X  /* Release working memory */
  1389. X  /* (no work -- we let free_all release what's needful) */
  1390. X}
  1391. X
  1392. X#endif /* ENTROPY_OPT_SUPPORTED */
  1393. X
  1394. X
  1395. X/*
  1396. X * Compression pipeline controller used for multiple-scan files
  1397. X * with no optimization of entropy parameters.
  1398. X */
  1399. X
  1400. X#ifdef C_MULTISCAN_FILES_SUPPORTED
  1401. X
  1402. XMETHODDEF void
  1403. Xmulti_ccontroller (compress_info_ptr cinfo)
  1404. X{
  1405. X  ERREXIT(cinfo->emethods, "Not implemented yet");
  1406. X}
  1407. X
  1408. X#endif /* C_MULTISCAN_FILES_SUPPORTED */
  1409. X
  1410. X
  1411. X/*
  1412. X * Compression pipeline controller used for multiple-scan files
  1413. X * with optimization of entropy parameters.
  1414. X */
  1415. X
  1416. X#ifdef C_MULTISCAN_FILES_SUPPORTED
  1417. X#ifdef ENTROPY_OPT_SUPPORTED
  1418. X
  1419. XMETHODDEF void
  1420. Xmulti_eopt_ccontroller (compress_info_ptr cinfo)
  1421. X{
  1422. X  ERREXIT(cinfo->emethods, "Not implemented yet");
  1423. X}
  1424. X
  1425. X#endif /* ENTROPY_OPT_SUPPORTED */
  1426. X#endif /* C_MULTISCAN_FILES_SUPPORTED */
  1427. X
  1428. X
  1429. X/*
  1430. X * The method selection routine for compression pipeline controllers.
  1431. X */
  1432. X
  1433. XGLOBAL void
  1434. Xjselcpipeline (compress_info_ptr cinfo)
  1435. X{
  1436. X  if (cinfo->interleave || cinfo->num_components == 1) {
  1437. X    /* single scan needed */
  1438. X#ifdef ENTROPY_OPT_SUPPORTED
  1439. X    if (cinfo->optimize_coding)
  1440. X      cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
  1441. X    else
  1442. X#endif
  1443. X      cinfo->methods->c_pipeline_controller = single_ccontroller;
  1444. X  } else {
  1445. X    /* multiple scans needed */
  1446. X#ifdef C_MULTISCAN_FILES_SUPPORTED
  1447. X#ifdef ENTROPY_OPT_SUPPORTED
  1448. X    if (cinfo->optimize_coding)
  1449. X      cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
  1450. X    else
  1451. X#endif
  1452. X      cinfo->methods->c_pipeline_controller = multi_ccontroller;
  1453. X#else
  1454. X    ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
  1455. X#endif
  1456. X  }
  1457. X}
  1458. END_OF_FILE
  1459.   if test 26905 -ne `wc -c <'jcpipe.c'`; then
  1460.     echo shar: \"'jcpipe.c'\" unpacked with wrong size!
  1461.   fi
  1462.   # end of 'jcpipe.c'
  1463. fi
  1464. echo shar: End of archive 8 \(of 18\).
  1465. cp /dev/null ark8isdone
  1466. MISSING=""
  1467. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1468.     if test ! -f ark${I}isdone ; then
  1469.     MISSING="${MISSING} ${I}"
  1470.     fi
  1471. done
  1472. if test "${MISSING}" = "" ; then
  1473.     echo You have unpacked all 18 archives.
  1474.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1475. else
  1476.     echo You still must unpack the following archives:
  1477.     echo "        " ${MISSING}
  1478. fi
  1479. exit 0
  1480. exit 0 # Just in case...
  1481.