The Independent JPEG Group's JPEG software v1
diff --git a/README b/README
new file mode 100644
index 0000000..9a2a1bb
--- /dev/null
+++ b/README
@@ -0,0 +1,391 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release of  7-Oct-91
+===============================
+
+This distribution contains the first public release of the Independent JPEG
+Group's free JPEG software.  You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+This software is still undergoing revision.  Updated versions may be obtained
+by anonymous FTP to uunet.uu.net; look under directory /graphics/jpeg.  This
+particular version will be archived as jpegsrc.v1.tar.Z.  If you don't have
+access to Internet FTP, UUNET's archives are also available via UUCP; contact
+postmaster@uunet.uu.net for information on retrieving files that way.
+
+Please report any problems with this software to jpeg-info@uunet.uu.net.
+
+If you intend to become a serious user of this software, please contact
+jpeg-info@uunet to be added to our electronic mailing list.  Then you'll be
+notified of updates and have a chance to participate in discussions, etc.
+
+This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, and other
+members of the independent JPEG group.
+
+
+DISCLAIMER
+==========
+
+THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED.  It is not guaranteed to be
+useful for anything, nor to be compatible with subsequent releases, nor to be
+an accurate implementation of the JPEG standard.  (See LEGAL ISSUES for even
+more disclaimers.)
+
+
+WHAT'S HERE
+===========
+
+This distribution contains software to implement JPEG image compression and
+decompression.  JPEG is a standardized compression method for full-color and
+gray-scale images.  JPEG is intended for "real-world" scenes; cartoons and
+other non-realistic images are not its strong suit.  JPEG is lossy, meaning
+that the output image is not necessarily identical to the input image.  Hence
+you should not use JPEG if you have to have identical output bits.  However,
+on typical images of real-world scenes, very good compression levels can be
+obtained with hardly any visible change, and amazingly high compression levels
+can be obtained if you can tolerate a low-quality image.  For more details,
+see the references, or just experiment with various compression settings.
+
+The software implements JPEG baseline and extended-sequential compression
+processes.  Provision is made for supporting all variants of these processes,
+although some uncommon parameter settings aren't implemented yet.  For legal
+reasons, we are not distributing code for the arithmetic-coding process; see
+LEGAL ISSUES.  At present we have made no provision for supporting the
+progressive or lossless processes defined in the standard.
+
+The present software is still largely in the prototype stage.  It does not
+support all possible variants of the JPEG standard, and some functions have
+rather slow and/or crude implementations.  However, it is useful already.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful.  We have not yet
+undertaken serious performance measurement or tuning; we intend to do so in
+the future.
+
+
+This software can be used on several levels:
+
+* As canned software for JPEG compression and decompression.  Just edit the
+  Makefile and configuration files as needed (see SETUP), compile and go.
+  Members of the independent JPEG group will improve the out-of-the-box
+  functionality as time goes on.
+
+* As the basis for other JPEG programs.  For example, you could incorporate
+  the decompressor into a general image viewing package by replacing the
+  output module with write-to-screen functions.  For an implementation on
+  specific hardware, you might want to replace some of the inner loops with
+  assembly code.  For a non-command-line-driven system, you might want a
+  different user interface.  (Members of the group will be producing Macintosh
+  and Amiga versions with appropriate user interfaces, for example.)
+
+* As a toolkit for experimentation with JPEG and JPEG-like algorithms.  Most
+  of the individual decisions you might want to mess with are packaged up into
+  separate modules.  For example, the details of color-space conversion and
+  subsampling techniques are each localized in one compressor and one
+  decompressor module.  You'd probably also want to extend the user interface
+  to give you more detailed control over the JPEG compression parameters.
+
+In particular, we welcome the use of this software as the basis for commercial
+products; no royalty is required.
+
+
+SETUP
+=====
+
+The installation process is not very automatic; you will need at least some
+familiarity with C programming and program build procedures for your system.
+(Volunteers to work on improving this situation are welcome.  Also, we will
+probably start distributing pre-built binaries for popular systems at some
+point.)
+
+First, select a makefile and copy it to "Makefile".  "makefile.unix"
+is appropriate for most Unix and Unix-like systems.  Special makefiles are
+included for various PC compilers.  If you don't see a makefile for your
+system, we recommend starting from makefile.unix.
+
+Look over the Makefile and adjust options as needed.  In particular, you'll
+need to change the CC= and CFLAGS= definitions if you don't have gcc
+(makefile.unix only).  If you have a function-prototype-less compiler, be sure
+to uncomment the .c.o rule and say "make ansi2knr".  This will cause the
+source files to be preprocessed to change our ANSI-style function definitions
+to old-style definitions.  (Thanks to Peter Deutsch of Aladdin Enterprises for
+ansi2knr.)
+
+Also look over jconfig.h and adjust #defines as necessary.  If you have an
+ANSI-compliant C compiler (gcc for instance), no changes should be necessary
+except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE.  For
+older compilers other mods may be needed, depending on what ANSI features are
+supported.  If you prefer, you can usually leave jconfig.h unmodified and add
+-D switches to the Makefile's CFLAGS= definition.
+
+Then say "make".
+
+If you have trouble with missing system include files or inclusion of the
+wrong ones, you can fix it in jinclude.h.  In particular, if you are using
+gcc on a machine with non-ANSI system include files, you are likely to find
+that jinclude.h tries to include the wrong files (because gcc defines
+__STDC__).  There's no good automatic solution to this, so you'll just have
+to hand-edit jinclude.h.
+
+As a quick test of functionality we've included three sample files:
+	testorig.jpg	same as blkint.jpg from JPEG validation floppy.
+	testimg.ppm	output of djpeg testorig.jpg
+	testimg.jpg	output of cjpeg testimg.ppm
+The two .jpg files aren't identical due to different parameter choices (and
+wouldn't be anyway, since JPEG is lossy).  However, if you can generate
+duplicates of testimg.ppm and testimg.jpg then you probably have a working
+port.  "make test" will perform the necessary comparisons (by generating
+testout.ppm and testout.jpg and comparing these to testimg.*).  NOTE: this
+is far from an exhaustive test of the JPEG software; some modules, such as
+color quantization and GIF I/O, are not exercised at all.  It's just a quick
+test to give you some confidence that you haven't missed something major.
+
+If you need to make a smaller version of the JPEG software, some optional
+functions can be removed at compile time.  See the xxx_SUPPORTED #defines
+in jconfig.h.  (Not a lot is actually removed right now, but as more optional
+stuff gets added, this mechanism will start to make a difference.)
+
+If you want to incorporate the JPEG code as subroutines in a larger program,
+we recommend that you make libjpeg.a.  Then use the .h files and libjpeg.a as
+your interface to the JPEG functions.  Your surrounding program will have to
+provide functionality similar to what's in jcmain.c or jdmain.c, and you may
+want to replace jerror.c and possibly other modules depending on your needs.
+See the "architecture" file for more info.  If it seems to you that the system
+structure doesn't accommodate what you want to do, please contact the authors.
+
+Special notes for Macintosh Think C users: If you have version 5.0 you should
+be able to just turn on __STDC__ through the compiler switch that enables
+that.  With version 4.0 you must manually edit jconfig.h to define PROTO,
+HAVE_UNSIGNED_CHAR, HAVE_UNSIGNED_SHORT, and const.  (It seems to be safe to
+just define __STDC__ to take care of the first three.)  When setting up
+project files, use the COBJECTS and DOBJECTS lists in makefile.unix as a guide
+to which files need to be included, and add the ANSI and Unix C libraries in a
+separate segment.  You may need to divide the JPEG files into more than one
+segment; you can do this pretty much as you please.
+
+
+USAGE
+=====
+
+The user interface is pretty minimal at this point.  We haven't bothered to
+generate manual-page files since the switches badly need redesign.  At the
+moment, things work like this:
+
+There are two programs, cjpeg to compress an image file into JPEG format,
+and djpeg to decompress.
+
+On Unix systems, you say:
+	cjpeg [switches] [imagefile] >jpegfile
+	djpeg [switches] [jpegfile]  >imagefile
+The programs read the specified input file, or standard input if none is
+named.  They always write to standard output (with trace/error messages to
+standard error).  These conventions are handy for piping images between
+programs.
+
+On PC, Macintosh, and Amiga systems, you say:
+	cjpeg [switches] imagefile jpegfile
+	djpeg [switches] jpegfile  imagefile
+i.e., both input and output files are named on the command line.  This style
+is a little more foolproof, and it loses no functionality if you don't have
+pipes.  You can get this style on Unix too, if you prefer, by defining
+TWO_FILE_COMMANDLINE in jconfig.h or in the Makefile.  You MUST use this style
+on any system that doesn't cope well with binary data fed through
+stdin/stdout.
+
+Currently supported image file formats include raw-format PPM, raw-format PGM
+(for monochrome images), and GIF.  cjpeg recognizes the input image format
+automatically, but you have to tell djpeg which format to generate.
+
+The only JPEG file format currently supported is a raw JPEG data stream.
+Unless modified, the programs use the JFIF conventions for variables left
+unspecified by the JPEG standard.  (In particular, cjpeg generates a JFIF APP0
+marker.)  Support for the JPEG-in-TIFF format will probably be added at some
+future date.
+
+The command line switches for cjpeg are:
+
+	-I		Generate noninterleaved JPEG file (not yet supported).
+
+	-Q quality	Scale quantization tables to adjust quality.
+			Quality is 0 (worst) to 100 (best); default is 75.
+			(See below for more info.)
+
+	-a		Use arithmetic coding rather than Huffman coding.
+			(Not currently supported, see LEGAL ISSUES.)
+
+	-o		Perform optimization of entropy encoding parameters.
+			Without this, default Huffman or arithmetic
+			parameters are used.  -o makes the JPEG file a tad
+			smaller, but compression uses much more memory.
+			Image quality is unaffected by -o.
+
+	-d		Enable debug printout.  More -d's give more printout.
+
+Typically you'd use -Q settings of 50 or 75 or so.  -Q 100 will generate a
+quantization table of all 1's, meaning no quantization loss; then any
+differences between input and output images are due to subsampling or to
+roundoff error in the DCT or colorspace-conversion steps.  -Q values below 50
+may be useful for making real small, low-quality images.  Try -Q 2 (or so) for
+some amusing Cubist effects.  (Note that -Q values below about 25 generate
+2-byte quantization tables, which are not decodable by pure baseline JPEG
+decoders.  cjpeg emits a warning message when you give such a -Q value.)
+
+The command line switches for djpeg are:
+
+	-G		Select GIF output format (implies -q, with default
+			of 256 colors).
+
+	-b		Perform cross-block smoothing.  This is quite
+			memory-intensive and only seems to improve the image
+			at very low quality settings (-Q 10 to 20 or so).
+
+	-g		Force gray-scale output even if input is color.
+
+	-q N		Quantize to N colors.
+
+	-D		Use Floyd-Steinberg dithering in color quantization.
+
+	-2		Use two-pass color quantization (not yet supported).
+
+	-d		Enable debug printout.  More -d's give more printout.
+
+Color quantization currently uses a rather shoddy algorithm (although it's not
+so horrible when dithered).  Because of this, the GIF output mode is not
+recommended in the current release, except for gray-scale output.  You can get
+better results by applying ppmquant to the unquantized (PPM) output of djpeg,
+then converting to GIF with ppmtogif.  We expect to provide a considerably
+better quantization algorithm in a future release.
+
+Note that djpeg *can* read noninterleaved JPEG files even though cjpeg can't
+yet generate them.  For most applications this is a nonissue, since hardly
+anybody seems to be using noninterleaved format.
+
+On a non-virtual-memory machine, you may run out of memory if you use -I or -o
+in cjpeg, or -q ... -2 in djpeg, or try to read an interlaced GIF file.  This
+will be addressed eventually by replacing jvirtmem.c with something that uses
+temporary files for large images (see TO DO).
+
+
+REFERENCES
+==========
+
+The best and most readily available introduction to the JPEG compression
+algorithm is Wallace's article in the April '91 CACM:
+	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
+	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.)  We highly recommend reading that
+article before looking at any of the JPEG software.
+
+For more detail about the JPEG standard you pretty much have to go to the
+draft standard, which is not nearly as intelligible as Wallace's article.
+The current version is ISO/IEC Committee Draft CD 10918-1 dated 1991-03-15.
+The standard is not presently available electronically; you must order a paper
+copy through ISO.
+
+The JPEG standard does not specify all details of an interchangeable file
+format.  For the omitted details we follow the "JFIF" conventions, revision
+1.01.  A copy of the JFIF spec is available from:
+	Literature Department
+	C-Cube Microsystems, Inc.
+	399A West Trimble Road
+	San Jose, CA  95131
+	(408) 944-6300
+Requests can also be e-mailed to info@c3.pla.ca.us (this address good after
+10/10/91).  The same source can supply copies of the draft JPEG-in-TIFF specs.
+
+If you want to understand this implementation, start by reading the
+"architecture" documentation file.  Please read "codingrules" if you want to
+contribute any code.
+
+
+SUPPORTING SOFTWARE
+===================
+
+You will probably want Jef Poskanzer's PBMPLUS image software; this provides
+many useful operations on PPM-format image files.  In particular, it can
+convert PPM images to and from a wide range of other formats.  You can FTP
+this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or
+ftp.ee.lbl.gov (pbmplus*.tar.Z).
+
+If you are using X Windows you might want to use the xv or xloadimage viewers
+to save yourself the trouble of converting PPM to some other format.
+Both of these can be found in the contrib directory at export.lcs.mit.edu.
+
+
+LEGAL ISSUES
+============
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+Permission is NOT granted for the use of any author's name or author's company
+name in advertising or publicity relating to this software or products derived
+from it.  This software may be referred to only as "the Independent JPEG
+Group's software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it.  (See the file
+ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
+of any product generated from the JPEG code, this does not limit you more than
+the foregoing paragraphs do.
+
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents held by IBM, and possibly also patents of AT&T and Mitsubishi.  Hence
+arithmetic coding cannot legally be used without obtaining one or more
+licenses.  For this reason, support for arithmetic coding has been removed
+from the free JPEG software.  (Since arithmetic coding provides only a
+marginal gain over the unpatented Huffman mode, it is unlikely that very many
+people will choose to use it.  If you do obtain such a license, contact
+jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.)  So far
+as we are aware, there are no patent restrictions on the remaining code.
+
+
+TO DO
+=====
+
+Many of the modules need fleshing out to provide more complete
+implementations, or to provide faster paths for common cases.  The greatest
+needs are for (a) decent color quantization, and (b) a memory manager
+implementation that can work in limited memory by swapping "big" images to
+temporary files.  I (Tom Lane) am going to work on color quantization next.
+Volunteers to write a PC memory manager, or to work on any other modules, are
+welcome.
+
+We'd appreciate it if people would compile and check out the code on as wide a
+variety of systems as possible, and report any portability problems
+encountered (with solutions, if possible).  Checks of file compatibility with
+other JPEG implementations would also be of interest.  Finally, we would
+appreciate code profiles showing where the most time is spent, especially on
+unusual systems.
+
+Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff --git a/ansi2knr.c b/ansi2knr.c
new file mode 100644
index 0000000..77d3d81
--- /dev/null
+++ b/ansi2knr.c
@@ -0,0 +1,477 @@
+/*
+ * Received from Peter Deutsch (ghost@aladdin.com)
+ * Fri, 26 Apr 91 10:10:10 PDT
+ */
+
+/* Copyright (C) 1989, 1991 Aladdin Enterprises.  All rights reserved.
+   Distributed by Free Software Foundation, Inc.
+
+This file is part of Ghostscript.
+
+Ghostscript is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
+to anyone for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.  Refer
+to the Ghostscript General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+Ghostscript, but only under the conditions described in the Ghostscript
+General Public License.  A copy of this license is supposed to have been
+given to you along with Ghostscript so you can know your rights and
+responsibilities.  It should be in a file named COPYING.  Among other
+things, the copyright notice and this notice must be preserved on all
+copies.  */
+
+/*
+---------- Here is the GhostScript file COPYING, referred to above ----------
+----- These terms do NOT apply to the JPEG software itself; see README ------
+
+		    GHOSTSCRIPT GENERAL PUBLIC LICENSE
+		    (Clarified 11 Feb 1988)
+
+ Copyright (C) 1988 Richard M. Stallman
+ Everyone is permitted to copy and distribute verbatim copies of this
+ license, but changing it is not allowed.  You can also use this wording
+ to make the terms for other programs.
+
+  The license agreements of most software companies keep you at the
+mercy of those companies.  By contrast, our general public license is
+intended to give everyone the right to share Ghostscript.  To make sure
+that you get the rights we want you to have, we need to make
+restrictions that forbid anyone to deny you these rights or to ask you
+to surrender the rights.  Hence this license agreement.
+
+  Specifically, we want to make sure that you have the right to give
+away copies of Ghostscript, that you receive source code or else can get
+it if you want it, that you can change Ghostscript or use pieces of it
+in new free programs, and that you know you can do these things.
+
+  To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights.  For example, if you distribute
+copies of Ghostscript, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  Also, for our own protection, we must make certain that everyone finds
+out that there is no warranty for Ghostscript.  If Ghostscript is
+modified by someone else and passed on, we want its recipients to know
+that what they have is not what we distributed, so that any problems
+introduced by others will not reflect on our reputation.
+
+  Therefore we (Richard M. Stallman and the Free Software Foundation,
+Inc.) make the following terms which say what you must do to be allowed
+to distribute or change Ghostscript.
+
+
+			COPYING POLICIES
+
+  1. You may copy and distribute verbatim copies of Ghostscript source
+code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy a valid copyright and license
+notice "Copyright (C) 1989 Aladdin Enterprises.  All rights reserved.
+Distributed by Free Software Foundation, Inc." (or with whatever year is
+appropriate); keep intact the notices on all files that refer to this
+License Agreement and to the absence of any warranty; and give any other
+recipients of the Ghostscript program a copy of this License Agreement
+along with the program.  You may charge a distribution fee for the
+physical act of transferring a copy.
+
+  2. You may modify your copy or copies of Ghostscript or any portion of
+it, and copy and distribute such modifications under the terms of
+Paragraph 1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish,
+    that in whole or in part contains or is a derivative of Ghostscript
+    or any part thereof, to be licensed at no charge to all third
+    parties on terms identical to those contained in this License
+    Agreement (except that you may choose to grant more extensive
+    warranty protection to some or all third parties, at your option).
+
+    c) You may charge a distribution fee for the physical act of
+    transferring a copy, and you may at your option offer warranty
+    protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+  3. You may copy and distribute Ghostscript (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the
+terms of Paragraphs 1 and 2 above provided that you also do one of the
+following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal
+    shipping charge) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+  4. You may not copy, sublicense, distribute or transfer Ghostscript
+except as expressly provided under this License Agreement.  Any attempt
+otherwise to copy, sublicense, distribute or transfer Ghostscript is
+void and your rights to use the program under this License agreement
+shall be automatically terminated.  However, parties who have received
+computer software programs from you with this License Agreement will not
+have their licenses terminated so long as such parties remain in full
+compliance.
+
+  5. If you wish to incorporate parts of Ghostscript into other free
+programs whose distribution conditions are different, write to the Free
+Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not
+yet worked out a simple rule that can be stated here, but we will often
+permit this.  We will be guided by the two goals of preserving the free
+status of all derivatives of our free software and of promoting the
+sharing and reuse of software.
+
+Your comments and suggestions about our licensing policies and our
+software are welcome!  Please contact the Free Software Foundation,
+Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
+
+		       NO WARRANTY
+
+  BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
+M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
+PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
+YOU.  SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
+ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
+GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
+ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
+PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
+HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
+BY ANY OTHER PARTY.
+-------------------- End of file COPYING ------------------------------
+*/
+
+
+/* ansi2knr.c */
+/* Convert ANSI function declarations to K&R syntax */
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef BSD
+#  include <strings.h>
+#  define strchr index
+#else
+#  ifdef VMS
+	extern char *strcat(), *strchr(), *strcpy(), *strupr();
+	extern int strcmp(), strlen(), strncmp();
+#  else
+#    include <string.h>
+#  endif
+#endif
+
+#ifdef MSDOS
+#  include <malloc.h>
+#else
+#  ifdef VMS
+     extern char *malloc();
+     extern void free();
+#  else
+#    ifdef BSD
+       extern char *malloc();
+#    else
+#      include <malloc.h>
+#    endif
+#  endif
+#endif
+
+/* Usage:
+	ansi2knr input_file output_file
+ * If no output_file is supplied, output goes to stdout.
+ * There are no error messages.
+ *
+ * ansi2knr recognizes functions by seeing a non-keyword identifier
+ * at the left margin, followed by a left parenthesis,
+ * with a right parenthesis as the last character on the line.
+ * It will recognize a multi-line header if the last character
+ * on each line but the last is a left parenthesis or comma.
+ * These algorithms ignore whitespace and comments, except that
+ * the function name must be the first thing on the line.
+ * The following constructs will confuse it:
+	- Any other construct that starts at the left margin and
+	    follows the above syntax (such as a macro or function call).
+	- Macros that tinker with the syntax of the function header.
+ */
+
+/* Scanning macros */
+#define isidchar(ch) (isalnum(ch) || (ch) == '_')
+#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
+
+main(argc, argv)
+    int argc;
+    char *argv[];
+{	FILE *in, *out;
+#define bufsize 500			/* arbitrary size */
+	char buf[bufsize];
+	char *line;
+	switch ( argc )
+	   {
+	default:
+		printf("Usage: ansi2knr input_file [output_file]\n");
+		exit(0);
+	case 2:
+		out = stdout; break;
+	case 3:
+		out = fopen(argv[2], "w");
+		if ( out == NULL )
+		   {	fprintf(stderr, "Cannot open %s\n", argv[2]);
+			exit(1);
+		   }
+	   }
+	in = fopen(argv[1], "r");
+	if ( in == NULL )
+	   {	fprintf(stderr, "Cannot open %s\n", argv[1]);
+		exit(1);
+	   }
+	fprintf(out, "#line 1 \"%s\"\n", argv[1]);
+	line = buf;
+	while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
+	   {	switch ( test1(buf) )
+		   {
+		case 1:			/* a function */
+			convert1(buf, out);
+			break;
+		case -1:		/* maybe the start of a function */
+			line = buf + strlen(buf);
+			continue;
+		default:		/* not a function */
+			fputs(buf, out);
+			break;
+		   }
+		line = buf;
+	   }
+	if ( line != buf ) fputs(buf, out);
+	fclose(out);
+	fclose(in);
+	return 0;
+}
+
+/* Skip over space and comments, in either direction. */
+char *
+skipspace(p, dir)
+    register char *p;
+    register int dir;			/* 1 for forward, -1 for backward */
+{	for ( ; ; )
+	   {	while ( isspace(*p) ) p += dir;
+		if ( !(*p == '/' && p[dir] == '*') ) break;
+		p += dir;  p += dir;
+		while ( !(*p == '*' && p[dir] == '/') )
+		   {	if ( *p == 0 ) return p;	/* multi-line comment?? */
+			p += dir;
+		   }
+		p += dir;  p += dir;
+	   }
+	return p;
+}
+
+/*
+ * Write blanks over part of a string.
+ */
+void
+writeblanks(start, end)
+    char *start;
+    char *end;
+{	char *p;
+	for ( p = start; p < end; p++ ) *p = ' ';
+}
+
+/*
+ * Test whether the string in buf is a function definition.
+ * The string may contain and/or end with a newline.
+ * Return as follows:
+ *	0 - definitely not a function definition;
+ *	1 - definitely a function definition;
+ *	-1 - may be the beginning of a function definition,
+ *		append another line and look again.
+ */
+test1(buf)
+    char *buf;
+{	register char *p = buf;
+	char *bend;
+	char *endfn;
+	int contin;
+	if ( !isidfirstchar(*p) )
+		return 0;		/* no name at left margin */
+	bend = skipspace(buf + strlen(buf) - 1, -1);
+	switch ( *bend )
+	   {
+	case ')': contin = 1; break;
+	case '(':
+	case ',': contin = -1; break;
+	default: return 0;		/* not a function */
+	   }
+	while ( isidchar(*p) ) p++;
+	endfn = p;
+	p = skipspace(p, 1);
+	if ( *p++ != '(' )
+		return 0;		/* not a function */
+	p = skipspace(p, 1);
+	if ( *p == ')' )
+		return 0;		/* no parameters */
+	/* Check that the apparent function name isn't a keyword. */
+	/* We only need to check for keywords that could be followed */
+	/* by a left parenthesis (which, unfortunately, is most of them). */
+	   {	static char *words[] =
+		   {	"asm", "auto", "case", "char", "const", "double",
+			"extern", "float", "for", "if", "int", "long",
+			"register", "return", "short", "signed", "sizeof",
+			"static", "switch", "typedef", "unsigned",
+			"void", "volatile", "while", 0
+		   };
+		char **key = words;
+		char *kp;
+		int len = endfn - buf;
+		while ( (kp = *key) != 0 )
+		   {	if ( strlen(kp) == len && !strncmp(kp, buf, len) )
+				return 0;	/* name is a keyword */
+			key++;
+		   }
+	   }
+	return contin;
+}
+
+convert1(buf, out)
+    char *buf;
+    FILE *out;
+{	char *endfn = strchr(buf, '(') + 1;
+	register char *p;
+	char **breaks;
+	unsigned num_breaks = 2;	/* for testing */
+	char **btop;
+	char **bp;
+	char **ap;
+top:	p = endfn;
+	breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
+	if ( breaks == 0 )
+	   {	/* Couldn't allocate break table, give up */
+		fprintf(stderr, "Unable to allocate break table!\n");
+		fputs(buf, out);
+		return -1;
+	   }
+	btop = breaks + num_breaks * 2 - 2;
+	bp = breaks;
+	/* Parse the argument list */
+	do
+	   {	int level = 0;
+		char *end = NULL;
+		if ( bp >= btop )
+		   {	/* Filled up break table. */
+			/* Allocate a bigger one and start over. */
+			free((char *)breaks);
+			num_breaks <<= 1;
+			goto top;
+		   }
+		*bp++ = p;
+		/* Find the end of the argument */
+		for ( ; end == NULL; p++ )
+		   {	switch(*p)
+			   {
+			case ',': if ( !level ) end = p; break;
+			case '(': level++; break;
+			case ')': if ( --level < 0 ) end = p; break;
+			case '/': p = skipspace(p, 1) - 1; break;
+			default: ;
+			   }
+		   }
+		p--;			/* back up over terminator */
+		/* Find the name being declared. */
+		/* This is complicated because of procedure and */
+		/* array modifiers. */
+		for ( ; ; )
+		   {	p = skipspace(p - 1, -1);
+			switch ( *p )
+			   {
+			case ']':	/* skip array dimension(s) */
+			case ')':	/* skip procedure args OR name */
+			   {	int level = 1;
+				while ( level )
+				 switch ( *--p )
+				   {
+				case ']': case ')': level++; break;
+				case '[': case '(': level--; break;
+				case '/': p = skipspace(p, -1) + 1; break;
+				default: ;
+				   }
+			   }
+				if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
+				   {	/* We found the name being declared */
+					while ( !isidfirstchar(*p) )
+						p = skipspace(p, 1) + 1;
+					goto found;
+				   }
+				break;
+			default: goto found;
+			   }
+		   }
+found:		if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
+		   {	p++;
+			if ( bp == breaks + 1 )	/* sole argument */
+				writeblanks(breaks[0], p);
+			else
+				writeblanks(bp[-1] - 1, p);
+			bp--;
+		   }
+		else
+		   {	while ( isidchar(*p) ) p--;
+			*bp++ = p+1;
+		   }
+		p = end;
+	   }
+	while ( *p++ == ',' );
+	*bp = p;
+	/* Make a special check for 'void' arglist */
+	if ( bp == breaks+2 )
+	   {	p = skipspace(breaks[0], 1);
+		if ( !strncmp(p, "void", 4) )
+		   {	p = skipspace(p+4, 1);
+			if ( p == breaks[2] - 1 )
+			   {	bp = breaks;	/* yup, pretend arglist is empty */
+				writeblanks(breaks[0], p + 1);
+			   }
+		   }
+	   }
+	/* Put out the function name */
+	p = buf;
+	while ( p != endfn ) putc(*p, out), p++;
+	/* Put out the declaration */
+	for ( ap = breaks+1; ap < bp; ap += 2 )
+	   {	p = *ap;
+		while ( isidchar(*p) ) putc(*p, out), p++;
+		if ( ap < bp - 1 ) fputs(", ", out);
+	   }
+	fputs(")  ", out);
+	/* Put out the argument declarations */
+	for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
+	fputs(breaks[0], out);
+	free((char *)breaks);
+	return 0;
+}
diff --git a/architecture b/architecture
new file mode 100644
index 0000000..78587cd
--- /dev/null
+++ b/architecture
@@ -0,0 +1,1106 @@
+
+	JPEG SYSTEM ARCHITECTURE		3-OCT-91
+
+
+This file provides an overview of the "architecture" of the portable JPEG
+software; that is, the functions of the various modules in the system and the
+interfaces between modules.  For more precise details about any data structure
+or calling convention, see the header files.
+
+Important note: when I say "module" I don't mean "a C function", which is what
+some people seem to think the term means.  A separate C source file is closer
+to the mark.  Also, it is frequently the case that several different modules
+present a common interface to callers; the term "object" or "method" refers to
+this common interface (see "Poor man's object-oriented programming", below).
+
+JPEG-specific terminology follows the JPEG R9 draft:
+  A "component" means a color channel, e.g., Red or Luminance.
+  A "sample" is a pixel component value (i.e., one number in the image data).
+  A "coefficient" is a frequency coefficient (a DCT transform output number).
+  The term "block" refers to an 8x8 group of samples or coefficients.
+  "MCU" (minimum coded unit) is the same as "MDU" of the R8 draft; i.e., an
+	interleaved set of blocks of size determined by the sampling factors,
+	or a single block in a noninterleaved scan.
+
+
+*** System requirements ***
+
+We must support compression and decompression of both Huffman and
+arithmetic-coded JPEG files.  Any set of compression parameters allowed by the
+JPEG spec should be readable for decompression.  (We can be more restrictive
+about what formats we can generate.)  (Note: for legal reasons no arithmetic
+coding implementation is currently included in the publicly available sources.
+However, the architecture still supports it.)
+
+We need to be able to handle both raw JPEG files (more specifically, the JFIF
+format) and JPEG-in-TIFF (C-cubed's format, and perhaps Kodak's).  Even if we
+don't implement TIFF ourselves, other people will want to use our code for
+that.  This means that generation and scanning of the file header has to be
+separated out.
+
+Perhaps we should be prepared to support the JPEG lossless mode (also referred
+to in the spec as spatial DPCM coding).  A lot of people seem to believe they
+need this... whether they really do is debatable, but the customer is always
+right.  On the other hand, there will not be much sharable code between the
+lossless and lossy modes!  At best, a lossless program could be derived from
+parts of the lossy version.  For now we will only worry about the lossy mode.
+
+I see no real value in supporting the JPEG progressive modes (note that
+spectral selection and successive approximation are two different progressive
+modes).  These are only of interest when painting the decompressed image in
+real-time, which nobody is going to do with a pure software implementation.
+
+There is some value in supporting the hierarchical mode, which allows for
+successive frames of higher resolution.  This could be of use for including
+"thumbnail" representations.  Also, Storm's JPEG++ files probably use the
+hierarchical mode (I haven't looked).  However, this appears to add a lot more
+complexity than it is worth.
+
+A variety of uncompressed image file formats and user interfaces must be
+supported.  These aspects therefore have to be kept separate from the rest of
+the system.  A particularly important issue is whether color quantization of
+the output is needed (i.e., whether a colormap is used).  We should be able to
+support both adaptive quantization (which requires two or more passes over the
+image) and nonadaptive (quantization to a prespecified colormap, which can be
+done in one pass).
+
+Memory usage is an important concern, since we will port this code to 80x86
+and other limited-memory machines.  For large intermediate structures, we
+should be able to use either virtual memory or temporary files.
+
+It should be possible to build programs that handle compression only,
+decompression only, or both, without much duplicate or unused code in any
+version.  (In particular, a decompression-only version should have no extra
+baggage.)
+
+
+*** Compression overview ***
+
+The *logical* steps needed in (non-lossless) JPEG compression are:
+
+1. Conversion from incoming image format to a standardized internal form
+   (either RGB or greyscale).
+
+2. Color space conversion (e.g., RGB to YCbCr).  This is a null step for
+   greyscale (unless we support mapping color inputs to greyscale, which
+   would most easily be done here).  Gamma adjustment may also be needed here.
+
+3. Subsampling (reduction of number of samples in some color components).
+   This step operates independently on each color component.
+
+4. MCU extraction (creation of a single sequence of 8x8 sample blocks).
+   This step and the following ones are performed once for each scan
+   in the output JPEG file, i.e., once if making an interleaved file and more
+   than once for a noninterleaved file.
+   Note: both this step and the previous one must deal with edge conditions
+   for pictures that aren't a multiple of the MCU dimensions.  Alternately,
+   we could expand the picture to a multiple of an MCU before doing these
+   two steps.  (The latter seems better and has been adopted below.)
+
+5. DCT transformation of each 8x8 block.
+
+6. Quantization scaling and zigzag reordering of the elements in each 8x8
+   block.
+
+7. Huffman or arithmetic encoding of the transformed block sequence.
+
+8. Output of the JPEG file with whatever headers/markers are wanted.
+
+Of course, the actual implementation will combine some of these logical steps
+for efficiency.  The trick is to keep these logical functions as separate as
+possible without losing too much performance.
+
+In addition to these logical pipeline steps, we need various modules that
+aren't part of the data pipeline.  These are:
+
+A. Overall control (sequencing of other steps & management of data passing).
+
+B. User interface; this will determine the input and output files, and supply
+   values for some compression parameters.  Note that this module is highly
+   platform-dependent.
+
+C. Compression parameter selection: some parameters should be chosen
+   automatically rather than requiring the user to find a good value.
+   The prototype only does this for the back-end (Huffman or arithmetic)
+   parameters, but further in the future, more might be done.  A
+   straightforward approach to selection is to try several values; this
+   requires being able to repeatedly apply some portion of the pipeline and
+   inspect the results (without actually outputting them).  Probably only
+   entropy encoding parameters can reasonably be done this way; optimizing
+   earlier steps would require too much data to be reprocessed (not to mention
+   the problem of interactions between parameters for different steps).
+   What other facilities do we need to support automatic parameter selection?
+
+D. A memory management module to deal with small-memory machines.  This must
+   create the illusion of virtual memory for certain large data structures
+   (e.g., the subsampled image or the transformed coefficients).
+   The interface to this must be defined to minimize the overhead incurred,
+   especially on virtual-memory machines where the module won't do much.
+
+In many cases we can arrange things so that a data stream is produced in
+segments by one module and consumed by another without the need to hold it all
+in (virtual) memory.  This is obviously not possible for any data that must be
+scanned more than once, so it won't work everywhere.
+
+The major variable at this level of detail is whether the JPEG file is to be
+interleaved or not; that affects the order of processing so fundamentally that
+the central control module must know about it.  Some of the other modules may
+need to know it too.  It would simplify life if we didn't need to support
+noninterleaved images, but that is not reasonable.
+
+Many of these steps operate independently on each color component; the
+knowledge of how many components there are, and how they are interleaved,
+ought to be confined to the central control module.  (Color space conversion
+and MCU extraction probably have to know it too.)
+
+
+*** Decompression overview ***
+
+Decompression is roughly the inverse process from compression, but there are
+some additional steps needed to produce a good output image.
+
+The *logical* steps needed in (non-lossless) JPEG decompression are:
+
+1. Scanning of the JPEG file, decoding of headers/markers etc.
+
+2. Huffman or arithmetic decoding of the coefficient sequence.
+
+3. Quantization descaling and zigzag reordering of the elements in each 8x8
+   block.
+
+4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8
+   blocks back to separate components in pixel map order).
+
+5. (Optional)  Cross-block smoothing per JPEG section 13.10 or a similar
+   algorithm.  (Steps 5-8 operate independently on each component.)
+
+6. Inverse DCT transformation of each 8x8 block.
+
+7. De-subsampling.  At this point a pixel image of the original dimensions
+   has been recreated.
+
+8. Post-subsampling smoothing.  This can be combined with de-subsampling,
+   by using a convolution-like calculation to generate each output pixel
+   directly from one or more input pixels.
+
+9. Cropping to the original pixel dimensions (throwing away duplicated
+   pixels at the edges).  It is most convenient to do this now, as the
+   preceding steps are simplified by not having to worry about odd picture
+   sizes.
+
+10. Color space reconversion (e.g., YCbCr to RGB).  This is a null step for
+    greyscale.  (Note that if we support mapping color JPEG to greyscale,
+    it could be done as part of this step.)  Gamma adjustment may also be
+    needed here.
+
+11. Color quantization (only if a colormapped output format is requested).
+    NOTE: it might be better to do this on the internal color space instead of
+    RGB?  If so, it would need to be performed one step earlier.
+
+12. Writing of the desired image format.
+
+As before, some of these will be combined into single steps.  When dealing
+with a noninterleaved JPEG file, steps 2-9 will be performed once for each
+scan; the resulting data will need to be buffered up so that step 10 can
+process all the color components together.
+
+The same auxiliary modules are needed as before, except for compression
+parameter selection.  Note that rerunning a pipeline stage should never be
+needed during decompression.  This may allow a simpler control module.  The
+user interface might also be simpler since it need not supply any compression
+parameters.
+
+As before, not all of these steps require the whole image to be stored.
+Actually, two-pass color quantization is the only step that logically requires
+this; everything else could be done a few raster lines at a time (at least for
+interleaved images).  We might want to make color quantization be a separate
+program because of this fact.
+
+Again, many of the steps should be able to work on one color component in
+ignorance of the other components.
+
+
+*** Implications of noninterleaved formats ***
+
+Much of the work can be done in a single pass if an interleaved JPEG file
+format is used.  With a noninterleaved JPEG file, separating or recombining
+the components will force use of virtual memory (on a small-memory machine,
+we probably would want one temp file per color component).
+
+If any of the image formats we read or write are noninterleaved, the opposite
+condition might apply: processing a noninterleaved JPEG file would be more
+efficient.  Offhand, though, I can't think of any popular image formats that
+work that way; besides the win would only come if the same color space were
+used in JPEG and non-JPEG files.  It's not worth the complexity to make the
+system design accommodate that case efficiently.
+
+An argument against interleaving is that it makes the decompressor need more
+memory for cross-block smoothing (since the minimum processable chunk of the
+image gets bigger).  With images more than 1000 pixels across, 80x86 machines
+are likely to have difficulty in handling this feature.
+
+Another argument against interleaving is that the noninterleaved format allows
+a wider range of sampling factors, since the limit of ten blocks per MCU no
+longer applies.  We could get around this by blithely ignoring the spec's
+limit of ten blocks, but that seems like a bad idea (especially since it makes
+the above problem worse).
+
+The upshot is that we need to support both interleaved and noninterleaved JPEG
+formats, since for any given machine and picture size one may be much more
+efficient than the other.  However, the non-JPEG format we convert to or from
+will be assumed to be an interleaved format (i.e., it produces or stores all
+the components of a pixel together).
+
+I do not think it is necessary for the compressor to be able to output
+partially-interleaved formats (multiple scans, some of which interleave a
+subset of the components).  However, the decompressor must be able to read
+such files to conform to the spec.
+
+
+*** Data formats ***
+
+Pipeline steps that work on pixel sample values will use the following data
+structure:
+
+    typedef something JSAMPLE;		a pixel component value, 0..MAXJSAMPLE
+    typedef JSAMPLE *JSAMPROW;		ptr to a row of samples
+    typedef JSAMPROW *JSAMPARRAY;	ptr to a list of rows
+    typedef JSAMPARRAY *JSAMPIMAGE;	ptr to a list of color-component arrays
+
+The basic element type JSAMPLE will be one of unsigned char, (signed) char, or
+unsigned short.  Unsigned short will be used if samples wider than 8 bits are
+to be supported (this is a compile-time option).  Otherwise, unsigned char is
+used if possible.  If the compiler only supports signed chars, then it is
+necessary to mask off the value when reading.  Thus, all reads of sample
+values should be coded as "GETJSAMPLE(value)", where the macro will be defined
+as "((value)&0xFF)" on signed-char machines and "(value)" elsewhere.
+
+With these conventions, JSAMPLE values can be assumed to be >= 0.  This should
+simplify correct rounding during subsampling, etc.  The JPEG draft's
+specification that sample values run from -128..127 will be accommodated by
+subtracting 128 just as the sample value is copied into the source array for
+the DCT step (this will be an array of signed shorts or longs).  Similarly,
+during decompression the output of the IDCT step will be immediately shifted
+back to 0..255.  (NB: different values are required when 12-bit samples are in
+use.  The code should be written in terms of MAXJSAMPLE and CENTERJSAMPLE,
+which will be #defined as 255 and 128 respectively in an 8-bit implementation,
+and as 4095 and 2048 in a 12-bit implementation.)
+
+On compilers that don't support "unsigned short", signed short can be used for
+a 12-bit implementation.  To support lossless coding (which allows up to
+16-bit data precision) masking with 0xFFFF in GETJSAMPLE might be necessary.
+(But if "int" is 16 bits then using "unsigned int" is the best solution.)
+
+Notice that we use a pointer per row, rather than a two-dimensional JSAMPLE
+array.  This choice costs only a small amount of memory and has several
+benefits:
+
+* Code using the data structure doesn't need to know the allocated width of
+the rows.  This will simplify edge expansion/compression, since we can work
+in an array that's wider than the logical picture width.
+
+* The rows forming a component array may be allocated at different times
+without extra copying.  This will simplify working a few scanlines at a time,
+especially in smoothing steps that need access to the previous and next rows.
+
+* Indexing doesn't require multiplication; this is a performance win on many
+machines.
+
+Note that each color component is stored in a separate array; we don't use the
+traditional structure in which the components of a pixel are stored together.
+This simplifies coding of steps that work on each component independently,
+because they don't need to know how many components there are.  Furthermore,
+we can read or write each component to a temp file independently, which is
+helpful when dealing with noninterleaved JPEG files.
+
+A specific sample value will be accessed by code such as
+	GETJSAMPLE(image[colorcomponent][row][col])
+where col is measured from the image left edge, but row is measured from the
+first sample row currently in memory.  Either of the first two indexings can
+be precomputed by copying the relevant pointer.
+
+
+Pipeline steps that work on frequency-coefficient values will use the
+following data structure:
+
+    typedef short JCOEF;		a 16-bit signed integer
+    typedef JCOEF JBLOCK[64];		an 8x8 block of coefficients
+    typedef JBLOCK *JBLOCKROW;		ptr to one horizontal row of 8x8 blocks
+    typedef JBLOCKROW *JBLOCKARRAY;	ptr to a list of such rows
+    typedef JBLOCKARRAY *JBLOCKIMAGE;	ptr to a list of color component arrays
+
+The underlying type is always a 16-bit signed integer (this is "short" on all
+machines of interest, but let's use the typedef name anyway).  These are
+grouped into 8x8 blocks (we should use #defines DCTSIZE and DCTSIZE2 rather
+than "8" and "64").  The contents of a block may be either in "natural" or
+zigzagged order, and may be true values or divided by the quantization
+coefficients, depending on where the block is in the pipeline.
+
+Notice that the allocation unit is now a row of 8x8 blocks, corresponding to
+eight rows of samples.  Otherwise the structure is much the same as for
+samples, and for the same reasons.
+
+On machines where malloc() can't handle a request bigger than 64Kb, this data
+structure limits us to rows of less than 512 JBLOCKs, which would be a picture
+width of 4000 pixels.  This seems an acceptable restriction.
+
+
+On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW)
+must be declared as "far" pointers, but the upper levels can be "near"
+(implying that the pointer lists are allocated in the DS segment).
+To simplify sharing code, we'll have a #define symbol FAR, which expands to
+the "far" keyword when compiling on 80x86 machines and to nothing elsewhere.
+
+
+The data arrays used as input and output of the DCT transform subroutine will
+be declared using a separate typedef; they could be arrays of "short", "int"
+or "long" independently of the above choices.  This would depend on what is
+needed to make the compiler generate correct and efficient multiply/add code
+in the DCT inner loops.  No significant speed or memory penalty will be paid
+to have a different representation than is used in the main image storage
+arrays, since some additional value-by-value processing is done at the time of
+creation or extraction of the DCT data anyway (e.g., add/subtract 128).
+
+
+*** Poor man's object-oriented programming ***
+
+It should be pretty clear by now that we have a lot of quasi-independent
+steps, many of which have several possible behaviors.  To avoid cluttering the
+code with lots of switch statements, we'll use a simple form of object-style
+programming to separate out the different possibilities.
+
+For example, Huffman and arithmetic coding will be implemented as two separate
+modules that present the same external interface; at runtime, the calling code
+will access the proper module indirectly through an "object".
+
+We can get the limited features we need while staying within portable C.  The
+basic tool is a function pointer.  An "object" is just a struct containing one
+or more function pointer fields, each of which corresponds to a method name in
+real object-oriented languages.  During initialization we fill in the function
+pointers with references to whichever module we have determined we need to use
+in this run.  Then invocation of the module is done by indirecting through a
+function pointer; on most architectures this is no more expensive (and
+possibly cheaper) than a switch, which would be the only other way of making
+the required run-time choice.  The really significant benefit, of course, is
+keeping the source code clean and well structured.
+
+For example, the interface for entropy decoding (Huffman or arithmetic
+decoding) might look like this:
+
+	struct function_ptr_struct {
+		...
+		/* Entropy decoding methods */
+		void (*prepare_for_scan) ();
+		void (*get_next_mcu) ();
+		...
+		};
+
+	typedef struct function_ptr_struct * function_ptrs;
+
+The struct pointer is what will actually be passed around.  A call site might
+look like this:
+
+	some_function (function_ptrs fptrs)
+	    {
+		...
+		(*fptrs->get_next_mcu) (...);
+		...
+	    }
+
+(It might be worth inventing some specialized macros to hide the rather ugly
+syntax for method definition and call.)  Note that the caller doesn't know how
+many different get_next_mcu procedures there are, what their real names are,
+nor how to choose which one to call.
+
+An important benefit of this scheme is that it is easy to provide multiple
+versions of any method, each tuned to a particular case.  While a lot of
+precalculation might be done to select an optimal implementation of a method,
+the cost per invocation is constant.  For example, the MCU extraction step
+might have a "generic" method, plus one or more "hardwired" methods for the
+most popular sampling factors; the hardwired methods would be faster because
+they'd use straight-line code instead of for-loops.  The cost to determine
+which method to use is paid only once, at startup, and the selection criteria
+are hidden from the callers of the method.
+
+This plan differs a little bit from usual object-oriented structures, in that
+only one instance of each object class will exist during execution.  The
+reason for having the class structure is that on different runs we may create
+different instances (choose to execute different modules).
+
+To minimize the number of object pointers that have to be passed around, it
+will be easiest to have just a few big structs containing all the method
+pointers.  We'll actually use two such structs, one for "globally" defined
+methods (applicable to the whole file or to all components of the current
+scan) and one for methods applicable to a single component.  There'll be one
+copy of the second kind of struct for each component of the current scan.
+This is necessary so that preselection of an optimal method can be done based
+on component-specific information (like sampling ratios...)
+
+Because of this choice, it's best not to think of an "object" as a specific
+data structure.  Rather, an "object" is just a group of related methods.
+There would typically be one or more C modules (source files) providing
+concrete implementations of those methods.  You can think of the term
+"method" as denoting the common interface presented by some set of functions,
+and "object" as denoting a group of common method interfaces, or the total
+shared interface behavior of a group of modules.
+
+
+*** Data chunk sizes ***
+
+To make the cost of this object-oriented style really minimal, we should make
+sure that each method call does a fair amount of computation.  To do that we
+should pass large chunks of data around; for example, the colorspace
+conversion method should process much more than one pixel per call.
+
+For many steps, the most natural unit of data seems to be an "MCU row".
+This consists of one complete horizontal strip of the image, as high as an
+MCU.  In a noninterleaved scan, an MCU row is always eight samples high (when
+looking at samples) or one 8x8 block high (when looking at coefficients).  In
+an interleaved scan, an MCU row consists of all the data for one horizontal
+row of MCUs; this may be from one to four blocks high (eight to thirty-two
+samples) depending on the sampling factors.  The height and width of an MCU
+row may be different in each component.  (Note that the height and width of an
+MCU row changes at the subsampling and de-subsampling steps.  An unsubsampled
+image has the same size in each component.  The preceding statements apply to
+the subsampled dimensions.)
+
+For example, consider a 1024-pixel-wide image using (2h:2v)(1h:1v)(1h:1v)
+subsampling.  In the noninterleaved case, an MCU row of Y would contain 8x1024
+samples or the same number of frequency coefficients, so it would occupy
+8K bytes (samples) or 16K bytes (coefficients).  An MCU row of Cb or Cr would
+contain 8x512 samples and occupy half as much space.  In the interleaved case,
+an MCU row would contain 16x1024 Y samples, 8x512 Cb and 8x512 Cr samples, so
+a total of 24K (samples) or 48K (coefficients) would be needed.  This is a
+reasonable amount of data to expect to retain in memory at one time.  (Bear in
+mind that we'll usually need to have several MCU rows resident in memory at
+once, at the inputs and outputs to various pipeline steps.)
+
+The worst case is probably (2h:4v)(1h:1v)(1h:1v) interleaving (this uses 10
+blocks per MCU, which is the maximum allowed by the spec).  An MCU will then
+contain 32 sample rows worth of Y, so it would occupy 40K or 80K bytes for a
+1024-pixel-wide image.  The most memory-intensive step is probably cross-block
+smoothing, for which we'd need 3 MCU rows of coefficients as input and another
+one as output; that would be 320K of working storage.  Anything much larger
+would not fit in an 80x86 machine.  (To decompress wider pictures on an 80x86,
+we'll have to skip cross-block smoothing or else use temporary files.)
+
+This unit is thus a reasonable-sized chunk for passing through the pipeline.
+Of course, its major advantage is that it is a natural chunk size for the MCU
+assembly and disassembly steps to work with.
+
+For the entropy (Huffman or arithmetic) encoding/decoding steps, the most
+convenient chunk is a single MCU: one 8x8 block if not interleaved, three to
+ten such blocks if interleaved.  The advantage of this is that when handling
+interleaved data, the blocks have the same sequence of component membership on
+each call.  (For example, Y,Y,Y,Y,Cb,Cr when using (2h:2v)(1h:1v)(1h:1v)
+subsampling.)  The code needs to know component membership so that it can
+apply the right set of compression coefficients to each block.  A prebuilt
+array describing this membership can be used during each call.  This chunk
+size also makes it easy to handle restart intervals: just count off one MCU
+per call and reinitialize when the count reaches zero (restart intervals are
+specified in numbers of MCU).
+
+For similar reasons, one MCU is also the best chunk size for the frequency
+coefficient quantization and dequantization steps.
+
+For subsampling and desubsampling, the best chunk size is to have each call
+transform Vk sample rows from or to Vmax sample rows (Vk = this component's
+vertical sampling factor, Vmax = largest vertical sampling factor).  There are
+eight such chunks in each MCU row.  Using a whole MCU row as the chunk size
+would reduce function call overhead a fraction, but would imply more buffering
+to provide context for cross-pixel smoothing.
+
+
+*** Compression object structure ***
+
+I propose the following set of objects for the compressor.  Here an "object"
+is the common interface for one or more modules having comparable functions.
+
+Most of these objects can be justified as information-hiding modules.
+I've indicated what information is private to each object/module.
+
+Note that in all cases, the caller of a method is expected to have allocated
+any storage needed for it to return its result.  (Typically this storage can
+be re-used in successive calls, so malloc'ing and free'ing once per call is
+not reasonable.)  Also, much of the context required (compression parameters,
+image size, etc) will be passed around in large common data structures, which
+aren't described here; see the header files.  Notice that any object that
+might need to allocate working storage receives an "init" and a "term" call;
+"term" should be careful to free all allocated storage so that the JPEG system
+can be used multiple times during a program run.  (For the same reason,
+depending on static initialization of variables is a no-no.)
+
+1. Input file conversion to standardized form.  This provides these methods:
+	input_init: read the file header, report image size & component count.
+	get_input_row: read one pixel row, return it in our standard format.
+	input_term: finish up at the end.
+   In implementations that support multiple input formats, input_init could
+   set up an appropriate get_input_row method depending on the format it
+   finds.  Note that in most applications, the selection and opening of the
+   input file will be under the control of the user interface module; and
+   indeed the user interface may have already read the input header, so that
+   all that input_init may have to do is return previously saved values.  The
+   behind-the-scenes interaction between this object and the user interface is
+   not specified by this architecture.
+   (Hides format of input image and mechanism used to read it.  This code is
+   likely to vary considerably from one implementation to another.  Note that
+   the color space and number of color components of the source are not hidden;
+   but they are used only by the next object.)
+
+2. Gamma and color space conversion.  This provides three methods:
+	colorin_init: initialization.
+	get_sample_rows: read, convert, and return a specified number of pixel
+			 rows (not more than remain in the picture).
+	colorin_term: finish up at the end.
+   The most efficient approach seems to be for this object to call
+   get_input_row directly, rather than being passed the input data; that way,
+   any intermediate storage required can be local to this object.
+   (get_sample_rows might tell get_input_row to read directly into its own
+   output area and then convert in place; or it may do something different.
+   For example, conversion in place wouldn't work if it is changing the number
+   of color components.)  The output of this step is in the standardized
+   sample array format shown previously.
+   (Hides all knowledge of color space semantics and conversion.  Remaining
+   modules only need to know the number of JPEG components.)
+
+3. Edge expansion: needs only a single method.
+	edge_expand: Given an NxM sample array, expand to a desired size (a
+		     multiple of the MCU dimensions) by duplicating the last
+		     row or column.  Repeat for each component.
+   Expansion will occur in place, so the caller must have pre-allocated enough
+   storage.  (I'm assuming that it is easier and faster to do this expansion
+   than it is to worry about boundary conditions in the next two steps.
+   Notice that vertical expansion will occur only once, at the bottom of the
+   picture, so only horizontal expansion by a few pixels is speed-critical.)
+   (This doesn't really hide any information, so maybe it could be a simple
+   subroutine instead of a method.  Depends on whether we want to be able to
+   use alternative, optimized methods.)
+
+4. Subsampling: this will be applied to one component at a time.
+	subsample_init: initialize (precalculate convolution factors, for
+			example).  This will be called once per scan.
+	subsample: Given a sample array, reduce it to a smaller number of
+		   samples using specified sampling factors.
+	subsample_term: clean up at the end of a scan.
+   If the current component has vertical sampling factor Vk and the largest
+   sampling factor is Vmax, then the input is always Vmax sample rows (whose
+   width is a multiple of Hmax) and the output is always Vk sample rows.
+   Vmax additional rows above and below the nominal input rows are also passed
+   for use by partial-pixel-averaging sampling methods.  (Is this necessary?)
+   At the top and bottom of the image, these extra rows are copies of the
+   first or last actual input row.
+   (This hides whether and how cross-pixel averaging occurs.)
+
+5. MCU extraction (creation of a single sequence of 8x8 sample blocks).
+	extract_init: initialize as needed.  This will be called once per scan.
+	extract_MCUs: convert a sample array to a sequence of MCUs.
+	extract_term: clean up at the end of a scan.
+   Given one or more MCU rows worth of image data, extract sample blocks in the
+   appropriate order; pass these off to subsequent steps one MCU at a time.
+   The input must be a multiple of the MCU dimensions.  It will probably be
+   most convenient for the DCT transform, frequency quantization, and zigzag
+   reordering of each block to be done as simple subroutines of this step.
+   Once a transformed MCU has been completed, it'll be passed off to a
+   method call, which will be passed as a parameter to extract_MCUs.
+   That routine might either encode and output the MCU immediately, or buffer
+   it up for later output if we want to do global optimization of the entropy
+   encoding coefficients.  Note: when outputting a noninterleaved file this
+   object will be called separately for each component.  Direct output could
+   be done for the first component, but the others would have to be buffered.
+   (Again, an object mainly on the grounds that multiple instantiations might
+   be useful.)
+
+6. DCT transformation of each 8x8 block.  This probably doesn't have to be a
+   full-fledged method, but just a plain subroutine that will be called by MCU
+   extraction.  One 8x8 block will be processed per call.
+
+7. Quantization scaling and zigzag reordering of the elements in each 8x8
+   block.  (This can probably be a plain subroutine called once per block by
+   MCU extraction; hard to see a need for multiple instantiations here.)
+
+8. Entropy encoding (Huffman or arithmetic).
+	entropy_encoder_init: prepare for one scan.
+	entropy_encode: accepts an MCU's worth of quantized coefficients,
+			encodes and outputs them.
+	entropy_encoder_term: finish up at end of a scan (dump any buffered
+			      bytes, for example).
+   The data output by this module will be sent to the entropy_output method
+   provided by the pipeline controller.  (It will probably be worth using
+   buffering to pass multiple bytes per call of the output method.)  The
+   output method could be just write_jpeg_data, but might also be a dummy
+   routine that counts output bytes (for use during cut-and-try coefficient
+   optimization).
+   (This hides which entropy encoding method is in use.)
+
+9. JPEG file header construction.  This will provide these methods:
+	write_file_header: output the initial header.
+	write_scan_header: output scan header (called once per component
+			   if noninterleaved mode).
+	write_jpeg_data: the actual data output method for the preceding step.
+	write_scan_trailer: finish up after one scan.
+	write_file_trailer: finish up at end of file.
+   Note that compressed data is passed to the write_jpeg_data method, in case
+   a simple fwrite isn't appropriate for some reason.
+   (This hides which variant JPEG file format is being written.  Also, the
+   actual mechanism for writing the file is private to this object and the
+   user interface.)
+
+10. Pipeline control.  This object will provide the "main loop" that invokes
+    all the pipeline objects.  Note that we will need several different main
+    loops depending on the situation (interleaved output or not, global
+    optimization of encoding parameters or not, etc).  This object will do
+    most of the memory allocation, since it will provide the working buffers
+    that are the inputs and outputs of the pipeline steps.
+    (An object mostly to support multiple instantiations; however, overall
+    memory management and sequencing of operations are known only here.)
+
+11. Overall control.  This module will provide at least two routines:
+	jpeg_compress: the main entry point to the compressor.
+	per_scan_method_selection: called by pipeline controllers for
+				   secondary method selection passes.
+    jpeg_compress is invoked from the user interface after the UI has selected
+    the input and output files and obtained values for all compression
+    parameters that aren't dynamically determined.  jpeg_compress performs
+    basic initialization (e.g., calculating the size of MCUs), does the
+    "global" method selection pass, and finally calls the selected pipeline
+    control object.  (Per-scan method selections will be invoked by the
+    pipeline controller.)
+    Note that jpeg_compress can't be a method since it is invoked prior to
+    method selection.
+
+12. User interface; this is the architecture's term for "the rest of the
+    application program", i.e., that which invokes the JPEG compressor.  In a
+    standalone JPEG compression program the UI need be little more than a C
+    main() routine and argument parsing code; but we can expect that the JPEG
+    compressor may be incorporated into complex graphics applications, wherein
+    the UI is much more complex.  Much of the UI will need to be written
+    afresh for each non-Unix-like platform the compressor is ported to.
+    The UI is expected to supply input and output files and values for all
+    non-automatically-chosen compression parameters.  (Hence defaults are
+    determined by the UI; we should probably provide helpful routines to fill
+    in recommended defaults.)  The UI must also supply error handling
+    routines and some mechanism for trace messages.
+    (This module hides the user interface provided --- command line,
+    interactive, etc.  Except for error/message handling, the UI calls the
+    portable JPEG code, not the other way around.)
+
+13. (Optional) Compression parameter selection control.
+	entropy_optimize: given an array of MCUs ready to be fed to entropy
+			  encoding, find optimal encoding parameters.
+    The actual optimization algorithm ought to be separated out as an object,
+    even though a special pipeline control method will be needed.  (The
+    pipeline controller only has to understand that the output of extract_MCUs
+    must be built up as a virtual array rather than fed directly to entropy
+    encoding and output.  This pipeline behavior may also be useful for future
+    implementation of hierarchical modes, etc.)
+    To minimize the amount of control logic in the optimization module, the
+    pipeline control doesn't actually hand over big-array pointers, but rather
+    an "iterator": a function which knows how to scan the stored image.
+    (This hides the details of the parameter optimization algorithm.)
+
+    The present design doesn't allow for multiple passes at earlier points
+    in the pipeline, but allowing that would only require providing some
+    new pipeline control methods; nothing else need change.
+
+14. A memory management object.  This will provide methods to allocate "small"
+    things and "big" things.  Small things have to fit in memory and you get
+    back direct pointers (this could be handled by direct calls to malloc, but
+    it's cleaner not to assume malloc is the right routine).  "Big" things
+    mean buffered images for multiple passes, noninterleaved output, etc.
+    In this case the memory management object will give you room for a few MCU
+    rows and you have to ask for access to the next few; dumping and reloading
+    in a temporary file will go on behind the scenes.  (All big objects are
+    image arrays containing either samples or coefficients, and will be
+    scanned top-to-bottom some number of times, so we can apply this access
+    model easily.)  On a platform with virtual memory, the memory manager can
+    treat small and big things alike: just malloc up enough virtual memory for
+    the whole image, and let the operating system worry about swapping the
+    image to disk.
+
+    Most of the actual calls on the memory manager will be made from pipeline
+    control objects; changing any data item from "small" to "big" status would
+    require a new pipeline control object, since it will contain the logic to
+    ask for a new chunk of a big thing.  Thus, one way in which pipeline
+    controllers will vary is in which structures they treat as big.
+
+    The memory manager will need to be told roughly how much space is going to
+    be requested overall, so that it can figure out how big a buffer is safe
+    to allocate for a "big" object.  (If it happens that you are dealing with
+    a small image, you'd like to decide to keep it all in memory!)  The most
+    flexible way of doing this is to divide allocation of "big" objects into
+    two steps.  First, there will be one or more "request" calls that indicate
+    the desired object sizes; then an "instantiate" call causes the memory
+    manager to actually construct the objects.  The instantiation must occur
+    before the contents of any big object can be accessed.
+
+    For 80x86 CPUs, we would like the code to be compilable under small or
+    medium model, meaning that pointers are 16 bits unless explicitly declared
+    FAR.  Hence space allocated by the "small" allocator must fit into the
+    64Kb default data segment, along with stack space and global/static data.
+    For normal JPEG operations we seem to need only about 32Kb of such space,
+    so we are within the target (and have a reasonable slop for the needs of
+    a surrounding application program).  However, some color quantization
+    algorithms need 64Kb or more of all-in-memory space in order to create
+    color histograms.  For this purpose, we will also support "medium" size
+    things.  These are semantically the same as "small" things but are
+    referenced through FAR pointers.
+
+    The following methods will be needed:
+	alloc_small:	allocate an object of given size; use for any random
+			data that's not an image array.
+	free_small:	release same.
+	alloc_medium:	like alloc_small, but returns a FAR pointer.
+	free_medium:	release same.
+	alloc_small_sarray: construct an all-in-memory image sample array.
+	free_small_sarray:  release same.
+	alloc_small_barray,
+	free_small_barray:  ditto for block (coefficient) arrays.
+	request_big_sarray:  request a virtual image sample array.  The size
+			     of the in-memory buffer will be determined by the
+			     memory manager, but it will always be a multiple
+			     of the passed-in MCU height.
+	request_big_barray:  ditto for block (coefficient) arrays.
+	alloc_big_arrays:  instantiate all the big arrays previously requested.
+			   This call will also pass some info about future
+			   memory demands, so that the memory manager can
+			   figure out how much space to leave unallocated.
+	access_big_sarray: obtain access to a specified portion of a virtual
+			   image sample array.
+	access_big_barray: ditto for block (coefficient) arrays.
+	free_big_sarray:   release a virtual sample array.
+	free_big_barray:   ditto for block (coefficient) arrays.
+
+    alloc_big_arrays will be called by the pipeline controller, which does
+    most of the memory allocation anyway.  The only reason for having separate
+    request calls is to allow some of the other modules to get big arrays.
+    The pipeline controller is required to give an upper bound on total future
+    small-array requests, so that this space can be discounted.  (A fairly
+    conservative estimate will be adequate.)  Future small-object requests
+    aren't counted; the memory manager has to use a slop factor for those.
+    10K or so seems to be sufficient.  (In an 80x86, small objects aren't an
+    issue anyway, since they don't compete for far-heap space.  "Medium"-size
+    objects will have to be counted separately.)
+
+    The distinction between sample and coefficient array routines is annoying,
+    but it has to be maintained for machines in which "char *" is represented
+    differently from "int *"... on byte-addressable machines some of these
+    methods could point to the same code.
+
+    The array routines will operate on only 2-D arrays (one component at a
+    time), since different components may require different-size arrays.
+
+    (This object hides the knowledge of whether virtual memory is available,
+    as well as the actual interface to OS and library support routines.)
+
+Note that any given implementation will presumably contain only one
+instantiation of input file header reading, overall control, user interface,
+and memory management.  Thus these could be called as simple subroutines,
+without bothering with an object indirection.  This is essential for overall
+control (which has to initialize the object structure); I'm undecided whether
+to impose objectness on the other three.
+
+
+*** Decompression object structure ***
+
+I propose the following set of objects for decompression.  The general
+comments at the top of the compression object section also apply here.
+
+1. JPEG file scanning.  This will provide these methods:
+	read_file_header: read the file header, determine which variant
+			  JPEG format is in use, read everything through SOF.
+	read_scan_header: read scan header (up through SOS).  This is called
+			  after read_file_header and again after each scan;
+			  it returns TRUE if it finds SOS, FALSE if EOI.
+	read_jpeg_data: fetch data for entropy decoder.
+	read_scan_trailer: finish up after one scan, prepare for another call
+			   of read_scan_header (may be a no-op).
+	read_file_trailer: finish up at end of file (probably a no-op).
+   The entropy decoder must deal with restart markers, but all other JPEG
+   marker types will be handled in this object; useful data from the markers
+   will be extracted into data structures available to subsequent routines.
+   Note that on exit from read_file_header, only the SOF-marker data should be
+   assumed valid (image size, component IDs, sampling factors); other data
+   such as Huffman tables may not appear until after the SOF.  The overall
+   image size and colorspace can be determined after read_file_header, but not
+   whether or how the data is interleaved.  (This hides which variant JPEG
+   file format is being read.  In particular, for JPEG-in-TIFF the read_header
+   routines might not be scanning standard JPEG markers at all; they could
+   extract the data from TIFF tags.  The user interface will already have
+   opened the input file and possibly read part of the header before
+   read_file_header is called.)
+
+   NOTE: for JFIF/raw-JPEG file format, the read_jpeg_data routine is actually
+   supplied by the user interface; the jrdjfif module uses read_jpeg_data
+   internally to scan the input stream.  This makes it possible for the user
+   interface module to single-handedly implement special applications like
+   reading from a non-stdio source.  For JPEG-in-TIFF format, the need for
+   random access will make it impossible for this to work; hence the TIFF
+   header module will probably override the UI read_jpeg_data routine.
+   Non-stdio input from a TIFF file will require extensive surgery to the TIFF
+   header module, if indeed it is practical at all.
+
+2. Entropy (Huffman or arithmetic) decoding of the coefficient sequence.
+	entropy_decoder_init: prepare for one scan.
+	entropy_decode: decodes and returns an MCU's worth of quantized
+			coefficients per call.
+	entropy_decoder_term: finish up after a scan (may be a no-op).
+   This will read raw data by calling the read_jpeg_data method (I don't see
+   any reason to provide a further level of indirection).
+   (This hides which entropy encoding method is in use.)
+
+3. Quantization descaling and zigzag reordering of the elements in each 8x8
+   block.  (This can probably be a plain subroutine called once per block;
+   hard to see a need for multiple instantiations here.)
+
+4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8
+   blocks back to separate components in pixel map order).
+	disassemble_init: initialize.  This will be called once per scan.
+	disassemble_MCU:  Given an MCU's worth of dequantized blocks,
+			  distribute them into the proper locations in a
+			  coefficient image array.
+	disassemble_term: clean up at the end of a scan.
+   Probably this should be called once per MCU row and should call the
+   preceding two objects repeatedly to obtain the row's data.  The output is
+   always a multiple of an MCU's dimensions.
+   (An object on the grounds that multiple instantiations might be useful.)
+
+5. Cross-block smoothing per JPEG section 13.10 or a similar algorithm.
+	smooth_coefficients: Given three block rows' worth of a single
+			     component, emit a smoothed equivalent of the
+			     middle row.  The "above" and "below" pointers
+			     may be NULL if at top/bottom of image.
+   The pipeline controller will do the necessary buffering to provide the
+   above/below context.  Smoothing will be optional since a good deal of
+   extra memory is needed to buffer the additional block rows.
+   (This object hides the details of the smoothing algorithm.)
+
+6. Inverse DCT transformation of each 8x8 block.  (This can be a plain
+   subroutine processing one block per call.)
+
+7. De-subsampling and smoothing: this will be applied to one component at a
+   time.  Note that cross-pixel smoothing, which was a separate step in the
+   prototype code, will now be performed simultaneously with expansion.
+	unsubsample_init: initialize (precalculate convolution factors, for
+			  example).  This will be called once per scan.
+	unsubsample: Given a sample array, enlarge it by specified sampling
+		     factors.
+	unsubsample_term: clean up at the end of a scan.
+   If the current component has vertical sampling factor Vk and the largest
+   sampling factor is Vmax, then the input is always Vk sample rows (whose
+   width is a multiple of Hk) and the output is always Vmax sample rows.
+   Vk additional rows above and below the nominal input rows are also passed
+   for use in cross-pixel smoothing.  At the top and bottom of the image,
+   these extra rows are copies of the first or last actual input row.
+   (This hides whether and how cross-pixel smoothing occurs.)
+
+8. Cropping to the original pixel dimensions (throwing away duplicated
+   pixels at the edges).  This won't be a separate object, just an
+   adjustment of the nominal image size in the pipeline controller.
+
+9. Color space reconversion and gamma adjustment.
+	colorout_init: initialization.  This will be passed the component
+		       data from read_file_header, and will determine the
+		       number of output components.
+	color_convert: convert a specified number of pixel rows.  Input and
+		       output are image arrays of same size but possibly
+		       different numbers of components.
+	colorout_term: cleanup (probably a no-op except for memory dealloc).
+   In practice will always be given an MCU row's worth of pixel rows, except
+   at the bottom where a smaller number of rows may be left over.  Note that
+   this object works on all the components at once.
+   (Hides all knowledge of color space semantics and conversion.  Remaining
+   modules only need to know the number of JPEG and output components.)
+
+10. Color quantization (used only if a colormapped output format is requested).
+    We use two different strategies depending on whether one-pass (on-the-fly)
+    or two-pass quantization is requested.  Note that the two-pass interface
+    is actually designed to let the quantizer make any number of passes.
+	color_quant_init: initialization, allocate working memory.  In 1-pass
+			  quantization, should call put_color_map.
+	color_quantize: convert a specified number of pixel rows.  Input
+			and output are image arrays of same size, but input
+			is N coefficients and output is only one.  (Used only
+			in 1-pass quantization.)
+	color_quant_prescan: prescan a specified number of pixel rows in
+			     2-pass quantization.
+	color_quant_doit: perform multi-pass color quantization.  Input is a
+			  "big" sample image, output is via put_color_map and
+			  put_pixel_rows.  (Used only in 2-pass quantization.)
+	color_quant_term: cleanup (probably a no-op except for memory dealloc).
+    For one-pass quantization the image is simply processed by color_quantize,
+    a few rows at a time.  For two-pass quantization, the pipeline controller
+    accumulates the output of color_convert into a "big" sample image.  The
+    color_quant_prescan method is invoked during this process so that the
+    quantizer can accumulate statistics.  At the end of the image,
+    color_quant_doit is called; it must rescan the "big" image and pass
+    converted data to the output module.  Additional scans of the image could
+    be made before the output pass is done (in fact, prescan could be a no-op).
+    As with entropy parameter optimization, the pipeline controller actually
+    passes an iterator function rather than direct access to the big image.
+    NOTE: it might be better to do this on the internal color space instead of
+    RGB?  If so, it would need to be performed one step earlier.
+    (Hides color quantization algorithm.)
+
+11. Writing of the desired image format.
+	output_init: produce the file header given data from read_file_header.
+	put_color_map: output colormap, if any (called by color quantizer).
+	put_pixel_rows: output image data in desired format.
+	output_term: finish up at the end.
+    Note that whether colormapping is needed will be determined by the user
+    interface object prior to method selection.  In implementations that
+    support multiple output formats, the actual output format will also be
+    determined by the user interface.
+    (Hides format of output image and mechanism used to write it.  Note that
+    several other objects know the color model used by the output format.  The
+    actual mechanism for writing the file is private to this object and the
+    user interface.)
+
+12. Pipeline control.  This object will provide the "main loop" that invokes
+    all the pipeline objects.  Note that we will need several different main
+    loops depending on the situation (interleaved input or not, whether to
+    apply cross-block smoothing or not, etc).  We may want to divvy up the
+    pipeline controllers into two levels, one that retains control over the
+    whole file and one that is invoked per scan.
+    This object will do most of the memory allocation, since it will provide
+    the working buffers that are the inputs and outputs of the pipeline steps.
+    (An object mostly to support multiple instantiations; however, overall
+    memory management and sequencing of operations are known only here.)
+
+13. Overall control.  This module will provide at least two routines:
+	jpeg_decompress: the main entry point to the decompressor.
+	per_scan_method_selection: called by pipeline controllers for
+				   secondary method selection passes.
+    jpeg_decompress is invoked from the user interface after the UI has
+    selected the input and output files and obtained values for all
+    user-specified options (e.g., output file format, whether to do block
+    smoothing).  jpeg_decompress calls read_file_header, performs basic
+    initialization (e.g., calculating the size of MCUs), does the "global"
+    method selection pass, and finally calls the selected pipeline control
+    object.  (Per-scan method selections will be invoked by the pipeline
+    controller.)
+    Note that jpeg_decompress can't be a method since it is invoked prior to
+    method selection.
+
+14. User interface; this is the architecture's term for "the rest of the
+    application program", i.e., that which invokes the JPEG decompressor.
+    The UI is expected to supply input and output files and values for all
+    operational parameters.  The UI must also supply error handling routines.
+    At the moment I can't think of any nonfatal errors the JPEG code is likely
+    to report, so a single report-this-error-and-exit method should be
+    sufficient.
+    (This module hides the user interface provided --- command line,
+    interactive, etc.  Except for error handling, the UI calls the portable
+    JPEG code, not the other way around.)
+
+15. A memory management object.  This will be identical to the memory
+    management for compression (and will be the same code, in combined
+    programs).  See above for details.
+
+
+*** Initial method selection ***
+
+The main ugliness in this design is the portion of startup that will select
+which of several instantiations should be used for each of the objects.  (For
+example, Huffman or arithmetic for entropy encoding; one of several pipeline
+controllers depending on interleaving, the size of the image, etc.)  It's not
+really desirable to have a single chunk of code that knows the names of all
+the possible instantiations and the conditions under which to select each one.
+
+The best approach seems to be to provide a selector function for each object
+(group of related method calls).  This function knows about each possible
+instantiation of its object and how to choose the right one; but it doesn't
+know about any other objects.
+
+Note that there will be several rounds of method selection: at initial startup,
+after overall compression parameters are determined (after the file header is
+read, if decompressing), and one in preparation for each scan (this occurs
+more than once if the file is noninterleaved).  Each object method will need
+to be clearly identified as to which round sets it up.
+
+
+*** Implications of DNL marker ***
+
+Some JPEG files may use a DNL marker to postpone definition of the image
+height (this would be useful for a fax-like scanner's output, for instance).
+In these files the SOF marker claims the image height is 0, and you only
+find out the true image height at the end of the first scan.
+
+We could handle these files as follows:
+1. Upon seeing zero image height, replace it by 65535 (the maximum allowed).
+2. When the DNL is found, update the image height in the global image
+   descriptor.
+This implies that pipeline control objects must avoid making copies of the
+image height, and must re-test for termination after each MCU row.  This is
+no big deal.
+
+In situations where image-size data structures are allocated, this approach
+will result in very inefficient use of virtual memory or
+much-larger-than-necessary temporary files.  This seems acceptable for
+something that probably won't be a mainstream usage.  People might have to
+forgo use of memory-hogging options (such as two-pass color quantization or
+noninterleaved JPEG files) if they want efficient conversion of such files.
+(One could improve efficiency by demanding a user-supplied upper bound for the
+height, less than 65536; in most cases it could be much less.)
+
+Alternately, we could insist that DNL-using files be preprocessed by a
+separate program that reads ahead to the DNL, then goes back and fixes the SOF
+marker.  This is a much simpler solution and is probably far more efficient.
+Even if one wants piped input, buffering the first scan of the JPEG file
+needs a lot smaller temp file than is implied by the maximum-height method.
+For this approach we'd simply treat DNL as a no-op in the decompressor (at
+most, check that it matches the SOF image height).
+
+We will not worry about making the compressor capable of outputting DNL.  Note
+that something similar to the first scheme above could be applied if anyone
+ever wants to make that work.
+
+
+*** Notes for MS-DOS implementors ***
+
+The standalone cjpeg and djpeg applications can be compiled in "small" memory
+model, at least at the moment; as the code grows we may be forced to switch to
+"medium" model.  (Small = both code and data pointers are near by default;
+medium = far code pointers, near data pointers.)  Medium model will slow down
+calls through method pointers, but I don't think this will amount to any
+significant speed penalty.
+
+When integrating the JPEG code into a larger application, it's a good idea to
+stay with a small-data-space model if possible.  An 8K stack is much more than
+sufficient for the JPEG code, and its static data requirements are less than
+1K.  When executed, it will typically malloc about 10K worth of near heap
+space (and lots of far heap, but that doesn't count in this calculation).
+This figure will vary depending on image size and other factors, but figuring
+20K should be more than sufficient.  Thus you have about 35K available for
+other modules' static data and near heap requirements before you need to go to
+a larger memory model.  The C library's static data will account for several K
+of this, but that still leaves a good deal for your needs.  (If you are tight
+on space, you could reduce JPEG_BUF_SIZE from 4K to 1K to save 3K of near heap
+space.)
+
+As the code is improved, we will endeavor to hold the near data requirements
+to the range given above.  This does imply that certain data structures will
+be allocated as FAR although they would fit in near space if we assumed the
+JPEG code is stand-alone.  (The LZW tables in jrdgif/jwrgif are examples.)
+To make an optimal implementation, you might want to move these structures
+back to near heap if you know there is sufficient space.
+
+
+*** Potential optimizations ***
+
+For colormapped input formats it might be worthwhile to merge the input file
+reading and the colorspace conversion steps; in other words, do the colorspace
+conversion by hacking up the colormap before inputting the image body, rather
+than doing the conversion on each pixel independently.  Not clear if this is
+worth the uglification involved.  In the above design for the compressor, only
+the colorspace conversion step ever sees the output of get_input_row, so this
+sort of thing could be done via private agreement between those two modules.
+
+Level shift from 0..255 to -128..127 may be done either during colorspace
+conversion, or at the moment of converting an 8x8 sample block into the format
+used by the DCT step (which will be signed short or long int).  This could be
+selectable by a compile-time flag, so that the intermediate steps can work on
+either signed or unsigned chars as samples, whichever is most easily handled
+by the platform.  However, making sure that rounding is done right will be a
+lot easier if we can assume positive values.  At the moment I think that
+benefit is worth the overhead of "& 0xFF" when reading out sample values on
+signed-char-only machines.
diff --git a/codingrules b/codingrules
new file mode 100644
index 0000000..fd6f700
--- /dev/null
+++ b/codingrules
@@ -0,0 +1,99 @@
+
+	JPEG SYSTEM CODING RULES		27-SEP-91
+
+Since numerous people will be contributing code and bug fixes, it's important
+to establish a common coding style.  The goal of using similar coding styles
+is much more important than the details of just what that style is.
+
+I suggest we follow the recommendations of "Recommended C Style and Coding
+Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
+Brader).  I have placed a copy of this document in the jpeg FTP archive (see
+jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
+
+Unless someone has a real strong objection, let's do block comments thusly:
+
+/*
+ *  Block comments in this style.
+ */
+
+and indent statements in K&R style, e.g.,
+
+	if (test) {
+	    then-part;
+	} else {
+	    else-part;
+	}
+
+I suggest that multi-word names be written in the style multi_word_name
+rather than multiWordName, but I am open to argument on this.
+
+
+I would like to use function prototypes everywhere, and rely on automatic
+source code transformation to feed non-ANSI C compilers.  The best tool
+I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
+ansi2knr is not very bright, so it imposes a format requirement on function
+declarations: the function name MUST BEGIN IN COLUMN 1.  Thus all functions
+should be written in the following style:
+
+static int *
+function_name (int a, char *b)
+{
+    code...
+}
+
+ansi2knr won't help with method declarations (function pointers in structs).
+I suggest we use a macro to declare method pointers, something like this:
+
+#ifdef PROTO
+#define METHOD(type,methodname,arglist)  type (*methodname) arglist
+#else
+#define METHOD(type,methodname,arglist)  type (*methodname) ()
+#endif
+
+which is used like this:
+
+struct function_pointers {
+	METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
+	METHOD(void, term_entropy_encoder, (void));
+};
+
+Note the set of parentheses surrounding the parameter list.
+
+A similar solution is used for external function declarations (see the PP
+macro in jpegdata.h).
+
+If the code is to work on non-ANSI compilers, you cannot rely on a prototype
+declaration to coerce actual parameters into the right types.  Therefore, use
+explicit casts on actual parameters whenever the actual parameter type is not
+identical to the formal parameter.  Beware of implicit conversions to "int".
+
+It seems there are some non-ANSI compilers in which the sizeof() operator
+is defined to return int, while size_t is defined as long.  Needless to say,
+this is brain-damaged.  Always use the SIZEOF() macro in place of sizeof(),
+so that the result is guaranteed to be of type size_t.
+
+
+We can expect that the JPEG compressor and decompressor will be incorporated
+into larger programs.  Therefore, the following rules are important:
+
+1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
+pass these through the common routines provided.
+
+2. Assume that the JPEG code may be invoked more than once per program run;
+therefore, do not rely on static initialization of variables, and be careful
+to release all allocated storage at the end of processing.
+
+3. Minimize global namespace pollution.  Functions should be declared static
+wherever possible.  (Note that our method-based calling conventions help this
+a lot: in many modules only the method-selector function will ever need to be
+called directly, so only that function need be externally visible.)  All
+global function names should begin with "j", and should be unique in the first
+six characters for portability reasons.
+Don't use global variables at all; anything that must be used in another
+module should be put into parameters (there'll be some large structs passed
+around for this purpose).
+
+4. Source file names should also begin with "j"; remember to keep them to
+eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
+Do not put code for both compression and decompression into the same source
+file.
diff --git a/egetopt.c b/egetopt.c
new file mode 100644
index 0000000..8183d35
--- /dev/null
+++ b/egetopt.c
@@ -0,0 +1,276 @@
+/*
+ * egetopt.c -- Extended 'getopt'.
+ *
+ * A while back, a public-domain version of getopt() was posted to the
+ * net.  A bit later, a gentleman by the name of Keith Bostic made some
+ * enhancements and reposted it.
+ *
+ * In recent weeks (i.e., early-to-mid 1988) there's been some
+ * heated discussion in comp.lang.c about the merits and drawbacks
+ * of getopt(), especially with regard to its handling of '?'.
+ *
+ * In light of this, I have taken Mr. Bostic's public-domain getopt()
+ * and have made some changes that I hope will be considered to be
+ * improvements.  I call this routine 'egetopt' ("Extended getopt").
+ * The default behavior of this routine is the same as that of getopt(),
+ * but it has some optional features that make it more useful.  These
+ * options are controlled by the settings of some global variables.
+ * By not setting any of these extra global variables, you will have
+ * the same functionality as getopt(), which should satisfy those
+ * purists who believe getopt() is perfect and can never be improved.
+ * If, on the other hand, you are someone who isn't satisfied with the
+ * status quo, egetopt() may very well give you the added capabilities
+ * you want.
+ *
+ * Look at the enclosed README file for a description of egetopt()'s
+ * new features.
+ *
+ * The code was originally posted to the net as getopt.c by ...
+ *
+ *	Keith Bostic
+ *	ARPA: keith@seismo 
+ *	UUCP: seismo!keith
+ *
+ * Current version: added enhancements and comments, reformatted code.
+ *
+ *	Lloyd Zusman
+ *	Master Byte Software
+ *	Los Gatos, California
+ *	Internet:	ljz@fx.com
+ *	UUCP:		...!ames!fxgrp!ljz
+ *
+ *    	May, 1988
+ */
+
+/*
+ * If you want, include stdio.h or something where EOF and NULL are defined.
+ * However, egetopt() is written so as not to need stdio.h, which should
+ * make it significantly smaller on some systems.
+ */
+
+#ifndef EOF
+# define EOF		(-1)
+#endif /* ! EOF */
+
+#ifndef NULL
+# define NULL		(char *)0
+#endif /* ! NULL */
+
+/*
+ * None of these constants are referenced in the executable portion of
+ * the code ... their sole purpose is to initialize global variables.
+ */
+#define BADCH		(int)'?'
+#define NEEDSEP		(int)':'
+#define MAYBESEP	(int)'\0'
+#define ERRFD		2
+#define EMSG		""
+#define START		"-"
+
+/*
+ * Here are all the pertinent global variables.
+ */
+int opterr = 1;		/* if true, output error message */
+int optind = 1;		/* index into parent argv vector */
+int optopt;		/* character checked for validity */
+int optbad = BADCH;	/* character returned on error */
+int optchar = 0;	/* character that begins returned option */
+int optneed = NEEDSEP;	/* flag for mandatory argument */
+int optmaybe = MAYBESEP;/* flag for optional argument */
+int opterrfd = ERRFD;	/* file descriptor for error text */
+char *optarg;		/* argument associated with option */
+char *optstart = START;	/* list of characters that start options */
+
+
+/*
+ * Macros.
+ */
+
+/*
+ * Conditionally print out an error message and return (depends on the
+ * setting of 'opterr' and 'opterrfd').  Note that this version of
+ * TELL() doesn't require the existence of stdio.h.
+ */
+#define TELL(S)	{ \
+	if (opterr && opterrfd >= 0) { \
+		char option = optopt; \
+		write(opterrfd, *nargv, strlen(*nargv)); \
+		write(opterrfd, (S), strlen(S)); \
+		write(opterrfd, &option, 1); \
+		write(opterrfd, "\n", 1); \
+	} \
+	return (optbad); \
+}
+
+/*
+ * This works similarly to index() and strchr().  I include it so that you
+ * don't need to be concerned as to which one your system has.
+ */
+static char *
+_sindex(string, ch)
+char *string;
+int ch;
+{
+	if (string != NULL) {
+		for (; *string != '\0'; ++string) {
+			if (*string == (char)ch) {
+				return (string);
+			}
+		}
+	}
+
+	return (NULL);
+}
+
+/*
+ * Here it is:
+ */
+int
+egetopt(nargc, nargv, ostr)
+int nargc;
+char **nargv;
+char *ostr;
+{
+	static char *place = EMSG;	/* option letter processing */
+	register char *oli;		/* option letter list index */
+	register char *osi = NULL;	/* option start list index */
+
+	if (nargv == (char **)NULL) {
+		return (EOF);
+	}
+
+	if (nargc <= optind || nargv[optind] == NULL) {
+		return (EOF);
+	}
+
+	if (place == NULL) {
+		place = EMSG;
+	}
+
+	/*
+	 * Update scanning pointer.
+	 */
+	if (*place == '\0') {
+		place = nargv[optind];
+		if (place == NULL) {
+			return (EOF);
+		}
+		osi = _sindex(optstart, *place);
+		if (osi != NULL) {
+			optchar = (int)*osi;
+		}
+		if (optind >= nargc || osi == NULL || *++place == '\0') {
+		    	return (EOF);
+		}
+
+		/*
+		 * Two adjacent, identical flag characters were found.
+		 * This takes care of "--", for example.
+		 */
+		if (*place == place[-1]) {
+			++optind;
+			return (EOF);
+		}
+	}
+
+	/*
+	 * If the option is a separator or the option isn't in the list,
+	 * we've got an error.
+	 */
+	optopt = (int)*place++;
+	oli = _sindex(ostr, optopt);
+	if (optopt == optneed || optopt == optmaybe || oli == NULL) {
+		/*
+		 * If we're at the end of the current argument, bump the
+		 * argument index.
+		 */
+		if (*place == '\0') {
+			++optind;
+		}
+		TELL(": illegal option -- ");	/* byebye */
+	}
+
+	/*
+	 * If there is no argument indicator, then we don't even try to
+	 * return an argument.
+	 */
+	++oli;
+	if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
+		/*
+		 * If we're at the end of the current argument, bump the
+		 * argument index.
+		 */
+		if (*place == '\0') {
+			++optind;
+		}
+		optarg = NULL;
+	}
+	/*
+	 * If we're here, there's an argument indicator.  It's handled
+	 * differently depending on whether it's a mandatory or an
+	 * optional argument.
+	 */
+	else {
+		/*
+		 * If there's no white space, use the rest of the
+		 * string as the argument.  In this case, it doesn't
+		 * matter if the argument is mandatory or optional.
+		 */
+		if (*place != '\0') {
+			optarg = place;
+		}
+		/*
+		 * If we're here, there's whitespace after the option.
+		 *
+		 * Is it a mandatory argument?  If so, return the
+		 * next command-line argument if there is one.
+		 */
+		else if (*oli == optneed) {
+			/*
+			 * If we're at the end of the argument list, there
+			 * isn't an argument and hence we have an error.
+			 * Otherwise, make 'optarg' point to the argument.
+			 */
+			if (nargc <= ++optind) {
+				place = EMSG;
+				TELL(": option requires an argument -- ");
+			}
+			else {
+				optarg = nargv[optind];
+			}
+		}
+		/*
+		 * If we're here it must have been an optional argument.
+		 */
+		else {
+			if (nargc <= ++optind) {
+				place = EMSG;
+				optarg = NULL;
+			}
+			else {
+				optarg = nargv[optind];
+				if (optarg == NULL) {
+					place = EMSG;
+				}
+				/*
+				 * If the next item begins with a flag
+				 * character, we treat it like a new
+				 * argument.  This is accomplished by
+				 * decrementing 'optind' and returning
+				 * a null argument.
+				 */
+				else if (_sindex(optstart, *optarg) != NULL) {
+					--optind;
+					optarg = NULL;
+				}
+			}
+		}
+		place = EMSG;
+		++optind;
+	}
+
+	/*
+	 * Return option letter.
+	 */
+	return (optopt);
+}
diff --git a/jbsmooth.c b/jbsmooth.c
new file mode 100644
index 0000000..ad2138d
--- /dev/null
+++ b/jbsmooth.c
@@ -0,0 +1,120 @@
+/*
+ * jbsmooth.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains cross-block smoothing routines.
+ * These routines are invoked via the smooth_coefficients method.
+ */
+
+#include "jinclude.h"
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+
+/*
+ * Cross-block coefficient smoothing.
+ */
+
+METHODDEF void
+smooth_coefficients (decompress_info_ptr cinfo,
+		     jpeg_component_info *compptr,
+		     JBLOCKROW above,
+		     JBLOCKROW currow,
+		     JBLOCKROW below,
+		     JBLOCKROW output)
+{
+  QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
+  long blocks_in_row = compptr->subsampled_width / DCTSIZE;
+  long col;
+
+  /* First, copy the block row as-is.
+   * This takes care of the first & last blocks in the row, the top/bottom
+   * special cases, and the higher-order coefficients in each block.
+   */
+  jcopy_block_row(currow, output, blocks_in_row);
+
+  /* Now apply the smoothing calculation, but not to any blocks on the
+   * edges of the image.
+   */
+
+  if (above != NULL && below != NULL) {
+    for (col = 1; col < blocks_in_row-1; col++) {
+
+      /* See section 13.10 of JPEG-8-R8, or K.8 of JPEG-9-R6.
+       *
+       * As I understand it, this produces approximations
+       * for the low frequency AC components, based on the
+       * DC values of the block and its eight neighboring blocks.
+       * (Thus it can't be used for blocks on the image edges.)
+       */
+
+      /* The layout of these variables corresponds to
+       * the text in 13.10
+       */
+      
+      JCOEF DC1, DC2, DC3;
+      JCOEF DC4, DC5, DC6;
+      JCOEF DC7, DC8, DC9;
+      
+      long       AC01, AC02;
+      long AC10, AC11;
+      long AC20;
+      
+      DC1 = above [col-1][0];
+      DC2 = above [col  ][0];
+      DC3 = above [col+1][0];
+      DC4 = currow[col-1][0];
+      DC5 = currow[col  ][0];
+      DC6 = currow[col+1][0];
+      DC7 = below [col-1][0];
+      DC8 = below [col  ][0];
+      DC9 = below [col+1][0];
+      
+#define DIVIDE_256(x)	x = ( (x) < 0 ? -((128-(x))/256) : ((x)+128)/256 )
+      
+      AC01 = (36 * (DC4 - DC6));
+      DIVIDE_256(AC01);
+      AC10 = (36 * (DC2 - DC8));
+      DIVIDE_256(AC10);
+      AC20 = (9 * (DC2 + DC8 - 2*DC5));
+      DIVIDE_256(AC20);
+      AC11 = (5 * ((DC1 - DC3) - (DC7 - DC9)));
+      DIVIDE_256(AC11);
+      AC02 = (9 * (DC4 + DC6 - 2*DC5));
+      DIVIDE_256(AC02);
+      
+      /* I think that this checks to see if the quantisation
+       * on the transmitting side would have produced this
+       * answer. If so, then we use our (hopefully better)
+       * estimate.
+       */
+
+#define ABS(x)	((x) < 0 ? -(x) : (x))
+
+#define COND_ASSIGN(_ac,_n,_z)   if ((ABS(output[col][_n] - (_ac))<<1) <= Qptr[_z]) output[col][_n] = (_ac)
+
+      COND_ASSIGN(AC01,  1, 1);
+      COND_ASSIGN(AC02,  2, 5);
+      COND_ASSIGN(AC10,  8, 2);
+      COND_ASSIGN(AC11,  9, 4);
+      COND_ASSIGN(AC20, 16, 3);
+    }
+  }
+}
+
+
+/*
+ * The method selection routine for cross-block smoothing.
+ */
+
+GLOBAL void
+jselbsmooth (decompress_info_ptr cinfo)
+{
+  /* just one implementation for now */
+  cinfo->methods->smooth_coefficients = smooth_coefficients;
+}
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
diff --git a/jcarith.c b/jcarith.c
new file mode 100644
index 0000000..1949459
--- /dev/null
+++ b/jcarith.c
@@ -0,0 +1,42 @@
+/*
+ * jcarith.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains arithmetic entropy encoding routines.
+ * These routines are invoked via the methods entropy_encode,
+ * entropy_encoder_init/term, and entropy_optimize.
+ */
+
+#include "jinclude.h"
+
+#ifdef ARITH_CODING_SUPPORTED
+
+
+/*
+ * The arithmetic coding option of the JPEG standard specifies Q-coding,
+ * which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
+ * At this time it does not appear to be legal for the Independent JPEG
+ * Group to distribute software that implements arithmetic coding.
+ * We have therefore removed arithmetic coding support from the
+ * distributed source code.
+ *
+ * We're not happy about it either.
+ */
+
+
+/*
+ * The method selection routine for arithmetic entropy encoding.
+ */
+
+GLOBAL void
+jselcarithmetic (compress_info_ptr cinfo)
+{
+  if (cinfo->arith_code) {
+    ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
+  }
+}
+
+#endif /* ARITH_CODING_SUPPORTED */
diff --git a/jccolor.c b/jccolor.c
new file mode 100644
index 0000000..7fd198c
--- /dev/null
+++ b/jccolor.c
@@ -0,0 +1,203 @@
+/*
+ * jccolor.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input colorspace conversion routines.
+ * These routines are invoked via the methods get_sample_rows
+ * and colorin_init/term.
+ */
+
+#include "jinclude.h"
+
+
+static JSAMPARRAY pixel_row;	/* Workspace for a pixel row in input format */
+
+
+/*
+ * Initialize for colorspace conversion.
+ */
+
+METHODDEF void
+colorin_init (compress_info_ptr cinfo)
+{
+  /* Allocate a workspace for the result of get_input_row. */
+  pixel_row = (*cinfo->emethods->alloc_small_sarray)
+		(cinfo->image_width, (long) cinfo->input_components);
+}
+
+
+/*
+ * Fetch some rows of pixels from get_input_row and convert to the
+ * JPEG colorspace.
+ * This version handles RGB -> YCbCr conversion.
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ */
+
+METHODDEF void
+get_rgb_ycc_rows (compress_info_ptr cinfo,
+		  int rows_to_read, JSAMPIMAGE image_data)
+{
+  register INT32 r, g, b;
+  register JSAMPROW inptr0, inptr1, inptr2;
+  register JSAMPROW outptr0, outptr1, outptr2;
+  register long col;
+  long width = cinfo->image_width;
+  int row;
+
+  for (row = 0; row < rows_to_read; row++) {
+    /* Read one row from the source file */
+    (*cinfo->methods->get_input_row) (cinfo, pixel_row);
+    /* Convert colorspace */
+    inptr0 = pixel_row[0];
+    inptr1 = pixel_row[1];
+    inptr2 = pixel_row[2];
+    outptr0 = image_data[0][row];
+    outptr1 = image_data[1][row];
+    outptr2 = image_data[2][row];
+    for (col = width; col > 0; col--) {
+      r = GETJSAMPLE(*inptr0++);
+      g = GETJSAMPLE(*inptr1++);
+      b = GETJSAMPLE(*inptr2++);
+      /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+       * must be too; do not need an explicit range-limiting operation.
+       */
+      /* Y */
+      *outptr0++ = (   306*r +  601*g +  117*b + (INT32) 512) >> 10;
+      /* Cb */
+      *outptr1++ = ((-173)*r -  339*g +  512*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10;
+      /* Cr */
+      *outptr2++ = (   512*r -  429*g -   83*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10;
+    }
+  }
+}
+
+
+/*
+ * Fetch some rows of pixels from get_input_row and convert to the
+ * JPEG colorspace.
+ * This version handles grayscale (no conversion).
+ */
+
+METHODDEF void
+get_grayscale_rows (compress_info_ptr cinfo,
+		    int rows_to_read, JSAMPIMAGE image_data)
+{
+  int row;
+
+  for (row = 0; row < rows_to_read; row++) {
+    /* Read one row from the source file */
+    (*cinfo->methods->get_input_row) (cinfo, pixel_row);
+    /* Convert colorspace (gamma mapping needed here) */
+    jcopy_sample_rows(pixel_row, 0, image_data[0], row,
+		      1, cinfo->image_width);
+  }
+}
+
+
+/*
+ * Fetch some rows of pixels from get_input_row and convert to the
+ * JPEG colorspace.
+ * This version handles multi-component colorspaces without conversion.
+ */
+
+METHODDEF void
+get_noconvert_rows (compress_info_ptr cinfo,
+		    int rows_to_read, JSAMPIMAGE image_data)
+{
+  int row, ci;
+
+  for (row = 0; row < rows_to_read; row++) {
+    /* Read one row from the source file */
+    (*cinfo->methods->get_input_row) (cinfo, pixel_row);
+    /* Convert colorspace (gamma mapping needed here) */
+    for (ci = 0; ci < cinfo->input_components; ci++) {
+      jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
+			1, cinfo->image_width);
+    }
+  }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+colorin_term (compress_info_ptr cinfo)
+{
+  /* Release the workspace. */
+  (*cinfo->emethods->free_small_sarray)
+		(pixel_row, (long) cinfo->input_components);
+}
+
+
+/*
+ * The method selection routine for input colorspace conversion.
+ */
+
+GLOBAL void
+jselccolor (compress_info_ptr cinfo)
+{
+  /* Make sure input_components agrees with in_color_space */
+  switch (cinfo->in_color_space) {
+  case CS_GRAYSCALE:
+    if (cinfo->input_components != 1)
+      ERREXIT(cinfo->emethods, "Bogus input colorspace");
+    break;
+
+  case CS_RGB:
+    if (cinfo->input_components != 3)
+      ERREXIT(cinfo->emethods, "Bogus input colorspace");
+    break;
+
+  case CS_CMYK:
+    if (cinfo->input_components != 4)
+      ERREXIT(cinfo->emethods, "Bogus input colorspace");
+    break;
+
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported input colorspace");
+    break;
+  }
+
+  /* Check num_components, set conversion method based on requested space */
+  switch (cinfo->jpeg_color_space) {
+  case CS_GRAYSCALE:
+    if (cinfo->num_components != 1)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    if (cinfo->in_color_space == CS_GRAYSCALE)
+      cinfo->methods->get_sample_rows = get_grayscale_rows;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  case CS_YCbCr:
+    if (cinfo->num_components != 3)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    if (cinfo->in_color_space == CS_RGB)
+      cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  case CS_CMYK:
+    if (cinfo->num_components != 4)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    if (cinfo->in_color_space == CS_CMYK)
+      cinfo->methods->get_sample_rows = get_noconvert_rows;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
+    break;
+  }
+
+  cinfo->methods->colorin_init = colorin_init;
+  cinfo->methods->colorin_term = colorin_term;
+}
diff --git a/jcdeflts.c b/jcdeflts.c
new file mode 100644
index 0000000..cd1624a
--- /dev/null
+++ b/jcdeflts.c
@@ -0,0 +1,364 @@
+/*
+ * jcdeflts.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains optional default-setting code for the JPEG compressor.
+ */
+
+#include "jinclude.h"
+
+
+LOCAL void
+add_huff_table (compress_info_ptr cinfo,
+		HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+  if (*htblptr == NULL)
+    *htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
+  
+  memcpy((void *) (*htblptr)->bits, (void *) bits,
+	 SIZEOF((*htblptr)->bits));
+  memcpy((void *) (*htblptr)->huffval, (void *) val,
+	 SIZEOF((*htblptr)->huffval));
+
+  /* Initialize sent_table FALSE so table will be written to JPEG file.
+   * In an application where we are writing non-interchange JPEG files,
+   * it might be desirable to save space by leaving default Huffman tables
+   * out of the file.  To do that, just initialize sent_table = TRUE...
+   */
+
+  (*htblptr)->sent_table = FALSE;
+}
+
+
+LOCAL void
+std_huff_tables (compress_info_ptr cinfo)
+/* Set up the standard Huffman tables (cf. JPEG-8-R8 section 13.3) */
+{
+  static const UINT8 dc_luminance_bits[17] =
+    { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+  static const UINT8 dc_luminance_val[] =
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+  
+  static const UINT8 dc_chrominance_bits[17] =
+    { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+  static const UINT8 dc_chrominance_val[] =
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+  
+  static const UINT8 ac_luminance_bits[17] =
+    { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+  static const UINT8 ac_luminance_val[] =
+    { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+      0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+      0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+      0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+      0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+      0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+      0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+      0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+      0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+      0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+      0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+      0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+      0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+      0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+      0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+      0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+      0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+      0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+      0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+      0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+      0xf9, 0xfa };
+  
+  static const UINT8 ac_chrominance_bits[17] =
+    { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+  static const UINT8 ac_chrominance_val[] =
+    { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+      0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+      0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+      0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+      0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+      0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+      0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+      0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+      0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+      0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+      0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+      0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+      0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+      0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+      0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+      0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+      0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+      0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+      0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+      0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+      0xf9, 0xfa };
+  
+  add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+		 dc_luminance_bits, dc_luminance_val);
+  add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+		 ac_luminance_bits, ac_luminance_val);
+  add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+		 dc_chrominance_bits, dc_chrominance_val);
+  add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+		 ac_chrominance_bits, ac_chrominance_val);
+}
+
+
+/* This is the sample quantization table given in JPEG-8-R8 sec 13.1,
+ * but expressed in zigzag order (as are all of our quant. tables).
+ * The spec says that the values given produce "good" quality, and
+ * when divided by 2, "very good" quality.  (These two settings are
+ * selected by quality=50 and quality=75 in j_set_quality, below.)
+ */
+
+
+static const QUANT_VAL std_luminance_quant_tbl[DCTSIZE2] = {
+  16,  11,  12,  14,  12,  10,  16,  14,
+  13,  14,  18,  17,  16,  19,  24,  40,
+  26,  24,  22,  22,  24,  49,  35,  37,
+  29,  40,  58,  51,  61,  60,  57,  51,
+  56,  55,  64,  72,  92,  78,  64,  68,
+  87,  69,  55,  56,  80, 109,  81,  87,
+  95,  98, 103, 104, 103,  62,  77, 113,
+ 121, 112, 100, 120,  92, 101, 103,  99
+};
+
+static const QUANT_VAL std_chrominance_quant_tbl[DCTSIZE2] = {
+  17,  18,  18,  24,  21,  24,  47,  26,
+  26,  47,  99,  66,  56,  66,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99
+};
+
+
+LOCAL void
+add_quant_table (compress_info_ptr cinfo, int which_tbl,
+		 const QUANT_VAL *basic_table, int scale_factor,
+		 boolean force_baseline)
+/* Define a quantization table equal to the basic_table times */
+/* a scale factor (given as a percentage) */
+{
+  QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+  int i;
+  long temp;
+
+  if (*qtblptr == NULL)
+    *qtblptr = (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
+
+  for (i = 0; i < DCTSIZE2; i++) {
+    temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+    /* limit the values to the valid range */
+    if (temp <= 0L) temp = 1L;
+#ifdef EIGHT_BIT_SAMPLES
+    if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */
+#else
+    if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */
+#endif
+    if (force_baseline && temp > 255L)
+      temp = 255L;		/* limit to baseline range if requested */
+    (*qtblptr)[i] = (QUANT_VAL) temp;
+  }
+}
+
+
+GLOBAL void
+j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting. */
+/* The 'quality' factor should be 0 (terrible) to 100 (very good). */
+/* Quality 50 corresponds to the JPEG basic tables given above; */
+/* quality 100 results in no quantization scaling at all. */
+/* If force_baseline is TRUE, quantization table entries are limited */
+/* to 0..255 for JPEG baseline compatibility; this is only an issue */
+/* for quality settings below 24. */
+{
+  /* Safety limit on quality factor.  Convert 0 to 1 to avoid zero divide. */
+  if (quality <= 0) quality = 1;
+  if (quality > 100) quality = 100;
+
+  /* Convert quality rating to a percentage scaling of the basic tables.
+   * The basic table is used as-is (scaling 100) for a quality of 50.
+   * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
+   * note that at Q=100 the scaling is 0, which will cause add_quant_table
+   * to make all the table entries 1 (hence, no quantization loss).
+   * Qualities 1..50 are converted to scaling percentage 5000/Q.
+   */
+  if (quality < 50)
+    quality = 5000 / quality;
+  else
+    quality = 200 - quality*2;
+
+  /* Set up two quantization tables using the specified quality scaling */
+  add_quant_table(cinfo, 0, std_luminance_quant_tbl, quality, force_baseline);
+  add_quant_table(cinfo, 1, std_chrominance_quant_tbl, quality, force_baseline);
+}
+
+
+
+/* Default parameter setup for compression.
+ *
+ * User interfaces that don't choose to use this routine must do their
+ * own setup of all these parameters.  Alternately, you can call this
+ * to establish defaults and then alter parameters selectively.
+ *
+ * See above for the meaning of the 'quality' parameter.  Typically,
+ * the application's default quality setting will be passed to this
+ * routine.  A later call on j_set_quality() can be used to change to
+ * a user-specified quality setting.
+ *
+ * This sets up for a color image; to output a grayscale image,
+ * do this first and call j_monochrome_default() afterwards.
+ * (The latter can be called within c_ui_method_selection, so the
+ * choice can depend on the input file header.)
+ * Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr,
+ * you should also change the component ID codes, and you should NOT emit
+ * a JFIF header (set write_JFIF_header = FALSE).
+ *
+ * CAUTION: if you want to compress multiple images per run, it's safest
+ * to call j_default_compression before *each* call to jpeg_compress (and
+ * j_free_defaults afterwards).  If this isn't practical, you'll have to
+ * be careful to reset any individual parameters that may change during
+ * the compression run.  The main thing you need to worry about as this
+ * is written is that the sent_table boolean in each Huffman table must
+ * be reset to FALSE before each compression; otherwise, Huffman tables
+ * won't get emitted for the second and subsequent images.
+ */
+
+GLOBAL void
+j_default_compression (compress_info_ptr cinfo, int quality)
+/* NB: the external methods must already be set up. */
+{
+  short i;
+  jpeg_component_info * compptr;
+
+  /* Initialize pointers as needed to mark stuff unallocated. */
+  cinfo->comp_info = NULL;
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    cinfo->quant_tbl_ptrs[i] = NULL;
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    cinfo->dc_huff_tbl_ptrs[i] = NULL;
+    cinfo->ac_huff_tbl_ptrs[i] = NULL;
+  }
+
+  cinfo->data_precision = 8;	/* default; can be overridden by input_init */
+  cinfo->density_unit = 0;	/* Pixel size is unknown by default */
+  cinfo->X_density = 1;		/* Pixel aspect ratio is square by default */
+  cinfo->Y_density = 1;
+
+  cinfo->input_gamma = 1.0;	/* no gamma correction by default */
+
+  /* Prepare three color components; first is luminance which is also usable */
+  /* for grayscale.  The others are assumed to be UV or similar chrominance. */
+  cinfo->write_JFIF_header = TRUE;
+  cinfo->jpeg_color_space = CS_YCbCr;
+  cinfo->num_components = 3;
+  cinfo->comp_info = (*cinfo->emethods->alloc_small)
+			(4 * SIZEOF(jpeg_component_info));
+  /* Note: we allocate a 4-entry comp_info array so that user interface can
+   * easily change over to CMYK color space if desired.
+   */
+
+  compptr = &cinfo->comp_info[0];
+  compptr->component_index = 0;
+  compptr->component_id = 1;	/* JFIF specifies IDs 1,2,3 */
+  compptr->h_samp_factor = 2;	/* default to 2x2 subsamples of chrominance */
+  compptr->v_samp_factor = 2;
+  compptr->quant_tbl_no = 0;	/* use tables 0 for luminance */
+  compptr->dc_tbl_no = 0;
+  compptr->ac_tbl_no = 0;
+
+  compptr = &cinfo->comp_info[1];
+  compptr->component_index = 1;
+  compptr->component_id = 2;
+  compptr->h_samp_factor = 1;
+  compptr->v_samp_factor = 1;
+  compptr->quant_tbl_no = 1;	/* use tables 1 for chrominance */
+  compptr->dc_tbl_no = 1;
+  compptr->ac_tbl_no = 1;
+
+  compptr = &cinfo->comp_info[2];
+  compptr->component_index = 2;
+  compptr->component_id = 3;
+  compptr->h_samp_factor = 1;
+  compptr->v_samp_factor = 1;
+  compptr->quant_tbl_no = 1;	/* use tables 1 for chrominance */
+  compptr->dc_tbl_no = 1;
+  compptr->ac_tbl_no = 1;
+
+  /* Set up two quantization tables using the specified quality scaling */
+  /* Baseline compatibility is forced (a nonissue for reasonable defaults) */
+  j_set_quality(cinfo, quality, TRUE);
+
+  /* Set up two Huffman tables in case user interface wants Huffman coding */
+  std_huff_tables(cinfo);
+
+  /* Initialize default arithmetic coding conditioning */
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    cinfo->arith_dc_L[i] = 0;
+    cinfo->arith_dc_U[i] = 1;
+    cinfo->arith_ac_K[i] = 5;
+  }
+
+  /* Use Huffman coding, not arithmetic coding, by default */
+  cinfo->arith_code = FALSE;
+
+  /* Color images are interleaved by default */
+  cinfo->interleave = TRUE;
+
+  /* By default, don't do extra passes to optimize entropy coding */
+  cinfo->optimize_coding = FALSE;
+
+  /* By default, use the simpler non-cosited sampling alignment */
+  cinfo->CCIR601_sampling = FALSE;
+
+  /* No restart markers */
+  cinfo->restart_interval = 0;
+}
+
+
+
+GLOBAL void
+j_monochrome_default (compress_info_ptr cinfo)
+/* Change the j_default_compression() values to emit a monochrome JPEG file. */
+{
+  jpeg_component_info * compptr;
+
+  cinfo->jpeg_color_space = CS_GRAYSCALE;
+  cinfo->num_components = 1;
+  /* Set single component to 1x1 subsampling */
+  compptr = &cinfo->comp_info[0];
+  compptr->h_samp_factor = 1;
+  compptr->v_samp_factor = 1;
+}
+
+
+
+/* This routine releases storage allocated by j_default_compression.
+ * Note that freeing the method pointer structs and the compress_info_struct
+ * itself are the responsibility of the user interface.
+ */
+
+GLOBAL void
+j_free_defaults (compress_info_ptr cinfo)
+{
+  short i;
+
+#define FREE(ptr)  if ((ptr) != NULL) \
+			(*cinfo->emethods->free_small) ((void *) ptr)
+
+  FREE(cinfo->comp_info);
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    FREE(cinfo->quant_tbl_ptrs[i]);
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    FREE(cinfo->dc_huff_tbl_ptrs[i]);
+    FREE(cinfo->ac_huff_tbl_ptrs[i]);
+  }
+}
diff --git a/jcexpand.c b/jcexpand.c
new file mode 100644
index 0000000..94878bd
--- /dev/null
+++ b/jcexpand.c
@@ -0,0 +1,75 @@
+/*
+ * jcexpand.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains image edge-expansion routines.
+ * These routines are invoked via the edge_expand method.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * Expand an image so that it is a multiple of the MCU dimensions.
+ * This is to be accomplished by duplicating the rightmost column
+ * and/or bottommost row of pixels.  The image has not yet been
+ * subsampled, so all components have the same dimensions.
+ */
+
+METHODDEF void
+edge_expand (compress_info_ptr cinfo,
+	     long input_cols, int input_rows,
+	     long output_cols, int output_rows,
+	     JSAMPIMAGE image_data)
+{
+  /* Expand horizontally */
+  if (input_cols < output_cols) {
+    register JSAMPROW ptr;
+    register JSAMPLE pixval;
+    register long count;
+    register int row;
+    short ci;
+    long numcols = output_cols - input_cols;
+
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      for (row = 0; row < input_rows; row++) {
+	ptr = image_data[ci][row] + (input_cols-1);
+	pixval = GETJSAMPLE(*ptr++);
+	for (count = numcols; count > 0; count--)
+	  *ptr++ = pixval;
+      }
+    }
+  }
+
+  /* Expand vertically */
+  /* This happens only once at the bottom of the image, */
+  /* so it needn't be super-efficient */
+  if (input_rows < output_rows) {
+    register int row;
+    short ci;
+    JSAMPARRAY this_component;
+
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      this_component = image_data[ci];
+      for (row = input_rows; row < output_rows; row++) {
+	jcopy_sample_rows(this_component, input_rows-1, this_component, row,
+			  1, output_cols);
+      }
+    }
+  }
+}
+
+
+/*
+ * The method selection routine for edge expansion.
+ */
+
+GLOBAL void
+jselexpand (compress_info_ptr cinfo)
+{
+  /* just one implementation for now */
+  cinfo->methods->edge_expand = edge_expand;
+}
diff --git a/jchuff.c b/jchuff.c
new file mode 100644
index 0000000..531bc75
--- /dev/null
+++ b/jchuff.c
@@ -0,0 +1,689 @@
+/*
+ * jchuff.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines.
+ * These routines are invoked via the methods entropy_encode,
+ * entropy_encoder_init/term, and entropy_optimize.
+ */
+
+#include "jinclude.h"
+
+
+/* Static variables to avoid passing 'round extra parameters */
+
+static compress_info_ptr cinfo;
+
+static INT32 huff_put_buffer;	/* current bit-accumulation buffer */
+static int huff_put_bits;	/* # of bits now in it */
+
+static char * output_buffer;	/* output buffer */
+static int bytes_in_buffer;
+
+
+
+LOCAL void
+fix_huff_tbl (HUFF_TBL * htbl)
+/* Compute derived values for a Huffman table */
+{
+  int p, i, l, lastp, si;
+  char huffsize[257];
+  UINT16 huffcode[257];
+  UINT16 code;
+  
+  /* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
+  /* Note that this is in code-length order. */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    for (i = 1; i <= htbl->bits[l]; i++)
+      huffsize[p++] = l;
+  }
+  huffsize[p] = 0;
+  lastp = p;
+  
+  /* Figure 7.3.5.4.2.2: generate the codes themselves */
+  /* Note that this is in code-length order. */
+  
+  code = 0;
+  si = huffsize[0];
+  p = 0;
+  while (huffsize[p]) {
+    while (huffsize[p] == si) {
+      huffcode[p++] = code;
+      code++;
+    }
+    code <<= 1;
+    si++;
+  }
+  
+  /* Figure 7.3.5.4.2.3: generate encoding tables */
+  /* These are code and size indexed by symbol value */
+
+  for (p = 0; p < lastp; p++) {
+    htbl->ehufco[htbl->huffval[p]] = huffcode[p];
+    htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
+  }
+  
+  /* Figure 13.4.2.3.1: generate decoding tables */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    if (htbl->bits[l]) {
+      htbl->valptr[l] = p;	/* huffval[] index of 1st sym of code len l */
+      htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
+      p += htbl->bits[l];
+      htbl->maxcode[l] = huffcode[p-1];	/* maximum code of length l */
+    } else {
+      htbl->maxcode[l] = -1;
+    }
+  }
+}
+
+
+/* Outputting bytes to the file */
+
+LOCAL void
+flush_bytes (void)
+{
+  if (bytes_in_buffer)
+    (*cinfo->methods->entropy_output) (cinfo, output_buffer, bytes_in_buffer);
+  bytes_in_buffer = 0;
+}
+
+
+#define emit_byte(val)	((bytes_in_buffer >= JPEG_BUF_SIZE ? \
+				(flush_bytes(), 0) : 0), \
+			 output_buffer[bytes_in_buffer] = (val), \
+			 bytes_in_buffer++)
+
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of huff_put_buffer are used; the valid bits are
+ * left-justified in this part.  At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in huff_put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+LOCAL void
+emit_bits (UINT16 code, int size)
+{
+  /* This routine is heavily used, so it's worth coding tightly. */
+  register INT32 put_buffer = code;
+  register int put_bits = huff_put_bits;
+
+  put_buffer &= (((INT32) 1) << size) - 1; /* Mask off any excess bits in code */
+  
+  put_bits += size;		/* new number of bits in buffer */
+  
+  put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+  put_buffer |= huff_put_buffer; /* and merge with old buffer contents */
+  
+  while (put_bits >= 8) {
+    int c = (int) ((put_buffer >> 16) & 0xFF);
+    
+    emit_byte(c);
+    if (c == 0xFF) {		/* need to stuff a zero byte? */
+      emit_byte(0);
+    }
+    put_buffer <<= 8;
+    put_bits -= 8;
+  }
+
+  huff_put_buffer = put_buffer;	/* Update global variables */
+  huff_put_bits = put_bits;
+}
+
+
+LOCAL void
+flush_bits (void)
+{
+  emit_bits((UINT16) 0x7F, 7);	/* fill any partial byte with ones */
+  huff_put_buffer = 0;		/* and reset bit-buffer to empty */
+  huff_put_bits = 0;
+}
+
+
+
+/* Encode a single block's worth of coefficients */
+/* Note that the DC coefficient has already been converted to a difference */
+
+LOCAL void
+encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
+{
+  register INT32 temp;
+  register int nbits;
+  register int k, r, i;
+  
+  /* Encode the DC coefficient difference per section 7.3.5.1 */
+  
+  /* Find the number of bits needed for the magnitude of the coefficient */
+  temp = block[0];
+  if (temp < 0) temp = -temp;
+  
+  nbits = 0;
+  while (temp) {
+    nbits++;
+    temp >>= 1;
+  }
+  
+  /* Emit the Huffman-coded symbol for the number of bits */
+  emit_bits(dctbl->ehufco[nbits], dctbl->ehufsi[nbits]);
+  
+  /* If positive, emit nbits low order bits; */
+  /* if negative, emit nbits low order bits of value-1 */
+  if ((temp = block[0]) < 0)
+    temp--;
+  
+  emit_bits((UINT16) temp, nbits);
+  
+  /* Encode the AC coefficients per section 7.3.5.2 */
+  
+  r = 0;			/* r = run length of zeros */
+  
+  for (k = 1; k < DCTSIZE2; k++) {
+    if ((temp = block[k]) == 0) {
+      r++;
+    } else {
+      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+      while (r > 15) {
+	emit_bits(actbl->ehufco[0xF0], actbl->ehufsi[0xF0]);
+	r -= 16;
+      }
+      
+      /* Find the number of bits needed for the magnitude of the coefficient */
+      if (temp < 0) temp = -temp;
+
+      nbits = 1;		/* there must be at least one 1 bit */
+      while (temp >>= 1)
+	nbits++;
+      
+      /* Emit Huffman symbol for run length / number of bits */
+      i = (r << 4) + nbits;
+      emit_bits(actbl->ehufco[i], actbl->ehufsi[i]);
+      
+      /* If positive, emit nbits low order bits; */
+      /* if negative, emit nbits low order bits of value-1 */
+      if ((temp = block[k]) < 0)
+	temp--;
+      
+      emit_bits((UINT16) temp, nbits);
+      
+      r = 0;
+    }
+  }
+
+  /* If the last coef(s) were zero, emit an end-of-block code */
+  if (r > 0)
+    emit_bits(actbl->ehufco[0], actbl->ehufsi[0]);
+}
+
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * This is invoked after writing the SOS marker.
+ * The pipeline controller must establish the entropy_output method pointer
+ * before calling this routine.
+ */
+
+METHODDEF void
+huff_init (compress_info_ptr xinfo)
+{
+  short ci;
+  jpeg_component_info * compptr;
+
+  /* Initialize static variables */
+  cinfo = xinfo;
+  huff_put_buffer = 0;
+  huff_put_bits = 0;
+
+  /* Initialize the output buffer */
+  output_buffer = (char *) (*cinfo->emethods->alloc_small)
+				((size_t) JPEG_BUF_SIZE);
+  bytes_in_buffer = 0;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* Make sure requested tables are present */
+    if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
+	cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
+      ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
+    /* Compute derived values for Huffman tables */
+    /* We may do this more than once for same table, but it's not a big deal */
+    fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
+    fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
+    /* Initialize DC predictions to 0 */
+    cinfo->last_dc_val[ci] = 0;
+  }
+
+  /* Initialize restart stuff */
+  cinfo->restarts_to_go = cinfo->restart_interval;
+  cinfo->next_restart_num = 0;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL void
+emit_restart (compress_info_ptr cinfo)
+{
+  short ci;
+
+  flush_bits();
+
+  emit_byte(0xFF);
+  emit_byte(RST0 + cinfo->next_restart_num);
+
+  /* Re-initialize DC predictions to 0 */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+    cinfo->last_dc_val[ci] = 0;
+
+  /* Update restart state */
+  cinfo->restarts_to_go = cinfo->restart_interval;
+  cinfo->next_restart_num++;
+  cinfo->next_restart_num &= 7;
+}
+
+
+/*
+ * Encode and output one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF void
+huff_encode (compress_info_ptr cinfo, JBLOCK *MCU_data)
+{
+  short blkn, ci;
+  jpeg_component_info * compptr;
+  JCOEF temp;
+
+  /* Account for restart interval, emit restart marker if needed */
+  if (cinfo->restart_interval) {
+    if (cinfo->restarts_to_go == 0)
+      emit_restart(cinfo);
+    cinfo->restarts_to_go--;
+  }
+
+  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    /* Convert DC value to difference, update last_dc_val */
+    temp = MCU_data[blkn][0];
+    MCU_data[blkn][0] -= cinfo->last_dc_val[ci];
+    cinfo->last_dc_val[ci] = temp;
+    encode_one_block(MCU_data[blkn],
+		     cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no],
+		     cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
+  }
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF void
+huff_term (compress_info_ptr cinfo)
+{
+  /* Flush out the last data */
+  flush_bits();
+  flush_bytes();
+  /* Release the I/O buffer */
+  (*cinfo->emethods->free_small) ((void *) output_buffer);
+}
+
+
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * This actually is optimization, in the sense that we find the best possible
+ * Huffman table(s) for the given data.  We first scan the supplied data and
+ * count the number of uses of each symbol that is to be Huffman-coded.
+ * (This process must agree with the code above.)  Then we build an
+ * optimal Huffman coding tree for the observed counts.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+
+/* These are static so htest_one_block can find 'em */
+static long * dc_count_ptrs[NUM_HUFF_TBLS];
+static long * ac_count_ptrs[NUM_HUFF_TBLS];
+
+
+LOCAL void
+gen_huff_coding (compress_info_ptr cinfo, HUFF_TBL *htbl, long freq[])
+/* Generate the optimal coding for the given counts */
+{
+#define MAX_CLEN 32		/* assumed maximum initial code length */
+  UINT8 bits[MAX_CLEN+1];	/* bits[k] = # of symbols with code length k */
+  short codesize[257];		/* codesize[k] = code length of symbol k */
+  short others[257];		/* next symbol in current branch of tree */
+  int c1, c2;
+  int p, i, j;
+  long v;
+
+  /* This algorithm is explained in section 13.2 of JPEG-8-R8 */
+
+  MEMZERO((void *) bits, SIZEOF(bits));
+  MEMZERO((void *) codesize, SIZEOF(codesize));
+  for (i = 0; i < 257; i++)
+    others[i] = -1;		/* init links to empty */
+  
+  freq[256] = 1;		/* make sure there is a nonzero count */
+  /* including the pseudo-symbol 256 in the Huffman procedure guarantees
+   * that no real symbol is given code-value of all ones, because 256
+   * will be placed in the largest codeword category.
+   */
+
+  /* Huffman's basic algorithm to assign optimal code lengths to symbols */
+
+  for (;;) {
+    /* Find the smallest nonzero frequency, set c1 = its symbol */
+    /* In case of ties, take the larger symbol number */
+    c1 = -1;
+    v = 1000000000L;
+    for (i = 0; i <= 256; i++) {
+      if (freq[i] && freq[i] <= v) {
+	v = freq[i];
+	c1 = i;
+      }
+    }
+
+    /* Find the next smallest nonzero frequency, set c2 = its symbol */
+    /* In case of ties, take the larger symbol number */
+    c2 = -1;
+    v = 1000000000L;
+    for (i = 0; i <= 256; i++) {
+      if (freq[i] && freq[i] <= v && i != c1) {
+	v = freq[i];
+	c2 = i;
+      }
+    }
+
+    /* Done if we've merged everything into one frequency */
+    if (c2 < 0)
+      break;
+    
+    /* Else merge the two counts/trees */
+    freq[c1] += freq[c2];
+    freq[c2] = 0;
+
+    /* Increment the codesize of everything in c1's tree branch */
+    codesize[c1]++;
+    while (others[c1] >= 0) {
+      c1 = others[c1];
+      codesize[c1]++;
+    }
+    
+    others[c1] = c2;		/* chain c2 onto c1's tree branch */
+    
+    /* Increment the codesize of everything in c2's tree branch */
+    codesize[c2]++;
+    while (others[c2] >= 0) {
+      c2 = others[c2];
+      codesize[c2]++;
+    }
+  }
+
+  /* Now count the number of symbols of each code length */
+  for (i = 0; i <= 256; i++) {
+    if (codesize[i]) {
+      /* The JPEG standard seems to think that this can't happen, */
+      /* but I'm paranoid... */
+      if (codesize[i] > MAX_CLEN)
+	ERREXIT(cinfo->emethods, "Huffman code size table overflow");
+
+      bits[codesize[i]]++;
+    }
+  }
+
+  /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+   * Huffman procedure assigned any such lengths, we must adjust the coding.
+   * Here is what the JPEG spec says about how this next bit works:
+   * Since symbols are paired for the longest Huffman code, the symbols are
+   * removed from this length category two at a time.  The prefix for the pair
+   * (which is one bit shorter) is allocated to one of the pair; then,
+   * skipping the BITS entry for that prefix length, a code word from the next
+   * shortest nonzero BITS entry is converted into a prefix for two code words
+   * one bit longer.
+   */
+  
+  for (i = MAX_CLEN; i > 16; i--) {
+    while (bits[i] > 0) {
+      j = i - 2;		/* find length of new prefix to be used */
+      while (bits[j] == 0)
+	j--;
+      
+      bits[i] -= 2;		/* remove two symbols */
+      bits[i-1]++;		/* one goes in this length */
+      bits[j+1] += 2;		/* two new symbols in this length */
+      bits[j]--;		/* symbol of this length is now a prefix */
+    }
+  }
+
+  /* Remove the count for the pseudo-symbol 256 from the largest codelength */
+  while (bits[i] == 0)		/* find largest codelength still in use */
+    i--;
+  bits[i]--;
+  
+  /* Return final symbol counts (only for lengths 0..16) */
+  memcpy((void *) htbl->bits, (void *) bits, SIZEOF(htbl->bits));
+  
+  /* Return a list of the symbols sorted by code length */
+  /* It's not real clear to me why we don't need to consider the codelength
+   * changes made above, but the JPEG spec seems to think this works.
+   */
+  p = 0;
+  for (i = 1; i <= MAX_CLEN; i++) {
+    for (j = 0; j <= 255; j++) {
+      if (codesize[j] == i) {
+	htbl->huffval[p] = j;
+	p++;
+      }
+    }
+  }
+}
+
+
+/* Process a single block's worth of coefficients */
+/* Note that the DC coefficient has already been converted to a difference */
+
+LOCAL void
+htest_one_block (JBLOCK block, JCOEF block0,
+		 long dc_counts[], long ac_counts[])
+{
+  register INT32 temp;
+  register int nbits;
+  register int k, r;
+  
+  /* Encode the DC coefficient difference per section 7.3.5.1 */
+  
+  /* Find the number of bits needed for the magnitude of the coefficient */
+  temp = block0;
+  if (temp < 0) temp = -temp;
+  
+  for (nbits = 0; temp; nbits++)
+    temp >>= 1;
+  
+  /* Count the Huffman symbol for the number of bits */
+  dc_counts[nbits]++;
+  
+  /* Encode the AC coefficients per section 7.3.5.2 */
+  
+  r = 0;			/* r = run length of zeros */
+  
+  for (k = 1; k < DCTSIZE2; k++) {
+    if ((temp = block[k]) == 0) {
+      r++;
+    } else {
+      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+      while (r > 15) {
+	ac_counts[0xF0]++;
+	r -= 16;
+      }
+      
+      /* Find the number of bits needed for the magnitude of the coefficient */
+      if (temp < 0) temp = -temp;
+      
+      for (nbits = 0; temp; nbits++)
+	temp >>= 1;
+      
+      /* Count Huffman symbol for run length / number of bits */
+      ac_counts[(r << 4) + nbits]++;
+      
+      r = 0;
+    }
+  }
+
+  /* If the last coef(s) were zero, emit an end-of-block code */
+  if (r > 0)
+    ac_counts[0]++;
+}
+
+
+
+/*
+ * Trial-encode one MCU's worth of Huffman-compressed coefficients.
+ */
+
+LOCAL void
+htest_encode (compress_info_ptr cinfo, JBLOCK *MCU_data)
+{
+  short blkn, ci;
+  jpeg_component_info * compptr;
+
+  /* Take care of restart intervals if needed */
+  if (cinfo->restart_interval) {
+    if (cinfo->restarts_to_go == 0) {
+      /* Re-initialize DC predictions to 0 */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+	cinfo->last_dc_val[ci] = 0;
+      /* Update restart state */
+      cinfo->restarts_to_go = cinfo->restart_interval;
+    }
+    cinfo->restarts_to_go--;
+  }
+
+  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    /* NB: unlike the real entropy encoder, we may not change the input data */
+    htest_one_block(MCU_data[blkn],
+		    (JCOEF) (MCU_data[blkn][0] - cinfo->last_dc_val[ci]),
+		    dc_count_ptrs[compptr->dc_tbl_no],
+		    ac_count_ptrs[compptr->ac_tbl_no]);
+    cinfo->last_dc_val[ci] = MCU_data[blkn][0];
+  }
+}
+
+
+
+/*
+ * Find the best coding parameters for a Huffman-coded scan.
+ * When called, the scan data has already been converted to a sequence of
+ * MCU groups of quantized coefficients, which are stored in a "big" array.
+ * The source_method knows how to iterate through that array.
+ * On return, the MCU data is unmodified, but the Huffman tables referenced
+ * by the scan components may have been altered.
+ */
+
+METHODDEF void
+huff_optimize (compress_info_ptr cinfo, MCU_output_caller_ptr source_method)
+/* Optimize Huffman-coding parameters (Huffman symbol table) */
+{
+  int i, tbl;
+  HUFF_TBL **htblptr;
+
+  /* Allocate and zero the count tables */
+  /* Note that gen_huff_coding expects 257 entries in each table! */
+
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    dc_count_ptrs[i] = NULL;
+    ac_count_ptrs[i] = NULL;
+  }
+
+  for (i = 0; i < cinfo->comps_in_scan; i++) {
+    /* Create DC table */
+    tbl = cinfo->cur_comp_info[i]->dc_tbl_no;
+    if (dc_count_ptrs[tbl] == NULL) {
+      dc_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small)
+					(257 * SIZEOF(long));
+      MEMZERO((void *) dc_count_ptrs[tbl], 257 * SIZEOF(long));
+    }
+    /* Create AC table */
+    tbl = cinfo->cur_comp_info[i]->ac_tbl_no;
+    if (ac_count_ptrs[tbl] == NULL) {
+      ac_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small)
+					(257 * SIZEOF(long));
+      MEMZERO((void *) ac_count_ptrs[tbl], 257 * SIZEOF(long));
+    }
+  }
+
+  /* Initialize DC predictions to 0 */
+  for (i = 0; i < cinfo->comps_in_scan; i++) {
+    cinfo->last_dc_val[i] = 0;
+  }
+  /* Initialize restart stuff */
+  cinfo->restarts_to_go = cinfo->restart_interval;
+
+  /* Scan the MCU data, count symbol uses */
+  (*source_method) (cinfo, htest_encode);
+
+  /* Now generate optimal Huffman tables */
+  for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) {
+    if (dc_count_ptrs[tbl] != NULL) {
+      htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+      if (*htblptr == NULL)
+	*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
+      /* Set sent_table FALSE so updated table will be written to JPEG file. */
+      (*htblptr)->sent_table = FALSE;
+      /* Compute the optimal Huffman encoding */
+      gen_huff_coding(cinfo, *htblptr, dc_count_ptrs[tbl]);
+      /* Release the count table */
+      (*cinfo->emethods->free_small) ((void *) dc_count_ptrs[tbl]);
+    }
+    if (ac_count_ptrs[tbl] != NULL) {
+      htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+      if (*htblptr == NULL)
+	*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
+      /* Set sent_table FALSE so updated table will be written to JPEG file. */
+      (*htblptr)->sent_table = FALSE;
+      /* Compute the optimal Huffman encoding */
+      gen_huff_coding(cinfo, *htblptr, ac_count_ptrs[tbl]);
+      /* Release the count table */
+      (*cinfo->emethods->free_small) ((void *) ac_count_ptrs[tbl]);
+    }
+  }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+/*
+ * The method selection routine for Huffman entropy encoding.
+ */
+
+GLOBAL void
+jselchuffman (compress_info_ptr cinfo)
+{
+  if (! cinfo->arith_code) {
+    cinfo->methods->entropy_encoder_init = huff_init;
+    cinfo->methods->entropy_encode = huff_encode;
+    cinfo->methods->entropy_encoder_term = huff_term;
+#ifdef ENTROPY_OPT_SUPPORTED
+    cinfo->methods->entropy_optimize = huff_optimize;
+#endif
+  }
+}
diff --git a/jcmain.c b/jcmain.c
new file mode 100644
index 0000000..f71d5ad
--- /dev/null
+++ b/jcmain.c
@@ -0,0 +1,272 @@
+/*
+ * jcmain.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a trivial test user interface for the JPEG compressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ *	cjpeg [options]  inputfile outputfile
+ *	cjpeg [options]  [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program.  Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes.  Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ */
+
+#include "jinclude.h"
+#ifdef __STDC__
+#include <stdlib.h>		/* to declare exit() */
+#endif
+
+#ifdef THINK_C
+#include <console.h>		/* command-line reader for Macintosh */
+#endif
+
+#ifdef DONT_USE_B_MODE		/* define mode parameters for fopen() */
+#define READ_BINARY	"r"
+#define WRITE_BINARY	"w"
+#else
+#define READ_BINARY	"rb"
+#define WRITE_BINARY	"wb"
+#endif
+
+
+/*
+ * If your system has getopt(3), you can use your library version by
+ * defining HAVE_GETOPT.  By default, we use the PD 'egetopt'.
+ */
+
+#ifdef HAVE_GETOPT
+extern int getopt PP((int argc, char **argv, char *optstring));
+extern char * optarg;
+extern int optind;
+#else
+#include "egetopt.c"
+#define getopt(argc,argv,opt)	egetopt(argc,argv,opt)
+#endif
+
+
+/*
+ * This routine determines what format the input file is,
+ * and selects the appropriate input-reading module.
+ *
+ * To determine which family of input formats the file belongs to,
+ * we look only at the first byte of the file, since C does not
+ * guarantee that more than one character can be pushed back with ungetc.
+ * This is sufficient for the currently envisioned set of input formats.
+ *
+ * If you need to look at more than one character to select an input module,
+ * you can either
+ *     1) assume you can fseek() the input file (may fail for piped input);
+ *     2) assume you can push back more than one character (works in
+ *        some C implementations, but unportable);
+ * or  3) don't put back the data, and modify the various input_init
+ *        methods to assume they start reading after the start of file.
+ */
+
+LOCAL void
+select_file_type (compress_info_ptr cinfo)
+{
+  int c;
+
+  if ((c = getc(cinfo->input_file)) == EOF)
+    ERREXIT(cinfo->emethods, "Empty input file");
+
+  switch (c) {
+#ifdef GIF_SUPPORTED
+  case 'G':
+    jselrgif(cinfo);
+    break;
+#endif
+#ifdef PPM_SUPPORTED
+  case 'P':
+    jselrppm(cinfo);
+    break;
+#endif
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported input file format");
+    break;
+  }
+
+  if (ungetc(c, cinfo->input_file) == EOF)
+    ERREXIT(cinfo->emethods, "ungetc failed");
+}
+
+
+/*
+ * This routine gets control after the input file header has been read.
+ * It must determine what output JPEG file format is to be written,
+ * and make any other compression parameter changes that are desirable.
+ */
+
+METHODDEF void
+c_ui_method_selection (compress_info_ptr cinfo)
+{
+  /* If the input is gray scale, generate a monochrome JPEG file. */
+  if (cinfo->in_color_space == CS_GRAYSCALE)
+    j_monochrome_default(cinfo);
+  /* For now, always select JFIF output format. */
+#ifdef JFIF_SUPPORTED
+  jselwjfif(cinfo);
+#else
+  You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
+#endif
+}
+
+
+LOCAL void
+usage (char * progname)
+/* complain about bad command line */
+{
+  fprintf(stderr, "usage: %s ", progname);
+  fprintf(stderr, "[-I] [-Q quality 0..100] [-a] [-o] [-d]");
+#ifdef TWO_FILE_COMMANDLINE
+  fprintf(stderr, " inputfile outputfile\n");
+#else
+  fprintf(stderr, " [inputfile]\n");
+#endif
+  exit(2);
+}
+
+
+/*
+ * The main program.
+ */
+
+GLOBAL void
+main (int argc, char **argv)
+{
+  struct compress_info_struct cinfo;
+  struct compress_methods_struct c_methods;
+  struct external_methods_struct e_methods;
+  int c;
+
+  /* On Mac, fetch a command line. */
+#ifdef THINK_C
+  argc = ccommand(&argv);
+#endif
+
+  /* Initialize the system-dependent method pointers. */
+  cinfo.methods = &c_methods;
+  cinfo.emethods = &e_methods;
+  jselerror(&e_methods);	/* error/trace message routines */
+  jselvirtmem(&e_methods);	/* memory allocation routines */
+  c_methods.c_ui_method_selection = c_ui_method_selection;
+
+  /* Set up default input and output file references. */
+  /* (These may be overridden below.) */
+  cinfo.input_file = stdin;
+  cinfo.output_file = stdout;
+
+  /* Set up default parameters. */
+  e_methods.trace_level = 0;
+  j_default_compression(&cinfo, 75); /* default quality level */
+
+  /* Scan parameters */
+  
+  while ((c = getopt(argc, argv, "IQ:aod")) != EOF)
+    switch (c) {
+    case 'I':			/* Create noninterleaved file. */
+#ifdef MULTISCAN_FILES_SUPPORTED
+      cinfo.interleave = FALSE;
+#else
+      fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
+	      argv[0]);
+      exit(2);
+#endif
+      break;
+    case 'Q':			/* Quality factor. */
+      { int val;
+	if (optarg == NULL)
+	  usage(argv[0]);
+	if (sscanf(optarg, "%d", &val) != 1)
+	  usage(argv[0]);
+	/* Note: for now, we leave force_baseline FALSE.
+	 * In a production user interface, probably should make it TRUE
+	 * unless overridden by a separate switch.
+	 */
+	j_set_quality(&cinfo, val, FALSE);
+      }
+      break;
+    case 'a':			/* Use arithmetic coding. */
+#ifdef ARITH_CODING_SUPPORTED
+      cinfo.arith_code = TRUE;
+#else
+      fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
+	      argv[0]);
+      exit(2);
+#endif
+      break;
+    case 'o':			/* Enable entropy parm optimization. */
+#ifdef ENTROPY_OPT_SUPPORTED
+      cinfo.optimize_coding = TRUE;
+#else
+      fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
+	      argv[0]);
+      exit(2);
+#endif
+      break;
+    case 'd':			/* Debugging. */
+      e_methods.trace_level++;
+      break;
+    case '?':
+    default:
+      usage(argv[0]);
+      break;
+    }
+
+  /* Select the input and output files */
+
+#ifdef TWO_FILE_COMMANDLINE
+
+  if (optind != argc-2) {
+    fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
+    usage(argv[0]);
+  }
+  if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
+    exit(2);
+  }
+  if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
+    exit(2);
+  }
+
+#else /* not TWO_FILE_COMMANDLINE -- use Unix style */
+
+  if (optind < argc-1) {
+    fprintf(stderr, "%s: only one input file\n", argv[0]);
+    usage(argv[0]);
+  }
+  if (optind < argc) {
+    if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
+      fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
+      exit(2);
+    }
+  }
+
+#endif /* TWO_FILE_COMMANDLINE */
+
+  /* Figure out the input file format, and set up to read it. */
+  select_file_type(&cinfo);
+
+  /* Do it to it! */
+  jpeg_compress(&cinfo);
+
+  /* Release memory. */
+  j_free_defaults(&cinfo);
+#ifdef MEM_STATS
+  if (e_methods.trace_level > 0)
+    j_mem_stats();
+#endif
+
+  /* All done. */
+  exit(0);
+}
diff --git a/jcmaster.c b/jcmaster.c
new file mode 100644
index 0000000..b15217a
--- /dev/null
+++ b/jcmaster.c
@@ -0,0 +1,127 @@
+/*
+ * jcmaster.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main control for the JPEG compressor.
+ * The system-dependent (user interface) code should call jpeg_compress()
+ * after doing appropriate setup of the compress_info_struct parameter.
+ */
+
+#include "jinclude.h"
+
+
+METHODDEF void
+c_per_scan_method_selection (compress_info_ptr cinfo)
+/* Central point for per-scan method selection */
+{
+  /* Edge expansion */
+  jselexpand(cinfo);
+  /* Subsampling of pixels */
+  jselsubsample(cinfo);
+  /* MCU extraction */
+  jselcmcu(cinfo);
+}
+
+
+LOCAL void
+c_initial_method_selection (compress_info_ptr cinfo)
+/* Central point for initial method selection */
+{
+  /* Input image reading method selection is already done. */
+  /* So is output file header formatting (both are done by user interface). */
+
+  /* Gamma and color space conversion */
+  jselccolor(cinfo);
+  /* Entropy encoding: either Huffman or arithmetic coding. */
+#ifdef ARITH_CODING_SUPPORTED
+  jselcarithmetic(cinfo);
+#else
+  cinfo->arith_code = FALSE;	/* force Huffman mode */
+#endif
+  jselchuffman(cinfo);
+  /* Pipeline control */
+  jselcpipeline(cinfo);
+  /* Overall control (that's me!) */
+  cinfo->methods->c_per_scan_method_selection = c_per_scan_method_selection;
+}
+
+
+LOCAL void
+initial_setup (compress_info_ptr cinfo)
+/* Do computations that are needed before initial method selection */
+{
+  short ci;
+  jpeg_component_info *compptr;
+
+  /* Compute maximum sampling factors; check factor validity */
+  cinfo->max_h_samp_factor = 1;
+  cinfo->max_v_samp_factor = 1;
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = &cinfo->comp_info[ci];
+    if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+	compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+      ERREXIT(cinfo->emethods, "Bogus sampling factors");
+    cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+				   compptr->h_samp_factor);
+    cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+				   compptr->v_samp_factor);
+
+  }
+
+  /* Compute logical subsampled dimensions of components */
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = &cinfo->comp_info[ci];
+    compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+				+ cinfo->max_h_samp_factor - 1)
+				/ cinfo->max_h_samp_factor;
+    compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+				 + cinfo->max_v_samp_factor - 1)
+				 / cinfo->max_v_samp_factor;
+  }
+}
+
+
+/*
+ * This is the main entry point to the JPEG compressor.
+ */
+
+
+GLOBAL void
+jpeg_compress (compress_info_ptr cinfo)
+{
+  /* Read the input file header: determine image size & component count.
+   * NOTE: the user interface must have initialized the input_init method
+   * pointer (eg, by calling jselrppm) before calling me.
+   * The other file reading methods (get_input_row etc.) were probably
+   * set at the same time, but could be set up by input_init itself,
+   * or by c_ui_method_selection.
+   */
+  (*cinfo->methods->input_init) (cinfo);
+
+  /* Give UI a chance to adjust compression parameters and select */
+  /* output file format based on results of input_init. */
+  (*cinfo->methods->c_ui_method_selection) (cinfo);
+
+  /* Now select methods for compression steps. */
+  initial_setup(cinfo);
+  c_initial_method_selection(cinfo);
+
+  /* Initialize the output file & other modules as needed */
+  /* (entropy_encoder is inited by pipeline controller) */
+
+  (*cinfo->methods->colorin_init) (cinfo);
+  (*cinfo->methods->write_file_header) (cinfo);
+
+  /* And let the pipeline controller do the rest. */
+  (*cinfo->methods->c_pipeline_controller) (cinfo);
+
+  /* Finish output file, release working storage, etc */
+  (*cinfo->methods->write_file_trailer) (cinfo);
+  (*cinfo->methods->colorin_term) (cinfo);
+  (*cinfo->methods->input_term) (cinfo);
+
+  /* My, that was easy, wasn't it? */
+}
diff --git a/jcmcu.c b/jcmcu.c
new file mode 100644
index 0000000..1400eab
--- /dev/null
+++ b/jcmcu.c
@@ -0,0 +1,212 @@
+/*
+ * jcmcu.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains MCU extraction routines and quantization scaling.
+ * These routines are invoked via the extract_MCUs and
+ * extract_init/term methods.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * If this file is compiled with -DDCT_ERR_STATS, it will reverse-DCT each
+ * block and sum the total errors across the whole picture.  This provides
+ * a convenient method of using real picture data to test the roundoff error
+ * of a DCT algorithm.  DCT_ERR_STATS should *not* be defined for a production
+ * compression program, since compression is much slower with it defined.
+ * Also note that jrevdct.o must be linked into the compressor when this
+ * switch is defined.
+ */
+
+#ifdef DCT_ERR_STATS
+static int dcterrorsum;		/* these hold the error statistics */
+static int dcterrormax;
+static int dctcoefcount;	/* This will probably overflow on a 16-bit-int machine */
+#endif
+
+
+/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
+
+static const short ZAG[DCTSIZE2] = {
+  0,  1,  8, 16,  9,  2,  3, 10,
+ 17, 24, 32, 25, 18, 11,  4,  5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13,  6,  7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+
+LOCAL void
+extract_block (JSAMPARRAY input_data, int start_row, long start_col,
+	       JBLOCK output_data, QUANT_TBL_PTR quanttbl)
+/* Extract one 8x8 block from the specified location in the sample array; */
+/* perform forward DCT, quantization scaling, and zigzag reordering on it. */
+{
+  /* This routine is heavily used, so it's worth coding it tightly. */
+  DCTBLOCK block;
+#ifdef DCT_ERR_STATS
+  DCTBLOCK svblock;		/* saves input data for comparison */
+#endif
+
+  { register JSAMPROW elemptr;
+    register DCTELEM *localblkptr = block;
+#if DCTSIZE != 8
+    register short elemc;
+#endif
+    register short elemr;
+
+    for (elemr = DCTSIZE; elemr > 0; elemr--) {
+      elemptr = input_data[start_row++] + start_col;
+#if DCTSIZE == 8		/* unroll the inner loop */
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      *localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+#else
+      for (elemc = DCTSIZE; elemc > 0; elemc--) {
+	*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+      }
+#endif
+    }
+  }
+
+#ifdef DCT_ERR_STATS
+  memcpy((void *) svblock, (void *) block, SIZEOF(DCTBLOCK));
+#endif
+
+  j_fwd_dct(block);
+
+  { register JCOEF temp;
+    register short i;
+
+    for (i = 0; i < DCTSIZE2; i++) {
+      temp = (JCOEF) block[ZAG[i]];
+      /* divide by *quanttbl, ensuring proper rounding */
+      if (temp < 0) {
+	temp = -temp;
+	temp += *quanttbl>>1;
+	temp /= *quanttbl;
+	temp = -temp;
+      } else {
+	temp += *quanttbl>>1;
+	temp /= *quanttbl;
+      }
+      *output_data++ = temp;
+      quanttbl++;
+    }
+  }
+
+#ifdef DCT_ERR_STATS
+  j_rev_dct(block);
+
+  { register int diff;
+    register short i;
+
+    for (i = 0; i < DCTSIZE2; i++) {
+      diff = block[i] - svblock[i];
+      if (diff < 0) diff = -diff;
+      dcterrorsum += diff;
+      if (dcterrormax < diff) dcterrormax = diff;
+    }
+    dctcoefcount += DCTSIZE2;
+  }
+#endif
+}
+
+
+/*
+ * Extract samples in MCU order, process & hand off to output_method.
+ * The input is always exactly N MCU rows worth of data.
+ */
+
+METHODDEF void
+extract_MCUs (compress_info_ptr cinfo,
+	      JSAMPIMAGE image_data,
+	      int num_mcu_rows,
+	      MCU_output_method_ptr output_method)
+{
+  JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
+  int mcurow;
+  long mcuindex;
+  short blkn, ci, xpos, ypos;
+  jpeg_component_info * compptr;
+  QUANT_TBL_PTR quant_ptr;
+
+  for (mcurow = 0; mcurow < num_mcu_rows; mcurow++) {
+    for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
+      /* Extract data from the image array, DCT it, and quantize it */
+      blkn = 0;
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+	compptr = cinfo->cur_comp_info[ci];
+	quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
+	for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
+	  for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
+	    extract_block(image_data[ci],
+			  (mcurow * compptr->MCU_height + ypos)*DCTSIZE,
+			  (mcuindex * compptr->MCU_width + xpos)*DCTSIZE,
+			  MCU_data[blkn], quant_ptr);
+	    blkn++;
+	  }
+	}
+      }
+      /* Send the MCU whereever the pipeline controller wants it to go */
+      (*output_method) (cinfo, MCU_data);
+    }
+  }
+}
+
+
+/*
+ * Initialize for processing a scan.
+ */
+
+METHODDEF void
+extract_init (compress_info_ptr cinfo)
+{
+  /* no work for now */
+#ifdef DCT_ERR_STATS
+  dcterrorsum = dcterrormax = dctcoefcount = 0;
+#endif
+}
+
+
+/*
+ * Clean up after a scan.
+ */
+
+METHODDEF void
+extract_term (compress_info_ptr cinfo)
+{
+  /* no work for now */
+#ifdef DCT_ERR_STATS
+  TRACEMS3(cinfo->emethods, 0, "DCT roundoff errors = %d/%d,  max = %d",
+	   dcterrorsum, dctcoefcount, dcterrormax);
+#endif
+}
+
+
+
+/*
+ * The method selection routine for MCU extraction.
+ */
+
+GLOBAL void
+jselcmcu (compress_info_ptr cinfo)
+{
+  /* just one implementation for now */
+  cinfo->methods->extract_init = extract_init;
+  cinfo->methods->extract_MCUs = extract_MCUs;
+  cinfo->methods->extract_term = extract_term;
+}
diff --git a/jconfig.h b/jconfig.h
new file mode 100644
index 0000000..3b22acb
--- /dev/null
+++ b/jconfig.h
@@ -0,0 +1,320 @@
+/*
+ * jconfig.h
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains preprocessor declarations that help customize
+ * the JPEG software for a particular application, machine, or compiler.
+ * Edit these declarations as needed (or add -D flags to the Makefile).
+ */
+
+
+/*
+ * These symbols indicate the properties of your machine or compiler.
+ * The conditional definitions given may do the right thing already,
+ * but you'd best look them over closely, especially if your compiler
+ * does not handle full ANSI C.  An ANSI-compliant C compiler should
+ * provide all the necessary features; __STDC__ is supposed to be
+ * predefined by such compilers.
+ */
+
+/* Does your compiler support function prototypes? */
+/* (If not, you also need to use ansi2knr, see README) */
+
+#ifdef __STDC__			/* ANSI C compilers always have prototypes */
+#define PROTO
+#else
+#ifdef __cplusplus		/* So do C++ compilers */
+#define PROTO
+#endif
+#endif
+
+/* Does your compiler support the declaration "unsigned char" ? */
+/* How about "unsigned short" ? */
+
+#ifdef __STDC__			/* ANSI C compilers must support both */
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+#endif
+
+/* Define this if an ordinary "char" type is unsigned.
+ * If you're not sure, leaving it undefined will work at some cost in speed.
+ * If you defined HAVE_UNSIGNED_CHAR then it doesn't matter very much.
+ */
+
+/* #define CHAR_IS_UNSIGNED */
+
+/* Define this if your compiler implements ">>" on signed values as a logical
+ * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
+ * which is the normal and rational definition.
+ * The DCT and IDCT routines will compute wrong values if you get this wrong!
+ */
+
+/* #define RIGHT_SHIFT_IS_UNSIGNED */
+
+/* Define "void" as "char" if your compiler doesn't know about type void.
+ * NOTE: be sure to define void such that "void *" represents the most general
+ * pointer type, e.g., that returned by malloc().
+ */
+
+/* #define void char */
+
+/* Define const as empty if your compiler doesn't know the "const" keyword. */
+/* (Even if it does, defining const as empty won't break anything.) */
+
+#ifndef __STDC__		/* ANSI C and C++ compilers should know it. */
+#ifndef __cplusplus
+#define const
+#endif
+#endif
+
+/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
+ * unless you are using a large-data memory model or 80386 flat-memory mode.
+ * On less brain-damaged CPUs this symbol must not be defined.
+ * (Defining this symbol causes large data structures to be referenced through
+ * "far" pointers and to be allocated with a special version of malloc.)
+ */
+
+#ifdef MSDOS			/* Microsoft C and compatibles */
+#define NEED_FAR_POINTERS
+#else
+#ifdef __TURBOC__		/* Turbo C doesn't define MSDOS */
+#define NEED_FAR_POINTERS
+#endif
+#endif
+
+
+/* The next couple of symbols only affect the system-dependent user interface
+ * modules (jcmain.c, jdmain.c).  You can ignore these if you are supplying
+ * your own user interface code.
+ */
+
+/* Define this if you want to name both input and output files on the command
+ * line, rather than using stdout and optionally stdin.  You MUST do this if
+ * your system can't cope with binary I/O to stdin/stdout.  See comments at
+ * head of jcmain.c or jdmain.c.
+ */
+
+#ifdef MSDOS			/* two-file style is needed for PCs */
+#define TWO_FILE_COMMANDLINE
+#else
+#ifdef __TURBOC__		/* Turbo C doesn't define MSDOS */
+#define TWO_FILE_COMMANDLINE
+#endif
+#endif
+#ifdef THINK_C			/* needed for Macintosh too */
+#define TWO_FILE_COMMANDLINE
+#endif
+
+/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
+ * This is necessary on systems that distinguish text files from binary files,
+ * and is harmless on most systems that don't.  If you have one of the rare
+ * systems that complains about the "b" spec, define this symbol.
+ */
+
+/* #define DONT_USE_B_MODE */
+
+
+/* If you're getting bored, that's the end of the symbols you HAVE to
+ * worry about.  Go fix the makefile and compile.
+ */
+
+
+/* If your compiler supports inline functions, define INLINE as
+ * the inline keyword; otherwise define it as empty.
+ */
+
+#ifdef __GNUC__			/* GNU C has inline... */
+#define INLINE inline
+#else				/* ...but I don't think anyone else does. */
+#define INLINE
+#endif
+
+/* On a few systems, type boolean and/or macros FALSE, TRUE may appear
+ * in standard header files.  Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * In that case you need only comment out these definitions.
+ */
+
+typedef int boolean;
+#define FALSE	0		/* values of boolean */
+#define TRUE	1
+
+/* This defines the size of the I/O buffers for entropy compression
+ * and decompression; you could reduce it if memory is tight.
+ */
+
+#define JPEG_BUF_SIZE	4096 /* bytes */
+
+
+
+/* These symbols determine the JPEG functionality supported. */
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * program file.  Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Arithmetic coding is unsupported for legal reasons.  Complaints to IBM. */
+#undef  ARITH_CODING_SUPPORTED	/* Arithmetic coding back end? */
+#define MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define ENTROPY_OPT_SUPPORTED	/* Optimization of entropy coding parms? */
+#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */
+#define QUANT_1PASS_SUPPORTED	/* 1-pass color quantization? */
+#undef  QUANT_2PASS_SUPPORTED	/* 2-pass color quantization? (not yet impl.) */
+/* these defines indicate which JPEG file formats are allowed */
+#define JFIF_SUPPORTED		/* JFIF or "raw JPEG" files */
+#undef  JTIFF_SUPPORTED		/* JPEG-in-TIFF (not yet implemented) */
+/* these defines indicate which image (non-JPEG) file formats are allowed */
+#define PPM_SUPPORTED		/* PPM/PGM image file format */
+#define GIF_SUPPORTED		/* GIF image file format */
+#undef  TIFF_SUPPORTED		/* TIFF image file format (not yet impl.) */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Define exactly one of these three symbols to indicate whether you want
+ * 8-bit, 12-bit, or 16-bit sample (pixel component) values.  8-bit is the
+ * default and is nearly always the right thing to use.  You can use 12-bit if
+ * you need to support image formats with more than 8 bits of resolution in a
+ * color value.  16-bit should only be used for the lossless JPEG mode (not
+ * currently supported).  Note that 12- and 16-bit values take up twice as
+ * much memory as 8-bit!
+ */
+
+#define EIGHT_BIT_SAMPLES
+#undef  TWELVE_BIT_SAMPLES
+#undef  SIXTEEN_BIT_SAMPLES
+
+
+
+/*
+ * The remaining definitions don't need to be hand-edited in most cases.
+ * You may need to change these if you have a machine with unusual data
+ * types; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits.  We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* First define the representation of a single pixel element value. */
+
+#ifdef EIGHT_BIT_SAMPLES
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ * If you have only signed chars, and you are more worried about speed than
+ * memory usage, it might be a win to make JSAMPLE be short.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value)  (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+
+typedef char JSAMPLE;
+#define GETJSAMPLE(value)  (value)
+
+#else /* not CHAR_IS_UNSIGNED */
+
+typedef char JSAMPLE;
+#define GETJSAMPLE(value)  ((value) & 0xFF)
+
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE	255
+#define CENTERJSAMPLE	128
+
+#endif /* EIGHT_BIT_SAMPLES */
+
+
+#ifdef TWELVE_BIT_SAMPLES
+/* JSAMPLE should be the smallest type that will hold the values 0..4095. */
+/* On nearly all machines "short" will do nicely. */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value)  (value)
+
+#define MAXJSAMPLE	4095
+#define CENTERJSAMPLE	2048
+
+#endif /* TWELVE_BIT_SAMPLES */
+
+
+#ifdef SIXTEEN_BIT_SAMPLES
+/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+
+typedef unsigned short JSAMPLE;
+#define GETJSAMPLE(value)  (value)
+
+#else /* not HAVE_UNSIGNED_SHORT */
+
+/* If int is 32 bits this'll be horrendously inefficient storage-wise.
+ * But since we don't actually support 16-bit samples (ie lossless coding) yet,
+ * I'm not going to worry about making a smarter definition ...
+ */
+typedef unsigned int JSAMPLE;
+#define GETJSAMPLE(value)  (value)
+
+#endif /* HAVE_UNSIGNED_SHORT */
+
+#define MAXJSAMPLE	65535
+#define CENTERJSAMPLE	32768
+
+#endif /* SIXTEEN_BIT_SAMPLES */
+
+
+/* Here we define the representation of a DCT frequency coefficient.
+ * This should be a signed 16-bit value; "short" is usually right.
+ * It's important that this be exactly 16 bits, no more and no less;
+ * more will cost you a BIG hit of memory, less will give wrong answers.
+ */
+
+typedef short JCOEF;
+
+
+/* The remaining typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE.  (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+typedef short INT16;
+
+/* INT32 must hold signed 32-bit values; if your machine happens */
+/* to have 64-bit longs, you might want to change this. */
+
+typedef long INT32;
diff --git a/jcpipe.c b/jcpipe.c
new file mode 100644
index 0000000..f58e7db
--- /dev/null
+++ b/jcpipe.c
@@ -0,0 +1,715 @@
+/*
+ * jcpipe.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression pipeline controllers.
+ * These routines are invoked via the c_pipeline_controller method.
+ *
+ * There are four basic pipeline controllers, one for each combination of:
+ *	single-scan JPEG file (single component or fully interleaved)
+ *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
+ *
+ *	optimization of entropy encoding parameters
+ *  vs. usage of default encoding parameters.
+ *
+ * Note that these conditions determine the needs for "big" arrays:
+ * multiple scans imply a big array for splitting the color components;
+ * entropy encoding optimization needs a big array for the MCU data.
+ *
+ * All but the simplest controller (single-scan, no optimization) can be
+ * compiled out through configuration options, if you need to make a minimal
+ * implementation.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * About the data structures:
+ *
+ * The processing chunk size for subsampling is referred to in this file as
+ * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
+ * any component after subsampling, or Vmax (max_v_samp_factor) unsubsampled
+ * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
+ * groups of each component in the scan.  In a noninterleaved scan an MCU row
+ * is one row of blocks, which might not be an integral number of row groups;
+ * for convenience we use a buffer of the same size as in interleaved scans,
+ * and process Vk MCU rows in each burst of subsampling.
+ * To provide context for the subsampling step, we have to retain the last
+ * two row groups of the previous MCU row while reading in the next MCU row
+ * (or set of Vk MCU rows).  To do this without copying data about, we create
+ * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
+ * are allocated, but we create two different sets of pointers to this array.
+ * The second set swaps the last two pairs of row groups.  By working
+ * alternately with the two sets of pointers, we can access the data in the
+ * desired order.
+ */
+
+
+
+/*
+ * Utility routines: common code for pipeline controllers
+ */
+
+LOCAL void
+interleaved_scan_setup (compress_info_ptr cinfo)
+/* Compute all derived info for an interleaved (multi-component) scan */
+/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
+{
+  short ci, mcublks;
+  jpeg_component_info *compptr;
+
+  if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
+
+  cinfo->MCUs_per_row = (cinfo->image_width
+			 + cinfo->max_h_samp_factor*DCTSIZE - 1)
+			/ (cinfo->max_h_samp_factor*DCTSIZE);
+
+  cinfo->MCU_rows_in_scan = (cinfo->image_height
+			     + cinfo->max_v_samp_factor*DCTSIZE - 1)
+			    / (cinfo->max_v_samp_factor*DCTSIZE);
+  
+  cinfo->blocks_in_MCU = 0;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* for interleaved scan, sampling factors give # of blocks per component */
+    compptr->MCU_width = compptr->h_samp_factor;
+    compptr->MCU_height = compptr->v_samp_factor;
+    compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+    /* compute physical dimensions of component */
+    compptr->subsampled_width = jround_up(compptr->true_comp_width,
+					  (long) (compptr->MCU_width*DCTSIZE));
+    compptr->subsampled_height = jround_up(compptr->true_comp_height,
+					   (long) (compptr->MCU_height*DCTSIZE));
+    /* Sanity check */
+    if (compptr->subsampled_width !=
+	(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
+      ERREXIT(cinfo->emethods, "I'm confused about the image width");
+    /* Prepare array describing MCU composition */
+    mcublks = compptr->MCU_blocks;
+    if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
+      ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
+    while (mcublks-- > 0) {
+      cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+    }
+  }
+
+  (*cinfo->methods->c_per_scan_method_selection) (cinfo);
+}
+
+
+LOCAL void
+noninterleaved_scan_setup (compress_info_ptr cinfo)
+/* Compute all derived info for a noninterleaved (single-component) scan */
+/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
+{
+  jpeg_component_info *compptr = cinfo->cur_comp_info[0];
+
+  /* for noninterleaved scan, always one block per MCU */
+  compptr->MCU_width = 1;
+  compptr->MCU_height = 1;
+  compptr->MCU_blocks = 1;
+  /* compute physical dimensions of component */
+  compptr->subsampled_width = jround_up(compptr->true_comp_width,
+					(long) DCTSIZE);
+  compptr->subsampled_height = jround_up(compptr->true_comp_height,
+					 (long) DCTSIZE);
+
+  cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
+  cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
+
+  /* Prepare array describing MCU composition */
+  cinfo->blocks_in_MCU = 1;
+  cinfo->MCU_membership[0] = 0;
+
+  (*cinfo->methods->c_per_scan_method_selection) (cinfo);
+}
+
+
+
+LOCAL void
+alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
+		       long fullsize_width)
+/* Create a pre-subsampling data buffer having the desired structure */
+/* (see comments at head of file) */
+{
+  short ci, vs, i;
+
+  vs = cinfo->max_v_samp_factor; /* row group height */
+
+  /* Get top-level space for array pointers */
+  fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+  fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    /* Allocate the real storage */
+    fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
+				(fullsize_width,
+				(long) (vs * (DCTSIZE+2)));
+    /* Create space for the scrambled-order pointers */
+    fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
+				(vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
+    /* Duplicate the first DCTSIZE-2 row groups */
+    for (i = 0; i < vs * (DCTSIZE-2); i++) {
+      fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
+    }
+    /* Copy the last four row groups in swapped order */
+    for (i = 0; i < vs * 2; i++) {
+      fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
+      fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
+    }
+  }
+}
+
+
+LOCAL void
+free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
+/* Release a sampling buffer created by alloc_sampling_buffer */
+{
+  short ci, vs;
+
+  vs = cinfo->max_v_samp_factor; /* row group height */
+
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    /* Free the real storage */
+    (*cinfo->emethods->free_small_sarray)
+		(fullsize_data[0][ci], (long) (vs * (DCTSIZE+2)));
+    /* Free the scrambled-order pointers */
+    (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
+  }
+
+  /* Free the top-level space */
+  (*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
+  (*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
+}
+
+
+LOCAL void
+subsample (compress_info_ptr cinfo,
+	   JSAMPIMAGE fullsize_data, JSAMPIMAGE subsampled_data,
+	   long fullsize_width,
+	   short above, short current, short below, short out)
+/* Do subsampling of a single row group (of each component). */
+/* above, current, below are indexes of row groups in fullsize_data;      */
+/* out is the index of the target row group in subsampled_data.           */
+/* Special case: above, below can be -1 to indicate top, bottom of image. */
+{
+  jpeg_component_info *compptr;
+  JSAMPARRAY above_ptr, below_ptr;
+  JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
+  short ci, vs, i;
+
+  vs = cinfo->max_v_samp_factor; /* row group height */
+
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = & cinfo->comp_info[ci];
+
+    if (above >= 0)
+      above_ptr = fullsize_data[ci] + above * vs;
+    else {
+      /* Top of image: make a dummy above-context with copies of 1st row */
+      /* We assume current=0 in this case */
+      for (i = 0; i < vs; i++)
+	dummy[i] = fullsize_data[ci][0];
+      above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
+    }
+
+    if (below >= 0)
+      below_ptr = fullsize_data[ci] + below * vs;
+    else {
+      /* Bot of image: make a dummy below-context with copies of last row */
+      for (i = 0; i < vs; i++)
+	dummy[i] = fullsize_data[ci][(current+1)*vs-1];
+      below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
+    }
+
+    (*cinfo->methods->subsample[ci])
+		(cinfo, (int) ci,
+		 fullsize_width, (int) vs,
+		 compptr->subsampled_width, (int) compptr->v_samp_factor,
+		 above_ptr,
+		 fullsize_data[ci] + current * vs,
+		 below_ptr,
+		 subsampled_data[ci] + out * compptr->v_samp_factor);
+  }
+}
+
+
+/* These vars are initialized by the pipeline controller for use by
+ * MCU_output_catcher.
+ * To avoid a lot of row-pointer overhead, we cram as many MCUs into each
+ * row of whole_scan_MCUs as we can get without exceeding 64KB per row.
+ */
+
+#define MAX_WHOLE_ROW_BLOCKS	(65500 / SIZEOF(JBLOCK)) /* max blocks/row */
+
+static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
+static int MCUs_in_big_row;	/* # of MCUs in each row of whole_scan_MCUs */
+static long next_whole_row;	/* next row to access in whole_scan_MCUs */
+static int next_MCU_index;	/* next MCU in current row */
+
+
+METHODDEF void
+MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
+/* Output method for siphoning off extract_MCUs output into a big array */
+{
+  static JBLOCKARRAY rowptr;
+
+  if (next_MCU_index >= MCUs_in_big_row) {
+    rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
+						    next_whole_row, TRUE);
+    next_whole_row++;
+    next_MCU_index = 0;
+  }
+
+  /*
+   * note that on 80x86, the cast applied to MCU_data implies
+   * near to far pointer conversion.
+   */
+  jcopy_block_row((JBLOCKROW) MCU_data,
+		  rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
+		  (long) cinfo->blocks_in_MCU);
+  next_MCU_index++;
+}
+
+
+METHODDEF void
+dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
+/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
+/* The method may be either the entropy encoder or some routine supplied */
+/* by the entropy optimizer. */
+{
+  /* On an 80x86 machine, the entropy encoder expects the passed data block
+   * to be in NEAR memory (for performance reasons), so we have to copy it
+   * back from the big array to a local array.  On less brain-damaged CPUs
+   * we needn't do that.
+   */
+#ifdef NEED_FAR_POINTERS
+  JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
+#endif
+  long mcurow, mcuindex, next_row;
+  int next_index;
+  JBLOCKARRAY rowptr = NULL;	/* init only to suppress compiler complaint */
+
+  next_row = 0;
+  next_index = MCUs_in_big_row;
+
+  for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
+    for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
+      if (next_index >= MCUs_in_big_row) {
+	rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
+							next_row, FALSE);
+	next_row++;
+	next_index = 0;
+      }
+#ifdef NEED_FAR_POINTERS
+      jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
+		      (JBLOCKROW) MCU_data, /* note cast */
+		      (long) cinfo->blocks_in_MCU);
+      (*output_method) (cinfo, MCU_data);
+#else
+      (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
+#endif
+      next_index++;
+    }
+  }
+}
+
+
+
+/*
+ * Compression pipeline controller used for single-scan files
+ * with no optimization of entropy parameters.
+ */
+
+METHODDEF void
+single_ccontroller (compress_info_ptr cinfo)
+{
+  int rows_in_mem;		/* # of sample rows in full-size buffers */
+  long fullsize_width;		/* # of samples per row in full-size buffers */
+  long cur_pixel_row;		/* counts # of pixel rows processed */
+  long mcu_rows_output;		/* # of MCU rows actually emitted */
+  int mcu_rows_per_loop;	/* # of MCU rows processed per outer loop */
+  /* Work buffer for pre-subsampling data (see comments at head of file) */
+  JSAMPIMAGE fullsize_data[2];
+  /* Work buffer for subsampled data */
+  JSAMPIMAGE subsampled_data;
+  int rows_this_time;
+  short ci, whichss, i;
+
+  /* Prepare for single scan containing all components */
+  if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
+  cinfo->comps_in_scan = cinfo->num_components;
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+  }
+  if (cinfo->comps_in_scan == 1) {
+    noninterleaved_scan_setup(cinfo);
+    /* Vk block rows constitute the same number of MCU rows */
+    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
+  } else {
+    interleaved_scan_setup(cinfo);
+    /* in an interleaved scan, one MCU row contains Vk block rows */
+    mcu_rows_per_loop = 1;
+  }
+
+  /* Compute dimensions of full-size pixel buffers */
+  /* Note these are the same whether interleaved or not. */
+  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
+  fullsize_width = jround_up(cinfo->image_width,
+			     (long) (cinfo->max_h_samp_factor * DCTSIZE));
+
+  /* Allocate working memory: */
+  /* fullsize_data is sample data before subsampling */
+  alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
+  /* subsampled_data is sample data after subsampling */
+  subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
+			(cinfo->comp_info[ci].subsampled_width,
+			 (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
+  }
+
+  /* Tell the memory manager to instantiate big arrays.
+   * We don't need any big arrays in this controller,
+   * but some other module (like the input file reader) may need one.
+   */
+  (*cinfo->emethods->alloc_big_arrays)
+	((long) 0,				/* no more small sarrays */
+	 (long) 0,				/* no more small barrays */
+	 (long) 0);				/* no more "medium" objects */
+
+  /* Initialize output file & do per-scan object init */
+
+  (*cinfo->methods->write_scan_header) (cinfo);
+  cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
+  (*cinfo->methods->entropy_encoder_init) (cinfo);
+  (*cinfo->methods->subsample_init) (cinfo);
+  (*cinfo->methods->extract_init) (cinfo);
+
+  /* Loop over input image: rows_in_mem pixel rows are processed per loop */
+
+  mcu_rows_output = 0;
+  whichss = 1;			/* arrange to start with fullsize_data[0] */
+
+  for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
+       cur_pixel_row += rows_in_mem) {
+    whichss ^= 1;		/* switch to other fullsize_data buffer */
+    
+    /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
+    /* Then we have exactly DCTSIZE row groups for subsampling. */   
+    rows_this_time = MIN(rows_in_mem, cinfo->image_height - cur_pixel_row);
+ 
+    (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
+					fullsize_data[whichss]);
+    (*cinfo->methods->edge_expand) (cinfo,
+				    cinfo->image_width, rows_this_time,
+				    fullsize_width, rows_in_mem,
+				    fullsize_data[whichss]);
+    
+    /* Subsample the data (all components) */
+    /* First time through is a special case */
+    
+    if (cur_pixel_row) {
+      /* Subsample last row group of previous set */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
+		(short) (DCTSIZE-1));
+      /* and dump the previous set's subsampled data */
+      (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
+				       mcu_rows_per_loop,
+				       cinfo->methods->entropy_encode);
+      mcu_rows_output += mcu_rows_per_loop;
+      /* Subsample first row group of this set */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (DCTSIZE+1), (short) 0, (short) 1,
+		(short) 0);
+    } else {
+      /* Subsample first row group with dummy above-context */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (-1), (short) 0, (short) 1,
+		(short) 0);
+    }
+    /* Subsample second through next-to-last row groups of this set */
+    for (i = 1; i <= DCTSIZE-2; i++) {
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (i-1), (short) i, (short) (i+1),
+		(short) i);
+    }
+  } /* end of outer loop */
+  
+  /* Subsample the last row group with dummy below-context */
+  /* Note whichss points to last buffer side used */
+  subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+	    (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
+	    (short) (DCTSIZE-1));
+  /* Dump the remaining data (may be less than full height if uninterleaved) */
+  (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
+		(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
+		cinfo->methods->entropy_encode);
+
+  /* Finish output file */
+  (*cinfo->methods->extract_term) (cinfo);
+  (*cinfo->methods->subsample_term) (cinfo);
+  (*cinfo->methods->entropy_encoder_term) (cinfo);
+  (*cinfo->methods->write_scan_trailer) (cinfo);
+
+  /* Release working memory */
+  free_sampling_buffer(cinfo, fullsize_data);
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    (*cinfo->emethods->free_small_sarray)
+		(subsampled_data[ci],
+		 (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
+  }
+  (*cinfo->emethods->free_small) ((void *) subsampled_data);
+}
+
+
+/*
+ * Compression pipeline controller used for single-scan files
+ * with optimization of entropy parameters.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+METHODDEF void
+single_eopt_ccontroller (compress_info_ptr cinfo)
+{
+  int rows_in_mem;		/* # of sample rows in full-size buffers */
+  long fullsize_width;		/* # of samples per row in full-size buffers */
+  long cur_pixel_row;		/* counts # of pixel rows processed */
+  long mcu_rows_output;		/* # of MCU rows actually emitted */
+  int mcu_rows_per_loop;	/* # of MCU rows processed per outer loop */
+  /* Work buffer for pre-subsampling data (see comments at head of file) */
+  JSAMPIMAGE fullsize_data[2];
+  /* Work buffer for subsampled data */
+  JSAMPIMAGE subsampled_data;
+  int rows_this_time;
+  int blocks_in_big_row;
+  short ci, whichss, i;
+
+  /* Prepare for single scan containing all components */
+  if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
+  cinfo->comps_in_scan = cinfo->num_components;
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+  }
+  if (cinfo->comps_in_scan == 1) {
+    noninterleaved_scan_setup(cinfo);
+    /* Vk block rows constitute the same number of MCU rows */
+    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
+  } else {
+    interleaved_scan_setup(cinfo);
+    /* in an interleaved scan, one MCU row contains Vk block rows */
+    mcu_rows_per_loop = 1;
+  }
+
+  /* Compute dimensions of full-size pixel buffers */
+  /* Note these are the same whether interleaved or not. */
+  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
+  fullsize_width = jround_up(cinfo->image_width,
+			     (long) (cinfo->max_h_samp_factor * DCTSIZE));
+
+  /* Allocate working memory: */
+  /* fullsize_data is sample data before subsampling */
+  alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
+  /* subsampled_data is sample data after subsampling */
+  subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
+			(cinfo->comp_info[ci].subsampled_width,
+			 (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
+  }
+
+  /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
+  MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
+  blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
+
+  /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
+  whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
+		((long) blocks_in_big_row,
+		 (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
+			 + MCUs_in_big_row-1) / MCUs_in_big_row,
+		 1L);		/* unit height is 1 row */
+
+  next_whole_row = 0;		/* init output ptr for MCU_output_catcher */
+  next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
+
+  /* Tell the memory manager to instantiate big arrays */
+  (*cinfo->emethods->alloc_big_arrays)
+	((long) 0,				/* no more small sarrays */
+	 (long) 0,				/* no more small barrays */
+	 (long) 0);				/* no more "medium" objects */
+
+  /* Do per-scan object init */
+
+  (*cinfo->methods->subsample_init) (cinfo);
+  (*cinfo->methods->extract_init) (cinfo);
+
+  /* Loop over input image: rows_in_mem pixel rows are processed per loop */
+  /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
+
+  mcu_rows_output = 0;
+  whichss = 1;			/* arrange to start with fullsize_data[0] */
+
+  for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
+       cur_pixel_row += rows_in_mem) {
+    whichss ^= 1;		/* switch to other fullsize_data buffer */
+    
+    /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
+    /* Then we have exactly DCTSIZE row groups for subsampling. */   
+    rows_this_time = MIN(rows_in_mem, cinfo->image_height - cur_pixel_row);
+ 
+    (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
+					fullsize_data[whichss]);
+    (*cinfo->methods->edge_expand) (cinfo,
+				    cinfo->image_width, rows_this_time,
+				    fullsize_width, rows_in_mem,
+				    fullsize_data[whichss]);
+    
+    /* Subsample the data (all components) */
+    /* First time through is a special case */
+    
+    if (cur_pixel_row) {
+      /* Subsample last row group of previous set */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
+		(short) (DCTSIZE-1));
+      /* and dump the previous set's subsampled data */
+      (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
+				       mcu_rows_per_loop,
+				       MCU_output_catcher);
+      mcu_rows_output += mcu_rows_per_loop;
+      /* Subsample first row group of this set */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (DCTSIZE+1), (short) 0, (short) 1,
+		(short) 0);
+    } else {
+      /* Subsample first row group with dummy above-context */
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (-1), (short) 0, (short) 1,
+		(short) 0);
+    }
+    /* Subsample second through next-to-last row groups of this set */
+    for (i = 1; i <= DCTSIZE-2; i++) {
+      subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+		(short) (i-1), (short) i, (short) (i+1),
+		(short) i);
+    }
+  } /* end of outer loop */
+  
+  /* Subsample the last row group with dummy below-context */
+  /* Note whichss points to last buffer side used */
+  subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
+	    (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
+	    (short) (DCTSIZE-1));
+  /* Dump the remaining data (may be less than full height if uninterleaved) */
+  (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
+		(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
+		MCU_output_catcher);
+
+  /* Clean up after that stuff, then find the optimal entropy parameters */
+
+  (*cinfo->methods->extract_term) (cinfo);
+  (*cinfo->methods->subsample_term) (cinfo);
+
+  (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
+
+  /* Emit scan to output file */
+  /* Note: we can't do write_scan_header until entropy parameters are set! */
+
+  (*cinfo->methods->write_scan_header) (cinfo);
+  cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
+  (*cinfo->methods->entropy_encoder_init) (cinfo);
+  dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
+  (*cinfo->methods->entropy_encoder_term) (cinfo);
+  (*cinfo->methods->write_scan_trailer) (cinfo);
+
+  /* Release working memory */
+  free_sampling_buffer(cinfo, fullsize_data);
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    (*cinfo->emethods->free_small_sarray)
+		(subsampled_data[ci],
+		 (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
+  }
+  (*cinfo->emethods->free_small) ((void *) subsampled_data);
+  (*cinfo->emethods->free_big_barray) (whole_scan_MCUs);
+}
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+/*
+ * Compression pipeline controller used for multiple-scan files
+ * with no optimization of entropy parameters.
+ */
+
+#ifdef MULTISCAN_FILES_SUPPORTED
+
+METHODDEF void
+multi_ccontroller (compress_info_ptr cinfo)
+{
+  ERREXIT(cinfo->emethods, "Not implemented yet");
+}
+
+#endif /* MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Compression pipeline controller used for multiple-scan files
+ * with optimization of entropy parameters.
+ */
+
+#ifdef MULTISCAN_FILES_SUPPORTED
+#ifdef ENTROPY_OPT_SUPPORTED
+
+METHODDEF void
+multi_eopt_ccontroller (compress_info_ptr cinfo)
+{
+  ERREXIT(cinfo->emethods, "Not implemented yet");
+}
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+#endif /* MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * The method selection routine for compression pipeline controllers.
+ */
+
+GLOBAL void
+jselcpipeline (compress_info_ptr cinfo)
+{
+  if (cinfo->interleave || cinfo->num_components == 1) {
+    /* single scan needed */
+#ifdef ENTROPY_OPT_SUPPORTED
+    if (cinfo->optimize_coding)
+      cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
+    else
+#endif
+      cinfo->methods->c_pipeline_controller = single_ccontroller;
+  } else {
+    /* multiple scans needed */
+#ifdef MULTISCAN_FILES_SUPPORTED
+#ifdef ENTROPY_OPT_SUPPORTED
+    if (cinfo->optimize_coding)
+      cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
+    else
+#endif
+      cinfo->methods->c_pipeline_controller = multi_ccontroller;
+#else
+    ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
+#endif
+  }
+}
diff --git a/jcsample.c b/jcsample.c
new file mode 100644
index 0000000..d23e23a
--- /dev/null
+++ b/jcsample.c
@@ -0,0 +1,135 @@
+/*
+ * jcsample.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains subsampling routines.
+ * These routines are invoked via the subsample and
+ * subsample_init/term methods.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * Initialize for subsampling a scan.
+ */
+
+METHODDEF void
+subsample_init (compress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+/*
+ * Subsample pixel values of a single component.
+ * This version only handles integral sampling ratios.
+ */
+
+METHODDEF void
+subsample (compress_info_ptr cinfo, int which_component,
+	   long input_cols, int input_rows,
+	   long output_cols, int output_rows,
+	   JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
+	   JSAMPARRAY output_data)
+{
+  jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
+  int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
+  long outcol;
+  JSAMPROW inptr, outptr;
+  INT32 outvalue;
+
+  /* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
+  if (output_rows != compptr->v_samp_factor ||
+      input_rows != cinfo->max_v_samp_factor ||
+      (output_cols % compptr->h_samp_factor) != 0 ||
+      (input_cols % cinfo->max_h_samp_factor) != 0 ||
+      input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
+    ERREXIT(cinfo->emethods, "Bogus subsample parameters");
+
+  h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
+  v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
+  numpix = h_expand * v_expand;
+  numpix2 = numpix/2;
+
+  inrow = 0;
+  for (outrow = 0; outrow < output_rows; outrow++) {
+    outptr = output_data[outrow];
+    for (outcol = 0; outcol < output_cols; outcol++) {
+      outvalue = 0;
+      for (v = 0; v < v_expand; v++) {
+	inptr = input_data[inrow+v] + (outcol*h_expand);
+	for (h = 0; h < h_expand; h++) {
+	  outvalue += GETJSAMPLE(*inptr++);
+	}
+      }
+      *outptr++ = (outvalue + numpix2) / numpix;
+    }
+    inrow += v_expand;
+  }
+}
+
+
+/*
+ * Subsample pixel values of a single component.
+ * This version handles the special case of a full-size component.
+ */
+
+METHODDEF void
+fullsize_subsample (compress_info_ptr cinfo, int which_component,
+		    long input_cols, int input_rows,
+		    long output_cols, int output_rows,
+		    JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
+		    JSAMPARRAY output_data)
+{
+  if (input_cols != output_cols || input_rows != output_rows) /* DEBUG */
+    ERREXIT(cinfo->emethods, "Pipeline controller messed up");
+
+  jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
+}
+
+
+/*
+ * Clean up after a scan.
+ */
+
+METHODDEF void
+subsample_term (compress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+
+/*
+ * The method selection routine for subsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL void
+jselsubsample (compress_info_ptr cinfo)
+{
+  short ci;
+  jpeg_component_info * compptr;
+
+  if (cinfo->CCIR601_sampling)
+    ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
+	compptr->v_samp_factor == cinfo->max_v_samp_factor)
+      cinfo->methods->subsample[ci] = fullsize_subsample;
+    else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
+	     (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
+      cinfo->methods->subsample[ci] = subsample;
+    else
+      ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
+  }
+
+  cinfo->methods->subsample_init = subsample_init;
+  cinfo->methods->subsample_term = subsample_term;
+}
diff --git a/jdarith.c b/jdarith.c
new file mode 100644
index 0000000..0f19be8
--- /dev/null
+++ b/jdarith.c
@@ -0,0 +1,42 @@
+/*
+ * jdarith.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains arithmetic entropy decoding routines.
+ * These routines are invoked via the methods entropy_decode
+ * and entropy_decoder_init/term.
+ */
+
+#include "jinclude.h"
+
+#ifdef ARITH_CODING_SUPPORTED
+
+
+/*
+ * The arithmetic coding option of the JPEG standard specifies Q-coding,
+ * which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
+ * At this time it does not appear to be legal for the Independent JPEG
+ * Group to distribute software that implements arithmetic coding.
+ * We have therefore removed arithmetic coding support from the
+ * distributed source code.
+ *
+ * We're not happy about it either.
+ */
+
+
+/*
+ * The method selection routine for arithmetic entropy decoding.
+ */
+
+GLOBAL void
+jseldarithmetic (decompress_info_ptr cinfo)
+{
+  if (cinfo->arith_code) {
+    ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
+  }
+}
+
+#endif /* ARITH_CODING_SUPPORTED */
diff --git a/jdcolor.c b/jdcolor.c
new file mode 100644
index 0000000..a39ebff
--- /dev/null
+++ b/jdcolor.c
@@ -0,0 +1,194 @@
+/*
+ * jdcolor.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains output colorspace conversion routines.
+ * These routines are invoked via the methods color_convert
+ * and colorout_init/term.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * Initialize for colorspace conversion.
+ */
+
+METHODDEF void
+colorout_init (decompress_info_ptr cinfo)
+{
+  /* no work needed */
+}
+
+
+/*
+ * Convert some rows of samples to the output colorspace.
+ * This version handles YCbCr -> RGB conversion.
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ */
+
+METHODDEF void
+ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows,
+		 JSAMPIMAGE input_data, JSAMPIMAGE output_data)
+{
+  register INT32 y, u, v, x;
+  register JSAMPROW inptr0, inptr1, inptr2;
+  register JSAMPROW outptr0, outptr1, outptr2;
+  register long col;
+  register long width = cinfo->image_width;
+  register int row;
+  
+  for (row = 0; row < num_rows; row++) {
+    inptr0 = input_data[0][row];
+    inptr1 = input_data[1][row];
+    inptr2 = input_data[2][row];
+    outptr0 = output_data[0][row];
+    outptr1 = output_data[1][row];
+    outptr2 = output_data[2][row];
+    for (col = width; col > 0; col--) {
+      y = GETJSAMPLE(*inptr0++);
+      u = (int) GETJSAMPLE(*inptr1++) - CENTERJSAMPLE;
+      v = (int) GETJSAMPLE(*inptr2++) - CENTERJSAMPLE;
+      /* Note: if the inputs were computed directly from RGB values,
+       * range-limiting would be unnecessary here; but due to possible
+       * noise in the DCT/IDCT phase, we do need to apply range limits.
+       */
+      y *= 1024;	/* in case compiler can't spot common subexpression */
+      x = y          + 1436*v + 512; /* red */
+      if (x < 0) x = 0;
+      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
+      *outptr0++ = x >> 10;
+      x = y -  352*u -  731*v + 512; /* green */
+      if (x < 0) x = 0;
+      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
+      *outptr1++ = x >> 10;
+      x = y + 1815*u          + 512; /* blue */
+      if (x < 0) x = 0;
+      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
+      *outptr2++ = x >> 10;
+    }
+  }
+}
+
+
+/*
+ * Color conversion for no colorspace change: just copy the data.
+ */
+
+METHODDEF void
+null_convert (decompress_info_ptr cinfo, int num_rows,
+	      JSAMPIMAGE input_data, JSAMPIMAGE output_data)
+{
+  short ci;
+
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
+		      num_rows, cinfo->image_width);
+  }
+}
+
+
+/*
+ * Color conversion for grayscale: just copy the data.
+ * This also works for YCbCr/YIQ -> grayscale conversion, in which
+ * we just copy the Y (luminance) component and ignore chrominance.
+ */
+
+METHODDEF void
+grayscale_convert (decompress_info_ptr cinfo, int num_rows,
+		   JSAMPIMAGE input_data, JSAMPIMAGE output_data)
+{
+  jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
+		    num_rows, cinfo->image_width);
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+colorout_term (decompress_info_ptr cinfo)
+{
+  /* no work needed */
+}
+
+
+/*
+ * The method selection routine for output colorspace conversion.
+ */
+
+GLOBAL void
+jseldcolor (decompress_info_ptr cinfo)
+{
+  /* Make sure num_components agrees with jpeg_color_space */
+  switch (cinfo->jpeg_color_space) {
+  case CS_GRAYSCALE:
+    if (cinfo->num_components != 1)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    break;
+
+  case CS_RGB:
+  case CS_YIQ:
+  case CS_YCbCr:
+    if (cinfo->num_components != 3)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    break;
+
+  case CS_CMYK:
+    if (cinfo->num_components != 4)
+      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
+    break;
+
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
+    break;
+  }
+
+  /* Set color_out_comps and conversion method based on requested space */
+  switch (cinfo->out_color_space) {
+  case CS_GRAYSCALE:
+    cinfo->color_out_comps = 1;
+    if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
+	cinfo->jpeg_color_space == CS_YCbCr ||
+	cinfo->jpeg_color_space == CS_YIQ)
+      cinfo->methods->color_convert = grayscale_convert;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  case CS_RGB:
+    cinfo->color_out_comps = 3;
+    if (cinfo->jpeg_color_space == CS_YCbCr)
+      cinfo->methods->color_convert = ycc_rgb_convert;
+    else if (cinfo->jpeg_color_space == CS_RGB)
+      cinfo->methods->color_convert = null_convert;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  case CS_CMYK:
+    cinfo->color_out_comps = 4;
+    if (cinfo->jpeg_color_space == CS_CMYK)
+      cinfo->methods->color_convert = null_convert;
+    else
+      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
+    break;
+
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported output colorspace");
+    break;
+  }
+
+  if (cinfo->quantize_colors)
+    cinfo->final_out_comps = 1;	/* single colormapped output component */
+  else
+    cinfo->final_out_comps = cinfo->color_out_comps;
+
+  cinfo->methods->colorout_init = colorout_init;
+  cinfo->methods->colorout_term = colorout_term;
+}
diff --git a/jdhuff.c b/jdhuff.c
new file mode 100644
index 0000000..e9af688
--- /dev/null
+++ b/jdhuff.c
@@ -0,0 +1,318 @@
+/*
+ * jdhuff.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines.
+ * These routines are invoked via the methods entropy_decode
+ * and entropy_decoder_init/term.
+ */
+
+#include "jinclude.h"
+
+
+/* Static variables to avoid passing 'round extra parameters */
+
+static decompress_info_ptr dcinfo;
+
+static unsigned int get_buffer; /* current bit-extraction buffer */
+static int bits_left;		/* # of unused bits in it */
+
+
+LOCAL void
+fix_huff_tbl (HUFF_TBL * htbl)
+/* Compute derived values for a Huffman table */
+{
+  int p, i, l, lastp, si;
+  char huffsize[257];
+  UINT16 huffcode[257];
+  UINT16 code;
+  
+  /* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
+  /* Note that this is in code-length order. */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    for (i = 1; i <= htbl->bits[l]; i++)
+      huffsize[p++] = l;
+  }
+  huffsize[p] = 0;
+  lastp = p;
+  
+  /* Figure 7.3.5.4.2.2: generate the codes themselves */
+  /* Note that this is in code-length order. */
+  
+  code = 0;
+  si = huffsize[0];
+  p = 0;
+  while (huffsize[p]) {
+    while (huffsize[p] == si) {
+      huffcode[p++] = code;
+      code++;
+    }
+    code <<= 1;
+    si++;
+  }
+  
+  /* Figure 7.3.5.4.2.3: generate encoding tables */
+  /* These are code and size indexed by symbol value */
+
+  for (p = 0; p < lastp; p++) {
+    htbl->ehufco[htbl->huffval[p]] = huffcode[p];
+    htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
+  }
+  
+  /* Figure 13.4.2.3.1: generate decoding tables */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    if (htbl->bits[l]) {
+      htbl->valptr[l] = p;	/* huffval[] index of 1st sym of code len l */
+      htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
+      p += htbl->bits[l];
+      htbl->maxcode[l] = huffcode[p-1];	/* maximum code of length l */
+    } else {
+      htbl->maxcode[l] = -1;
+    }
+  }
+}
+
+
+/* Extract the next N bits from the input stream (N <= 8) */
+
+LOCAL int
+get_bits (int nbits)
+{
+  int result;
+  
+  while (nbits > bits_left) {
+    int c = JGETC(dcinfo);
+    
+    get_buffer = (get_buffer << 8) + c;
+    bits_left += 8;
+    /* If it's 0xFF, check and discard stuffed zero byte */
+    if (c == 0xff) {
+      c = JGETC(dcinfo);  /* Byte stuffing */
+      if (c != 0)
+	ERREXIT1(dcinfo->emethods,
+		 "Unexpected marker 0x%02x in compressed data", c);
+    }
+  }
+  
+  bits_left -= nbits;
+  result = (get_buffer >> bits_left) & ((1 << nbits) - 1);
+  return result;
+}
+
+/* Macro to make things go at some speed! */
+
+#define get_bit()	(bits_left ? \
+			 ((get_buffer >> (--bits_left)) & 1) : \
+			 get_bits(1))
+
+
+/* Figure 13.4.2.3.2: extract next coded symbol from input stream */
+  
+LOCAL int
+huff_DECODE (HUFF_TBL * htbl)
+{
+  int l, p;
+  INT32 code;
+  
+  code = get_bit();
+  l = 1;
+  while (code > htbl->maxcode[l]) {
+    code = (code << 1) + get_bit();
+    l++;
+  }
+  
+  p = htbl->valptr[l] + (code - htbl->mincode[l]);
+  
+  return htbl->huffval[p];
+}
+
+
+/* Figure 13.4.2.1.1: extend sign bit */
+
+#define huff_EXTEND(x, s)	((x) < (1 << ((s)-1)) ? \
+				 (x) + (-1 << (s)) + 1 : \
+				 (x))
+
+
+/* Decode a single block's worth of coefficients */
+/* Note that only the difference is returned for the DC coefficient */
+
+LOCAL void
+decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
+{
+  int s, k, r, n;
+
+  /* zero out the coefficient block */
+
+  MEMZERO((void *) block, SIZEOF(JBLOCK));
+  
+  /* Section 13.4.2.1: decode the DC coefficient difference */
+
+  s = huff_DECODE(dctbl);
+  r = get_bits(s);
+  block[0] = huff_EXTEND(r, s);
+  
+  /* Section 13.4.2.2: decode the AC coefficients */
+  
+  for (k = 1; k < DCTSIZE2; k++) {
+    r = huff_DECODE(actbl);
+    
+    s = r & 15;
+    n = r >> 4;
+    
+    if (s) {
+      k = k + n;
+      r = get_bits(s);
+      block[k] = huff_EXTEND(r, s);
+    } else {
+      if (n != 15)
+	break;
+      k += 15;
+    }
+  }
+}
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * This is invoked after reading the SOS marker.
+ */
+
+METHODDEF void
+huff_decoder_init (decompress_info_ptr cinfo)
+{
+  short ci;
+  jpeg_component_info * compptr;
+
+  /* Initialize static variables */
+  dcinfo = cinfo;
+  bits_left = 0;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* Make sure requested tables are present */
+    if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
+	cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
+      ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
+    /* Compute derived values for Huffman tables */
+    /* We may do this more than once for same table, but it's not a big deal */
+    fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
+    fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
+    /* Initialize DC predictions to 0 */
+    cinfo->last_dc_val[ci] = 0;
+  }
+
+  /* Initialize restart stuff */
+  cinfo->restarts_to_go = cinfo->restart_interval;
+  cinfo->next_restart_num = 0;
+}
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ */
+
+LOCAL void
+process_restart (decompress_info_ptr cinfo)
+{
+  int c, nbytes;
+  short ci;
+
+  /* Throw away any partial unread byte */
+  bits_left = 0;
+
+  /* Scan for next JPEG marker */
+  nbytes = 0;
+  do {
+    do {			/* skip any non-FF bytes */
+      nbytes++;
+      c = JGETC(cinfo);
+    } while (c != 0xFF);
+    do {			/* skip any duplicate FFs */
+      nbytes++;
+      c = JGETC(cinfo);
+    } while (c == 0xFF);
+  } while (c == 0);		/* repeat if it was a stuffed FF/00 */
+
+  if (c != (RST0 + cinfo->next_restart_num))
+    ERREXIT2(cinfo->emethods, "Found 0x%02x marker instead of RST%d",
+	     c, cinfo->next_restart_num);
+
+  if (nbytes != 2)
+    TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before RST%d",
+	     nbytes-2, cinfo->next_restart_num);
+  else
+    TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num);
+
+  /* Re-initialize DC predictions to 0 */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+    cinfo->last_dc_val[ci] = 0;
+
+  /* Update restart state */
+  cinfo->restarts_to_go = cinfo->restart_interval;
+  cinfo->next_restart_num++;
+  cinfo->next_restart_num &= 7;
+}
+
+
+/*
+ * Decode and return one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF void
+huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
+{
+  short blkn, ci;
+  jpeg_component_info * compptr;
+
+  /* Account for restart interval, process restart marker if needed */
+  if (cinfo->restart_interval) {
+    if (cinfo->restarts_to_go == 0)
+      process_restart(cinfo);
+    cinfo->restarts_to_go--;
+  }
+
+  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    decode_one_block(MCU_data[blkn],
+		     cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no],
+		     cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
+    /* Convert DC difference to actual value, update last_dc_val */
+    MCU_data[blkn][0] += cinfo->last_dc_val[ci];
+    cinfo->last_dc_val[ci] = MCU_data[blkn][0];
+  }
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF void
+huff_decoder_term (decompress_info_ptr cinfo)
+{
+  /* No work needed */
+}
+
+
+/*
+ * The method selection routine for Huffman entropy decoding.
+ */
+
+GLOBAL void
+jseldhuffman (decompress_info_ptr cinfo)
+{
+  if (! cinfo->arith_code) {
+    cinfo->methods->entropy_decoder_init = huff_decoder_init;
+    cinfo->methods->entropy_decode = huff_decode;
+    cinfo->methods->entropy_decoder_term = huff_decoder_term;
+  }
+}
diff --git a/jdmain.c b/jdmain.c
new file mode 100644
index 0000000..109d124
--- /dev/null
+++ b/jdmain.c
@@ -0,0 +1,289 @@
+/*
+ * jdmain.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a trivial test user interface for the JPEG decompressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ *	djpeg [options]  inputfile outputfile
+ *	djpeg [options]  [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program.  Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes.  Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ */
+
+#include "jinclude.h"
+#ifdef __STDC__
+#include <stdlib.h>		/* to declare exit() */
+#endif
+
+#ifdef THINK_C
+#include <console.h>		/* command-line reader for Macintosh */
+#endif
+
+#ifdef DONT_USE_B_MODE		/* define mode parameters for fopen() */
+#define READ_BINARY	"r"
+#define WRITE_BINARY	"w"
+#else
+#define READ_BINARY	"rb"
+#define WRITE_BINARY	"wb"
+#endif
+
+
+/*
+ * If your system has getopt(3), you can use your library version by
+ * defining HAVE_GETOPT.  By default, we use the PD 'egetopt'.
+ */
+
+#ifdef HAVE_GETOPT
+extern int getopt PP((int argc, char **argv, char *optstring));
+extern char * optarg;
+extern int optind;
+#else
+#include "egetopt.c"
+#define getopt(argc,argv,opt)	egetopt(argc,argv,opt)
+#endif
+
+
+typedef enum {			/* defines known output image formats */
+	FMT_PPM,		/* PPM/PGM (PBMPLUS formats) */
+	FMT_GIF,		/* GIF format */
+	FMT_TIFF		/* TIFF format */
+} IMAGE_FORMATS;
+
+static IMAGE_FORMATS requested_fmt;
+
+
+/*
+ * This routine gets control after the input file header has been read.
+ * It must determine what output file format is to be written,
+ * and make any other decompression parameter changes that are desirable.
+ */
+
+METHODDEF void
+d_ui_method_selection (decompress_info_ptr cinfo)
+{
+  /* if grayscale or CMYK input, force similar output; */
+  /* else leave the output colorspace as set by options. */
+  if (cinfo->jpeg_color_space == CS_GRAYSCALE)
+    cinfo->out_color_space = CS_GRAYSCALE;
+  else if (cinfo->jpeg_color_space == CS_CMYK)
+    cinfo->out_color_space = CS_CMYK;
+
+  /* select output file format */
+  /* Note: jselwxxx routine may make additional parameter changes,
+   * such as forcing color quantization if it's a colormapped format.
+   */
+  switch (requested_fmt) {
+#ifdef GIF_SUPPORTED
+  case FMT_GIF:
+    jselwgif(cinfo);
+    break;
+#endif
+#ifdef PPM_SUPPORTED
+  case FMT_PPM:
+    jselwppm(cinfo);
+    break;
+#endif
+  default:
+    ERREXIT(cinfo->emethods, "Unsupported output file format");
+    break;
+  }
+}
+
+
+/*
+ * Reload the input buffer after it's been emptied, and return the next byte.
+ * See the JGETC macro for calling conditions.
+ *
+ * This routine would need to be replaced if reading JPEG data from something
+ * other than a stdio stream.
+ */
+
+METHODDEF int
+read_jpeg_data (decompress_info_ptr cinfo)
+{
+  cinfo->bytes_in_buffer = fread(cinfo->input_buffer + MIN_UNGET,
+				 1, JPEG_BUF_SIZE,
+				 cinfo->input_file);
+  
+  cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
+  
+  if (cinfo->bytes_in_buffer <= 0)
+    ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
+
+  return JGETC(cinfo);
+}
+
+
+
+LOCAL void
+usage (char * progname)
+/* complain about bad command line */
+{
+  fprintf(stderr, "usage: %s ", progname);
+  fprintf(stderr, "[-b] [-q colors] [-2] [-d] [-g] [-G]");
+#ifdef TWO_FILE_COMMANDLINE
+  fprintf(stderr, " inputfile outputfile\n");
+#else
+  fprintf(stderr, " [inputfile]\n");
+#endif
+  exit(2);
+}
+
+
+/*
+ * The main program.
+ */
+
+GLOBAL void
+main (int argc, char **argv)
+{
+  struct decompress_info_struct cinfo;
+  struct decompress_methods_struct dc_methods;
+  struct external_methods_struct e_methods;
+  int c;
+
+  /* On Mac, fetch a command line. */
+#ifdef THINK_C
+  argc = ccommand(&argv);
+#endif
+
+  /* Initialize the system-dependent method pointers. */
+  cinfo.methods = &dc_methods;
+  cinfo.emethods = &e_methods;
+  jselerror(&e_methods);	/* error/trace message routines */
+  jselvirtmem(&e_methods);	/* memory allocation routines */
+  dc_methods.d_ui_method_selection = d_ui_method_selection;
+  dc_methods.read_jpeg_data = read_jpeg_data;
+
+  /* Allocate memory for input buffer. */
+  cinfo.input_buffer = (char *) (*cinfo.emethods->alloc_small)
+					((size_t) (JPEG_BUF_SIZE + MIN_UNGET));
+  cinfo.bytes_in_buffer = 0;	/* initialize buffer to empty */
+
+  /* Set up default input and output file references. */
+  /* (These may be overridden below.) */
+  cinfo.input_file = stdin;
+  cinfo.output_file = stdout;
+
+  /* Set up default parameters. */
+  e_methods.trace_level = 0;
+  cinfo.output_gamma = 1.0;
+  cinfo.quantize_colors = FALSE;
+  cinfo.two_pass_quantize = FALSE;
+  cinfo.use_dithering = FALSE;
+  cinfo.desired_number_of_colors = 256;
+  cinfo.do_block_smoothing = FALSE;
+  cinfo.do_pixel_smoothing = FALSE;
+  cinfo.out_color_space = CS_RGB;
+  cinfo.jpeg_color_space = CS_UNKNOWN;
+  /* setting any other value in jpeg_color_space overrides heuristics */
+  /* in jrdjfif.c ... */
+  /* You may wanta change the default output format; here's the place: */
+#ifdef PPM_SUPPORTED
+  requested_fmt = FMT_PPM;
+#else
+  requested_fmt = FMT_GIF;
+#endif
+
+  /* Scan parameters */
+  
+  while ((c = getopt(argc, argv, "bq:2DdgG")) != EOF)
+    switch (c) {
+    case 'b':			/* Enable cross-block smoothing. */
+      cinfo.do_block_smoothing = TRUE;
+      break;
+    case 'q':			/* Do color quantization. */
+      { int val;
+	if (optarg == NULL)
+	  usage(argv[0]);
+	if (sscanf(optarg, "%d", &val) != 1)
+	  usage(argv[0]);
+	cinfo.desired_number_of_colors = val;
+      }
+      cinfo.quantize_colors = TRUE;
+      break;
+    case '2':			/* Use two-pass quantization. */
+      cinfo.two_pass_quantize = TRUE;
+      break;
+    case 'D':			/* Use dithering in color quantization. */
+      cinfo.use_dithering = TRUE;
+      break;
+    case 'd':			/* Debugging. */
+      e_methods.trace_level++;
+      break;
+    case 'g':			/* Force grayscale output. */
+      cinfo.out_color_space = CS_GRAYSCALE;
+      break;
+    case 'G':			/* GIF output format. */
+      requested_fmt = FMT_GIF;
+      break;
+    case '?':
+    default:
+      usage(argv[0]);
+      break;
+    }
+
+  /* Select the input and output files */
+
+#ifdef TWO_FILE_COMMANDLINE
+
+  if (optind != argc-2) {
+    fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
+    usage(argv[0]);
+  }
+  if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
+    exit(2);
+  }
+  if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
+    exit(2);
+  }
+
+#else /* not TWO_FILE_COMMANDLINE -- use Unix style */
+
+  if (optind < argc-1) {
+    fprintf(stderr, "%s: only one input file\n", argv[0]);
+    usage(argv[0]);
+  }
+  if (optind < argc) {
+    if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
+      fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
+      exit(2);
+    }
+  }
+
+#endif /* TWO_FILE_COMMANDLINE */
+  
+  /* Set up to read a JFIF or baseline-JPEG file. */
+  /* A smarter UI would inspect the first few bytes of the input file */
+  /* to determine its type. */
+#ifdef JFIF_SUPPORTED
+  jselrjfif(&cinfo);
+#else
+  You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
+#endif
+
+  /* Do it to it! */
+  jpeg_decompress(&cinfo);
+
+  /* Release memory. */
+  (*cinfo.emethods->free_small) ((void *) cinfo.input_buffer);
+#ifdef MEM_STATS
+  if (e_methods.trace_level > 0)
+    j_mem_stats();
+#endif
+
+  /* All done. */
+  exit(0);
+}
diff --git a/jdmaster.c b/jdmaster.c
new file mode 100644
index 0000000..5693882
--- /dev/null
+++ b/jdmaster.c
@@ -0,0 +1,180 @@
+/*
+ * jdmaster.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main control for the JPEG decompressor.
+ * The system-dependent (user interface) code should call jpeg_decompress()
+ * after doing appropriate setup of the decompress_info_struct parameter.
+ */
+
+#include "jinclude.h"
+
+
+METHODDEF void
+d_per_scan_method_selection (decompress_info_ptr cinfo)
+/* Central point for per-scan method selection */
+{
+  /* MCU disassembly */
+  jseldmcu(cinfo);
+  /* Un-subsampling of pixels */
+  jselunsubsample(cinfo);
+}
+
+
+LOCAL void
+d_initial_method_selection (decompress_info_ptr cinfo)
+/* Central point for initial method selection (after reading file header) */
+{
+  /* JPEG file scanning method selection is already done. */
+  /* So is output file format selection (both are done by user interface). */
+
+  /* Entropy decoding: either Huffman or arithmetic coding. */
+#ifdef ARITH_CODING_SUPPORTED
+  jseldarithmetic(cinfo);
+#else
+  if (cinfo->arith_code) {
+    ERREXIT(cinfo->emethods, "Arithmetic coding not supported");
+  }
+#endif
+  jseldhuffman(cinfo);
+  /* Cross-block smoothing */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  jselbsmooth(cinfo);
+#else
+  cinfo->do_block_smoothing = FALSE;
+#endif
+  /* Gamma and color space conversion */
+  jseldcolor(cinfo);
+
+  /* Color quantization */
+#ifdef QUANT_1PASS_SUPPORTED
+#ifndef QUANT_2PASS_SUPPORTED
+  cinfo->two_pass_quantize = FALSE; /* only have 1-pass */
+#endif
+#else /* not QUANT_1PASS_SUPPORTED */
+#ifdef QUANT_2PASS_SUPPORTED
+  cinfo->two_pass_quantize = TRUE; /* only have 2-pass */
+#else /* not QUANT_2PASS_SUPPORTED */
+  if (cinfo->quantize_colors) {
+    ERREXIT(cinfo->emethods, "Color quantization was not compiled");
+  }
+#endif
+#endif
+
+#ifdef QUANT_1PASS_SUPPORTED
+  jsel1quantize(cinfo);
+#endif
+#ifdef QUANT_2PASS_SUPPORTED
+  jsel2quantize(cinfo);
+#endif
+
+  /* Pipeline control */
+  jseldpipeline(cinfo);
+  /* Overall control (that's me!) */
+  cinfo->methods->d_per_scan_method_selection = d_per_scan_method_selection;
+}
+
+
+LOCAL void
+initial_setup (decompress_info_ptr cinfo)
+/* Do computations that are needed before initial method selection */
+{
+  short ci;
+  jpeg_component_info *compptr;
+
+  /* Compute maximum sampling factors; check factor validity */
+  cinfo->max_h_samp_factor = 1;
+  cinfo->max_v_samp_factor = 1;
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = &cinfo->comp_info[ci];
+    if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+	compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+      ERREXIT(cinfo->emethods, "Bogus sampling factors");
+    cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+				   compptr->h_samp_factor);
+    cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+				   compptr->v_samp_factor);
+
+  }
+
+  /* Compute logical subsampled dimensions of components */
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = &cinfo->comp_info[ci];
+    compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+				+ cinfo->max_h_samp_factor - 1)
+				/ cinfo->max_h_samp_factor;
+    compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+				 + cinfo->max_v_samp_factor - 1)
+				 / cinfo->max_v_samp_factor;
+  }
+}
+
+
+/*
+ * This is the main entry point to the JPEG decompressor.
+ */
+
+
+GLOBAL void
+jpeg_decompress (decompress_info_ptr cinfo)
+{
+  short i;
+
+  /* Initialize pointers as needed to mark stuff unallocated. */
+  cinfo->comp_info = NULL;
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    cinfo->quant_tbl_ptrs[i] = NULL;
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    cinfo->dc_huff_tbl_ptrs[i] = NULL;
+    cinfo->ac_huff_tbl_ptrs[i] = NULL;
+  }
+
+  /* Read the JPEG file header markers; everything up through the first SOS
+   * marker is read now.  NOTE: the user interface must have initialized the
+   * read_file_header method pointer (eg, by calling jselrjfif or jselrtiff).
+   * The other file reading methods (read_scan_header etc.) were probably
+   * set at the same time, but could be set up by read_file_header itself.
+   */
+  (*cinfo->methods->read_file_header) (cinfo);
+  if (! ((*cinfo->methods->read_scan_header) (cinfo)))
+    ERREXIT(cinfo->emethods, "Empty JPEG file");
+
+  /* Give UI a chance to adjust decompression parameters and select */
+  /* output file format based on info from file header. */
+  (*cinfo->methods->d_ui_method_selection) (cinfo);
+
+  /* Now select methods for decompression steps. */
+  initial_setup(cinfo);
+  d_initial_method_selection(cinfo);
+
+  /* Initialize the output file & other modules as needed */
+  /* (color_quant and entropy_decoder are inited by pipeline controller) */
+
+  (*cinfo->methods->output_init) (cinfo);
+  (*cinfo->methods->colorout_init) (cinfo);
+
+  /* And let the pipeline controller do the rest. */
+  (*cinfo->methods->d_pipeline_controller) (cinfo);
+
+  /* Finish output file, release working storage, etc */
+  (*cinfo->methods->colorout_term) (cinfo);
+  (*cinfo->methods->output_term) (cinfo);
+  (*cinfo->methods->read_file_trailer) (cinfo);
+
+  /* Release allocated storage for tables */
+#define FREE(ptr)  if ((ptr) != NULL) \
+			(*cinfo->emethods->free_small) ((void *) ptr)
+
+  FREE(cinfo->comp_info);
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    FREE(cinfo->quant_tbl_ptrs[i]);
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    FREE(cinfo->dc_huff_tbl_ptrs[i]);
+    FREE(cinfo->ac_huff_tbl_ptrs[i]);
+  }
+
+  /* My, that was easy, wasn't it? */
+}
diff --git a/jdmcu.c b/jdmcu.c
new file mode 100644
index 0000000..0d99170
--- /dev/null
+++ b/jdmcu.c
@@ -0,0 +1,146 @@
+/*
+ * jdmcu.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains MCU disassembly routines and quantization descaling.
+ * These routines are invoked via the disassemble_MCU and
+ * disassemble_init/term methods.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * Quantization descaling and zigzag reordering
+ */
+
+
+/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
+
+static const short ZAG[DCTSIZE2] = {
+  0,  1,  8, 16,  9,  2,  3, 10,
+ 17, 24, 32, 25, 18, 11,  4,  5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13,  6,  7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+
+LOCAL void
+qdescale_zig (JBLOCK input, JBLOCKROW outputptr, QUANT_TBL_PTR quanttbl)
+{
+  short i;
+
+  for (i = 0; i < DCTSIZE2; i++) {
+    (*outputptr)[ZAG[i]] = (*input++) * (*quanttbl++);
+  }
+}
+
+
+
+/*
+ * Fetch one MCU row from entropy_decode, build coefficient array.
+ * This version is used for noninterleaved (single-component) scans.
+ */
+
+METHODDEF void
+disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
+				JBLOCKIMAGE image_data)
+{
+  JBLOCK MCU_data[1];
+  long mcuindex;
+  jpeg_component_info * compptr;
+  QUANT_TBL_PTR quant_ptr;
+
+  /* this is pretty easy since there is one component and one block per MCU */
+  compptr = cinfo->cur_comp_info[0];
+  quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
+  for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
+    /* Fetch the coefficient data */
+    (*cinfo->methods->entropy_decode) (cinfo, MCU_data);
+    /* Descale, reorder, and distribute it into the image array */
+    qdescale_zig(MCU_data[0], image_data[0][0] + mcuindex, quant_ptr);
+  }
+}
+
+
+/*
+ * Fetch one MCU row from entropy_decode, build coefficient array.
+ * This version is used for interleaved (multi-component) scans.
+ */
+
+METHODDEF void
+disassemble_interleaved_MCU (decompress_info_ptr cinfo,
+			     JBLOCKIMAGE image_data)
+{
+  JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
+  long mcuindex;
+  short blkn, ci, xpos, ypos;
+  jpeg_component_info * compptr;
+  QUANT_TBL_PTR quant_ptr;
+  JBLOCKROW image_ptr;
+
+  for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
+    /* Fetch the coefficient data */
+    (*cinfo->methods->entropy_decode) (cinfo, MCU_data);
+    /* Descale, reorder, and distribute it into the image array */
+    blkn = 0;
+    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+      compptr = cinfo->cur_comp_info[ci];
+      quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
+      for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
+	image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width);
+	for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
+	  qdescale_zig(MCU_data[blkn], image_ptr, quant_ptr);
+	  image_ptr++;
+	  blkn++;
+	}
+      }
+    }
+  }
+}
+
+
+/*
+ * Initialize for processing a scan.
+ */
+
+METHODDEF void
+disassemble_init (decompress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+/*
+ * Clean up after a scan.
+ */
+
+METHODDEF void
+disassemble_term (decompress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+
+/*
+ * The method selection routine for MCU disassembly.
+ */
+
+GLOBAL void
+jseldmcu (decompress_info_ptr cinfo)
+{
+  if (cinfo->comps_in_scan == 1)
+    cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
+  else
+    cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
+  cinfo->methods->disassemble_init = disassemble_init;
+  cinfo->methods->disassemble_term = disassemble_term;
+}
diff --git a/jdpipe.c b/jdpipe.c
new file mode 100644
index 0000000..8e08874
--- /dev/null
+++ b/jdpipe.c
@@ -0,0 +1,1309 @@
+/*
+ * jdpipe.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression pipeline controllers.
+ * These routines are invoked via the d_pipeline_controller method.
+ *
+ * There are four basic pipeline controllers, one for each combination of:
+ *	single-scan JPEG file (single component or fully interleaved)
+ *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
+ *
+ *	2-pass color quantization
+ *  vs. no color quantization or 1-pass quantization.
+ *
+ * Note that these conditions determine the needs for "big" images:
+ * multiple scans imply a big image for recombining the color components;
+ * 2-pass color quantization needs a big image for saving the data for pass 2.
+ *
+ * All but the simplest controller (single-scan, no 2-pass quantization) can be
+ * compiled out through configuration options, if you need to make a minimal
+ * implementation.  You should leave in multiple-scan support if at all
+ * possible, so that you can handle all legal JPEG files.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * About the data structures:
+ *
+ * The processing chunk size for unsubsampling is referred to in this file as
+ * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
+ * any component while subsampled, or Vmax (max_v_samp_factor) unsubsampled
+ * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
+ * groups of each component in the scan.  In a noninterleaved scan an MCU row
+ * is one row of blocks, which might not be an integral number of row groups;
+ * therefore, we read in Vk MCU rows to obtain the same amount of data as we'd
+ * have in an interleaved scan.
+ * To provide context for the unsubsampling step, we have to retain the last
+ * two row groups of the previous MCU row while reading in the next MCU row
+ * (or set of Vk MCU rows).  To do this without copying data about, we create
+ * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
+ * are allocated, but we create two different sets of pointers to this array.
+ * The second set swaps the last two pairs of row groups.  By working
+ * alternately with the two sets of pointers, we can access the data in the
+ * desired order.
+ *
+ * Cross-block smoothing also needs context above and below the "current" row.
+ * Since this is an optional feature, I've implemented it in a way that is
+ * much simpler but requires more than the minimum amount of memory.  We
+ * simply allocate three extra MCU rows worth of coefficient blocks and use
+ * them to "read ahead" one MCU row in the file.  For a typical 1000-pixel-wide
+ * image with 2x2,1x1,1x1 sampling, each MCU row is about 50Kb; an 80x86
+ * machine may be unable to apply cross-block smoothing to wider images.
+ */
+
+
+/*
+ * These variables are logically local to the pipeline controller,
+ * but we make them static so that scan_big_image can use them
+ * without having to pass them through the quantization routines.
+ * If you don't support 2-pass quantization, you could make them locals.
+ */
+
+static int rows_in_mem;		/* # of sample rows in full-size buffers */
+/* Full-size image array holding desubsampled, color-converted data. */
+static big_sarray_ptr *fullsize_cnvt_image;
+static JSAMPIMAGE fullsize_cnvt_ptrs; /* workspace for access_big_sarray() results */
+/* Work buffer for color quantization output (full size, only 1 component). */
+static JSAMPARRAY quantize_out;
+
+
+/*
+ * Utility routines: common code for pipeline controllers
+ */
+
+LOCAL void
+interleaved_scan_setup (decompress_info_ptr cinfo)
+/* Compute all derived info for an interleaved (multi-component) scan */
+/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
+{
+  short ci, mcublks;
+  jpeg_component_info *compptr;
+
+  if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
+
+  cinfo->MCUs_per_row = (cinfo->image_width
+			 + cinfo->max_h_samp_factor*DCTSIZE - 1)
+			/ (cinfo->max_h_samp_factor*DCTSIZE);
+
+  cinfo->MCU_rows_in_scan = (cinfo->image_height
+			     + cinfo->max_v_samp_factor*DCTSIZE - 1)
+			    / (cinfo->max_v_samp_factor*DCTSIZE);
+  
+  cinfo->blocks_in_MCU = 0;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* for interleaved scan, sampling factors give # of blocks per component */
+    compptr->MCU_width = compptr->h_samp_factor;
+    compptr->MCU_height = compptr->v_samp_factor;
+    compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+    /* compute physical dimensions of component */
+    compptr->subsampled_width = jround_up(compptr->true_comp_width,
+					  (long) (compptr->MCU_width*DCTSIZE));
+    compptr->subsampled_height = jround_up(compptr->true_comp_height,
+					   (long) (compptr->MCU_height*DCTSIZE));
+    /* Sanity check */
+    if (compptr->subsampled_width !=
+	(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
+      ERREXIT(cinfo->emethods, "I'm confused about the image width");
+    /* Prepare array describing MCU composition */
+    mcublks = compptr->MCU_blocks;
+    if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
+      ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
+    while (mcublks-- > 0) {
+      cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+    }
+  }
+
+  (*cinfo->methods->d_per_scan_method_selection) (cinfo);
+}
+
+
+LOCAL void
+noninterleaved_scan_setup (decompress_info_ptr cinfo)
+/* Compute all derived info for a noninterleaved (single-component) scan */
+/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
+{
+  jpeg_component_info *compptr = cinfo->cur_comp_info[0];
+
+  /* for noninterleaved scan, always one block per MCU */
+  compptr->MCU_width = 1;
+  compptr->MCU_height = 1;
+  compptr->MCU_blocks = 1;
+  /* compute physical dimensions of component */
+  compptr->subsampled_width = jround_up(compptr->true_comp_width,
+					(long) DCTSIZE);
+  compptr->subsampled_height = jround_up(compptr->true_comp_height,
+					 (long) DCTSIZE);
+
+  cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
+  cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
+
+  /* Prepare array describing MCU composition */
+  cinfo->blocks_in_MCU = 1;
+  cinfo->MCU_membership[0] = 0;
+
+  (*cinfo->methods->d_per_scan_method_selection) (cinfo);
+}
+
+
+LOCAL void
+reverse_DCT (decompress_info_ptr cinfo,
+	     JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data,
+	     int start_row)
+/* Perform inverse DCT on each block in an MCU row's worth of data; */
+/* output the results into a sample array starting at row start_row. */
+/* NB: start_row can only be nonzero when dealing with a single-component */
+/* scan; otherwise we'd have to provide for different offsets for different */
+/* components, since the heights of interleaved MCU rows can vary. */
+{
+  DCTBLOCK block;
+  JBLOCKROW browptr;
+  JSAMPARRAY srowptr;
+  long blocksperrow, bi;
+  short numrows, ri;
+  short ci;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    /* calc size of an MCU row in this component */
+    blocksperrow = cinfo->cur_comp_info[ci]->subsampled_width / DCTSIZE;
+    numrows = cinfo->cur_comp_info[ci]->MCU_height;
+    /* iterate through all blocks in MCU row */
+    for (ri = 0; ri < numrows; ri++) {
+      browptr = coeff_data[ci][ri];
+      srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
+      for (bi = 0; bi < blocksperrow; bi++) {
+	/* copy the data into a local DCTBLOCK.  This allows for change of
+	 * representation (if DCTELEM != JCOEF).  On 80x86 machines it also
+	 * brings the data back from FAR storage to NEAR storage.
+	 */
+	{ register JCOEFPTR elemptr = browptr[bi];
+	  register DCTELEM *localblkptr = block;
+	  register short elem = DCTSIZE2;
+
+	  while (--elem >= 0)
+	    *localblkptr++ = (DCTELEM) *elemptr++;
+	}
+
+	j_rev_dct(block);	/* perform inverse DCT */
+
+	/* output the data into the sample array.
+	 * Note change from signed to unsigned representation:
+	 * DCT calculation works with values +-CENTERJSAMPLE,
+	 * but sample arrays always hold 0..MAXJSAMPLE.
+	 * Have to do explicit range-limiting because of quantization errors
+	 * and so forth in the DCT/IDCT phase.
+	 */
+	{ register JSAMPROW elemptr;
+	  register DCTELEM *localblkptr = block;
+	  register short elemr, elemc;
+	  register DCTELEM temp;
+
+	  for (elemr = 0; elemr < DCTSIZE; elemr++) {
+	    elemptr = srowptr[elemr] + (bi * DCTSIZE);
+	    for (elemc = 0; elemc < DCTSIZE; elemc++) {
+	      temp = (*localblkptr++) + CENTERJSAMPLE;
+	      if (temp < 0) temp = 0;
+	      else if (temp > MAXJSAMPLE) temp = MAXJSAMPLE;
+	      *elemptr++ = (JSAMPLE) temp;
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+
+LOCAL JSAMPIMAGE
+alloc_sampimage (decompress_info_ptr cinfo,
+		 int num_comps, long num_rows, long num_cols)
+/* Allocate an in-memory sample image (all components same size) */
+{
+  JSAMPIMAGE image;
+  int ci;
+
+  image = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(num_comps * SIZEOF(JSAMPARRAY));
+  for (ci = 0; ci < num_comps; ci++) {
+    image[ci] = (*cinfo->emethods->alloc_small_sarray) (num_cols, num_rows);
+  }
+  return image;
+}
+
+
+LOCAL void
+free_sampimage (decompress_info_ptr cinfo, JSAMPIMAGE image,
+		int num_comps, long num_rows)
+/* Release a sample image created by alloc_sampimage */
+{
+  int ci;
+
+  for (ci = 0; ci < num_comps; ci++) {
+      (*cinfo->emethods->free_small_sarray) (image[ci], num_rows);
+  }
+  (*cinfo->emethods->free_small) ((void *) image);
+}
+
+
+LOCAL JBLOCKIMAGE
+alloc_MCU_row (decompress_info_ptr cinfo)
+/* Allocate one MCU row's worth of coefficient blocks */
+{
+  JBLOCKIMAGE image;
+  int ci;
+
+  image = (JBLOCKIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->comps_in_scan * SIZEOF(JBLOCKARRAY));
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    image[ci] = (*cinfo->emethods->alloc_small_barray)
+			(cinfo->cur_comp_info[ci]->subsampled_width / DCTSIZE,
+			 (long) cinfo->cur_comp_info[ci]->MCU_height);
+  }
+  return image;
+}
+
+
+LOCAL void
+free_MCU_row (decompress_info_ptr cinfo, JBLOCKIMAGE image)
+/* Release a coefficient block array created by alloc_MCU_row */
+{
+  int ci;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    (*cinfo->emethods->free_small_barray)
+		(image[ci], (long) cinfo->cur_comp_info[ci]->MCU_height);
+  }
+  (*cinfo->emethods->free_small) ((void *) image);
+}
+
+
+LOCAL void
+alloc_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE subsampled_data[2])
+/* Create a subsampled-data buffer having the desired structure */
+/* (see comments at head of file) */
+{
+  short ci, vs, i;
+
+  /* Get top-level space for array pointers */
+  subsampled_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->comps_in_scan * SIZEOF(JSAMPARRAY));
+  subsampled_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->comps_in_scan * SIZEOF(JSAMPARRAY));
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    vs = cinfo->cur_comp_info[ci]->v_samp_factor; /* row group height */
+    /* Allocate the real storage */
+    subsampled_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
+				(cinfo->cur_comp_info[ci]->subsampled_width,
+				(long) (vs * (DCTSIZE+2)));
+    /* Create space for the scrambled-order pointers */
+    subsampled_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
+				(vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
+    /* Duplicate the first DCTSIZE-2 row groups */
+    for (i = 0; i < vs * (DCTSIZE-2); i++) {
+      subsampled_data[1][ci][i] = subsampled_data[0][ci][i];
+    }
+    /* Copy the last four row groups in swapped order */
+    for (i = 0; i < vs * 2; i++) {
+      subsampled_data[1][ci][vs*DCTSIZE + i] = subsampled_data[0][ci][vs*(DCTSIZE-2) + i];
+      subsampled_data[1][ci][vs*(DCTSIZE-2) + i] = subsampled_data[0][ci][vs*DCTSIZE + i];
+    }
+  }
+}
+
+
+LOCAL void
+free_sampling_buffer (decompress_info_ptr cinfo, JSAMPIMAGE subsampled_data[2])
+/* Release a sampling buffer created by alloc_sampling_buffer */
+{
+  short ci, vs;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    vs = cinfo->cur_comp_info[ci]->v_samp_factor; /* row group height */
+    /* Free the real storage */
+    (*cinfo->emethods->free_small_sarray)
+		(subsampled_data[0][ci], (long) (vs * (DCTSIZE+2)));
+    /* Free the scrambled-order pointers */
+    (*cinfo->emethods->free_small) ((void *) subsampled_data[1][ci]);
+  }
+
+  /* Free the top-level space */
+  (*cinfo->emethods->free_small) ((void *) subsampled_data[0]);
+  (*cinfo->emethods->free_small) ((void *) subsampled_data[1]);
+}
+
+
+LOCAL void
+duplicate_row (JSAMPARRAY image_data,
+	       long num_cols, int source_row, int num_rows)
+/* Duplicate the source_row at source_row+1 .. source_row+num_rows */
+/* This happens only at the bottom of the image, */
+/* so it needn't be super-efficient */
+{
+  register int row;
+
+  for (row = 1; row <= num_rows; row++) {
+    jcopy_sample_rows(image_data, source_row, image_data, source_row + row,
+		      1, num_cols);
+  }
+}
+
+
+LOCAL void
+expand (decompress_info_ptr cinfo,
+	JSAMPIMAGE subsampled_data, JSAMPIMAGE fullsize_data,
+	long fullsize_width,
+	short above, short current, short below, short out)
+/* Do unsubsampling expansion of a single row group (of each component).  */
+/* above, current, below are indexes of row groups in subsampled_data;    */
+/* out is the index of the target row group in fullsize_data.             */
+/* Special case: above, below can be -1 to indicate top, bottom of image. */
+{
+  jpeg_component_info *compptr;
+  JSAMPARRAY above_ptr, below_ptr;
+  JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
+  short ci, vs, i;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    vs = compptr->v_samp_factor; /* row group height */
+
+    if (above >= 0)
+      above_ptr = subsampled_data[ci] + above * vs;
+    else {
+      /* Top of image: make a dummy above-context with copies of 1st row */
+      /* We assume current=0 in this case */
+      for (i = 0; i < vs; i++)
+	dummy[i] = subsampled_data[ci][0];
+      above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
+    }
+
+    if (below >= 0)
+      below_ptr = subsampled_data[ci] + below * vs;
+    else {
+      /* Bot of image: make a dummy below-context with copies of last row */
+      for (i = 0; i < vs; i++)
+	dummy[i] = subsampled_data[ci][(current+1)*vs-1];
+      below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
+    }
+
+    (*cinfo->methods->unsubsample[ci])
+		(cinfo, (int) ci,
+		 compptr->subsampled_width, (int) vs,
+		 fullsize_width, (int) cinfo->max_v_samp_factor,
+		 above_ptr,
+		 subsampled_data[ci] + current * vs,
+		 below_ptr,
+		 fullsize_data[ci] + out * cinfo->max_v_samp_factor);
+  }
+}
+
+
+LOCAL void
+emit_1pass (decompress_info_ptr cinfo, int num_rows,
+	    JSAMPIMAGE fullsize_data, JSAMPIMAGE color_data)
+/* Do color conversion and output of num_rows full-size rows. */
+/* This is not used for 2-pass color quantization. */
+{
+  (*cinfo->methods->color_convert) (cinfo, num_rows,
+				    fullsize_data, color_data);
+
+  if (cinfo->quantize_colors) {
+    (*cinfo->methods->color_quantize) (cinfo, num_rows,
+				       color_data, quantize_out);
+
+    (*cinfo->methods->put_pixel_rows) (cinfo, num_rows,
+				       &quantize_out);
+  } else {
+    (*cinfo->methods->put_pixel_rows) (cinfo, num_rows,
+				       color_data);
+  }
+}
+
+
+/*
+ * Support routines for 2-pass color quantization.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+LOCAL void
+emit_2pass (decompress_info_ptr cinfo, long top_row, int num_rows,
+	    JSAMPIMAGE fullsize_data)
+/* Do color conversion and output data to the quantization buffer image. */
+/* This is used only with 2-pass color quantization. */
+{
+  short ci;
+
+  /* Realign the big buffers */
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    fullsize_cnvt_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
+      (fullsize_cnvt_image[ci], top_row, TRUE);
+  }
+
+  /* Do colorspace conversion */
+  (*cinfo->methods->color_convert) (cinfo, num_rows,
+				    fullsize_data, fullsize_cnvt_ptrs);
+  /* Let quantizer get first-pass peek at the data. */
+  /* (Quantizer could change data if it wants to.)  */
+  (*cinfo->methods->color_quant_prescan) (cinfo, num_rows, fullsize_cnvt_ptrs);
+}
+
+
+METHODDEF void
+scan_big_image (decompress_info_ptr cinfo, quantize_method_ptr quantize_method)
+/* This is the "iterator" routine used by the quantizer. */
+{
+  long pixel_rows_output;
+  short ci;
+
+  for (pixel_rows_output = 0; pixel_rows_output < cinfo->image_height;
+       pixel_rows_output += rows_in_mem) {
+    /* Realign the big buffers */
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      fullsize_cnvt_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
+	(fullsize_cnvt_image[ci], pixel_rows_output, FALSE);
+    }
+    /* Let the quantizer have its way with the data.
+     * Note that quantize_out is simply workspace for the quantizer;
+     * when it's ready to output, it must call put_pixel_rows itself.
+     */
+    (*quantize_method) (cinfo,
+			(int) MIN(rows_in_mem,
+				  cinfo->image_height - pixel_rows_output),
+			fullsize_cnvt_ptrs, quantize_out);
+  }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Support routines for cross-block smoothing.
+ */
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+
+LOCAL void
+smooth_mcu_row (decompress_info_ptr cinfo,
+		JBLOCKIMAGE above, JBLOCKIMAGE input, JBLOCKIMAGE below,
+		JBLOCKIMAGE output)
+/* Apply cross-block smoothing to one MCU row's worth of coefficient blocks. */
+/* above,below are NULL if at top/bottom of image. */
+{
+  jpeg_component_info *compptr;
+  short ci, ri, last;
+  JBLOCKROW prev;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    last = compptr->MCU_height - 1;
+
+    if (above == NULL)
+      prev = NULL;
+    else
+      prev = above[ci][last];
+
+    for (ri = 0; ri < last; ri++) {
+      (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
+				prev, input[ci][ri], input[ci][ri+1],
+				output[ci][ri]);
+      prev = input[ci][ri];
+    }
+
+    if (below == NULL)
+      (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
+				prev, input[ci][last], (JBLOCKROW) NULL,
+				output[ci][last]);
+    else
+      (*cinfo->methods->smooth_coefficients) (cinfo, compptr,
+				prev, input[ci][last], below[ci][0],
+				output[ci][last]);
+  }
+}
+
+
+LOCAL void
+get_smoothed_row (decompress_info_ptr cinfo, JBLOCKIMAGE coeff_data,
+		  JBLOCKIMAGE bsmooth[3], int * whichb, long cur_mcu_row)
+/* Get an MCU row of coefficients, applying cross-block smoothing. */
+/* The output row is placed in coeff_data.  bsmooth and whichb hold */
+/* working state, and cur_row is needed to check for image top/bottom. */
+/* This routine just takes care of the buffering logic. */
+{
+  int prev, cur, next;
+  
+  /* Special case for top of image: need to pre-fetch a row & init whichb */
+  if (cur_mcu_row == 0) {
+    (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[0]);
+    if (cinfo->MCU_rows_in_scan > 1) {
+      (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[1]);
+      smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], bsmooth[1],
+		     coeff_data);
+    } else {
+      smooth_mcu_row(cinfo, (JBLOCKIMAGE) NULL, bsmooth[0], (JBLOCKIMAGE) NULL,
+		     coeff_data);
+    }
+    *whichb = 1;		/* points to next bsmooth[] element to use */
+    return;
+  }
+  
+  cur = *whichb;		/* set up references */
+  prev = (cur == 0 ? 2 : cur - 1);
+  next = (cur == 2 ? 0 : cur + 1);
+  *whichb = next;		/* advance whichb for next time */
+  
+  /* Special case for bottom of image: don't read another row */
+  if (cur_mcu_row >= cinfo->MCU_rows_in_scan - 1) {
+    smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], (JBLOCKIMAGE) NULL,
+		   coeff_data);
+    return;
+  }
+  
+  /* Normal case: read ahead a new row, smooth the one I got before */
+  (*cinfo->methods->disassemble_MCU) (cinfo, bsmooth[next]);
+  smooth_mcu_row(cinfo, bsmooth[prev], bsmooth[cur], bsmooth[next],
+		 coeff_data);
+}
+
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
+
+
+
+/*
+ * Decompression pipeline controller used for single-scan files
+ * without 2-pass color quantization.
+ */
+
+METHODDEF void
+single_dcontroller (decompress_info_ptr cinfo)
+{
+  long fullsize_width;		/* # of samples per row in full-size buffers */
+  long cur_mcu_row;		/* counts # of MCU rows processed */
+  long pixel_rows_output;	/* # of pixel rows actually emitted */
+  int mcu_rows_per_loop;	/* # of MCU rows processed per outer loop */
+  /* Work buffer for dequantized coefficients (IDCT input) */
+  JBLOCKIMAGE coeff_data;
+  /* Work buffer for cross-block smoothing input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  JBLOCKIMAGE bsmooth[3];	/* this is optional */
+  int whichb;
+#endif
+  /* Work buffer for subsampled image data (see comments at head of file) */
+  JSAMPIMAGE subsampled_data[2];
+  /* Work buffer for desubsampled data */
+  JSAMPIMAGE fullsize_data;
+  /* Work buffer for color conversion output (full size) */
+  JSAMPIMAGE color_data;
+  int whichss, ri;
+  short i;
+
+  /* Initialize for 1-pass color quantization, if needed */
+  if (cinfo->quantize_colors)
+    (*cinfo->methods->color_quant_init) (cinfo);
+
+  /* Prepare for single scan containing all components */
+  if (cinfo->comps_in_scan == 1) {
+    noninterleaved_scan_setup(cinfo);
+    /* Need to read Vk MCU rows to obtain Vk block rows */
+    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
+  } else {
+    interleaved_scan_setup(cinfo);
+    /* in an interleaved scan, one MCU row provides Vk block rows */
+    mcu_rows_per_loop = 1;
+  }
+
+  /* Compute dimensions of full-size pixel buffers */
+  /* Note these are the same whether interleaved or not. */
+  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
+  fullsize_width = jround_up(cinfo->image_width,
+			     (long) (cinfo->max_h_samp_factor * DCTSIZE));
+
+  /* Allocate working memory: */
+  /* coeff_data holds a single MCU row of coefficient blocks */
+  coeff_data = alloc_MCU_row(cinfo);
+  /* if doing cross-block smoothing, need extra space for its input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  if (cinfo->do_block_smoothing) {
+    bsmooth[0] = alloc_MCU_row(cinfo);
+    bsmooth[1] = alloc_MCU_row(cinfo);
+    bsmooth[2] = alloc_MCU_row(cinfo);
+  }
+#endif
+  /* subsampled_data is sample data before unsubsampling */
+  alloc_sampling_buffer(cinfo, subsampled_data);
+  /* fullsize_data is sample data after unsubsampling */
+  fullsize_data = alloc_sampimage(cinfo, (int) cinfo->num_components,
+				  (long) rows_in_mem, fullsize_width);
+  /* color_data is the result of the colorspace conversion step */
+  color_data = alloc_sampimage(cinfo, (int) cinfo->color_out_comps,
+			       (long) rows_in_mem, fullsize_width);
+  /* if quantizing colors, also need a one-component output area for that. */
+  if (cinfo->quantize_colors)
+    quantize_out = (*cinfo->emethods->alloc_small_sarray)
+				(fullsize_width, (long) rows_in_mem);
+
+  /* Tell the memory manager to instantiate big arrays.
+   * We don't need any big arrays in this controller,
+   * but some other module (like the output file writer) may need one.
+   */
+  (*cinfo->emethods->alloc_big_arrays)
+	((long) 0,				/* no more small sarrays */
+	 (long) 0,				/* no more small barrays */
+	 (long) 0);				/* no more "medium" objects */
+	 /* NB: quantizer must get any such objects at color_quant_init time */
+
+  /* Initialize to read scan data */
+
+  (*cinfo->methods->entropy_decoder_init) (cinfo);
+  (*cinfo->methods->unsubsample_init) (cinfo);
+  (*cinfo->methods->disassemble_init) (cinfo);
+
+  /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
+
+  pixel_rows_output = 0;
+  whichss = 1;			/* arrange to start with subsampled_data[0] */
+
+  for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
+       cur_mcu_row += mcu_rows_per_loop) {
+    whichss ^= 1;		/* switch to other subsample buffer */
+
+    /* Obtain v_samp_factor block rows of each component in the scan. */
+    /* This is a single MCU row if interleaved, multiple MCU rows if not. */
+    /* In the noninterleaved case there might be fewer than v_samp_factor */
+    /* block rows remaining; if so, pad with copies of the last pixel row */
+    /* so that unsubsampling doesn't have to treat it as a special case. */
+
+    for (ri = 0; ri < mcu_rows_per_loop; ri++) {
+      if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
+	/* OK to actually read an MCU row. */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+	if (cinfo->do_block_smoothing)
+	  get_smoothed_row(cinfo, coeff_data,
+			   bsmooth, &whichb, cur_mcu_row + ri);
+	else
+#endif
+	  (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
+      
+	reverse_DCT(cinfo, coeff_data, subsampled_data[whichss],
+		    ri * DCTSIZE);
+      } else {
+	/* Need to pad out with copies of the last subsampled row. */
+	/* This can only happen if there is just one component. */
+	duplicate_row(subsampled_data[whichss][0],
+		      cinfo->cur_comp_info[0]->subsampled_width,
+		      ri * DCTSIZE - 1, DCTSIZE);
+      }
+    }
+
+    /* Unsubsample the data */
+    /* First time through is a special case */
+
+    if (cur_mcu_row) {
+      /* Expand last row group of previous set */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
+	     (short) (DCTSIZE-1));
+      /* and dump the previous set's expanded data */
+      emit_1pass (cinfo, rows_in_mem, fullsize_data, color_data);
+      pixel_rows_output += rows_in_mem;
+      /* Expand first row group of this set */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (DCTSIZE+1), (short) 0, (short) 1,
+	     (short) 0);
+    } else {
+      /* Expand first row group with dummy above-context */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (-1), (short) 0, (short) 1,
+	     (short) 0);
+    }
+    /* Expand second through next-to-last row groups of this set */
+    for (i = 1; i <= DCTSIZE-2; i++) {
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (i-1), (short) i, (short) (i+1),
+	     (short) i);
+    }
+  } /* end of outer loop */
+
+  /* Expand the last row group with dummy below-context */
+  /* Note whichss points to last buffer side used */
+  expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	 (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
+	 (short) (DCTSIZE-1));
+  /* and dump the remaining data (may be less than full height) */
+  emit_1pass (cinfo, (int) (cinfo->image_height - pixel_rows_output),
+	      fullsize_data, color_data);
+
+  /* Clean up after the scan */
+  (*cinfo->methods->disassemble_term) (cinfo);
+  (*cinfo->methods->unsubsample_term) (cinfo);
+  (*cinfo->methods->entropy_decoder_term) (cinfo);
+  (*cinfo->methods->read_scan_trailer) (cinfo);
+
+  /* Verify that we've seen the whole input file */
+  if ((*cinfo->methods->read_scan_header) (cinfo))
+    ERREXIT(cinfo->emethods, "Didn't expect more than one scan");
+
+  /* Release working memory */
+  free_MCU_row(cinfo, coeff_data);
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  if (cinfo->do_block_smoothing) {
+    free_MCU_row(cinfo, bsmooth[0]);
+    free_MCU_row(cinfo, bsmooth[1]);
+    free_MCU_row(cinfo, bsmooth[2]);
+  }
+#endif
+  free_sampling_buffer(cinfo, subsampled_data);
+  free_sampimage(cinfo, fullsize_data, (int) cinfo->num_components,
+		 (long) rows_in_mem);
+  free_sampimage(cinfo, color_data, (int) cinfo->color_out_comps,
+		 (long) rows_in_mem);
+  if (cinfo->quantize_colors)
+    (*cinfo->emethods->free_small_sarray)
+		(quantize_out, (long) rows_in_mem);
+
+  /* Close up shop */
+  if (cinfo->quantize_colors)
+    (*cinfo->methods->color_quant_term) (cinfo);
+}
+
+
+/*
+ * Decompression pipeline controller used for single-scan files
+ * with 2-pass color quantization.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF void
+single_2quant_dcontroller (decompress_info_ptr cinfo)
+{
+  long fullsize_width;		/* # of samples per row in full-size buffers */
+  long cur_mcu_row;		/* counts # of MCU rows processed */
+  long pixel_rows_output;	/* # of pixel rows actually emitted */
+  int mcu_rows_per_loop;	/* # of MCU rows processed per outer loop */
+  /* Work buffer for dequantized coefficients (IDCT input) */
+  JBLOCKIMAGE coeff_data;
+  /* Work buffer for cross-block smoothing input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  JBLOCKIMAGE bsmooth[3];	/* this is optional */
+  int whichb;
+#endif
+  /* Work buffer for subsampled image data (see comments at head of file) */
+  JSAMPIMAGE subsampled_data[2];
+  /* Work buffer for desubsampled data */
+  JSAMPIMAGE fullsize_data;
+  int whichss, ri;
+  short ci, i;
+
+  /* Initialize for 2-pass color quantization */
+  (*cinfo->methods->color_quant_init) (cinfo);
+
+  /* Prepare for single scan containing all components */
+  if (cinfo->comps_in_scan == 1) {
+    noninterleaved_scan_setup(cinfo);
+    /* Need to read Vk MCU rows to obtain Vk block rows */
+    mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
+  } else {
+    interleaved_scan_setup(cinfo);
+    /* in an interleaved scan, one MCU row provides Vk block rows */
+    mcu_rows_per_loop = 1;
+  }
+
+  /* Compute dimensions of full-size pixel buffers */
+  /* Note these are the same whether interleaved or not. */
+  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
+  fullsize_width = jround_up(cinfo->image_width,
+			     (long) (cinfo->max_h_samp_factor * DCTSIZE));
+
+  /* Allocate working memory: */
+  /* coeff_data holds a single MCU row of coefficient blocks */
+  coeff_data = alloc_MCU_row(cinfo);
+  /* if doing cross-block smoothing, need extra space for its input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  if (cinfo->do_block_smoothing) {
+    bsmooth[0] = alloc_MCU_row(cinfo);
+    bsmooth[1] = alloc_MCU_row(cinfo);
+    bsmooth[2] = alloc_MCU_row(cinfo);
+  }
+#endif
+  /* subsampled_data is sample data before unsubsampling */
+  alloc_sampling_buffer(cinfo, subsampled_data);
+  /* fullsize_data is sample data after unsubsampling */
+  fullsize_data = alloc_sampimage(cinfo, (int) cinfo->num_components,
+				  (long) rows_in_mem, fullsize_width);
+  /* Also need a one-component output area for color quantizer. */
+  quantize_out = (*cinfo->emethods->alloc_small_sarray)
+				(fullsize_width, (long) rows_in_mem);
+
+  /* Get a big image for quantizer input: desubsampled, color-converted data */
+  fullsize_cnvt_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small)
+			(cinfo->num_components * SIZEOF(big_sarray_ptr));
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    fullsize_cnvt_image[ci] = (*cinfo->emethods->request_big_sarray)
+			(fullsize_width,
+			 jround_up(cinfo->image_height, (long) rows_in_mem),
+			 (long) rows_in_mem);
+  }
+  /* Also get an area for pointers to currently accessible chunks */
+  fullsize_cnvt_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+
+  /* Tell the memory manager to instantiate big arrays */
+  (*cinfo->emethods->alloc_big_arrays)
+	((long) 0,				/* no more small sarrays */
+	 (long) 0,				/* no more small barrays */
+	 (long) 0);				/* no more "medium" objects */
+	 /* NB: quantizer must get any such objects at color_quant_init time */
+
+  /* Initialize to read scan data */
+
+  (*cinfo->methods->entropy_decoder_init) (cinfo);
+  (*cinfo->methods->unsubsample_init) (cinfo);
+  (*cinfo->methods->disassemble_init) (cinfo);
+
+  /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
+
+  pixel_rows_output = 0;
+  whichss = 1;			/* arrange to start with subsampled_data[0] */
+
+  for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
+       cur_mcu_row += mcu_rows_per_loop) {
+    whichss ^= 1;		/* switch to other subsample buffer */
+
+    /* Obtain v_samp_factor block rows of each component in the scan. */
+    /* This is a single MCU row if interleaved, multiple MCU rows if not. */
+    /* In the noninterleaved case there might be fewer than v_samp_factor */
+    /* block rows remaining; if so, pad with copies of the last pixel row */
+    /* so that unsubsampling doesn't have to treat it as a special case. */
+
+    for (ri = 0; ri < mcu_rows_per_loop; ri++) {
+      if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
+	/* OK to actually read an MCU row. */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+	if (cinfo->do_block_smoothing)
+	  get_smoothed_row(cinfo, coeff_data,
+			   bsmooth, &whichb, cur_mcu_row + ri);
+	else
+#endif
+	  (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
+      
+	reverse_DCT(cinfo, coeff_data, subsampled_data[whichss],
+		    ri * DCTSIZE);
+      } else {
+	/* Need to pad out with copies of the last subsampled row. */
+	/* This can only happen if there is just one component. */
+	duplicate_row(subsampled_data[whichss][0],
+		      cinfo->cur_comp_info[0]->subsampled_width,
+		      ri * DCTSIZE - 1, DCTSIZE);
+      }
+    }
+
+    /* Unsubsample the data */
+    /* First time through is a special case */
+
+    if (cur_mcu_row) {
+      /* Expand last row group of previous set */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
+	     (short) (DCTSIZE-1));
+      /* and dump the previous set's expanded data */
+      emit_2pass (cinfo, pixel_rows_output, rows_in_mem, fullsize_data);
+      pixel_rows_output += rows_in_mem;
+      /* Expand first row group of this set */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (DCTSIZE+1), (short) 0, (short) 1,
+	     (short) 0);
+    } else {
+      /* Expand first row group with dummy above-context */
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (-1), (short) 0, (short) 1,
+	     (short) 0);
+    }
+    /* Expand second through next-to-last row groups of this set */
+    for (i = 1; i <= DCTSIZE-2; i++) {
+      expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	     (short) (i-1), (short) i, (short) (i+1),
+	     (short) i);
+    }
+  } /* end of outer loop */
+
+  /* Expand the last row group with dummy below-context */
+  /* Note whichss points to last buffer side used */
+  expand(cinfo, subsampled_data[whichss], fullsize_data, fullsize_width,
+	 (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
+	 (short) (DCTSIZE-1));
+  /* and dump the remaining data (may be less than full height) */
+  emit_2pass (cinfo, pixel_rows_output,
+	      (int) (cinfo->image_height - pixel_rows_output),
+	      fullsize_data);
+
+  /* Clean up after the scan */
+  (*cinfo->methods->disassemble_term) (cinfo);
+  (*cinfo->methods->unsubsample_term) (cinfo);
+  (*cinfo->methods->entropy_decoder_term) (cinfo);
+  (*cinfo->methods->read_scan_trailer) (cinfo);
+
+  /* Verify that we've seen the whole input file */
+  if ((*cinfo->methods->read_scan_header) (cinfo))
+    ERREXIT(cinfo->emethods, "Didn't expect more than one scan");
+
+  /* Now that we've collected the data, let the color quantizer do its thing */
+  (*cinfo->methods->color_quant_doit) (cinfo, scan_big_image);
+
+  /* Release working memory */
+  free_MCU_row(cinfo, coeff_data);
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  if (cinfo->do_block_smoothing) {
+    free_MCU_row(cinfo, bsmooth[0]);
+    free_MCU_row(cinfo, bsmooth[1]);
+    free_MCU_row(cinfo, bsmooth[2]);
+  }
+#endif
+  free_sampling_buffer(cinfo, subsampled_data);
+  free_sampimage(cinfo, fullsize_data, (int) cinfo->num_components,
+		 (long) rows_in_mem);
+  (*cinfo->emethods->free_small_sarray)
+		(quantize_out, (long) rows_in_mem);
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    (*cinfo->emethods->free_big_sarray) (fullsize_cnvt_image[ci]);
+  }
+  (*cinfo->emethods->free_small) ((void *) fullsize_cnvt_image);
+  (*cinfo->emethods->free_small) ((void *) fullsize_cnvt_ptrs);
+
+  /* Close up shop */
+  (*cinfo->methods->color_quant_term) (cinfo);
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Decompression pipeline controller used for multiple-scan files
+ * without 2-pass color quantization.
+ *
+ * The current implementation places the "big" buffer at the stage of
+ * desubsampled data.  Buffering subsampled data instead would reduce the
+ * size of temp files (by about a factor of 2 in typical cases).  However,
+ * the unsubsampling logic is dependent on the assumption that unsubsampling
+ * occurs during a scan, so it's much easier to do the enlargement as the
+ * JPEG file is read.  This also simplifies life for the memory manager,
+ * which would otherwise have to deal with overlapping access_big_sarray()
+ * requests.
+ *
+ * At present it appears that most JPEG files will be single-scan, so
+ * it doesn't seem worthwhile to try to make this implementation smarter.
+ */
+
+#ifdef MULTISCAN_FILES_SUPPORTED
+
+METHODDEF void
+multi_dcontroller (decompress_info_ptr cinfo)
+{
+  long fullsize_width;		/* # of samples per row in full-size buffers */
+  long cur_mcu_row;		/* counts # of MCU rows processed */
+  long pixel_rows_output;	/* # of pixel rows actually emitted */
+  int mcu_rows_per_loop;	/* # of MCU rows processed per outer loop */
+  /* Work buffer for dequantized coefficients (IDCT input) */
+  JBLOCKIMAGE coeff_data;
+  /* Work buffer for cross-block smoothing input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  JBLOCKIMAGE bsmooth[3];	/* this is optional */
+  int whichb;
+#endif
+  /* Work buffer for subsampled image data (see comments at head of file) */
+  JSAMPIMAGE subsampled_data[2];
+  /* Full-image buffer holding desubsampled, but not color-converted, data */
+  big_sarray_ptr *fullsize_image;
+  JSAMPIMAGE fullsize_ptrs;	/* workspace for access_big_sarray() results */
+  /* Work buffer for color conversion output (full size) */
+  JSAMPIMAGE color_data;
+  int whichss, ri;
+  short ci, i;
+
+  /* Initialize for 1-pass color quantization, if needed */
+  if (cinfo->quantize_colors)
+    (*cinfo->methods->color_quant_init) (cinfo);
+
+  /* Compute dimensions of full-size pixel buffers */
+  /* Note these are the same whether interleaved or not. */
+  rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
+  fullsize_width = jround_up(cinfo->image_width,
+			     (long) (cinfo->max_h_samp_factor * DCTSIZE));
+
+  /* Allocate all working memory that doesn't depend on scan info */
+  /* color_data is the result of the colorspace conversion step */
+  color_data = alloc_sampimage(cinfo, (int) cinfo->color_out_comps,
+			       (long) rows_in_mem, fullsize_width);
+  /* if quantizing colors, also need a one-component output area for that. */
+  if (cinfo->quantize_colors)
+    quantize_out = (*cinfo->emethods->alloc_small_sarray)
+				(fullsize_width, (long) rows_in_mem);
+
+  /* Get a big image: fullsize_image is sample data after unsubsampling. */
+  fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small)
+			(cinfo->num_components * SIZEOF(big_sarray_ptr));
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    fullsize_image[ci] = (*cinfo->emethods->request_big_sarray)
+			(fullsize_width,
+			 jround_up(cinfo->image_height, (long) rows_in_mem),
+			 (long) rows_in_mem);
+  }
+  /* Also get an area for pointers to currently accessible chunks */
+  fullsize_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
+				(cinfo->num_components * SIZEOF(JSAMPARRAY));
+
+  /* Tell the memory manager to instantiate big arrays */
+  (*cinfo->emethods->alloc_big_arrays)
+	 /* extra sarray space is for subsampled-data buffers: */
+	((long) (fullsize_width			/* max width in samples */
+	 * cinfo->max_v_samp_factor*(DCTSIZE+2)	/* max height */
+	 * cinfo->num_components),		/* max components per scan */
+	 /* extra barray space is for MCU-row buffers: */
+	 (long) ((fullsize_width / DCTSIZE)	/* max width in blocks */
+	 * cinfo->max_v_samp_factor		/* max height */
+	 * cinfo->num_components		/* max components per scan */
+	 * (cinfo->do_block_smoothing ? 4 : 1)),/* how many of these we need */
+	 /* no extra "medium"-object space */
+	 /* NB: quantizer must get any such objects at color_quant_init time */
+	 (long) 0);
+
+
+  /* Loop over scans in file */
+
+  do {
+    
+    /* Prepare for this scan */
+    if (cinfo->comps_in_scan == 1) {
+      noninterleaved_scan_setup(cinfo);
+      /* Need to read Vk MCU rows to obtain Vk block rows */
+      mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
+    } else {
+      interleaved_scan_setup(cinfo);
+      /* in an interleaved scan, one MCU row provides Vk block rows */
+      mcu_rows_per_loop = 1;
+    }
+    
+    /* Allocate scan-local working memory */
+    /* coeff_data holds a single MCU row of coefficient blocks */
+    coeff_data = alloc_MCU_row(cinfo);
+    /* if doing cross-block smoothing, need extra space for its input */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+    if (cinfo->do_block_smoothing) {
+      bsmooth[0] = alloc_MCU_row(cinfo);
+      bsmooth[1] = alloc_MCU_row(cinfo);
+      bsmooth[2] = alloc_MCU_row(cinfo);
+    }
+#endif
+    /* subsampled_data is sample data before unsubsampling */
+    alloc_sampling_buffer(cinfo, subsampled_data);
+
+    /* line up the big buffers */
+    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+      fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
+	(fullsize_image[cinfo->cur_comp_info[ci]->component_index],
+	 (long) 0, TRUE);
+    }
+    
+    /* Initialize to read scan data */
+    
+    (*cinfo->methods->entropy_decoder_init) (cinfo);
+    (*cinfo->methods->unsubsample_init) (cinfo);
+    (*cinfo->methods->disassemble_init) (cinfo);
+    
+    /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */
+    
+    pixel_rows_output = 0;
+    whichss = 1;		/* arrange to start with subsampled_data[0] */
+    
+    for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan;
+	 cur_mcu_row += mcu_rows_per_loop) {
+      whichss ^= 1;		/* switch to other subsample buffer */
+
+      /* Obtain v_samp_factor block rows of each component in the scan. */
+      /* This is a single MCU row if interleaved, multiple MCU rows if not. */
+      /* In the noninterleaved case there might be fewer than v_samp_factor */
+      /* block rows remaining; if so, pad with copies of the last pixel row */
+      /* so that unsubsampling doesn't have to treat it as a special case. */
+      
+      for (ri = 0; ri < mcu_rows_per_loop; ri++) {
+	if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) {
+	  /* OK to actually read an MCU row. */
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+	  if (cinfo->do_block_smoothing)
+	    get_smoothed_row(cinfo, coeff_data,
+			     bsmooth, &whichb, cur_mcu_row + ri);
+	  else
+#endif
+	    (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data);
+	  
+	  reverse_DCT(cinfo, coeff_data, subsampled_data[whichss],
+		      ri * DCTSIZE);
+	} else {
+	  /* Need to pad out with copies of the last subsampled row. */
+	  /* This can only happen if there is just one component. */
+	  duplicate_row(subsampled_data[whichss][0],
+			cinfo->cur_comp_info[0]->subsampled_width,
+			ri * DCTSIZE - 1, DCTSIZE);
+	}
+      }
+      
+      /* Unsubsample the data */
+      /* First time through is a special case */
+      
+      if (cur_mcu_row) {
+	/* Expand last row group of previous set */
+	expand(cinfo, subsampled_data[whichss], fullsize_ptrs, fullsize_width,
+	       (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
+	       (short) (DCTSIZE-1));
+	/* Realign the big buffers */
+	pixel_rows_output += rows_in_mem;
+	for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+	  fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
+	    (fullsize_image[cinfo->cur_comp_info[ci]->component_index],
+	     pixel_rows_output, TRUE);
+	}
+	/* Expand first row group of this set */
+	expand(cinfo, subsampled_data[whichss], fullsize_ptrs, fullsize_width,
+	       (short) (DCTSIZE+1), (short) 0, (short) 1,
+	       (short) 0);
+      } else {
+	/* Expand first row group with dummy above-context */
+	expand(cinfo, subsampled_data[whichss], fullsize_ptrs, fullsize_width,
+	       (short) (-1), (short) 0, (short) 1,
+	       (short) 0);
+      }
+      /* Expand second through next-to-last row groups of this set */
+      for (i = 1; i <= DCTSIZE-2; i++) {
+	expand(cinfo, subsampled_data[whichss], fullsize_ptrs, fullsize_width,
+	       (short) (i-1), (short) i, (short) (i+1),
+	       (short) i);
+      }
+    } /* end of outer loop */
+    
+    /* Expand the last row group with dummy below-context */
+    /* Note whichss points to last buffer side used */
+    expand(cinfo, subsampled_data[whichss], fullsize_ptrs, fullsize_width,
+	   (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
+	   (short) (DCTSIZE-1));
+    
+    /* Clean up after the scan */
+    (*cinfo->methods->disassemble_term) (cinfo);
+    (*cinfo->methods->unsubsample_term) (cinfo);
+    (*cinfo->methods->entropy_decoder_term) (cinfo);
+    (*cinfo->methods->read_scan_trailer) (cinfo);
+
+    /* Release scan-local working memory */
+    free_MCU_row(cinfo, coeff_data);
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+    if (cinfo->do_block_smoothing) {
+      free_MCU_row(cinfo, bsmooth[0]);
+      free_MCU_row(cinfo, bsmooth[1]);
+      free_MCU_row(cinfo, bsmooth[2]);
+    }
+#endif
+    free_sampling_buffer(cinfo, subsampled_data);
+    
+    /* Repeat if there is another scan */
+  } while ((*cinfo->methods->read_scan_header) (cinfo));
+
+  /* Now that we've collected all the data, color convert & output it. */
+
+  for (pixel_rows_output = 0; pixel_rows_output < cinfo->image_height;
+       pixel_rows_output += rows_in_mem) {
+
+    /* realign the big buffers */
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray)
+	(fullsize_image[ci], pixel_rows_output, FALSE);
+    }
+
+    emit_1pass (cinfo,
+		(int) MIN(rows_in_mem, cinfo->image_height-pixel_rows_output),
+		fullsize_ptrs, color_data);
+  }
+
+  /* Release working memory */
+  free_sampimage(cinfo, color_data, (int) cinfo->color_out_comps,
+		 (long) rows_in_mem);
+  if (cinfo->quantize_colors)
+    (*cinfo->emethods->free_small_sarray)
+		(quantize_out, (long) rows_in_mem);
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    (*cinfo->emethods->free_big_sarray) (fullsize_image[ci]);
+  }
+  (*cinfo->emethods->free_small) ((void *) fullsize_image);
+  (*cinfo->emethods->free_small) ((void *) fullsize_ptrs);
+
+  /* Close up shop */
+  if (cinfo->quantize_colors)
+    (*cinfo->methods->color_quant_term) (cinfo);
+}
+
+#endif /* MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Decompression pipeline controller used for multiple-scan files
+ * with 2-pass color quantization.
+ */
+
+#ifdef MULTISCAN_FILES_SUPPORTED
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF void
+multi_2quant_dcontroller (decompress_info_ptr cinfo)
+{
+  ERREXIT(cinfo->emethods, "Not implemented yet");
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+#endif /* MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * The method selection routine for decompression pipeline controllers.
+ * Note that at this point we've already read the JPEG header and first SOS,
+ * so we can tell whether the input is one scan or not.
+ */
+
+GLOBAL void
+jseldpipeline (decompress_info_ptr cinfo)
+{
+  /* simplify subsequent tests on color quantization */
+  if (! cinfo->quantize_colors)
+    cinfo->two_pass_quantize = FALSE;
+  
+  if (cinfo->comps_in_scan == cinfo->num_components) {
+    /* It's a single-scan file */
+#ifdef QUANT_2PASS_SUPPORTED
+    if (cinfo->two_pass_quantize)
+      cinfo->methods->d_pipeline_controller = single_2quant_dcontroller;
+    else
+#endif
+      cinfo->methods->d_pipeline_controller = single_dcontroller;
+  } else {
+    /* It's a multiple-scan file */
+#ifdef MULTISCAN_FILES_SUPPORTED
+#ifdef QUANT_2PASS_SUPPORTED
+    if (cinfo->two_pass_quantize)
+      cinfo->methods->d_pipeline_controller = multi_2quant_dcontroller;
+    else
+#endif
+      cinfo->methods->d_pipeline_controller = multi_dcontroller;
+#else
+    ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
+#endif
+  }
+}
diff --git a/jdsample.c b/jdsample.c
new file mode 100644
index 0000000..15dbf4f
--- /dev/null
+++ b/jdsample.c
@@ -0,0 +1,133 @@
+/*
+ * jdsample.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains un-subsampling routines.
+ * These routines are invoked via the unsubsample and
+ * unsubsample_init/term methods.
+ */
+
+#include "jinclude.h"
+
+
+/*
+ * Initialize for un-subsampling a scan.
+ */
+
+METHODDEF void
+unsubsample_init (decompress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+/*
+ * Un-subsample pixel values of a single component.
+ * This version only handles integral sampling ratios.
+ */
+
+METHODDEF void
+unsubsample (decompress_info_ptr cinfo, int which_component,
+	     long input_cols, int input_rows,
+	     long output_cols, int output_rows,
+	     JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
+	     JSAMPARRAY output_data)
+{
+  jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
+  short h_expand, v_expand, h, v;
+  int inrow, outrow;
+  long incol;
+  JSAMPROW inptr, outptr;
+  JSAMPLE invalue;
+
+  /* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
+  if (input_rows != compptr->v_samp_factor ||
+      output_rows != cinfo->max_v_samp_factor ||
+      (input_cols % compptr->h_samp_factor) != 0 ||
+      (output_cols % cinfo->max_h_samp_factor) != 0 ||
+      output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor)
+    ERREXIT(cinfo->emethods, "Bogus unsubsample parameters");
+
+  h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
+  v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
+
+  outrow = 0;
+  for (inrow = 0; inrow < input_rows; inrow++) {
+    for (v = 0; v < v_expand; v++) {
+      inptr = input_data[inrow];
+      outptr = output_data[outrow++];
+      for (incol = 0; incol < input_cols; incol++) {
+	invalue = GETJSAMPLE(*inptr++);
+	for (h = 0; h < h_expand; h++) {
+	  *outptr++ = invalue;
+	}
+      }
+    }
+  }
+}
+
+
+/*
+ * Un-subsample pixel values of a single component.
+ * This version handles the special case of a full-size component.
+ */
+
+METHODDEF void
+fullsize_unsubsample (decompress_info_ptr cinfo, int which_component,
+		      long input_cols, int input_rows,
+		      long output_cols, int output_rows,
+		      JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
+		      JSAMPARRAY output_data)
+{
+  if (input_cols != output_cols || input_rows != output_rows) /* DEBUG */
+    ERREXIT(cinfo->emethods, "Pipeline controller messed up");
+
+  jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
+}
+
+
+
+/*
+ * Clean up after a scan.
+ */
+
+METHODDEF void
+unsubsample_term (decompress_info_ptr cinfo)
+{
+  /* no work for now */
+}
+
+
+
+/*
+ * The method selection routine for unsubsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL void
+jselunsubsample (decompress_info_ptr cinfo)
+{
+  short ci;
+  jpeg_component_info * compptr;
+
+  if (cinfo->CCIR601_sampling)
+    ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
+	compptr->v_samp_factor == cinfo->max_v_samp_factor)
+      cinfo->methods->unsubsample[ci] = fullsize_unsubsample;
+    else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
+	     (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
+      cinfo->methods->unsubsample[ci] = unsubsample;
+    else
+      ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
+  }
+
+  cinfo->methods->unsubsample_init = unsubsample_init;
+  cinfo->methods->unsubsample_term = unsubsample_term;
+}
diff --git a/jerror.c b/jerror.c
new file mode 100644
index 0000000..591b185
--- /dev/null
+++ b/jerror.c
@@ -0,0 +1,67 @@
+/*
+ * jerror.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains simple error-reporting and trace-message routines.
+ * These are suitable for Unix-like systems and others where writing to
+ * stderr is the right thing to do.  If the JPEG software is integrated
+ * into a larger application, you may well need to replace these.
+ *
+ * The error_exit() routine should not return to its caller.  Within a
+ * larger application, you might want to have it do a longjmp() to return
+ * control to the outer user interface routine.  This should work since
+ * the portable JPEG code doesn't use setjmp/longjmp.  However, this won't
+ * release allocated memory or close temp files --- some bookkeeping would
+ * need to be added to the memory manager module to make that work.
+ *
+ * These routines are used by both the compression and decompression code.
+ */
+
+#include "jinclude.h"
+#ifdef __STDC__
+#include <stdlib.h>		/* to declare exit() */
+#endif
+
+
+static external_methods_ptr methods; /* saved for access to message_parm */
+
+
+METHODDEF void
+trace_message (char *msgtext)
+{
+  fprintf(stderr, msgtext,
+	  methods->message_parm[0], methods->message_parm[1],
+	  methods->message_parm[2], methods->message_parm[3],
+	  methods->message_parm[4], methods->message_parm[5],
+	  methods->message_parm[6], methods->message_parm[7]);
+  fprintf(stderr, "\n");
+}
+
+
+METHODDEF void
+error_exit (char *msgtext)
+{
+  trace_message(msgtext);
+  exit(1);
+}
+
+
+/*
+ * The method selection routine for simple error handling.
+ * The system-dependent setup routine should call this routine
+ * to install the necessary method pointers in the supplied struct.
+ */
+
+GLOBAL void
+jselerror (external_methods_ptr emethods)
+{
+  methods = emethods;		/* save struct addr for msg parm access */
+
+  emethods->error_exit = error_exit;
+  emethods->trace_message = trace_message;
+
+  emethods->trace_level = 0;	/* default = no tracing */
+}
diff --git a/jfwddct.c b/jfwddct.c
new file mode 100644
index 0000000..58291ac
--- /dev/null
+++ b/jfwddct.c
@@ -0,0 +1,179 @@
+/*
+ * jfwddct.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the basic DCT (Discrete Cosine Transform)
+ * transformation subroutine.
+ *
+ * This implementation is based on Appendix A.2 of the book
+ * "Discrete Cosine Transform---Algorithms, Advantages, Applications"
+ * by K.R. Rao and P. Yip  (Academic Press, Inc, London, 1990).
+ * It uses scaled fixed-point arithmetic instead of floating point.
+ */
+
+#include "jinclude.h"
+
+
+/* The poop on this scaling stuff is as follows:
+ *
+ * Most of the numbers (after multiplication by the constants) are
+ * (logically) shifted left by LG2_DCT_SCALE. This is undone by UNFIXH
+ * before assignment to the output array. Note that we want an additional
+ * division by 2 on the output (required by the equations).
+ *
+ * If right shifts are unsigned, then there is a potential problem.
+ * However, shifting right by 16 and then assigning to a short
+ * (assuming short = 16 bits) will keep the sign right!!
+ *
+ * For other shifts,
+ *
+ *     ((x + (1 << 30)) >> shft) - (1 << (30 - shft))
+ *
+ * gives a nice right shift with sign (assuming no overflow). However, all the
+ * scaling is such that this isn't a problem. (Is this true?)
+ */
+
+
+#define ONE 1L			/* remove L if long > 32 bits */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define LG2_DCT_SCALE 15
+#define RIGHT_SHIFT(_x,_shft)   ((((_x) + (ONE << 30)) >> (_shft)) - (ONE << (30 - (_shft))))
+#else
+#define LG2_DCT_SCALE 16
+#define RIGHT_SHIFT(_x,_shft)   ((_x) >> (_shft))
+#endif
+
+#define DCT_SCALE (ONE << LG2_DCT_SCALE)
+
+#define LG2_OVERSCALE 2
+#define OVERSCALE (ONE << LG2_OVERSCALE)
+
+#define FIX(x)  ((INT32) ((x) * DCT_SCALE + 0.5))
+#define FIXO(x)  ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
+#define UNFIX(x)   RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
+#define UNFIXH(x)  RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
+#define UNFIXO(x)  RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)), LG2_DCT_SCALE-LG2_OVERSCALE)
+#define OVERSH(x)   ((x) << LG2_OVERSCALE)
+
+#define SIN_1_4 FIX(0.7071067811856476)
+#define COS_1_4 SIN_1_4
+
+#define SIN_1_8 FIX(0.3826834323650898)
+#define COS_1_8 FIX(0.9238795325112870)
+#define SIN_3_8 COS_1_8
+#define COS_3_8 SIN_1_8
+
+#define SIN_1_16 FIX(0.1950903220161282)
+#define COS_1_16 FIX(0.9807852804032300)
+#define SIN_7_16 COS_1_16
+#define COS_7_16 SIN_1_16
+
+#define SIN_3_16 FIX(0.5555702330196022)
+#define COS_3_16 FIX(0.8314696123025450)
+#define SIN_5_16 COS_3_16
+#define COS_5_16 SIN_3_16
+
+#define OSIN_1_4 FIXO(0.707106781185647)
+#define OCOS_1_4 OSIN_1_4
+
+#define OSIN_1_8 FIXO(0.3826834323650898)
+#define OCOS_1_8 FIXO(0.9238795325112870)
+#define OSIN_3_8 OCOS_1_8
+#define OCOS_3_8 OSIN_1_8
+
+#define OSIN_1_16 FIXO(0.1950903220161282)
+#define OCOS_1_16 FIXO(0.9807852804032300)
+#define OSIN_7_16 OCOS_1_16
+#define OCOS_7_16 OSIN_1_16
+
+#define OSIN_3_16 FIXO(0.5555702330196022)
+#define OCOS_3_16 FIXO(0.8314696123025450)
+#define OSIN_5_16 OCOS_3_16
+#define OCOS_5_16 OSIN_3_16
+
+
+INLINE
+LOCAL void
+fast_dct_8 (DCTELEM *in, int stride)
+{
+  /* tmp1x are new values of tmpx -- flashy register colourers
+   * should be able to do this lot very well
+   */
+  INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17;
+  INT32 tmp25, tmp26;
+  INT32 in0, in1, in2, in3, in4, in5, in6, in7;
+  
+  in0 = in[       0];
+  in1 = in[stride  ];
+  in2 = in[stride*2];
+  in3 = in[stride*3];
+  in4 = in[stride*4];
+  in5 = in[stride*5];
+  in6 = in[stride*6];
+  in7 = in[stride*7];
+  
+  tmp0 = in7 + in0;
+  tmp1 = in6 + in1;
+  tmp2 = in5 + in2;
+  tmp3 = in4 + in3;
+  tmp4 = in3 - in4;
+  tmp5 = in2 - in5;
+  tmp6 = in1 - in6;
+  tmp7 = in0 - in7;
+  
+  tmp10 = tmp3 + tmp0 ;
+  tmp11 = tmp2 + tmp1 ;
+  tmp12 = tmp1 - tmp2 ;
+  tmp13 = tmp0 - tmp3 ;
+  
+  /* Now using tmp10, tmp11, tmp12, tmp13 */
+  
+  in[       0] = UNFIXH((tmp10 + tmp11) * SIN_1_4);
+  in[stride*4] = UNFIXH((tmp10 - tmp11) * COS_1_4);
+  
+  in[stride*2] = UNFIXH(tmp13*COS_1_8 + tmp12*SIN_1_8);
+  in[stride*6] = UNFIXH(tmp13*SIN_1_8 - tmp12*COS_1_8);
+  
+  tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4);
+  tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4);
+  
+  /* Now using tmp10, tmp11, tmp13, tmp14, tmp15, tmp16 */
+  
+  tmp14 = OVERSH(tmp4) + tmp15;
+  tmp25 = OVERSH(tmp4) - tmp15;
+  tmp26 = OVERSH(tmp7) - tmp16;
+  tmp17 = OVERSH(tmp7) + tmp16;
+  
+  /* These are now overscaled by OVERSCALE */
+  
+  /* tmp10, tmp11, tmp12, tmp13, tmp14, tmp25, tmp26, tmp17 */
+  
+  in[stride  ] = UNFIXH(tmp17*OCOS_1_16 + tmp14*OSIN_1_16);
+  in[stride*7] = UNFIXH(tmp17*OCOS_7_16 - tmp14*OSIN_7_16);
+  in[stride*5] = UNFIXH(tmp26*OCOS_5_16 + tmp25*OSIN_5_16);
+  in[stride*3] = UNFIXH(tmp26*OCOS_3_16 - tmp25*OSIN_3_16);
+}
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ *
+ * Note that this code is specialized to the case DCTSIZE = 8.
+ */
+
+GLOBAL void
+j_fwd_dct (DCTBLOCK data)
+{
+  int i;
+  
+  for (i = 0; i < DCTSIZE; i++)
+    fast_dct_8(data+i*DCTSIZE, 1);
+
+  for (i = 0; i < DCTSIZE; i++)
+    fast_dct_8(data+i, DCTSIZE);
+}
diff --git a/jinclude.h b/jinclude.h
new file mode 100644
index 0000000..ec7a7e8
--- /dev/null
+++ b/jinclude.h
@@ -0,0 +1,73 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This is the central file that's #include'd by all the JPEG .c files.
+ * Its purpose is to provide a single place to fix any problems with
+ * including the wrong system include files.
+ * You can edit these declarations if you use a system with nonstandard
+ * system include files.
+ */
+
+
+/*
+ * <stdio.h> is included to get the FILE typedef and NULL macro.
+ * Note that the core portable-JPEG files do not actually do any I/O
+ * using the stdio library; only the user interface, error handler,
+ * and file reading/writing modules invoke any stdio functions.
+ * (Well, we did cheat a bit in jvirtmem.c, but only if MEM_STATS is defined.)
+ */
+
+#include <stdio.h>
+
+/*
+ * We need the size_t typedef, which defines the parameter type of malloc().
+ * In an ANSI-conforming implementation this is provided by <stdio.h>,
+ * but on non-ANSI systems it's more likely to be in <sys/types.h>.
+ */
+
+#ifndef __STDC__		/* shouldn't need this if __STDC__ */
+#include <sys/types.h>
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof().  However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long.  To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object)	((size_t) sizeof(object))
+
+/*
+ * We need the memcpy() and strcmp() functions, plus memory zeroing.
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Insert casts in these macros if not!
+ */
+
+#ifdef __STDC__
+#include <string.h>
+#define MEMZERO(voidptr,size)	memset((voidptr), 0, (size))
+#else /* not STDC */
+#ifdef BSD
+#include <strings.h>
+#define MEMZERO(voidptr,size)	bzero((voidptr), (size))
+#define memcpy(dest,src,size)	bcopy((src), (dest), (size))
+#else /* not BSD, assume Sys V or compatible */
+#include <string.h>
+#define MEMZERO(voidptr,size)	memset((voidptr), 0, (size))
+#endif /* BSD */
+#endif /* STDC */
+
+
+/* Now include the portable JPEG definition files. */
+
+#include "jconfig.h"
+
+#include "jpegdata.h"
diff --git a/jpegdata.h b/jpegdata.h
new file mode 100644
index 0000000..3e4d753
--- /dev/null
+++ b/jpegdata.h
@@ -0,0 +1,812 @@
+/*
+ * jpegdata.h
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines shared data structures for the various JPEG modules.
+ */
+
+
+/*
+ * You might need to change some of the following declarations if you are
+ * using the JPEG software within a surrounding application program
+ * or porting it to an unusual system.
+ */
+
+
+/* If the source or destination of image data is not to be stdio streams,
+ * these types may need work.  You can replace them with some kind of
+ * pointer or indicator that is useful to you, or just ignore 'em.
+ * Note that the user interface and the various jrdxxx/jwrxxx modules
+ * will also need work for non-stdio input/output.
+ */
+
+typedef FILE * JFILEREF;	/* source or dest of JPEG-compressed data */
+
+typedef FILE * IFILEREF;	/* source or dest of non-JPEG image data */
+
+
+/* These defines are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions,
+ * as is shown below for use with C++.  Another application would be to make
+ * all functions global for use with code profilers that require it.
+ * NOTE: the C++ test does the right thing if you are reading this include
+ * file in a C++ application to link to JPEG code that's been compiled with a
+ * regular C compiler.  I'm not sure it works if you try to compile the JPEG
+ * code with C++.
+ */
+
+#define METHODDEF static	/* a function called through method pointers */
+#define LOCAL	  static	/* a function used only in its module */
+#define GLOBAL			/* a function referenced thru EXTERNs */
+#ifdef __cplusplus
+#define EXTERN	  extern "C"	/* a reference to a GLOBAL function */
+#else
+#define EXTERN	  extern	/* a reference to a GLOBAL function */
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines.  Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed.  In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifdef NEED_FAR_POINTERS
+#define FAR  far
+#else
+#define FAR
+#endif
+
+
+
+/* The remaining declarations are not system-dependent, we hope. */
+
+
+/*
+ * NOTE: if you have an ancient, strict-K&R C compiler, it may choke on the
+ * similarly-named fields in compress_info_struct and decompress_info_struct.
+ * If this happens, you can get around it by rearranging the two structs so
+ * that the similarly-named fields appear first and in the same order in
+ * each struct.  Since such compilers are now pretty rare, we haven't done
+ * this in the portable code, preferring to maintain a logical ordering.
+ */
+
+
+
+/* This macro is used to declare a "method", that is, a function pointer. */
+/* We want to supply prototype parameters if the compiler can cope. */
+/* Note that the arglist parameter must be parenthesized! */
+
+#ifdef PROTO
+#define METHOD(type,methodname,arglist)  type (*methodname) arglist
+#else
+#define METHOD(type,methodname,arglist)  type (*methodname) ()
+#endif
+
+/* Forward references to lists of method pointers */
+typedef struct external_methods_struct * external_methods_ptr;
+typedef struct compress_methods_struct * compress_methods_ptr;
+typedef struct decompress_methods_struct * decompress_methods_ptr;
+
+
+/* Data structures for images containing either samples or coefficients. */
+/* Note that the topmost (leftmost) index is always color component. */
+/* On 80x86 machines, the image arrays are too big for near pointers, */
+/* but the pointer arrays can fit in near memory. */
+
+typedef JSAMPLE FAR *JSAMPROW;	/* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY;	/* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE;	/* a 3-D sample array: top index is color */
+
+
+#define DCTSIZE		8	/* The basic DCT block is 8x8 samples */
+#define DCTSIZE2	64	/* DCTSIZE squared; # of elements in a block */
+
+typedef JCOEF JBLOCK[DCTSIZE2];	/* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW;	/* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY;		/* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE;	/* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR;	/* useful in a couple of places */
+
+
+/* The input and output data of the DCT transform subroutines are of
+ * the following type, which need not be the same as JCOEF.
+ * For example, on a machine with fast floating point, it might make sense
+ * to recode the DCT routines to use floating point; then DCTELEM would be
+ * 'float' or 'double'.
+ */
+
+typedef JCOEF DCTELEM;
+typedef DCTELEM DCTBLOCK[DCTSIZE2];
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+typedef enum {			/* defines known color spaces */
+	CS_UNKNOWN,		/* error/unspecified */
+	CS_GRAYSCALE,		/* monochrome (only 1 component) */
+	CS_RGB,			/* red/green/blue */
+	CS_YCbCr,		/* Y/Cb/Cr (also known as YUV) */
+	CS_YIQ,			/* Y/I/Q */
+	CS_CMYK			/* C/M/Y/K */
+} COLOR_SPACE;
+
+
+typedef struct {		/* Basic info about one component */
+  /* These values are fixed over the whole image */
+  /* For compression, they must be supplied by the user interface; */
+  /* for decompression, they are read from the SOF marker. */
+	short component_id;	/* identifier for this component (0..255) */
+	short component_index;	/* its index in SOF or cinfo->comp_info[] */
+	short h_samp_factor;	/* horizontal sampling factor (1..4) */
+	short v_samp_factor;	/* vertical sampling factor (1..4) */
+	short quant_tbl_no;	/* quantization table selector (0..3) */
+  /* These values may vary between scans */
+  /* For compression, they must be supplied by the user interface; */
+  /* for decompression, they are read from the SOS marker. */
+	short dc_tbl_no;	/* DC entropy table selector (0..3) */
+	short ac_tbl_no;	/* AC entropy table selector (0..3) */
+  /* These values are computed during compression or decompression startup */
+	long true_comp_width;	/* component's image width in samples */
+	long true_comp_height;	/* component's image height in samples */
+	/* the above are the logical dimensions of the subsampled image */
+  /* These values are computed before starting a scan of the component */
+	short MCU_width;	/* number of blocks per MCU, horizontally */
+	short MCU_height;	/* number of blocks per MCU, vertically */
+	short MCU_blocks;	/* MCU_width * MCU_height */
+	long subsampled_width;	/* image width in samples, after expansion */
+	long subsampled_height;	/* image height in samples, after expansion */
+	/* the above are the true_comp_xxx values rounded up to multiples of */
+	/* the MCU dimensions; these are the working dimensions of the array */
+	/* as it is passed through the DCT or IDCT step.  NOTE: these values */
+	/* differ depending on whether the component is interleaved or not!! */
+} jpeg_component_info;
+
+
+/* DCT coefficient quantization tables.
+ * For 8-bit precision, 'INT16' should be good enough for quantization values;
+ * for more precision, we go for the full 16 bits.  'INT16' provides a useful
+ * speedup on many machines (multiplication & division of JCOEFs by
+ * quantization values is a significant chunk of the runtime).
+ * Note: the values in a QUANT_TBL are always given in zigzag order.
+ */
+#ifdef EIGHT_BIT_SAMPLES
+typedef INT16 QUANT_VAL;	/* element of a quantization table */
+#else
+typedef UINT16 QUANT_VAL;	/* element of a quantization table */
+#endif
+typedef QUANT_VAL QUANT_TBL[DCTSIZE2];	/* A quantization table */
+typedef QUANT_VAL * QUANT_TBL_PTR;	/* pointer to same */
+
+
+typedef struct {		/* A Huffman coding table */
+  /* These two fields directly represent the contents of a JPEG DHT marker */
+	UINT8 bits[17];		/* bits[k] = # of symbols with codes of */
+				/* length k bits; bits[0] is unused */
+	UINT8 huffval[256];	/* The symbols, in order of incr code length */
+  /* This field is used only during compression.  It's initialized FALSE when
+   * the table is created, and set TRUE when it's been output to the file.
+   */
+	boolean sent_table;	/* TRUE when table has been output */
+  /* The remaining fields are computed from the above to allow more efficient
+   * coding and decoding.  These fields should be considered private to the
+   * Huffman compression & decompression modules.
+   */
+	UINT16 ehufco[256];	/* code for each symbol */
+	char ehufsi[256];	/* length of code for each symbol */
+	UINT16 mincode[17];	/* smallest code of length k */
+	INT32 maxcode[17];	/* largest code of length k (-1 if none) */
+	short valptr[17];	/* huffval[] index of 1st symbol of length k */
+} HUFF_TBL;
+
+
+#define NUM_QUANT_TBLS      4	/* quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS       4	/* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS      16	/* arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN   4	/* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR     4	/* JPEG limit on sampling factors */
+#define MAX_BLOCKS_IN_MCU   10	/* JPEG limit on # of blocks in an MCU */
+
+
+/* Working data for compression */
+
+struct compress_info_struct {
+/*
+ * All of these fields shall be established by the user interface before
+ * calling jpeg_compress, or by the input_init or c_ui_method_selection
+ * methods.
+ * Most parameters can be set to reasonable defaults by j_default_compression.
+ * Note that the UI must supply the storage for the main methods struct,
+ * though it sets only a few of the methods there.
+ */
+	compress_methods_ptr methods; /* Points to list of methods to use */
+
+	external_methods_ptr emethods; /* Points to list of methods to use */
+
+	IFILEREF input_file;	/* tells input routines where to read image */
+	JFILEREF output_file;	/* tells output routines where to write JPEG */
+
+	long image_width;	/* input image width */
+	long image_height;	/* input image height */
+	short input_components;	/* # of color components in input image */
+
+	short data_precision;	/* bits of precision in image data */
+
+	COLOR_SPACE in_color_space; /* colorspace of input file */
+	COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
+
+	double input_gamma;	/* image gamma of input file */
+
+	boolean write_JFIF_header; /* should a JFIF marker be written? */
+	/* These three values are not used by the JPEG code, only copied */
+	/* into the JFIF APP0 marker.  density_unit can be 0 for unknown, */
+	/* 1 for dots/inch, or 2 for dots/cm.  Note that the pixel aspect */
+	/* ratio is defined by X_density/Y_density even when density_unit=0. */
+	UINT8 density_unit;	/* JFIF code for pixel size units */
+	UINT16 X_density;	/* Horizontal pixel density */
+	UINT16 Y_density;	/* Vertical pixel density */
+
+	short num_components;	/* # of color components in JPEG image */
+	jpeg_component_info * comp_info;
+	/* comp_info[i] describes component that appears i'th in SOF */
+
+	QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
+	/* ptrs to coefficient quantization tables, or NULL if not defined */
+
+	HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+	HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+	/* ptrs to Huffman coding tables, or NULL if not defined */
+
+	UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arithmetic-coding tables */
+	UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arithmetic-coding tables */
+	UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arithmetic-coding tables */
+
+	boolean arith_code;	/* TRUE=arithmetic coding, FALSE=Huffman */
+	boolean interleave;	/* TRUE=interleaved output, FALSE=not */
+	boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
+	boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+
+	UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
+
+/*
+ * These fields are computed during jpeg_compress startup
+ */
+	short max_h_samp_factor; /* largest h_samp_factor */
+	short max_v_samp_factor; /* largest v_samp_factor */
+
+/*
+ * These fields are valid during any one scan
+ */
+	short comps_in_scan;	/* # of JPEG components output this time */
+	jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+	/* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+	long MCUs_per_row;	/* # of MCUs across the image */
+	long MCU_rows_in_scan;	/* # of MCU rows in the image */
+
+	short blocks_in_MCU;	/* # of DCT blocks per MCU */
+	short MCU_membership[MAX_BLOCKS_IN_MCU];
+	/* MCU_membership[i] is index in cur_comp_info of component owning */
+	/* i'th block in an MCU */
+
+	/* these fields are private data for the entropy encoder */
+	JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
+	JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
+	UINT16 restarts_to_go;	/* MDUs left in this restart interval */
+	short next_restart_num;	/* # of next RSTn marker (0..7) */
+};
+
+typedef struct compress_info_struct * compress_info_ptr;
+
+
+/* Working data for decompression */
+
+struct decompress_info_struct {
+/*
+ * These fields shall be established by the user interface before
+ * calling jpeg_decompress.  Note that the UI must supply the storage for
+ * the main methods struct, though it sets only a few of the methods there.
+ */
+	decompress_methods_ptr methods; /* Points to list of methods to use */
+
+	external_methods_ptr emethods; /* Points to list of methods to use */
+
+	JFILEREF input_file;	/* tells input routines where to read JPEG */
+	IFILEREF output_file;	/* tells output routines where to write image */
+
+	/* these can be set at d_ui_method_selection time: */
+
+	COLOR_SPACE out_color_space; /* colorspace of output */
+
+	double output_gamma;	/* image gamma wanted in output */
+
+	boolean quantize_colors; /* T if output is a colormapped format */
+	/* the following are ignored if not quantize_colors: */
+	boolean two_pass_quantize;	/* use two-pass color quantization? */
+	boolean use_dithering;		/* want color dithering? */
+	int desired_number_of_colors;	/* number of colors to use */
+
+	boolean do_block_smoothing; /* T = apply cross-block smoothing */
+	boolean do_pixel_smoothing; /* T = apply post-subsampling smoothing */
+
+/*
+ * These fields are used for efficient buffering of data between read_jpeg_data
+ * and the entropy decoding object.  By using a shared buffer, we avoid copying
+ * data and eliminate the need for an "unget" operation at the end of a scan.
+ * The actual source of the data is known only to read_jpeg_data; see the
+ * JGETC macro, below.
+ * Note: the user interface is expected to allocate the input_buffer and
+ * initialize bytes_in_buffer to 0.  Also, for JFIF/raw-JPEG input, the UI
+ * actually supplies the read_jpeg_data method.
+ */
+	char * input_buffer;	/* start of buffer (private to input code) */
+	char * next_input_byte;	/* => next byte to read from buffer */
+	int bytes_in_buffer;	/* # of bytes remaining in buffer */
+
+/*
+ * These fields are set by read_file_header or read_scan_header
+ */
+	long image_width;	/* overall image width */
+	long image_height;	/* overall image height */
+
+	short data_precision;	/* bits of precision in image data */
+
+	COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
+
+        /* These three values are not used by the JPEG code, merely copied */
+	/* from the JFIF APP0 marker (if any). */
+	UINT8 density_unit;	/* JFIF code for pixel size units */
+	UINT16 X_density;	/* Horizontal pixel density */
+	UINT16 Y_density;	/* Vertical pixel density */
+
+	short num_components;	/* # of color components in JPEG image */
+	jpeg_component_info * comp_info;
+	/* comp_info[i] describes component that appears i'th in SOF */
+
+	QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
+	/* ptrs to coefficient quantization tables, or NULL if not defined */
+
+	HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+	HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+	/* ptrs to Huffman coding tables, or NULL if not defined */
+
+	UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+	UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+	UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+	boolean arith_code;	/* TRUE=arithmetic coding, FALSE=Huffman */
+	boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+
+	UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
+
+/*
+ * These fields are computed during jpeg_decompress startup
+ */
+	short max_h_samp_factor; /* largest h_samp_factor */
+	short max_v_samp_factor; /* largest v_samp_factor */
+
+	short color_out_comps;	/* # of color components output by color_convert */
+				/* (need not match num_components) */
+	short final_out_comps;	/* # of color components in output image */
+	/* (1 when quantizing colors, else same as color_out_comps) */
+
+/*
+ * These fields are valid during any one scan
+ */
+	short comps_in_scan;	/* # of JPEG components input this time */
+	jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+	/* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+	long MCUs_per_row;	/* # of MCUs across the image */
+	long MCU_rows_in_scan;	/* # of MCU rows in the image */
+
+	short blocks_in_MCU;	/* # of DCT blocks per MCU */
+	short MCU_membership[MAX_BLOCKS_IN_MCU];
+	/* MCU_membership[i] is index in cur_comp_info of component owning */
+	/* i'th block in an MCU */
+
+	/* these fields are private data for the entropy encoder */
+	JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
+	JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
+	UINT16 restarts_to_go;	/* MDUs left in this restart interval */
+	short next_restart_num;	/* # of next RSTn marker (0..7) */
+};
+
+typedef struct decompress_info_struct * decompress_info_ptr;
+
+
+/* Macros for reading data from the decompression input buffer */
+
+#ifdef CHAR_IS_UNSIGNED
+#define JGETC(cinfo)	( --(cinfo)->bytes_in_buffer < 0 ? \
+			 (*(cinfo)->methods->read_jpeg_data) (cinfo) : \
+			 (int) *(cinfo)->next_input_byte++ )
+#else
+#define JGETC(cinfo)	( --(cinfo)->bytes_in_buffer < 0 ? \
+			 (*(cinfo)->methods->read_jpeg_data) (cinfo) : \
+			 (int) (*(cinfo)->next_input_byte++) & 0xFF )
+#endif
+
+#define JUNGETC(ch,cinfo)  ((cinfo)->bytes_in_buffer++, \
+			    *(--((cinfo)->next_input_byte)) = (ch))
+
+#define MIN_UNGET	2	/* may always do at least 2 JUNGETCs */
+
+
+/* A virtual image has a control block whose contents are private to the
+ * memory manager module (and may differ between managers).  The rest of the
+ * code only refers to virtual images by these pointer types.
+ */
+
+typedef struct big_sarray_control * big_sarray_ptr;
+typedef struct big_barray_control * big_barray_ptr;
+
+
+/* Method types that need typedefs */
+
+typedef METHOD(void, MCU_output_method_ptr, (compress_info_ptr cinfo,
+					     JBLOCK *MCU_data));
+typedef METHOD(void, MCU_output_caller_ptr, (compress_info_ptr cinfo,
+					     MCU_output_method_ptr output_method));
+typedef METHOD(void, subsample_ptr, (compress_info_ptr cinfo,
+				     int which_component,
+				     long input_cols, int input_rows,
+				     long output_cols, int output_rows,
+				     JSAMPARRAY above,
+				     JSAMPARRAY input_data,
+				     JSAMPARRAY below,
+				     JSAMPARRAY output_data));
+typedef METHOD(void, unsubsample_ptr, (decompress_info_ptr cinfo,
+				       int which_component,
+				       long input_cols, int input_rows,
+				       long output_cols, int output_rows,
+				       JSAMPARRAY above,
+				       JSAMPARRAY input_data,
+				       JSAMPARRAY below,
+				       JSAMPARRAY output_data));
+typedef METHOD(void, quantize_method_ptr, (decompress_info_ptr cinfo,
+					   int num_rows,
+					   JSAMPIMAGE input_data,
+					   JSAMPARRAY output_workspace));
+typedef METHOD(void, quantize_caller_ptr, (decompress_info_ptr cinfo,
+					   quantize_method_ptr quantize_method));
+
+
+/* These structs contain function pointers for the various JPEG methods. */
+
+/* Routines to be provided by the surrounding application, rather than the
+ * portable JPEG code proper.  These are the same for compression and
+ * decompression.
+ */
+
+struct external_methods_struct {
+	/* User interface: error exit and trace message routines */
+	/* NOTE: the string msgtext parameters will eventually be replaced */
+	/* by an enumerated-type code so that non-English error messages */
+	/* can be substituted easily.  This will not be done until all the */
+	/* code is in place, so that we know what messages are needed. */
+	METHOD(void, error_exit, (char *msgtext));
+	METHOD(void, trace_message, (char *msgtext));
+
+	/* Working data for error/trace facility */
+	/* See macros below for the usage of these variables */
+	int trace_level;	/* level of detail of tracing messages */
+	/* Use level 0 for unsuppressable messages (nonfatal errors) */
+	/* Use levels 1, 2, 3 for successively more detailed trace options */
+
+	int message_parm[8];	/* store numeric parms for messages here */
+
+	/* Memory management */
+	/* NB: alloc routines never return NULL. They exit to */
+	/* error_exit if not successful. */
+	METHOD(void *, alloc_small, (size_t sizeofobject));
+	METHOD(void, free_small, (void *ptr));
+#ifdef NEED_FAR_POINTERS	/* routines for getting far-heap space */
+	METHOD(void FAR *, alloc_medium, (size_t sizeofobject));
+	METHOD(void, free_medium, (void FAR *ptr));
+#else
+#define alloc_medium alloc_small
+#define free_medium  free_small
+#endif
+	METHOD(JSAMPARRAY, alloc_small_sarray, (long samplesperrow,
+						long numrows));
+	METHOD(void, free_small_sarray, (JSAMPARRAY ptr,
+					 long numrows));
+	METHOD(JBLOCKARRAY, alloc_small_barray, (long blocksperrow,
+						 long numrows));
+	METHOD(void, free_small_barray, (JBLOCKARRAY ptr,
+					 long numrows));
+	METHOD(big_sarray_ptr, request_big_sarray, (long samplesperrow,
+						    long numrows,
+						    long unitheight));
+	METHOD(big_barray_ptr, request_big_barray, (long blocksperrow,
+						    long numrows,
+						    long unitheight));
+	METHOD(void, alloc_big_arrays, (long extra_small_samples,
+					long extra_small_blocks,
+					long extra_medium_space));
+	METHOD(JSAMPARRAY, access_big_sarray, (big_sarray_ptr ptr,
+					       long start_row,
+					       boolean writable));
+	METHOD(JBLOCKARRAY, access_big_barray, (big_barray_ptr ptr,
+						long start_row,
+						boolean writable));
+	METHOD(void, free_big_sarray, (big_sarray_ptr ptr));
+	METHOD(void, free_big_barray, (big_barray_ptr ptr));
+};
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is generally cinfo->emethods */
+
+#define ERREXIT(emeth,msg)		((*(emeth)->error_exit) (msg))
+#define ERREXIT1(emeth,msg,p1)		((emeth)->message_parm[0] = (p1), \
+					 (*(emeth)->error_exit) (msg))
+#define ERREXIT2(emeth,msg,p1,p2)	((emeth)->message_parm[0] = (p1), \
+					 (emeth)->message_parm[1] = (p2), \
+					 (*(emeth)->error_exit) (msg))
+#define ERREXIT3(emeth,msg,p1,p2,p3)	((emeth)->message_parm[0] = (p1), \
+					 (emeth)->message_parm[1] = (p2), \
+					 (emeth)->message_parm[2] = (p3), \
+					 (*(emeth)->error_exit) (msg))
+#define ERREXIT4(emeth,msg,p1,p2,p3,p4) ((emeth)->message_parm[0] = (p1), \
+					 (emeth)->message_parm[1] = (p2), \
+					 (emeth)->message_parm[2] = (p3), \
+					 (emeth)->message_parm[3] = (p4), \
+					 (*(emeth)->error_exit) (msg))
+
+#define TRACEMS(emeth,lvl,msg)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((*(emeth)->trace_message) (msg), 0) : 0)
+#define TRACEMS1(emeth,lvl,msg,p1)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((emeth)->message_parm[0] = (p1), \
+    (*(emeth)->trace_message) (msg), 0) : 0)
+#define TRACEMS2(emeth,lvl,msg,p1,p2)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((emeth)->message_parm[0] = (p1), \
+    (emeth)->message_parm[1] = (p2), \
+    (*(emeth)->trace_message) (msg), 0) : 0)
+#define TRACEMS3(emeth,lvl,msg,p1,p2,p3)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((emeth)->message_parm[0] = (p1), \
+    (emeth)->message_parm[1] = (p2), \
+    (emeth)->message_parm[2] = (p3), \
+    (*(emeth)->trace_message) (msg), 0) : 0)
+#define TRACEMS4(emeth,lvl,msg,p1,p2,p3,p4)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((emeth)->message_parm[0] = (p1), \
+    (emeth)->message_parm[1] = (p2), \
+    (emeth)->message_parm[2] = (p3), \
+    (emeth)->message_parm[3] = (p4), \
+    (*(emeth)->trace_message) (msg), 0) : 0)
+#define TRACEMS8(emeth,lvl,msg,p1,p2,p3,p4,p5,p6,p7,p8)    \
+  ( (emeth)->trace_level >= (lvl) ? \
+   ((emeth)->message_parm[0] = (p1), \
+    (emeth)->message_parm[1] = (p2), \
+    (emeth)->message_parm[2] = (p3), \
+    (emeth)->message_parm[3] = (p4), \
+    (emeth)->message_parm[4] = (p5), \
+    (emeth)->message_parm[5] = (p6), \
+    (emeth)->message_parm[6] = (p7), \
+    (emeth)->message_parm[7] = (p8), \
+    (*(emeth)->trace_message) (msg), 0) : 0)
+
+
+/* Methods used during JPEG compression. */
+
+struct compress_methods_struct {
+	/* Hook for user interface to get control after input_init */
+	METHOD(void, c_ui_method_selection, (compress_info_ptr cinfo));
+	/* Input image reading & conversion to standard form */
+	METHOD(void, input_init, (compress_info_ptr cinfo));
+	METHOD(void, get_input_row, (compress_info_ptr cinfo,
+				     JSAMPARRAY pixel_row));
+	METHOD(void, input_term, (compress_info_ptr cinfo));
+	/* Gamma and color space conversion */
+	METHOD(void, colorin_init, (compress_info_ptr cinfo));
+	METHOD(void, get_sample_rows, (compress_info_ptr cinfo,
+				       int rows_to_read,
+				       JSAMPIMAGE image_data));
+	METHOD(void, colorin_term, (compress_info_ptr cinfo));
+	/* Expand picture data at edges */
+	METHOD(void, edge_expand, (compress_info_ptr cinfo,
+				   long input_cols, int input_rows,
+				   long output_cols, int output_rows,
+				   JSAMPIMAGE image_data));
+	/* Subsample pixel values of a single component */
+	/* There can be a different subsample method for each component */
+	METHOD(void, subsample_init, (compress_info_ptr cinfo));
+	subsample_ptr subsample[MAX_COMPS_IN_SCAN];
+	METHOD(void, subsample_term, (compress_info_ptr cinfo));
+	/* Extract samples in MCU order, process & hand off to output_method */
+	/* The input is always exactly N MCU rows worth of data */
+	METHOD(void, extract_init, (compress_info_ptr cinfo));
+	METHOD(void, extract_MCUs, (compress_info_ptr cinfo,
+				    JSAMPIMAGE image_data,
+				    int num_mcu_rows,
+				    MCU_output_method_ptr output_method));
+	METHOD(void, extract_term, (compress_info_ptr cinfo));
+	/* Entropy encoding parameter optimization */
+	METHOD(void, entropy_optimize, (compress_info_ptr cinfo,
+					MCU_output_caller_ptr source_method));
+	/* Entropy encoding */
+	METHOD(void, entropy_encoder_init, (compress_info_ptr cinfo));
+	METHOD(void, entropy_encode, (compress_info_ptr cinfo,
+				      JBLOCK *MCU_data));
+	METHOD(void, entropy_encoder_term, (compress_info_ptr cinfo));
+	/* JPEG file header construction */
+	METHOD(void, write_file_header, (compress_info_ptr cinfo));
+	METHOD(void, write_scan_header, (compress_info_ptr cinfo));
+	METHOD(void, write_jpeg_data, (compress_info_ptr cinfo,
+				       char *dataptr,
+				       int datacount));
+	METHOD(void, write_scan_trailer, (compress_info_ptr cinfo));
+	METHOD(void, write_file_trailer, (compress_info_ptr cinfo));
+	/* Pipeline control */
+	METHOD(void, c_pipeline_controller, (compress_info_ptr cinfo));
+	METHOD(void, entropy_output, (compress_info_ptr cinfo,
+				      char *dataptr,
+				      int datacount));
+	/* Overall control */
+	METHOD(void, c_per_scan_method_selection, (compress_info_ptr cinfo));
+};
+
+/* Methods used during JPEG decompression. */
+
+struct decompress_methods_struct {
+	/* Hook for user interface to get control after reading file header */
+	METHOD(void, d_ui_method_selection, (decompress_info_ptr cinfo));
+	/* JPEG file scanning */
+	/* Note: user interface supplies read_jpeg_data for JFIF/raw-JPEG
+	 * reading.  For file formats that require random access (eg, TIFF)
+	 * the JPEG file header module will override the UI read_jpeg_data.
+	 */
+	METHOD(void, read_file_header, (decompress_info_ptr cinfo));
+	METHOD(boolean, read_scan_header, (decompress_info_ptr cinfo));
+	METHOD(int, read_jpeg_data, (decompress_info_ptr cinfo));
+	METHOD(void, read_scan_trailer, (decompress_info_ptr cinfo));
+	METHOD(void, read_file_trailer, (decompress_info_ptr cinfo));
+	/* Entropy decoding */
+	METHOD(void, entropy_decoder_init, (decompress_info_ptr cinfo));
+	METHOD(void, entropy_decode, (decompress_info_ptr cinfo,
+				      JBLOCK *MCU_data));
+	METHOD(void, entropy_decoder_term, (decompress_info_ptr cinfo));
+	/* MCU disassembly: fetch MCUs from entropy_decode, build coef array */
+	METHOD(void, disassemble_init, (decompress_info_ptr cinfo));
+	METHOD(void, disassemble_MCU, (decompress_info_ptr cinfo,
+				       JBLOCKIMAGE image_data));
+	METHOD(void, disassemble_term, (decompress_info_ptr cinfo));
+	/* Cross-block smoothing */
+	METHOD(void, smooth_coefficients, (decompress_info_ptr cinfo,
+					   jpeg_component_info *compptr,
+					   JBLOCKROW above,
+					   JBLOCKROW currow,
+					   JBLOCKROW below,
+					   JBLOCKROW output));
+	/* Un-subsample pixel values of a single component */
+	/* There can be a different unsubsample method for each component */
+	METHOD(void, unsubsample_init, (decompress_info_ptr cinfo));
+	unsubsample_ptr unsubsample[MAX_COMPS_IN_SCAN];
+	METHOD(void, unsubsample_term, (decompress_info_ptr cinfo));
+	/* Gamma and color space conversion */
+	METHOD(void, colorout_init, (decompress_info_ptr cinfo));
+	METHOD(void, color_convert, (decompress_info_ptr cinfo,
+				     int num_rows,
+				     JSAMPIMAGE input_data,
+				     JSAMPIMAGE output_data));
+	METHOD(void, colorout_term, (decompress_info_ptr cinfo));
+	/* Color quantization */
+	METHOD(void, color_quant_init, (decompress_info_ptr cinfo));
+	METHOD(void, color_quantize, (decompress_info_ptr cinfo,
+				      int num_rows,
+				      JSAMPIMAGE input_data,
+				      JSAMPARRAY output_data));
+	METHOD(void, color_quant_prescan, (decompress_info_ptr cinfo,
+					   int num_rows,
+					   JSAMPIMAGE image_data));
+	METHOD(void, color_quant_doit, (decompress_info_ptr cinfo,
+					quantize_caller_ptr source_method));
+	METHOD(void, color_quant_term, (decompress_info_ptr cinfo));
+	/* Output image writing */
+	METHOD(void, output_init, (decompress_info_ptr cinfo));
+	METHOD(void, put_color_map, (decompress_info_ptr cinfo,
+				     int num_colors, JSAMPARRAY colormap));
+	METHOD(void, put_pixel_rows, (decompress_info_ptr cinfo,
+				      int num_rows,
+				      JSAMPIMAGE pixel_data));
+	METHOD(void, output_term, (decompress_info_ptr cinfo));
+	/* Pipeline control */
+	METHOD(void, d_pipeline_controller, (decompress_info_ptr cinfo));
+	/* Overall control */
+	METHOD(void, d_per_scan_method_selection, (decompress_info_ptr cinfo));
+};
+
+
+/* External declarations for routines that aren't called via method ptrs. */
+/* Note: use "j" as first char of names to minimize namespace pollution. */
+/* The PP macro hides prototype parameters from compilers that can't cope. */
+
+#ifdef PROTO
+#define PP(arglist)	arglist
+#else
+#define PP(arglist)	()
+#endif
+
+
+/* main entry for compression */
+EXTERN void jpeg_compress PP((compress_info_ptr cinfo));
+/* default parameter setup for compression */
+EXTERN void j_default_compression PP((compress_info_ptr cinfo, int quality));
+EXTERN void j_monochrome_default PP((compress_info_ptr cinfo));
+EXTERN void j_set_quality PP((compress_info_ptr cinfo, int quality,
+			      boolean force_baseline));
+EXTERN void j_free_defaults PP((compress_info_ptr cinfo));
+
+/* main entry for decompression */
+EXTERN void jpeg_decompress PP((decompress_info_ptr cinfo));
+
+/* forward DCT */
+EXTERN void j_fwd_dct PP((DCTBLOCK data));
+/* inverse DCT */
+EXTERN void j_rev_dct PP((DCTBLOCK data));
+
+/* utility routines in jutils.c */
+EXTERN long jround_up PP((long a, long b));
+EXTERN void jcopy_sample_rows PP((JSAMPARRAY input_array, int source_row,
+				  JSAMPARRAY output_array, int dest_row,
+				  int num_rows, long num_cols));
+EXTERN void jcopy_block_row PP((JBLOCKROW input_row, JBLOCKROW output_row,
+				long num_blocks));
+EXTERN void jzero_far PP((void FAR * target, size_t bytestozero));
+
+/* method selection routines for compression modules */
+EXTERN void jselcpipeline PP((compress_info_ptr cinfo)); /* jcpipe.c */
+EXTERN void jselchuffman PP((compress_info_ptr cinfo)); /* jchuff.c */
+EXTERN void jselcarithmetic PP((compress_info_ptr cinfo)); /* jcarith.c */
+EXTERN void jselexpand PP((compress_info_ptr cinfo)); /* jcexpand.c */
+EXTERN void jselsubsample PP((compress_info_ptr cinfo)); /* jcsample.c */
+EXTERN void jselcmcu PP((compress_info_ptr cinfo)); /* jcmcu.c */
+EXTERN void jselccolor PP((compress_info_ptr cinfo));	/* jccolor.c */
+/* The user interface should call one of these to select input format: */
+EXTERN void jselrgif PP((compress_info_ptr cinfo)); /* jrdgif.c */
+EXTERN void jselrppm PP((compress_info_ptr cinfo)); /* jrdppm.c */
+/* and one of these to select output header format: */
+EXTERN void jselwjfif PP((compress_info_ptr cinfo)); /* jwrjfif.c */
+
+/* method selection routines for decompression modules */
+EXTERN void jseldpipeline PP((decompress_info_ptr cinfo)); /* jdpipe.c */
+EXTERN void jseldhuffman PP((decompress_info_ptr cinfo)); /* jdhuff.c */
+EXTERN void jseldarithmetic PP((decompress_info_ptr cinfo)); /* jdarith.c */
+EXTERN void jseldmcu PP((decompress_info_ptr cinfo)); /* jdmcu.c */
+EXTERN void jselbsmooth PP((decompress_info_ptr cinfo)); /* jbsmooth.c */
+EXTERN void jselunsubsample PP((decompress_info_ptr cinfo)); /* jdsample.c */
+EXTERN void jseldcolor PP((decompress_info_ptr cinfo));	/* jdcolor.c */
+EXTERN void jsel1quantize PP((decompress_info_ptr cinfo)); /* jquant1.c */
+EXTERN void jsel2quantize PP((decompress_info_ptr cinfo)); /* jquant2.c */
+/* The user interface should call one of these to select input format: */
+EXTERN void jselrjfif PP((decompress_info_ptr cinfo)); /* jrdjfif.c */
+/* and one of these to select output image format: */
+EXTERN void jselwgif PP((decompress_info_ptr cinfo)); /* jwrgif.c */
+EXTERN void jselwppm PP((decompress_info_ptr cinfo)); /* jwrppm.c */
+
+/* method selection routines for system-dependent modules */
+EXTERN void jselerror PP((external_methods_ptr emethods)); /* jerror.c */
+EXTERN void jselvirtmem PP((external_methods_ptr emethods)); /* jvirtmem.c */
+
+/* debugging hook in jvirtmem.c */
+#ifdef MEM_STATS
+EXTERN void j_mem_stats PP((void));
+#endif
+
+/* Miscellaneous useful macros */
+
+#define MAX(a,b)	((a) > (b) ? (a) : (b))
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+
+
+#define RST0	0xD0		/* RST0 marker code */
diff --git a/jquant1.c b/jquant1.c
new file mode 100644
index 0000000..49dfd97
--- /dev/null
+++ b/jquant1.c
@@ -0,0 +1,387 @@
+/*
+ * jquant1.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 1-pass color quantization (color mapping) routines.
+ * These routines are invoked via the methods color_quantize
+ * and color_quant_init/term.
+ */
+
+#include "jinclude.h"
+
+#ifdef QUANT_1PASS_SUPPORTED
+
+
+/*
+ * This implementation is a fairly dumb, quick-and-dirty quantizer;
+ * it's here mostly so that we can start working on colormapped output formats.
+ *
+ * We quantize to a color map that is selected in advance of seeing the image;
+ * the map depends only on the requested number of colors (at least 8).
+ * The map consists of all combinations of Ncolors[j] color values for each
+ * component j; we choose Ncolors[] based on the requested # of colors.
+ * We always use 0 and MAXJSAMPLE in each color (hence the minimum 8 colors).
+ * Any additional color values are equally spaced between these limits.
+ *
+ * The result almost always needs dithering to look decent.
+ */
+
+#define MAX_COMPONENTS 4	/* max components I can handle */
+
+static int total_colors;	/* Number of distinct output colors */
+static int Ncolors[MAX_COMPONENTS]; /* # of values alloced to each component */
+/* total_colors is the product of the Ncolors[] values */
+
+static JSAMPARRAY colormap;	/* The actual color map */
+/* colormap[i][j] = value of i'th color component for output pixel value j */
+
+static JSAMPARRAY colorindex;	/* Precomputed mapping for speed */
+/* colorindex[i][j] = index of color closest to pixel value j in component i,
+ * premultiplied so that the correct mapped value for a pixel (r,g,b) is:
+ *   colorindex[0][r] + colorindex[1][g] + colorindex[2][b]
+ */
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ * Errors are accumulated into the arrays evenrowerrs[] and oddrowerrs[],
+ * each of which have #colors * (#columns + 2) entries (so that first/last
+ * pixels need not be special cases).  These have resolutions of 1/16th of
+ * a pixel count.  The error at a given pixel is propagated to its unprocessed
+ * neighbors using the standard F-S fractions,
+ *		...	(here)	7/16
+ *		3/16	5/16	1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error arrays; so they are allocated with alloc_medium.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+typedef short FSERROR;		/* 16 bits should be enough */
+#else
+typedef INT32 FSERROR;		/* may need more than 16 bits? */
+#endif
+
+typedef FSERROR FAR *FSERRPTR;	/* pointer to error array (in FAR storage!) */
+
+static FSERRPTR evenrowerrs, oddrowerrs; /* current-row and next-row errors */
+static boolean on_odd_row;	/* flag to remember which row we are on */
+
+
+/*
+ * Initialize for one-pass color quantization.
+ */
+
+METHODDEF void
+color_quant_init (decompress_info_ptr cinfo)
+{
+  int max_colors = cinfo->desired_number_of_colors;
+  int i,j,k, ntc, nci, blksize, blkdist, ptr, val;
+
+  if (cinfo->color_out_comps > MAX_COMPONENTS)
+    ERREXIT1(cinfo->emethods, "Cannot quantize more than %d color components",
+	     MAX_COMPONENTS);
+  if (max_colors > (MAXJSAMPLE+1))
+    ERREXIT1(cinfo->emethods, "Cannot request more than %d quantized colors",
+	    MAXJSAMPLE+1);
+
+  /* Initialize to 2 color values for each component */
+  total_colors = 1;
+  for (i = 0; i < cinfo->color_out_comps; i++) {
+    Ncolors[i] = 2;
+    total_colors *= 2;
+  }
+  if (total_colors > max_colors)
+    ERREXIT1(cinfo->emethods, "Cannot quantize to fewer than %d colors",
+	     total_colors);
+
+  /* Increase the number of color values until requested limit is reached. */
+  /* Note that for standard RGB color space, we will have at least as many */
+  /* red values as green, and at least as many green values as blue. */
+  i = 0;			/* component index to increase next */
+  /* test calculates ntc = new total_colors if Ncolors[i] is incremented */
+  while ((ntc = (total_colors / Ncolors[i]) * (Ncolors[i]+1)) <= max_colors) {
+    Ncolors[i]++;		/* OK, apply the increment */
+    total_colors = ntc;
+    i++;			/* advance to next component */
+    if (i >= cinfo->color_out_comps) i = 0;
+  }
+
+  /* Report selected color counts */
+  if (cinfo->color_out_comps == 3)
+    TRACEMS4(cinfo->emethods, 1, "Quantizing to %d = %d*%d*%d colors",
+	     total_colors, Ncolors[0], Ncolors[1], Ncolors[2]);
+  else
+    TRACEMS1(cinfo->emethods, 1, "Quantizing to %d colors", total_colors);
+
+  /* Allocate and fill in the colormap and color index. */
+  /* The colors are ordered in the map in standard row-major order, */
+  /* i.e. rightmost (highest-indexed) color changes most rapidly. */
+
+  colormap = (*cinfo->emethods->alloc_small_sarray)
+		((long) total_colors, (long) cinfo->color_out_comps);
+  colorindex = (*cinfo->emethods->alloc_small_sarray)
+		((long) (MAXJSAMPLE+1), (long) cinfo->color_out_comps);
+
+  /* blksize is number of adjacent repeated entries for a component */
+  /* blkdist is distance between groups of identical entries for a component */
+  blkdist = total_colors;
+
+  for (i = 0; i < cinfo->color_out_comps; i++) {
+    /* fill in colormap entries for i'th color component */
+    nci = Ncolors[i];		/* # of distinct values for this color */
+    blksize = blkdist / nci;
+    for (j = 0; j < nci; j++) {
+      val = (j * MAXJSAMPLE + (nci-1)/2) / (nci-1); /* j'th value of color */
+      for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
+	/* fill in blksize entries beginning at ptr */
+	for (k = 0; k < blksize; k++)
+	  colormap[i][ptr+k] = val;
+      }
+    }
+    blkdist = blksize;		/* blksize of this color is blkdist of next */
+
+    /* fill in colorindex entries for i'th color component */
+    for (j = 0; j <= MAXJSAMPLE; j++) {
+      /* compute index of color closest to pixel value j */
+      val = (j * (nci-1) + CENTERJSAMPLE) / MAXJSAMPLE;
+      /* premultiply so that no multiplication needed in main processing */
+      val *= blksize;
+      colorindex[i][j] = val;
+    }
+  }
+
+  /* Pass the colormap to the output module.  Note that the output */
+  /* module is allowed to save this pointer and use the map during */
+  /* any put_pixel_rows call! */
+  (*cinfo->methods->put_color_map) (cinfo, total_colors, colormap);
+
+  /* Allocate Floyd-Steinberg workspace if necessary */
+  if (cinfo->use_dithering) {
+    size_t arraysize = (cinfo->image_width + 2L) * cinfo->color_out_comps
+		       * SIZEOF(FSERROR);
+
+    evenrowerrs = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
+    oddrowerrs  = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
+    /* we only need to zero the forward contribution for current row. */
+    jzero_far((void FAR *) evenrowerrs, arraysize);
+    on_odd_row = FALSE;
+  }
+
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF void
+color_quantize (decompress_info_ptr cinfo, int num_rows,
+		JSAMPIMAGE input_data, JSAMPARRAY output_data)
+/* General case, no dithering */
+{
+  register int pixcode, ci;
+  register long col;
+  register int row;
+  register long widthm1 = cinfo->image_width - 1;
+  register int nc = cinfo->color_out_comps;  
+
+  for (row = 0; row < num_rows; row++) {
+    for (col = widthm1; col >= 0; col--) {
+      pixcode = 0;
+      for (ci = 0; ci < nc; ci++) {
+	pixcode += GETJSAMPLE(colorindex[ci]
+			      [GETJSAMPLE(input_data[ci][row][col])]);
+      }
+      output_data[row][col] = pixcode;
+    }
+  }
+}
+
+
+METHODDEF void
+color_quantize3 (decompress_info_ptr cinfo, int num_rows,
+		 JSAMPIMAGE input_data, JSAMPARRAY output_data)
+/* Fast path for color_out_comps==3, no dithering */
+{
+  register int pixcode;
+  register JSAMPROW ptr0, ptr1, ptr2, ptrout;
+  register long col;
+  register int row;
+  register long width = cinfo->image_width;
+
+  for (row = 0; row < num_rows; row++) {
+    ptr0 = input_data[0][row];
+    ptr1 = input_data[1][row];
+    ptr2 = input_data[2][row];
+    ptrout = output_data[row];
+    for (col = width; col > 0; col--) {
+      pixcode  = GETJSAMPLE(colorindex[0][GETJSAMPLE(*ptr0++)]);
+      pixcode += GETJSAMPLE(colorindex[1][GETJSAMPLE(*ptr1++)]);
+      pixcode += GETJSAMPLE(colorindex[2][GETJSAMPLE(*ptr2++)]);
+      *ptrout++ = pixcode;
+    }
+  }
+}
+
+
+METHODDEF void
+color_quantize_dither (decompress_info_ptr cinfo, int num_rows,
+		       JSAMPIMAGE input_data, JSAMPARRAY output_data)
+/* General case, with Floyd-Steinberg dithering */
+{
+  register int pixcode, ci;
+  register FSERROR val;
+  register FSERRPTR thisrowerr, nextrowerr;
+  register long col;
+  register int row;
+  register long width = cinfo->image_width;
+  register int nc = cinfo->color_out_comps;  
+
+  for (row = 0; row < num_rows; row++) {
+    if (on_odd_row) {
+      /* work right to left in this row */
+      thisrowerr = oddrowerrs + width*nc;
+      nextrowerr = evenrowerrs + width*nc;
+      for (ci = 0; ci < nc; ci++) /* need only initialize this one entry */
+	nextrowerr[ci] = 0;
+      for (col = width - 1; col >= 0; col--) {
+	/* select the output pixel value */
+	pixcode = 0;
+	for (ci = 0; ci < nc; ci++) {
+	  /* compute pixel value + accumulated error */
+	  val = (((FSERROR) GETJSAMPLE(input_data[ci][row][col])) << 4)
+		+ thisrowerr[ci];
+	  if (val < 0) val = 0;	/* must watch for range overflow! */
+	  else {
+	    val += 8;		/* divide by 16 with proper rounding */
+	    val >>= 4;
+	    if (val > MAXJSAMPLE) val = MAXJSAMPLE;
+	  }
+	  thisrowerr[ci] = val;	/* save for error propagation */
+	  pixcode += GETJSAMPLE(colorindex[ci][val]);
+	}
+	output_data[row][col] = pixcode;
+	/* propagate error to adjacent pixels */
+	for (ci = 0; ci < nc; ci++) {
+	  val = thisrowerr[ci] - GETJSAMPLE(colormap[ci][pixcode]);
+	  thisrowerr[ci-nc] += val * 7;
+	  nextrowerr[ci+nc] += val * 3;
+	  nextrowerr[ci   ] += val * 5;
+	  nextrowerr[ci-nc]  = val; /* not +=, since not initialized yet */
+	}
+	thisrowerr -= nc;	/* advance error ptrs to next pixel entry */
+	nextrowerr -= nc;
+      }
+      on_odd_row = FALSE;
+    } else {
+      /* work left to right in this row */
+      thisrowerr = evenrowerrs + nc;
+      nextrowerr = oddrowerrs + nc;
+      for (ci = 0; ci < nc; ci++) /* need only initialize this one entry */
+	nextrowerr[ci] = 0;
+      for (col = 0; col < width; col++) {
+	/* select the output pixel value */
+	pixcode = 0;
+	for (ci = 0; ci < nc; ci++) {
+	  /* compute pixel value + accumulated error */
+	  val = (((FSERROR) GETJSAMPLE(input_data[ci][row][col])) << 4)
+		+ thisrowerr[ci];
+	  if (val < 0) val = 0;	/* must watch for range overflow! */
+	  else {
+	    val += 8;		/* divide by 16 with proper rounding */
+	    val >>= 4;
+	    if (val > MAXJSAMPLE) val = MAXJSAMPLE;
+	  }
+	  thisrowerr[ci] = val;	/* save for error propagation */
+	  pixcode += GETJSAMPLE(colorindex[ci][val]);
+	}
+	output_data[row][col] = pixcode;
+	/* propagate error to adjacent pixels */
+	for (ci = 0; ci < nc; ci++) {
+	  val = thisrowerr[ci] - GETJSAMPLE(colormap[ci][pixcode]);
+	  thisrowerr[ci+nc] += val * 7;
+	  nextrowerr[ci-nc] += val * 3;
+	  nextrowerr[ci   ] += val * 5;
+	  nextrowerr[ci+nc]  = val; /* not +=, since not initialized yet */
+	}
+	thisrowerr += nc;	/* advance error ptrs to next pixel entry */
+	nextrowerr += nc;
+      }
+      on_odd_row = TRUE;
+    }
+  }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+color_quant_term (decompress_info_ptr cinfo)
+{
+  /* We can't free the colormap until now, since output module may use it! */
+  (*cinfo->emethods->free_small_sarray)
+		(colormap, (long) cinfo->color_out_comps);
+  (*cinfo->emethods->free_small_sarray)
+		(colorindex, (long) cinfo->color_out_comps);
+  if (cinfo->use_dithering) {
+    (*cinfo->emethods->free_medium) ((void FAR *) evenrowerrs);
+    (*cinfo->emethods->free_medium) ((void FAR *) oddrowerrs);
+  }
+}
+
+
+/*
+ * Prescan some rows of pixels.
+ * Not used in one-pass case.
+ */
+
+METHODDEF void
+color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
+		     JSAMPIMAGE image_data)
+{
+  ERREXIT(cinfo->emethods, "Should not get here!");
+}
+
+
+/*
+ * Do two-pass quantization.
+ * Not used in one-pass case.
+ */
+
+METHODDEF void
+color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method)
+{
+  ERREXIT(cinfo->emethods, "Should not get here!");
+}
+
+
+/*
+ * The method selection routine for 1-pass color quantization.
+ */
+
+GLOBAL void
+jsel1quantize (decompress_info_ptr cinfo)
+{
+  if (! cinfo->two_pass_quantize) {
+    cinfo->methods->color_quant_init = color_quant_init;
+    if (cinfo->use_dithering) {
+      cinfo->methods->color_quantize = color_quantize_dither;
+    } else {
+      if (cinfo->color_out_comps == 3)
+	cinfo->methods->color_quantize = color_quantize3;
+      else
+	cinfo->methods->color_quantize = color_quantize;
+    }
+    cinfo->methods->color_quant_prescan = color_quant_prescan;
+    cinfo->methods->color_quant_doit = color_quant_doit;
+    cinfo->methods->color_quant_term = color_quant_term;
+  }
+}
+
+#endif /* QUANT_1PASS_SUPPORTED */
diff --git a/jquant2.c b/jquant2.c
new file mode 100644
index 0000000..2569b20
--- /dev/null
+++ b/jquant2.c
@@ -0,0 +1,122 @@
+/*
+ * jquant2.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 2-pass color quantization (color mapping) routines.
+ * These routines are invoked via the methods color_quant_prescan,
+ * color_quant_doit, and color_quant_init/term.
+ */
+
+#include "jinclude.h"
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
+/*
+ * Initialize for two-pass color quantization.
+ */
+
+METHODDEF void
+color_quant_init (decompress_info_ptr cinfo)
+{
+  TRACEMS(cinfo->emethods, 1, "color_quant_init 2 pass");
+}
+
+
+/*
+ * Prescan some rows of pixels.
+ * Note: this could change the data being written into the big image array,
+ * if there were any benefit to doing so.  The doit routine is not allowed
+ * to modify the big image array, because the memory manager is not required
+ * to support multiple write passes on a big image.
+ */
+
+METHODDEF void
+color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
+		     JSAMPIMAGE image_data)
+{
+  TRACEMS1(cinfo->emethods, 2, "color_quant_prescan %d rows", num_rows);
+}
+
+
+/*
+ * This routine makes the final pass over the image data.
+ * output_workspace is a one-component array of pixel dimensions at least
+ * as large as the input image strip; it can be used to hold the converted
+ * pixels' colormap indexes.
+ */
+
+METHODDEF void
+final_pass (decompress_info_ptr cinfo, int num_rows,
+	    JSAMPIMAGE image_data, JSAMPARRAY output_workspace)
+{
+  TRACEMS1(cinfo->emethods, 2, "final_pass %d rows", num_rows);
+  /* for debug purposes, just emit input data */
+  /* NB: this only works for PPM output */
+  (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, image_data);
+}
+
+
+/*
+ * Perform two-pass quantization: rescan the image data and output the
+ * converted data via put_color_map and put_pixel_rows.
+ * The source_method is a routine that can scan the image data; it can
+ * be called as many times as desired.  The processing routine called by
+ * source_method has the same interface as color_quantize does in the
+ * one-pass case, except it must call put_pixel_rows itself.  (This allows
+ * me to use multiple passes in which earlier passes don't output anything.)
+ */
+
+METHODDEF void
+color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method)
+{
+  TRACEMS(cinfo->emethods, 1, "color_quant_doit 2 pass");
+  (*source_method) (cinfo, final_pass);
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+color_quant_term (decompress_info_ptr cinfo)
+{
+  TRACEMS(cinfo->emethods, 1, "color_quant_term 2 pass");
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ * Not used in two-pass case.
+ */
+
+METHODDEF void
+color_quantize (decompress_info_ptr cinfo, int num_rows,
+		JSAMPIMAGE input_data, JSAMPARRAY output_data)
+{
+  ERREXIT(cinfo->emethods, "Should not get here!");
+}
+
+
+/*
+ * The method selection routine for 2-pass color quantization.
+ */
+
+GLOBAL void
+jsel2quantize (decompress_info_ptr cinfo)
+{
+  if (cinfo->two_pass_quantize) {
+    /* just one alternative for the moment */
+    cinfo->methods->color_quant_init = color_quant_init;
+    cinfo->methods->color_quant_prescan = color_quant_prescan;
+    cinfo->methods->color_quant_doit = color_quant_doit;
+    cinfo->methods->color_quant_term = color_quant_term;
+    cinfo->methods->color_quantize = color_quantize;
+  }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/jrdgif.c b/jrdgif.c
new file mode 100644
index 0000000..e2d4b33
--- /dev/null
+++ b/jrdgif.c
@@ -0,0 +1,620 @@
+/*
+ * jrdgif.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in GIF format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications.  As they stand, they assume input from
+ * an ordinary stdio stream.  They further assume that reading begins
+ * at the start of the file; input_init may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed GIF format).
+ *
+ * These routines are invoked via the methods get_input_row
+ * and input_init/term.
+ */
+
+/*
+ * This code is loosely based on giftoppm from the PBMPLUS distribution
+ * of Feb. 1991.  That file contains the following copyright notice:
+ * +-------------------------------------------------------------------+
+ * | Copyright 1990, David Koblas.                                     |
+ * |   Permission to use, copy, modify, and distribute this software   |
+ * |   and its documentation for any purpose and without fee is hereby |
+ * |   granted, provided that the above copyright notice appear in all |
+ * |   copies and that both that copyright notice and this permission  |
+ * |   notice appear in supporting documentation.  This software is    |
+ * |   provided "as is" without express or implied warranty.           |
+ * +-------------------------------------------------------------------+
+ *
+ * We are also required to state that
+ *    "The Graphics Interchange Format(c) is the Copyright property of
+ *    CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ *    CompuServe Incorporated."
+ */
+
+#include "jinclude.h"
+
+#ifdef GIF_SUPPORTED
+
+
+#define	MAXCOLORMAPSIZE	256	/* max # of colors in a GIF colormap */
+#define NUMCOLORS	3	/* # of colors */
+#define CM_RED		0	/* color component numbers */
+#define CM_GREEN	1
+#define CM_BLUE		2
+
+static JSAMPARRAY colormap;	/* the colormap to use */
+/* colormap[i][j] = value of i'th color component for pixel value j */
+
+#define	MAX_LZW_BITS	12	/* maximum LZW code size */
+#define LZW_TABLE_SIZE	(1<<MAX_LZW_BITS) /* # of possible LZW symbols */
+
+/* Macros for extracting header data --- note we assume chars may be signed */
+
+#define LM_to_uint(a,b)		((((b)&0xFF) << 8) | ((a)&0xFF))
+
+#define BitSet(byte, bit)	((byte) & (bit))
+#define INTERLACE	0x40	/* mask for bit signifying interlaced image */
+#define COLORMAPFLAG	0x80	/* mask for bit signifying colormap presence */
+
+#define	ReadOK(file,buffer,len)	(fread(buffer, 1, len, file) == (len))
+
+/* Static vars for GetCode and LZWReadByte */
+
+static char code_buf[256+4];	/* current input data block */
+static int last_byte;		/* # of bytes in code_buf */
+static int last_bit;		/* # of bits in code_buf */
+static int cur_bit;		/* next bit index to read */
+static boolean out_of_blocks;	/* TRUE if hit terminator data block */
+
+static int input_code_size;	/* codesize given in GIF file */
+static int clear_code,end_code; /* values for Clear and End codes */
+
+static int code_size;		/* current actual code size */
+static int limit_code;		/* 2^code_size */
+static int max_code;		/* first unused code value */
+static boolean first_time;	/* flags first call to LZWReadByte */
+
+/* LZW decompression tables:
+ *   symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1)
+ *   symbol_tail[K] = suffix byte   of any LZW symbol K (0..LZW_TABLE_SIZE-1)
+ * Note that entries 0..end_code of the above tables are not used,
+ * since those symbols represent raw bytes or special codes.
+ *
+ * The stack represents the not-yet-used expansion of the last LZW symbol.
+ * In the worst case, a symbol could expand to as many bytes as there are
+ * LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack.
+ * (This is conservative since that number includes the raw-byte symbols.)
+ *
+ * The tables are allocated from FAR heap space since they would use up
+ * rather a lot of the near data space in a PC.
+ */
+
+static UINT16 FAR *symbol_head; /* => table of prefix symbols */
+static UINT8  FAR *symbol_tail; /* => table of suffix bytes */
+static UINT8  FAR *symbol_stack; /* stack for symbol expansions */
+static UINT8  FAR *sp;		/* stack pointer */
+
+/* Static state for interlaced image processing */
+
+static boolean is_interlaced;	/* TRUE if have interlaced image */
+static big_sarray_ptr interlaced_image;	/* full image in interlaced order */
+static long cur_row_number;	/* need to know actual row number */
+static long pass2_offset;	/* # of pixel rows in pass 1 */
+static long pass3_offset;	/* # of pixel rows in passes 1&2 */
+static long pass4_offset;	/* # of pixel rows in passes 1,2,3 */
+
+
+/* Forward declarations */
+METHODDEF void load_interlaced_image PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
+METHODDEF void get_interlaced_row PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
+
+
+
+LOCAL int
+ReadByte (compress_info_ptr cinfo)
+/* Read next byte from GIF file */
+{
+  register FILE * infile = cinfo->input_file;
+  int c;
+
+  if ((c = getc(infile)) == EOF)
+    ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
+  return c;
+}
+
+
+LOCAL int
+GetDataBlock (compress_info_ptr cinfo, char *buf)
+/* Read a GIF data block, which has a leading count byte */
+/* A zero-length block marks the end of a data block sequence */
+{
+  int count;
+
+  count = ReadByte(cinfo);
+  if (count > 0) {
+    if (! ReadOK(cinfo->input_file, buf, count))
+      ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
+  }
+  return count;
+}
+
+
+LOCAL void
+SkipDataBlocks (compress_info_ptr cinfo)
+/* Skip a series of data blocks, until a block terminator is found */
+{
+  char buf[256];
+
+  while (GetDataBlock(cinfo, buf) > 0)
+    /* skip */;
+}
+
+
+LOCAL void
+ReInitLZW (void)
+/* (Re)initialize LZW state; shared code for startup and Clear processing */
+{
+  code_size = input_code_size+1;
+  limit_code = clear_code << 1;	/* 2^code_size */
+  max_code = clear_code + 2;	/* first unused code value */
+  sp = symbol_stack;		/* init stack to empty */
+}
+
+
+LOCAL void
+InitLZWCode (void)
+/* Initialize for a series of LZWReadByte (and hence GetCode) calls */
+{
+  /* GetCode initialization */
+  last_byte = 2;		/* make safe to "recopy last two bytes" */
+  last_bit = 0;			/* nothing in the buffer */
+  cur_bit = 0;			/* force buffer load on first call */
+  out_of_blocks = FALSE;
+
+  /* LZWReadByte initialization */
+  clear_code = 1 << input_code_size; /* compute special code values */
+  end_code = clear_code + 1;	/* note that these do not change */
+  first_time = TRUE;
+  ReInitLZW();
+}
+
+
+LOCAL int
+GetCode (compress_info_ptr cinfo)
+/* Fetch the next code_size bits from the GIF data */
+/* We assume code_size is less than 16 */
+{
+  register INT32 accum;
+  int offs, ret, count;
+
+  if ( (cur_bit+code_size) > last_bit) {
+    /* Time to reload the buffer */
+    if (out_of_blocks) {
+      TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
+      return end_code;		/* fake something useful */
+    }
+    /* preserve last two bytes of what we have -- assume code_size <= 16 */
+    code_buf[0] = code_buf[last_byte-2];
+    code_buf[1] = code_buf[last_byte-1];
+    /* Load more bytes; set flag if we reach the terminator block */
+    if ((count = GetDataBlock(cinfo, &code_buf[2])) == 0) {
+      out_of_blocks = TRUE;
+      TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
+      return end_code;		/* fake something useful */
+    }
+    /* Reset counters */
+    cur_bit = (cur_bit - last_bit) + 16;
+    last_byte = 2 + count;
+    last_bit = last_byte * 8;
+  }
+
+  /* Form up next 24 bits in accum */
+  offs = cur_bit >> 3;		/* byte containing cur_bit */
+#ifdef CHAR_IS_UNSIGNED
+  accum = code_buf[offs+2];
+  accum <<= 8;
+  accum |= code_buf[offs+1];
+  accum <<= 8;
+  accum |= code_buf[offs];
+#else
+  accum = code_buf[offs+2] & 0xFF;
+  accum <<= 8;
+  accum |= code_buf[offs+1] & 0xFF;
+  accum <<= 8;
+  accum |= code_buf[offs] & 0xFF;
+#endif
+
+  /* Right-align cur_bit in accum, then mask off desired number of bits */
+  accum >>= (cur_bit & 7);
+  ret = ((int) accum) & ((1 << code_size) - 1);
+  
+  cur_bit += code_size;
+  return ret;
+}
+
+
+LOCAL int
+LZWReadByte (compress_info_ptr cinfo)
+/* Read an LZW-compressed byte */
+{
+  static int oldcode;		/* previous LZW symbol */
+  static int firstcode;		/* first byte of oldcode's expansion */
+  register int code;		/* current working code */
+  int incode;			/* saves actual input code */
+
+  /* First time, just eat the expected Clear code(s) and return next code, */
+  /* which is assumed to be a raw byte. */
+  if (first_time) {
+    first_time = FALSE;
+    do {
+      code = GetCode(cinfo);
+    } while (code == clear_code);
+    firstcode = oldcode = code;	/* make firstcode, oldcode valid! */
+    return code;
+  }
+
+  /* If any codes are stacked from a previously read symbol, return them */
+  if (sp > symbol_stack)
+    return *(--sp);
+
+  code = GetCode(cinfo);
+
+  if (code == clear_code) {
+    /* Reinit static state, swallow any extra Clear codes, and return */
+    ReInitLZW();
+    do {
+      code = GetCode(cinfo);
+    } while (code == clear_code);
+    firstcode = oldcode = code; /* gotta reinit these too */
+    return code;
+  }
+
+  if (code == end_code) {
+    /* Skip the rest of the image, unless GetCode already read terminator */
+    if (! out_of_blocks)
+      SkipDataBlocks(cinfo);
+    return -1;
+  }
+
+  /* Normal raw byte or LZW symbol */
+  incode = code;		/* save for a moment */
+  
+  if (code >= max_code) {	/* special case for not-yet-defined symbol */
+    *sp++ = firstcode;		/* it will be defined as oldcode/firstcode */
+    code = oldcode;
+  }
+
+  /* If it's a symbol, expand it into the stack */
+  while (code >= clear_code) {
+    *sp++ = symbol_tail[code];	/* tail of symbol: a simple byte value */
+    code = symbol_head[code];	/* head of symbol: another LZW symbol */
+  }
+  /* At this point code just represents a raw byte */
+  firstcode = code;		/* save for possible future use */
+
+  /* If there's room in table, */
+  if ((code = max_code) < LZW_TABLE_SIZE) {
+    /* Define a new symbol = prev sym + head of this sym's expansion */
+    symbol_head[code] = oldcode;
+    symbol_tail[code] = firstcode;
+    max_code++;
+    /* Is it time to increase code_size? */
+    if ((max_code >= limit_code) && (code_size < MAX_LZW_BITS)) {
+      code_size++;
+      limit_code <<= 1;		/* keep equal to 2^code_size */
+    }
+  }
+  
+  oldcode = incode;		/* save last input symbol for future use */
+  return firstcode;		/* return first byte of symbol's expansion */
+}
+
+
+LOCAL void
+ReadColorMap (compress_info_ptr cinfo, int cmaplen, JSAMPARRAY cmap)
+/* Read a GIF colormap */
+{
+  int i;
+
+  for (i = 0; i < cmaplen; i++) {
+    cmap[CM_RED][i]   = ReadByte(cinfo);
+    cmap[CM_GREEN][i] = ReadByte(cinfo);
+    cmap[CM_BLUE][i]  = ReadByte(cinfo);
+  }
+}
+
+
+LOCAL void
+DoExtension (compress_info_ptr cinfo)
+/* Process an extension block */
+/* Currently we ignore 'em all */
+{
+  int extlabel;
+
+  /* Read extension label byte */
+  extlabel = ReadByte(cinfo);
+  TRACEMS1(cinfo->emethods, 1, "Ignoring GIF extension block of type 0x%02x",
+	   extlabel);
+  /* Skip the data block(s) associated with the extension */
+  SkipDataBlocks(cinfo);
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF void
+input_init (compress_info_ptr cinfo)
+{
+  char hdrbuf[10];		/* workspace for reading control blocks */
+  UINT16 width, height;		/* image dimensions */
+  int colormaplen, aspectRatio;
+  int c;
+
+  /* Allocate space to store the colormap */
+  colormap = (*cinfo->emethods->alloc_small_sarray)
+		((long) MAXCOLORMAPSIZE, (long) NUMCOLORS);
+
+  /* Read and verify GIF Header */
+  if (! ReadOK(cinfo->input_file, hdrbuf, 6))
+    ERREXIT(cinfo->emethods, "Not a GIF file");
+  if (strncmp(hdrbuf, "GIF", 3) != 0)
+    ERREXIT(cinfo->emethods, "Not a GIF file");
+  /* Check for expected version numbers.
+   * If unknown version, give warning and try to process anyway;
+   * this is per recommendation in GIF89a standard.
+   */
+  if ((strncmp(hdrbuf+3, "87a", 3) != 0) &&
+      (strncmp(hdrbuf+3, "89a", 3) != 0))
+    TRACEMS3(cinfo->emethods, 1,
+	     "Warning: unexpected GIF version number '%c%c%c'",
+	     hdrbuf[3], hdrbuf[4], hdrbuf[5]);
+
+  /* Read and decipher Logical Screen Descriptor */
+  if (! ReadOK(cinfo->input_file, hdrbuf, 7))
+    ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
+  width = LM_to_uint(hdrbuf[0],hdrbuf[1]);
+  height = LM_to_uint(hdrbuf[2],hdrbuf[3]);
+  colormaplen = 2 << (hdrbuf[4] & 0x07);
+  /* we ignore the color resolution, sort flag, and background color index */
+  aspectRatio = hdrbuf[6] & 0xFF;
+  if (aspectRatio != 0 && aspectRatio != 49)
+    TRACEMS(cinfo->emethods, 1, "Warning: nonsquare pixels in input");
+
+  /* Read global colormap if header indicates it is present */
+  if (BitSet(hdrbuf[4], COLORMAPFLAG))
+    ReadColorMap(cinfo, colormaplen, colormap);
+
+  /* Scan until we reach start of desired image.
+   * We don't currently support skipping images, but could add it easily.
+   */
+  for (;;) {
+    c = ReadByte(cinfo);
+
+    if (c == ';')		/* GIF terminator?? */
+      ERREXIT(cinfo->emethods, "Too few images in GIF file");
+
+    if (c == '!') {		/* Extension */
+      DoExtension(cinfo);
+      continue;
+    }
+    
+    if (c != ',') {		/* Not an image separator? */
+      TRACEMS1(cinfo->emethods, 1, "Bogus input char 0x%02x, ignoring", c);
+      continue;
+    }
+
+    /* Read and decipher Local Image Descriptor */
+    if (! ReadOK(cinfo->input_file, hdrbuf, 9))
+      ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
+    /* we ignore top/left position info, also sort flag */
+    width = LM_to_uint(hdrbuf[4],hdrbuf[5]);
+    height = LM_to_uint(hdrbuf[6],hdrbuf[7]);
+    is_interlaced = BitSet(hdrbuf[8], INTERLACE);
+    colormaplen = 2 << (hdrbuf[8] & 0x07);
+
+    /* Read local colormap if header indicates it is present */
+    /* Note: if we wanted to support skipping images, */
+    /* we'd need to skip rather than read colormap for ignored images */
+    if (BitSet(hdrbuf[8], COLORMAPFLAG))
+      ReadColorMap(cinfo, colormaplen, colormap);
+
+    input_code_size = ReadByte(cinfo); /* get minimum-code-size byte */
+    if (input_code_size < 2 || input_code_size >= MAX_LZW_BITS)
+      ERREXIT1(cinfo->emethods, "Bogus codesize %d", input_code_size);
+
+    /* Reached desired image, so break out of loop */
+    /* If we wanted to skip this image, */
+    /* we'd call SkipDataBlocks and then continue the loop */
+    break;
+  }
+
+  /* Prepare to read selected image: first initialize LZW decompressor */
+  symbol_head = (UINT16 FAR *) (*cinfo->emethods->alloc_medium)
+				(LZW_TABLE_SIZE * SIZEOF(UINT16));
+  symbol_tail = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
+				(LZW_TABLE_SIZE * SIZEOF(UINT8));
+  symbol_stack = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
+				(LZW_TABLE_SIZE * SIZEOF(UINT8));
+  InitLZWCode();
+
+  /*
+   * If image is interlaced, we read it into a full-size sample array,
+   * decompressing as we go; then get_input_row selects rows from the
+   * sample array in the proper order.
+   */
+  if (is_interlaced) {
+    /* We request the big array now, but can't access it until the pipeline
+     * controller causes all the big arrays to be allocated.  Hence, the
+     * actual work of reading the image is postponed until the first call
+     * of get_input_row.
+     */
+    interlaced_image = (*cinfo->emethods->request_big_sarray)
+		((long) width, (long) height, (long) 1);
+    cinfo->methods->get_input_row = load_interlaced_image;
+  }
+
+  /* Return info about the image. */
+  cinfo->input_components = NUMCOLORS;
+  cinfo->in_color_space = CS_RGB;
+  cinfo->image_width = width;
+  cinfo->image_height = height;
+  cinfo->data_precision = 8;
+}
+
+
+/*
+ * Read one row of pixels.
+ * This version is used for noninterlaced GIF images:
+ * we read directly from the GIF file.
+ */
+
+METHODDEF void
+get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
+{
+  register JSAMPROW ptr0, ptr1, ptr2;
+  register long col;
+  register int c;
+  
+  ptr0 = pixel_row[0];
+  ptr1 = pixel_row[1];
+  ptr2 = pixel_row[2];
+  for (col = cinfo->image_width; col > 0; col--) {
+    if ((c = LZWReadByte(cinfo)) < 0)
+      ERREXIT(cinfo->emethods, "Premature end of GIF image");
+    *ptr0++ = colormap[CM_RED][c];
+    *ptr1++ = colormap[CM_GREEN][c];
+    *ptr2++ = colormap[CM_BLUE][c];
+  }
+}
+
+
+/*
+ * Read one row of pixels.
+ * This version is used for the first call on get_input_row when
+ * reading an interlaced GIF file: we read the whole image into memory.
+ */
+
+METHODDEF void
+load_interlaced_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
+{
+  JSAMPARRAY image_ptr;
+  register JSAMPROW sptr;
+  register long col;
+  register int c;
+  long row;
+
+  /* Read the interlaced image into the big array we've created. */
+  for (row = 0; row < cinfo->image_height; row++) {
+    image_ptr = (*cinfo->emethods->access_big_sarray)
+			(interlaced_image, row, TRUE);
+    sptr = image_ptr[0];
+    for (col = cinfo->image_width; col > 0; col--) {
+      if ((c = LZWReadByte(cinfo)) < 0)
+	ERREXIT(cinfo->emethods, "Premature end of GIF image");
+      *sptr++ = c;
+    }
+  }
+
+  /* Replace method pointer so subsequent calls don't come here. */
+  cinfo->methods->get_input_row = get_interlaced_row;
+  /* Initialize for get_interlaced_row, and perform first call on it. */
+  cur_row_number = 0;
+  pass2_offset = (cinfo->image_height + 7L) / 8L;
+  pass3_offset = pass2_offset + (cinfo->image_height + 3L) / 8L;
+  pass4_offset = pass3_offset + (cinfo->image_height + 1L) / 4L;
+
+  get_interlaced_row(cinfo, pixel_row);
+}
+
+
+/*
+ * Read one row of pixels.
+ * This version is used for interlaced GIF images:
+ * we read from the big in-memory image.
+ */
+
+METHODDEF void
+get_interlaced_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
+{
+  JSAMPARRAY image_ptr;
+  register JSAMPROW sptr, ptr0, ptr1, ptr2;
+  register long col;
+  register int c;
+  long irow;
+
+  /* Figure out which row of interlaced image is needed, and access it. */
+  switch ((int) (cur_row_number & 7L)) {
+  case 0:			/* first-pass row */
+    irow = cur_row_number >> 3;
+    break;
+  case 4:			/* second-pass row */
+    irow = (cur_row_number >> 3) + pass2_offset;
+    break;
+  case 2:			/* third-pass row */
+  case 6:
+    irow = (cur_row_number >> 2) + pass3_offset;
+    break;
+  default:			/* fourth-pass row */
+    irow = (cur_row_number >> 1) + pass4_offset;
+    break;
+  }
+  image_ptr = (*cinfo->emethods->access_big_sarray)
+			(interlaced_image, irow, FALSE);
+  /* Scan the row, expand colormap, and output */
+  sptr = image_ptr[0];
+  ptr0 = pixel_row[0];
+  ptr1 = pixel_row[1];
+  ptr2 = pixel_row[2];
+  for (col = cinfo->image_width; col > 0; col--) {
+    c = GETJSAMPLE(*sptr++);
+    *ptr0++ = colormap[CM_RED][c];
+    *ptr1++ = colormap[CM_GREEN][c];
+    *ptr2++ = colormap[CM_BLUE][c];
+  }
+  cur_row_number++;		/* for next time */
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+input_term (compress_info_ptr cinfo)
+{
+  if (is_interlaced) {
+    (*cinfo->emethods->free_big_sarray) (interlaced_image);
+  }
+  (*cinfo->emethods->free_small_sarray)
+		(colormap, (long) NUMCOLORS);
+  (*cinfo->emethods->free_medium) ((void FAR *) symbol_head);
+  (*cinfo->emethods->free_medium) ((void FAR *) symbol_tail);
+  (*cinfo->emethods->free_medium) ((void FAR *) symbol_stack);
+}
+
+
+/*
+ * The method selection routine for GIF format input.
+ * Note that this must be called by the user interface before calling
+ * jpeg_compress.  If multiple input formats are supported, the
+ * user interface is responsible for discovering the file format and
+ * calling the appropriate method selection routine.
+ */
+
+GLOBAL void
+jselrgif (compress_info_ptr cinfo)
+{
+  cinfo->methods->input_init = input_init;
+  cinfo->methods->get_input_row = get_input_row; /* assume uninterlaced */
+  cinfo->methods->input_term = input_term;
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/jrdjfif.c b/jrdjfif.c
new file mode 100644
index 0000000..5ff14ba
--- /dev/null
+++ b/jrdjfif.c
@@ -0,0 +1,733 @@
+/*
+ * jrdjfif.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to decode standard JPEG file headers/markers.
+ * This will handle baseline and JFIF-convention JPEG files.
+ *
+ * This module relies on the JGETC macro and the read_jpeg_data method (which
+ * is provided by the user interface) to read from the JPEG data stream.
+ * Therefore, this module is NOT dependent on any particular assumption about
+ * the data source.  This fact does not carry over to more complex JPEG file
+ * formats such as JPEG-in-TIFF; those format control modules may well need to
+ * assume stdio input.
+ *
+ * read_file_header assumes that reading begins at the JPEG SOI marker
+ * (although it will skip non-FF bytes looking for a JPEG marker).
+ * The user interface must position the data stream appropriately.
+ *
+ * These routines are invoked via the methods read_file_header,
+ * read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
+ */
+
+#include "jinclude.h"
+
+#ifdef JFIF_SUPPORTED
+
+
+typedef enum {			/* JPEG marker codes */
+  M_SOF0  = 0xc0,
+  M_SOF1  = 0xc1,
+  M_SOF2  = 0xc2,
+  M_SOF3  = 0xc3,
+  
+  M_SOF5  = 0xc5,
+  M_SOF6  = 0xc6,
+  M_SOF7  = 0xc7,
+  
+  M_JPG   = 0xc8,
+  M_SOF9  = 0xc9,
+  M_SOF10 = 0xca,
+  M_SOF11 = 0xcb,
+  
+  M_SOF13 = 0xcd,
+  M_SOF14 = 0xce,
+  M_SOF15 = 0xcf,
+  
+  M_DHT   = 0xc4,
+  
+  M_DAC   = 0xcc,
+  
+  M_RST0  = 0xd0,
+  M_RST1  = 0xd1,
+  M_RST2  = 0xd2,
+  M_RST3  = 0xd3,
+  M_RST4  = 0xd4,
+  M_RST5  = 0xd5,
+  M_RST6  = 0xd6,
+  M_RST7  = 0xd7,
+  
+  M_SOI   = 0xd8,
+  M_EOI   = 0xd9,
+  M_SOS   = 0xda,
+  M_DQT   = 0xdb,
+  M_DNL   = 0xdc,
+  M_DRI   = 0xdd,
+  M_DHP   = 0xde,
+  M_EXP   = 0xdf,
+  
+  M_APP0  = 0xe0,
+  M_APP15 = 0xef,
+  
+  M_JPG0  = 0xf0,
+  M_JPG13 = 0xfd,
+  M_COM   = 0xfe,
+  
+  M_TEM   = 0x01,
+  
+  M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/*
+ * Reload the input buffer after it's been emptied, and return the next byte.
+ * This is exported for direct use by the entropy decoder.
+ * See the JGETC macro for calling conditions.
+ *
+ * For this header control module, read_jpeg_data is supplied by the
+ * user interface.  However, header formats that require random access
+ * to the input file would need to supply their own code.  This code is
+ * left here to indicate what is required.
+ */
+
+#if 0				/* not needed in this module */
+
+METHODDEF int
+read_jpeg_data (decompress_info_ptr cinfo)
+{
+  cinfo->bytes_in_buffer = fread(cinfo->input_buffer + MIN_UNGET,
+				 1, JPEG_BUF_SIZE,
+				 cinfo->input_file);
+  
+  cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
+  
+  if (cinfo->bytes_in_buffer <= 0)
+    ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
+
+  return JGETC(cinfo);
+}
+
+#endif
+
+
+/*
+ * Routines to parse JPEG markers & save away the useful info.
+ */
+
+
+LOCAL INT32
+get_2bytes (decompress_info_ptr cinfo)
+/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
+{
+  INT32 a;
+  
+  a = JGETC(cinfo);
+  return (a << 8) + JGETC(cinfo);
+}
+
+
+LOCAL void
+skip_variable (decompress_info_ptr cinfo, int code)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+  INT32 length;
+  
+  length = get_2bytes(cinfo);
+  
+  TRACEMS2(cinfo->emethods, 1,
+	   "Skipping marker 0x%02x, length %d", code, length);
+  
+  for (length -= 2; length > 0; length--)
+    (void) JGETC(cinfo);
+}
+
+
+LOCAL void
+get_dht (decompress_info_ptr cinfo)
+/* Process a DHT marker */
+{
+  INT32 length;
+  UINT8 bits[17];
+  UINT8 huffval[256];
+  int i, index, count;
+  HUFF_TBL **htblptr;
+  
+  length = get_2bytes(cinfo)-2;
+  
+  while (length > 0) {
+    index = JGETC(cinfo);
+
+    TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
+      
+    bits[0] = 0;
+    count = 0;
+    for (i = 1; i <= 16; i++) {
+      bits[i] = JGETC(cinfo);
+      count += bits[i];
+    }
+
+    TRACEMS8(cinfo->emethods, 2, "        %3d %3d %3d %3d %3d %3d %3d %3d",
+	     bits[1], bits[2], bits[3], bits[4],
+	     bits[5], bits[6], bits[7], bits[8]);
+    TRACEMS8(cinfo->emethods, 2, "        %3d %3d %3d %3d %3d %3d %3d %3d",
+	     bits[9], bits[10], bits[11], bits[12],
+	     bits[13], bits[14], bits[15], bits[16]);
+
+    if (count > 256)
+      ERREXIT(cinfo->emethods, "Bogus DHT counts");
+
+    for (i = 0; i < count; i++)
+      huffval[i] = JGETC(cinfo);
+
+    length -= 1 + 16 + count;
+
+    if (index & 0x10) {		/* AC table definition */
+      index -= 0x10;
+      htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+    } else {			/* DC table definition */
+      htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+    }
+
+    if (index < 0 || index >= NUM_HUFF_TBLS)
+      ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index);
+
+    if (*htblptr == NULL)
+      *htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
+  
+    memcpy((void *) (*htblptr)->bits, (void *) bits,
+	   SIZEOF((*htblptr)->bits));
+    memcpy((void *) (*htblptr)->huffval, (void *) huffval,
+	   SIZEOF((*htblptr)->huffval));
+    }
+}
+
+
+LOCAL void
+get_dac (decompress_info_ptr cinfo)
+/* Process a DAC marker */
+{
+  INT32 length;
+  int index, val;
+
+  length = get_2bytes(cinfo)-2;
+  
+  while (length > 0) {
+    index = JGETC(cinfo);
+    val = JGETC(cinfo);
+
+    TRACEMS2(cinfo->emethods, 1,
+	     "Define Arithmetic Table 0x%02x: 0x%02x", index, val);
+
+    if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+      ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index);
+
+    if (index >= NUM_ARITH_TBLS) { /* define AC table */
+      cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = val;
+    } else {			/* define DC table */
+      cinfo->arith_dc_L[index] = val & 0x0F;
+      cinfo->arith_dc_U[index] = val >> 4;
+      if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+	ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
+    }
+
+    length -= 2;
+  }
+}
+
+
+LOCAL void
+get_dqt (decompress_info_ptr cinfo)
+/* Process a DQT marker */
+{
+  INT32 length;
+  int n, i, prec;
+  UINT16 tmp;
+  QUANT_TBL_PTR quant_ptr;
+  
+  length = get_2bytes(cinfo) - 2;
+  
+  while (length > 0) {
+    n = JGETC(cinfo);
+    prec = n >> 4;
+    n &= 0x0F;
+
+    TRACEMS2(cinfo->emethods, 1,
+	     "Define Quantization Table %d  precision %d", n, prec);
+
+    if (n >= NUM_QUANT_TBLS)
+      ERREXIT1(cinfo->emethods, "Bogus table number %d", n);
+      
+    if (cinfo->quant_tbl_ptrs[n] == NULL)
+      cinfo->quant_tbl_ptrs[n] = (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
+    quant_ptr = cinfo->quant_tbl_ptrs[n];
+
+    for (i = 0; i < DCTSIZE2; i++) {
+      tmp = JGETC(cinfo);
+      if (prec)
+	tmp = (tmp<<8) + JGETC(cinfo);
+      quant_ptr[i] = tmp;
+    }
+
+    for (i = 0; i < DCTSIZE2; i += 8) {
+      TRACEMS8(cinfo->emethods, 2, "        %4d %4d %4d %4d %4d %4d %4d %4d",
+	       quant_ptr[i  ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
+	       quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
+    }
+
+    length -= DCTSIZE2+1;
+    if (prec) length -= DCTSIZE2;
+  }
+}
+
+
+LOCAL void
+get_dri (decompress_info_ptr cinfo)
+/* Process a DRI marker */
+{
+  if (get_2bytes(cinfo) != 4)
+    ERREXIT(cinfo->emethods, "Bogus length in DRI");
+
+  cinfo->restart_interval = get_2bytes(cinfo);
+
+  TRACEMS1(cinfo->emethods, 1,
+	   "Define Restart Interval %d", cinfo->restart_interval);
+}
+
+
+LOCAL void
+get_app0 (decompress_info_ptr cinfo)
+/* Process an APP0 marker */
+{
+#define JFIF_LEN 14
+  INT32 length;
+  UINT8 b[JFIF_LEN];
+  int buffp;
+
+  length = get_2bytes(cinfo) - 2;
+
+  /* See if a JFIF APP0 marker is present */
+
+  if (length >= JFIF_LEN) {
+    for (buffp = 0; buffp < JFIF_LEN; buffp++)
+      b[buffp] = JGETC(cinfo);
+    length -= JFIF_LEN;
+
+    if (b[0]=='J' && b[1]=='F' && b[2]=='I' && b[3]=='F' && b[4]==0) {
+      /* Found JFIF APP0 marker: check version */
+      /* Major version must be 1 */
+      if (b[5] != 1)
+	ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
+		 b[5], b[6]);
+      /* Minor version should be 0 or 1, but try to process anyway if newer */
+      if (b[6] != 0 && b[6] != 1)
+	TRACEMS2(cinfo->emethods, 0, "Warning: unknown JFIF revision number %d.%02d",
+		 b[5], b[6]);
+      /* Save info */
+      cinfo->density_unit = b[7];
+      cinfo->X_density = (b[8] << 8) + b[9];
+      cinfo->Y_density = (b[10] << 8) + b[11];
+      /* Assume colorspace is YCbCr, unless UI has overridden me */
+      if (cinfo->jpeg_color_space == CS_UNKNOWN)
+	cinfo->jpeg_color_space = CS_YCbCr;
+      TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d  %d",
+	       cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
+    } else {
+      TRACEMS(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF)");
+    }
+  } else {
+    TRACEMS1(cinfo->emethods, 1,
+	     "Short APP0 marker, length %d", (int) length);
+  }
+
+  while (length-- > 0)		/* skip any remaining data */
+    (void) JGETC(cinfo);
+}
+
+
+LOCAL void
+get_sof (decompress_info_ptr cinfo, int code)
+/* Process a SOFn marker */
+{
+  INT32 length;
+  short ci;
+  int c;
+  jpeg_component_info * compptr;
+  
+  length = get_2bytes(cinfo);
+  
+  cinfo->data_precision = JGETC(cinfo);
+  cinfo->image_height   = get_2bytes(cinfo);
+  cinfo->image_width    = get_2bytes(cinfo);
+  cinfo->num_components = JGETC(cinfo);
+
+  TRACEMS4(cinfo->emethods, 1,
+	   "Start Of Frame 0x%02x: width=%d, height=%d, components=%d",
+	   code, cinfo->image_width, cinfo->image_height,
+	   cinfo->num_components);
+
+  /* We don't support files in which the image height is initially specified */
+  /* as 0 and is later redefined by DNL.  As long as we have to check that,  */
+  /* might as well have a general sanity check. */
+  if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+      || cinfo->num_components <= 0)
+    ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)");
+
+#ifdef EIGHT_BIT_SAMPLES
+  if (cinfo->data_precision != 8)
+    ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
+#endif
+#ifdef TWELVE_BIT_SAMPLES
+  if (cinfo->data_precision != 12) /* this needs more thought?? */
+    ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
+#endif
+#ifdef SIXTEEN_BIT_SAMPLES
+  if (cinfo->data_precision != 16) /* this needs more thought?? */
+    ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
+#endif
+
+  if (length != (cinfo->num_components * 3 + 8))
+    ERREXIT(cinfo->emethods, "Bogus SOF length");
+
+  cinfo->comp_info = (*cinfo->emethods->alloc_small)
+			(cinfo->num_components * SIZEOF(jpeg_component_info));
+  
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    compptr = &cinfo->comp_info[ci];
+    compptr->component_index = ci;
+    compptr->component_id = JGETC(cinfo);
+    c = JGETC(cinfo);
+    compptr->h_samp_factor = (c >> 4) & 15;
+    compptr->v_samp_factor = (c     ) & 15;
+    compptr->quant_tbl_no  = JGETC(cinfo);
+      
+    TRACEMS4(cinfo->emethods, 1, "    Component %d: %dhx%dv q=%d",
+	     compptr->component_id, compptr->h_samp_factor,
+	     compptr->v_samp_factor, compptr->quant_tbl_no);
+  }
+}
+
+
+LOCAL void
+get_sos (decompress_info_ptr cinfo)
+/* Process a SOS marker */
+{
+  INT32 length;
+  int i, ci, n, c, cc;
+  jpeg_component_info * compptr;
+  
+  length = get_2bytes(cinfo);
+  
+  n = JGETC(cinfo);  /* Number of components */
+  cinfo->comps_in_scan = n;
+  length -= 3;
+  
+  if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo->emethods, "Bogus SOS length");
+
+  TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n);
+  
+  for (i = 0; i < n; i++) {
+    cc = JGETC(cinfo);
+    c = JGETC(cinfo);
+    length -= 2;
+    
+    for (ci = 0; ci < cinfo->num_components; ci++)
+      if (cc == cinfo->comp_info[ci].component_id)
+	break;
+    
+    if (ci >= cinfo->num_components)
+      ERREXIT(cinfo->emethods, "Invalid component number in SOS");
+    
+    compptr = &cinfo->comp_info[ci];
+    cinfo->cur_comp_info[i] = compptr;
+    compptr->dc_tbl_no = (c >> 4) & 15;
+    compptr->ac_tbl_no = (c     ) & 15;
+    
+    TRACEMS3(cinfo->emethods, 1, "    c%d: [dc=%d ac=%d]", cc,
+	     compptr->dc_tbl_no, compptr->ac_tbl_no);
+  }
+  
+  while (length > 0) {
+    (void) JGETC(cinfo);
+    length--;
+  }
+}
+
+
+LOCAL void
+get_soi (decompress_info_ptr cinfo)
+/* Process an SOI marker */
+{
+  int i;
+  
+  TRACEMS(cinfo->emethods, 1, "Start of Image");
+
+  /* Reset all parameters that are defined to be reset by SOI */
+
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    cinfo->arith_dc_L[i] = 0;
+    cinfo->arith_dc_U[i] = 1;
+    cinfo->arith_ac_K[i] = 5;
+  }
+  cinfo->restart_interval = 0;
+
+  cinfo->density_unit = 0;	/* set default JFIF APP0 values */
+  cinfo->X_density = 1;
+  cinfo->Y_density = 1;
+
+  cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */
+}
+
+
+LOCAL int
+next_marker (decompress_info_ptr cinfo)
+/* Find the next JPEG marker */
+/* Note that the output might not be a valid marker code, */
+/* but it will never be 0 or FF */
+{
+  int c, nbytes;
+
+  nbytes = 0;
+  do {
+    do {			/* skip any non-FF bytes */
+      nbytes++;
+      c = JGETC(cinfo);
+    } while (c != 0xFF);
+    do {			/* skip any duplicate FFs */
+      nbytes++;
+      c = JGETC(cinfo);
+    } while (c == 0xFF);
+  } while (c == 0);		/* repeat if it was a stuffed FF/00 */
+
+  if (nbytes != 2)
+    TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before marker 0x%02x",
+	     nbytes-2, c);
+
+  return c;
+}
+
+
+LOCAL JPEG_MARKER
+process_tables (decompress_info_ptr cinfo)
+/* Scan and process JPEG markers that can appear in any order */
+/* Return when an SOI, EOI, SOFn, or SOS is found */
+{
+  int c;
+
+  while (TRUE) {
+    c = next_marker(cinfo);
+      
+    switch (c) {
+    case M_SOF0:
+    case M_SOF1:
+    case M_SOF2:
+    case M_SOF3:
+    case M_SOF5:
+    case M_SOF6:
+    case M_SOF7:
+    case M_JPG:
+    case M_SOF9:
+    case M_SOF10:
+    case M_SOF11:
+    case M_SOF13:
+    case M_SOF14:
+    case M_SOF15:
+    case M_SOI:
+    case M_EOI:
+    case M_SOS:
+      return c;
+      
+    case M_DHT:
+      get_dht(cinfo);
+      break;
+      
+    case M_DAC:
+      get_dac(cinfo);
+      break;
+      
+    case M_DQT:
+      get_dqt(cinfo);
+      break;
+      
+    case M_DRI:
+      get_dri(cinfo);
+      break;
+      
+    case M_APP0:
+      get_app0(cinfo);
+      break;
+
+    case M_RST0:		/* these are all parameterless */
+    case M_RST1:
+    case M_RST2:
+    case M_RST3:
+    case M_RST4:
+    case M_RST5:
+    case M_RST6:
+    case M_RST7:
+    case M_TEM:
+      TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
+      break;
+
+    default:	/* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
+      skip_variable(cinfo, c);
+      break;
+    }
+  }
+}
+
+
+
+/*
+ * Initialize and read the file header (everything through the SOF marker).
+ */
+
+METHODDEF void
+read_file_header (decompress_info_ptr cinfo)
+{
+  int c;
+
+  /* Expect an SOI marker first */
+  if (next_marker(cinfo) == M_SOI)
+    get_soi(cinfo);
+  else
+    ERREXIT(cinfo->emethods, "File does not start with JPEG SOI marker");
+
+  /* Process markers until SOF */
+  c = process_tables(cinfo);
+
+  switch (c) {
+  case M_SOF0:
+  case M_SOF1:
+    get_sof(cinfo, c);
+    cinfo->arith_code = FALSE;
+    break;
+      
+  case M_SOF9:
+    get_sof(cinfo, c);
+    cinfo->arith_code = TRUE;
+    break;
+
+  default:
+    ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c);
+    break;
+  }
+
+  /* Figure out what colorspace we have */
+  /* (too bad the JPEG committee didn't provide a real way to specify this) */
+
+  switch (cinfo->num_components) {
+  case 1:
+    cinfo->jpeg_color_space = CS_GRAYSCALE;
+    break;
+
+  case 3:
+    /* if we saw a JFIF marker, leave it set to YCbCr; */
+    /* also leave it alone if UI has provided a value */
+    if (cinfo->jpeg_color_space == CS_UNKNOWN) {
+      short cid0 = cinfo->comp_info[0].component_id;
+      short cid1 = cinfo->comp_info[1].component_id;
+      short cid2 = cinfo->comp_info[2].component_id;
+
+      if (cid0 == 1 && cid1 == 2 && cid2 == 3)
+	cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */
+      else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
+	cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
+      else {
+	TRACEMS3(cinfo->emethods, 0,
+		 "Unrecognized component IDs %d %d %d, assuming YCbCr",
+		 cid0, cid1, cid2);
+	cinfo->jpeg_color_space = CS_YCbCr;
+      }
+    }
+    break;
+
+  case 4:
+    cinfo->jpeg_color_space = CS_CMYK;
+    break;
+
+  default:
+    cinfo->jpeg_color_space = CS_UNKNOWN;
+    break;
+  }
+}
+
+
+/*
+ * Read the start of a scan (everything through the SOS marker).
+ * Return TRUE if find SOS, FALSE if find EOI.
+ */
+
+METHODDEF boolean
+read_scan_header (decompress_info_ptr cinfo)
+{
+  int c;
+  
+  /* Process markers until SOS or EOI */
+  c = process_tables(cinfo);
+  
+  switch (c) {
+  case M_SOS:
+    get_sos(cinfo);
+    return TRUE;
+    
+  case M_EOI:
+    TRACEMS(cinfo->emethods, 1, "End Of Image");
+    return FALSE;
+
+  default:
+    ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c);
+    break;
+  }
+  return FALSE;			/* keeps lint happy */
+}
+
+
+/*
+ * Finish up after a compressed scan (series of read_jpeg_data calls);
+ * prepare for another read_scan_header call.
+ */
+
+METHODDEF void
+read_scan_trailer (decompress_info_ptr cinfo)
+{
+  /* no work needed */
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+read_file_trailer (decompress_info_ptr cinfo)
+{
+  /* no work needed */
+}
+
+
+/*
+ * The method selection routine for standard JPEG header reading.
+ * Note that this must be called by the user interface before calling
+ * jpeg_decompress.  When a non-JFIF file is to be decompressed (TIFF,
+ * perhaps), the user interface must discover the file type and call
+ * the appropriate method selection routine.
+ */
+
+GLOBAL void
+jselrjfif (decompress_info_ptr cinfo)
+{
+  cinfo->methods->read_file_header = read_file_header;
+  cinfo->methods->read_scan_header = read_scan_header;
+  /* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */
+#if 0
+  cinfo->methods->read_jpeg_data = read_jpeg_data;
+#endif
+  cinfo->methods->read_scan_trailer = read_scan_trailer;
+  cinfo->methods->read_file_trailer = read_file_trailer;
+}
+
+#endif /* JFIF_SUPPORTED */
diff --git a/jrdppm.c b/jrdppm.c
new file mode 100644
index 0000000..15e2393
--- /dev/null
+++ b/jrdppm.c
@@ -0,0 +1,124 @@
+/*
+ * jrdppm.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in PPM format.
+ * The PBMPLUS library is required (well, it will be in the real version).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications.  As they stand, they assume input from
+ * an ordinary stdio stream.  They further assume that reading begins
+ * at the start of the file; input_init may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed PPM format).
+ *
+ * These routines are invoked via the methods get_input_row
+ * and input_init/term.
+ */
+
+#include "jinclude.h"
+
+#ifdef PPM_SUPPORTED
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF void
+input_init (compress_info_ptr cinfo)
+{
+  int c, w, h, prec;
+
+  if (getc(cinfo->input_file) != 'P')
+    ERREXIT(cinfo->emethods, "Not a PPM file");
+
+  c = getc(cinfo->input_file);
+  switch (c) {
+  case '5':			/* it's a PGM file */
+    cinfo->input_components = 1;
+    cinfo->in_color_space = CS_GRAYSCALE;
+    break;
+
+  case '6':			/* it's a PPM file */
+    cinfo->input_components = 3;
+    cinfo->in_color_space = CS_RGB;
+    break;
+
+  default:
+    ERREXIT(cinfo->emethods, "Not a PPM file");
+    break;
+  }
+
+  if (fscanf(cinfo->input_file, " %d %d %d", &w, &h, &prec) != 3)
+    ERREXIT(cinfo->emethods, "Not a PPM file");
+
+  if (getc(cinfo->input_file) != '\n' || w <= 0 || h <= 0 || prec != 255)
+    ERREXIT(cinfo->emethods, "Not a PPM file");
+
+  cinfo->image_width = w;
+  cinfo->image_height = h;
+  cinfo->data_precision = 8;
+}
+
+
+/*
+ * Read one row of pixels.
+ */
+
+METHODDEF void
+get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
+{
+  register FILE * infile = cinfo->input_file;
+  register JSAMPROW ptr0, ptr1, ptr2;
+  register long col;
+  
+  if (cinfo->input_components == 1) {
+    ptr0 = pixel_row[0];
+    for (col = cinfo->image_width; col > 0; col--) {
+      *ptr0++ = getc(infile);
+    }
+  } else {
+    ptr0 = pixel_row[0];
+    ptr1 = pixel_row[1];
+    ptr2 = pixel_row[2];
+    for (col = cinfo->image_width; col > 0; col--) {
+      *ptr0++ = getc(infile);
+      *ptr1++ = getc(infile);
+      *ptr2++ = getc(infile);
+    }
+  }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+input_term (compress_info_ptr cinfo)
+{
+  /* no work required */
+}
+
+
+/*
+ * The method selection routine for PPM format input.
+ * Note that this must be called by the user interface before calling
+ * jpeg_compress.  If multiple input formats are supported, the
+ * user interface is responsible for discovering the file format and
+ * calling the appropriate method selection routine.
+ */
+
+GLOBAL void
+jselrppm (compress_info_ptr cinfo)
+{
+  cinfo->methods->input_init = input_init;
+  cinfo->methods->get_input_row = get_input_row;
+  cinfo->methods->input_term = input_term;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/jrevdct.c b/jrevdct.c
new file mode 100644
index 0000000..bafbf55
--- /dev/null
+++ b/jrevdct.c
@@ -0,0 +1,171 @@
+/*
+ * jrevdct.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the basic inverse-DCT transformation subroutine.
+ *
+ * This implementation is based on Appendix A.2 of the book
+ * "Discrete Cosine Transform---Algorithms, Advantages, Applications"
+ * by K.R. Rao and P. Yip  (Academic Press, Inc, London, 1990).
+ * It uses scaled fixed-point arithmetic instead of floating point.
+ */
+
+#include "jinclude.h"
+
+
+/* The poop on this scaling stuff is as follows:
+ *
+ * Most of the numbers (after multiplication by the constants) are
+ * (logically) shifted left by LG2_DCT_SCALE. This is undone by UNFIXH
+ * before assignment to the output array. Note that we want an additional
+ * division by 2 on the output (required by the equations).
+ *
+ * If right shifts are unsigned, then there is a potential problem.
+ * However, shifting right by 16 and then assigning to a short
+ * (assuming short = 16 bits) will keep the sign right!!
+ *
+ * For other shifts,
+ *
+ *     ((x + (1 << 30)) >> shft) - (1 << (30 - shft))
+ *
+ * gives a nice right shift with sign (assuming no overflow). However, all the
+ * scaling is such that this isn't a problem. (Is this true?)
+ */
+
+
+#define ONE 1L			/* remove L if long > 32 bits */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define LG2_DCT_SCALE 15
+#define RIGHT_SHIFT(_x,_shft)   ((((_x) + (ONE << 30)) >> (_shft)) - (ONE << (30 - (_shft))))
+#else
+#define LG2_DCT_SCALE 16
+#define RIGHT_SHIFT(_x,_shft)   ((_x) >> (_shft))
+#endif
+
+#define DCT_SCALE (ONE << LG2_DCT_SCALE)
+
+#define LG2_OVERSCALE 2
+#define OVERSCALE (ONE << LG2_OVERSCALE)
+
+#define FIX(x)  ((INT32) ((x) * DCT_SCALE + 0.5))
+#define FIXO(x)  ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
+#define UNFIX(x)   RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
+#define UNFIXH(x)  RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
+#define UNFIXO(x)  RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)), LG2_DCT_SCALE-LG2_OVERSCALE)
+#define OVERSH(x)   ((x) << LG2_OVERSCALE)
+
+#define SIN_1_4 FIX(0.7071067811856476)
+#define COS_1_4 SIN_1_4
+
+#define SIN_1_8 FIX(0.3826834323650898)
+#define COS_1_8 FIX(0.9238795325112870)
+#define SIN_3_8 COS_1_8
+#define COS_3_8 SIN_1_8
+
+#define SIN_1_16 FIX(0.1950903220161282)
+#define COS_1_16 FIX(0.9807852804032300)
+#define SIN_7_16 COS_1_16
+#define COS_7_16 SIN_1_16
+
+#define SIN_3_16 FIX(0.5555702330196022)
+#define COS_3_16 FIX(0.8314696123025450)
+#define SIN_5_16 COS_3_16
+#define COS_5_16 SIN_3_16
+
+#define OSIN_1_4 FIXO(0.707106781185647)
+#define OCOS_1_4 OSIN_1_4
+
+#define OSIN_1_8 FIXO(0.3826834323650898)
+#define OCOS_1_8 FIXO(0.9238795325112870)
+#define OSIN_3_8 OCOS_1_8
+#define OCOS_3_8 OSIN_1_8
+
+#define OSIN_1_16 FIXO(0.1950903220161282)
+#define OCOS_1_16 FIXO(0.9807852804032300)
+#define OSIN_7_16 OCOS_1_16
+#define OCOS_7_16 OSIN_1_16
+
+#define OSIN_3_16 FIXO(0.5555702330196022)
+#define OCOS_3_16 FIXO(0.8314696123025450)
+#define OSIN_5_16 OCOS_3_16
+#define OCOS_5_16 OSIN_3_16
+
+
+INLINE
+LOCAL void
+fast_idct_8 (DCTELEM *in, int stride)
+{
+  /* tmp1x are new values of tmpx -- flashy register colourers
+   * should be able to do this lot very well
+   */
+  INT32 tmp10, tmp11, tmp12, tmp13;
+  INT32 tmp20, tmp21, tmp22, tmp23;
+  INT32 tmp30, tmp31;
+  INT32 tmp40, tmp41, tmp42, tmp43;
+  INT32 tmp50, tmp51, tmp52, tmp53;
+  INT32 in0, in1, in2, in3, in4, in5, in6, in7;
+  
+  in0 = in[       0];
+  in1 = in[stride  ];
+  in2 = in[stride*2];
+  in3 = in[stride*3];
+  in4 = in[stride*4];
+  in5 = in[stride*5];
+  in6 = in[stride*6];
+  in7 = in[stride*7];
+  
+  tmp10 = (in0 + in4) * COS_1_4;
+  tmp11 = (in0 - in4) * COS_1_4;
+  tmp12 = in2 * SIN_1_8 - in6 * COS_1_8;
+  tmp13 = in6 * SIN_1_8 + in2 * COS_1_8;
+  
+  tmp20 = tmp10 + tmp13;
+  tmp21 = tmp11 + tmp12;
+  tmp22 = tmp11 - tmp12;
+  tmp23 = tmp10 - tmp13;
+  
+  tmp30 = UNFIXO((in3 + in5) * COS_1_4);
+  tmp31 = UNFIXO((in3 - in5) * COS_1_4);
+  
+  tmp40 = OVERSH(in1) + tmp30;
+  tmp41 = OVERSH(in7) + tmp31;
+  tmp42 = OVERSH(in1) - tmp30;
+  tmp43 = OVERSH(in7) - tmp31;
+  
+  tmp50 = tmp40 * OCOS_1_16 + tmp41 * OSIN_1_16;
+  tmp51 = tmp40 * OSIN_1_16 - tmp41 * OCOS_1_16;
+  tmp52 = tmp42 * OCOS_5_16 + tmp43 * OSIN_5_16;
+  tmp53 = tmp42 * OSIN_5_16 - tmp43 * OCOS_5_16;
+  
+  in[       0] = UNFIXH(tmp20 + tmp50);
+  in[stride  ] = UNFIXH(tmp21 + tmp53);
+  in[stride*2] = UNFIXH(tmp22 + tmp52);
+  in[stride*3] = UNFIXH(tmp23 + tmp51);
+  in[stride*4] = UNFIXH(tmp23 - tmp51);
+  in[stride*5] = UNFIXH(tmp22 - tmp52);
+  in[stride*6] = UNFIXH(tmp21 - tmp53);
+  in[stride*7] = UNFIXH(tmp20 - tmp50);
+}
+
+
+/*
+ * Perform the inverse DCT on one block of coefficients.
+ *
+ * Note that this code is specialized to the case DCTSIZE = 8.
+ */
+
+GLOBAL void
+j_rev_dct (DCTBLOCK data)
+{
+  int i;
+  
+  for (i = 0; i < DCTSIZE; i++)
+    fast_idct_8(data+i*DCTSIZE, 1);
+  
+  for (i = 0; i < DCTSIZE; i++)
+    fast_idct_8(data+i, DCTSIZE);
+}
diff --git a/jutils.c b/jutils.c
new file mode 100644
index 0000000..aebcaa9
--- /dev/null
+++ b/jutils.c
@@ -0,0 +1,106 @@
+/*
+ * jutils.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains miscellaneous utility routines needed for both
+ * compression and decompression.
+ * Note we prefix all global names with "j" to minimize conflicts with
+ * a surrounding application.
+ */
+
+#include "jinclude.h"
+
+
+GLOBAL long
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b; a >= 0, b > 0 */
+{
+  a += b-1;
+  return a - (a % b);
+}
+
+
+GLOBAL void
+jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
+		   JSAMPARRAY output_array, int dest_row,
+		   int num_rows, long num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas should not overlap.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+  /* On normal machines we can use memcpy().  This won't work on 80x86 because
+   * the sample arrays are FAR and we're assuming a small-pointer memory model.
+   */
+  register JSAMPROW inptr, outptr;
+#ifdef NEED_FAR_POINTERS
+  register long count;
+#else
+  register size_t count = num_cols * SIZEOF(JSAMPLE);
+#endif
+  register int row;
+
+  input_array += source_row;
+  output_array += dest_row;
+
+  for (row = num_rows; row > 0; row--) {
+    inptr = *input_array++;
+    outptr = *output_array++;
+#ifdef NEED_FAR_POINTERS
+    for (count = num_cols; count > 0; count--)
+      *outptr++ = *inptr++;	/* needn't bother with GETJSAMPLE() here */
+#else
+    memcpy((void *) outptr, (void *) inptr, count);
+#endif
+  }
+}
+
+
+GLOBAL void
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, long num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+  /* On normal machines we can use memcpy().  This won't work on 80x86 because
+   * the block arrays are FAR and we're assuming a small-pointer memory model.
+   */
+#ifdef NEED_FAR_POINTERS
+  register JCOEFPTR inptr, outptr;
+  register int i;
+  register long count;
+
+  for (count = num_blocks; count > 0; count--) {
+    inptr = *input_row++;
+    outptr = *output_row++;
+    for (i = DCTSIZE2; i > 0; i--)
+      *outptr++ = *inptr++;
+  }
+#else
+    memcpy((void *) output_row, (void *) input_row,
+	   (size_t) (num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))));
+#endif
+}
+
+
+GLOBAL void
+jzero_far (void FAR * target, size_t bytestozero)
+/* Zero out a chunk of FAR memory. */
+/* This might be sample-array data, block-array data, or alloc_medium data. */
+{
+  /* On normal machines we can use MEMZERO().  This won't work on 80x86
+   * because we're assuming a small-pointer memory model.
+   */
+#ifdef NEED_FAR_POINTERS
+  register char FAR * ptr = (char FAR *) target;
+  register size_t count;
+
+  for (count = bytestozero; count > 0; count--) {
+    *ptr++ = 0;
+  }
+#else
+  MEMZERO((void *) target, bytestozero);
+#endif
+}
diff --git a/jvirtmem.c b/jvirtmem.c
new file mode 100644
index 0000000..4a0627c
--- /dev/null
+++ b/jvirtmem.c
@@ -0,0 +1,548 @@
+/*
+ * jvirtmem.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides the system-dependent memory allocation routines
+ * for the case where we can rely on virtual memory to handle large arrays.
+ *
+ * This includes some MS-DOS code just for trial purposes; "big" arrays will
+ * have to be handled with temp files on MS-DOS, so a real implementation of
+ * a DOS memory manager will probably be a separate file.  (See additional
+ * comments about big arrays, below.)
+ * 
+ * NB: allocation routines never return NULL.
+ * They should exit to error_exit if unsuccessful.
+ */
+
+#include "jinclude.h"
+
+#ifdef __STDC__
+#include <stdlib.h>		/* to declare malloc(), free() */
+#else
+extern void * malloc PP((size_t size));
+extern void free PP((void *ptr));
+#endif
+
+
+/* Insert system-specific definitions of far_malloc, far_free here. */
+
+#ifndef NEED_FAR_POINTERS	/* Generic for non-braindamaged CPUs */
+
+#define far_malloc(x)	malloc(x)
+#define far_free(x)	free(x)
+
+#else /* NEED_FAR_POINTERS */
+
+#ifdef __TURBOC__
+/* These definitions work for Turbo C */
+#include <alloc.h>		/* need farmalloc(), farfree() */
+#define far_malloc(x)	farmalloc(x)
+#define far_free(x)	farfree(x)
+#else
+#ifdef MSDOS
+/* These definitions work for Microsoft C and compatible compilers */
+#include <malloc.h>		/* need _fmalloc(), _ffree() */
+#define far_malloc(x)	_fmalloc(x)
+#define far_free(x)	_ffree(x)
+#endif
+#endif
+
+#endif /* NEED_FAR_POINTERS */
+
+
+/*
+ * Some important notes:
+ *   The array alloc/dealloc routines are not merely a convenience;
+ *   on 80x86 machines the bottom-level pointers in an array are FAR
+ *   and thus may not be allocatable by alloc_small.
+ *
+ *   Also, it's not a good idea to try to merge the sarray and barray
+ *   routines, even though they are textually almost the same, because
+ *   samples are usually stored as bytes while coefficients are shorts.
+ *   Thus, in machines where byte pointers have a different representation
+ *   from word pointers, the resulting machine code could not be the same.
+ */
+
+
+static external_methods_ptr methods; /* saved for access to error_exit */
+
+
+#ifdef MEM_STATS		/* optional extra stuff for statistics */
+
+#define MALLOC_OVERHEAD  (SIZEOF(char *)) /* assumed overhead per request */
+#define MALLOC_FAR_OVERHEAD  (SIZEOF(char FAR *)) /* for "far" storage */
+
+static long total_num_small = 0;	/* total # of small objects alloced */
+static long total_bytes_small = 0;	/* total bytes requested */
+static long cur_num_small = 0;		/* # currently alloced */
+static long max_num_small = 0;		/* max simultaneously alloced */
+
+#ifdef NEED_FAR_POINTERS
+static long total_num_medium = 0;	/* total # of medium objects alloced */
+static long total_bytes_medium = 0;	/* total bytes requested */
+static long cur_num_medium = 0;		/* # currently alloced */
+static long max_num_medium = 0;		/* max simultaneously alloced */
+#endif
+
+static long total_num_sarray = 0;	/* total # of sarray objects alloced */
+static long total_bytes_sarray = 0;	/* total bytes requested */
+static long cur_num_sarray = 0;		/* # currently alloced */
+static long max_num_sarray = 0;		/* max simultaneously alloced */
+
+static long total_num_barray = 0;	/* total # of barray objects alloced */
+static long total_bytes_barray = 0;	/* total bytes requested */
+static long cur_num_barray = 0;		/* # currently alloced */
+static long max_num_barray = 0;		/* max simultaneously alloced */
+
+
+GLOBAL void
+j_mem_stats (void)
+{
+  /* since this is only a debugging stub, we can cheat a little on the
+   * trace message mechanism... helps 'cuz trace can't handle longs.
+   */
+  fprintf(stderr, "total_num_small = %ld\n", total_num_small);
+  fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small);
+  if (cur_num_small)
+    fprintf(stderr, "CUR_NUM_SMALL = %ld\n", cur_num_small);
+  fprintf(stderr, "max_num_small = %ld\n", max_num_small);
+  
+#ifdef NEED_FAR_POINTERS
+  fprintf(stderr, "total_num_medium = %ld\n", total_num_medium);
+  fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium);
+  if (cur_num_medium)
+    fprintf(stderr, "CUR_NUM_MEDIUM = %ld\n", cur_num_medium);
+  fprintf(stderr, "max_num_medium = %ld\n", max_num_medium);
+#endif
+  
+  fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray);
+  fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray);
+  if (cur_num_sarray)
+    fprintf(stderr, "CUR_NUM_SARRAY = %ld\n", cur_num_sarray);
+  fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray);
+  
+  fprintf(stderr, "total_num_barray = %ld\n", total_num_barray);
+  fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray);
+  if (cur_num_barray)
+    fprintf(stderr, "CUR_NUM_BARRAY = %ld\n", cur_num_barray);
+  fprintf(stderr, "max_num_barray = %ld\n", max_num_barray);
+}
+
+#endif /* MEM_STATS */
+
+
+LOCAL void
+out_of_memory (int which)
+/* Report an out-of-memory error and stop execution */
+/* If we compiled MEM_STATS support, report alloc requests before dying */
+{
+#ifdef MEM_STATS
+  j_mem_stats();
+#endif
+  ERREXIT1(methods, "Insufficient memory (case %d)", which);
+}
+
+
+
+METHODDEF void *
+alloc_small (size_t sizeofobject)
+/* Allocate a "small" (all-in-memory) object */
+{
+  void * result;
+
+#ifdef MEM_STATS
+  total_num_small++;
+  total_bytes_small += sizeofobject + MALLOC_OVERHEAD;
+  cur_num_small++;
+  if (cur_num_small > max_num_small) max_num_small = cur_num_small;
+#endif
+
+  result = malloc(sizeofobject);
+  if (result == NULL)
+    out_of_memory(1);
+  return result;
+}
+
+
+METHODDEF void
+free_small (void *ptr)
+/* Free a "small" (all-in-memory) object */
+{
+  free(ptr);
+
+#ifdef MEM_STATS
+  cur_num_small--;
+#endif
+}
+
+
+#ifdef NEED_FAR_POINTERS
+
+METHODDEF void FAR *
+alloc_medium (size_t sizeofobject)
+/* Allocate a "medium" (all in memory, but in far heap) object */
+{
+  void FAR * result;
+
+#ifdef MEM_STATS
+  total_num_medium++;
+  total_bytes_medium += sizeofobject + MALLOC_FAR_OVERHEAD;
+  cur_num_medium++;
+  if (cur_num_medium > max_num_medium) max_num_medium = cur_num_medium;
+#endif
+
+  result = far_malloc(sizeofobject);
+  if (result == NULL)
+    out_of_memory(2);
+  return result;
+}
+
+
+METHODDEF void
+free_medium (void FAR *ptr)
+/* Free a "medium" (all in memory, but in far heap) object */
+{
+  far_free(ptr);
+
+#ifdef MEM_STATS
+  cur_num_medium--;
+#endif
+}
+
+#endif /* NEED_FAR_POINTERS */
+
+
+METHODDEF JSAMPARRAY
+alloc_small_sarray (long samplesperrow, long numrows)
+/* Allocate a "small" (all-in-memory) 2-D sample array */
+{
+  JSAMPARRAY result;
+  long i;
+
+#ifdef MEM_STATS
+  total_num_sarray++;
+  total_bytes_sarray += (samplesperrow * SIZEOF(JSAMPLE) + MALLOC_FAR_OVERHEAD)
+			* numrows;
+  cur_num_sarray++;
+  if (cur_num_sarray > max_num_sarray) max_num_sarray = cur_num_sarray;
+#endif
+
+  /* Get space for row pointers; this is always "near" on 80x86 */
+  result = (JSAMPARRAY) alloc_small((size_t) (numrows * SIZEOF(JSAMPROW)));
+
+  /* Get the rows themselves; on 80x86 these are "far" */
+  for (i = 0; i < numrows; i++) {
+    result[i] = (JSAMPROW) far_malloc((size_t) (samplesperrow * SIZEOF(JSAMPLE)));
+    if (result[i] == NULL)
+      out_of_memory(3);
+  }
+
+  return result;
+}
+
+
+METHODDEF void
+free_small_sarray (JSAMPARRAY ptr, long numrows)
+/* Free a "small" (all-in-memory) 2-D sample array */
+{
+  long i;
+
+  /* Free the rows themselves; on 80x86 these are "far" */
+  for (i = 0; i < numrows; i++) {
+    far_free((void FAR *) ptr[i]);
+  }
+
+  /* Free space for row pointers; this is always "near" on 80x86 */
+  free_small((void *) ptr);
+
+#ifdef MEM_STATS
+  cur_num_sarray--;
+#endif
+}
+
+
+METHODDEF JBLOCKARRAY
+alloc_small_barray (long blocksperrow, long numrows)
+/* Allocate a "small" (all-in-memory) 2-D coefficient-block array */
+{
+  JBLOCKARRAY result;
+  long i;
+
+#ifdef MEM_STATS
+  total_num_barray++;
+  total_bytes_barray += (blocksperrow * SIZEOF(JBLOCK) + MALLOC_FAR_OVERHEAD)
+			* numrows;
+  cur_num_barray++;
+  if (cur_num_barray > max_num_barray) max_num_barray = cur_num_barray;
+#endif
+
+  /* Get space for row pointers; this is always "near" on 80x86 */
+  result = (JBLOCKARRAY) alloc_small((size_t) (numrows * SIZEOF(JBLOCKROW)));
+
+  /* Get the rows themselves; on 80x86 these are "far" */
+  for (i = 0; i < numrows; i++) {
+    result[i] = (JBLOCKROW) far_malloc((size_t) (blocksperrow * SIZEOF(JBLOCK)));
+    if (result[i] == NULL)
+      out_of_memory(4);
+  }
+
+  return result;
+}
+
+
+METHODDEF void
+free_small_barray (JBLOCKARRAY ptr, long numrows)
+/* Free a "small" (all-in-memory) 2-D coefficient-block array */
+{
+  long i;
+
+  /* Free the rows themselves; on 80x86 these are "far" */
+  for (i = 0; i < numrows; i++) {
+    far_free((void FAR *) ptr[i]);
+  }
+
+  /* Free space for row pointers; this is always "near" on 80x86 */
+  free_small((void *) ptr);
+
+#ifdef MEM_STATS
+  cur_num_barray--;
+#endif
+}
+
+
+
+/*
+ * About "big" array management:
+ *
+ * To allow machines with limited memory to handle large images,
+ * all processing in the JPEG system is done a few pixel or block rows
+ * at a time.  The above "small" array routines are only used to allocate
+ * strip buffers (as wide as the image, but just a few rows high).
+ * In some cases multiple passes must be made over the data.  In these
+ * cases the "big" array routines are used.  The array is still accessed
+ * a strip at a time, but the memory manager must save the whole array
+ * for repeated accesses.  The intended implementation is that there is
+ * a strip buffer in memory (as high as is possible given the desired memory
+ * limit), plus a backing file that holds the rest of the array.
+ *
+ * The request_big_array routines are told the total size of the image (in case
+ * it is useful to know the total file size that will be needed).  They are
+ * also given the unit height, which is the number of rows that will be
+ * accessed at once; the in-memory buffer should usually be made a multiple of
+ * this height for best efficiency.
+ *
+ * The request routines create control blocks (and may open backing files),
+ * but they don't create the in-memory buffers.  This is postponed until
+ * alloc_big_arrays is called.  At that time the total amount of space needed
+ * is known (approximately, anyway), so free memory can be divided up fairly.
+ *
+ * The access_big_array routines are responsible for making a specific strip
+ * area accessible (after reading or writing the backing file, if necessary).
+ * Note that the access routines are told whether the caller intends to modify
+ * the accessed strip; during a read-only pass this saves having to rewrite
+ * data to disk.
+ *
+ * The typical access pattern is one top-to-bottom pass to write the data,
+ * followed by one or more read-only top-to-bottom passes.  However, other
+ * access patterns may occur while reading.  For example, translation of image
+ * formats that use bottom-to-top scan order will require bottom-to-top read
+ * passes.  The memory manager need not support multiple write passes nor
+ * funny write orders (meaning that rearranging rows must be handled while
+ * reading data out of the big array, not while putting it in).
+ *
+ * In current usage, the access requests are always for nonoverlapping strips;
+ * that is, successive access start_row numbers always differ by exactly the
+ * unitheight.  This allows fairly simple buffer dump/reload logic if the
+ * in-memory buffer is made a multiple of the unitheight.  It would be
+ * possible to keep subsampled rather than fullsize data in the "big" arrays,
+ * thus reducing temp file size, if we supported overlapping strip access
+ * (access requests differing by less than the unitheight).  At the moment
+ * I don't believe this is worth the extra complexity.
+ *
+ * This particular implementation doesn't use temp files; the whole of a big
+ * array is allocated in (virtual) memory, and any swapping is done behind the
+ * scenes by the operating system.
+ */
+
+
+
+/* The control blocks for virtual arrays.
+ * These are pretty minimal in this implementation.
+ * Note: in this implementation we could realize big arrays
+ * at request time and make alloc_big_arrays a no-op;
+ * however, doing it separately keeps callers honest.
+ */
+
+struct big_sarray_control {
+	JSAMPARRAY mem_buffer;	/* memory buffer (the whole thing, here) */
+	long rows_in_mem;	/* Height of memory buffer */
+	long samplesperrow;	/* Width of memory buffer */
+	long unitheight;	/* # of rows accessed by access_big_sarray() */
+	big_sarray_ptr next;	/* list link for unrealized arrays */
+};
+
+struct big_barray_control {
+	JBLOCKARRAY mem_buffer;	/* memory buffer (the whole thing, here) */
+	long rows_in_mem;	/* Height of memory buffer */
+	long blocksperrow;	/* Width of memory buffer */
+	long unitheight;	/* # of rows accessed by access_big_barray() */
+	big_barray_ptr next;	/* list link for unrealized arrays */
+};
+
+
+/* Headers of lists of control blocks for unrealized big arrays */
+static big_sarray_ptr unalloced_sarrays;
+static big_barray_ptr unalloced_barrays;
+
+
+METHODDEF big_sarray_ptr
+request_big_sarray (long samplesperrow, long numrows, long unitheight)
+/* Request a "big" (virtual-memory) 2-D sample array */
+{
+  big_sarray_ptr result;
+
+  /* get control block */
+  result = (big_sarray_ptr) alloc_small(SIZEOF(struct big_sarray_control));
+
+  result->mem_buffer = NULL;	/* lets access routine spot premature access */
+  result->rows_in_mem = numrows;
+  result->samplesperrow = samplesperrow;
+  result->unitheight = unitheight;
+  result->next = unalloced_sarrays; /* add to list of unallocated arrays */
+  unalloced_sarrays = result;
+
+  return result;
+}
+
+
+METHODDEF big_barray_ptr
+request_big_barray (long blocksperrow, long numrows, long unitheight)
+/* Request a "big" (virtual-memory) 2-D coefficient-block array */
+{
+  big_barray_ptr result;
+
+  /* get control block */
+  result = (big_barray_ptr) alloc_small(SIZEOF(struct big_barray_control));
+
+  result->mem_buffer = NULL;	/* lets access routine spot premature access */
+  result->rows_in_mem = numrows;
+  result->blocksperrow = blocksperrow;
+  result->unitheight = unitheight;
+  result->next = unalloced_barrays; /* add to list of unallocated arrays */
+  unalloced_barrays = result;
+
+  return result;
+}
+
+
+METHODDEF void
+alloc_big_arrays (long extra_small_samples, long extra_small_blocks,
+		  long extra_medium_space)
+/* Allocate the in-memory buffers for any unrealized "big" arrays */
+/* 'extra' values are upper bounds for total future small-array requests */
+/* and far-heap requests */
+{
+  /* In this implementation we just malloc the whole arrays */
+  /* and expect the system's virtual memory to worry about swapping them */
+  big_sarray_ptr sptr;
+  big_barray_ptr bptr;
+
+  for (sptr = unalloced_sarrays; sptr != NULL; sptr = sptr->next) {
+    sptr->mem_buffer = alloc_small_sarray(sptr->samplesperrow,
+					  sptr->rows_in_mem);
+  }
+
+  for (bptr = unalloced_barrays; bptr != NULL; bptr = bptr->next) {
+    bptr->mem_buffer = alloc_small_barray(bptr->blocksperrow,
+					  bptr->rows_in_mem);
+  }
+
+  unalloced_sarrays = NULL;	/* reset for possible future cycles */
+  unalloced_barrays = NULL;
+}
+
+
+METHODDEF JSAMPARRAY
+access_big_sarray (big_sarray_ptr ptr, long start_row, boolean writable)
+/* Access the part of a "big" sample array starting at start_row */
+/* and extending for ptr->unitheight rows.  writable is true if  */
+/* caller intends to modify the accessed area. */
+{
+  /* debugging check */
+  if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
+      ptr->mem_buffer == NULL)
+    ERREXIT(methods, "Bogus access_big_sarray request");
+
+  return ptr->mem_buffer + start_row;
+}
+
+
+METHODDEF JBLOCKARRAY
+access_big_barray (big_barray_ptr ptr, long start_row, boolean writable)
+/* Access the part of a "big" coefficient-block array starting at start_row */
+/* and extending for ptr->unitheight rows.  writable is true if  */
+/* caller intends to modify the accessed area. */
+{
+  /* debugging check */
+  if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
+      ptr->mem_buffer == NULL)
+    ERREXIT(methods, "Bogus access_big_barray request");
+
+  return ptr->mem_buffer + start_row;
+}
+
+
+METHODDEF void
+free_big_sarray (big_sarray_ptr ptr)
+/* Free a "big" (virtual-memory) 2-D sample array */
+{
+  free_small_sarray(ptr->mem_buffer, ptr->rows_in_mem);
+  free_small((void *) ptr);	/* free the control block too */
+}
+
+
+METHODDEF void
+free_big_barray (big_barray_ptr ptr)
+/* Free a "big" (virtual-memory) 2-D coefficient-block array */
+{
+  free_small_barray(ptr->mem_buffer, ptr->rows_in_mem);
+  free_small((void *) ptr);	/* free the control block too */
+}
+
+
+
+/*
+ * The method selection routine for virtual memory systems.
+ * The system-dependent setup routine should call this routine
+ * to install the necessary method pointers in the supplied struct.
+ */
+
+GLOBAL void
+jselvirtmem (external_methods_ptr emethods)
+{
+  methods = emethods;		/* save struct addr for error exit access */
+
+  emethods->alloc_small = alloc_small;
+  emethods->free_small = free_small;
+#ifdef NEED_FAR_POINTERS
+  emethods->alloc_medium = alloc_medium;
+  emethods->free_medium = free_medium;
+#endif
+  emethods->alloc_small_sarray = alloc_small_sarray;
+  emethods->free_small_sarray = free_small_sarray;
+  emethods->alloc_small_barray = alloc_small_barray;
+  emethods->free_small_barray = free_small_barray;
+  emethods->request_big_sarray = request_big_sarray;
+  emethods->request_big_barray = request_big_barray;
+  emethods->alloc_big_arrays = alloc_big_arrays;
+  emethods->access_big_sarray = access_big_sarray;
+  emethods->access_big_barray = access_big_barray;
+  emethods->free_big_sarray = free_big_sarray;
+  emethods->free_big_barray = free_big_barray;
+
+  unalloced_sarrays = NULL;	/* make sure list headers are empty */
+  unalloced_barrays = NULL;
+}
diff --git a/jwrgif.c b/jwrgif.c
new file mode 100644
index 0000000..44062ec
--- /dev/null
+++ b/jwrgif.c
@@ -0,0 +1,497 @@
+/*
+ * jwrgif.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in GIF format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications.  As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * These routines are invoked via the methods put_pixel_rows, put_color_map,
+ * and output_init/term.
+ */
+
+/*
+ * This code is loosely based on ppmtogif from the PBMPLUS distribution
+ * of Feb. 1991.  That file contains the following copyright notice:
+ *    Based on GIFENCODE by David Rowley <mgardi@watdscu.waterloo.edu>.
+ *    Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
+ *    Copyright (C) 1989 by Jef Poskanzer.
+ *    Permission to use, copy, modify, and distribute this software and its
+ *    documentation for any purpose and without fee is hereby granted, provided
+ *    that the above copyright notice appear in all copies and that both that
+ *    copyright notice and this permission notice appear in supporting
+ *    documentation.  This software is provided "as is" without express or
+ *    implied warranty.
+ *
+ * We are also required to state that
+ *    "The Graphics Interchange Format(c) is the Copyright property of
+ *    CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ *    CompuServe Incorporated."
+ */
+
+#include "jinclude.h"
+
+#ifdef GIF_SUPPORTED
+
+
+static decompress_info_ptr dcinfo; /* to avoid passing to all functions */
+
+#define	MAX_LZW_BITS	12	/* maximum LZW code size (4096 symbols) */
+
+typedef INT16 code_int;		/* must hold -1 .. 2**MAX_LZW_BITS */
+
+#define LZW_TABLE_SIZE	((code_int) 1 << MAX_LZW_BITS)
+
+#define HSIZE		5003	/* hash table size for 80% occupancy */
+
+typedef int hash_int;		/* must hold -2*HSIZE..2*HSIZE */
+
+static int n_bits;		/* current number of bits/code */
+static code_int maxcode;	/* maximum code, given n_bits */
+#define MAXCODE(n_bits)	(((code_int) 1 << (n_bits)) - 1)
+
+static int init_bits;		/* initial n_bits ... restored after clear */
+
+static code_int ClearCode;	/* clear code (doesn't change) */
+static code_int EOFCode;	/* EOF code (ditto) */
+
+static code_int free_code;	/* first not-yet-used symbol code */
+
+/*
+ * The LZW hash table consists of three parallel arrays:
+ *   hash_code[i]	code of symbol in slot i, or 0 if empty slot
+ *   hash_prefix[i]	symbol's prefix code; undefined if empty slot
+ *   hash_suffix[i]	symbol's suffix character; undefined if empty slot
+ * where slot values (i) range from 0 to HSIZE-1.
+ *
+ * Algorithm:  use open addressing double hashing (no chaining) on the
+ * prefix code / suffix character combination.  We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe.
+ *
+ * The hash tables are allocated from FAR heap space since they would use up
+ * rather a lot of the near data space in a PC.
+ */
+
+static code_int FAR *hash_code;	/* => hash table of symbol codes */
+static code_int FAR *hash_prefix; /* => hash table of prefix symbols */
+static UINT8 FAR *hash_suffix;	/* => hash table of suffix bytes */
+
+
+/*
+ * Routines to package compressed data bytes into GIF data blocks.
+ * A data block consists of a count byte (1..255) and that many data bytes.
+ */
+
+static int bytesinpkt;		/* # of bytes in current packet */
+static char packetbuf[256];	/* workspace for accumulating packet */
+
+
+LOCAL void
+flush_packet (void)
+/* flush any accumulated data */
+{
+  if (bytesinpkt > 0) {		/* never write zero-length packet */
+    packetbuf[0] = bytesinpkt++;
+    if (fwrite(packetbuf, 1, bytesinpkt, dcinfo->output_file) != bytesinpkt)
+      ERREXIT(dcinfo->emethods, "Output file write error");
+    bytesinpkt = 0;
+  }
+}
+
+
+LOCAL void
+char_out (int c)
+/* Add a character to current packet; flush to disk if necessary */
+{
+  packetbuf[++bytesinpkt] = c;
+  if (bytesinpkt >= 255)
+    flush_packet();
+}
+
+
+/* Routine to convert variable-width codes into a byte stream */
+
+static INT32 cur_accum;		/* holds bits not yet output */
+static int cur_bits;		/* # of bits in cur_accum */
+
+
+LOCAL void
+output (code_int code)
+/* Emit a code of n_bits bits */
+/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
+{
+  if (cur_bits > 0)
+    cur_accum |= ((INT32) code << cur_bits);
+  else
+    cur_accum = code;
+  cur_bits += n_bits;
+
+  while (cur_bits >= 8) {
+    char_out((int) (cur_accum & 0xFF));
+    cur_accum >>= 8;
+    cur_bits -= 8;
+  }
+
+  /*
+   * If the next entry is going to be too big for the code size,
+   * then increase it, if possible.  We do this here to ensure
+   * that it's done in sync with the decoder's codesize increases.
+   */
+  if (free_code > maxcode) {
+    n_bits++;
+    if (n_bits == MAX_LZW_BITS)
+      maxcode = LZW_TABLE_SIZE;	/* free_code will never exceed this */
+    else
+      maxcode = MAXCODE(n_bits);
+  }
+}
+
+
+/* The LZW algorithm proper */
+
+static code_int waiting_code;	/* symbol not yet output; may be extendable */
+static boolean first_byte;	/* if TRUE, waiting_code is not valid */
+
+
+LOCAL void
+clear_hash (void)
+/* Fill the hash table with empty entries */
+{
+  /* It's sufficient to zero hash_code[] */
+  jzero_far((void FAR *) hash_code, HSIZE * SIZEOF(code_int));
+}
+
+
+LOCAL void
+clear_block (void)
+/* Reset compressor and issue a Clear code */
+{
+  clear_hash();			/* delete all the symbols */
+  free_code = ClearCode + 2;
+  output(ClearCode);		/* inform decoder */
+  n_bits = init_bits;		/* reset code size */
+  maxcode = MAXCODE(n_bits);
+}
+
+
+LOCAL void
+compress_init (int i_bits)
+/* Initialize LZW compressor */
+{
+  /* init all the static variables */
+  n_bits = init_bits = i_bits;
+  maxcode = MAXCODE(n_bits);
+  ClearCode = ((code_int) 1 << (init_bits - 1));
+  EOFCode = ClearCode + 1;
+  free_code = ClearCode + 2;
+  first_byte = TRUE;		/* no waiting symbol yet */
+  /* init output buffering vars */
+  bytesinpkt = 0;
+  cur_accum = 0;
+  cur_bits = 0;
+  /* clear hash table */
+  clear_hash();
+  /* GIF specifies an initial Clear code */
+  output(ClearCode);
+}
+
+
+LOCAL void
+compress_byte (int c)
+/* Accept and compress one 8-bit byte */
+{
+  register hash_int i;
+  register hash_int disp;
+
+  if (first_byte) {		/* need to initialize waiting_code */
+    waiting_code = c;
+    first_byte = FALSE;
+    return;
+  }
+
+  /* Probe hash table to see if a symbol exists for
+   * waiting_code followed by c.
+   * If so, replace waiting_code by that symbol and return.
+   */
+  i = ((hash_int) c << (MAX_LZW_BITS-8)) + waiting_code;
+  /* i is less than twice 2**MAX_LZW_BITS, therefore less than twice HSIZE */
+  if (i >= HSIZE)
+    i -= HSIZE;
+  
+  if (hash_code[i] != 0) {	/* is first probed slot empty? */
+    if (hash_prefix[i] == waiting_code && hash_suffix[i] == c) {
+      waiting_code = hash_code[i];
+      return;
+    }
+    if (i == 0)			/* secondary hash (after G. Knott) */
+      disp = 1;
+    else
+      disp = HSIZE - i;
+    while (1) {
+      i -= disp;
+      if (i < 0)
+	i += HSIZE;
+      if (hash_code[i] == 0)
+	break;			/* hit empty slot */
+      if (hash_prefix[i] == waiting_code && hash_suffix[i] == c) {
+	waiting_code = hash_code[i];
+	return;
+      }
+    }
+  }
+
+  /* here when hashtable[i] is an empty slot; desired symbol not in table */
+  output(waiting_code);
+  if (free_code < LZW_TABLE_SIZE) {
+    hash_code[i] = free_code++;	/* add symbol to hashtable */
+    hash_prefix[i] = waiting_code;
+    hash_suffix[i] = c;
+  } else
+    clear_block();
+  waiting_code = c;
+}
+
+
+LOCAL void
+compress_term (void)
+/* Clean up at end */
+{
+  /* Flush out the buffered code */
+  if (! first_byte)
+    output(waiting_code);
+  /* Send an EOF code */
+  output(EOFCode);
+  /* Flush the bit-packing buffer */
+  if (cur_bits > 0) {
+    char_out((int) (cur_accum & 0xFF));
+  }
+  /* Flush the packet buffer */
+  flush_packet();
+}
+
+
+/* GIF header construction */
+
+
+LOCAL void
+put_word (UINT16 w)
+/* Emit a 16-bit word, LSB first */
+{
+  putc(w & 0xFF, dcinfo->output_file);
+  putc((w >> 8) & 0xFF, dcinfo->output_file);
+}
+
+
+LOCAL void
+put_3bytes (int val)
+/* Emit 3 copies of same byte value --- handy subr for colormap construction */
+{
+  putc(val, dcinfo->output_file);
+  putc(val, dcinfo->output_file);
+  putc(val, dcinfo->output_file);
+}
+
+
+LOCAL void
+emit_header (int num_colors, JSAMPARRAY colormap)
+/* Output the GIF file header, including color map */
+/* If colormap==NULL, synthesize a gray-scale colormap */
+{
+  int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
+  int i;
+
+  if (num_colors > 256)
+    ERREXIT(dcinfo->emethods, "GIF can only handle 256 colors");
+  /* Compute bits/pixel and related values */
+  if (num_colors <= 2)
+    BitsPerPixel = 1;
+  else if (num_colors <= 4)
+    BitsPerPixel = 2;
+  else if (num_colors <= 8)
+    BitsPerPixel = 3;
+  else if (num_colors <= 16)
+    BitsPerPixel = 4;
+  else if (num_colors <= 32)
+    BitsPerPixel = 5;
+  else if (num_colors <= 64)
+    BitsPerPixel = 6;
+  else if (num_colors <= 128)
+    BitsPerPixel = 7;
+  else
+    BitsPerPixel = 8;
+  ColorMapSize = 1 << BitsPerPixel;
+  if (BitsPerPixel <= 1)
+    InitCodeSize = 2;
+  else
+    InitCodeSize = BitsPerPixel;
+  /*
+   * Write the GIF header.
+   * Note that we generate a plain GIF87 header for maximum compatibility.
+   */
+  fwrite("GIF87a", 1, 6, dcinfo->output_file);
+  /* Write the Logical Screen Descriptor */
+  put_word((UINT16) dcinfo->image_width);
+  put_word((UINT16) dcinfo->image_height);
+  FlagByte = 0x80;		/* Yes, there is a global color table */
+  FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
+  FlagByte |= (BitsPerPixel-1);	/* size of global color table */
+  putc(FlagByte, dcinfo->output_file);
+  putc(0, dcinfo->output_file);	/* Background color index */
+  putc(0, dcinfo->output_file);	/* Reserved in GIF87 (aspect ratio in GIF89) */
+  /* Write the Global Color Map */
+  for (i=0; i < ColorMapSize; i++) {
+    if (i < num_colors) {
+      if (colormap != NULL) {
+	if (dcinfo->out_color_space == CS_RGB) {
+	  /* Normal case: RGB color map */
+	  putc(GETJSAMPLE(colormap[0][i]), dcinfo->output_file);
+	  putc(GETJSAMPLE(colormap[1][i]), dcinfo->output_file);
+	  putc(GETJSAMPLE(colormap[2][i]), dcinfo->output_file);
+	} else {
+	  /* Grayscale "color map": possible if quantizing grayscale image */
+	  put_3bytes(GETJSAMPLE(colormap[0][i]));
+	}
+      } else {
+	/* Create a gray-scale map of num_colors values, range 0..255 */
+	put_3bytes((i * 255 + (num_colors-1)/2) / (num_colors-1));
+      }
+    } else {
+      /* fill out the map to a power of 2 */
+      put_3bytes(0);
+    }
+  }
+  /* Write image separator and Image Descriptor */
+  putc(',', dcinfo->output_file); /* separator */
+  put_word((UINT16) 0);		/* left/top offset */
+  put_word((UINT16) 0);
+  put_word((UINT16) dcinfo->image_width); /* image size */
+  put_word((UINT16) dcinfo->image_height);
+  /* flag byte: not interlaced, no local color map */
+  putc(0x00, dcinfo->output_file);
+  /* Write Initial Code Size byte */
+  putc(InitCodeSize, dcinfo->output_file);
+
+  /* Initialize for LZW compression of image data */
+  compress_init(InitCodeSize+1);
+}
+
+
+
+/*
+ * Initialize for GIF output.
+ */
+
+METHODDEF void
+output_init (decompress_info_ptr cinfo)
+{
+  dcinfo = cinfo;		/* save for use by local routines */
+  if (cinfo->final_out_comps != 1) /* safety check */
+    ERREXIT(cinfo->emethods, "GIF output got confused");
+  /* Allocate space for hash table */
+  hash_code = (code_int FAR *) (*cinfo->emethods->alloc_medium)
+				(HSIZE * SIZEOF(code_int));
+  hash_prefix = (code_int FAR *) (*cinfo->emethods->alloc_medium)
+				(HSIZE * SIZEOF(code_int));
+  hash_suffix = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
+				(HSIZE * SIZEOF(UINT8));
+  /*
+   * If we aren't quantizing, put_color_map won't be called,
+   * so emit the header now.  This only happens with gray scale output.
+   * (If we are quantizing, wait for the color map to be provided.)
+   */
+  if (! cinfo->quantize_colors)
+    emit_header(256, (JSAMPARRAY) NULL);
+}
+
+
+/*
+ * Write the color map.
+ */
+
+METHODDEF void
+put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
+{
+  emit_header(num_colors, colormap);
+}
+
+
+/*
+ * Write some pixel data.
+ */
+
+METHODDEF void
+put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
+		JSAMPIMAGE pixel_data)
+{
+  register JSAMPROW ptr;
+  register long col;
+  register long width = cinfo->image_width;
+  register int row;
+  
+  for (row = 0; row < num_rows; row++) {
+    ptr = pixel_data[0][row];
+    for (col = width; col > 0; col--) {
+      compress_byte(GETJSAMPLE(*ptr));
+      ptr++;
+    }
+  }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+output_term (decompress_info_ptr cinfo)
+{
+  /* Flush LZW mechanism */
+  compress_term();
+  /* Write a zero-length data block to end the series */
+  putc(0, cinfo->output_file);
+  /* Write the GIF terminator mark */
+  putc(';', cinfo->output_file);
+  /* Make sure we wrote the output file OK */
+  fflush(cinfo->output_file);
+  if (ferror(cinfo->output_file))
+    ERREXIT(cinfo->emethods, "Output file write error");
+  /* Free space */
+  (*cinfo->emethods->free_medium) ((void FAR *) hash_code);
+  (*cinfo->emethods->free_medium) ((void FAR *) hash_prefix);
+  (*cinfo->emethods->free_medium) ((void FAR *) hash_suffix);
+}
+
+
+/*
+ * The method selection routine for GIF format output.
+ * This should be called from d_ui_method_selection if GIF output is wanted.
+ */
+
+GLOBAL void
+jselwgif (decompress_info_ptr cinfo)
+{
+  cinfo->methods->output_init = output_init;
+  cinfo->methods->put_color_map = put_color_map;
+  cinfo->methods->put_pixel_rows = put_pixel_rows;
+  cinfo->methods->output_term = output_term;
+
+  if (cinfo->out_color_space != CS_GRAYSCALE &&
+      cinfo->out_color_space != CS_RGB)
+    ERREXIT(cinfo->emethods, "GIF output must be grayscale or RGB");
+
+  /* Force quantization if color or if > 8 bits input */
+  if (cinfo->out_color_space == CS_RGB || cinfo->data_precision > 8) {
+    /* Force quantization to at most 256 colors */
+    cinfo->quantize_colors = TRUE;
+    if (cinfo->desired_number_of_colors > 256)
+      cinfo->desired_number_of_colors = 256;
+  }
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/jwrjfif.c b/jwrjfif.c
new file mode 100644
index 0000000..cc379ac
--- /dev/null
+++ b/jwrjfif.c
@@ -0,0 +1,468 @@
+/*
+ * jwrjfif.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write standard JPEG file headers/markers.
+ * The file format created is a raw JPEG data stream with (optionally) an
+ * APP0 marker per the JFIF spec.  This will handle baseline and
+ * JFIF-convention JPEG files, although there is currently no provision
+ * for inserting a thumbnail image in the JFIF header.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications.  As they stand, they assume output to
+ * an ordinary stdio stream.  However, the changes to write to something
+ * else are localized in the macros appearing just below.
+ *
+ * These routines are invoked via the methods write_file_header,
+ * write_scan_header, write_jpeg_data, write_scan_trailer, and
+ * write_file_trailer.
+ */
+
+#include "jinclude.h"
+
+#ifdef JFIF_SUPPORTED
+
+
+/*
+ * To output to something other than a stdio stream, you'd need to redefine
+ * these macros.
+ */
+
+/* Write a single byte */
+#define emit_byte(cinfo,x)  putc((x), cinfo->output_file)
+
+/* Write some bytes from a (char *) buffer */
+#define WRITE_BYTES(cinfo,dataptr,datacount)  \
+  { if (fwrite((dataptr), 1, (datacount), cinfo->output_file) != (datacount)) \
+      ERREXIT(cinfo->emethods, "Output file write error"); }
+
+/* Clean up and verify successful output */
+#define CHECK_OUTPUT(cinfo)  \
+  { fflush(cinfo->output_file); \
+    if (ferror(cinfo->output_file)) \
+      ERREXIT(cinfo->emethods, "Output file write error"); }
+
+
+/* End of stdio-specific code. */
+
+
+typedef enum {			/* JPEG marker codes */
+  M_SOF0  = 0xc0,
+  M_SOF1  = 0xc1,
+  M_SOF2  = 0xc2,
+  M_SOF3  = 0xc3,
+  
+  M_SOF5  = 0xc5,
+  M_SOF6  = 0xc6,
+  M_SOF7  = 0xc7,
+  
+  M_JPG   = 0xc8,
+  M_SOF9  = 0xc9,
+  M_SOF10 = 0xca,
+  M_SOF11 = 0xcb,
+  
+  M_SOF13 = 0xcd,
+  M_SOF14 = 0xce,
+  M_SOF15 = 0xcf,
+  
+  M_DHT   = 0xc4,
+  
+  M_DAC   = 0xcc,
+  
+  M_RST0  = 0xd0,
+  M_RST1  = 0xd1,
+  M_RST2  = 0xd2,
+  M_RST3  = 0xd3,
+  M_RST4  = 0xd4,
+  M_RST5  = 0xd5,
+  M_RST6  = 0xd6,
+  M_RST7  = 0xd7,
+  
+  M_SOI   = 0xd8,
+  M_EOI   = 0xd9,
+  M_SOS   = 0xda,
+  M_DQT   = 0xdb,
+  M_DNL   = 0xdc,
+  M_DRI   = 0xdd,
+  M_DHP   = 0xde,
+  M_EXP   = 0xdf,
+  
+  M_APP0  = 0xe0,
+  M_APP15 = 0xef,
+  
+  M_JPG0  = 0xf0,
+  M_JPG13 = 0xfd,
+  M_COM   = 0xfe,
+  
+  M_TEM   = 0x01,
+  
+  M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+LOCAL void
+emit_marker (compress_info_ptr cinfo, JPEG_MARKER mark)
+/* Emit a marker code */
+{
+  emit_byte(cinfo, 0xFF);
+  emit_byte(cinfo, mark);
+}
+
+
+LOCAL void
+emit_2bytes (compress_info_ptr cinfo, int value)
+/* Emit a 2-byte integer; these are always MSB first in JPEG files */
+{
+  emit_byte(cinfo, (value >> 8) & 0xFF);
+  emit_byte(cinfo, value & 0xFF);
+}
+
+
+LOCAL int
+emit_dqt (compress_info_ptr cinfo, int index)
+/* Emit a DQT marker */
+/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
+{
+  QUANT_TBL_PTR data = cinfo->quant_tbl_ptrs[index];
+  int prec = 0;
+  int i;
+  
+  for (i = 0; i < DCTSIZE2; i++) {
+    if (data[i] > 255)
+      prec = 1;
+  }
+
+  emit_marker(cinfo, M_DQT);
+  
+  emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+  
+  emit_byte(cinfo, index + (prec<<4));
+  
+  for (i = 0; i < DCTSIZE2; i++) {
+    if (prec)
+      emit_byte(cinfo, data[i] >> 8);
+    emit_byte(cinfo, data[i] & 0xFF);
+  }
+
+  return prec;
+}
+
+
+LOCAL void
+emit_dht (compress_info_ptr cinfo, int index, boolean is_ac)
+/* Emit a DHT marker */
+{
+  HUFF_TBL * htbl;
+  int length, i;
+  
+  if (is_ac) {
+    htbl = cinfo->ac_huff_tbl_ptrs[index];
+    index += 0x10;		/* output index has AC bit set */
+  } else {
+    htbl = cinfo->dc_huff_tbl_ptrs[index];
+  }
+  
+  if (! htbl->sent_table) {
+    emit_marker(cinfo, M_DHT);
+    
+    length = 0;
+    for (i = 1; i <= 16; i++)
+      length += htbl->bits[i];
+    
+    emit_2bytes(cinfo, length + 2 + 1 + 16);
+    emit_byte(cinfo, index);
+    
+    for (i = 1; i <= 16; i++)
+      emit_byte(cinfo, htbl->bits[i]);
+    
+    for (i = 0; i < length; i++)
+      emit_byte(cinfo, htbl->huffval[i]);
+    
+    htbl->sent_table = TRUE;
+  }
+}
+
+
+LOCAL void
+emit_dac (compress_info_ptr cinfo)
+/* Emit a DAC marker */
+/* Since the useful info is so small, we want to emit all the tables in */
+/* one DAC marker.  Therefore this routine does its own scan of the table. */
+{
+  char dc_in_use[NUM_ARITH_TBLS];
+  char ac_in_use[NUM_ARITH_TBLS];
+  int length, i;
+  
+  for (i = 0; i < NUM_ARITH_TBLS; i++)
+    dc_in_use[i] = ac_in_use[i] = 0;
+  
+  for (i = 0; i < cinfo->num_components; i++) {
+    dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1;
+    ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1;
+  }
+  
+  length = 0;
+  for (i = 0; i < NUM_ARITH_TBLS; i++)
+    length += dc_in_use[i] + ac_in_use[i];
+  
+  emit_marker(cinfo, M_DAC);
+  
+  emit_2bytes(cinfo, length*2 + 2);
+  
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    if (dc_in_use[i]) {
+      emit_byte(cinfo, i);
+      emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+    }
+    if (ac_in_use[i]) {
+      emit_byte(cinfo, i + 0x10);
+      emit_byte(cinfo, cinfo->arith_ac_K[i]);
+    }
+  }
+}
+
+
+LOCAL void
+emit_dri (compress_info_ptr cinfo)
+/* Emit a DRI marker */
+{
+  emit_marker(cinfo, M_DRI);
+  
+  emit_2bytes(cinfo, 4);	/* fixed length */
+
+  emit_2bytes(cinfo, (int) cinfo->restart_interval);
+}
+
+
+LOCAL void
+emit_sof (compress_info_ptr cinfo, JPEG_MARKER code)
+/* Emit a SOF marker */
+{
+  int i;
+  
+  emit_marker(cinfo, code);
+  
+  emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
+
+  emit_byte(cinfo, cinfo->data_precision);
+  emit_2bytes(cinfo, (int) cinfo->image_height);
+  emit_2bytes(cinfo, (int) cinfo->image_width);
+
+  emit_byte(cinfo, cinfo->num_components);
+
+  for (i = 0; i < cinfo->num_components; i++) {
+    emit_byte(cinfo, cinfo->comp_info[i].component_id);
+    emit_byte(cinfo, (cinfo->comp_info[i].h_samp_factor << 4)
+		     + cinfo->comp_info[i].v_samp_factor);
+    emit_byte(cinfo, cinfo->comp_info[i].quant_tbl_no);
+  }
+}
+
+
+LOCAL void
+emit_sos (compress_info_ptr cinfo)
+/* Emit a SOS marker */
+{
+  int i;
+  
+  emit_marker(cinfo, M_SOS);
+  
+  emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
+  
+  emit_byte(cinfo, cinfo->comps_in_scan);
+  
+  for (i = 0; i < cinfo->comps_in_scan; i++) {
+    emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id);
+    emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4)
+		     + cinfo->cur_comp_info[i]->ac_tbl_no);
+  }
+
+  emit_byte(cinfo, 0);		/* Spectral selection start */
+  emit_byte(cinfo, DCTSIZE2-1);	/* Spectral selection end */
+  emit_byte(cinfo, 0);		/* Successive approximation */
+}
+
+
+LOCAL void
+emit_jfif_app0 (compress_info_ptr cinfo)
+/* Emit a JFIF-compliant APP0 marker */
+{
+  /*
+   * Length of APP0 block	(2 bytes)
+   * Block ID			(4 bytes - ASCII "JFIF")
+   * Zero byte			(1 byte to terminate the ID string)
+   * Version Major, Minor	(2 bytes - 0x01, 0x01)
+   * Units			(1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
+   * Xdpu			(2 bytes - dots per unit horizontal)
+   * Ydpu			(2 bytes - dots per unit vertical)
+   * Thumbnail X size		(1 byte)
+   * Thumbnail Y size		(1 byte)
+   */
+  
+  emit_marker(cinfo, M_APP0);
+  
+  emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
+
+  emit_byte(cinfo, 'J');	/* Identifier */
+  emit_byte(cinfo, 'F');
+  emit_byte(cinfo, 'I');
+  emit_byte(cinfo, 'F');
+  emit_byte(cinfo, 0);
+  emit_byte(cinfo, 1);		/* Major version */
+  emit_byte(cinfo, 1);		/* Minor version */
+  emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
+  emit_2bytes(cinfo, (int) cinfo->X_density);
+  emit_2bytes(cinfo, (int) cinfo->Y_density);
+  emit_byte(cinfo, 0);		/* No thumbnail image */
+  emit_byte(cinfo, 0);
+}
+
+
+/*
+ * Write the file header.
+ */
+
+
+METHODDEF void
+write_file_header (compress_info_ptr cinfo)
+{
+  char qt_in_use[NUM_QUANT_TBLS];
+  int i, prec;
+  boolean is_baseline;
+  
+  emit_marker(cinfo, M_SOI);	/* first the SOI */
+
+  if (cinfo->write_JFIF_header)	/* next an optional JFIF APP0 */
+    emit_jfif_app0(cinfo);
+
+  /* Emit DQT for each quantization table. */
+  /* Note that doing it here means we can't adjust the QTs on-the-fly. */
+  /* If we did want to do that, we'd have a problem with checking precision */
+  /* for the is_baseline determination. */
+
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    qt_in_use[i] = 0;
+
+  for (i = 0; i < cinfo->num_components; i++)
+    qt_in_use[cinfo->comp_info[i].quant_tbl_no] = 1;
+
+  prec = 0;
+  for (i = 0; i < NUM_QUANT_TBLS; i++) {
+    if (qt_in_use[i])
+      prec += emit_dqt(cinfo, i);
+  }
+  /* now prec is nonzero iff there are any 16-bit quant tables. */
+
+  if (cinfo->restart_interval)
+    emit_dri(cinfo);
+
+  /* Check for a non-baseline specification. */
+  /* Note we assume that Huffman table numbers won't be changed later. */
+  is_baseline = TRUE;
+  if (cinfo->arith_code || (cinfo->data_precision != 8))
+    is_baseline = FALSE;
+  for (i = 0; i < cinfo->num_components; i++) {
+    if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1)
+      is_baseline = FALSE;
+  }
+  if (prec && is_baseline) {
+    is_baseline = FALSE;
+    /* If it's baseline except for quantizer size, warn the user */
+    TRACEMS(cinfo->emethods, 0,
+	    "Caution: quantization tables are too coarse for baseline JPEG");
+  }
+
+
+  /* Emit the proper SOF marker */
+  if (cinfo->arith_code)
+    emit_sof(cinfo, M_SOF9);	/* SOF code for arithmetic coding */
+  else if (is_baseline)
+    emit_sof(cinfo, M_SOF0);	/* SOF code for baseline implementation */
+  else
+    emit_sof(cinfo, M_SOF1);	/* SOF code for non-baseline Huffman file */
+}
+
+
+/*
+ * Write the start of a scan (everything through the SOS marker).
+ */
+
+METHODDEF void
+write_scan_header (compress_info_ptr cinfo)
+{
+  int i;
+
+  if (cinfo->arith_code) {
+    /* Emit arith conditioning info.  We will have some duplication
+     * if the file has multiple scans, but it's so small it's hardly
+     * worth worrying about.
+     */
+    emit_dac(cinfo);
+  } else {
+    /* Emit Huffman tables.  Note that emit_dht takes care of
+     * suppressing duplicate tables.
+     */
+    for (i = 0; i < cinfo->comps_in_scan; i++) {
+      emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE);
+      emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE);
+    }
+  }
+
+  emit_sos(cinfo);
+}
+
+
+/*
+ * Write some bytes of compressed data within a scan.
+ */
+
+METHODDEF void
+write_jpeg_data (compress_info_ptr cinfo, char *dataptr, int datacount)
+{
+  WRITE_BYTES(cinfo, dataptr, datacount);
+}
+
+
+/*
+ * Finish up after a compressed scan (series of write_jpeg_data calls).
+ */
+
+METHODDEF void
+write_scan_trailer (compress_info_ptr cinfo)
+{
+  /* no work needed in this format */
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+write_file_trailer (compress_info_ptr cinfo)
+{
+  emit_marker(cinfo, M_EOI);
+  /* Make sure we wrote the output file OK */
+  CHECK_OUTPUT(cinfo);
+}
+
+
+/*
+ * The method selection routine for standard JPEG header writing.
+ * This should be called from c_ui_method_selection if appropriate.
+ */
+
+GLOBAL void
+jselwjfif (compress_info_ptr cinfo)
+{
+  cinfo->methods->write_file_header = write_file_header;
+  cinfo->methods->write_scan_header = write_scan_header;
+  cinfo->methods->write_jpeg_data = write_jpeg_data;
+  cinfo->methods->write_scan_trailer = write_scan_trailer;
+  cinfo->methods->write_file_trailer = write_file_trailer;
+}
+
+#endif /* JFIF_SUPPORTED */
diff --git a/jwrppm.c b/jwrppm.c
new file mode 100644
index 0000000..41687fe
--- /dev/null
+++ b/jwrppm.c
@@ -0,0 +1,167 @@
+/*
+ * jwrppm.c
+ *
+ * Copyright (C) 1991, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in PPM format.
+ * The PBMPLUS library is required (well, it will be in the real version).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications.  As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * These routines are invoked via the methods put_pixel_rows, put_color_map,
+ * and output_init/term.
+ */
+
+#include "jinclude.h"
+
+#ifdef PPM_SUPPORTED
+
+
+static JSAMPARRAY color_map;	/* saves color map passed by quantizer */
+
+
+/*
+ * Write the file header.
+ */
+
+METHODDEF void
+output_init (decompress_info_ptr cinfo)
+{
+  if (cinfo->out_color_space == CS_GRAYSCALE) {
+    /* emit header for raw PGM format */
+    fprintf(cinfo->output_file, "P5\n%ld %ld\n%d\n",
+	    cinfo->image_width, cinfo->image_height, 255);
+  } else if (cinfo->out_color_space == CS_RGB) {
+    /* emit header for raw PPM format */
+    fprintf(cinfo->output_file, "P6\n%ld %ld\n%d\n",
+	    cinfo->image_width, cinfo->image_height, 255);
+  } else {
+    ERREXIT(cinfo->emethods, "PPM output must be grayscale or RGB");
+  }
+}
+
+
+/*
+ * Write some pixel data.
+ */
+
+METHODDEF void
+put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
+		JSAMPIMAGE pixel_data)
+{
+  register FILE * outfile = cinfo->output_file;
+  register JSAMPROW ptr0, ptr1, ptr2;
+  register long col;
+  register long width = cinfo->image_width;
+  register int row;
+  
+  if (cinfo->out_color_space == CS_GRAYSCALE) {
+    for (row = 0; row < num_rows; row++) {
+      ptr0 = pixel_data[0][row];
+      for (col = width; col > 0; col--) {
+	putc(GETJSAMPLE(*ptr0), outfile);
+	ptr0++;
+      }
+    }
+  } else {
+    for (row = 0; row < num_rows; row++) {
+      ptr0 = pixel_data[0][row];
+      ptr1 = pixel_data[1][row];
+      ptr2 = pixel_data[2][row];
+      for (col = width; col > 0; col--) {
+	putc(GETJSAMPLE(*ptr0), outfile);
+	ptr0++;
+	putc(GETJSAMPLE(*ptr1), outfile);
+	ptr1++;
+	putc(GETJSAMPLE(*ptr2), outfile);
+	ptr2++;
+      }
+    }
+  }
+}
+
+
+/*
+ * Write some pixel data when color quantization is in effect.
+ */
+
+METHODDEF void
+put_demapped_rows (decompress_info_ptr cinfo, int num_rows,
+		   JSAMPIMAGE pixel_data)
+{
+  register FILE * outfile = cinfo->output_file;
+  register JSAMPROW ptr;
+  register long col;
+  register long width = cinfo->image_width;
+  register int row;
+  
+  if (cinfo->out_color_space == CS_GRAYSCALE) {
+    for (row = 0; row < num_rows; row++) {
+      ptr = pixel_data[0][row];
+      for (col = width; col > 0; col--) {
+	putc(GETJSAMPLE(color_map[0][GETJSAMPLE(*ptr)]), outfile);
+	ptr++;
+      }
+    }
+  } else {
+    for (row = 0; row < num_rows; row++) {
+      ptr = pixel_data[0][row];
+      for (col = width; col > 0; col--) {
+	register int pixval = GETJSAMPLE(*ptr);
+
+	putc(GETJSAMPLE(color_map[0][pixval]), outfile);
+	putc(GETJSAMPLE(color_map[1][pixval]), outfile);
+	putc(GETJSAMPLE(color_map[2][pixval]), outfile);
+	ptr++;
+      }
+    }
+  }
+}
+
+
+/*
+ * Write the color map.
+ * For PPM output, we just demap the output data!
+ */
+
+METHODDEF void
+put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
+{
+  color_map = colormap;		/* save for use in output */
+  cinfo->methods->put_pixel_rows = put_demapped_rows;
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF void
+output_term (decompress_info_ptr cinfo)
+{
+  /* No work except to make sure we wrote the output file OK */
+  fflush(cinfo->output_file);
+  if (ferror(cinfo->output_file))
+    ERREXIT(cinfo->emethods, "Output file write error");
+}
+
+
+/*
+ * The method selection routine for PPM format output.
+ * This should be called from d_ui_method_selection if PPM output is wanted.
+ */
+
+GLOBAL void
+jselwppm (decompress_info_ptr cinfo)
+{
+  cinfo->methods->output_init = output_init;
+  cinfo->methods->put_color_map = put_color_map;
+  cinfo->methods->put_pixel_rows = put_pixel_rows;
+  cinfo->methods->output_term = output_term;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/makcjpeg.cf b/makcjpeg.cf
new file mode 100644
index 0000000..ea93ce4
--- /dev/null
+++ b/makcjpeg.cf
@@ -0,0 +1,5 @@
+L jcmain.mix jerror.mix jcdeflts.mix jrdgif.mix jrdppm.mix jwrjfif.mix
+L jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmaster.mix jcmcu.mix
+L jcpipe.mix jcsample.mix jfwddct.mix jutils.mix jvirtmem.mix
+fa;
+b cjpeg,8K,48K,
diff --git a/makcjpeg.lnk b/makcjpeg.lnk
new file mode 100644
index 0000000..23702b2
--- /dev/null
+++ b/makcjpeg.lnk
@@ -0,0 +1,21 @@
+jcmain.obj +
+jerror.obj +
+jcdeflts.obj +
+jrdgif.obj +
+jrdppm.obj +
+jwrjfif.obj +
+jcarith.obj +
+jccolor.obj +
+jcexpand.obj +
+jchuff.obj +
+jcmaster.obj +
+jcmcu.obj +
+jcpipe.obj +
+jcsample.obj +
+jfwddct.obj +
+jutils.obj +
+jvirtmem.obj
+cjpeg.exe /NOI
+nul.map
+
+nul.def
diff --git a/makdjpeg.cf b/makdjpeg.cf
new file mode 100644
index 0000000..968af31
--- /dev/null
+++ b/makdjpeg.cf
@@ -0,0 +1,6 @@
+L jdmain.mix jerror.mix jrdjfif.mix jwrgif.mix jwrppm.mix
+L jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmaster.mix jdmcu.mix
+L jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jutils.mix
+L jvirtmem.mix
+fa;
+b djpeg,8K,48K,
diff --git a/makdjpeg.lnk b/makdjpeg.lnk
new file mode 100644
index 0000000..6e9107c
--- /dev/null
+++ b/makdjpeg.lnk
@@ -0,0 +1,22 @@
+jdmain.obj +
+jerror.obj +
+jrdjfif.obj +
+jwrgif.obj +
+jwrppm.obj +
+jbsmooth.obj +
+jdarith.obj +
+jdcolor.obj +
+jdhuff.obj +
+jdmaster.obj +
+jdmcu.obj +
+jdpipe.obj +
+jdsample.obj +
+jquant1.obj +
+jquant2.obj +
+jrevdct.obj +
+jutils.obj +
+jvirtmem.obj /NOI
+djpeg.exe
+nul.map
+
+nul.def
diff --git a/makefile.amiga b/makefile.amiga
new file mode 100644
index 0000000..2fde93a
--- /dev/null
+++ b/makefile.amiga
@@ -0,0 +1,143 @@
+# Makefile for Independent JPEG Group's software
+
+# This makefile is suitable for Amiga systems using Manx Aztec C ver 5.x.
+# Thanks to D.J. James for this version.
+
+# See README and edit jconfig.h before saying "make" !!
+
+CC= cc
+
+# You may need to adjust these cc options:
+CFLAGS= -MC -MD -DTWO_FILE_COMMANDLINE
+LDFLAGS=
+LDLIBS= -lml -lcl
+
+# miscellaneous OS-dependent stuff
+LN= ln		# linker
+RM= delete quiet # file deletion command
+AR= lb		# library (.lib) file creation command
+
+
+# source files
+INCLUDES= jinclude.h jconfig.h jpegdata.h 
+SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c \
+	 jchuff.c jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c \
+	 jdarith.c jdcolor.c jdhuff.c jdmain.c jdmaster.c jdmcu.c \
+	 jdpipe.c jdsample.c jerror.c jfwddct.c jquant1.c jquant2.c \
+	 jrdjfif.c jrdgif.c jrdppm.c jrevdct.c jutils.c jvirtmem.c \
+	 jwrjfif.c jwrgif.c jwrppm.c egetopt.c
+DOCS= README architecture codingrules
+MAKEFILES= makefile.unix makefile.amiga \
+	   makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk \
+	   makefile.pwc makcjpeg.cf makdjpeg.cf makljpeg.cf
+TESTFILES= testorig.jpg testimg.ppm testimg.jpg
+DISTFILES= $(DOCS) $(MAKEFILES) ansi2knr.c $(SOURCES) $(INCLUDES) $(TESTFILES)
+
+# compression objectfiles
+COBJECTS = jcmain.o jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
+	   jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
+	   jrdgif.o jrdppm.o jwrjfif.o \
+	   jutils.o jvirtmem.o jerror.o
+# decompression objectfiles
+DOBJECTS = jdmain.o jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
+	   jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
+	   jrdjfif.o jwrgif.o jwrppm.o \
+	   jutils.o jvirtmem.o jerror.o
+# These objectfiles are included in libjpeg.lib (all but jcmain.o, jdmain.o)
+LIBOBJECTS = jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
+	     jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
+	     jrdgif.o jrdppm.o jwrjfif.o \
+	     jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
+	     jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
+	     jrdjfif.o jwrgif.o jwrppm.o \
+	     jutils.o jvirtmem.o jerror.o
+
+
+all: cjpeg djpeg
+# By default, libjpeg.lib is not built unless you explicitly request it.
+
+
+# If you have a C compiler that doesn't understand function prototypes,
+# uncomment the 5 lines below and make sure PROTO is not defined by jconfig.h.
+# Then say "make ansi2knr" before "make".
+
+#.c.o:
+#	./ansi2knr $*.c tmpansi.c
+#	$(CC) $(CFLAGS) -c tmpansi.c
+#	mv tmpansi.o $*.o
+#	$(RM) tmpansi.c
+
+ansi2knr: ansi2knr.c
+	$(CC) -o ansi2knr ansi2knr.c
+# You may need to add one of -DBSD, -DVMS, or -DMSDOS to the line above.
+
+
+cjpeg: $(COBJECTS)
+	$(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS)
+
+djpeg: $(DOBJECTS)
+	$(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS)
+
+# libjpeg.lib is useful if you are including the JPEG software in a larger
+# program; you'd include it in your link, rather than the individual modules.
+libjpeg.lib: $(LIBOBJECTS)
+	-$(RM) libjpeg.lib
+	$(AR) libjpeg.lib  $(LIBOBJECTS)
+
+# Use the following to test the built library
+#cjpeg: jcmain.o libjpeg.lib
+#	$(LN) $(LDFLAGS) -o cjpeg jcmain.o -llibjpeg $(LDLIBS)
+#
+#djpeg: jdmain.o libjpeg.lib
+#	$(LN) $(LDFLAGS) -o djpeg jdmain.o -llibjpeg $(LDLIBS)
+
+clean:
+	-$(RM) *.o cjpeg djpeg libjpeg.lib ansi2knr core tmpansi.* testout.ppm testout.jpg
+
+distribute:
+	-$(RM) jpegsrc.tar*
+	tar cvf jpegsrc.tar $(DISTFILES)
+	list jpegsrc.tar
+	compress -v jpegsrc.tar
+	list jpegsrc.tar*
+
+test: cjpeg djpeg
+	-$(RM) testout.ppm testout.jpg
+	./djpeg testorig.jpg testout.ppm
+	./cjpeg testimg.ppm testout.jpg
+	cmp testimg.ppm testout.ppm
+	cmp testimg.jpg testout.jpg
+
+
+jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h 
+jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h 
+jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h 
+jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h 
+jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h 
+jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h 
+jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c 
+jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h 
+jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h 
+jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h 
+jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h 
+jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h 
+jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h 
+jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h 
+jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
+jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h 
+jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h 
+jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h 
+jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h 
+jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h 
+jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h 
+jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h 
+jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h 
+jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h 
+jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h 
+jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h 
+jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h 
+jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h 
+jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h 
+jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h 
+jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h 
+jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h 
diff --git a/makefile.mc5 b/makefile.mc5
new file mode 100644
index 0000000..eee9f21
--- /dev/null
+++ b/makefile.mc5
@@ -0,0 +1,115 @@
+# Makefile for Independent JPEG Group's software
+
+# This makefile is for Microsoft C for MS-DOS, version 5.x.
+
+# See README and edit jconfig.h before saying "make" !!
+
+# Microsoft's brain-damaged version of make uses nonstandard syntax (a blank
+# line is needed to terminate a command list) and it simply scans the rules
+# in order, rather than doing a true dependency-tree walk.  Furthermore,
+# expanded command lines can't exceed 128 chars (this is a DOS bug, not
+# make's fault); so we can't just name all the objectfiles in the link steps.
+# Instead we shove each objectfile into a library as it is made, and link
+# from the library.  The objectfiles are also kept separately as timestamps.
+
+# You may need to adjust these cc options:
+CFLAGS=  /AS /I. /W3 /Oail /Gs /DMEM_STATS  # NB: /Gs turns off stack oflo checks
+LDFLAGS= /Fm /F 2000  # /F hhhh  sets stack size (in hex)
+# In particular:
+#   Add /DMSDOS if your compiler doesn't automatically #define MSDOS.
+#   Add /DHAVE_GETOPT if your library includes getopt(3) (see jcmain.c, jdmain.c).
+#   /DMEM_STATS is optional -- it enables gathering of memory usage statistics.
+
+# compression objectfiles
+COBJECTS = jcmain.obj jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
+	   jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
+	   jrdgif.obj jrdppm.obj jwrjfif.obj \
+	   jutils.obj jvirtmem.obj jerror.obj
+# decompression objectfiles
+DOBJECTS = jdmain.obj jdmaster.obj jbsmooth.obj jdarith.obj jdcolor.obj jdhuff.obj \
+	   jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj jquant2.obj jrevdct.obj \
+	   jrdjfif.obj jwrgif.obj jwrppm.obj \
+	   jutils.obj jvirtmem.obj jerror.obj
+
+
+# inference rule used for all compilations except jcmain.c, jdmain.c
+# notice that objectfile is also inserted into libjpeg.lib
+.c.obj:
+	cl $(CFLAGS) /c $*.c
+	lib libjpeg -+$*.obj;
+
+# these two objectfiles are not inserted into libjpeg
+# because they have duplicate global symbol names (notably main()).
+jcmain.obj: jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c 
+	cl $(CFLAGS) /c $*.c
+
+jdmain.obj: jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
+	cl $(CFLAGS) /c $*.c
+
+
+jbsmooth.obj: jbsmooth.c jinclude.h jconfig.h jpegdata.h 
+
+jcarith.obj: jcarith.c jinclude.h jconfig.h jpegdata.h 
+
+jccolor.obj: jccolor.c jinclude.h jconfig.h jpegdata.h 
+
+jcdeflts.obj: jcdeflts.c jinclude.h jconfig.h jpegdata.h 
+
+jcexpand.obj: jcexpand.c jinclude.h jconfig.h jpegdata.h 
+
+jchuff.obj: jchuff.c jinclude.h jconfig.h jpegdata.h 
+
+jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpegdata.h 
+
+jcmcu.obj: jcmcu.c jinclude.h jconfig.h jpegdata.h 
+
+jcpipe.obj: jcpipe.c jinclude.h jconfig.h jpegdata.h 
+
+jcsample.obj: jcsample.c jinclude.h jconfig.h jpegdata.h 
+
+jdarith.obj: jdarith.c jinclude.h jconfig.h jpegdata.h 
+
+jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpegdata.h 
+
+jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpegdata.h 
+
+jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpegdata.h 
+
+jdmcu.obj: jdmcu.c jinclude.h jconfig.h jpegdata.h 
+
+jdpipe.obj: jdpipe.c jinclude.h jconfig.h jpegdata.h 
+
+jdsample.obj: jdsample.c jinclude.h jconfig.h jpegdata.h 
+
+jerror.obj: jerror.c jinclude.h jconfig.h jpegdata.h 
+
+jfwddct.obj: jfwddct.c jinclude.h jconfig.h jpegdata.h 
+
+jquant1.obj: jquant1.c jinclude.h jconfig.h jpegdata.h 
+
+jquant2.obj: jquant2.c jinclude.h jconfig.h jpegdata.h 
+
+jrdjfif.obj: jrdjfif.c jinclude.h jconfig.h jpegdata.h 
+
+jrdgif.obj: jrdgif.c jinclude.h jconfig.h jpegdata.h 
+
+jrdppm.obj: jrdppm.c jinclude.h jconfig.h jpegdata.h 
+
+jrevdct.obj: jrevdct.c jinclude.h jconfig.h jpegdata.h 
+
+jutils.obj: jutils.c jinclude.h jconfig.h jpegdata.h 
+
+jvirtmem.obj: jvirtmem.c jinclude.h jconfig.h jpegdata.h 
+
+jwrjfif.obj: jwrjfif.c jinclude.h jconfig.h jpegdata.h 
+
+jwrgif.obj: jwrgif.c jinclude.h jconfig.h jpegdata.h 
+
+jwrppm.obj: jwrppm.c jinclude.h jconfig.h jpegdata.h 
+
+
+cjpeg.exe: $(COBJECTS)
+	cl /Fecjpeg.exe jcmain.obj libjpeg.lib $(LDFLAGS)
+
+djpeg.exe: $(DOBJECTS)
+	cl /Fedjpeg.exe jdmain.obj libjpeg.lib $(LDFLAGS)
diff --git a/makefile.mc6 b/makefile.mc6
new file mode 100644
index 0000000..b9ca60f
--- /dev/null
+++ b/makefile.mc6
@@ -0,0 +1,79 @@
+# Makefile for Independent JPEG Group's software
+
+# This makefile is for Microsoft C for MS-DOS, version 6.x (use NMAKE).
+# Thanks to Alan Wright and Chris Turner of Olivetti Research Ltd.
+
+# See README and edit jconfig.h before saying "make" !!
+
+all: cjpeg.exe djpeg.exe
+
+# compiler flags. -D gives a #define to the sources:
+#       -O              default optimisation
+#       -W3             warning level 3
+#       -Za             ANSI conformance, defines__STDC__ but undefines far
+#                       and near!
+#       -D__STDC__      pretend we have full ANSI compliance. MSC is near
+#                       enough anyway
+#       -DMSDOS         we are on an MSDOS machine
+#       -DMEM_STATS     enable memory usage statistics (optional)
+#       -DHAVE_GETOPT   library has getopt routine to parse cmnd line options
+#       -c              compile, don't link (implicit in inference rules)
+
+CFLAGS = -c -O -W3 -DMSDOS -D__STDC__ -DMEM_STATS
+
+
+# compression objectfiles
+COBJECTS = jcmain.obj jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
+	   jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
+	   jrdgif.obj jrdppm.obj jwrjfif.obj \
+	   jutils.obj jvirtmem.obj jerror.obj
+# decompression objectfiles
+DOBJECTS = jdmain.obj jdmaster.obj jbsmooth.obj jdarith.obj jdcolor.obj jdhuff.obj \
+	   jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj jquant2.obj jrevdct.obj \
+	   jrdjfif.obj jwrgif.obj jwrppm.obj \
+	   jutils.obj jvirtmem.obj jerror.obj
+
+
+# default rules in nmake will use cflags and compile the list below
+
+jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h 
+jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h 
+jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h 
+jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h 
+jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h 
+jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h 
+jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c 
+jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h 
+jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h 
+jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h 
+jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h 
+jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h 
+jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h 
+jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h 
+jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
+jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h 
+jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h 
+jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h 
+jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h 
+jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h 
+jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h 
+jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h 
+jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h 
+jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h 
+jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h 
+jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h 
+jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h 
+jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h 
+jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h 
+jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h 
+jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h 
+jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h 
+
+
+# use linker response files because file list > 128 chars
+
+cjpeg.exe: $(COBJECTS)
+        link /STACK:8192 @makcjpeg.lnk
+
+djpeg.exe: $(DOBJECTS)
+        link /STACK:8192 @makdjpeg.lnk
diff --git a/makefile.pwc b/makefile.pwc
new file mode 100644
index 0000000..f41dd48
--- /dev/null
+++ b/makefile.pwc
@@ -0,0 +1,100 @@
+# Makefile for Independent JPEG Group's software
+
+# This makefile is for Mix Software's Power C, v2.1.1
+# and Dan Grayson's pd make 2.14 under MS-DOS.
+# Thanks to Bob Hardy for this version.
+
+# See README and edit jconfig.h before saying "make" !!
+
+# NOTE: make sure you have converted end-of-line markers to CR/LF in this file
+# and in the three mak*.cf files; otherwise pd make and the Mix linker will
+# choke.  Power C doesn't seem to care whether end-of-lines are CR/LF or just
+# LF in the *.h and *.c files.  If you blindly converted LF to CR/LF in ALL
+# the files, then you broke the test*.* files, which contain binary data.
+
+CC=pc
+
+# You may need to adjust these cc options:
+MODEL=m
+CFLAGS=-dMEM_STATS -dMSDOS -m$(MODEL)
+LDFLAGS=
+# In particular:
+#   -dMEM_STATS is optional -- it enables gathering of memory usage statistics.
+LDLIBS=
+
+# miscellaneous OS-dependent stuff
+# linker
+LN=pcl
+# file deletion command
+RM=del
+# library (.mix) file creation command
+AR=merge
+
+
+# compression objectfiles
+COBJECTS = jcmain.mix jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jrdgif.mix jrdppm.mix jwrjfif.mix jutils.mix jvirtmem.mix jerror.mix
+# decompression objectfiles
+DOBJECTS = jdmain.mix jdmaster.mix jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmcu.mix jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jrdjfif.mix jwrgif.mix jwrppm.mix jutils.mix jvirtmem.mix jerror.mix
+# These objectfiles are included in libjpeg.mix (all but jcmain, jdmain)
+LIBOBJECTS = jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jrdgif.mix jrdppm.mix jwrjfif.mix jdmaster.mix jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmcu.mix jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jrdjfif.mix jwrgif.mix jwrppm.mix jutils.mix jvirtmem.mix jerror.mix
+
+
+all: cjpeg.exe djpeg.exe test
+# By default, libjpeg.mix is not built unless you explicitly request it.
+
+
+cjpeg.exe: $(COBJECTS)
+	$(LN) $(LDFLAGS) @makcjpeg.cf
+
+djpeg.exe: $(DOBJECTS)
+	$(LN) $(LDFLAGS) @makdjpeg.cf
+
+# libjpeg.mix is useful if you are including the JPEG software in a larger
+# program; you'd include it in your link, rather than the individual modules.
+libjpeg.mix: $(LIBOBJECTS)
+	@$(RM) libjpeg.mix
+	$(AR) libjpeg.mix @makljpeg.cf
+
+clean:
+	$(RM) *.mix cjpeg.exe djpeg.exe testout.*
+
+test:
+	@$(RM) testout.*
+	+djpeg testorig.jpg testout.ppm
+	+cjpeg testimg.ppm testout.jpg
+	fc testimg.ppm testout.ppm
+	fc testimg.jpg testout.jpg
+
+
+jbsmooth.mix : jbsmooth.c jinclude.h jconfig.h jpegdata.h 
+jcarith.mix : jcarith.c jinclude.h jconfig.h jpegdata.h 
+jccolor.mix : jccolor.c jinclude.h jconfig.h jpegdata.h 
+jcdeflts.mix : jcdeflts.c jinclude.h jconfig.h jpegdata.h 
+jcexpand.mix : jcexpand.c jinclude.h jconfig.h jpegdata.h 
+jchuff.mix : jchuff.c jinclude.h jconfig.h jpegdata.h 
+jcmain.mix : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c 
+jcmaster.mix : jcmaster.c jinclude.h jconfig.h jpegdata.h 
+jcmcu.mix : jcmcu.c jinclude.h jconfig.h jpegdata.h 
+jcpipe.mix : jcpipe.c jinclude.h jconfig.h jpegdata.h 
+jcsample.mix : jcsample.c jinclude.h jconfig.h jpegdata.h 
+jdarith.mix : jdarith.c jinclude.h jconfig.h jpegdata.h 
+jdcolor.mix : jdcolor.c jinclude.h jconfig.h jpegdata.h 
+jdhuff.mix : jdhuff.c jinclude.h jconfig.h jpegdata.h 
+jdmain.mix : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
+jdmaster.mix : jdmaster.c jinclude.h jconfig.h jpegdata.h 
+jdmcu.mix : jdmcu.c jinclude.h jconfig.h jpegdata.h 
+jdpipe.mix : jdpipe.c jinclude.h jconfig.h jpegdata.h 
+jdsample.mix : jdsample.c jinclude.h jconfig.h jpegdata.h 
+jerror.mix : jerror.c jinclude.h jconfig.h jpegdata.h 
+jfwddct.mix : jfwddct.c jinclude.h jconfig.h jpegdata.h 
+jquant1.mix : jquant1.c jinclude.h jconfig.h jpegdata.h 
+jquant2.mix : jquant2.c jinclude.h jconfig.h jpegdata.h 
+jrdjfif.mix : jrdjfif.c jinclude.h jconfig.h jpegdata.h 
+jrdgif.mix : jrdgif.c jinclude.h jconfig.h jpegdata.h 
+jrdppm.mix : jrdppm.c jinclude.h jconfig.h jpegdata.h 
+jrevdct.mix : jrevdct.c jinclude.h jconfig.h jpegdata.h 
+jutils.mix : jutils.c jinclude.h jconfig.h jpegdata.h 
+jvirtmem.mix : jvirtmem.c jinclude.h jconfig.h jpegdata.h 
+jwrjfif.mix : jwrjfif.c jinclude.h jconfig.h jpegdata.h 
+jwrgif.mix : jwrgif.c jinclude.h jconfig.h jpegdata.h 
+jwrppm.mix : jwrppm.c jinclude.h jconfig.h jpegdata.h 
diff --git a/makefile.unix b/makefile.unix
new file mode 100644
index 0000000..0f11afa
--- /dev/null
+++ b/makefile.unix
@@ -0,0 +1,152 @@
+# Makefile for Independent JPEG Group's software
+
+# This makefile is suitable for Unix-like systems.
+
+# See README and edit jconfig.h before saying "make" !!
+
+# Comment out this line if you don't have gcc:
+CC=gcc
+
+# You may need to adjust these cc options:
+CFLAGS= -O -g -Wall -DHAVE_GETOPT -DMEM_STATS
+LDFLAGS= -g
+# In particular:
+#   Remove -g and -Wall if not using gcc.
+#   Add -DBSD if on a pure BSD system (see jinclude.h).
+#   Remove -DHAVE_GETOPT if you don't have getopt(3) (see jcmain.c, jdmain.c).
+#   -DMEM_STATS is optional -- it enables gathering of memory usage statistics.
+#   You may also want to add -DTWO_FILE_COMMANDLINE or -D switches for other
+#   symbols listed in jconfig.h, if you prefer not to change jconfig.h.
+# If your compiler is non-ANSI, also see the .c.o rule below.
+
+# On HP-UX (and probably other SysV systems) the alternate malloc(3X) is a lot
+# faster than the standard malloc; this makes a noticeable difference in the
+# startup time when handling big noninterleaved images.  I say "-lmalloc" to
+# get the alternate allocator.  On most non-SysV systems you can just
+# define LDLIBS as empty.
+LDLIBS= -lmalloc
+
+# miscellaneous OS-dependent stuff
+LN= $(CC)	# linker
+RM= rm -f	# file deletion command
+AR= ar rc	# library (.a) file creation command
+AR2= ranlib	# second step in .a creation (use "touch" if not needed)
+
+
+# source files
+INCLUDES= jinclude.h jconfig.h jpegdata.h 
+SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c \
+	 jchuff.c jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c \
+	 jdarith.c jdcolor.c jdhuff.c jdmain.c jdmaster.c jdmcu.c \
+	 jdpipe.c jdsample.c jerror.c jfwddct.c jquant1.c jquant2.c \
+	 jrdjfif.c jrdgif.c jrdppm.c jrevdct.c jutils.c jvirtmem.c \
+	 jwrjfif.c jwrgif.c jwrppm.c egetopt.c
+DOCS= README architecture codingrules
+MAKEFILES= makefile.unix makefile.amiga \
+	   makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk \
+	   makefile.pwc makcjpeg.cf makdjpeg.cf makljpeg.cf
+TESTFILES= testorig.jpg testimg.ppm testimg.jpg
+DISTFILES= $(DOCS) $(MAKEFILES) ansi2knr.c $(SOURCES) $(INCLUDES) $(TESTFILES)
+
+# compression objectfiles
+COBJECTS = jcmain.o jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
+	   jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
+	   jrdgif.o jrdppm.o jwrjfif.o \
+	   jutils.o jvirtmem.o jerror.o
+# decompression objectfiles
+DOBJECTS = jdmain.o jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
+	   jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
+	   jrdjfif.o jwrgif.o jwrppm.o \
+	   jutils.o jvirtmem.o jerror.o
+# These objectfiles are included in libjpeg.a (all but jcmain.o, jdmain.o)
+LIBOBJECTS = jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
+	     jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
+	     jrdgif.o jrdppm.o jwrjfif.o \
+	     jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
+	     jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
+	     jrdjfif.o jwrgif.o jwrppm.o \
+	     jutils.o jvirtmem.o jerror.o
+
+
+all: cjpeg djpeg
+# By default, libjpeg.a is not built unless you explicitly request it.
+
+
+# If you have a C compiler that doesn't understand function prototypes,
+# uncomment the 5 lines below and make sure PROTO is not defined by jconfig.h.
+# Then say "make ansi2knr" before "make".
+
+#.c.o:
+#	./ansi2knr $*.c tmpansi.c
+#	$(CC) $(CFLAGS) -c tmpansi.c
+#	mv tmpansi.o $*.o
+#	$(RM) tmpansi.c
+
+ansi2knr: ansi2knr.c
+	$(CC) -o ansi2knr ansi2knr.c
+# You may need to add one of -DBSD, -DVMS, or -DMSDOS to the line above.
+
+
+cjpeg: $(COBJECTS)
+	$(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS)
+
+djpeg: $(DOBJECTS)
+	$(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS)
+
+# libjpeg.a is useful if you are including the JPEG software in a larger
+# program; you'd include it in your link, rather than the individual modules.
+libjpeg.a: $(LIBOBJECTS)
+	$(RM) libjpeg.a
+	$(AR) libjpeg.a  $(LIBOBJECTS)
+	$(AR2) libjpeg.a
+
+clean:
+	$(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core tmpansi.* testout.ppm testout.jpg
+
+distribute:
+	$(RM) jpegsrc.tar*
+	tar cvf jpegsrc.tar $(DISTFILES)
+	ls -l jpegsrc.tar
+	compress -v jpegsrc.tar
+	ls -l jpegsrc.tar*
+
+test: cjpeg djpeg
+	$(RM) testout.ppm testout.jpg
+	./djpeg testorig.jpg >testout.ppm
+	./cjpeg testimg.ppm >testout.jpg
+	cmp testimg.ppm testout.ppm
+	cmp testimg.jpg testout.jpg
+
+
+jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h 
+jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h 
+jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h 
+jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h 
+jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h 
+jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h 
+jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c 
+jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h 
+jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h 
+jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h 
+jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h 
+jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h 
+jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h 
+jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h 
+jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
+jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h 
+jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h 
+jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h 
+jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h 
+jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h 
+jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h 
+jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h 
+jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h 
+jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h 
+jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h 
+jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h 
+jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h 
+jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h 
+jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h 
+jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h 
+jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h 
+jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h 
diff --git a/makljpeg.cf b/makljpeg.cf
new file mode 100644
index 0000000..3325bf4
--- /dev/null
+++ b/makljpeg.cf
@@ -0,0 +1,5 @@
+jbsmooth.mix,jcarith.mix,jccolor.mix,jcdeflts.mix,jcexpand.mix,jchuff.mix
+jcmaster.mix,jcmcu.mix,jcpipe.mix,jcsample.mix,jdarith.mix,jdcolor.mix
+jdhuff.mix,jdmaster.mix,jdmcu.mix,jdpipe.mix,jdsample.mix,jerror.mix
+jfwddct.mix,jquant1.mix,jquant2.mix,jrdgif.mix,jrdjfif.mix,jrdppm.mix
+jrevdct.mix,jutils.mix,jvirtmem.mix,jwrgif.mix,jwrjfif.mix,jwrppm.mix
diff --git a/testimg.jpg b/testimg.jpg
new file mode 100644
index 0000000..b6b68bc
--- /dev/null
+++ b/testimg.jpg
Binary files differ
diff --git a/testimg.ppm b/testimg.ppm
new file mode 100644
index 0000000..c7dab37
--- /dev/null
+++ b/testimg.ppm
Binary files differ
diff --git a/testorig.jpg b/testorig.jpg
new file mode 100644
index 0000000..1a628fc
--- /dev/null
+++ b/testorig.jpg
Binary files differ