home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / jpeg / part12 < prev    next >
Encoding:
Text File  |  1992-03-27  |  53.7 KB  |  1,830 lines

  1. Newsgroups: comp.sources.misc
  2. From: jpeg-info@uunet.uu.net (Independent JPEG Group)
  3. Subject:  v29i012:  jpeg - JPEG image compression, Part12/18
  4. Message-ID: <1992Mar25.145246.512@sparky.imd.sterling.com>
  5. X-Md4-Signature: 0d9a9e7a1e09e2d4f2267531baf9d1bb
  6. Date: Wed, 25 Mar 1992 14:52:46 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jpeg-info@uunet.uu.net (Independent JPEG Group)
  10. Posting-number: Volume 29, Issue 12
  11. Archive-name: jpeg/part12
  12. Environment: UNIX, VMS, MS-DOS, Mac, Amiga, Cray
  13.  
  14. #! /bin/sh
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  ansi2knr.c jmemansi.c jmemdos.c jversion.h jwrjfif.c
  20. # Wrapped by kent@sparky on Mon Mar 23 16:02:50 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 12 (of 18)."'
  24. if test -f 'ansi2knr.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'ansi2knr.c'\"
  26. else
  27.   echo shar: Extracting \"'ansi2knr.c'\" \(16258 characters\)
  28.   sed "s/^X//" >'ansi2knr.c' <<'END_OF_FILE'
  29. X/*
  30. X * Received from Peter Deutsch (ghost@aladdin.com)
  31. X * Fri, 26 Apr 91 10:10:10 PDT
  32. X * Small portability improvements by Tom Lane
  33. X */
  34. X
  35. X/* Copyright (C) 1989, 1991 Aladdin Enterprises.  All rights reserved.
  36. X   Distributed by Free Software Foundation, Inc.
  37. X
  38. XThis file is part of Ghostscript.
  39. X
  40. XGhostscript is distributed in the hope that it will be useful, but
  41. XWITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  42. Xto anyone for the consequences of using it or for whether it serves any
  43. Xparticular purpose or works at all, unless he says so in writing.  Refer
  44. Xto the Ghostscript General Public License for full details.
  45. X
  46. XEveryone is granted permission to copy, modify and redistribute
  47. XGhostscript, but only under the conditions described in the Ghostscript
  48. XGeneral Public License.  A copy of this license is supposed to have been
  49. Xgiven to you along with Ghostscript so you can know your rights and
  50. Xresponsibilities.  It should be in a file named COPYING.  Among other
  51. Xthings, the copyright notice and this notice must be preserved on all
  52. Xcopies.  */
  53. X
  54. X/*
  55. X---------- Here is the GhostScript file COPYING, referred to above ----------
  56. X----- These terms do NOT apply to the JPEG software itself; see README ------
  57. X
  58. X            GHOSTSCRIPT GENERAL PUBLIC LICENSE
  59. X            (Clarified 11 Feb 1988)
  60. X
  61. X Copyright (C) 1988 Richard M. Stallman
  62. X Everyone is permitted to copy and distribute verbatim copies of this
  63. X license, but changing it is not allowed.  You can also use this wording
  64. X to make the terms for other programs.
  65. X
  66. X  The license agreements of most software companies keep you at the
  67. Xmercy of those companies.  By contrast, our general public license is
  68. Xintended to give everyone the right to share Ghostscript.  To make sure
  69. Xthat you get the rights we want you to have, we need to make
  70. Xrestrictions that forbid anyone to deny you these rights or to ask you
  71. Xto surrender the rights.  Hence this license agreement.
  72. X
  73. X  Specifically, we want to make sure that you have the right to give
  74. Xaway copies of Ghostscript, that you receive source code or else can get
  75. Xit if you want it, that you can change Ghostscript or use pieces of it
  76. Xin new free programs, and that you know you can do these things.
  77. X
  78. X  To make sure that everyone has such rights, we have to forbid you to
  79. Xdeprive anyone else of these rights.  For example, if you distribute
  80. Xcopies of Ghostscript, you must give the recipients all the rights that
  81. Xyou have.  You must make sure that they, too, receive or can get the
  82. Xsource code.  And you must tell them their rights.
  83. X
  84. X  Also, for our own protection, we must make certain that everyone finds
  85. Xout that there is no warranty for Ghostscript.  If Ghostscript is
  86. Xmodified by someone else and passed on, we want its recipients to know
  87. Xthat what they have is not what we distributed, so that any problems
  88. Xintroduced by others will not reflect on our reputation.
  89. X
  90. X  Therefore we (Richard M. Stallman and the Free Software Foundation,
  91. XInc.) make the following terms which say what you must do to be allowed
  92. Xto distribute or change Ghostscript.
  93. X
  94. X
  95. X            COPYING POLICIES
  96. X
  97. X  1. You may copy and distribute verbatim copies of Ghostscript source
  98. Xcode as you receive it, in any medium, provided that you conspicuously
  99. Xand appropriately publish on each copy a valid copyright and license
  100. Xnotice "Copyright (C) 1989 Aladdin Enterprises.  All rights reserved.
  101. XDistributed by Free Software Foundation, Inc." (or with whatever year is
  102. Xappropriate); keep intact the notices on all files that refer to this
  103. XLicense Agreement and to the absence of any warranty; and give any other
  104. Xrecipients of the Ghostscript program a copy of this License Agreement
  105. Xalong with the program.  You may charge a distribution fee for the
  106. Xphysical act of transferring a copy.
  107. X
  108. X  2. You may modify your copy or copies of Ghostscript or any portion of
  109. Xit, and copy and distribute such modifications under the terms of
  110. XParagraph 1 above, provided that you also do the following:
  111. X
  112. X    a) cause the modified files to carry prominent notices stating
  113. X    that you changed the files and the date of any change; and
  114. X
  115. X    b) cause the whole of any work that you distribute or publish,
  116. X    that in whole or in part contains or is a derivative of Ghostscript
  117. X    or any part thereof, to be licensed at no charge to all third
  118. X    parties on terms identical to those contained in this License
  119. X    Agreement (except that you may choose to grant more extensive
  120. X    warranty protection to some or all third parties, at your option).
  121. X
  122. X    c) You may charge a distribution fee for the physical act of
  123. X    transferring a copy, and you may at your option offer warranty
  124. X    protection in exchange for a fee.
  125. X
  126. XMere aggregation of another unrelated program with this program (or its
  127. Xderivative) on a volume of a storage or distribution medium does not bring
  128. Xthe other program under the scope of these terms.
  129. X
  130. X  3. You may copy and distribute Ghostscript (or a portion or derivative
  131. Xof it, under Paragraph 2) in object code or executable form under the
  132. Xterms of Paragraphs 1 and 2 above provided that you also do one of the
  133. Xfollowing:
  134. X
  135. X    a) accompany it with the complete corresponding machine-readable
  136. X    source code, which must be distributed under the terms of
  137. X    Paragraphs 1 and 2 above; or,
  138. X
  139. X    b) accompany it with a written offer, valid for at least three
  140. X    years, to give any third party free (except for a nominal
  141. X    shipping charge) a complete machine-readable copy of the
  142. X    corresponding source code, to be distributed under the terms of
  143. X    Paragraphs 1 and 2 above; or,
  144. X
  145. X    c) accompany it with the information you received as to where the
  146. X    corresponding source code may be obtained.  (This alternative is
  147. X    allowed only for noncommercial distribution and only if you
  148. X    received the program in object code or executable form alone.)
  149. X
  150. XFor an executable file, complete source code means all the source code for
  151. Xall modules it contains; but, as a special exception, it need not include
  152. Xsource code for modules which are standard libraries that accompany the
  153. Xoperating system on which the executable file runs.
  154. X
  155. X  4. You may not copy, sublicense, distribute or transfer Ghostscript
  156. Xexcept as expressly provided under this License Agreement.  Any attempt
  157. Xotherwise to copy, sublicense, distribute or transfer Ghostscript is
  158. Xvoid and your rights to use the program under this License agreement
  159. Xshall be automatically terminated.  However, parties who have received
  160. Xcomputer software programs from you with this License Agreement will not
  161. Xhave their licenses terminated so long as such parties remain in full
  162. Xcompliance.
  163. X
  164. X  5. If you wish to incorporate parts of Ghostscript into other free
  165. Xprograms whose distribution conditions are different, write to the Free
  166. XSoftware Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not
  167. Xyet worked out a simple rule that can be stated here, but we will often
  168. Xpermit this.  We will be guided by the two goals of preserving the free
  169. Xstatus of all derivatives of our free software and of promoting the
  170. Xsharing and reuse of software.
  171. X
  172. XYour comments and suggestions about our licensing policies and our
  173. Xsoftware are welcome!  Please contact the Free Software Foundation,
  174. XInc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
  175. X
  176. X               NO WARRANTY
  177. X
  178. X  BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  179. XNO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  180. XWHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
  181. XM. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
  182. XPROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  183. XEXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  184. XWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE
  185. XENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
  186. XYOU.  SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
  187. XNECESSARY SERVICING, REPAIR OR CORRECTION.
  188. X
  189. X  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  190. XSTALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
  191. XENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
  192. XGHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
  193. XANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
  194. XCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
  195. X(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
  196. XINACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
  197. XPROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
  198. XHAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
  199. XBY ANY OTHER PARTY.
  200. X-------------------- End of file COPYING ------------------------------
  201. X*/
  202. X
  203. X
  204. X/* ansi2knr.c */
  205. X/* Convert ANSI function declarations to K&R syntax */
  206. X
  207. X#include <stdio.h>
  208. X#include <ctype.h>
  209. X
  210. X#ifdef BSD
  211. X#include <strings.h>
  212. X#define strchr index
  213. X#else
  214. X#ifdef VMS
  215. X    extern char *strcat(), *strchr(), *strcpy(), *strupr();
  216. X    extern int strcmp(), strlen(), strncmp();
  217. X#else
  218. X#include <string.h>
  219. X#endif
  220. X#endif
  221. X
  222. X#ifdef MSDOS
  223. X#include <malloc.h>
  224. X#else
  225. X#ifdef VMS
  226. X     extern char *malloc();
  227. X     extern void free();
  228. X#else
  229. X     extern char *malloc();
  230. X     extern int free();
  231. X#endif
  232. X#endif
  233. X
  234. X/* Usage:
  235. X    ansi2knr input_file output_file
  236. X * If no output_file is supplied, output goes to stdout.
  237. X * There are no error messages.
  238. X *
  239. X * ansi2knr recognizes functions by seeing a non-keyword identifier
  240. X * at the left margin, followed by a left parenthesis,
  241. X * with a right parenthesis as the last character on the line.
  242. X * It will recognize a multi-line header if the last character
  243. X * on each line but the last is a left parenthesis or comma.
  244. X * These algorithms ignore whitespace and comments, except that
  245. X * the function name must be the first thing on the line.
  246. X * The following constructs will confuse it:
  247. X    - Any other construct that starts at the left margin and
  248. X        follows the above syntax (such as a macro or function call).
  249. X    - Macros that tinker with the syntax of the function header.
  250. X */
  251. X
  252. X/* Scanning macros */
  253. X#define isidchar(ch) (isalnum(ch) || (ch) == '_')
  254. X#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
  255. X
  256. Xint
  257. Xmain(argc, argv)
  258. X    int argc;
  259. X    char *argv[];
  260. X{    FILE *in, *out;
  261. X#define bufsize 500            /* arbitrary size */
  262. X    char buf[bufsize+1];
  263. X    char *line;
  264. X    switch ( argc )
  265. X       {
  266. X    default:
  267. X        printf("Usage: ansi2knr input_file [output_file]\n");
  268. X        exit(0);
  269. X    case 2:
  270. X        out = stdout; break;
  271. X    case 3:
  272. X        out = fopen(argv[2], "w");
  273. X        if ( out == NULL )
  274. X           {    fprintf(stderr, "Cannot open %s\n", argv[2]);
  275. X            exit(1);
  276. X           }
  277. X       }
  278. X    in = fopen(argv[1], "r");
  279. X    if ( in == NULL )
  280. X       {    fprintf(stderr, "Cannot open %s\n", argv[1]);
  281. X        exit(1);
  282. X       }
  283. X    fprintf(out, "#line 1 \"%s\"\n", argv[1]);
  284. X    line = buf;
  285. X    while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
  286. X       {    switch ( test1(buf) )
  287. X           {
  288. X        case 1:            /* a function */
  289. X            convert1(buf, out);
  290. X            break;
  291. X        case -1:        /* maybe the start of a function */
  292. X            line = buf + strlen(buf);
  293. X            continue;
  294. X        default:        /* not a function */
  295. X            fputs(buf, out);
  296. X            break;
  297. X           }
  298. X        line = buf;
  299. X       }
  300. X    if ( line != buf ) fputs(buf, out);
  301. X    fclose(out);
  302. X    fclose(in);
  303. X    return 0;
  304. X}
  305. X
  306. X/* Skip over space and comments, in either direction. */
  307. Xchar *
  308. Xskipspace(p, dir)
  309. X    register char *p;
  310. X    register int dir;            /* 1 for forward, -1 for backward */
  311. X{    for ( ; ; )
  312. X       {    while ( isspace(*p) ) p += dir;
  313. X        if ( !(*p == '/' && p[dir] == '*') ) break;
  314. X        p += dir;  p += dir;
  315. X        while ( !(*p == '*' && p[dir] == '/') )
  316. X           {    if ( *p == 0 ) return p;    /* multi-line comment?? */
  317. X            p += dir;
  318. X           }
  319. X        p += dir;  p += dir;
  320. X       }
  321. X    return p;
  322. X}
  323. X
  324. X/*
  325. X * Write blanks over part of a string.
  326. X */
  327. Xint
  328. Xwriteblanks(start, end)
  329. X    char *start;
  330. X    char *end;
  331. X{    char *p;
  332. X    for ( p = start; p < end; p++ ) *p = ' ';
  333. X    return 0;
  334. X}
  335. X
  336. X/*
  337. X * Test whether the string in buf is a function definition.
  338. X * The string may contain and/or end with a newline.
  339. X * Return as follows:
  340. X *    0 - definitely not a function definition;
  341. X *    1 - definitely a function definition;
  342. X *    -1 - may be the beginning of a function definition,
  343. X *        append another line and look again.
  344. X */
  345. Xint
  346. Xtest1(buf)
  347. X    char *buf;
  348. X{    register char *p = buf;
  349. X    char *bend;
  350. X    char *endfn;
  351. X    int contin;
  352. X    if ( !isidfirstchar(*p) )
  353. X        return 0;        /* no name at left margin */
  354. X    bend = skipspace(buf + strlen(buf) - 1, -1);
  355. X    switch ( *bend )
  356. X       {
  357. X    case ')': contin = 1; break;
  358. X    case '(':
  359. X    case ',': contin = -1; break;
  360. X    default: return 0;        /* not a function */
  361. X       }
  362. X    while ( isidchar(*p) ) p++;
  363. X    endfn = p;
  364. X    p = skipspace(p, 1);
  365. X    if ( *p++ != '(' )
  366. X        return 0;        /* not a function */
  367. X    p = skipspace(p, 1);
  368. X    if ( *p == ')' )
  369. X        return 0;        /* no parameters */
  370. X    /* Check that the apparent function name isn't a keyword. */
  371. X    /* We only need to check for keywords that could be followed */
  372. X    /* by a left parenthesis (which, unfortunately, is most of them). */
  373. X       {    static char *words[] =
  374. X           {    "asm", "auto", "case", "char", "const", "double",
  375. X            "extern", "float", "for", "if", "int", "long",
  376. X            "register", "return", "short", "signed", "sizeof",
  377. X            "static", "switch", "typedef", "unsigned",
  378. X            "void", "volatile", "while", 0
  379. X           };
  380. X        char **key = words;
  381. X        char *kp;
  382. X        int len = endfn - buf;
  383. X        while ( (kp = *key) != 0 )
  384. X           {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )
  385. X                return 0;    /* name is a keyword */
  386. X            key++;
  387. X           }
  388. X       }
  389. X    return contin;
  390. X}
  391. X
  392. Xint
  393. Xconvert1(buf, out)
  394. X    char *buf;
  395. X    FILE *out;
  396. X{    char *endfn = strchr(buf, '(') + 1;
  397. X    register char *p;
  398. X    char **breaks;
  399. X    unsigned num_breaks = 2;    /* for testing */
  400. X    char **btop;
  401. X    char **bp;
  402. X    char **ap;
  403. Xtop:    p = endfn;
  404. X    breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
  405. X    if ( breaks == 0 )
  406. X       {    /* Couldn't allocate break table, give up */
  407. X        fprintf(stderr, "Unable to allocate break table!\n");
  408. X        fputs(buf, out);
  409. X        return -1;
  410. X       }
  411. X    btop = breaks + num_breaks * 2 - 2;
  412. X    bp = breaks;
  413. X    /* Parse the argument list */
  414. X    do
  415. X       {    int level = 0;
  416. X        char *end = NULL;
  417. X        if ( bp >= btop )
  418. X           {    /* Filled up break table. */
  419. X            /* Allocate a bigger one and start over. */
  420. X            free((char *)breaks);
  421. X            num_breaks <<= 1;
  422. X            goto top;
  423. X           }
  424. X        *bp++ = p;
  425. X        /* Find the end of the argument */
  426. X        for ( ; end == NULL; p++ )
  427. X           {    switch(*p)
  428. X               {
  429. X            case ',': if ( !level ) end = p; break;
  430. X            case '(': level++; break;
  431. X            case ')': if ( --level < 0 ) end = p; break;
  432. X            case '/': p = skipspace(p, 1) - 1; break;
  433. X            default: ;
  434. X               }
  435. X           }
  436. X        p--;            /* back up over terminator */
  437. X        /* Find the name being declared. */
  438. X        /* This is complicated because of procedure and */
  439. X        /* array modifiers. */
  440. X        for ( ; ; )
  441. X           {    p = skipspace(p - 1, -1);
  442. X            switch ( *p )
  443. X               {
  444. X            case ']':    /* skip array dimension(s) */
  445. X            case ')':    /* skip procedure args OR name */
  446. X               {    int level = 1;
  447. X                while ( level )
  448. X                 switch ( *--p )
  449. X                   {
  450. X                case ']': case ')': level++; break;
  451. X                case '[': case '(': level--; break;
  452. X                case '/': p = skipspace(p, -1) + 1; break;
  453. X                default: ;
  454. X                   }
  455. X               }
  456. X                if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
  457. X                   {    /* We found the name being declared */
  458. X                    while ( !isidfirstchar(*p) )
  459. X                        p = skipspace(p, 1) + 1;
  460. X                    goto found;
  461. X                   }
  462. X                break;
  463. X            default: goto found;
  464. X               }
  465. X           }
  466. Xfound:        if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
  467. X           {    p++;
  468. X            if ( bp == breaks + 1 )    /* sole argument */
  469. X                writeblanks(breaks[0], p);
  470. X            else
  471. X                writeblanks(bp[-1] - 1, p);
  472. X            bp--;
  473. X           }
  474. X        else
  475. X           {    while ( isidchar(*p) ) p--;
  476. X            *bp++ = p+1;
  477. X           }
  478. X        p = end;
  479. X       }
  480. X    while ( *p++ == ',' );
  481. X    *bp = p;
  482. X    /* Make a special check for 'void' arglist */
  483. X    if ( bp == breaks+2 )
  484. X       {    p = skipspace(breaks[0], 1);
  485. X        if ( !strncmp(p, "void", 4) )
  486. X           {    p = skipspace(p+4, 1);
  487. X            if ( p == breaks[2] - 1 )
  488. X               {    bp = breaks;    /* yup, pretend arglist is empty */
  489. X                writeblanks(breaks[0], p + 1);
  490. X               }
  491. X           }
  492. X       }
  493. X    /* Put out the function name */
  494. X    p = buf;
  495. X    while ( p != endfn ) putc(*p, out), p++;
  496. X    /* Put out the declaration */
  497. X    for ( ap = breaks+1; ap < bp; ap += 2 )
  498. X       {    p = *ap;
  499. X        while ( isidchar(*p) ) putc(*p, out), p++;
  500. X        if ( ap < bp - 1 ) fputs(", ", out);
  501. X       }
  502. X    fputs(")  ", out);
  503. X    /* Put out the argument declarations */
  504. X    for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
  505. X    fputs(breaks[0], out);
  506. X    free((char *)breaks);
  507. X    return 0;
  508. X}
  509. END_OF_FILE
  510.   if test 16258 -ne `wc -c <'ansi2knr.c'`; then
  511.     echo shar: \"'ansi2knr.c'\" unpacked with wrong size!
  512.   fi
  513.   # end of 'ansi2knr.c'
  514. fi
  515. if test -f 'jmemansi.c' -a "${1}" != "-c" ; then 
  516.   echo shar: Will not clobber existing file \"'jmemansi.c'\"
  517. else
  518.   echo shar: Extracting \"'jmemansi.c'\" \(4303 characters\)
  519.   sed "s/^X//" >'jmemansi.c' <<'END_OF_FILE'
  520. X/*
  521. X * jmemansi.c  (jmemsys.c)
  522. X *
  523. X * Copyright (C) 1992, Thomas G. Lane.
  524. X * This file is part of the Independent JPEG Group's software.
  525. X * For conditions of distribution and use, see the accompanying README file.
  526. X *
  527. X * This file provides a simple generic implementation of the system-
  528. X * dependent portion of the JPEG memory manager.  This implementation
  529. X * assumes that you have the ANSI-standard library routine tmpfile().
  530. X * Also, the problem of determining the amount of memory available
  531. X * is shoved onto the user.
  532. X */
  533. X
  534. X#include "jinclude.h"
  535. X#include "jmemsys.h"
  536. X
  537. X#ifdef INCLUDES_ARE_ANSI
  538. X#include <stdlib.h>        /* to declare malloc(), free() */
  539. X#else
  540. Xextern void * malloc PP((size_t size));
  541. Xextern void free PP((void *ptr));
  542. X#endif
  543. X
  544. X#ifndef SEEK_SET        /* pre-ANSI systems may not define this; */
  545. X#define SEEK_SET  0        /* if not, assume 0 is correct */
  546. X#endif
  547. X
  548. X
  549. Xstatic external_methods_ptr methods; /* saved for access to error_exit */
  550. X
  551. Xstatic long total_used;        /* total memory requested so far */
  552. X
  553. X
  554. X/*
  555. X * Memory allocation and freeing are controlled by the regular library
  556. X * routines malloc() and free().
  557. X */
  558. X
  559. XGLOBAL void *
  560. Xjget_small (size_t sizeofobject)
  561. X{
  562. X  total_used += sizeofobject;
  563. X  return (void *) malloc(sizeofobject);
  564. X}
  565. X
  566. XGLOBAL void
  567. Xjfree_small (void * object)
  568. X{
  569. X  free(object);
  570. X}
  571. X
  572. X/*
  573. X * We assume NEED_FAR_POINTERS is not defined and so the separate entry points
  574. X * jget_large, jfree_large are not needed.
  575. X */
  576. X
  577. X
  578. X/*
  579. X * This routine computes the total memory space available for allocation.
  580. X * It's impossible to do this in a portable way; our current solution is
  581. X * to make the user tell us (with a default value set at compile time).
  582. X * If you can actually get the available space, it's a good idea to subtract
  583. X * a slop factor of 5% or so.
  584. X */
  585. X
  586. X#ifndef DEFAULT_MAX_MEM        /* so can override from makefile */
  587. X#define DEFAULT_MAX_MEM        1000000L /* default: one megabyte */
  588. X#endif
  589. X
  590. XGLOBAL long
  591. Xjmem_available (long min_bytes_needed, long max_bytes_needed)
  592. X{
  593. X  return methods->max_memory_to_use - total_used;
  594. X}
  595. X
  596. X
  597. X/*
  598. X * Backing store (temporary file) management.
  599. X * Backing store objects are only used when the value returned by
  600. X * jmem_available is less than the total space needed.  You can dispense
  601. X * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  602. X */
  603. X
  604. X
  605. XMETHODDEF void
  606. Xread_backing_store (backing_store_ptr info, void FAR * buffer_address,
  607. X            long file_offset, long byte_count)
  608. X{
  609. X  if (fseek(info->temp_file, file_offset, SEEK_SET))
  610. X    ERREXIT(methods, "fseek failed on temporary file");
  611. X  if (JFREAD(info->temp_file, buffer_address, byte_count)
  612. X      != (size_t) byte_count)
  613. X    ERREXIT(methods, "fread failed on temporary file");
  614. X}
  615. X
  616. X
  617. XMETHODDEF void
  618. Xwrite_backing_store (backing_store_ptr info, void FAR * buffer_address,
  619. X             long file_offset, long byte_count)
  620. X{
  621. X  if (fseek(info->temp_file, file_offset, SEEK_SET))
  622. X    ERREXIT(methods, "fseek failed on temporary file");
  623. X  if (JFWRITE(info->temp_file, buffer_address, byte_count)
  624. X      != (size_t) byte_count)
  625. X    ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
  626. X}
  627. X
  628. X
  629. XMETHODDEF void
  630. Xclose_backing_store (backing_store_ptr info)
  631. X{
  632. X  fclose(info->temp_file);
  633. X  /* Since this implementation uses tmpfile() to create the file,
  634. X   * no explicit file deletion is needed.
  635. X   */
  636. X}
  637. X
  638. X
  639. X/*
  640. X * Initial opening of a backing-store object.
  641. X *
  642. X * This version uses tmpfile(), which constructs a suitable file name
  643. X * behind the scenes.  We don't have to use temp_name[] at all;
  644. X * indeed, we can't even find out the actual name of the temp file.
  645. X */
  646. X
  647. XGLOBAL void
  648. Xjopen_backing_store (backing_store_ptr info, long total_bytes_needed)
  649. X{
  650. X  if ((info->temp_file = tmpfile()) == NULL)
  651. X    ERREXIT(methods, "Failed to create temporary file");
  652. X  info->read_backing_store = read_backing_store;
  653. X  info->write_backing_store = write_backing_store;
  654. X  info->close_backing_store = close_backing_store;
  655. X}
  656. X
  657. X
  658. X/*
  659. X * These routines take care of any system-dependent initialization and
  660. X * cleanup required.  Keep in mind that jmem_term may be called more than
  661. X * once.
  662. X */
  663. X
  664. XGLOBAL void
  665. Xjmem_init (external_methods_ptr emethods)
  666. X{
  667. X  methods = emethods;        /* save struct addr for error exit access */
  668. X  emethods->max_memory_to_use = DEFAULT_MAX_MEM;
  669. X  total_used = 0;
  670. X}
  671. X
  672. XGLOBAL void
  673. Xjmem_term (void)
  674. X{
  675. X  /* no work */
  676. X}
  677. END_OF_FILE
  678.   if test 4303 -ne `wc -c <'jmemansi.c'`; then
  679.     echo shar: \"'jmemansi.c'\" unpacked with wrong size!
  680.   fi
  681.   # end of 'jmemansi.c'
  682. fi
  683. if test -f 'jmemdos.c' -a "${1}" != "-c" ; then 
  684.   echo shar: Will not clobber existing file \"'jmemdos.c'\"
  685. else
  686.   echo shar: Extracting \"'jmemdos.c'\" \(17266 characters\)
  687.   sed "s/^X//" >'jmemdos.c' <<'END_OF_FILE'
  688. X/*
  689. X * jmemdos.c  (jmemsys.c)
  690. X *
  691. X * Copyright (C) 1992, Thomas G. Lane.
  692. X * This file is part of the Independent JPEG Group's software.
  693. X * For conditions of distribution and use, see the accompanying README file.
  694. X *
  695. X * This file provides an MS-DOS-compatible implementation of the system-
  696. X * dependent portion of the JPEG memory manager.  Temporary data can be
  697. X * stored in extended or expanded memory as well as in regular DOS files.
  698. X *
  699. X * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
  700. X * if you compile in a small-data memory model; it should NOT be defined if
  701. X * you use a large-data memory model.  This file is not recommended if you
  702. X * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
  703. X *
  704. X * Based on code contributed by Ge' Weijers.
  705. X */
  706. X
  707. X/*
  708. X * If you have both extended and expanded memory, you may want to change the
  709. X * order in which they are tried in jopen_backing_store.  On a 286 machine
  710. X * expanded memory is usually faster, since extended memory access involves
  711. X * an expensive protected-mode-and-back switch.  On 386 and better, extended
  712. X * memory is usually faster.  As distributed, the code tries extended memory
  713. X * first (what? not everyone has a 386? :-).
  714. X *
  715. X * You can disable use of extended/expanded memory entirely by altering these
  716. X * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
  717. X */
  718. X
  719. X#ifndef XMS_SUPPORTED
  720. X#define XMS_SUPPORTED  1
  721. X#endif
  722. X#ifndef EMS_SUPPORTED
  723. X#define EMS_SUPPORTED  1
  724. X#endif
  725. X
  726. X
  727. X#include "jinclude.h"
  728. X#include "jmemsys.h"
  729. X
  730. X#ifdef INCLUDES_ARE_ANSI
  731. X#include <stdlib.h>        /* to declare malloc(), free() */
  732. X#else
  733. Xextern void * malloc PP((size_t size));
  734. Xextern void free PP((void *ptr));
  735. X#endif
  736. X
  737. X#ifdef NEED_FAR_POINTERS
  738. X
  739. X#ifdef __TURBOC__
  740. X/* These definitions work for Borland C (Turbo C) */
  741. X#include <alloc.h>        /* need farmalloc(), farfree() */
  742. X#define far_malloc(x)    farmalloc(x)
  743. X#define far_free(x)    farfree(x)
  744. X#else
  745. X/* These definitions work for Microsoft C and compatible compilers */
  746. X#include <malloc.h>        /* need _fmalloc(), _ffree() */
  747. X#define far_malloc(x)    _fmalloc(x)
  748. X#define far_free(x)    _ffree(x)
  749. X#endif
  750. X
  751. X#endif
  752. X
  753. X#ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  754. X#define READ_BINARY    "r"
  755. X#else
  756. X#define READ_BINARY    "rb"
  757. X#endif
  758. X
  759. X
  760. X/*
  761. X * Declarations for assembly-language support routines (see jmemdosa.asm).
  762. X *
  763. X * The functions are declared "far" as are all pointer arguments;
  764. X * this ensures the assembly source code will work regardless of the
  765. X * compiler memory model.  We assume "short" is 16 bits, "long" is 32.
  766. X */
  767. X
  768. Xtypedef void far * XMSDRIVER;    /* actually a pointer to code */
  769. Xtypedef struct {        /* registers for calling XMS driver */
  770. X    unsigned short ax, dx, bx;
  771. X    void far * ds_si;
  772. X      } XMScontext;
  773. Xtypedef struct {        /* registers for calling EMS driver */
  774. X    unsigned short ax, dx, bx;
  775. X    void far * ds_si;
  776. X      } EMScontext;
  777. X
  778. XEXTERN short far jdos_open PP((short far * handle, char far * filename));
  779. XEXTERN short far jdos_close PP((short handle));
  780. XEXTERN short far jdos_seek PP((short handle, long offset));
  781. XEXTERN short far jdos_read PP((short handle, void far * buffer,
  782. X                   unsigned short count));
  783. XEXTERN short far jdos_write PP((short handle, void far * buffer,
  784. X                unsigned short count));
  785. XEXTERN void far jxms_getdriver PP((XMSDRIVER far *));
  786. XEXTERN void far jxms_calldriver PP((XMSDRIVER, XMScontext far *));
  787. XEXTERN short far jems_available PP((void));
  788. XEXTERN void far jems_calldriver PP((EMScontext far *));
  789. X
  790. X
  791. Xstatic external_methods_ptr methods; /* saved for access to error_exit */
  792. X
  793. Xstatic long total_used;        /* total FAR memory requested so far */
  794. X
  795. X
  796. X/*
  797. X * Selection of a file name for a temporary file.
  798. X * This is highly system-dependent, and you may want to customize it.
  799. X */
  800. X
  801. Xstatic int next_file_num;    /* to distinguish among several temp files */
  802. X
  803. XLOCAL void
  804. Xselect_file_name (char * fname)
  805. X{
  806. X  const char * env;
  807. X  char * ptr;
  808. X  FILE * tfile;
  809. X
  810. X  /* Keep generating file names till we find one that's not in use */
  811. X  for (;;) {
  812. X    /* Get temp directory name from environment TMP or TEMP variable;
  813. X     * if none, use "."
  814. X     */
  815. X    if ((env = (const char *) getenv("TMP")) == NULL)
  816. X      if ((env = (const char *) getenv("TEMP")) == NULL)
  817. X    env = ".";
  818. X    if (*env == '\0')        /* null string means "." */
  819. X      env = ".";
  820. X    ptr = fname;        /* copy name to fname */
  821. X    while (*env != '\0')
  822. X      *ptr++ = *env++;
  823. X    if (ptr[-1] != '\\' && ptr[-1] != '/')
  824. X      *ptr++ = '\\';        /* append backslash if not in env variable */
  825. X    /* Append a suitable file name */
  826. X    next_file_num++;        /* advance counter */
  827. X    sprintf(ptr, "JPG%03d.TMP", next_file_num);
  828. X    /* Probe to see if file name is already in use */
  829. X    if ((tfile = fopen(fname, READ_BINARY)) == NULL)
  830. X      break;
  831. X    fclose(tfile);        /* oops, it's there; close tfile & try again */
  832. X  }
  833. X}
  834. X
  835. X
  836. X/*
  837. X * Near-memory allocation and freeing are controlled by the regular library
  838. X * routines malloc() and free().
  839. X */
  840. X
  841. XGLOBAL void *
  842. Xjget_small (size_t sizeofobject)
  843. X{
  844. X  /* near data space is NOT counted in total_used */
  845. X#ifndef NEED_FAR_POINTERS
  846. X  total_used += sizeofobject;
  847. X#endif
  848. X  return (void *) malloc(sizeofobject);
  849. X}
  850. X
  851. XGLOBAL void
  852. Xjfree_small (void * object)
  853. X{
  854. X  free(object);
  855. X}
  856. X
  857. X
  858. X/*
  859. X * Far-memory allocation and freeing
  860. X */
  861. X
  862. X#ifdef NEED_FAR_POINTERS
  863. X
  864. XGLOBAL void FAR *
  865. Xjget_large (size_t sizeofobject)
  866. X{
  867. X  total_used += sizeofobject;
  868. X  return (void FAR *) far_malloc(sizeofobject);
  869. X}
  870. X
  871. XGLOBAL void
  872. Xjfree_large (void FAR * object)
  873. X{
  874. X  far_free(object);
  875. X}
  876. X
  877. X#endif
  878. X
  879. X
  880. X/*
  881. X * This routine computes the total memory space available for allocation.
  882. X * It's impossible to do this in a portable way; our current solution is
  883. X * to make the user tell us (with a default value set at compile time).
  884. X * If you can actually get the available space, it's a good idea to subtract
  885. X * a slop factor of 5% or so.
  886. X */
  887. X
  888. X#ifndef DEFAULT_MAX_MEM        /* so can override from makefile */
  889. X#define DEFAULT_MAX_MEM        300000L /* for total usage about 450K */
  890. X#endif
  891. X
  892. XGLOBAL long
  893. Xjmem_available (long min_bytes_needed, long max_bytes_needed)
  894. X{
  895. X  return methods->max_memory_to_use - total_used;
  896. X}
  897. X
  898. X
  899. X/*
  900. X * Backing store (temporary file) management.
  901. X * Backing store objects are only used when the value returned by
  902. X * jmem_available is less than the total space needed.  You can dispense
  903. X * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  904. X */
  905. X
  906. X/*
  907. X * For MS-DOS we support three types of backing storage:
  908. X *   1. Conventional DOS files.  We access these by direct DOS calls rather
  909. X *      than via the stdio package.  This provides a bit better performance,
  910. X *      but the real reason is that the buffers to be read or written are FAR.
  911. X *      The stdio library for small-data memory models can't cope with that.
  912. X *   2. Extended memory, accessed per the XMS V2.0 specification.
  913. X *   3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
  914. X * You'll need copies of those specs to make sense of the related code.
  915. X * The specs are available by Internet FTP from SIMTEL20 and its various
  916. X * mirror sites; see microsoft/xms20.arc and info/limems41.zip.
  917. X */
  918. X
  919. X
  920. X/*
  921. X * Access methods for a DOS file.
  922. X */
  923. X
  924. X
  925. XMETHODDEF void
  926. Xread_file_store (backing_store_ptr info, void FAR * buffer_address,
  927. X         long file_offset, long byte_count)
  928. X{
  929. X  if (jdos_seek(info->handle.file_handle, file_offset))
  930. X    ERREXIT(methods, "seek failed on temporary file");
  931. X  /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
  932. X  if (byte_count > 65535L)    /* safety check */
  933. X    ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
  934. X  if (jdos_read(info->handle.file_handle, buffer_address,
  935. X        (unsigned short) byte_count))
  936. X    ERREXIT(methods, "read failed on temporary file");
  937. X}
  938. X
  939. X
  940. XMETHODDEF void
  941. Xwrite_file_store (backing_store_ptr info, void FAR * buffer_address,
  942. X          long file_offset, long byte_count)
  943. X{
  944. X  if (jdos_seek(info->handle.file_handle, file_offset))
  945. X    ERREXIT(methods, "seek failed on temporary file");
  946. X  /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
  947. X  if (byte_count > 65535L)    /* safety check */
  948. X    ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
  949. X  if (jdos_write(info->handle.file_handle, buffer_address,
  950. X         (unsigned short) byte_count))
  951. X    ERREXIT(methods, "write failed on temporary file --- out of disk space?");
  952. X}
  953. X
  954. X
  955. XMETHODDEF void
  956. Xclose_file_store (backing_store_ptr info)
  957. X{
  958. X  jdos_close(info->handle.file_handle);    /* close the file */
  959. X  remove(info->temp_name);    /* delete the file */
  960. X/* If your system doesn't have remove(), try unlink() instead.
  961. X * remove() is the ANSI-standard name for this function, but
  962. X * unlink() was more common in pre-ANSI systems.
  963. X */
  964. X  TRACEMS1(methods, 1, "Closed DOS file %d", info->handle.file_handle);
  965. X}
  966. X
  967. X
  968. XLOCAL boolean
  969. Xopen_file_store (backing_store_ptr info, long total_bytes_needed)
  970. X{
  971. X  short handle;
  972. X  char tracemsg[TEMP_NAME_LENGTH+40];
  973. X
  974. X  select_file_name(info->temp_name);
  975. X  if (jdos_open((short far *) & handle, (char far *) info->temp_name))
  976. X    return FALSE;
  977. X  info->handle.file_handle = handle;
  978. X  info->read_backing_store = read_file_store;
  979. X  info->write_backing_store = write_file_store;
  980. X  info->close_backing_store = close_file_store;
  981. X  /* hack to get around TRACEMS' inability to handle string parameters */
  982. X  sprintf(tracemsg, "Opened DOS file %d  %s", handle, info->temp_name);
  983. X  TRACEMS(methods, 1, tracemsg);
  984. X  return TRUE;            /* succeeded */
  985. X}
  986. X
  987. X
  988. X/*
  989. X * Access methods for extended memory.
  990. X */
  991. X
  992. X#if XMS_SUPPORTED
  993. X
  994. Xstatic XMSDRIVER xms_driver;    /* saved address of XMS driver */
  995. X
  996. Xtypedef union {            /* either long offset or real-mode pointer */
  997. X    long offset;
  998. X    void far * ptr;
  999. X      } XMSPTR;
  1000. X
  1001. Xtypedef struct {        /* XMS move specification structure */
  1002. X    long length;
  1003. X    XMSH src_handle;
  1004. X    XMSPTR src;
  1005. X    XMSH dst_handle;
  1006. X    XMSPTR dst;
  1007. X      } XMSspec;
  1008. X
  1009. X#define ODD(X)    (((X) & 1L) != 0)
  1010. X
  1011. X
  1012. XMETHODDEF void
  1013. Xread_xms_store (backing_store_ptr info, void FAR * buffer_address,
  1014. X        long file_offset, long byte_count)
  1015. X{
  1016. X  XMScontext ctx;
  1017. X  XMSspec spec;
  1018. X  char endbuffer[2];
  1019. X
  1020. X  /* The XMS driver can't cope with an odd length, so handle the last byte
  1021. X   * specially if byte_count is odd.  We don't expect this to be common.
  1022. X   */
  1023. X
  1024. X  spec.length = byte_count & (~ 1L);
  1025. X  spec.src_handle = info->handle.xms_handle;
  1026. X  spec.src.offset = file_offset;
  1027. X  spec.dst_handle = 0;
  1028. X  spec.dst.ptr = buffer_address;
  1029. X  
  1030. X  ctx.ds_si = (void far *) & spec;
  1031. X  ctx.ax = 0x0b00;        /* EMB move */
  1032. X  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
  1033. X  if (ctx.ax != 1)
  1034. X    ERREXIT(methods, "read from extended memory failed");
  1035. X
  1036. X  if (ODD(byte_count)) {
  1037. X    read_xms_store(info, (void FAR *) endbuffer,
  1038. X           file_offset + byte_count - 1L, 2L);
  1039. X    ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
  1040. X  }
  1041. X}
  1042. X
  1043. X
  1044. XMETHODDEF void
  1045. Xwrite_xms_store (backing_store_ptr info, void FAR * buffer_address,
  1046. X         long file_offset, long byte_count)
  1047. X{
  1048. X  XMScontext ctx;
  1049. X  XMSspec spec;
  1050. X  char endbuffer[2];
  1051. X
  1052. X  /* The XMS driver can't cope with an odd length, so handle the last byte
  1053. X   * specially if byte_count is odd.  We don't expect this to be common.
  1054. X   */
  1055. X
  1056. X  spec.length = byte_count & (~ 1L);
  1057. X  spec.src_handle = 0;
  1058. X  spec.src.ptr = buffer_address;
  1059. X  spec.dst_handle = info->handle.xms_handle;
  1060. X  spec.dst.offset = file_offset;
  1061. X
  1062. X  ctx.ds_si = (void far *) & spec;
  1063. X  ctx.ax = 0x0b00;        /* EMB move */
  1064. X  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
  1065. X  if (ctx.ax != 1)
  1066. X    ERREXIT(methods, "write to extended memory failed");
  1067. X
  1068. X  if (ODD(byte_count)) {
  1069. X    read_xms_store(info, (void FAR *) endbuffer,
  1070. X           file_offset + byte_count - 1L, 2L);
  1071. X    endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
  1072. X    write_xms_store(info, (void FAR *) endbuffer,
  1073. X            file_offset + byte_count - 1L, 2L);
  1074. X  }
  1075. X}
  1076. X
  1077. X
  1078. XMETHODDEF void
  1079. Xclose_xms_store (backing_store_ptr info)
  1080. X{
  1081. X  XMScontext ctx;
  1082. X
  1083. X  ctx.dx = info->handle.xms_handle;
  1084. X  ctx.ax = 0x0a00;
  1085. X  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
  1086. X  TRACEMS1(methods, 1, "Freed XMS handle %u", info->handle.xms_handle);
  1087. X  /* we ignore any error return from the driver */
  1088. X}
  1089. X
  1090. X
  1091. XLOCAL boolean
  1092. Xopen_xms_store (backing_store_ptr info, long total_bytes_needed)
  1093. X{
  1094. X  XMScontext ctx;
  1095. X
  1096. X  /* Get address of XMS driver */
  1097. X  jxms_getdriver((XMSDRIVER far *) & xms_driver);
  1098. X  if (xms_driver == NULL)
  1099. X    return FALSE;        /* no driver to be had */
  1100. X
  1101. X  /* Get version number, must be >= 2.00 */
  1102. X  ctx.ax = 0x0000;
  1103. X  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
  1104. X  if (ctx.ax < (unsigned short) 0x0200)
  1105. X    return FALSE;
  1106. X
  1107. X  /* Try to get space (expressed in kilobytes) */
  1108. X  ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
  1109. X  ctx.ax = 0x0900;
  1110. X  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
  1111. X  if (ctx.ax != 1)
  1112. X    return FALSE;
  1113. X
  1114. X  /* Succeeded, save the handle and away we go */
  1115. X  info->handle.xms_handle = ctx.dx;
  1116. X  info->read_backing_store = read_xms_store;
  1117. X  info->write_backing_store = write_xms_store;
  1118. X  info->close_backing_store = close_xms_store;
  1119. X  TRACEMS1(methods, 1, "Obtained XMS handle %u", ctx.dx);
  1120. X  return TRUE;            /* succeeded */
  1121. X}
  1122. X
  1123. X#endif /* XMS_SUPPORTED */
  1124. X
  1125. X
  1126. X/*
  1127. X * Access methods for expanded memory.
  1128. X */
  1129. X
  1130. X#if EMS_SUPPORTED
  1131. X
  1132. Xtypedef union {            /* either offset/page or real-mode pointer */
  1133. X    struct { unsigned short offset, page; } ems;
  1134. X    void far * ptr;
  1135. X      } EMSPTR;
  1136. X
  1137. Xtypedef struct {        /* EMS move specification structure */
  1138. X    long length;
  1139. X    char src_type;        /* 1 = EMS, 0 = conventional memory */
  1140. X    EMSH src_handle;    /* use 0 if conventional memory */
  1141. X    EMSPTR src;
  1142. X    char dst_type;
  1143. X    EMSH dst_handle;
  1144. X    EMSPTR dst;
  1145. X      } EMSspec;
  1146. X
  1147. X#define EMSPAGESIZE    16384L    /* gospel, see the EMS specs */
  1148. X
  1149. X#define HIBYTE(W)  (((W) >> 8) & 0xFF)
  1150. X#define LOBYTE(W)  ((W) & 0xFF)
  1151. X
  1152. X
  1153. XMETHODDEF void
  1154. Xread_ems_store (backing_store_ptr info, void FAR * buffer_address,
  1155. X        long file_offset, long byte_count)
  1156. X{
  1157. X  EMScontext ctx;
  1158. X  EMSspec spec;
  1159. X
  1160. X  spec.length = byte_count;
  1161. X  spec.src_type = 1;
  1162. X  spec.src_handle = info->handle.ems_handle;
  1163. X  spec.src.ems.page = (unsigned short) (file_offset / EMSPAGESIZE);
  1164. X  spec.src.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE);
  1165. X  spec.dst_type = 0;
  1166. X  spec.dst_handle = 0;
  1167. X  spec.dst.ptr = buffer_address;
  1168. X  
  1169. X  ctx.ds_si = (void far *) & spec;
  1170. X  ctx.ax = 0x5700;        /* move memory region */
  1171. X  jems_calldriver((EMScontext far *) & ctx);
  1172. X  if (HIBYTE(ctx.ax) != 0)
  1173. X    ERREXIT(methods, "read from expanded memory failed");
  1174. X}
  1175. X
  1176. X
  1177. XMETHODDEF void
  1178. Xwrite_ems_store (backing_store_ptr info, void FAR * buffer_address,
  1179. X         long file_offset, long byte_count)
  1180. X{
  1181. X  EMScontext ctx;
  1182. X  EMSspec spec;
  1183. X
  1184. X  spec.length = byte_count;
  1185. X  spec.src_type = 0;
  1186. X  spec.src_handle = 0;
  1187. X  spec.src.ptr = buffer_address;
  1188. X  spec.dst_type = 1;
  1189. X  spec.dst_handle = info->handle.ems_handle;
  1190. X  spec.dst.ems.page = (unsigned short) (file_offset / EMSPAGESIZE);
  1191. X  spec.dst.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE);
  1192. X  
  1193. X  ctx.ds_si = (void far *) & spec;
  1194. X  ctx.ax = 0x5700;        /* move memory region */
  1195. X  jems_calldriver((EMScontext far *) & ctx);
  1196. X  if (HIBYTE(ctx.ax) != 0)
  1197. X    ERREXIT(methods, "write to expanded memory failed");
  1198. X}
  1199. X
  1200. X
  1201. XMETHODDEF void
  1202. Xclose_ems_store (backing_store_ptr info)
  1203. X{
  1204. X  EMScontext ctx;
  1205. X
  1206. X  ctx.ax = 0x4500;
  1207. X  ctx.dx = info->handle.ems_handle;
  1208. X  jems_calldriver((EMScontext far *) & ctx);
  1209. X  TRACEMS1(methods, 1, "Freed EMS handle %u", info->handle.ems_handle);
  1210. X  /* we ignore any error return from the driver */
  1211. X}
  1212. X
  1213. X
  1214. XLOCAL boolean
  1215. Xopen_ems_store (backing_store_ptr info, long total_bytes_needed)
  1216. X{
  1217. X  EMScontext ctx;
  1218. X
  1219. X  /* Is EMS driver there? */
  1220. X  if (! jems_available())
  1221. X    return FALSE;
  1222. X
  1223. X  /* Get status, make sure EMS is OK */
  1224. X  ctx.ax = 0x4000;
  1225. X  jems_calldriver((EMScontext far *) & ctx);
  1226. X  if (HIBYTE(ctx.ax) != 0)
  1227. X    return FALSE;
  1228. X
  1229. X  /* Get version, must be >= 4.0 */
  1230. X  ctx.ax = 0x4600;
  1231. X  jems_calldriver((EMScontext far *) & ctx);
  1232. X  if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
  1233. X    return FALSE;
  1234. X
  1235. X  /* Try to allocate requested space */
  1236. X  ctx.ax = 0x4300;
  1237. X  ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
  1238. X  jems_calldriver((EMScontext far *) & ctx);
  1239. X  if (HIBYTE(ctx.ax) != 0)
  1240. X    return FALSE;
  1241. X
  1242. X  /* Succeeded, save the handle and away we go */
  1243. X  info->handle.ems_handle = ctx.dx;
  1244. X  info->read_backing_store = read_ems_store;
  1245. X  info->write_backing_store = write_ems_store;
  1246. X  info->close_backing_store = close_ems_store;
  1247. X  TRACEMS1(methods, 1, "Obtained EMS handle %u", ctx.dx);
  1248. X  return TRUE;            /* succeeded */
  1249. X}
  1250. X
  1251. X#endif /* EMS_SUPPORTED */
  1252. X
  1253. X
  1254. X/*
  1255. X * Initial opening of a backing-store object.
  1256. X */
  1257. X
  1258. XGLOBAL void
  1259. Xjopen_backing_store (backing_store_ptr info, long total_bytes_needed)
  1260. X{
  1261. X  /* Try extended memory, then expanded memory, then regular file. */
  1262. X#if XMS_SUPPORTED
  1263. X  if (open_xms_store(info, total_bytes_needed))
  1264. X    return;
  1265. X#endif
  1266. X#if EMS_SUPPORTED
  1267. X  if (open_ems_store(info, total_bytes_needed))
  1268. X    return;
  1269. X#endif
  1270. X  if (open_file_store(info, total_bytes_needed))
  1271. X    return;
  1272. X  ERREXIT(methods, "Failed to create temporary file");
  1273. X}
  1274. X
  1275. X
  1276. X/*
  1277. X * These routines take care of any system-dependent initialization and
  1278. X * cleanup required.  Keep in mind that jmem_term may be called more than
  1279. X * once.
  1280. X */
  1281. X
  1282. XGLOBAL void
  1283. Xjmem_init (external_methods_ptr emethods)
  1284. X{
  1285. X  methods = emethods;        /* save struct addr for error exit access */
  1286. X  emethods->max_memory_to_use = DEFAULT_MAX_MEM;
  1287. X  total_used = 0;
  1288. X  next_file_num = 0;
  1289. X}
  1290. X
  1291. XGLOBAL void
  1292. Xjmem_term (void)
  1293. X{
  1294. X  /* no work */
  1295. X}
  1296. END_OF_FILE
  1297.   if test 17266 -ne `wc -c <'jmemdos.c'`; then
  1298.     echo shar: \"'jmemdos.c'\" unpacked with wrong size!
  1299.   fi
  1300.   # end of 'jmemdos.c'
  1301. fi
  1302. if test -f 'jversion.h' -a "${1}" != "-c" ; then 
  1303.   echo shar: Will not clobber existing file \"'jversion.h'\"
  1304. else
  1305.   echo shar: Extracting \"'jversion.h'\" \(358 characters\)
  1306.   sed "s/^X//" >'jversion.h' <<'END_OF_FILE'
  1307. X/*
  1308. X * jversion.h
  1309. X *
  1310. X * Copyright (C) 1991, 1992, Thomas G. Lane.
  1311. X * This file is part of the Independent JPEG Group's software.
  1312. X * For conditions of distribution and use, see the accompanying README file.
  1313. X *
  1314. X * This file contains software version identification.
  1315. X */
  1316. X
  1317. X
  1318. X#define JVERSION    "3  17-Mar-92"
  1319. X
  1320. X#define JCOPYRIGHT    "Copyright (C) 1992, Thomas G. Lane"
  1321. END_OF_FILE
  1322.   if test 358 -ne `wc -c <'jversion.h'`; then
  1323.     echo shar: \"'jversion.h'\" unpacked with wrong size!
  1324.   fi
  1325.   # end of 'jversion.h'
  1326. fi
  1327. if test -f 'jwrjfif.c' -a "${1}" != "-c" ; then 
  1328.   echo shar: Will not clobber existing file \"'jwrjfif.c'\"
  1329. else
  1330.   echo shar: Extracting \"'jwrjfif.c'\" \(11708 characters\)
  1331.   sed "s/^X//" >'jwrjfif.c' <<'END_OF_FILE'
  1332. X/*
  1333. X * jwrjfif.c
  1334. X *
  1335. X * Copyright (C) 1991, 1992, Thomas G. Lane.
  1336. X * This file is part of the Independent JPEG Group's software.
  1337. X * For conditions of distribution and use, see the accompanying README file.
  1338. X *
  1339. X * This file contains routines to write standard JPEG file headers/markers.
  1340. X * The file format created is a raw JPEG data stream with (optionally) an
  1341. X * APP0 marker per the JFIF spec.  This will handle baseline and
  1342. X * JFIF-convention JPEG files, although there is currently no provision
  1343. X * for inserting a thumbnail image in the JFIF header.
  1344. X *
  1345. X * These routines may need modification for non-Unix environments or
  1346. X * specialized applications.  As they stand, they assume output to
  1347. X * an ordinary stdio stream.  However, the changes to write to something
  1348. X * else are localized in the macros appearing just below.
  1349. X *
  1350. X * These routines are invoked via the methods write_file_header,
  1351. X * write_scan_header, write_jpeg_data, write_scan_trailer, and
  1352. X * write_file_trailer.
  1353. X */
  1354. X
  1355. X#include "jinclude.h"
  1356. X
  1357. X#ifdef JFIF_SUPPORTED
  1358. X
  1359. X
  1360. X/*
  1361. X * To output to something other than a stdio stream, you'd need to redefine
  1362. X * these macros.
  1363. X */
  1364. X
  1365. X/* Write a single byte */
  1366. X#define emit_byte(cinfo,x)  putc((x), cinfo->output_file)
  1367. X
  1368. X/* Write some bytes from a (char *) buffer */
  1369. X#define WRITE_BYTES(cinfo,dataptr,datacount)  \
  1370. X  { if (JFWRITE(cinfo->output_file, dataptr, datacount) \
  1371. X    != (size_t) (datacount)) \
  1372. X      ERREXIT(cinfo->emethods, "Output file write error"); }
  1373. X
  1374. X/* Clean up and verify successful output */
  1375. X#define CHECK_OUTPUT(cinfo)  \
  1376. X  { fflush(cinfo->output_file); \
  1377. X    if (ferror(cinfo->output_file)) \
  1378. X      ERREXIT(cinfo->emethods, "Output file write error"); }
  1379. X
  1380. X
  1381. X/* End of stdio-specific code. */
  1382. X
  1383. X
  1384. Xtypedef enum {            /* JPEG marker codes */
  1385. X  M_SOF0  = 0xc0,
  1386. X  M_SOF1  = 0xc1,
  1387. X  M_SOF2  = 0xc2,
  1388. X  M_SOF3  = 0xc3,
  1389. X  
  1390. X  M_SOF5  = 0xc5,
  1391. X  M_SOF6  = 0xc6,
  1392. X  M_SOF7  = 0xc7,
  1393. X  
  1394. X  M_JPG   = 0xc8,
  1395. X  M_SOF9  = 0xc9,
  1396. X  M_SOF10 = 0xca,
  1397. X  M_SOF11 = 0xcb,
  1398. X  
  1399. X  M_SOF13 = 0xcd,
  1400. X  M_SOF14 = 0xce,
  1401. X  M_SOF15 = 0xcf,
  1402. X  
  1403. X  M_DHT   = 0xc4,
  1404. X  
  1405. X  M_DAC   = 0xcc,
  1406. X  
  1407. X  M_RST0  = 0xd0,
  1408. X  M_RST1  = 0xd1,
  1409. X  M_RST2  = 0xd2,
  1410. X  M_RST3  = 0xd3,
  1411. X  M_RST4  = 0xd4,
  1412. X  M_RST5  = 0xd5,
  1413. X  M_RST6  = 0xd6,
  1414. X  M_RST7  = 0xd7,
  1415. X  
  1416. X  M_SOI   = 0xd8,
  1417. X  M_EOI   = 0xd9,
  1418. X  M_SOS   = 0xda,
  1419. X  M_DQT   = 0xdb,
  1420. X  M_DNL   = 0xdc,
  1421. X  M_DRI   = 0xdd,
  1422. X  M_DHP   = 0xde,
  1423. X  M_EXP   = 0xdf,
  1424. X  
  1425. X  M_APP0  = 0xe0,
  1426. X  M_APP15 = 0xef,
  1427. X  
  1428. X  M_JPG0  = 0xf0,
  1429. X  M_JPG13 = 0xfd,
  1430. X  M_COM   = 0xfe,
  1431. X  
  1432. X  M_TEM   = 0x01,
  1433. X  
  1434. X  M_ERROR = 0x100
  1435. X} JPEG_MARKER;
  1436. X
  1437. X
  1438. XLOCAL void
  1439. Xemit_marker (compress_info_ptr cinfo, JPEG_MARKER mark)
  1440. X/* Emit a marker code */
  1441. X{
  1442. X  emit_byte(cinfo, 0xFF);
  1443. X  emit_byte(cinfo, mark);
  1444. X}
  1445. X
  1446. X
  1447. XLOCAL void
  1448. Xemit_2bytes (compress_info_ptr cinfo, int value)
  1449. X/* Emit a 2-byte integer; these are always MSB first in JPEG files */
  1450. X{
  1451. X  emit_byte(cinfo, (value >> 8) & 0xFF);
  1452. X  emit_byte(cinfo, value & 0xFF);
  1453. X}
  1454. X
  1455. X
  1456. XLOCAL int
  1457. Xemit_dqt (compress_info_ptr cinfo, int index)
  1458. X/* Emit a DQT marker */
  1459. X/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
  1460. X{
  1461. X  QUANT_TBL_PTR data = cinfo->quant_tbl_ptrs[index];
  1462. X  int prec = 0;
  1463. X  int i;
  1464. X  
  1465. X  for (i = 0; i < DCTSIZE2; i++) {
  1466. X    if (data[i] > 255)
  1467. X      prec = 1;
  1468. X  }
  1469. X
  1470. X  emit_marker(cinfo, M_DQT);
  1471. X  
  1472. X  emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
  1473. X  
  1474. X  emit_byte(cinfo, index + (prec<<4));
  1475. X  
  1476. X  for (i = 0; i < DCTSIZE2; i++) {
  1477. X    if (prec)
  1478. X      emit_byte(cinfo, data[i] >> 8);
  1479. X    emit_byte(cinfo, data[i] & 0xFF);
  1480. X  }
  1481. X
  1482. X  return prec;
  1483. X}
  1484. X
  1485. X
  1486. XLOCAL void
  1487. Xemit_dht (compress_info_ptr cinfo, int index, boolean is_ac)
  1488. X/* Emit a DHT marker */
  1489. X{
  1490. X  HUFF_TBL * htbl;
  1491. X  int length, i;
  1492. X  
  1493. X  if (is_ac) {
  1494. X    htbl = cinfo->ac_huff_tbl_ptrs[index];
  1495. X    index += 0x10;        /* output index has AC bit set */
  1496. X  } else {
  1497. X    htbl = cinfo->dc_huff_tbl_ptrs[index];
  1498. X  }
  1499. X
  1500. X  if (htbl == NULL)
  1501. X    ERREXIT1(cinfo->emethods, "Huffman table 0x%02x was not defined", index);
  1502. X  
  1503. X  if (! htbl->sent_table) {
  1504. X    emit_marker(cinfo, M_DHT);
  1505. X    
  1506. X    length = 0;
  1507. X    for (i = 1; i <= 16; i++)
  1508. X      length += htbl->bits[i];
  1509. X    
  1510. X    emit_2bytes(cinfo, length + 2 + 1 + 16);
  1511. X    emit_byte(cinfo, index);
  1512. X    
  1513. X    for (i = 1; i <= 16; i++)
  1514. X      emit_byte(cinfo, htbl->bits[i]);
  1515. X    
  1516. X    for (i = 0; i < length; i++)
  1517. X      emit_byte(cinfo, htbl->huffval[i]);
  1518. X    
  1519. X    htbl->sent_table = TRUE;
  1520. X  }
  1521. X}
  1522. X
  1523. X
  1524. XLOCAL void
  1525. Xemit_dac (compress_info_ptr cinfo)
  1526. X/* Emit a DAC marker */
  1527. X/* Since the useful info is so small, we want to emit all the tables in */
  1528. X/* one DAC marker.  Therefore this routine does its own scan of the table. */
  1529. X{
  1530. X  char dc_in_use[NUM_ARITH_TBLS];
  1531. X  char ac_in_use[NUM_ARITH_TBLS];
  1532. X  int length, i;
  1533. X  
  1534. X  for (i = 0; i < NUM_ARITH_TBLS; i++)
  1535. X    dc_in_use[i] = ac_in_use[i] = 0;
  1536. X  
  1537. X  for (i = 0; i < cinfo->num_components; i++) {
  1538. X    dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1;
  1539. X    ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1;
  1540. X  }
  1541. X  
  1542. X  length = 0;
  1543. X  for (i = 0; i < NUM_ARITH_TBLS; i++)
  1544. X    length += dc_in_use[i] + ac_in_use[i];
  1545. X  
  1546. X  emit_marker(cinfo, M_DAC);
  1547. X  
  1548. X  emit_2bytes(cinfo, length*2 + 2);
  1549. X  
  1550. X  for (i = 0; i < NUM_ARITH_TBLS; i++) {
  1551. X    if (dc_in_use[i]) {
  1552. X      emit_byte(cinfo, i);
  1553. X      emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
  1554. X    }
  1555. X    if (ac_in_use[i]) {
  1556. X      emit_byte(cinfo, i + 0x10);
  1557. X      emit_byte(cinfo, cinfo->arith_ac_K[i]);
  1558. X    }
  1559. X  }
  1560. X}
  1561. X
  1562. X
  1563. XLOCAL void
  1564. Xemit_dri (compress_info_ptr cinfo)
  1565. X/* Emit a DRI marker */
  1566. X{
  1567. X  emit_marker(cinfo, M_DRI);
  1568. X  
  1569. X  emit_2bytes(cinfo, 4);    /* fixed length */
  1570. X
  1571. X  emit_2bytes(cinfo, (int) cinfo->restart_interval);
  1572. X}
  1573. X
  1574. X
  1575. XLOCAL void
  1576. Xemit_sof (compress_info_ptr cinfo, JPEG_MARKER code)
  1577. X/* Emit a SOF marker */
  1578. X{
  1579. X  int i;
  1580. X  
  1581. X  emit_marker(cinfo, code);
  1582. X  
  1583. X  emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
  1584. X
  1585. X  if (cinfo->image_height > 65535L || cinfo->image_width > 65535L)
  1586. X    ERREXIT(cinfo->emethods, "Maximum image dimension for JFIF is 65535 pixels");
  1587. X
  1588. X  emit_byte(cinfo, cinfo->data_precision);
  1589. X  emit_2bytes(cinfo, (int) cinfo->image_height);
  1590. X  emit_2bytes(cinfo, (int) cinfo->image_width);
  1591. X
  1592. X  emit_byte(cinfo, cinfo->num_components);
  1593. X
  1594. X  for (i = 0; i < cinfo->num_components; i++) {
  1595. X    emit_byte(cinfo, cinfo->comp_info[i].component_id);
  1596. X    emit_byte(cinfo, (cinfo->comp_info[i].h_samp_factor << 4)
  1597. X             + cinfo->comp_info[i].v_samp_factor);
  1598. X    emit_byte(cinfo, cinfo->comp_info[i].quant_tbl_no);
  1599. X  }
  1600. X}
  1601. X
  1602. X
  1603. XLOCAL void
  1604. Xemit_sos (compress_info_ptr cinfo)
  1605. X/* Emit a SOS marker */
  1606. X{
  1607. X  int i;
  1608. X  
  1609. X  emit_marker(cinfo, M_SOS);
  1610. X  
  1611. X  emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
  1612. X  
  1613. X  emit_byte(cinfo, cinfo->comps_in_scan);
  1614. X  
  1615. X  for (i = 0; i < cinfo->comps_in_scan; i++) {
  1616. X    emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id);
  1617. X    emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4)
  1618. X             + cinfo->cur_comp_info[i]->ac_tbl_no);
  1619. X  }
  1620. X
  1621. X  emit_byte(cinfo, 0);        /* Spectral selection start */
  1622. X  emit_byte(cinfo, DCTSIZE2-1);    /* Spectral selection end */
  1623. X  emit_byte(cinfo, 0);        /* Successive approximation */
  1624. X}
  1625. X
  1626. X
  1627. XLOCAL void
  1628. Xemit_jfif_app0 (compress_info_ptr cinfo)
  1629. X/* Emit a JFIF-compliant APP0 marker */
  1630. X{
  1631. X  /*
  1632. X   * Length of APP0 block    (2 bytes)
  1633. X   * Block ID            (4 bytes - ASCII "JFIF")
  1634. X   * Zero byte            (1 byte to terminate the ID string)
  1635. X   * Version Major, Minor    (2 bytes - 0x01, 0x01)
  1636. X   * Units            (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
  1637. X   * Xdpu            (2 bytes - dots per unit horizontal)
  1638. X   * Ydpu            (2 bytes - dots per unit vertical)
  1639. X   * Thumbnail X size        (1 byte)
  1640. X   * Thumbnail Y size        (1 byte)
  1641. X   */
  1642. X  
  1643. X  emit_marker(cinfo, M_APP0);
  1644. X  
  1645. X  emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
  1646. X
  1647. X  emit_byte(cinfo, 'J');    /* Identifier */
  1648. X  emit_byte(cinfo, 'F');
  1649. X  emit_byte(cinfo, 'I');
  1650. X  emit_byte(cinfo, 'F');
  1651. X  emit_byte(cinfo, 0);
  1652. X  emit_byte(cinfo, 1);        /* Major version */
  1653. X  emit_byte(cinfo, 1);        /* Minor version */
  1654. X  emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
  1655. X  emit_2bytes(cinfo, (int) cinfo->X_density);
  1656. X  emit_2bytes(cinfo, (int) cinfo->Y_density);
  1657. X  emit_byte(cinfo, 0);        /* No thumbnail image */
  1658. X  emit_byte(cinfo, 0);
  1659. X}
  1660. X
  1661. X
  1662. X/*
  1663. X * Write the file header.
  1664. X */
  1665. X
  1666. X
  1667. XMETHODDEF void
  1668. Xwrite_file_header (compress_info_ptr cinfo)
  1669. X{
  1670. X  char qt_in_use[NUM_QUANT_TBLS];
  1671. X  int i, prec;
  1672. X  boolean is_baseline;
  1673. X  
  1674. X  emit_marker(cinfo, M_SOI);    /* first the SOI */
  1675. X
  1676. X  if (cinfo->write_JFIF_header)    /* next an optional JFIF APP0 */
  1677. X    emit_jfif_app0(cinfo);
  1678. X
  1679. X  /* Emit DQT for each quantization table. */
  1680. X  /* Note that doing it here means we can't adjust the QTs on-the-fly. */
  1681. X  /* If we did want to do that, we'd have a problem with checking precision */
  1682. X  /* for the is_baseline determination. */
  1683. X
  1684. X  for (i = 0; i < NUM_QUANT_TBLS; i++)
  1685. X    qt_in_use[i] = 0;
  1686. X
  1687. X  for (i = 0; i < cinfo->num_components; i++)
  1688. X    qt_in_use[cinfo->comp_info[i].quant_tbl_no] = 1;
  1689. X
  1690. X  prec = 0;
  1691. X  for (i = 0; i < NUM_QUANT_TBLS; i++) {
  1692. X    if (qt_in_use[i])
  1693. X      prec += emit_dqt(cinfo, i);
  1694. X  }
  1695. X  /* now prec is nonzero iff there are any 16-bit quant tables. */
  1696. X
  1697. X  if (cinfo->restart_interval)
  1698. X    emit_dri(cinfo);
  1699. X
  1700. X  /* Check for a non-baseline specification. */
  1701. X  /* Note we assume that Huffman table numbers won't be changed later. */
  1702. X  is_baseline = TRUE;
  1703. X  if (cinfo->arith_code || (cinfo->data_precision != 8))
  1704. X    is_baseline = FALSE;
  1705. X  for (i = 0; i < cinfo->num_components; i++) {
  1706. X    if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1)
  1707. X      is_baseline = FALSE;
  1708. X  }
  1709. X  if (prec && is_baseline) {
  1710. X    is_baseline = FALSE;
  1711. X    /* If it's baseline except for quantizer size, warn the user */
  1712. X    TRACEMS(cinfo->emethods, 0,
  1713. X        "Caution: quantization tables are too coarse for baseline JPEG");
  1714. X  }
  1715. X
  1716. X
  1717. X  /* Emit the proper SOF marker */
  1718. X  if (cinfo->arith_code)
  1719. X    emit_sof(cinfo, M_SOF9);    /* SOF code for arithmetic coding */
  1720. X  else if (is_baseline)
  1721. X    emit_sof(cinfo, M_SOF0);    /* SOF code for baseline implementation */
  1722. X  else
  1723. X    emit_sof(cinfo, M_SOF1);    /* SOF code for non-baseline Huffman file */
  1724. X}
  1725. X
  1726. X
  1727. X/*
  1728. X * Write the start of a scan (everything through the SOS marker).
  1729. X */
  1730. X
  1731. XMETHODDEF void
  1732. Xwrite_scan_header (compress_info_ptr cinfo)
  1733. X{
  1734. X  int i;
  1735. X
  1736. X  if (cinfo->arith_code) {
  1737. X    /* Emit arith conditioning info.  We will have some duplication
  1738. X     * if the file has multiple scans, but it's so small it's hardly
  1739. X     * worth worrying about.
  1740. X     */
  1741. X    emit_dac(cinfo);
  1742. X  } else {
  1743. X    /* Emit Huffman tables.  Note that emit_dht takes care of
  1744. X     * suppressing duplicate tables.
  1745. X     */
  1746. X    for (i = 0; i < cinfo->comps_in_scan; i++) {
  1747. X      emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE);
  1748. X      emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE);
  1749. X    }
  1750. X  }
  1751. X
  1752. X  emit_sos(cinfo);
  1753. X}
  1754. X
  1755. X
  1756. X/*
  1757. X * Write some bytes of compressed data within a scan.
  1758. X */
  1759. X
  1760. XMETHODDEF void
  1761. Xwrite_jpeg_data (compress_info_ptr cinfo, char *dataptr, int datacount)
  1762. X{
  1763. X  WRITE_BYTES(cinfo, dataptr, datacount);
  1764. X}
  1765. X
  1766. X
  1767. X/*
  1768. X * Finish up after a compressed scan (series of write_jpeg_data calls).
  1769. X */
  1770. X
  1771. XMETHODDEF void
  1772. Xwrite_scan_trailer (compress_info_ptr cinfo)
  1773. X{
  1774. X  /* no work needed in this format */
  1775. X}
  1776. X
  1777. X
  1778. X/*
  1779. X * Finish up at the end of the file.
  1780. X */
  1781. X
  1782. XMETHODDEF void
  1783. Xwrite_file_trailer (compress_info_ptr cinfo)
  1784. X{
  1785. X  emit_marker(cinfo, M_EOI);
  1786. X  /* Make sure we wrote the output file OK */
  1787. X  CHECK_OUTPUT(cinfo);
  1788. X}
  1789. X
  1790. X
  1791. X/*
  1792. X * The method selection routine for standard JPEG header writing.
  1793. X * This should be called from c_ui_method_selection if appropriate.
  1794. X */
  1795. X
  1796. XGLOBAL void
  1797. Xjselwjfif (compress_info_ptr cinfo)
  1798. X{
  1799. X  cinfo->methods->write_file_header = write_file_header;
  1800. X  cinfo->methods->write_scan_header = write_scan_header;
  1801. X  cinfo->methods->write_jpeg_data = write_jpeg_data;
  1802. X  cinfo->methods->write_scan_trailer = write_scan_trailer;
  1803. X  cinfo->methods->write_file_trailer = write_file_trailer;
  1804. X}
  1805. X
  1806. X#endif /* JFIF_SUPPORTED */
  1807. END_OF_FILE
  1808.   if test 11708 -ne `wc -c <'jwrjfif.c'`; then
  1809.     echo shar: \"'jwrjfif.c'\" unpacked with wrong size!
  1810.   fi
  1811.   # end of 'jwrjfif.c'
  1812. fi
  1813. echo shar: End of archive 12 \(of 18\).
  1814. cp /dev/null ark12isdone
  1815. MISSING=""
  1816. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1817.     if test ! -f ark${I}isdone ; then
  1818.     MISSING="${MISSING} ${I}"
  1819.     fi
  1820. done
  1821. if test "${MISSING}" = "" ; then
  1822.     echo You have unpacked all 18 archives.
  1823.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1824. else
  1825.     echo You still must unpack the following archives:
  1826.     echo "        " ${MISSING}
  1827. fi
  1828. exit 0
  1829. exit 0 # Just in case...
  1830.