The Independent JPEG Group's JPEG software v1

This commit is contained in:
Thomas G. Lane 1991-10-07 00:00:00 +00:00 committed by DRC
commit 2cbeb8abd9
53 changed files with 13965 additions and 0 deletions

391
README Normal file
View File

@ -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.

477
ansi2knr.c Normal file
View File

@ -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;
}

1106
architecture Normal file

File diff suppressed because it is too large Load Diff

99
codingrules Normal file
View File

@ -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.

276
egetopt.c Normal file
View File

@ -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);
}

120
jbsmooth.c Normal file
View File

@ -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 */

42
jcarith.c Normal file
View File

@ -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 */

203
jccolor.c Normal file
View File

@ -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;
}

364
jcdeflts.c Normal file
View File

@ -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]);
}
}

75
jcexpand.c Normal file
View File

@ -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;
}

689
jchuff.c Normal file
View File

@ -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
}
}

272
jcmain.c Normal file
View File

@ -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);
}

127
jcmaster.c Normal file
View File

@ -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? */
}

212
jcmcu.c Normal file
View File

@ -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;
}

320
jconfig.h Normal file
View File

@ -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;

715
jcpipe.c Normal file
View File

@ -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
}
}

135
jcsample.c Normal file
View File

@ -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;
}

42
jdarith.c Normal file
View File

@ -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 */

194
jdcolor.c Normal file
View File

@ -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;
}

318
jdhuff.c Normal file
View File

@ -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;
}
}

289
jdmain.c Normal file
View File

@ -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);
}

180
jdmaster.c Normal file
View File

@ -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? */
}

146
jdmcu.c Normal file
View File

@ -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;
}

1309
jdpipe.c Normal file

File diff suppressed because it is too large Load Diff

133
jdsample.c Normal file
View File

@ -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;
}

67
jerror.c Normal file
View File

@ -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 */
}

179
jfwddct.c Normal file
View File

@ -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);
}

73
jinclude.h Normal file
View File

@ -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"

812
jpegdata.h Normal file
View File

@ -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 */

387
jquant1.c Normal file
View File

@ -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 */

122
jquant2.c Normal file
View File

@ -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 */

620
jrdgif.c Normal file
View File

@ -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 */

733
jrdjfif.c Normal file
View File

@ -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 */

124
jrdppm.c Normal file
View File

@ -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 */

171
jrevdct.c Normal file
View File

@ -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);
}

106
jutils.c Normal file
View File

@ -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
}

548
jvirtmem.c Normal file
View File

@ -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;
}

497
jwrgif.c Normal file
View File

@ -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 */

468
jwrjfif.c Normal file
View File

@ -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 */

167
jwrppm.c Normal file
View File

@ -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 */

5
makcjpeg.cf Normal file
View File

@ -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,

21
makcjpeg.lnk Normal file
View File

@ -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

6
makdjpeg.cf Normal file
View File

@ -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,

22
makdjpeg.lnk Normal file
View File

@ -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

143
makefile.amiga Normal file
View File

@ -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

115
makefile.mc5 Normal file
View File

@ -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)

79
makefile.mc6 Normal file
View File

@ -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

100
makefile.pwc Normal file
View File

@ -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

152
makefile.unix Normal file
View File

@ -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

5
makljpeg.cf Normal file
View File

@ -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

BIN
testimg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

9
testimg.ppm Normal file

File diff suppressed because one or more lines are too long

BIN
testorig.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB