Compare commits

...

3 Commits

Author SHA1 Message Date
Thomas G. Lane
cc7150e281 The Independent JPEG Group's JPEG software v4a 2015-07-29 15:25:01 -05:00
Thomas G. Lane
88aeed428f The Independent JPEG Group's JPEG software v4 2015-07-29 15:23:45 -05:00
Thomas G. Lane
4a6b730364 The Independent JPEG Group's JPEG software v3 2015-07-29 15:21:19 -05:00
88 changed files with 12293 additions and 4409 deletions

109
CHANGELOG
View File

@@ -1,5 +1,114 @@
CHANGELOG for Independent JPEG Group's JPEG software
Version 4A 18-Feb-93
--------------------
Substantial speedup for grayscale output from color JPEG file (suppress
processing of chrominance components). Lesser speedups in Huffman decoding
and in compression quantization.
Can switch stdin/stdout to binary mode with either fdopen() or setmode();
this allows use of one-file command line style on a wider range of systems.
Also added -outfile switch so that makefile test scripts don't have to depend
on the command line style.
New makefile.icc for Code Builder; makefile.sas is updated for SAS C 6.x.
Hook added to allow surrounding application to read and write COM (comment)
blocks.
Bugfixes (DOS only): jmemdos.c code for accessing expanded memory only worked
if struct fields are packed on byte boundaries. This is not true by default
for Microsoft C. Furthermore, Microsoft C needs an _fheapmin() call to clean
up the far heap correctly.
Version 4 10-Dec-92
--------------------
Revised user interface: switches now use names instead of single letters.
(Old switch letters are acceptable abbreviations of new switch names, EXCEPT
for djpeg's old -g, -D, -1 switches.) cjpeg has several new switches.
Provision for smoothing the input image added to cjpeg. This helps a lot with
converting dithered GIFs to JPEG.
Decoder upsampling now uses interpolation instead of pixel replication; this
improves rendering of sharp colored edges.
The decompressor will now try to continue after detecting an error in the
compressed data, instead of just aborting. If the input file has restart
markers, full synchronization will usually be regained at the next undamaged
restart marker. (But you're still out of luck if any of the header markers
are corrupt.)
Substantial improvements in speed; DCT accuracy improved too.
Numerous minor changes to improve portability. egetopt.c, which was by far
the worst portability problem, is gone altogether.
A few bugfixes, sigh (mostly affecting DOS implementations only).
Bugfix: on DOS machines, cjpeg -o would fail on grayscale input files.
Bugfix: one-pass quantization to more than 64 color levels would fail on
16-bit-int machines. This could only happen with quantized grayscale output.
A couple of changes affect code that calls the JPEG subroutine library:
1. The parameter struct tag names are now capitalized (Compress_info_struct,
Compress_methods_struct, Decompress_info_struct, Decompress_methods_struct,
and External_methods_struct). This makes it easier to live with brain-damaged
compilers with short identifier lengths. (All identifiers used in the JPEG
code are now unique within the first 16 characters.)
2. If you are not calling jselerror(), you need to initialize three new fields
in the emethods structure, typically as follows:
e_methods.num_warnings = 0; /* no warnings emitted yet */
e_methods.first_warning_level = 0; /* display first corrupt-data warning */
e_methods.more_warning_level = 3; /* but suppress additional ones */
These fields control handling of corrupt-data warnings.
Version 3 17-Mar-92
--------------------
Memory manager is finally capable of swapping to temp files. There are
separate versions of jmemsys.c for no temp files (same behavior as older
versions), simple temp files with or without tmpfile(), and a DOS-specific
version (including special code for EMS and XMS). This is probably much more
system-dependent than any of the older code; some bugs may surface here.
Hooks added for user interface to install progress monitoring routine
(percent-done bar, etc). See comments with dummy progress_monitor
routines in jcdeflts.c, jddeflts.c.
Two-pass color quantization (finally!). This is now the default method when
quantizing; say '-1' to djpeg for quick-and-ugly 1-pass method. There is
a test file for checking 2-pass quantization and GIF output.
Fixed bug in jcopy_block_row that broke cjpeg -o option and djpeg -b option
on MSDOS machines.
Miscellaneous small speedups; notably, DCT computation rearranged so that
GCC "inline" feature is no longer needed for good code quality.
File config.c renamed ckconfig.c to avoid name conflict with /etc/config
on Unix systems.
Added example.c to document usage of JPEG subroutines better.
Memory manager now knows how to release all storage during error exit ---
avoids memory leak when using JPEG as subroutines. This implies a couple
small changes to the subroutine interface: the old free_defaults subroutines
are no longer needed, but if you have a replacement error_exit method then it
must call the new free_all method. Also, jselvirtmem renamed to jselmemmgr.
Code for reading Targa files with 32-bit pixels was incorrect.
Colorspace conversion slightly faster and more accurate; because of
this, old "test" files will no longer match bit-for-bit.
Version 2 13-Dec-91
--------------------

304
README
View File

@@ -1,27 +1,32 @@
The Independent JPEG Group's JPEG software
==========================================
README for release 2 of 13-Dec-91
=================================
README for release 4A of 18-Feb-93
==================================
This distribution contains the second public release of the Independent JPEG
This distribution contains a BETA TEST 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.
For installation instructions, see file SETUP; for usage instructions, see
file USAGE (or the cjpeg.1 and djpeg.1 manual pages).
For installation instructions, see file SETUP.
For usage instructions, see file USAGE (or the cjpeg.1 and djpeg.1 manual
pages; but USAGE contains a "hints" section not found in the manual pages).
Useful information can also be found in the JPEG FAQ (Frequently Asked
Questions) article; see ARCHIVE LOCATIONS below to obtain the FAQ article.
This software is still undergoing revision. Updated versions may be obtained
by FTP or UUCP to uunet.uu.net and other archive sites; see ARCHIVE LOCATIONS
below for details.
by FTP or UUCP to UUNET and other archive sites; see ARCHIVE LOCATIONS below
for details.
If you intend to become a serious user of this software, please contact
jpeg-info@uunet.uu.net to be added to our electronic mailing list. Then
you'll be notified of updates and have a chance to participate in discussions,
etc.
Serious users of this software (particularly those incorporating it into
larger programs) should contact jpeg-info@uunet.uu.net to be added to our
electronic mailing list. Mailing list members are notified of updates and
have a chance to participate in technical discussions, etc.
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz,
Lee Crocker, and other members of the Independent JPEG Group.
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Lee
Crocker, George Phillips, Ge' Weijers, and other members of the Independent
JPEG Group.
DISCLAIMER
@@ -32,46 +37,53 @@ 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.)
Please report any problems with this software to jpeg-info@uunet.uu.net.
Despite that, we believe that this software is pretty good, and if you find
any problems with it, we'd like to know about them. Please report problems
by e-mail to jpeg-info@uunet.uu.net.
WHAT'S HERE
===========
This distribution contains software to implement JPEG image compression and
This distribution contains C software to implement JPEG image compression and
decompression. JPEG (pronounced "jay-peg") is a standardized compression
method for full-color and gray-scale images. JPEG is intended for
method for full-color and gray-scale images. JPEG is intended for compressing
"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 no 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.
identical to the input image. Hence you must 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 no visible change, and amazingly
high compression levels are possible 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.
progressive, hierarchical, 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.
In order to support file conversion and viewing software, we have included
considerable functionality beyond the bare JPEG coding/decoding capability;
for example, the color quantization modules are not strictly part of JPEG
decoding, but they are essential for output to colormapped file formats or
colormapped displays. These extra functions can be compiled out if not
required for a particular application.
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.
flexibility, while also making it fast enough to be useful. In particular,
the software is not intended to be read as a tutorial on JPEG. (See the
REFERENCES section for introductory material.) While we hope that the entire
package will someday be industrial-strength code, much remains to be done in
performance tuning and in improving the capabilities of individual modules.
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 file SETUP), compile and go.
Members of the independent JPEG group will improve the out-of-the-box
Members of the Independent JPEG Group will improve the out-of-the-box
functionality and speed as time goes on.
* As the basis for other JPEG programs. For example, you could incorporate
@@ -89,37 +101,41 @@ This software can be used on several levels:
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
In particular, we welcome the use of this software as a component of commercial
products; no royalty is required.
ARCHIVE LOCATIONS
=================
The "official" archive site for this software is uunet.uu.net (Internet
address 137.39.1.2 or 192.48.96.2). The most recent released version can
[Version 4A is a beta-test release and will not be publicly archived.
The following paragraphs refer to the most recent official release.]
The "official" archive site for this software is ftp.uu.net (Internet
address 137.39.1.9 or 192.48.96.9). The most recent released version can
always be found there in directory graphics/jpeg. This particular version
will be archived as jpegsrc.v2.tar.Z. If you are on the Internet, you can
will be archived as jpegsrc.v4.tar.Z. If you are on the Internet, you can
retrieve files from UUNET by anonymous FTP. If you don't have FTP access,
UUNET's archives are also available via UUCP; contact postmaster@uunet.uu.net
for information on retrieving files that way.
Various other Internet sites maintain copies of the UUNET file, which may or
may not be up-to-date. In Europe, try nic.funet.fi (128.214.6.100; look in
directory pub/graphics/programs/jpeg).
Numerous Internet sites maintain copies of the UUNET files; in particular,
you can probably find a copy at any site that archives comp.sources.misc
submissions. However, only ftp.uu.net is guaranteed to have the latest
official version.
You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum
(GO PICS), library 10; this version will be file jpsrc2.zip.
(GO PICS), library 15; this version will be file jpsrc4.zip. Again,
CompuServe is not guaranteed to have the very latest version.
If you are not reasonably handy at configuring and installing portable C
programs, you may have some difficulty installing this package. You may
prefer to obtain a pre-built executable version. A collection of pre-built
executables for various machines is currently available for anonymous FTP at
procyon.cis.ksu.edu (129.130.10.80 --- this number is due to change soon);
look under /pub/JPEG. The administrators of this system ask that FTP traffic
be limited to non-prime hours. For more information on this archive, please
contact Steve Davis (strat@cis.ksu.edu). This collection is not maintained by
the Independent JPEG Group, and programs in it may not be the latest version.
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
general information about JPEG. It is updated constantly and therefore
is not included in this distribution. The FAQ is posted every two weeks
to Usenet newsgroups comp.graphics, news.answers, and other groups. You
can always obtain the latest version from the news.answers archive at
rtfm.mit.edu (18.172.1.27). By FTP, fetch /pub/usenet/news.answers/jpeg-faq.
If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu with body
"send usenet/news.answers/jpeg-faq".
SUPPORTING SOFTWARE
@@ -135,11 +151,18 @@ work on any non-Unix machine.
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.
There will soon be a new release of xv that incorporates our software and thus
can read and write JPEG files directly. (NOTE: since xv internally reduces
all images to 8 bits/pixel, a JPEG file written by xv will not be very high
quality. Caveat user.)
these can be found in the contrib directory at export.lcs.mit.edu. Actually,
xv version 2.00 and up incorporates our software and thus can read and write
JPEG files directly. (NOTE: since xv internally reduces all images to 8
bits/pixel, a JPEG file written by xv will not be very high quality; and xv
cannot fully exploit a 24-bit display. These problems are expected to go away
in the next xv release, planned for early 1993. In the meantime, use
xloadimage for 24-bit displays.)
For DOS machines, Lee Crocker's free Piclab program is a useful companion to
the JPEG software. The latest version, currently 1.91, is available by FTP
from SIMTEL20 and its various mirror sites, file <msdos.graphics>piclb191.zip.
CompuServe also has it, in the same library as the JPEG software.
SOFTWARE THAT'S NO HELP AT ALL
@@ -152,67 +175,146 @@ to produce compatible files with its -j switch, and their decompression
program JPG2GIF can read our files (at least ones produced with our default
option settings).
Unfortunately, most commercial JPEG implementations are also incompatible as
of this writing, especially programs released before summer 1991. The root of
the problem is that the ISO JPEG committee failed to specify a concrete file
format. Many vendors "filled in the blanks" on their own, creating
proprietary formats that no one else could read. (For example, none of the
early commercial JPEG implementations for the Macintosh were able to exchange
compressed files.)
Some commercial JPEG implementations are also incompatible as of this writing,
especially programs released before summer 1991. The root of the problem is
that the ISO JPEG committee failed to specify a concrete file format. Some
vendors "filled in the blanks" on their own, creating proprietary formats that
no one else could read. (For example, none of the early commercial JPEG
implementations for the Macintosh were able to exchange compressed files.)
The file format we have adopted is called JFIF (see REFERENCES). This format
has been agreed to by a number of major commercial JPEG vendors, and we expect
that it will become the de facto standard. JFIF is a minimal representation;
work is also going forward to incorporate JPEG compression into the TIFF
work is also going forward to incorporate JPEG compression into the TIFF 6.0
standard, for use in "high end" applications that need to record a lot of
additional data about an image. We intend to support JPEG-in-TIFF in the
future. We hope that these two formats will be sufficient and that other,
incompatible JPEG file formats will not proliferate.
additional data about an image. We intend to support TIFF 6.0 in the future.
We hope that these two formats will be sufficient and that other, incompatible
JPEG file formats will not proliferate.
Indeed, part of the reason for developing and releasing this free software is
to help force rapid convergence to de facto standards for JPEG file formats.
SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or JPEG-in-TIFF!
SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or TIFF 6.0!
USING JPEG AS A SUBROUTINE IN A LARGER PROGRAM
==============================================
You can readily incorporate the JPEG compression and decompression routines in
a larger program. The file example.c provides a skeleton of the interface
routines you'll need for this purpose. Essentially, you replace jcmain.c (for
compression) and/or jdmain.c (for decompression) with your own code. Note
that the fewer JPEG options you allow the user to twiddle, the less code you
need; all the default options are set up automatically. (Alternately, if you
know a lot about JPEG or have a special application, you may want to twiddle
the default options even more extensively than jcmain/jdmain do.)
Most likely, you will want the uncompressed image to come from memory (for
compression) or go to memory or the screen (for decompression). For this
purpose you must provide image reading or writing routines that match the
interface used by the image file I/O modules (jrdXXX or jwrXXX); again,
example.c shows a skeleton of what is required. In this situation, you
won't need any of the non-JPEG image file I/O modules used by cjpeg and djpeg.
By default, any error detected inside the JPEG routines will cause a message
to be printed on stderr, followed by exit(). You can override this behavior
by supplying your own message-printing and/or error-exit routines; again,
example.c shows how.
We recommend you create libjpeg.a as shown in the Makefile, then link that
with your surrounding program. (If your linker is at all reasonable, only the
code you actually need will get loaded.) Include the files jconfig.h and
jpegdata.h in C files that need to call the JPEG routines.
CAUTION: some people have tried to compile JPEG and their surrounding code
with different compilers, e.g., cc for JPEG and c++ or gcc for the rest. This
is a Real Bad Move and you will deserve what happens to you if you try it.
(Hint: the parameter structures can get laid out differently with no warning.)
Read our "architecture" file for more info. If it seems to you that the
software structure doesn't accommodate what you want to do, please contact
the authors.
Beginning with version 3, we will endeavor to hold the interface described by
example.c constant, so that you can plug in updated versions of the JPEG code
just by recompiling. However, we can't guarantee this, especially if you
choose to twiddle any JPEG options not listed in example.c. Check the
CHANGELOG when installing any new version, and compare example.c against the
prior version. Recompile your calling software (don't just relink), as we may
add or subtract fields in the parameter structures.
REFERENCES
==========
The best and most readily available introduction to the JPEG compression
algorithm is Wallace's article in the April '91 CACM:
We highly recommend reading one or more of these references before trying to
understand the innards of any JPEG software.
The best short technical introduction to the JPEG compression algorithm is
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 trying to understand the innards of any JPEG software.
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PostScript file containing a revised version of the article is
available at ftp.uu.net, graphics/jpeg/wallace.ps.Z. The file (actually a
preprint for an article to appear in IEEE Trans. Consumer Electronics) omits
the sample images that appeared in CACM, but it includes corrections and some
added material. Note: the Wallace article is copyright ACM and IEEE, and it
may not be used for commercial purposes.
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 standard is not now available electronically; you must order a paper copy
through ISO. In the US, copies may be ordered from ANSI Sales at (212)
642-4900. The standard is divided into two parts: Part 1 is the actual
specification, and Part 2 covers compliance testing methods. The current
"committee draft" version of Part 1 is titled "Digital Compression and Coding
of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has
document number ISO/IEC CD 10918-1. (The alternate number SC2 N2215 should
also be mentioned when ordering.) This draft is expected to be superseded by
the Draft International Standard version around the end of November 1991.
Ordering info will be the same as above, but replace "CD" with "DIS" in the
document number (alternate number not yet known). The committee draft of
Part 2 is expected to be available around the end of December 1991. It will
be titled "Digital Compression and Coding of Continuous-tone Still Images,
Part 2: Compliance testing" and will have document number ISO/IEC CD 10918-2
(alternate number not yet known).
A somewhat less technical, more leisurely introduction to JPEG can be found in
"The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood
City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and
example C code for a multitude of compression methods including JPEG. It is
an excellent source if you are comfortable reading C code but don't know much
about data compression in general. The book's JPEG sample code is far from
industrial-strength, but when you are ready to look at a full implementation,
you've got one here...
A new textbook about JPEG is "JPEG Still Image Data Compression Standard" by
William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand
Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95. This book includes the
complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2).
This is by far the most complete exposition of JPEG in existence, and I highly
recommend it. If you read the entire book, you will probably know more about
JPEG than I do.
The JPEG standard itself is not available electronically; you must order a
paper copy through ISO. (Unless you are concerned about having a certified
official copy, I recommend buying the Pennebaker and Mitchell book instead;
it's much cheaper and includes a great deal of useful explanatory material.)
In the US, copies of the standard may be ordered from ANSI Sales at (212)
642-4900. It's not cheap: as of 1992, Part 1 is $95 and Part 2 is $47, plus
7% shipping/handling. The standard is divided into two parts, Part 1 being
the actual specification, while Part 2 covers compliance testing methods.
As of early 1992, Part 1 has Draft International Standard status. It is
titled "Digital Compression and Coding of Continuous-tone Still Images, Part
1: Requirements and guidelines" and has document number ISO/IEC DIS 10918-1.
Part 2 is still at Committee Draft status. It is titled "Digital Compression
and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and
has document number ISO/IEC CD 10918-2. (NOTE: I'm told that the final
version of Part 2 will differ considerably from the CD draft.)
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:
1.02. 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. The same source can
supply copies of the draft JPEG-in-TIFF specs.
A PostScript version of this document is available at ftp.uu.net, file
graphics/jpeg/jfif.ps.Z. It can also be obtained by e-mail from the C-Cube
mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg"
to the server to obtain the JFIF document; send the message "help" if you have
trouble.
The TIFF 6.0 file format specification can be obtained by FTP from sgi.com
(192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed copy
from Aldus Corp. at (206) 628-6593. It should be noted that the TIFF 6.0 spec
of 3-June-92 has a number of serious problems in its JPEG features. A
clarification note will probably be needed to ensure that TIFF JPEG files are
compatible across different implementations. The IJG does not intend to
support TIFF 6.0 until these problems are resolved.
If you want to understand this implementation, start by reading the
"architecture" documentation file. Please read "codingrules" if you want to
@@ -227,7 +329,7 @@ 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.
This software is copyright (C) 1991, 1992, Thomas G. Lane.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
@@ -244,10 +346,10 @@ the Independent JPEG Group".
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".
Permission is NOT granted for the use of any IJG author's name or 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
@@ -260,7 +362,7 @@ 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
of any program generated from the JPEG code, this does not limit you more than
the foregoing paragraphs do.
@@ -270,7 +372,7 @@ 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 the necessary licenses,
implementors will support it. If you do obtain the necessary licenses,
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.
@@ -285,13 +387,13 @@ We are required to state that
TO DO
=====
The next major release will probably be a significant rewrite to allow use of
this code in conjunction with Sam Leffler's free TIFF library (assuming the
bugs in the TIFF 6.0 specification get resolved).
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.
implementations, or to provide faster paths for common cases.
Speeding things up is still high on our priority list.
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

453
SETUP
View File

@@ -26,16 +26,22 @@ STEP 1: PREPARE A MAKEFILE
First, select a makefile and copy it to "Makefile" (or whatever your version
of make uses as the default makefile name; for example, "makefile.mak" for
Borland C). We include several standard makefiles in the distribution:
old versions of Borland C). We include several standard makefiles in the
distribution:
makefile.ansi: for Unix systems with ANSI-compatible C compilers.
makefile.unix: for Unix systems with non-ANSI C compilers.
makefile.mc5: for Microsoft C 5.x under MS-DOS.
makefile.mc6: for Microsoft C 6.x under MS-DOS.
makefile.tc: for Borland's Turbo C under MS-DOS.
makefile.pwc: for Mix Software's Power C under MS-DOS.
makefile.manx: for Manx Aztec C on Amigas.
makefile.sas: for SAS C on Amigas.
makefile.ansi: for Unix systems with ANSI-compatible C compilers.
makefile.unix: for Unix systems with non-ANSI C compilers.
makefile.mc5: for Microsoft C 5.x under MS-DOS.
makefile.mc6: for Microsoft C 6.x and up under MS-DOS.
makefile.bcc: for Borland C (Turbo C) under MS-DOS.
makefile.icc: for Intel's Code Builder C under MS-DOS.
makefile.manx: for Manx Aztec C on Amigas.
makefile.sas: for SAS C on Amigas.
makcjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makdjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makljpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C.
makefile.mms: for VAX/VMS systems with MMS.
makefile.vms: for VAX/VMS systems without MMS.
If you don't see a makefile for your system, we recommend starting from either
makefile.ansi or makefile.unix, depending on whether your compiler accepts
@@ -46,32 +52,40 @@ preprocesses the source code to convert function definitions to old-style C.
(Our thanks to Peter Deutsch of Aladdin Enterprises for the ansi2knr program.)
If you don't know whether your compiler supports ANSI-style function
definitions, then take a look at config.c. It is a test program that will
definitions, then take a look at ckconfig.c. It is a test program that will
help you figure out this fact, as well as some other facts you'll need in
later steps. You must compile and execute config.c by hand; the makefiles
don't provide any support for this. config.c may not compile the first try
later steps. You must compile and execute ckconfig.c by hand; the makefiles
don't provide any support for this. ckconfig.c may not compile the first try
(in fact, the whole idea is for it to fail if anything is going to). If you
get compile errors, fix them by editing config.c according to the directions
given in config.c. Once you get it to run, select a makefile according to the
advice it prints out, and make any other changes it recommends.
get compile errors, fix them by editing ckconfig.c according to the directions
given in ckconfig.c. Once you get it to run, select a makefile according to
the advice it prints out, and make any other changes it recommends.
Look over the selected Makefile and adjust options as needed. In particular
you may want to change the CC and CFLAGS definitions. For instance, if you
are using GCC, set CC=gcc.
are using GCC, set CC=gcc. If you had to use any compiler switches to get
ckconfig.c to work, make sure the same switches are in CFLAGS.
If you are on a system that doesn't use makefiles, you'll need to set up
project files (or whatever you do use) to compile all the source files and
link them into executable files cjpeg and djpeg. See the file lists in any of
the makefiles to find out which files go into each program (makcjpeg.lst and
makdjpeg.lst are handy summaries).
the makefiles to find out which files go into each program. As a last resort,
you can make a batch script that just compiles everything and links it all
together; makefile.vms is an example of this (it's for VMS systems that have
no make-like utility).
STEP 2: EDIT JCONFIG.H
======================
Look over jconfig.h and adjust #defines to reflect the properties of your
system and C compiler. (If you prefer, you can usually leave jconfig.h
unmodified and add -Dsymbol switches to the Makefile's CFLAGS definition.)
system and C compiler. If you prefer, you can usually leave jconfig.h
unmodified and add -Dsymbol switches to the Makefile's CFLAGS definition.
(This is already done if you used a compiler-specific makefile in step 1.)
However, putting the switches in the Makefile is a bad idea if you are going
to incorporate the JPEG software into other programs --- you'd need to include
the same -D switches in the other programs' Makefiles. Better to change
jconfig.h.
If you have an ANSI-compliant C compiler, no changes should be necessary
except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE. For
@@ -79,8 +93,8 @@ older compilers other changes may be needed, depending on what ANSI features
are supported.
If you don't know enough about C programming to understand the questions in
jconfig.h, then use config.c to figure out what to change. (See description
of config.c in step 1.)
jconfig.h, then use ckconfig.c to figure out what to change. (See description
of ckconfig.c in step 1.)
A note about TWO_FILE_COMMANDLINE: defining this selects the command line
syntax in which the input and output files are both named on the command line.
@@ -88,57 +102,213 @@ If it's not defined, the output image goes to standard output, and the input
can optionally come from standard input. You MUST use two-file style on any
system that doesn't cope well with binary data fed through stdin/stdout; this
is true for most MS-DOS compilers, for example. If you're not on a Unix
system, it's probably safest to assume you need two-file style.
system, it's probably safest to assume you need two-file style. (But if your
compiler provides either the Posix-standard fdopen() library routine or a
Microsoft-compatible setmode() routine, you can use the Unix command line
style, by defining USE_FDOPEN or USE_SETMODE respectively.)
STEP 3: MAKE
STEP 3: SELECT SYSTEM-DEPENDENT FILES
=====================================
A few places in the JPEG software are so system-dependent that we have to
provide several different implementations and let you select the one you need.
The only system-dependent file in the current version is jmemsys.c. This file
controls use of temporary files for big images that won't fit in main memory.
You'll notice there is no file named jmemsys.c in the distribution; you must
select one of the provided versions and copy, rename, or link it to jmemsys.c.
Here are the provided versions:
jmemansi.c This is a reasonably portable version that should
work on most ANSI and near-ANSI C compilers. It uses
the ANSI-standard library routine tmpfile(), which not
all non-ANSI systems have. On some systems tmpfile()
may put the temporary file in a non-optimal location;
if you don't like what it does, use jmemname.c.
jmemname.c This version constructs the temp file name by itself.
For anything except a Unix machine, you'll need to
configure the select_file_name() routine appropriately;
see the comments near the head of jmemname.c.
If you use this version, define NEED_SIGNAL_CATCHER
in jconfig.h or in the Makefile to make sure the temp
files are removed if the program is aborted.
jmemnobs.c (That stands for No Backing Store :-). This will
compile on almost any system, but it assumes you
have enough main memory or virtual memory to hold
the biggest images you need to work with.
jmemdos.c This should be used in most MS-DOS installations; see
the system-specific notes about MS-DOS for more info.
IMPORTANT: if you use this, also copy jmemdos.h to
jmemsys.h, replacing the standard version. ALSO,
include the assembly file jmemdosa.asm in the programs.
(This last is already done if you used one of the
supplied MS-DOS-specific makefiles.)
If you have plenty of (real or virtual) main memory, just use jmemnobs.c.
"Plenty" means at least ten bytes for every pixel in the largest images
you plan to process, so a lot of systems don't meet this criterion.
If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have
to use jmemname.c; be sure to adjust select_file_name() for local conditions.
You may also need to change unlink() to remove() in close_backing_store().
Except with jmemnobs.c, you need to adjust the #define DEFAULT_MAX_MEM to a
reasonable value for your system (either by editing jmemsys.c, or by adding
a -D switch to the Makefile). This value limits the amount of data space the
program will attempt to allocate. Code and static data space isn't counted,
so the actual memory needs for cjpeg or djpeg are typically 100 to 150Kb more
than the max-memory setting. Larger max-memory settings reduce the amount of
I/O needed to process a large image, but too large a value can result in
"insufficient memory" failures. On most Unix machines (and other systems with
virtual memory), just set DEFAULT_MAX_MEM to several million and forget it.
At the other end of the spectrum, for MS-DOS machines you probably can't go
much above 300K to 400K. (On MS-DOS the value refers to conventional memory;
extended/expanded memory is handled separately by jmemdos.c.)
STEP 4: MAKE
============
Now you should be able to "make" the software.
If you have trouble with missing system include files or inclusion of the
wrong ones, look at jinclude.h (or use config.c, if you are not a C expert).
wrong ones, look at jinclude.h (or use ckconfig.c, if you are not a C expert).
If your compiler complains about big_sarray_control and big_barray_control
being undefined structures, you should be able to shut it up by adding
-DINCOMPLETE_TYPES_BROKEN to CFLAGS (or add #define INCOMPLETE_TYPES_BROKEN
to jconfig.h).
to jconfig.h). If you don't have a getenv() library routine, define NO_GETENV.
There are a fair number of routines that do not use all of their parameters;
some compilers will issue warnings about this, which you can ignore. Any
other warning deserves investigation.
STEP 4: TEST
STEP 5: TEST
============
As a quick test of functionality we've included three small sample files:
As a quick test of functionality we've included a small sample image in
several forms:
testorig.jpg A reduced section of the well-known Lenna picture.
testimg.ppm The output of djpeg testorig.jpg
testimg.gif The output of djpeg -gif testorig.jpg
testimg.jpg The output of cjpeg testimg.ppm
(The two .jpg files aren't identical since JPEG is lossy.) If you can
generate duplicates of testimg.ppm and testimg.jpg then you probably have a
working port.
generate duplicates of the testimg.* files then you probably have working
programs.
With most of the makefiles, "make test" will perform the necessary
comparisons. If you're using a makefile that doesn't provide this option, run
djpeg and cjpeg to generate testout.ppm and testout.jpg, then compare these to
testimg.* with whatever file comparison tool you have. The files should be
bit-for-bit identical.
comparisons. If you started with makefile.ansi or makefile.unix, and you
defined TWO_FILE_COMMANDLINE, then change the makefile's test script to use
two-file syntax (i.e., delete the ">" character from the invocations of cjpeg
and djpeg). The other makefiles will work with either command-line syntax.
If you're using a makefile that doesn't provide the test option, run djpeg and
cjpeg by hand to generate testout.ppm, testout.gif, and testout.jpg, then
compare these to testimg.* with whatever binary file comparison tool you have.
The files should be bit-for-bit identical.
If the cjpeg test run fails with "Missing Huffman code table entry", it's a
good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to step 2
and run ckconfig.c. (This is a good plan for any other test failure, too.)
If you are using Unix (one-file) command line style on a non-Unix system,
it's a good idea to check that binary I/O through stdin/stdout actually works.
You should get the same results from "djpeg <testorig.jpg >out.ppm" as from
"djpeg -outfile out.ppm testorig.jpg". Note that the non-Unix makefiles use
the latter style and therefore do not exercise stdin/stdout. If this test
fails, try recompiling jcmain.c & jdmain.c with USE_SETMODE and/or USE_FDOPEN.
If your choice of jmemsys.c was anything other than jmemnobs.c, you should
test that temporary-file usage works. Try "djpeg -gif -max 0 testorig.jpg"
and make sure its output matches testimg.gif. If you have any really large
images handy, try compressing them with -optimize and/or decompressing with
-gif to make sure your DEFAULT_MAX_MEM setting is not too large.
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.
such as 1-pass color quantization, are not exercised at all. It's just a quick
test to give you some confidence that you haven't missed something major.
If the test passes, you can copy the executable files cjpeg and djpeg to
wherever you normally install programs. Read the file USAGE to learn more
about using the programs.
STEP 6: INSTALLATION
====================
Once you're done with the above steps, you can install the software by copying
the executable files (cjpeg and djpeg) to wherever you normally install
programs. On Unix systems, you'll also want to put cjpeg.1 and djpeg.1 in the
corresponding manual directory. (The makefiles don't support this step since
there's such a wide variety of installation procedures on different systems.)
To learn to use the programs, read the file USAGE (or manual pages cjpeg(1)
and djpeg(1) on Unix). Note that the man pages cjpeg.1/djpeg.1 only describe
the Unix-style command line syntax; if you want to use these files with a
version that uses two-file command line syntax, you'll have to modify the text
accordingly. The USAGE file describes both styles.
OPTIMIZATION
============
Unless you own a Cray, you'll probably be interested in making the JPEG
software go as fast as possible. This section covers some machine-dependent
optimizations you may want to try. We suggest that before trying any of this,
you first get the basic installation to pass the self-test (step 5 above).
Repeat the self-test after any optimization to make sure that you haven't
broken anything.
The JPEG DCT routines perform a lot of multiplications. These multiplications
must yield 32-bit results, but none of their input values are more than 16
bits wide. On many machines, notably the 680x0 and 80x86 CPUs, a 16x16=>32
bit multiply instruction is faster than a full 32x32=>32 bit multiply.
Unfortunately there is no portable way to specify such a multiplication in C,
but some compilers can generate one when you use the right combination of
casts. See the MULTIPLY macro definitions in jfwddct.c and jrevdct.c.
If your compiler makes "int" be 32 bits and "short" be 16 bits, defining
SHORTxSHORT_32 is fairly likely to work. When experimenting with alternate
definitions, be sure to test not only whether the code still works (use the
self-test step), but also whether it is actually faster --- on some compilers,
alternate definitions may compute the right answer, yet be slower than the
default. Timing cjpeg on a large PPM input file is the best way to check
this, as the DCT will be the largest fraction of the runtime in that mode.
(Note: some of the distributed compiler-specific makefiles already contain
-D switches to select an appropriate MULTIPLY definition.)
If access to "short" arrays is slow on your machine, it may be a win to define
type DCTELEM as int rather than as JCOEF (which is normally defined as short).
This will cause the DCT routines to operate on int arrays instead of short
arrays. If shorts are slow and you have lots of memory to burn, you might
even make JCOEF itself be int.
If your compiler can compile function calls in-line, make sure the INLINE
macro in jconfig.h is defined as the keyword that marks a function
inline-able. Some compilers have a switch that tells the compiler to inline
any function it thinks is profitable (e.g., -finline-functions for gcc).
Enabling such a switch is likely to make the compiled code bigger but faster.
In general, it's worth trying the maximum optimization level of your compiler,
and experimenting with any optional optimizations such as loop unrolling.
(Unfortunately, far too many compilers have optimizer bugs ... be prepared to
back off if the code fails self-test.) If you do any experimentation along
these lines, please report the optimal settings to jpeg-info@uunet.uu.net so
we can mention them in future releases. Be sure to specify your machine and
compiler version.
OPTIONAL STUFF
==============
Progress monitor:
If you like, you can #define PROGRESS_REPORT (in jconfig.h or in the Makefile)
to enable display of percent-done progress reports. The routines provided in
jcmain.c/jdmain.c merely print percentages to stderr, but you can customize
them to do something fancier.
Utah RLE file format support:
We distribute the software with support for RLE image files (Utah Raster
Toolkit format) disabled, because the RLE support won't compile without the
Utah library. If you have URT version 3.0, you can enable RLE support as
@@ -151,19 +321,21 @@ follows:
the directory containing the URT "librle.a" file (typically the
"lib" subdirectory of the URT distribution).
JPEG library:
If you want to incorporate the JPEG code as subroutines in a larger program,
we recommend that you make libjpeg.a. Then use the jconfig.h and jpegdata.h
files as your interface to the JPEG functions, and link libjpeg.a with your
program. 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.
we recommend that you make libjpeg.a, then link that into your surrounding
program. See file README for more info.
CAUTION: When you use the JPEG code as subroutines, we recommend that you make
any required configuration changes by modifying jconfig.h, not by adding -D
switches to the Makefile. Otherwise you must be sure to provide the same -D
switches when compiling any program that includes the JPEG .h files.
switches when compiling any program that includes the JPEG .h files, to ensure
that the parameter structures are interpreted the same way. (This is only
critical for the first few symbols mentioned in jconfig.h, down through
NEED_FAR_POINTERS.)
Removing code:
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
@@ -178,33 +350,85 @@ NOTES FOR SPECIFIC SYSTEMS
==========================
We welcome reports on changes needed for systems not mentioned here.
Submit 'em to jpeg-info@uunet.uu.net. Also, config.c is fairly new and not
yet thoroughly tested; if it's wrong about how to configure the JPEG software
for your system, please let us know.
Submit 'em to jpeg-info@uunet.uu.net. Also, if ckconfig.c is wrong about
how to configure the JPEG software for your system, please let us know.
Amiga:
Makefiles are provided for Manx Aztec C and SAS C. I have also heard from
people who have compiled with the free DICE compiler, using makefile.ansi as a
starting point (set "CC= dcc" and "CFLAGS= -c -DAMIGA -DTWO_FILE_COMMANDLINE
-DNEED_SIGNAL_CATCHER" in the makefile). For all compilers, we recommend you
use jmemname.c as the system-dependent memory manager. Assuming you have
-DAMIGA in the makefile, jmemname.c will put temporary files in JPEGTMP:.
Change jmemname.c if you don't like this.
Atari:
The project files provided should work as-is with Pure C. For Turbo C, change
library filenames "PC..." to "TC..." in the project files for cjpeg.ttp and
djpeg.ttp. Don't forget to select a jmemsys.c file, see Step 3 (we recommend
jmemansi.c). Also adjust the DEFAULT_MAX_MEM setting --- you probably want it
to be a couple hundred K less than your normal free memory. Note that you
must make jpeg.lib before making cjpeg.ttp or cjpeg.ttp. You'll have to
perform the self-test (Step 5) by hand.
There is a bug in some older versions of the Turbo C library which causes the
space used by temporary files created with "tmpfile()" not to be freed after
an abnormal program exit. If you check your disk afterwards, you will find
cluster chains that are allocated but not used by a file. This should not
happen in cjpeg or djpeg, since we enable a signal catcher to explicitly close
temp files before exiting. But if you use the JPEG library with your own
code, be sure to supply a signal catcher, or else use a different
system-dependent memory manager.
Cray:
Should you be so fortunate as to be running JPEG on a Cray YMP, there is a
compiler bug in Cray's Standard C versions prior to 3.1. You'll need to
insert a line reading "#pragma novector" just before the loop
for (i = 1; i <= (int) htbl->bits[l]; i++)
huffsize[p++] = (char) l;
in fix_huff_tbl (in V4A, line 42 of jchuff.c and line 39 of jdhuff.c). The
usual symptom of not adding this line is a core-dump. See Cray's SPR 48222.
HP/Apollo DOMAIN:
At least in version 10.3.5, the C compiler is ANSI but the system include
files are not. Use makefile.ansi and add -DNONANSI_INCLUDES to CFLAGS.
With system release 10.4 or later, makefile.ansi should work OK. If you have
version 10.3.anything, you need to figure out whether you have the ANSI C
compiler (version 6.7 or later) and whether you've installed the ANSI C
include files (if so, the first line of <stdio.h> will mention ANSI C).
If you have the ANSI C compiler but not the ANSI C include files, use
makefile.ansi and add -DNONANSI_INCLUDES to CFLAGS. If you have both,
then makefile.ansi should work as is. If neither, use makefile.unix.
HP-UX:
If you have HP-UX 7.05 or later with the "software development" C compiler,
then you can use makefile.ansi. Add "-Aa" to the CFLAGS line in the
makefile. If you have a pre-7.05 system, or if you are using the non-ANSI C
compiler delivered with a minimum HP-UX 8.0 system, then you must use
makefile.unix (and do NOT add -Aa). Also, adding "-lmalloc" to LDLIBS is
recommended if you have libmalloc.a (it seems not to be present in minimum
8.0).
then you can use makefile.ansi. Add "-Aa" to the CFLAGS line in the makefile
to make the compiler work in ANSI mode. If you have a pre-7.05 system, or if
you are using the non-ANSI C compiler delivered with a minimum HP-UX 8.0
system, then you must use makefile.unix (and do NOT add -Aa). Also, adding
"-lmalloc" to LDLIBS is recommended if you have libmalloc.a (it seems not to
be present in minimum 8.0).
On HP series 800 machines, the HP C compiler is buggy in revisions prior to
A.08.07. If you get complaints about "not a typedef name", you'll have to
On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior
to A.08.07. If you get complaints about "not a typedef name", you'll have to
convert the code to K&R style (i.e., use makefile.unix).
IBM RS/6000 AIX:
The CFLAGS switch to make the compiler define __STDC__ is "-qlanglvl=ansi".
Macintosh MPW:
We don't directly support MPW in the current release, but Larry Rosenstein
reports that the JPEG code can be ported without very much trouble. There's
useful notes and conversion scripts in his kit for porting PBMPLUS to MPW.
You can obtain the kit by FTP to ftp.apple.com, file /pub/lsr/pbmplus-port*.
Macintosh Think C:
@@ -215,17 +439,108 @@ project. Also 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.
If you have Think C 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. (You can #define __STDC__, but also #define const.)
If you have Think C version 5.0 you need not modify jconfig.h; instead you
should turn on both the ANSI Settings and Language Extensions option buttons
(so that both __STDC__ and THINK_C are predefined). With version 4.0 you must
edit jconfig.h. (You can #define HAVE_STDC to do the right thing for all
options except const; you must also #define const.)
Microsoft C for MS-DOS:
jcmain and jdmain are set up to provide the usual command-line interface
by means of Think's ccommand() library routine. A more Mac-like interface
is in the works.
Some versions of MS C fail with an "out of macro expansion space" error
MS-DOS, generic comments:
The JPEG code is designed to be compiled with 80x86 "small" or "medium" memory
models (i.e., data pointers are 16 bits unless explicitly declared "far"; code
pointers can be either size). You should be able to use small model to
compile cjpeg or djpeg by itself, but you will probably have to go to medium
model if you include the JPEG code in a larger application. This shouldn't
hurt performance much. You *will* take a noticeable performance hit if you
compile in a large-data memory model, and you should avoid "huge" model if at
all possible. Be sure that NEED_FAR_POINTERS is defined by jconfig.h or by
the Makefile if you use a small-data model; be sure it is NOT defined if you
use a large-data memory model. (As distributed, jconfig.h defines
NEED_FAR_POINTERS if MSDOS is defined.)
The DOS-specific memory manager, jmemdos.c, should be used if possible.
(Be sure to install jmemdos.h and jmemdosa.asm along with it.) If you
can't use jmemdos.c for some reason --- for example, because you don't have
a Microsoft-compatible assembler to assemble jmemdosa.asm --- you'll have
to fall back to jmemansi.c or jmemname.c. IMPORTANT: if you use either of
the latter two files, you will have to compile in a large-data memory model
in order to get the right stdio library. Too bad.
None of the above advice applies if you are using a 386 flat-memory-space
environment, such as DJGPP or Watcom C. (And you should use one if you have
it, as performance will be much better than 8086-compatible code!) For
flat-memory-space compilers, do NOT define NEED_FAR_POINTERS, and do NOT use
jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual
memory, otherwise use jmemansi.c or jmemname.c.
Most MS-DOS compilers treat stdin/stdout as text files, so you must use
two-file command line style. But if your compiler has either fdopen() or
setmode(), you can use one-file style if you like. To do this, define
USE_FDOPEN or USE_SETMODE so that stdin/stdout will be set to binary mode.
(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You
should test that I/O through stdin/stdout produces the same results as I/O
to explicitly named files... the "make test" procedures in the DOS-specific
makefiles do NOT use stdin/stdout.
If you add more switches to CFLAGS in the DOS-specific makefiles, you are
likely to run up against DOS' 128-byte command line length limit. In that
case, remove some "-Dsymbol" switches from CFLAGS and instead put
corresponding "#define symbol" lines at the head of jinclude.h.
MS-DOS, Borland C:
Be sure to convert all the source files to DOS text format (CR/LF newlines).
Although Borland C will often work OK with unmodified Unix (LF newlines)
source files, sometimes it will give bogus compile errors.
"Illegal character '#'" is the most common such error.
Some versions of Borland's MAKE erroneously display the warning message about
creating jmemsys.c, even after you have done so. If this happens to you,
delete the four lines beginning with "jmemsys.c:" from the Makefile.
If you want one-file command line style, define USE_SETMODE. fdopen() does
not work correctly.
MS-DOS, DJGPP:
Use makefile.ansi and jmemnobs.c, and put "-UMSDOS" in CFLAGS to undo the
compiler's automatic definition of MSDOS. Also put either "-DUSE_SETMODE" or
"-DTWO_FILE_COMMANDLINE" in CFLAGS, depending on whether you prefer one-file
or two-file command line style. You'll also need to put the object-file lists
into response files in order to circumvent DOS's 128-byte command line length
limit at the final linking step.
MS-DOS, Microsoft C:
Old versions of MS C fail with an "out of macro expansion space" error
because they can't cope with the macro TRACEMS8 (defined in jpegdata.h).
If this happens to you, the easiest solution is to change TRACEMS8 to
expand to nothing. You'll lose the ability to dump out JPEG coefficient
tables with djpeg -d -d, but at least you can compile.
tables with djpeg -debug -debug, but at least you can compile.
Original MS C 6.0 is buggy; it compiles incorrect code unless you turn off
optimization (remove -O from CFLAGS). That problem seems to have been fixed
in 6.00A and later versions. 6.00A still generates a bogus "conditional
expression is constant" warning in jrdppm.c, but the emitted code seems OK.
If you want one-file command line style, define USE_SETMODE. fdopen() does
not work correctly, at least not in 6.00A.
SGI:
Use makefile.ansi, but set "AR2= ar -ts" rather than "AR2= ranlib". Also
make any changes recommended by ckconfig.c.
Sun:

332
USAGE
View File

@@ -1,28 +1,36 @@
USAGE instructions for the Independent JPEG Group's JPEG software
=================================================================
INTRODUCTION
This distribution contains software to implement JPEG image compression and
decompression. JPEG (pronounced "jay-peg") 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 no visible change, and
amazingly high compression levels can be obtained if you can tolerate a
low-quality image.
method for full-color and gray-scale images. JPEG is designed to handle
"real-world" scenes, for example scanned photographs. Cartoons, line
drawings, and other non-realistic images are not JPEG's strong suit; on this
sort of material you may get poor image quality and/or little compression.
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 real-world images, very good compression
levels can be obtained with no visible change, and amazingly high compression
is possible if you can tolerate a low-quality image. You can trade off image
quality against file size by adjusting the compressor's "quality" setting.
This file describes usage of the standard programs "cjpeg" and "djpeg" that
can be built directly from the distributed software. See the README file for
can be built directly from the distributed C code. See the README file for
hints on incorporating the JPEG software into other programs.
If you are on a Unix machine you may prefer to read the Unix-style manual
pages in files cjpeg.1 and djpeg.1.
pages in files cjpeg.1 and djpeg.1. But also see the HINTS section below,
which is not present in either manual page.
NOTE: at some point we will probably redesign the user interface, so the
command line switches described here will change.
NOTE: the switch syntax has been redesigned since the v3 release of
cjpeg/djpeg. Switch names are now words instead of single letters.
GENERAL USAGE
We provide two programs, cjpeg to compress an image file into JPEG format,
and djpeg to decompress a JPEG file back into a conventional image format.
@@ -35,128 +43,266 @@ 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:
On most non-Unix systems, you say:
cjpeg [switches] imagefile jpegfile
or
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; see SETUP.)
i.e., both the 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 when you compile the programs; see SETUP.)
You can also say:
cjpeg [switches] -outfile jpegfile imagefile
or
djpeg [switches] -outfile imagefile jpegfile
This syntax works on all systems, so it is useful for scripts.
The currently supported image file formats are: PPM (PBMPLUS color format),
PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit
format). (RLE is supported only if the URT library is available.)
cjpeg recognizes the input image format automatically, with the exception
of some Targa-format files.
of some Targa-format files. You have to tell djpeg which format to generate.
The only JPEG file format currently supported is the JFIF format. Support for
the TIFF/JPEG format will probably be added at some future date.
the TIFF 6.0 JPEG format will probably be added at some future date.
All switch names may be abbreviated; for example, -grayscale may be written
-gray or -gr. Most of the "basic" switches can be abbreviated to as little as
one letter. Upper and lower case are equivalent (-GIF is the same as -gif).
British spellings are also accepted (e.g., -greyscale), though for brevity
these are not mentioned below.
The command line switches for cjpeg are:
CJPEG DETAILS
-Q quality Scale quantization tables to adjust image quality.
The basic command line switches for cjpeg are:
-quality N Scale quantization tables to adjust image quality.
Quality is 0 (worst) to 100 (best); default is 75.
(See below for more info.)
-o Perform optimization of entropy encoding parameters.
Without this, default encoding parameters are used.
-o usually makes the JPEG file a little smaller, but
cjpeg runs much slower. Image quality and speed of
decompression are unaffected by -o.
-grayscale Create monochrome JPEG file from color input.
Be sure to use this switch when compressing a grayscale
GIF file, because cjpeg isn't bright enough to notice
whether a GIF file uses only shades of gray. By
saying -grayscale, you'll get a smaller JPEG file that
takes less time to process.
-T Input file is Targa format. Targa files that contain
-optimize Perform optimization of entropy encoding parameters.
Without this, default encoding parameters are used.
-optimize usually makes the JPEG file a little smaller,
but cjpeg runs somewhat slower and needs much more
memory. Image quality and speed of decompression are
unaffected by -optimize.
-targa Input file is Targa format. Targa files that contain
an "identification" field will not be automatically
recognized by cjpeg; for such files you must specify
-T to force cjpeg to treat the input as Targa format.
-targa to make cjpeg treat the input as Targa format.
-I Generate noninterleaved JPEG file (not yet supported).
The -quality switch lets you trade off compressed file size against quality of
the reconstructed image: the higher the quality setting, the larger the JPEG
file, and the closer the output image will be to the original input. Normally
you want to use the lowest quality setting (smallest file) that decompresses
into something visually indistinguishable from the original image. For this
purpose the quality setting should be between 50 and 95; the default of 75 is
often about right. If you see defects at -quality 75, then go up 5 or 10
counts at a time until you are happy with the output image. (The optimal
setting will vary from one image to another.)
-a Use arithmetic coding rather than Huffman coding.
-quality 100 will generate a quantization table of all 1's, eliminating loss
in the quantization step (but there is still information loss in subsampling,
as well as roundoff error). This setting is mainly of interest for
experimental purposes. Quality values above about 95 are NOT recommended for
normal use; the compressed file size goes up dramatically for hardly any gain
in output image quality.
In the other direction, quality values below 50 will produce very small files
of low image quality. Settings around 5 to 10 might be useful in preparing an
index of a large image library, for example. Try -quality 2 (or so) for some
amusing Cubist effects. (Note: quality values below about 25 generate 2-byte
quantization tables, which are considered optional in the JPEG standard.
cjpeg emits a warning message when you give such a quality value, because
some commercial JPEG programs may be unable to decode the resulting file.)
Switches for advanced users:
-maxmemory N Set limit for amount of memory to use in processing
large images. Value is in thousands of bytes, or
millions of bytes if "M" is attached to the number.
For example, -max 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
-restart N Emit a JPEG restart marker every N MCU rows, or every
N MCU blocks if "B" is attached to the number.
-restart 0 (the default) means no restart markers.
-smooth N Smooth the input image to eliminate dithering noise.
N, ranging from 1 to 100, indicates the strength of
smoothing. 0 (the default) means no smoothing.
-verbose Enable debug printout. More -v's give more printout.
or -debug Also, version information is printed at startup.
The -restart option inserts extra markers that allow a JPEG decoder to
resynchronize after a transmission error. Without restart markers, any damage
to a compressed file will usually ruin the image from the point of the error
to the end of the image; with restart markers, the damage is usually confined
to the portion of the image up to the next restart marker. Of course, the
restart markers occupy extra space. We recommend -restart 1 for images that
will be transmitted across unreliable networks such as Usenet.
The -smooth option filters the input to eliminate fine-scale noise. This is
often useful when converting GIF files to JPEG: a moderate smoothing factor of
10 to 50 gets rid of dithering patterns in the input file, resulting in a
smaller JPEG file and a better-looking image. Too large a smoothing factor
will visibly blur the image, however.
Switches for wizards:
-arithmetic Use arithmetic coding rather than Huffman coding.
(Not currently supported for legal reasons.)
-d Enable debug printout. More -d's give more printout.
Also, version information is printed at startup.
-nointerleave Generate noninterleaved JPEG file (not yet supported).
The -Q switch lets you trade off compressed file size against quality of the
reconstructed image: the higher the -Q setting, the larger the JPEG file, and
the closer the output image will be to the original input. Normally you want
to use the lowest -Q setting (smallest file) that decompresses into something
visually indistinguishable from the original image. For this purpose the -Q
setting should be between 50 and 95; the default of 75 is often about right.
If you see defects at -Q 75, then go up 5 or 10 counts at a time until you are
happy with the output image. (The optimal setting will vary from one image to
another.)
-qtables file Use the quantization tables given in the specified
file. The file should contain one to four tables
(64 values each) as plain text. Comments preceded by
'#' may be included in the file. The tables are
implicitly numbered 0,1,etc. If -quality N is also
specified, the values in the file are scaled according
to cjpeg's quality scaling curve.
-Q 100 will generate a quantization table of all 1's, eliminating loss in the
quantization step (but there is still information loss in subsampling, as well
as roundoff error). This setting is mainly of interest for experimental
purposes. -Q values above about 95 are NOT recommended for normal use; the
compressed file size goes up dramatically for hardly any gain in output image
quality.
-sample HxV[,...] Set JPEG sampling factors. If you specify
fewer H/V pairs than there are components, the
remaining components are set to 1x1 sampling. The
default setting is equivalent to "-sample 2x2".
In the other direction, -Q values below 50 will produce very small files of
low image quality. Settings around 5 to 10 might be useful in preparing an
index of a large image library, for example. Try -Q 2 (or so) for some
amusing Cubist effects. (Note: -Q values below about 25 generate 2-byte
quantization tables, which are considered optional in the JPEG standard.
cjpeg emits a warning message when you give such a -Q value, because some
commercial JPEG programs may be unable to decode the resulting file.)
The "wizard" switches are intended for experimentation with JPEG. If you
don't know what you are doing, DON'T USE THEM. You can easily produce files
with worse image quality and/or poorer compression than you'll get from the
default settings. Furthermore, these switches should not be used when making
files intended for general use, because not all JPEG implementations will
support unusual JPEG parameter settings.
The command line switches for djpeg are:
DJPEG DETAILS
-G Select GIF output format (implies -q, with default
of 256 colors).
The basic command line switches for djpeg are:
-P Select PPM or PGM output format (this is the default).
PGM is emitted if the JPEG file is gray-scale or if -g
is specified.
-colors N Reduce image to at most N colors. This reduces the
or -quantize N number of colors used in the output image, so that it
can be displayed on a colormapped display or stored in
a colormapped file format. For example, if you have
an 8-bit display, you'd need to reduce to 256 or fewer
colors. (-colors is the recommended name, -quantize
is provided only for backwards compatibility.)
-R Select RLE output format. Requires URT library.
-gif Select GIF output format. Since GIF does not support
more than 256 colors, -colors 256 is assumed (unless
you specify a smaller number of colors).
-T Select Targa output format. Gray-scale format is
emitted if the JPEG file is gray-scale or if -g is
specified; otherwise, colormapped format is emitted
if -q is specified; otherwise, 24-bit full-color
format is emitted.
-pnm Select PBMPLUS (PPM/PGM) output format (this is the
default format). PGM is emitted if the JPEG file is
gray-scale or if -grayscale is specified; otherwise
PPM is emitted.
-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).
At normal -Q settings it may make the image worse.
-rle Select RLE output format. (Requires URT library.)
-g Force gray-scale output even if input is color.
-targa Select Targa output format. Gray-scale format is
emitted if the JPEG file is gray-scale or if
-grayscale is specified; otherwise, colormapped format
is emitted if -colors is specified; otherwise, 24-bit
full-color format is emitted.
-q N Quantize to N colors.
Switches for advanced users:
-D Do NOT use dithering in color quantization.
-blocksmooth Perform cross-block smoothing. This is slow, quite
memory-intensive, and only seems to improve the image
at very low quality settings (-quality 10 to 20 or so).
At normal quality settings it may make things worse.
-grayscale Force gray-scale output even if JPEG file is color.
Useful for viewing on monochrome displays.
-maxmemory N Set limit for amount of memory to use in processing
large images. Value is in thousands of bytes, or
millions of bytes if "M" is attached to the number.
For example, -max 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
-nodither Do not use dithering in color quantization.
By default, Floyd-Steinberg dithering is applied when
quantizing colors, but on some images dithering may
result in objectionable "graininess". If that
happens, you can turn off dithering with -D.
happens, you can turn off dithering with -nodither.
-nodither is ignored unless you also say -colors N.
-2 Use two-pass color quantization (not yet supported).
-onepass Use one-pass instead of two-pass color quantization.
The one-pass method is faster and needs less memory,
but it produces a lower-quality image. -onepass is
ignored unless you also say -colors N. Also,
the one-pass method is always used for gray-scale
output (the two-pass method is no improvement then).
-d Enable debug printout. More -d's give more printout.
Also, version information is printed at startup.
-verbose Enable debug printout. More -v's give more printout.
or -debug Also, version information is printed at startup.
Color quantization currently uses a rather shoddy algorithm (although it's not
as 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. (See SUPPORTING SOFTWARE in the README
file.) We expect to provide a considerably better quantization algorithm in a
future release. (The same applies to colormapped RLE or Targa output, of
course.)
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.
HINTS
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, or try
to read or write an RLE file, or try to read an interlaced or bottom-up Targa
file. This will be addressed soon by replacing jvirtmem.c with something that
uses temporary files for large images.
Color GIF files are not the ideal input for JPEG; JPEG is really intended for
compressing full-color (24-bit) images. In particular, don't try to convert
cartoons, line drawings, and other images that have only a few distinct
colors. GIF works great on these, JPEG does not. If you want to convert a
GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options
to get a satisfactory conversion. -smooth 10 or so is often helpful.
Avoid running an image through a series of JPEG compression/decompression
cycles. Image quality loss will accumulate; after ten or so cycles the image
may be noticeably worse than it was after one cycle. It's best to use a
lossless format while manipulating an image, then convert to JPEG format when
you are ready to file the image away.
The -optimize option to cjpeg is worth using when you are making a "final"
version for posting or archiving. It's also a win when you are using low
quality settings to make very small JPEG files; the percentage improvement
is often a lot more than it is on larger files.
When making images to be posted on Usenet, we recommend using cjpeg's option
-restart 1. This option limits the damage done to a compressed image by
netnews transmission errors.
The default memory usage limit (-maxmemory) is set when the software is
compiled. If you get an "insufficient memory" error, try specifying a smaller
-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You
may want to recompile with a smaller default value if this happens often.
On machines that have "environment" variables, you can define the environment
variable JPEGMEM to set the default memory limit. The value is specified as
described for the -maxmemory switch. JPEGMEM overrides the default value
specified when the program was compiled, and itself is overridden by an
explicit -maxmemory switch.
On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to
use. (Extended or expanded memory is also used if available.) Most
DOS-specific versions of this software do their own memory space estimation
and do not need -maxmemory.
djpeg with two-pass color quantization requires a good deal of memory; on
MS-DOS machines it may run out of memory even with -maxmemory 0. In that case
you can still decompress, with some loss of image quality, by specifying
-onepass for one-pass quantization.
If more space is needed than will fit in the available main memory (as
determined by -maxmemory), temporary files will be used. (MS-DOS versions
will try to get extended or expanded memory first.) The temporary files are
often rather large: in typical cases they occupy three bytes per pixel, for
example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough
free disk space, leave out -optimize (for cjpeg) or specify -onepass (for
djpeg). On MS-DOS, the temporary files are created in the directory named by
the TMP or TEMP environment variable, or in the current directory if neither
of those exist. Amiga implementations put the temp files in the directory
named by JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with
adequate free space.

View File

@@ -1,9 +1,3 @@
/*
* Received from Peter Deutsch (ghost@aladdin.com)
* Fri, 26 Apr 91 10:10:10 PDT
* Small portability improvements by Tom Lane
*/
/* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved.
Distributed by Free Software Foundation, Inc.
@@ -225,13 +219,12 @@ BY ANY OTHER PARTY.
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
int
main(argc, argv)
int argc;
char *argv[];
{ FILE *in, *out;
#define bufsize 500 /* arbitrary size */
char buf[bufsize+1];
#define bufsize 5000 /* arbitrary size */
char *buf;
char *line;
switch ( argc )
{
@@ -253,6 +246,7 @@ main(argc, argv)
exit(1);
}
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
buf = malloc(bufsize);
line = buf;
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
{ switch ( test1(buf) )
@@ -262,7 +256,9 @@ main(argc, argv)
break;
case -1: /* maybe the start of a function */
line = buf + strlen(buf);
continue;
if ( line != buf + (bufsize - 1) ) /* overflow check */
continue;
/* falls through */
default: /* not a function */
fputs(buf, out);
break;
@@ -270,6 +266,7 @@ main(argc, argv)
line = buf;
}
if ( line != buf ) fputs(buf, out);
free(buf);
fclose(out);
fclose(in);
return 0;

View File

@@ -1,5 +1,5 @@
JPEG SYSTEM ARCHITECTURE 3-OCT-91
JPEG SYSTEM ARCHITECTURE 1-DEC-92
This file provides an overview of the "architecture" of the portable JPEG
@@ -13,7 +13,7 @@ to the mark. Also, it is frequently the case that several different modules
present a common interface to callers; the term "object" or "method" refers to
this common interface (see "Poor man's object-oriented programming", below).
JPEG-specific terminology follows the JPEG R9 draft:
JPEG-specific terminology follows the JPEG standard:
A "component" means a color channel, e.g., Red or Luminance.
A "sample" is a pixel component value (i.e., one number in the image data).
A "coefficient" is a frequency coefficient (a DCT transform output number).
@@ -52,8 +52,7 @@ real-time, which nobody is going to do with a pure software implementation.
There is some value in supporting the hierarchical mode, which allows for
successive frames of higher resolution. This could be of use for including
"thumbnail" representations. Also, Storm's JPEG++ files probably use the
hierarchical mode (I haven't looked). However, this appears to add a lot more
"thumbnail" representations. However, this appears to add a lot more
complexity than it is worth.
A variety of uncompressed image file formats and user interfaces must be
@@ -79,13 +78,13 @@ baggage.)
The *logical* steps needed in (non-lossless) JPEG compression are:
1. Conversion from incoming image format to a standardized internal form
(either RGB or greyscale).
(either RGB or grayscale).
2. Color space conversion (e.g., RGB to YCbCr). This is a null step for
greyscale (unless we support mapping color inputs to greyscale, which
grayscale (unless we support mapping color inputs to grayscale, which
would most easily be done here). Gamma adjustment may also be needed here.
3. Subsampling (reduction of number of samples in some color components).
3. Downsampling (reduction of number of samples in some color components).
This step operates independently on each color component.
4. MCU extraction (creation of a single sequence of 8x8 sample blocks).
@@ -133,7 +132,7 @@ C. Compression parameter selection: some parameters should be chosen
D. A memory management module to deal with small-memory machines. This must
create the illusion of virtual memory for certain large data structures
(e.g., the subsampled image or the transformed coefficients).
(e.g., the downsampled image or the transformed coefficients).
The interface to this must be defined to minimize the overhead incurred,
especially on virtual-memory machines where the module won't do much.
@@ -171,15 +170,15 @@ The *logical* steps needed in (non-lossless) JPEG decompression are:
4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8
blocks back to separate components in pixel map order).
5. (Optional) Cross-block smoothing per JPEG section 13.10 or a similar
5. (Optional) Cross-block smoothing per JPEG section K.8 or a similar
algorithm. (Steps 5-8 operate independently on each component.)
6. Inverse DCT transformation of each 8x8 block.
7. De-subsampling. At this point a pixel image of the original dimensions
7. Upsampling. At this point a pixel image of the original dimensions
has been recreated.
8. Post-subsampling smoothing. This can be combined with de-subsampling,
8. Post-upsampling smoothing. This can be combined with upsampling,
by using a convolution-like calculation to generate each output pixel
directly from one or more input pixels.
@@ -189,19 +188,23 @@ The *logical* steps needed in (non-lossless) JPEG decompression are:
sizes.
10. Color space reconversion (e.g., YCbCr to RGB). This is a null step for
greyscale. (Note that if we support mapping color JPEG to greyscale,
it could be done as part of this step.) Gamma adjustment may also be
needed here.
grayscale. (Note that mapping a color JPEG to grayscale output is most
easily done in this step.) Gamma adjustment may also be needed here.
11. Color quantization (only if a colormapped output format is requested).
NOTE: it might be better to do this on the internal color space instead of
RGB? If so, it would need to be performed one step earlier.
NOTE: it is probably preferable to perform quantization in the internal
(JPEG) colorspace rather than the output colorspace. Doing it that way,
color conversion need only be applied to the colormap entries, not to
every pixel; and quantization gets to operate in a non-gamma-corrected
space. But the internal space may not be suitable for some algorithms.
The system design is such that only the color quantizer module knows
whether color conversion happens before or after quantization.
12. Writing of the desired image format.
As before, some of these will be combined into single steps. When dealing
with a noninterleaved JPEG file, steps 2-9 will be performed once for each
scan; the resulting data will need to be buffered up so that step 10 can
scan; the resulting data will need to be buffered up so that steps 10-12 can
process all the color components together.
The same auxiliary modules are needed as before, except for compression
@@ -276,7 +279,7 @@ values should be coded as "GETJSAMPLE(value)", where the macro will be defined
as "((value)&0xFF)" on signed-char machines and "(value)" elsewhere.
With these conventions, JSAMPLE values can be assumed to be >= 0. This should
simplify correct rounding during subsampling, etc. The JPEG draft's
simplify correct rounding during downsampling, etc. The JPEG draft's
specification that sample values run from -128..127 will be accommodated by
subtracting 128 just as the sample value is copied into the source array for
the DCT step (this will be an array of signed shorts or longs). Similarly,
@@ -429,12 +432,8 @@ different instances (choose to execute different modules).
To minimize the number of object pointers that have to be passed around, it
will be easiest to have just a few big structs containing all the method
pointers. We'll actually use two such structs, one for "globally" defined
methods (applicable to the whole file or to all components of the current
scan) and one for methods applicable to a single component. There'll be one
copy of the second kind of struct for each component of the current scan.
This is necessary so that preselection of an optimal method can be done based
on component-specific information (like sampling ratios...)
pointers. We'll actually use two such structs, one for "system-dependent"
methods (memory allocation and error handling) and one for everything else.
Because of this choice, it's best not to think of an "object" as a specific
data structure. Rather, an "object" is just a group of related methods.
@@ -460,9 +459,9 @@ an interleaved scan, an MCU row consists of all the data for one horizontal
row of MCUs; this may be from one to four blocks high (eight to thirty-two
samples) depending on the sampling factors. The height and width of an MCU
row may be different in each component. (Note that the height and width of an
MCU row changes at the subsampling and de-subsampling steps. An unsubsampled
MCU row changes at the downsampling and upsampling steps. An unsubsampled
image has the same size in each component. The preceding statements apply to
the subsampled dimensions.)
the downsampled dimensions.)
For example, consider a 1024-pixel-wide image using (2h:2v)(1h:1v)(1h:1v)
subsampling. In the noninterleaved case, an MCU row of Y would contain 8x1024
@@ -503,7 +502,7 @@ specified in numbers of MCU).
For similar reasons, one MCU is also the best chunk size for the frequency
coefficient quantization and dequantization steps.
For subsampling and desubsampling, the best chunk size is to have each call
For downsampling and upsampling, the best chunk size is to have each call
transform Vk sample rows from or to Vmax sample rows (Vk = this component's
vertical sampling factor, Vmax = largest vertical sampling factor). There are
eight such chunks in each MCU row. Using a whole MCU row as the chunk size
@@ -528,7 +527,10 @@ aren't described here; see the header files. Notice that any object that
might need to allocate working storage receives an "init" and a "term" call;
"term" should be careful to free all allocated storage so that the JPEG system
can be used multiple times during a program run. (For the same reason,
depending on static initialization of variables is a no-no.)
depending on static initialization of variables is a no-no. The only
exception to the free-all-allocated-storage rule is that storage allocated for
the entire processing of an image need not be explicitly freed, since the
memory manager's free_all cleanup will free it.)
1. Input file conversion to standardized form. This provides these methods:
input_init: read the file header, report image size & component count.
@@ -576,12 +578,12 @@ depending on static initialization of variables is a no-no.)
subroutine instead of a method. Depends on whether we want to be able to
use alternative, optimized methods.)
4. Subsampling: this will be applied to one component at a time.
subsample_init: initialize (precalculate convolution factors, for
example). This will be called once per scan.
subsample: Given a sample array, reduce it to a smaller number of
samples using specified sampling factors.
subsample_term: clean up at the end of a scan.
4. Downsampling: this will be applied to one component at a time.
downsample_init: initialize (precalculate convolution factors, for
example). This will be called once per scan.
downsample: Given a sample array, reduce it to a smaller number of
samples using specified sampling factors.
downsample_term: clean up at the end of a scan.
If the current component has vertical sampling factor Vk and the largest
sampling factor is Vmax, then the input is always Vmax sample rows (whose
width is a multiple of Hmax) and the output is always Vk sample rows.
@@ -619,11 +621,11 @@ depending on static initialization of variables is a no-no.)
MCU extraction; hard to see a need for multiple instantiations here.)
8. Entropy encoding (Huffman or arithmetic).
entropy_encoder_init: prepare for one scan.
entropy_encode_init: prepare for one scan.
entropy_encode: accepts an MCU's worth of quantized coefficients,
encodes and outputs them.
entropy_encoder_term: finish up at end of a scan (dump any buffered
bytes, for example).
entropy_encode_term: finish up at end of a scan (dump any buffered
bytes, for example).
The data output by this module will be sent to the entropy_output method
provided by the pipeline controller. (It will probably be worth using
buffering to pass multiple bytes per call of the output method.) The
@@ -677,8 +679,8 @@ depending on static initialization of variables is a no-no.)
afresh for each non-Unix-like platform the compressor is ported to.
The UI is expected to supply input and output files and values for all
non-automatically-chosen compression parameters. (Hence defaults are
determined by the UI; we should probably provide helpful routines to fill
in recommended defaults.) The UI must also supply error handling
determined by the UI; we should provide helpful routines to fill in
the recommended defaults.) The UI must also supply error handling
routines and some mechanism for trace messages.
(This module hides the user interface provided --- command line,
interactive, etc. Except for error/message handling, the UI calls the
@@ -749,7 +751,8 @@ depending on static initialization of variables is a no-no.)
alloc_small: allocate an object of given size; use for any random
data that's not an image array.
free_small: release same.
alloc_medium: like alloc_small, but returns a FAR pointer.
alloc_medium: like alloc_small, but returns a FAR pointer. Use for
any object bigger than a couple kilobytes.
free_medium: release same.
alloc_small_sarray: construct an all-in-memory image sample array.
free_small_sarray: release same.
@@ -766,9 +769,13 @@ depending on static initialization of variables is a no-no.)
figure out how much space to leave unallocated.
access_big_sarray: obtain access to a specified portion of a virtual
image sample array.
access_big_barray: ditto for block (coefficient) arrays.
free_big_sarray: release a virtual sample array.
access_big_barray,
free_big_barray: ditto for block (coefficient) arrays.
free_all: release any remaining storage. This is called
before normal or error termination; the main reason
why it must exist is to ensure that any temporary
files will be deleted upon error termination.
alloc_big_arrays will be called by the pipeline controller, which does
most of the memory allocation anyway. The only reason for having separate
@@ -783,8 +790,8 @@ depending on static initialization of variables is a no-no.)
The distinction between sample and coefficient array routines is annoying,
but it has to be maintained for machines in which "char *" is represented
differently from "int *"... on byte-addressable machines some of these
methods could point to the same code.
differently from "int *". On byte-addressable machines some of these
methods could perhaps point to the same code.
The array routines will operate on only 2-D arrays (one component at a
time), since different components may require different-size arrays.
@@ -796,8 +803,8 @@ Note that any given implementation will presumably contain only one
instantiation of input file header reading, overall control, user interface,
and memory management. Thus these could be called as simple subroutines,
without bothering with an object indirection. This is essential for overall
control (which has to initialize the object structure); I'm undecided whether
to impose objectness on the other three.
control (which has to initialize the object structure); for consistency we
will impose objectness on the other three.
*** Decompression object structure ***
@@ -812,6 +819,7 @@ comments at the top of the compression object section also apply here.
after read_file_header and again after each scan;
it returns TRUE if it finds SOS, FALSE if EOI.
read_jpeg_data: fetch data for entropy decoder.
resync_to_restart: try to recover from bogus data (see below).
read_scan_trailer: finish up after one scan, prepare for another call
of read_scan_header (may be a no-op).
read_file_trailer: finish up at end of file (probably a no-op).
@@ -829,28 +837,42 @@ comments at the top of the compression object section also apply here.
opened the input file and possibly read part of the header before
read_file_header is called.)
When reading a file with a nonzero restart interval, the entropy decoder
expects to see a correct sequence of restart markers. In some cases, these
markers may be synthesized by the file-format module (a TIFF reader might
do so, for example, using tile boundary pointers to determine where the
restart intervals fall). If the incoming data is corrupted, the entropy
decoder will read as far as the next JPEG marker, which may or may not be
the expected next restart marker. If it isn't, resync_to_restart is called
to try to locate a good place to resume reading. We make this heuristic a
file-format-dependent operation since some file formats may have special
info that's not available to the entropy decoder (again, TIFF is an
example). Note that resync_to_restart is NOT called at the end of a scan;
it is read_scan_trailer's responsibility to resync there.
NOTE: for JFIF/raw-JPEG file format, the read_jpeg_data routine is actually
supplied by the user interface; the jrdjfif module uses read_jpeg_data
internally to scan the input stream. This makes it possible for the user
interface module to single-handedly implement special applications like
reading from a non-stdio source. For JPEG-in-TIFF format, the need for
random access will make it impossible for this to work; hence the TIFF
header module will probably override the UI read_jpeg_data routine.
header module will override the UI-supplied read_jpeg_data routine.
Non-stdio input from a TIFF file will require extensive surgery to the TIFF
header module, if indeed it is practical at all.
2. Entropy (Huffman or arithmetic) decoding of the coefficient sequence.
entropy_decoder_init: prepare for one scan.
entropy_decode_init: prepare for one scan.
entropy_decode: decodes and returns an MCU's worth of quantized
coefficients per call.
entropy_decoder_term: finish up after a scan (may be a no-op).
entropy_decode_term: finish up after a scan (may be a no-op).
This will read raw data by calling the read_jpeg_data method (I don't see
any reason to provide a further level of indirection).
(This hides which entropy encoding method is in use.)
3. Quantization descaling and zigzag reordering of the elements in each 8x8
block. (This can probably be a plain subroutine called once per block;
hard to see a need for multiple instantiations here.)
block. This will be folded into entropy_decode for efficiency reasons:
many of the coefficients are zeroes, and this can be exploited most easily
within entropy_decode since the encoding explicitly skips zeroes.
4. MCU disassembly (conversion of a possibly interleaved sequence of 8x8
blocks back to separate components in pixel map order).
@@ -860,11 +882,11 @@ comments at the top of the compression object section also apply here.
coefficient image array.
disassemble_term: clean up at the end of a scan.
Probably this should be called once per MCU row and should call the
preceding two objects repeatedly to obtain the row's data. The output is
entropy decoder repeatedly to obtain the row's data. The output is
always a multiple of an MCU's dimensions.
(An object on the grounds that multiple instantiations might be useful.)
5. Cross-block smoothing per JPEG section 13.10 or a similar algorithm.
5. Cross-block smoothing per JPEG section K.8 or a similar algorithm.
smooth_coefficients: Given three block rows' worth of a single
component, emit a smoothed equivalent of the
middle row. The "above" and "below" pointers
@@ -874,17 +896,22 @@ comments at the top of the compression object section also apply here.
extra memory is needed to buffer the additional block rows.
(This object hides the details of the smoothing algorithm.)
6. Inverse DCT transformation of each 8x8 block. (This can be a plain
subroutine processing one block per call.)
6. Inverse DCT transformation of each 8x8 block.
reverse_DCT: given an MCU row's worth of blocks, perform inverse
DCT on each block and output the results into an array
of samples.
We put this method into the jdmcu module for symmetry with the division of
labor in compression. Note that the actual IDCT code is a separate source
file.
7. De-subsampling and smoothing: this will be applied to one component at a
7. Upsampling and smoothing: this will be applied to one component at a
time. Note that cross-pixel smoothing, which was a separate step in the
prototype code, will now be performed simultaneously with expansion.
unsubsample_init: initialize (precalculate convolution factors, for
example). This will be called once per scan.
unsubsample: Given a sample array, enlarge it by specified sampling
factors.
unsubsample_term: clean up at the end of a scan.
upsample_init: initialize (precalculate convolution factors, for
example). This will be called once per scan.
upsample: Given a sample array, enlarge it by specified sampling
factors.
upsample_term: clean up at the end of a scan.
If the current component has vertical sampling factor Vk and the largest
sampling factor is Vmax, then the input is always Vk sample rows (whose
width is a multiple of Hk) and the output is always Vmax sample rows.
@@ -905,9 +932,13 @@ comments at the top of the compression object section also apply here.
output are image arrays of same size but possibly
different numbers of components.
colorout_term: cleanup (probably a no-op except for memory dealloc).
In practice will always be given an MCU row's worth of pixel rows, except
In practice will usually be given an MCU row's worth of pixel rows, except
at the bottom where a smaller number of rows may be left over. Note that
this object works on all the components at once.
When quantizing colors, color_convert may be applied to the colormap
instead of actual pixel data. color_convert is called by the color
quantizer in this case; the pipeline controller calls color_convert
directly only when not quantizing.
(Hides all knowledge of color space semantics and conversion. Remaining
modules only need to know the number of JPEG and output components.)
@@ -927,33 +958,44 @@ comments at the top of the compression object section also apply here.
"big" sample image, output is via put_color_map and
put_pixel_rows. (Used only in 2-pass quantization.)
color_quant_term: cleanup (probably a no-op except for memory dealloc).
The input to the color quantizer is always in the unconverted colorspace;
its output colormap must be in the converted colorspace. The quantizer
has the choice of which space to work in internally. It must call
color_convert either on its input data or on the colormap it sends to the
output module.
For one-pass quantization the image is simply processed by color_quantize,
a few rows at a time. For two-pass quantization, the pipeline controller
accumulates the output of color_convert into a "big" sample image. The
accumulates the output of steps 1-8 into a "big" sample image. The
color_quant_prescan method is invoked during this process so that the
quantizer can accumulate statistics. At the end of the image,
color_quant_doit is called; it must rescan the "big" image and pass
converted data to the output module. Additional scans of the image could
be made before the output pass is done (in fact, prescan could be a no-op).
quantizer can accumulate statistics. (If the input file has multiple
scans, the prescan may be done during the final scan or as a separate
pass.) At the end of the image, color_quant_doit is called; it must
create and output a colormap, then rescan the "big" image and pass mapped
data to the output module. Additional scans of the image could be made
before the output pass is done (in fact, prescan could be a no-op).
As with entropy parameter optimization, the pipeline controller actually
passes an iterator function rather than direct access to the big image.
NOTE: it might be better to do this on the internal color space instead of
RGB? If so, it would need to be performed one step earlier.
(Hides color quantization algorithm.)
11. Writing of the desired image format.
output_init: produce the file header given data from read_file_header.
put_color_map: output colormap, if any (called by color quantizer).
If used, must be called before any pixel data is output.
put_pixel_rows: output image data in desired format.
output_term: finish up at the end.
The actual timing of I/O may differ from that suggested by the routine
names; for instance, writing of the file header may be delayed until
put_color_map time if the actual number of colors is needed in the header.
Also, the colormap is available to put_pixel_rows and output_term as well
as put_color_map.
Note that whether colormapping is needed will be determined by the user
interface object prior to method selection. In implementations that
support multiple output formats, the actual output format will also be
determined by the user interface.
(Hides format of output image and mechanism used to write it. Note that
several other objects know the color model used by the output format. The
actual mechanism for writing the file is private to this object and the
user interface.)
several other objects know the color model used by the output format.
The actual mechanism for writing the file is private to this object and
the user interface.)
12. Pipeline control. This object will provide the "main loop" that invokes
all the pipeline objects. Note that we will need several different main
@@ -985,9 +1027,6 @@ comments at the top of the compression object section also apply here.
application program", i.e., that which invokes the JPEG decompressor.
The UI is expected to supply input and output files and values for all
operational parameters. The UI must also supply error handling routines.
At the moment I can't think of any nonfatal errors the JPEG code is likely
to report, so a single report-this-error-and-exit method should be
sufficient.
(This module hides the user interface provided --- command line,
interactive, etc. Except for error handling, the UI calls the portable
JPEG code, not the other way around.)
@@ -1050,9 +1089,52 @@ needs a lot smaller temp file than is implied by the maximum-height method.
For this approach we'd simply treat DNL as a no-op in the decompressor (at
most, check that it matches the SOF image height).
We will not worry about making the compressor capable of outputting DNL. Note
that something similar to the first scheme above could be applied if anyone
ever wants to make that work.
We will not worry about making the compressor capable of outputting DNL.
Something similar to the first scheme above could be applied if anyone ever
wants to make that work.
*** Memory manager internal structure ***
The memory manager contains the most potential for system dependencies.
To isolate system dependencies as much as possible, we have broken the
memory manager into two parts. There is a reasonably system-independent
"front end" (jmemmgr.c) and a "back end" that contains only the code
likely to change across systems. All of the memory management methods
outlined above are implemented by the front end. The back end provides
the following routines for use by the front end (none of these routines
are known to the rest of the JPEG code):
jmem_init, jmem_term system-dependent initialization/shutdown
jget_small, jfree_small interface to malloc and free library routines
jget_large, jfree_large interface to FAR malloc/free in MS-DOS machines;
otherwise same as jget_small/jfree_small
jmem_available estimate available memory
jopen_backing_store create a backing-store object
read_backing_store, manipulate a backing store object
write_backing_store,
close_backing_store
On some systems there will be more than one type of backing-store object
(specifically, in MS-DOS a backing store file might be an area of extended
memory as well as a disk file). jopen_backing_store is responsible for
choosing how to implement a given object. The read/write/close routines
are method pointers in the structure that describes a given object; this
lets them be different for different object types.
It may be necessary to ensure that backing store objects are explicitly
released upon abnormal program termination. (For example, MS-DOS won't free
extended memory by itself.) To support this, we will expect the main program
or surrounding application to arrange to call the free_all method upon
abnormal termination; this may require a SIGINT signal handler, for instance.
(We don't want to have the system-dependent module install its own signal
handler, because that would pre-empt the surrounding application's ability
to control signal handling.)
*** Notes for MS-DOS implementors ***
@@ -1067,10 +1149,10 @@ significant speed penalty.
When integrating the JPEG code into a larger application, it's a good idea to
stay with a small-data-space model if possible. An 8K stack is much more than
sufficient for the JPEG code, and its static data requirements are less than
1K. When executed, it will typically malloc about 10K worth of near heap
1K. When executed, it will typically malloc about 10K-20K worth of near heap
space (and lots of far heap, but that doesn't count in this calculation).
This figure will vary depending on image size and other factors, but figuring
20K should be more than sufficient. Thus you have about 35K available for
30K should be more than sufficient. Thus you have about 25K available for
other modules' static data and near heap requirements before you need to go to
a larger memory model. The C library's static data will account for several K
of this, but that still leaves a good deal for your needs. (If you are tight
@@ -1084,6 +1166,13 @@ JPEG code is stand-alone. (The LZW tables in jrdgif/jwrgif are examples.)
To make an optimal implementation, you might want to move these structures
back to near heap if you know there is sufficient space.
FAR data space may also be a tight resource when you are dealing with large
images. The most memory-intensive case is decompression with two-pass color
quantization. This requires a 128Kb color histogram plus strip buffers
amounting to about 150 bytes per column for typical sampling ratios (eg, about
96000 bytes for a 640-pixel-wide image). You may not be able to process wide
images if you have large data structures of your own.
*** Potential optimizations ***

242
cjpeg.1
View File

@@ -1,13 +1,46 @@
.TH CJPEG 1 "11 December 1991"
.TH CJPEG 1 "4 November 1992"
.SH NAME
cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS
.B cjpeg
[
.BI \-Q " quality"
.BI \-quality " N"
]
[
.B \-oTIad
.B \-grayscale
]
[
.B \-optimize
]
[
.B \-targa
]
[
.BI \-maxmemory " N"
]
[
.BI \-restart " N"
]
[
.BI \-smooth " N"
]
[
.B \-verbose
]
[
.B \-debug
]
[
.B \-arithmetic
]
[
.B \-nointerleave
]
[
.BI \-qtables " file"
]
[
.BI \-sample " HxV[,...]"
]
[
.I filename
@@ -18,101 +51,196 @@ cjpeg \- compress an image file to a JPEG file
.B cjpeg
compresses the named image file, or the standard input if no file is
named, and produces a JPEG/JFIF file on the standard output.
The currently supported image file formats are: PPM (PBMPLUS color
The currently supported input file formats are: PPM (PBMPLUS color
format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster
Toolkit format). (RLE is supported only if the URT library is available.)
.SH OPTIONS
All switch names may be abbreviated; for example,
.B \-grayscale
may be written
.B \-gray
or
.BR \-gr .
Most of the "basic" switches can be abbreviated to as little as one letter.
Upper and lower case are equivalent (thus
.B \-GIF
is the same as
.BR \-gif ).
British spellings are also accepted (e.g.,
.BR \-greyscale ),
though for brevity these are not mentioned below.
.PP
The basic switches are:
.TP
.BI \-Q " quality"
.BI \-quality " N"
Scale quantization tables to adjust image quality. Quality is 0 (worst) to
100 (best); default is 75. (See below for more info.)
.TP
.B \-o
.B \-grayscale
Create monochrome JPEG file from color input. Be sure to use this switch when
compressing a grayscale GIF file, because
.B cjpeg
isn't bright enough to notice whether a GIF file uses only shades of gray.
By saying
.BR \-grayscale ,
you'll get a smaller JPEG file that takes less time to process.
.TP
.B \-optimize
Perform optimization of entropy encoding parameters. Without this, default
encoding parameters are used.
.B \-o
.B \-optimize
usually makes the JPEG file a little smaller, but
.B cjpeg
runs much slower. Image quality and speed of decompression are unaffected by
.BR \-o .
runs somewhat slower and needs much more memory. Image quality and speed of
decompression are unaffected by
.BR \-optimize .
.TP
.B \-T
.B \-targa
Input file is Targa format. Targa files that contain an "identification"
field will not be automatically recognized by
.BR cjpeg ;
for such files you must specify
.B \-T
to force
.B \-targa
to make
.B cjpeg
to treat the input as Targa format.
.TP
.B \-I
Generate noninterleaved JPEG file (not yet supported).
.TP
.B \-a
Use arithmetic coding rather than Huffman coding (not currently
supported for legal reasons).
.TP
.B \-d
Enable debug printout. More
.BR \-d 's
give more output. Also, version information is printed at startup.
treat the input as Targa format.
.PP
The
.B \-Q
.B \-quality
switch lets you trade off compressed file size against quality of the
reconstructed image: the higher the
.B \-Q
setting, the larger the JPEG file, and the closer the output image will be to
the original input. Normally you want to use the lowest
.B \-Q
setting (smallest file) that decompresses into something visually
indistinguishable from the original image. For this purpose the
.B \-Q
setting should be between 50 and 95; the default of 75 is often about right.
If you see defects at
.B \-Q
reconstructed image: the higher the quality setting, the larger the JPEG file,
and the closer the output image will be to the original input. Normally you
want to use the lowest quality setting (smallest file) that decompresses into
something visually indistinguishable from the original image. For this
purpose the quality setting should be between 50 and 95; the default of 75 is
often about right. If you see defects at
.B \-quality
75, then go up 5 or 10 counts at a time until you are happy with the output
image. (The optimal setting will vary from one image to another.)
.PP
.B \-Q
.B \-quality
100 will generate a quantization table of all 1's, eliminating loss in the
quantization step (but there is still information loss in subsampling, as well
as roundoff error). This setting is mainly of interest for experimental
purposes.
.B \-Q
values above about 95 are
purposes. Quality values above about 95 are
.B not
recommended for normal use; the compressed file size goes up dramatically for
hardly any gain in output image quality.
.PP
In the other direction,
.B \-Q
values below 50 will produce very small files of low image quality. Settings
around 5 to 10 might be useful in preparing an index of a large image library,
for example. Try
.B \-Q
2 (or so) for some amusing Cubist effects. (Note:
.B \-Q
In the other direction, quality values below 50 will produce very small files
of low image quality. Settings around 5 to 10 might be useful in preparing an
index of a large image library, for example. Try
.B \-quality
2 (or so) for some amusing Cubist effects. (Note: quality
values below about 25 generate 2-byte quantization tables, which are
considered optional in the JPEG standard.
considered optional in the JPEG standard.
.B cjpeg
emits a warning message when you give such a
.B \-Q
value, because some commercial JPEG programs may be unable to decode the
resulting file.)
emits a warning message when you give such a quality value, because some
commercial JPEG programs may be unable to decode the resulting file.)
.PP
Switches for advanced users:
.TP
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.TP
.BI \-restart " N"
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
attached to the number.
.B \-restart 0
(the default) means no restart markers.
.TP
.BI \-smooth " N"
Smooth the input image to eliminate dithering noise. N, ranging from 1 to
100, indicates the strength of smoothing. 0 (the default) means no smoothing.
.TP
.B \-verbose
Enable debug printout. More
.BR \-v 's
give more output. Also, version information is printed at startup.
.TP
.B \-debug
Same as
.BR \-verbose .
.PP
The
.B \-restart
option inserts extra markers that allow a JPEG decoder to resynchronize after
a transmission error. Without restart markers, any damage to a compressed
file will usually ruin the image from the point of the error to the end of the
image; with restart markers, the damage is usually confined to the portion of
the image up to the next restart marker. Of course, the restart markers
occupy extra space. We recommend
.B \-restart 1
for images that will be transmitted across unreliable networks such as Usenet.
.PP
The
.B \-smooth
option filters the input to eliminate fine-scale noise. This is often useful
when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50
gets rid of dithering patterns in the input file, resulting in a smaller JPEG
file and a better-looking image. Too large a smoothing factor will visibly
blur the image, however.
.PP
Switches for wizards:
.TP
.B \-arithmetic
Use arithmetic coding rather than Huffman coding. (Not currently
supported for legal reasons.)
.TP
.B \-nointerleave
Generate noninterleaved JPEG file (not yet supported).
.TP
.BI \-qtables " file"
Use the quantization tables given in the specified file. The file should
contain one to four tables (64 values each) as plain text. Comments preceded
by '#' may be included in the file. The tables are implicitly numbered
0,1,etc. If
.B \-quality
N is also specified, the values in the file are scaled according to
.BR cjpeg 's
quality scaling curve.
.TP
.BI \-sample " HxV[,...]"
Set JPEG sampling factors. If you specify fewer H/V pairs than there are
components, the remaining components are set to 1x1 sampling. The default
setting is equivalent to \fB\-sample 2x2\fR.
.PP
The "wizard" switches are intended for experimentation with JPEG. If you
don't know what you are doing, \fBdon't use them\fR. You can easily produce
files with worse image quality and/or poorer compression than you'll get from
the default settings. Furthermore, these switches should not be used when
making files intended for general use, because not all JPEG implementations
will support unusual JPEG parameter settings.
.SH EXAMPLES
.LP
This example compresses the PPM file foo.ppm with a quality factor of
60 and saves the output as foo.jpg:
.IP
.B cjpeg \-Q
.B cjpeg \-quality
.I 60 foo.ppm
.B >
.I foo.jpg
.SH ENVIRONMENT
.TP
.B JPEGMEM
If this environment variable is set, its value is the default memory limit.
The value is specified as described for the
.B \-maxmemory
switch.
.B JPEGMEM
overrides the default value specified when the program was compiled, and
itself is overridden by an explicit
.BR \-maxmemory .
.SH SEE ALSO
.BR djpeg (1)
.br
.BR ppm (5),
.BR pgm (5)
.br
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
.SH AUTHOR
@@ -123,8 +251,8 @@ Arithmetic coding and interleaved output not yet supported.
Not all variants of Targa file format are supported.
.PP
The
.B -T
.B -targa
switch is not a bug, it's a feature. (It would be a bug if the Targa format
designers had not been clueless.)
.PP
Not as fast as we'd like.
Still not as fast as we'd like.

View File

@@ -1,7 +1,7 @@
/*
* config.c
* ckconfig.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*/
@@ -121,12 +121,18 @@ int testfunction (int arg1, int * arg2); /* check prototypes */
struct methods_struct { /* check method-pointer declarations */
int (*error_exit) (char *msgtext);
int (*trace_message) (char *msgtext);
int (*another_method) (void);
};
int testfunction (int arg1, int * arg2) /* check definitions */
{
return arg2[arg1];
}
int testfunction1 (void) /* check void arg list */
{
return 0;
}
#endif
@@ -212,8 +218,9 @@ int new_change ()
printf("\nMost of the changes recommended by this program can be made either\n");
printf("by editing jconfig.h, or by adding -Dsymbol switches to the CFLAGS\n");
printf("line in your Makefile. (Some PC compilers expect /Dsymbol instead.)\n");
printf("The CFLAGS method is simpler, but if your system doesn't use makefiles,\n");
printf("or if your compiler doesn't support -D, then you must change jconfig.h.\n");
printf("The CFLAGS method is simpler, but if your compiler doesn't support -D,\n");
printf("then you must change jconfig.h. Also, it's best to change jconfig.h\n");
printf("if you plan to use the JPEG software as a library for other programs.\n");
any_changes = 1;
}
printf("\n"); /* blank line before each problem report */
@@ -278,7 +285,7 @@ int main (argc, argv)
/* Check whether we have all the ANSI features, */
/* and whether this agrees with __STDC__ being predefined. */
#ifdef __STDC__
#define MY__STDC__ /* ANSI compilers won't allow redefining __STDC__ */
#define HAVE_STDC /* ANSI compilers won't allow redefining __STDC__ */
#endif
#ifdef HAVE_ANSI_DEFINITIONS
@@ -292,28 +299,23 @@ int main (argc, argv)
#endif
#ifdef HAVE_ALL_ANSI_FEATURES
#ifndef MY__STDC__
#ifndef HAVE_STDC
new_change();
printf("Your compiler doesn't claim to be ANSI-compliant, but it is close enough\n");
printf("for me. Either add -D__STDC__ to CFLAGS, or add #define __STDC__ at the\n");
printf("beginning of jinclude.h (NOT jconfig.h).\n");
printf("Some compilers will not let you do this: they will complain that __STDC__\n");
printf("is a reserved name. In that case you have a compiler that really is ANSI,\n");
printf("but you have to give it a special switch (often -ansi) to make it so.\n");
printf("Check your compiler documentation and add the proper switch to CFLAGS.\n");
#define MY__STDC__
printf("for me. Either add -DHAVE_STDC to CFLAGS, or add #define HAVE_STDC at the\n");
printf("beginning of jconfig.h.\n");
#define HAVE_STDC
#endif
#else /* !HAVE_ALL_ANSI_FEATURES */
#ifdef MY__STDC__
#ifdef HAVE_STDC
new_change();
printf("Your compiler claims to be ANSI-compliant, but it is lying!\n");
printf("Either add -U__STDC__ to CFLAGS, or add #undef __STDC__\n");
printf("at the beginning of jinclude.h (NOT jconfig.h).\n");
#undef MY__STDC__
printf("Delete the line #define HAVE_STDC near the beginning of jconfig.h.\n");
#undef HAVE_STDC
#endif
#endif /* HAVE_ALL_ANSI_FEATURES */
#ifndef MY__STDC__
#ifndef HAVE_STDC
#ifdef HAVE_ANSI_DEFINITIONS
new_change();
@@ -326,31 +328,30 @@ int main (argc, argv)
#ifdef HAVE_UNSIGNED_SHORT
new_change();
printf("You should add -DHAVE_UNSIGNED_CHAR and -DHAVE_UNSIGNED_SHORT\n");
printf("to CFLAGS, or else take out the #ifdef __STDC__/#endif lines\n");
printf("to CFLAGS, or else take out the #ifdef HAVE_STDC/#endif lines\n");
printf("surrounding #define HAVE_UNSIGNED_CHAR and #define HAVE_UNSIGNED_SHORT\n");
printf("in jconfig.h.\n");
#else /* only unsigned char */
new_change();
printf("You should add -DHAVE_UNSIGNED_CHAR to CFLAGS,\n");
printf("or else move #define HAVE_UNSIGNED_CHAR outside the\n");
printf("#ifdef __STDC__/#endif lines surrounding it in jconfig.h.\n");
printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n");
#endif
#else /* !HAVE_UNSIGNED_CHAR */
#ifdef HAVE_UNSIGNED_SHORT
new_change();
printf("You should add -DHAVE_UNSIGNED_SHORT to CFLAGS,\n");
printf("or else move #define HAVE_UNSIGNED_SHORT outside the\n");
printf("#ifdef __STDC__/#endif lines surrounding it in jconfig.h.\n");
printf("#ifdef HAVE_STDC/#endif lines surrounding it in jconfig.h.\n");
#endif
#endif /* HAVE_UNSIGNED_CHAR */
#ifdef HAVE_CONST
new_change();
printf("You can delete the #define const line from jconfig.h.\n");
printf("(But things should still work if you don't.)\n");
printf("You should delete the #define const line from jconfig.h.\n");
#endif
#endif /* MY__STDC__ */
#endif /* HAVE_STDC */
test_char_sign((int) signed_char_check);
@@ -365,13 +366,13 @@ int main (argc, argv)
#endif
#ifdef INCLUDES_ARE_ANSI
#ifndef MY__STDC__
#ifndef __STDC__
new_change();
printf("You should add -DINCLUDES_ARE_ANSI to CFLAGS, or else add\n");
printf("#define INCLUDES_ARE_ANSI at the beginning of jinclude.h (NOT jconfig.h).\n");
#endif
#else /* !INCLUDES_ARE_ANSI */
#ifdef MY__STDC__
#ifdef __STDC__
new_change();
printf("You should add -DNONANSI_INCLUDES to CFLAGS, or else add\n");
printf("#define NONANSI_INCLUDES at the beginning of jinclude.h (NOT jconfig.h).\n");

195
djpeg.1
View File

@@ -1,13 +1,43 @@
.TH DJPEG 1 "11 December 1991"
.TH DJPEG 1 "17 February 1993"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
.B djpeg
[
.B \-GPRTbgD2d
.BI \-colors " N"
]
[
.BI \-q " N"
.B \-gif
]
[
.B \-pnm
]
[
.B \-rle
]
[
.B \-targa
]
[
.B \-blocksmooth
]
[
.B \-grayscale
]
[
.BI \-maxmemory " N"
]
[
.B \-nodither
]
[
.B \-onepass
]
[
.B \-verbose
]
[
.B \-debug
]
[
.I filename
@@ -17,98 +47,141 @@ djpeg \- decompress a JPEG file to an image file
.LP
.B djpeg
decompresses the named JPEG file, or the standard input if no file is named,
and produces an image file on the standard output. PPM, GIF, Targa, or RLE
output format can be selected. (RLE is supported only if the URT library is
available.)
.LP
The color quantization algorithm is currently shoddy. Because of this, the
GIF output mode is not recommended in the current release, except for
gray-scale output (obtained with
.BR \-g ).
and produces an image file on the standard output. PBMPLUS (PPM/PGM), GIF,
Targa, or RLE (Utah Raster Toolkit) output format can be selected. (RLE is
supported only if the URT library is available.)
.SH OPTIONS
All switch names may be abbreviated; for example,
.B \-grayscale
may be written
.B \-gray
or
.BR \-gr .
Most of the "basic" switches can be abbreviated to as little as one letter.
Upper and lower case are equivalent (thus
.B \-GIF
is the same as
.BR \-gif ).
British spellings are also accepted (e.g.,
.BR \-greyscale ),
though for brevity these are not mentioned below.
.PP
The basic switches are:
.TP
.B \-G
Select GIF output format (implies
.BR \-q ,
with default of 256 colors).
Currently the color quantization uses a shoddy algorithm and external
quantization (e.g.
.IR ppmquant ,
.IR rlequant )
is recommended before conversion to GIF format.
.BI \-colors " N"
Reduce image to at most N colors. This reduces the number of colors used in
the output image, so that it can be displayed on a colormapped display or
stored in a colormapped file format. For example, if you have an 8-bit
display, you'd need to reduce to 256 or fewer colors.
.TP
.B \-P
Select PPM or PGM output format (this is the default). PGM is emitted if the
JPEG file is gray-scale or if
.B \-g
is specified.
.BI \-quantize " N"
Same as
.BR \-colors .
.B \-colors
is the recommended name,
.B \-quantize
is provided only for backwards compatibility.
.TP
.B \-R
Select RLE output format. Requires URT library.
.B \-gif
Select GIF output format. Since GIF does not support more than 256 colors,
.B \-colors 256
is assumed (unless you specify a smaller number of colors).
.TP
.B \-T
.B \-pnm
Select PBMPLUS (PPM/PGM) output format (this is the default format).
PGM is emitted if the JPEG file is gray-scale or if
.B \-grayscale
is specified; otherwise PPM is emitted.
.TP
.B \-rle
Select RLE output format. (Requires URT library.)
.TP
.B \-targa
Select Targa output format. Gray-scale format is emitted if the JPEG file is
gray-scale or if
.B \-g
.B \-grayscale
is specified; otherwise, colormapped format is emitted if
.B \-q
.B \-colors
is specified; otherwise, 24-bit full-color format is emitted.
.PP
Switches for advanced users:
.TP
.B \-b
Perform cross-block smoothing. This is quite memory-intensive and only seems
to improve the image at low quality settings (\fB\-Q\fR 10 to 20 or so).
At normal
.B \-Q
settings it may make the image worse.
.B \-blocksmooth
Perform cross-block smoothing. This is slow, quite memory-intensive, and only
seems to improve the image at very low quality settings (\fB\-quality\fR 10 to
20 or so). At normal quality settings it may make the image worse.
.TP
.B \-g
Force gray-scale output even if input is color.
.B \-grayscale
Force gray-scale output even if JPEG file is color.
Useful for viewing on monochrome displays.
.TP
.BI \-q " N"
Quantize to N colors.
.BI \-maxmemory " N"
Set limit for amount of memory to use in processing large images. Value is
in thousands of bytes, or millions of bytes if "M" is attached to the
number. For example,
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.TP
.B \-D
.B \-nodither
Do not use dithering in color quantization. By default, Floyd-Steinberg
dithering is applied when quantizing colors, but on some images dithering may
result in objectionable "graininess". If that happens, you can turn off
dithering with
.BR \-D .
.BR \-nodither .
.B \-nodither
is ignored unless you also say
.B \-colors
.IR N .
.TP
.B \-2
Use two-pass color quantization (not yet supported).
.B \-onepass
Use one-pass instead of two-pass color quantization. The one-pass method is
faster and needs less memory, but it produces a lower-quality image.
.B \-onepass
is ignored unless you also say
.B \-colors
.IR N .
Also, the one-pass method is always used for gray-scale output (the two-pass
method is no improvement then).
.TP
.B \-d
.B \-verbose
Enable debug printout. More
.BR \-d 's
.BR \-v 's
give more output. Also, version information is printed at startup.
.TP
.B \-debug
Same as
.BR \-verbose .
.SH EXAMPLES
.LP
This example decompresses the JPEG file foo.jpg and saves the output
as a gray-scale image in foo.pgm:
This example decompresses the JPEG file foo.jpg, automatically quantizes to
256 colors, and saves the output in GIF format in foo.gif:
.IP
.B djpeg \-g
.B djpeg \-gif
.I foo.jpg
.B >
.I foo.pgm
.I foo.gif
.SH ENVIRONMENT
.TP
.B JPEGMEM
If this environment variable is set, its value is the default memory limit.
The value is specified as described for the
.B \-maxmemory
switch.
.B JPEGMEM
overrides the default value specified when the program was compiled, and
itself is overridden by an explicit
.BR \-maxmemory .
.SH SEE ALSO
.BR cjpeg (1)
.br
.BR ppmquant (1)
[From the PBMplus distribution]
.br
.BR rlequant (1)
[From the Utah Raster Toolkit distribution]
.BR ppm (5),
.BR pgm (5)
.br
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
.SH AUTHOR
Independent JPEG Group
.SH BUGS
.B djpeg
currently uses a shoddy color quantization algorithm. This leads to
poor GIF file output. Two-pass color quantization is not yet
supported.
.PP
Arithmetic coding is not supported for legal reasons.
.PP
Not as fast as we'd like.
Still not as fast as we'd like.

286
egetopt.c
View File

@@ -1,286 +0,0 @@
/*
* 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
*
* Modified for use in free JPEG code:
*
* Ed Hanway
* UUCP: uunet!sisd!jeh
*
* October, 1991
*/
/* The original egetopt.c was written not to need stdio.h.
* For the JPEG code this is an unnecessary and unportable assumption.
* Also, we make all the variables and routines "static" to avoid
* possible conflicts with a system-library version of getopt.
*
* In the JPEG code, this file is compiled by #including it in jcmain.c
* or jdmain.c. Since ANSI2KNR does not process include files, we can't
* rely on it to convert function definitions to K&R style. Hence we
* provide both styles of function header with an explicit #ifdef PROTO (ick).
*/
#define GVAR static /* make empty to export these variables */
/*
* 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 EMSG ""
#define START "-"
/*
* Here are all the pertinent global variables.
*/
GVAR int opterr = 1; /* if true, output error message */
GVAR int optind = 1; /* index into parent argv vector */
GVAR int optopt; /* character checked for validity */
GVAR int optbad = BADCH; /* character returned on error */
GVAR int optchar = 0; /* character that begins returned option */
GVAR int optneed = NEEDSEP; /* flag for mandatory argument */
GVAR int optmaybe = MAYBESEP; /* flag for optional argument */
GVAR const char *optarg; /* argument associated with option */
GVAR const char *optstart = START; /* list of characters that start options */
/*
* Macros.
*/
/*
* Conditionally print out an error message and return (depends on the
* setting of 'opterr').
*/
#define TELL(S) { \
if (opterr) \
fprintf(stderr, "%s%s%c\n", *nargv, (S), optopt); \
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.
*/
#ifdef PROTO
LOCAL const char *
_sindex (const char *string, int ch)
#else
LOCAL const char *
_sindex (string, ch)
const char *string;
int ch;
#endif
{
if (string != NULL) {
for (; *string != '\0'; ++string) {
if (*string == (char)ch) {
return (string);
}
}
}
return (NULL);
}
/*
* Here it is:
*/
#ifdef PROTO
LOCAL int
egetopt (int nargc, char **nargv, const char *ostr)
#else
LOCAL int
egetopt (nargc, nargv, ostr)
int nargc;
char **nargv;
const char *ostr;
#endif
{
static const char *place = EMSG; /* option letter processing */
register const char *oli; /* option letter list index */
register const 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);
}

631
example.c Normal file
View File

@@ -0,0 +1,631 @@
/*
* example.c
*
* This file is not actually part of the JPEG software. Rather, it provides
* a skeleton that may be useful for constructing applications that use the
* JPEG software as subroutines. This code will NOT do anything useful as is.
*
* This file illustrates how to use the JPEG code as a subroutine library
* to read or write JPEG image files. We assume here that you are not
* merely interested in converting the image to yet another image file format
* (if you are, you should be adding another I/O module to cjpeg/djpeg, not
* constructing a new application). Instead, we show how to pass the
* decompressed image data into or out of routines that you provide. For
* example, a viewer program might use the JPEG decompressor together with
* routines that write the decompressed image directly to a display.
*
* We present these routines in the same coding style used in the JPEG code
* (ANSI function definitions, etc); but you are of course free to code your
* routines in a different style if you prefer.
*/
/*
* Include file for declaring JPEG data structures.
* This file also includes some system headers like <stdio.h>;
* if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
*/
#include "jinclude.h"
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
* the second part of the example.
*/
#include <setjmp.h>
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
/* This half of the example shows how to feed data into the JPEG compressor.
* We present a minimal version that does not worry about refinements such
* as error recovery (the JPEG code will just exit() if it gets an error).
*/
/*
* To supply the image data for compression, you must define three routines
* input_init, get_input_row, and input_term. These routines will be called
* from the JPEG compressor via function pointer values that you store in the
* cinfo data structure; hence they need not be globally visible and the exact
* names don't matter. (In fact, the "METHODDEF" macro expands to "static" if
* you use the unmodified JPEG include files.)
*
* The input file reading modules (jrdppm.c, jrdgif.c, jrdtarga.c, etc) may be
* useful examples of what these routines should actually do, although each of
* them is encrusted with a lot of specialized code for its own file format.
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
/* Initialize for input; return image size and component data. */
{
/* This routine must return five pieces of information about the incoming
* image, and must do any setup needed for the get_input_row routine.
* The image information is returned in fields of the cinfo struct.
* (If you don't care about modularity, you could initialize these fields
* in the main JPEG calling routine, and make this routine be a no-op.)
* We show some example values here.
*/
cinfo->image_width = 640; /* width in pixels */
cinfo->image_height = 480; /* height in pixels */
/* JPEG views an image as being a rectangular array of pixels, with each
* pixel having the same number of "component" values (color channels).
* You must specify how many components there are and the colorspace
* interpretation of the components. Most applications will use RGB data or
* grayscale data. If you want to use something else, you'll need to study
* and perhaps modify jcdeflts.c, jccolor.c, and jdcolor.c.
*/
cinfo->input_components = 3; /* or 1 for grayscale */
cinfo->in_color_space = CS_RGB; /* or CS_GRAYSCALE for grayscale */
cinfo->data_precision = 8; /* bits per pixel component value */
/* In the current JPEG software, data_precision must be set equal to
* BITS_IN_JSAMPLE, which is 8 unless you twiddle jconfig.h. Future
* versions might allow you to say either 8 or 12 if compiled with
* 12-bit JSAMPLEs, or up to 16 in lossless mode. In any case,
* it is up to you to scale incoming pixel values to the range
* 0 .. (1<<data_precision)-1.
* If your image data format is fixed at a byte per component,
* then saying "8" is probably the best long-term solution.
*/
}
/*
* This function is called repeatedly and must supply the next row of pixels
* on each call. The rows MUST be returned in top-to-bottom order if you want
* your JPEG files to be compatible with everyone else's. (If you cannot
* readily read your data in that order, you'll need an intermediate array to
* hold the image. See jrdtarga.c or jrdrle.c for examples of handling
* bottom-to-top source data using the JPEG code's portable mechanisms.)
* The data is to be returned into a 2-D array of JSAMPLEs, indexed as
* JSAMPLE pixel_row[component][column]
* where component runs from 0 to cinfo->input_components-1, and column runs
* from 0 to cinfo->image_width-1 (column 0 is left edge of image). Note that
* this is actually an array of pointers to arrays rather than a true 2D array,
* since C does not support variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char".
*/
METHODDEF void
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* Read next row of pixels into pixel_row[][] */
{
/* This example shows how you might read RGB data (3 components)
* from an input file in which the data is stored 3 bytes per pixel
* in left-to-right, top-to-bottom order.
*/
register FILE * infile = cinfo->input_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = 0; col < cinfo->image_width; col++) {
*ptr0++ = (JSAMPLE) getc(infile); /* red */
*ptr1++ = (JSAMPLE) getc(infile); /* green */
*ptr2++ = (JSAMPLE) getc(infile); /* blue */
}
}
METHODDEF void
input_term (compress_info_ptr cinfo)
/* Finish up at the end of the input */
{
/* This termination routine will very often have no work to do, */
/* but you must provide it anyway. */
/* Note that the JPEG code will only call it during successful exit; */
/* if you want it called during error exit, you gotta do that yourself. */
}
/*
* That's it for the routines that deal with reading the input image data.
* Now we have overall control and parameter selection routines.
*/
/*
* This routine must determine what output JPEG file format is to be written,
* and make any other compression parameter changes that are desirable.
* This routine gets control after the input file header has been read
* (i.e., right after input_init has been called). You could combine its
* functions into input_init, or even into the main control routine, but
* if you have several different input_init routines, it's a definite win
* to keep this separate. You MUST supply this routine even if it's a no-op.
*/
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. */
jselwjfif(cinfo);
}
/*
* OK, here is the main function that actually causes everything to happen.
* We assume here that the target filename is supplied by the caller of this
* routine, and that all JPEG compression parameters can be default values.
*/
GLOBAL void
write_JPEG_file (char * filename)
{
/* These three structs contain JPEG parameters and working data.
* They must survive for the duration of parameter setup and one
* call to jpeg_compress; typically, making them local data in the
* calling routine is the best strategy.
*/
struct Compress_info_struct cinfo;
struct Compress_methods_struct c_methods;
struct External_methods_struct e_methods;
/* Initialize the system-dependent method pointers. */
cinfo.methods = &c_methods; /* links to method structs */
cinfo.emethods = &e_methods;
/* Here we use the default JPEG error handler, which will just print
* an error message on stderr and call exit(). See the second half of
* this file for an example of more graceful error recovery.
*/
jselerror(&e_methods); /* select std error/trace message routines */
/* Here we use the standard memory manager provided with the JPEG code.
* In some cases you might want to replace the memory manager, or at
* least the system-dependent part of it, with your own code.
*/
jselmemmgr(&e_methods); /* select std memory allocation routines */
/* If the compressor requires full-image buffers (for entropy-coding
* optimization or a noninterleaved JPEG file), it will create temporary
* files for anything that doesn't fit within the maximum-memory setting.
* (Note that temp files are NOT needed if you use the default parameters.)
* You can change the default maximum-memory setting by changing
* e_methods.max_memory_to_use after jselmemmgr returns.
* On some systems you may also need to set up a signal handler to
* ensure that temporary files are deleted if the program is interrupted.
* (This is most important if you are on MS-DOS and use the jmemdos.c
* memory manager back end; it will try to grab extended memory for
* temp files, and that space will NOT be freed automatically.)
* See jcmain.c or jdmain.c for an example signal handler.
*/
/* Here, set up pointers to your own routines for input data handling
* and post-init parameter selection.
*/
c_methods.input_init = input_init;
c_methods.get_input_row = get_input_row;
c_methods.input_term = input_term;
c_methods.c_ui_method_selection = c_ui_method_selection;
/* Set up default JPEG parameters in the cinfo data structure. */
j_c_defaults(&cinfo, 75, FALSE);
/* Note: 75 is the recommended default quality level; you may instead pass
* a user-specified quality level. Be aware that values below 25 will cause
* non-baseline JPEG files to be created (and a warning message to that
* effect to be emitted on stderr). This won't bother our decoder, but some
* commercial JPEG implementations may choke on non-baseline JPEG files.
* If you want to force baseline compatibility, pass TRUE instead of FALSE.
* (If non-baseline files are fine, but you could do without that warning
* message, set e_methods.trace_level to -1.)
*/
/* At this point you can modify the default parameters set by j_c_defaults
* as needed. For a minimal implementation, you shouldn't need to change
* anything. See jcmain.c for some examples of what you might change.
*/
/* Select the input and output files.
* Note that cinfo.input_file is only used if your input reading routines
* use it; otherwise, you can just make it NULL.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to write binary files.
*/
cinfo.input_file = NULL; /* if no actual input file involved */
if ((cinfo.output_file = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
/* Here we go! */
jpeg_compress(&cinfo);
/* That's it, son. Nothin' else to do, except close files. */
/* Here we assume only the output file need be closed. */
fclose(cinfo.output_file);
/* Note: if you want to compress more than one image, we recommend you
* repeat this whole routine. You MUST repeat the j_c_defaults()/alter
* parameters/jpeg_compress() sequence, as some data structures allocated
* in j_c_defaults are freed upon exit from jpeg_compress.
*/
}
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
/* This half of the example shows how to read data from the JPEG decompressor.
* It's a little more refined than the above in that we show how to do your
* own error recovery. If you don't care about that, you don't need these
* next two routines.
*/
/*
* These routines replace the default trace/error routines included with the
* JPEG code. The example trace_message routine shown here is actually the
* same as the standard one, but you could modify it if you don't want messages
* sent to stderr. The example error_exit routine is set up to return
* control to read_JPEG_file() rather than calling exit(). You can use the
* same routines for both compression and decompression error recovery.
*/
/* These static variables are needed by the error routines. */
static jmp_buf setjmp_buffer; /* for return to caller */
static external_methods_ptr emethods; /* needed for access to message_parm */
/* This routine is used for any and all trace, debug, or error printouts
* from the JPEG code. The parameter is a printf format string; up to 8
* integer data values for the format string have been stored in the
* message_parm[] field of the external_methods struct.
*/
METHODDEF void
trace_message (const char *msgtext)
{
fprintf(stderr, msgtext,
emethods->message_parm[0], emethods->message_parm[1],
emethods->message_parm[2], emethods->message_parm[3],
emethods->message_parm[4], emethods->message_parm[5],
emethods->message_parm[6], emethods->message_parm[7]);
fprintf(stderr, "\n"); /* there is no \n in the format string! */
}
/*
* The error_exit() routine should not return to its caller. The default
* routine calls exit(), but here we assume that we want to return to
* read_JPEG_file, which has set up a setjmp context for the purpose.
* You should make sure that the free_all method is called, either within
* error_exit or after the return to the outer-level routine.
*/
METHODDEF void
error_exit (const char *msgtext)
{
trace_message(msgtext); /* report the error message */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
longjmp(setjmp_buffer, 1); /* return control to outer routine */
}
/*
* To accept the image data from decompression, you must define four routines
* output_init, put_color_map, put_pixel_rows, and output_term.
*
* You must understand the distinction between full color output mode
* (N independent color components) and colormapped output mode (a single
* output component representing an index into a color map). You should use
* colormapped mode to write to a colormapped display screen or output file.
* Colormapped mode is also useful for reducing grayscale output to a small
* number of gray levels: when using the 1-pass quantizer on grayscale data,
* the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
* can regard the indexes as directly representing gray levels at reduced
* precision. In any other case, you should not depend on the colormap
* entries having any particular order.
* To get colormapped output, set cinfo->quantize_colors to TRUE and set
* cinfo->desired_number_of_colors to the maximum number of entries in the
* colormap. This can be done either in your main routine or in
* d_ui_method_selection. For grayscale quantization, also set
* cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
* (presently this is the default, but it may not be so in the future).
*
* The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
* useful examples of what these routines should actually do, although each of
* them is encrusted with a lot of specialized code for its own file format.
*/
METHODDEF void
output_init (decompress_info_ptr cinfo)
/* This routine should do any setup required */
{
/* This routine can initialize for output based on the data passed in cinfo.
* Useful fields include:
* image_width, image_height Pretty obvious, I hope.
* data_precision bits per pixel value; typically 8.
* out_color_space output colorspace previously requested
* color_out_comps number of color components in same
* final_out_comps number of components actually output
* final_out_comps is 1 if quantize_colors is true, else it is equal to
* color_out_comps.
*
* If you have requested color quantization, the colormap is NOT yet set.
* You may wish to defer output initialization until put_color_map is called.
*/
}
/*
* This routine is called if and only if you have set cinfo->quantize_colors
* to TRUE. It is given the selected colormap and can complete any required
* initialization. This call will occur after output_init and before any
* calls to put_pixel_rows. Note that the colormap pointer is also placed
* in a cinfo field, whence it can be used by put_pixel_rows or output_term.
* num_colors will be less than or equal to desired_number_of_colors.
*
* The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
* JSAMPLE colormap[component][indexvalue]
* where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
* runs from 0 to num_colors-1. Note that this is actually an array of
* pointers to arrays rather than a true 2D array, since C does not support
* variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char". If you want your code
* to be as portable as the JPEG code proper, you should always access JSAMPLE
* values with the GETJSAMPLE() macro, which will do the right thing if the
* machine has only signed chars.
*/
METHODDEF void
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
/* Write the color map */
{
/* You need not provide this routine if you always set cinfo->quantize_colors
* FALSE; but a safer practice is to provide it and have it just print an
* error message, like this:
*/
fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n");
}
/*
* This function is called repeatedly, with a few more rows of pixels supplied
* on each call. With the current JPEG code, some multiple of 8 rows will be
* passed on each call except the last, but it is extremely bad form to depend
* on this. You CAN assume num_rows > 0.
* The data is supplied in top-to-bottom row order (the standard order within
* a JPEG file). If you cannot readily use the data in that order, you'll
* need an intermediate array to hold the image. See jwrrle.c for an example
* of outputting data in bottom-to-top order.
*
* The data is supplied as a 3-D array of JSAMPLEs, indexed as
* JSAMPLE pixel_data[component][row][column]
* where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
* num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
* left edge of image). Note that this is actually an array of pointers to
* pointers to arrays rather than a true 3D array, since C does not support
* variable-size multidimensional arrays.
* JSAMPLE is typically typedef'd as "unsigned char". If you want your code
* to be as portable as the JPEG code proper, you should always access JSAMPLE
* values with the GETJSAMPLE() macro, which will do the right thing if the
* machine has only signed chars.
*
* If quantize_colors is true, then there is only one component, and its values
* are indexes into the previously supplied colormap. Otherwise the values
* are actual data in your selected output colorspace.
*/
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)
/* Write some rows of output data */
{
/* This example shows how you might write full-color RGB data (3 components)
* to an output file in which the data is stored 3 bytes per pixel.
*/
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
register int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
ptr1 = pixel_data[1][row];
ptr2 = pixel_data[2][row];
for (col = 0; col < cinfo->image_width; col++) {
putc(GETJSAMPLE(*ptr0), outfile); /* red */
ptr0++;
putc(GETJSAMPLE(*ptr1), outfile); /* green */
ptr1++;
putc(GETJSAMPLE(*ptr2), outfile); /* blue */
ptr2++;
}
}
}
METHODDEF void
output_term (decompress_info_ptr cinfo)
/* Finish up at the end of the output */
{
/* This termination routine may not need to do anything. */
/* Note that the JPEG code will only call it during successful exit; */
/* if you want it called during error exit, you gotta do that yourself. */
}
/*
* That's it for the routines that deal with writing the output image.
* Now we have overall control and parameter selection routines.
*/
/*
* This routine gets control after the JPEG file header has been read;
* at this point the image size and colorspace are known.
* The routine must determine what output routines are to be used, and make
* any decompression parameter changes that are desirable. For example,
* if it is found that the JPEG file is grayscale, you might want to do
* things differently than if it is color. You can also delay setting
* quantize_colors and associated options until this point.
*
* j_d_defaults initializes out_color_space to CS_RGB. If you want grayscale
* output you should set out_color_space to CS_GRAYSCALE. Note that you can
* force grayscale output from a color JPEG file (though not vice versa).
*/
METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
{
/* if grayscale input, force grayscale output; */
/* else leave the output colorspace as set by main routine. */
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
cinfo->out_color_space = CS_GRAYSCALE;
/* select output routines */
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;
}
/*
* OK, here is the main function that actually causes everything to happen.
* We assume here that the JPEG filename is supplied by the caller of this
* routine, and that all decompression parameters can be default values.
* The routine returns 1 if successful, 0 if not.
*/
GLOBAL int
read_JPEG_file (char * filename)
{
/* These three structs contain JPEG parameters and working data.
* They must survive for the duration of parameter setup and one
* call to jpeg_decompress; typically, making them local data in the
* calling routine is the best strategy.
*/
struct Decompress_info_struct cinfo;
struct Decompress_methods_struct dc_methods;
struct External_methods_struct e_methods;
/* Select the input and output files.
* In this example we want to open the input file before doing anything else,
* so that the setjmp() error recovery below can assume the file is open.
* Note that cinfo.output_file is only used if your output handling routines
* use it; otherwise, you can just make it NULL.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to read binary files.
*/
if ((cinfo.input_file = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
cinfo.output_file = NULL; /* if no actual output file involved */
/* Initialize the system-dependent method pointers. */
cinfo.methods = &dc_methods; /* links to method structs */
cinfo.emethods = &e_methods;
/* Here we supply our own error handler; compare to use of standard error
* handler in the previous write_JPEG_file example.
*/
emethods = &e_methods; /* save struct addr for possible access */
e_methods.error_exit = error_exit; /* supply error-exit routine */
e_methods.trace_message = trace_message; /* supply trace-message routine */
e_methods.trace_level = 0; /* default = no tracing */
e_methods.num_warnings = 0; /* no warnings emitted yet */
e_methods.first_warning_level = 0; /* display first corrupt-data warning */
e_methods.more_warning_level = 3; /* but suppress additional ones */
/* prepare setjmp context for possible exit from error_exit */
if (setjmp(setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* Memory allocation has already been cleaned up (see free_all call in
* error_exit), but we need to close the input file before returning.
* You might also need to close an output file, etc.
*/
fclose(cinfo.input_file);
return 0;
}
/* Here we use the standard memory manager provided with the JPEG code.
* In some cases you might want to replace the memory manager, or at
* least the system-dependent part of it, with your own code.
*/
jselmemmgr(&e_methods); /* select std memory allocation routines */
/* If the decompressor requires full-image buffers (for two-pass color
* quantization or a noninterleaved JPEG file), it will create temporary
* files for anything that doesn't fit within the maximum-memory setting.
* You can change the default maximum-memory setting by changing
* e_methods.max_memory_to_use after jselmemmgr returns.
* On some systems you may also need to set up a signal handler to
* ensure that temporary files are deleted if the program is interrupted.
* (This is most important if you are on MS-DOS and use the jmemdos.c
* memory manager back end; it will try to grab extended memory for
* temp files, and that space will NOT be freed automatically.)
* See jcmain.c or jdmain.c for an example signal handler.
*/
/* Here, set up the pointer to your own routine for post-header-reading
* parameter selection. You could also initialize the pointers to the
* output data handling routines here, if they are not dependent on the
* image type.
*/
dc_methods.d_ui_method_selection = d_ui_method_selection;
/* Set up default decompression parameters. */
j_d_defaults(&cinfo, TRUE);
/* TRUE indicates that an input buffer should be allocated.
* In unusual cases you may want to allocate the input buffer yourself;
* see jddeflts.c for commentary.
*/
/* At this point you can modify the default parameters set by j_d_defaults
* as needed; for example, you can request color quantization or force
* grayscale output. See jdmain.c for examples of what you might change.
*/
/* Set up to read a JFIF or baseline-JPEG file. */
/* This is the only JPEG file format currently supported. */
jselrjfif(&cinfo);
/* Here we go! */
jpeg_decompress(&cinfo);
/* That's it, son. Nothin' else to do, except close files. */
/* Here we assume only the input file need be closed. */
fclose(cinfo.input_file);
/* You might want to test e_methods.num_warnings to see if bad data was
* detected. In this example, we just blindly forge ahead.
*/
return 1; /* indicate success */
/* Note: if you want to decompress more than one image, we recommend you
* repeat this whole routine. You MUST repeat the j_d_defaults()/alter
* parameters/jpeg_decompress() sequence, as some data structures allocated
* in j_d_defaults are freed upon exit from jpeg_decompress.
*/
}

View File

@@ -1,7 +1,7 @@
/*
* jbsmooth.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -27,7 +27,7 @@ smooth_coefficients (decompress_info_ptr cinfo,
JBLOCKROW output)
{
QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
long blocks_in_row = compptr->subsampled_width / DCTSIZE;
long blocks_in_row = compptr->downsampled_width / DCTSIZE;
long col;
/* First, copy the block row as-is.
@@ -43,7 +43,7 @@ smooth_coefficients (decompress_info_ptr cinfo,
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.
/* See section K.8 of the JPEG standard.
*
* As I understand it, this produces approximations
* for the low frequency AC components, based on the
@@ -51,9 +51,7 @@ smooth_coefficients (decompress_info_ptr cinfo,
* (Thus it can't be used for blocks on the image edges.)
*/
/* The layout of these variables corresponds to
* the text in 13.10
*/
/* The layout of these variables corresponds to text and figure in K.8 */
JCOEF DC1, DC2, DC3;
JCOEF DC4, DC5, DC6;

View File

@@ -1,18 +1,18 @@
/*
* jcarith.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* entropy_encode_init/term, and entropy_optimize.
*/
#include "jinclude.h"
#ifdef ARITH_CODING_SUPPORTED
#ifdef C_ARITH_CODING_SUPPORTED
/*
@@ -39,4 +39,4 @@ jselcarithmetic (compress_info_ptr cinfo)
}
}
#endif /* ARITH_CODING_SUPPORTED */
#endif /* C_ARITH_CODING_SUPPORTED */

273
jccolor.c
View File

@@ -1,7 +1,7 @@
/*
* jccolor.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -16,6 +16,201 @@
static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
/**************** RGB -> YCbCr conversion: most common case **************/
/*
* 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.
* The conversion equations to be implemented are therefore
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + MAXJSAMPLE/2
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + MAXJSAMPLE/2
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
*
* To avoid floating-point arithmetic, we represent the fractional constants
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
* the products by 2^16, with appropriate rounding, to get the correct answer.
*
* For even more speed, we avoid doing any multiplications in the inner loop
* by precalculating the constants times R,G,B for all possible values.
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
* for 12-bit samples it is still acceptable. It's not very reasonable for
* 16-bit samples, but if you want lossless storage you shouldn't be changing
* colorspace anyway.
* The MAXJSAMPLE/2 offsets and the rounding fudge-factor of 0.5 are included
* in the tables to save adding them separately in the inner loop.
*/
#ifdef SIXTEEN_BIT_SAMPLES
#define SCALEBITS 14 /* avoid overflow */
#else
#define SCALEBITS 16 /* speedier right-shift on some machines */
#endif
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
/* We allocate one big table and divide it up into eight parts, instead of
* doing eight alloc_small requests. This lets us use a single table base
* address, which can be held in a register in the inner loops on many
* machines (more than can hold all eight addresses, anyway).
*/
static INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
#define R_Y_OFF 0 /* offset to R => Y section */
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
#define R_CB_OFF (3*(MAXJSAMPLE+1))
#define G_CB_OFF (4*(MAXJSAMPLE+1))
#define B_CB_OFF (5*(MAXJSAMPLE+1))
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
#define G_CR_OFF (6*(MAXJSAMPLE+1))
#define B_CR_OFF (7*(MAXJSAMPLE+1))
#define TABLE_SIZE (8*(MAXJSAMPLE+1))
/*
* Initialize for colorspace conversion.
*/
METHODDEF void
rgb_ycc_init (compress_info_ptr cinfo)
{
INT32 i;
/* Allocate a workspace for the result of get_input_row. */
pixel_row = (*cinfo->emethods->alloc_small_sarray)
(cinfo->image_width, (long) cinfo->input_components);
/* Allocate and fill in the conversion tables. */
rgb_ycc_tab = (INT32 *) (*cinfo->emethods->alloc_small)
(TABLE_SIZE * SIZEOF(INT32));
for (i = 0; i <= MAXJSAMPLE; i++) {
rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1);
/* B=>Cb and R=>Cr tables are the same
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1);
*/
rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
}
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
*/
METHODDEF void
get_rgb_ycc_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
{
#ifdef SIXTEEN_BIT_SAMPLES
register UINT16 r, g, b;
#else
register int r, g, b;
#endif
register INT32 * ctab = rgb_ycc_tab;
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 = 0; col < width; col++) {
r = GETJSAMPLE(inptr0[col]);
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr0[col] = (JSAMPLE)
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
>> SCALEBITS);
/* Cb */
outptr1[col] = (JSAMPLE)
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
>> SCALEBITS);
/* Cr */
outptr2[col] = (JSAMPLE)
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
>> SCALEBITS);
}
}
}
/**************** Cases other than RGB -> YCbCr **************/
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* This version handles RGB->grayscale conversion, which is the same
* as the RGB->Y portion of RGB->YCbCr.
* We assume rgb_ycc_init has been called (we only use the Y tables).
*/
METHODDEF void
get_rgb_gray_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
{
#ifdef SIXTEEN_BIT_SAMPLES
register UINT16 r, g, b;
#else
register int r, g, b;
#endif
register INT32 * ctab = rgb_ycc_tab;
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr;
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];
outptr = image_data[0][row];
for (col = 0; col < width; col++) {
r = GETJSAMPLE(inptr0[col]);
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr[col] = (JSAMPLE)
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
>> SCALEBITS);
}
}
}
/*
* Initialize for colorspace conversion.
*/
@@ -32,57 +227,8 @@ colorin_init (compress_info_ptr cinfo)
/*
* 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++ = (JSAMPLE)
(( 306*r + 601*g + 117*b + (INT32) 512) >> 10);
/* Cb */
*outptr1++ = (JSAMPLE)
(((-173)*r - 339*g + 512*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10);
/* Cr */
*outptr2++ = (JSAMPLE)
(( 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).
* This version handles grayscale output with no conversion.
* The source can be either plain grayscale or YCbCr (since Y == gray).
*/
METHODDEF void
@@ -132,9 +278,7 @@ get_noconvert_rows (compress_info_ptr cinfo,
METHODDEF void
colorin_term (compress_info_ptr cinfo)
{
/* Release the workspace. */
(*cinfo->emethods->free_small_sarray)
(pixel_row, (long) cinfo->input_components);
/* no work (we let free_all release the workspace) */
}
@@ -153,6 +297,8 @@ jselccolor (compress_info_ptr cinfo)
break;
case CS_RGB:
case CS_YCbCr:
case CS_YIQ:
if (cinfo->input_components != 3)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
break;
@@ -167,6 +313,10 @@ jselccolor (compress_info_ptr cinfo)
break;
}
/* Standard init/term methods (may override below) */
cinfo->methods->colorin_init = colorin_init;
cinfo->methods->colorin_term = colorin_term;
/* Check num_components, set conversion method based on requested space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
@@ -174,6 +324,11 @@ jselccolor (compress_info_ptr cinfo)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_GRAYSCALE)
cinfo->methods->get_sample_rows = get_grayscale_rows;
else if (cinfo->in_color_space == CS_RGB) {
cinfo->methods->colorin_init = rgb_ycc_init;
cinfo->methods->get_sample_rows = get_rgb_gray_rows;
} else if (cinfo->in_color_space == CS_YCbCr)
cinfo->methods->get_sample_rows = get_grayscale_rows;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
break;
@@ -181,8 +336,11 @@ jselccolor (compress_info_ptr cinfo)
case CS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_RGB)
if (cinfo->in_color_space == CS_RGB) {
cinfo->methods->colorin_init = rgb_ycc_init;
cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
} else if (cinfo->in_color_space == CS_YCbCr)
cinfo->methods->get_sample_rows = get_noconvert_rows;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
break;
@@ -200,7 +358,4 @@ jselccolor (compress_info_ptr cinfo)
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
break;
}
cinfo->methods->colorin_init = colorin_init;
cinfo->methods->colorin_term = colorin_term;
}

View File

@@ -1,7 +1,7 @@
/*
* jcdeflts.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -13,6 +13,35 @@
#include "jinclude.h"
/* Default do-nothing progress monitoring routine.
* This can be overridden by a user interface that wishes to
* provide progress monitoring; just set methods->progress_monitor
* after j_c_defaults is done. The routine will be called periodically
* during the compression process.
*
* During any one pass, loopcounter increases from 0 up to (not including)
* looplimit; the step size is not necessarily 1. Both the step size and
* the limit may differ between passes. The expected total number of passes
* is in cinfo->total_passes, and the number of passes already completed is
* in cinfo->completed_passes. Thus the fraction of work completed may be
* estimated as
* completed_passes + (loopcounter/looplimit)
* ------------------------------------------
* total_passes
* ignoring the fact that the passes may not be equal amounts of work.
*/
METHODDEF void
progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
{
/* do nothing */
}
/*
* Huffman table setup routines
*/
LOCAL void
add_huff_table (compress_info_ptr cinfo,
HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
@@ -21,10 +50,8 @@ add_huff_table (compress_info_ptr cinfo,
if (*htblptr == NULL)
*htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
memcpy((void *) (*htblptr)->bits, (const void *) bits,
SIZEOF((*htblptr)->bits));
memcpy((void *) (*htblptr)->huffval, (const void *) val,
SIZEOF((*htblptr)->huffval));
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, 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,
@@ -38,7 +65,8 @@ add_huff_table (compress_info_ptr cinfo,
LOCAL void
std_huff_tables (compress_info_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG-8-R8 section 13.3) */
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
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 };
@@ -111,43 +139,19 @@ std_huff_tables (compress_info_ptr cinfo)
}
/* 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.)
/*
* Quantization table setup routines
*/
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) */
GLOBAL void
j_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).
* If force_baseline is TRUE, the computed quantization table entries
* are limited to 1..255 for JPEG baseline compatibility.
*/
{
QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
int i;
@@ -172,24 +176,20 @@ add_quant_table (compress_info_ptr cinfo, int which_tbl,
}
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. */
GLOBAL int
j_quality_scaling (int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/
{
/* 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.
/* 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
* note that at Q=100 the scaling is 0, which will cause j_add_quant_table
* to make all the table entries 1 (hence, no quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
@@ -198,9 +198,53 @@ j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
else
quality = 200 - quality*2;
return quality;
}
GLOBAL void
j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
* would use the preceding two routines directly.
*/
{
/* This is the sample quantization table given in the JPEG spec section K.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 respectively.)
*/
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
};
/* Convert user 0-100 rating to percentage scaling */
quality = j_quality_scaling(quality);
/* 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);
j_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
quality, force_baseline);
j_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
quality, force_baseline);
}
@@ -226,14 +270,9 @@ j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
* 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_c_defaults before *each* call to jpeg_compress (and
* j_c_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 at present
* 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.
* CAUTION: if you want to compress multiple images per run, it's necessary
* to call j_c_defaults before *each* call to jpeg_compress, since subsidiary
* structures like the Huffman tables are automatically freed during cleanup.
*/
GLOBAL void
@@ -252,16 +291,18 @@ j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline)
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
cinfo->data_precision = 8; /* default; can be overridden by input_init */
cinfo->data_precision = BITS_IN_JSAMPLE; /* 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 */
cinfo->write_JFIF_header = TRUE; /* write a JFIF marker */
cinfo->comment_text = NULL; /* but no COM block */
/* 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 = (jpeg_component_info *)
@@ -322,8 +363,15 @@ j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* By default, use the simpler non-cosited sampling alignment */
cinfo->CCIR601_sampling = FALSE;
/* No input smoothing */
cinfo->smoothing_factor = 0;
/* No restart markers */
cinfo->restart_interval = 0;
cinfo->restart_in_rows = 0;
/* Install default do-nothing progress monitoring method. */
cinfo->methods->progress_monitor = progress_monitor;
}
@@ -341,27 +389,3 @@ j_monochrome_default (compress_info_ptr cinfo)
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
}
/* This routine releases storage allocated by j_c_defaults.
* Note that freeing the method pointer structs and the compress_info_struct
* itself are the responsibility of the user interface.
*/
GLOBAL void
j_c_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]);
}
}

View File

@@ -1,7 +1,7 @@
/*
* jcexpand.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -16,7 +16,7 @@
* 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.
* downsampled, so all components have the same dimensions.
*/
METHODDEF void

View File

@@ -1,13 +1,13 @@
/*
* jchuff.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
* entropy_encode_init/term, and entropy_optimize.
*/
#include "jinclude.h"
@@ -34,7 +34,7 @@ fix_huff_tbl (HUFF_TBL * htbl)
UINT16 huffcode[257];
UINT16 code;
/* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
/* Figure C.1: make table of Huffman code length for each symbol */
/* Note that this is in code-length order. */
p = 0;
@@ -45,7 +45,7 @@ fix_huff_tbl (HUFF_TBL * htbl)
huffsize[p] = 0;
lastp = p;
/* Figure 7.3.5.4.2.2: generate the codes themselves */
/* Figure C.2: generate the codes themselves */
/* Note that this is in code-length order. */
code = 0;
@@ -60,26 +60,17 @@ fix_huff_tbl (HUFF_TBL * htbl)
si++;
}
/* Figure 7.3.5.4.2.3: generate encoding tables */
/* Figure C.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 */
/* Set any codeless symbols to have code length 0;
* this allows emit_bits to detect any attempt to emit such symbols.
*/
MEMZERO(htbl->priv.enc.ehufsi, SIZEOF(htbl->priv.enc.ehufsi));
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;
}
for (p = 0; p < lastp; p++) {
htbl->priv.enc.ehufco[htbl->huffval[p]] = huffcode[p];
htbl->priv.enc.ehufsi[htbl->huffval[p]] = huffsize[p];
}
}
@@ -110,6 +101,7 @@ flush_bytes (void)
* between calls, so 24 bits are sufficient.
*/
INLINE
LOCAL void
emit_bits (UINT16 code, int size)
{
@@ -117,6 +109,10 @@ emit_bits (UINT16 code, int size)
register INT32 put_buffer = code;
register int put_bits = huff_put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
if (size == 0)
ERREXIT(cinfo->emethods, "Missing Huffman code table entry");
put_buffer &= (((INT32) 1) << size) - 1; /* Mask off any excess bits in code */
put_bits += size; /* new number of bits in buffer */
@@ -161,7 +157,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
register int nbits;
register int k, r, i;
/* Encode the DC coefficient difference per section 7.3.5.1 */
/* Encode the DC coefficient difference per section F.1.2.1 */
temp = temp2 = block[0];
@@ -180,13 +176,14 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
}
/* Emit the Huffman-coded symbol for the number of bits */
emit_bits(dctbl->ehufco[nbits], dctbl->ehufsi[nbits]);
emit_bits(dctbl->priv.enc.ehufco[nbits], dctbl->priv.enc.ehufsi[nbits]);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
emit_bits((UINT16) temp2, nbits);
if (nbits) /* emit_bits rejects calls with size 0 */
emit_bits((UINT16) temp2, nbits);
/* Encode the AC coefficients per section 7.3.5.2 */
/* Encode the AC coefficients per section F.1.2.2 */
r = 0; /* r = run length of zeros */
@@ -196,7 +193,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
} else {
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
while (r > 15) {
emit_bits(actbl->ehufco[0xF0], actbl->ehufsi[0xF0]);
emit_bits(actbl->priv.enc.ehufco[0xF0], actbl->priv.enc.ehufsi[0xF0]);
r -= 16;
}
@@ -214,7 +211,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
/* Emit Huffman symbol for run length / number of bits */
i = (r << 4) + nbits;
emit_bits(actbl->ehufco[i], actbl->ehufsi[i]);
emit_bits(actbl->priv.enc.ehufco[i], actbl->priv.enc.ehufsi[i]);
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
@@ -226,7 +223,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
/* If the last coef(s) were zero, emit an end-of-block code */
if (r > 0)
emit_bits(actbl->ehufco[0], actbl->ehufsi[0]);
emit_bits(actbl->priv.enc.ehufco[0], actbl->priv.enc.ehufsi[0]);
}
@@ -378,10 +375,10 @@ gen_huff_coding (compress_info_ptr cinfo, HUFF_TBL *htbl, long freq[])
int p, i, j;
long v;
/* This algorithm is explained in section 13.2 of JPEG-8-R8 */
/* This algorithm is explained in section K.2 of the JPEG standard */
MEMZERO((void *) bits, SIZEOF(bits));
MEMZERO((void *) codesize, SIZEOF(codesize));
MEMZERO(bits, SIZEOF(bits));
MEMZERO(codesize, SIZEOF(codesize));
for (i = 0; i < 257; i++)
others[i] = -1; /* init links to empty */
@@ -483,7 +480,7 @@ gen_huff_coding (compress_info_ptr cinfo, HUFF_TBL *htbl, long freq[])
bits[i]--;
/* Return final symbol counts (only for lengths 0..16) */
memcpy((void *) htbl->bits, (void *) bits, SIZEOF(htbl->bits));
MEMCOPY(htbl->bits, 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
@@ -512,7 +509,7 @@ htest_one_block (JBLOCK block, JCOEF block0,
register int nbits;
register int k, r;
/* Encode the DC coefficient difference per section 7.3.5.1 */
/* Encode the DC coefficient difference per section F.1.2.1 */
/* Find the number of bits needed for the magnitude of the coefficient */
temp = block0;
@@ -524,7 +521,7 @@ htest_one_block (JBLOCK block, JCOEF block0,
/* Count the Huffman symbol for the number of bits */
dc_counts[nbits]++;
/* Encode the AC coefficients per section 7.3.5.2 */
/* Encode the AC coefficients per section F.1.2.2 */
r = 0; /* r = run length of zeros */
@@ -624,14 +621,14 @@ huff_optimize (compress_info_ptr cinfo, MCU_output_caller_ptr source_method)
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));
MEMZERO(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));
MEMZERO(ac_count_ptrs[tbl], 257 * SIZEOF(long));
}
}
@@ -684,11 +681,20 @@ GLOBAL void
jselchuffman (compress_info_ptr cinfo)
{
if (! cinfo->arith_code) {
cinfo->methods->entropy_encoder_init = huff_init;
cinfo->methods->entropy_encode_init = huff_init;
cinfo->methods->entropy_encode = huff_encode;
cinfo->methods->entropy_encoder_term = huff_term;
cinfo->methods->entropy_encode_term = huff_term;
#ifdef ENTROPY_OPT_SUPPORTED
cinfo->methods->entropy_optimize = huff_optimize;
/* The standard Huffman tables are only valid for 8-bit data precision.
* If the precision is higher, force optimization on so that usable
* tables will be computed. This test can be removed if default tables
* are supplied that are valid for the desired precision.
*/
if (cinfo->data_precision > 8)
cinfo->optimize_coding = TRUE;
if (cinfo->optimize_coding)
cinfo->total_passes++; /* one pass needed for entropy optimization */
#endif
}
}

673
jcmain.c
View File

@@ -1,11 +1,11 @@
/*
* jcmain.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
* This file contains a command-line 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
@@ -18,12 +18,22 @@
* 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.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* cjpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#include <ctype.h> /* to declare isupper(), tolower() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
@@ -37,16 +47,21 @@
#define WRITE_BINARY "wb"
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#ifdef VMS
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
#else
#define EXIT_SUCCESS 0
#endif
#endif
#include "jversion.h" /* for version message */
/*
* PD version of getopt(3).
*/
#include "egetopt.c"
/*
* This routine determines what format the input file is,
* and selects the appropriate input-reading module.
@@ -70,10 +85,10 @@
* We presently apply this method for Targa files. Most of the time Targa
* files start with 0x00, so we recognize that case. Potentially, however,
* a Targa file could start with any byte value (byte 0 is the length of the
* seldom-used ID field), so we accept a -T switch to force Targa input mode.
* seldom-used ID field), so we provide a switch to force Targa input mode.
*/
static boolean is_targa; /* records user -T switch */
static boolean is_targa; /* records user -targa switch */
LOCAL void
@@ -116,7 +131,7 @@ select_file_type (compress_info_ptr cinfo)
#endif
default:
#ifdef TARGA_SUPPORTED
ERREXIT(cinfo->emethods, "Unrecognized input file format --- did you forget -T ?");
ERREXIT(cinfo->emethods, "Unrecognized input file format --- perhaps you need -targa");
#else
ERREXIT(cinfo->emethods, "Unrecognized input file format");
#endif
@@ -149,18 +164,444 @@ c_ui_method_selection (compress_info_ptr cinfo)
}
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static external_methods_ptr emethods; /* for access to free_all */
GLOBAL void
signal_catcher (int signum)
{
if (emethods != NULL) {
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
* See jcdeflts.c for explanation of the information used.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
{
if (cinfo->total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
cinfo->completed_passes+1, cinfo->total_passes,
(int) (loopcounter*100L/looplimit));
} else {
fprintf(stderr, "\r %3d%% ",
(int) (loopcounter*100L/looplimit));
}
fflush(stderr);
}
#endif
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (char * progname)
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-Q quality 0..100] [-o] [-T] [-I] [-a] [-d]");
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, " inputfile outputfile\n");
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, " [inputfile]\n");
fprintf(stderr, "[inputfile]\n");
#endif
exit(2);
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
#ifdef ENTROPY_OPT_SUPPORTED
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
#ifdef INPUT_SMOOTHING_SUPPORTED
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, "Switches for wizards:\n");
#ifdef C_ARITH_CODING_SUPPORTED
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
#endif
#ifdef C_MULTISCAN_FILES_SUPPORTED
fprintf(stderr, " -nointerleave Create noninterleaved JPEG file\n");
#endif
fprintf(stderr, " -qtables file Use quantization tables given in file\n");
fprintf(stderr, " -sample HxV[,...] Set JPEG sampling factors\n");
exit(EXIT_FAILURE);
}
LOCAL boolean
keymatch (char * arg, const char * keyword, int minchars)
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
/* keyword is the constant keyword (must be lower case already), */
/* minchars is length of minimum legal abbreviation. */
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
LOCAL int
qt_getc (FILE * file)
/* Read next char, skipping over any comments (# to end of line) */
/* A comment/newline sequence is returned as a newline */
{
register int ch;
ch = getc(file);
if (ch == '#') {
do {
ch = getc(file);
} while (ch != '\n' && ch != EOF);
}
return ch;
}
LOCAL long
read_qt_integer (FILE * file)
/* Read an unsigned decimal integer from a quantization-table file */
/* Swallows one trailing character after the integer */
{
register int ch;
register long val;
/* Skip any leading whitespace, detect EOF */
do {
ch = qt_getc(file);
if (ch == EOF)
return EOF;
} while (isspace(ch));
if (! isdigit(ch)) {
fprintf(stderr, "%s: bogus data in quantization file\n", progname);
exit(EXIT_FAILURE);
}
val = ch - '0';
while (ch = qt_getc(file), isdigit(ch)) {
val *= 10;
val += ch - '0';
}
return val;
}
LOCAL void
read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor)
/* Read a set of quantization tables from the specified file.
* The file is plain ASCII text: decimal numbers with whitespace between.
* Comments preceded by '#' may be included in the file.
* There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
* The tables are implicitly numbered 0,1,etc.
*/
{
/* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
/* read in natural order (left to right, top to bottom). */
static const short ZIG[DCTSIZE2] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
FILE * fp;
int tblno, i;
long val;
QUANT_TBL table;
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, filename);
exit(EXIT_FAILURE);
}
tblno = 0;
while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
if (tblno >= NUM_QUANT_TBLS) {
fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
exit(EXIT_FAILURE);
}
table[0] = (QUANT_VAL) val;
for (i = 1; i < DCTSIZE2; i++) {
if ((val = read_qt_integer(fp)) == EOF) {
fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
exit(EXIT_FAILURE);
}
table[ZIG[i]] = (QUANT_VAL) val;
}
j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE);
tblno++;
}
fclose(fp);
}
LOCAL void
set_sample_factors (compress_info_ptr cinfo, char *arg)
/* Process a sample-factors parameter string, of the form */
/* HxV[,HxV,...] */
{
#define MAX_COMPONENTS 4 /* # of comp_info slots made by jcdeflts.c */
int ci, val1, val2;
char ch1, ch2;
for (ci = 0; ci < MAX_COMPONENTS; ci++) {
if (*arg) {
ch2 = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
usage();
if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
usage(); /* syntax check */
if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
fprintf(stderr, "JPEG sampling factors must be 1..4\n");
exit(EXIT_FAILURE);
}
cinfo->comp_info[ci].h_samp_factor = val1;
cinfo->comp_info[ci].v_samp_factor = val2;
while (*arg && *arg++ != ',') /* advance to next segment of arg string */
;
} else {
/* reached end of parameter, set remaining components to 1x1 sampling */
cinfo->comp_info[ci].h_samp_factor = 1;
cinfo->comp_info[ci].v_samp_factor = 1;
}
}
}
LOCAL int
parse_switches (compress_info_ptr cinfo, int last_file_arg_seen,
int argc, char **argv)
/* Initialize cinfo with default switch settings, then parse option switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
*/
{
int argn;
char * arg;
char * qtablefile = NULL; /* saves -qtables filename if any */
int q_scale_factor = 100; /* default to no scaling for -qtables */
/* (Re-)initialize the system-dependent error and memory managers. */
jselerror(cinfo->emethods); /* error/trace message routines */
jselmemmgr(cinfo->emethods); /* memory allocation routines */
cinfo->methods->c_ui_method_selection = c_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = cinfo->emethods;
#endif
/* Set up default JPEG parameters. */
/* Note that default -quality level here need not, and does not,
* match the default scaling for an explicit -qtables argument.
*/
j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */
is_targa = FALSE;
outfilename = NULL;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "arithmetic", 1)) {
/* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE;
#else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
cinfo->emethods->trace_level++;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */
j_monochrome_default(cinfo);
} else if (keymatch(arg, "maxmemory", 1)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->emethods->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nointerleave", 3)) {
/* Create noninterleaved file. */
#ifdef C_MULTISCAN_FILES_SUPPORTED
cinfo->interleave = FALSE;
#else
fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
/* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED
cinfo->optimize_coding = TRUE;
#else
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
progname);
exit(EXIT_FAILURE);
#endif
} else if (keymatch(arg, "outfile", 3)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "quality", 1)) {
/* Quality factor (quantization table scaling factor). */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
/* Set quantization tables (will be overridden if -qtables also given).
* Note: we make force_baseline FALSE.
* This means non-baseline JPEG files can be created with low Q values.
* To ensure only baseline files are generated, pass TRUE instead.
*/
j_set_quality(cinfo, val, FALSE);
/* Change scale factor in case -qtables is present. */
q_scale_factor = j_quality_scaling(val);
} else if (keymatch(arg, "qtables", 2)) {
/* Quantization tables fetched from file. */
if (++argn >= argc) /* advance to next argument */
usage();
qtablefile = argv[argn];
/* we postpone actually reading the file in case -quality comes later */
} else if (keymatch(arg, "restart", 1)) {
/* Restart interval in MCU rows (or in MCUs with 'b'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (lval < 0 || lval > 65535L)
usage();
if (ch == 'b' || ch == 'B')
cinfo->restart_interval = (UINT16) lval;
else
cinfo->restart_in_rows = (int) lval;
} else if (keymatch(arg, "sample", 2)) {
/* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */
usage();
set_sample_factors(cinfo, argv[argn]);
} else if (keymatch(arg, "smooth", 2)) {
/* Set input smoothing factor. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
if (val < 0 || val > 100)
usage();
cinfo->smoothing_factor = val;
} else if (keymatch(arg, "targa", 1)) {
/* Input file is Targa format. */
is_targa = TRUE;
} else {
usage(); /* bogus switch */
}
}
/* Post-switch-scanning cleanup */
if (qtablefile != NULL) /* process -qtables if it was present */
read_quant_tables(cinfo, qtablefile, q_scale_factor);
return argn; /* return index of next arg (file name) */
}
@@ -168,139 +609,125 @@ usage (char * progname)
* The main program.
*/
GLOBAL void
GLOBAL int
main (int argc, char **argv)
{
struct compress_info_struct cinfo;
struct compress_methods_struct c_methods;
struct external_methods_struct e_methods;
int c;
struct Compress_info_struct cinfo;
struct Compress_methods_struct c_methods;
struct External_methods_struct e_methods;
int file_index;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
/* Initialize the system-dependent method pointers. */
progname = argv[0];
/* Set up links to method structures. */
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 JPEG parameters. */
j_c_defaults(&cinfo, 75, FALSE); /* default quality level = 75 */
is_targa = FALSE;
/* Scan command line options, adjust parameters */
while ((c = egetopt(argc, argv, "IQ:Taod")) != 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);
/* Install, but don't yet enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = NULL;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#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 make force_baseline FALSE.
* This means non-baseline JPEG files can be created with low Q values.
* To ensure only baseline files are generated, pass TRUE instead.
*/
j_set_quality(&cinfo, val, FALSE);
}
break;
case 'T': /* Input file is Targa format. */
is_targa = TRUE;
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;
}
/* If -d appeared, print version identification */
if (e_methods.trace_level > 0)
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
/* Scan command line: set up compression parameters, find file names. */
/* Select the input and output files */
file_index = parse_switches(&cinfo, 0, argc, argv);
#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 */
cinfo.input_file = stdin; /* default input file */
cinfo.output_file = stdout; /* always the output file */
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);
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdin), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdout), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.output_file = stdout;
#endif
}
/* Figure out the input file format, and set up to read it. */
select_file_type(&cinfo);
#ifdef PROGRESS_REPORT
/* Start up progress display, unless trace output is on */
if (e_methods.trace_level == 0)
c_methods.progress_monitor = progress_monitor;
#endif
/* Do it to it! */
jpeg_compress(&cinfo);
/* Release memory. */
j_c_free_defaults(&cinfo);
#ifdef MEM_STATS
if (e_methods.trace_level > 0) /* Optional memory-usage statistics */
j_mem_stats();
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (e_methods.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(0);
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

View File

@@ -1,7 +1,7 @@
/*
* jcmaster.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -19,8 +19,8 @@ c_per_scan_method_selection (compress_info_ptr cinfo)
{
/* Edge expansion */
jselexpand(cinfo);
/* Subsampling of pixels */
jselsubsample(cinfo);
/* Downsampling of pixels */
jseldownsample(cinfo);
/* MCU extraction */
jselcmcu(cinfo);
}
@@ -36,7 +36,7 @@ c_initial_method_selection (compress_info_ptr cinfo)
/* Gamma and color space conversion */
jselccolor(cinfo);
/* Entropy encoding: either Huffman or arithmetic coding. */
#ifdef ARITH_CODING_SUPPORTED
#ifdef C_ARITH_CODING_SUPPORTED
jselcarithmetic(cinfo);
#else
cinfo->arith_code = FALSE; /* force Huffman mode */
@@ -71,7 +71,7 @@ initial_setup (compress_info_ptr cinfo)
}
/* Compute logical subsampled dimensions of components */
/* Compute logical downsampled 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
@@ -92,6 +92,10 @@ initial_setup (compress_info_ptr cinfo)
GLOBAL void
jpeg_compress (compress_info_ptr cinfo)
{
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
/* 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.
@@ -123,5 +127,7 @@ jpeg_compress (compress_info_ptr cinfo)
(*cinfo->methods->colorin_term) (cinfo);
(*cinfo->methods->input_term) (cinfo);
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
}

66
jcmcu.c
View File

@@ -1,7 +1,7 @@
/*
* jcmcu.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -32,7 +32,7 @@ static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
static const short ZAG[DCTSIZE2] = {
static const int 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,
@@ -58,53 +58,69 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col,
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
#if DCTSIZE != 8
register short elemc;
#endif
register short elemr;
register int 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;
*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;
{ register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
}
}
#endif
}
}
#ifdef DCT_ERR_STATS
memcpy((void *) svblock, (void *) block, SIZEOF(DCTBLOCK));
MEMCOPY(svblock, block, SIZEOF(DCTBLOCK));
#endif
j_fwd_dct(block);
{ register JCOEF temp;
register short i;
register QUANT_VAL qval;
register int i;
for (i = 0; i < DCTSIZE2; i++) {
qval = *quanttbl++;
temp = (JCOEF) block[ZAG[i]];
/* divide by *quanttbl, ensuring proper rounding */
/* Divide the coefficient value by qval, ensuring proper rounding.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
*
* In most files, at least half of the output values will be zero
* (at default quantization settings, more like three-quarters...)
* so we should ensure that this case is fast. On many machines,
* a comparison is enough cheaper than a divide to make a special test
* a win. Since both inputs will be nonnegative, we need only test
* for a < b to discover whether a/b is 0.
* If your machine's division is fast enough, define FAST_DIVIDE.
*/
#ifdef FAST_DIVIDE
#define DIVIDE_BY(a,b) a /= b
#else
#define DIVIDE_BY(a,b) (a >= b) ? (a /= b) : (a = 0)
#endif
if (temp < 0) {
temp = -temp;
temp += *quanttbl>>1;
temp /= *quanttbl;
temp += qval>>1; /* for rounding */
DIVIDE_BY(temp, qval);
temp = -temp;
} else {
temp += *quanttbl>>1;
temp /= *quanttbl;
temp += qval>>1; /* for rounding */
DIVIDE_BY(temp, qval);
}
*output_data++ = temp;
quanttbl++;
}
}
@@ -112,7 +128,7 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col,
j_rev_dct(block);
{ register int diff;
register short i;
register int i;
for (i = 0; i < DCTSIZE2; i++) {
diff = block[i] - svblock[i];

View File

@@ -1,7 +1,7 @@
/*
* jconfig.h
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -20,10 +20,23 @@
* predefined by such compilers.
*/
/*
* HAVE_STDC is tested below to see whether ANSI features are available.
* We avoid testing __STDC__ directly for arcane reasons of portability.
* (On some compilers, __STDC__ is only defined if a switch is given,
* but the switch also disables machine-specific features we need to get at.
* In that case, -DHAVE_STDC in the Makefile is a convenient solution.)
*/
#ifdef __STDC__ /* if compiler claims to be ANSI, believe it */
#define HAVE_STDC
#endif
/* Does your compiler support function prototypes? */
/* (If not, you also need to use ansi2knr, see SETUP) */
#ifdef __STDC__ /* ANSI C compilers always have prototypes */
#ifdef HAVE_STDC /* ANSI C compilers always have prototypes */
#define PROTO
#else
#ifdef __cplusplus /* So do C++ compilers */
@@ -34,7 +47,7 @@
/* Does your compiler support the declaration "unsigned char" ? */
/* How about "unsigned short" ? */
#ifdef __STDC__ /* ANSI C compilers must support both */
#ifdef HAVE_STDC /* ANSI C compilers must support both */
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
#endif
@@ -49,7 +62,6 @@
/* 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 */
@@ -64,7 +76,7 @@
/* 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 HAVE_STDC /* ANSI C and C++ compilers should know it. */
#ifndef __cplusplus
#define const
#endif
@@ -77,16 +89,12 @@
* "far" pointers and to be allocated with a special version of malloc.)
*/
#ifdef MSDOS /* Microsoft C and compatibles */
#ifdef MSDOS
#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
/* The next three 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.
*/
@@ -98,16 +106,25 @@
*/
#ifdef MSDOS /* two-file style is needed for PCs */
#define TWO_FILE_COMMANDLINE
#else
#ifdef __TURBOC__ /* Turbo C doesn't define MSDOS */
#ifndef USE_FDOPEN /* unless you have fdopen() or setmode() */
#ifndef USE_SETMODE
#define TWO_FILE_COMMANDLINE
#endif
#endif
#ifdef THINK_C /* needed for Macintosh too */
#endif
#ifdef THINK_C /* it's needed for Macintosh too */
#define TWO_FILE_COMMANDLINE
#endif
/* Define this if your system needs explicit cleanup of temporary files.
* This is crucial under MS-DOS, where the temporary "files" may be areas
* of extended memory; on most other systems it's not as important.
*/
#ifdef MSDOS
#define NEED_SIGNAL_CATCHER
#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
@@ -122,13 +139,14 @@
*/
/* If your compiler supports inline functions, define INLINE as
* the inline keyword; otherwise define it as empty.
/* 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. */
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
#define INLINE __inline__
#endif
#ifndef INLINE /* default is to define it as empty */
#define INLINE
#endif
@@ -163,18 +181,24 @@ typedef int boolean;
*/
/* 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? */
/* Encoder capability options: */
#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#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.) */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* 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 GIF_SUPPORTED /* GIF image file format */
/* #define RLE_SUPPORTED */ /* RLE image file format */
/* #define RLE_SUPPORTED */ /* RLE image file format (by default, no) */
#define PPM_SUPPORTED /* PPM/PGM image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#undef TIFF_SUPPORTED /* TIFF image file format (not yet impl.) */
@@ -190,6 +214,11 @@ typedef int boolean;
* 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!
* Note: if you select 12- or 16-bit precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
*/
#define EIGHT_BIT_SAMPLES
@@ -209,8 +238,6 @@ typedef int boolean;
/* First define the representation of a single pixel element value. */
#ifdef EIGHT_BIT_SAMPLES
#define BITS_IN_JSAMPLE 8
/* 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
@@ -236,6 +263,7 @@ typedef char JSAMPLE;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define BITS_IN_JSAMPLE 8
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
@@ -243,14 +271,13 @@ typedef char JSAMPLE;
#ifdef TWELVE_BIT_SAMPLES
#define BITS_IN_JSAMPLE 12
/* 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 BITS_IN_JSAMPLE 12
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
@@ -258,8 +285,6 @@ typedef short JSAMPLE;
#ifdef SIXTEEN_BIT_SAMPLES
#define BITS_IN_JSAMPLE 16
/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
@@ -278,6 +303,7 @@ typedef unsigned int JSAMPLE;
#endif /* HAVE_UNSIGNED_SHORT */
#define BITS_IN_JSAMPLE 16
#define MAXJSAMPLE 65535
#define CENTERJSAMPLE 32768

277
jcpipe.c
View File

@@ -1,7 +1,7 @@
/*
* jcpipe.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -30,15 +30,15 @@
/*
* About the data structures:
*
* The processing chunk size for subsampling is referred to in this file as
* The processing chunk size for downsampling 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
* any component after downsampling, 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
* and process Vk MCU rows in each burst of downsampling.
* To provide context for the downsampling 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
@@ -82,12 +82,12 @@ interleaved_scan_setup (compress_info_ptr cinfo)
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));
compptr->downsampled_width = jround_up(compptr->true_comp_width,
(long) (compptr->MCU_width*DCTSIZE));
compptr->downsampled_height = jround_up(compptr->true_comp_height,
(long) (compptr->MCU_height*DCTSIZE));
/* Sanity check */
if (compptr->subsampled_width !=
if (compptr->downsampled_width !=
(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
ERREXIT(cinfo->emethods, "I'm confused about the image width");
/* Prepare array describing MCU composition */
@@ -99,6 +99,13 @@ interleaved_scan_setup (compress_info_ptr cinfo)
}
}
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
}
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
@@ -115,18 +122,25 @@ noninterleaved_scan_setup (compress_info_ptr cinfo)
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,
compptr->downsampled_width = jround_up(compptr->true_comp_width,
(long) DCTSIZE);
compptr->downsampled_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;
cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE;
cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
}
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
@@ -135,7 +149,7 @@ noninterleaved_scan_setup (compress_info_ptr 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 */
/* Create a pre-downsampling data buffer having the desired structure */
/* (see comments at head of file) */
{
short ci, vs, i;
@@ -169,18 +183,17 @@ alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
}
#if 0 /* this routine not currently needed */
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 */
short ci;
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)));
(*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
/* Free the scrambled-order pointers */
(*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
}
@@ -190,20 +203,22 @@ free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
(*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
}
#endif
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). */
downsample (compress_info_ptr cinfo,
JSAMPIMAGE fullsize_data, JSAMPIMAGE sampled_data,
long fullsize_width,
short above, short current, short below, short out)
/* Do downsampling 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. */
/* out is the index of the target row group in sampled_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 */
JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */
short ci, vs, i;
vs = cinfo->max_v_samp_factor; /* row group height */
@@ -230,25 +245,27 @@ subsample (compress_info_ptr cinfo,
below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
}
(*cinfo->methods->subsample[ci])
(*cinfo->methods->downsample[ci])
(cinfo, (int) ci,
fullsize_width, (int) vs,
compptr->subsampled_width, (int) compptr->v_samp_factor,
compptr->downsampled_width, (int) compptr->v_samp_factor,
above_ptr,
fullsize_data[ci] + current * vs,
below_ptr,
subsampled_data[ci] + out * compptr->v_samp_factor);
sampled_data[ci] + out * compptr->v_samp_factor);
}
}
/* These vars are initialized by the pipeline controller for use by
/* These variables 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.
* row of whole_scan_MCUs as we can get without exceeding 32Kbytes per row.
* NOTE: the "arbitrary" constant here must not exceed MAX_ALLOC_CHUNK
* defined in jmemsys.h, which is 64K-epsilon in most DOS implementations.
*/
#define MAX_WHOLE_ROW_BLOCKS ((int) (65500 / SIZEOF(JBLOCK))) /* max blocks/row */
#define MAX_WHOLE_ROW_BLOCKS ((int) (32768L / 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 */
@@ -302,6 +319,8 @@ dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
next_index = MCUs_in_big_row;
for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
(*cinfo->methods->progress_monitor) (cinfo, mcurow,
cinfo->MCU_rows_in_scan);
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,
@@ -311,7 +330,7 @@ dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
}
#ifdef NEED_FAR_POINTERS
jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
(JBLOCKROW) MCU_data, /* note cast */
(JBLOCKROW) MCU_data, /* casts near to far pointer! */
(long) cinfo->blocks_in_MCU);
(*output_method) (cinfo, MCU_data);
#else
@@ -320,6 +339,8 @@ dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
next_index++;
}
}
cinfo->completed_passes++;
}
@@ -337,10 +358,10 @@ single_ccontroller (compress_info_ptr cinfo)
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) */
/* Work buffer for pre-downsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for subsampled data */
JSAMPIMAGE subsampled_data;
/* Work buffer for downsampled data */
JSAMPIMAGE sampled_data;
int rows_this_time;
short ci, whichss, i;
@@ -360,6 +381,7 @@ single_ccontroller (compress_info_ptr cinfo)
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
cinfo->total_passes++;
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
@@ -368,14 +390,14 @@ single_ccontroller (compress_info_ptr cinfo)
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before subsampling */
/* fullsize_data is sample data before downsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* subsampled_data is sample data after subsampling */
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
/* sampled_data is sample data after downsampling */
sampled_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,
sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].downsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
@@ -392,8 +414,8 @@ single_ccontroller (compress_info_ptr cinfo)
(*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->entropy_encode_init) (cinfo);
(*cinfo->methods->downsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
@@ -403,10 +425,13 @@ single_ccontroller (compress_info_ptr cinfo)
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
cinfo->image_height);
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. */
/* Then we have exactly DCTSIZE row groups for downsampling. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
@@ -417,61 +442,56 @@ single_ccontroller (compress_info_ptr cinfo)
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Subsample the data (all components) */
/* Downsample 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,
/* Downsample last row group of previous set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's downsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_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);
/* Downsample first row group of this set */
downsample(cinfo, fullsize_data[whichss], sampled_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);
/* Downsample first row group with dummy above-context */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Subsample second through next-to-last row groups of this set */
/* Downsample 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);
downsample(cinfo, fullsize_data[whichss], sampled_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 */
/* Downsample 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));
downsample(cinfo, fullsize_data[whichss], sampled_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,
(*cinfo->methods->extract_MCUs) (cinfo, sampled_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->downsample_term) (cinfo);
(*cinfo->methods->entropy_encode_term) (cinfo);
(*cinfo->methods->write_scan_trailer) (cinfo);
cinfo->completed_passes++;
/* 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);
/* (no work -- we let free_all release what's needful) */
}
@@ -490,10 +510,10 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
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) */
/* Work buffer for pre-downsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for subsampled data */
JSAMPIMAGE subsampled_data;
/* Work buffer for downsampled data */
JSAMPIMAGE sampled_data;
int rows_this_time;
int blocks_in_big_row;
short ci, whichss, i;
@@ -514,6 +534,7 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
cinfo->total_passes += 2; /* entropy encoder must add # passes it uses */
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
@@ -522,14 +543,14 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before subsampling */
/* fullsize_data is sample data before downsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* subsampled_data is sample data after subsampling */
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
/* sampled_data is sample data after downsampling */
sampled_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,
sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].downsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
@@ -555,7 +576,7 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
/* Do per-scan object init */
(*cinfo->methods->subsample_init) (cinfo);
(*cinfo->methods->downsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
@@ -566,10 +587,13 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
cinfo->image_height);
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. */
/* Then we have exactly DCTSIZE row groups for downsampling. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
@@ -580,51 +604,53 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Subsample the data (all components) */
/* Downsample 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,
/* Downsample last row group of previous set */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's downsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, sampled_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);
/* Downsample first row group of this set */
downsample(cinfo, fullsize_data[whichss], sampled_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);
/* Downsample first row group with dummy above-context */
downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Subsample second through next-to-last row groups of this set */
/* Downsample 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);
downsample(cinfo, fullsize_data[whichss], sampled_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 */
/* Downsample 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));
downsample(cinfo, fullsize_data[whichss], sampled_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,
(*cinfo->methods->extract_MCUs) (cinfo, sampled_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->downsample_term) (cinfo);
cinfo->completed_passes++;
(*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
@@ -633,20 +659,13 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
(*cinfo->methods->write_scan_header) (cinfo);
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
(*cinfo->methods->entropy_encoder_init) (cinfo);
(*cinfo->methods->entropy_encode_init) (cinfo);
dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
(*cinfo->methods->entropy_encoder_term) (cinfo);
(*cinfo->methods->entropy_encode_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);
/* (no work -- we let free_all release what's needful) */
}
#endif /* ENTROPY_OPT_SUPPORTED */
@@ -657,7 +676,7 @@ single_eopt_ccontroller (compress_info_ptr cinfo)
* with no optimization of entropy parameters.
*/
#ifdef MULTISCAN_FILES_SUPPORTED
#ifdef C_MULTISCAN_FILES_SUPPORTED
METHODDEF void
multi_ccontroller (compress_info_ptr cinfo)
@@ -665,7 +684,7 @@ multi_ccontroller (compress_info_ptr cinfo)
ERREXIT(cinfo->emethods, "Not implemented yet");
}
#endif /* MULTISCAN_FILES_SUPPORTED */
#endif /* C_MULTISCAN_FILES_SUPPORTED */
/*
@@ -673,7 +692,7 @@ multi_ccontroller (compress_info_ptr cinfo)
* with optimization of entropy parameters.
*/
#ifdef MULTISCAN_FILES_SUPPORTED
#ifdef C_MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF void
@@ -683,7 +702,7 @@ multi_eopt_ccontroller (compress_info_ptr cinfo)
}
#endif /* ENTROPY_OPT_SUPPORTED */
#endif /* MULTISCAN_FILES_SUPPORTED */
#endif /* C_MULTISCAN_FILES_SUPPORTED */
/*
@@ -703,7 +722,7 @@ jselcpipeline (compress_info_ptr cinfo)
cinfo->methods->c_pipeline_controller = single_ccontroller;
} else {
/* multiple scans needed */
#ifdef MULTISCAN_FILES_SUPPORTED
#ifdef C_MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->optimize_coding)
cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;

View File

@@ -1,54 +1,76 @@
/*
* jcsample.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* This file contains downsampling routines.
* These routines are invoked via the downsample and
* downsample_init/term methods.
*
* An excellent reference for image resampling is
* Digital Image Warping, George Wolberg, 1990.
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*
* The downsampling algorithm used here is a simple average of the source
* pixels covered by the output pixel. The hi-falutin sampling literature
* refers to this as a "box filter". In general the characteristics of a box
* filter are not very good, but for the specific cases we normally use (1:1
* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
* nearly so bad. If you intend to use other sampling ratios, you'd be well
* advised to improve this code.
*
* A simple input-smoothing capability is provided. This is mainly intended
* for cleaning up color-dithered GIF input files (if you find it inadequate,
* we suggest using an external filtering program such as pnmconvol). When
* enabled, each input pixel P is replaced by a weighted sum of itself and its
* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
* where SF = (smoothing_factor / 1024).
* Currently, smoothing is only supported for 2h2v sampling factors.
*/
#include "jinclude.h"
/*
* Initialize for subsampling a scan.
* Initialize for downsampling a scan.
*/
METHODDEF void
subsample_init (compress_info_ptr cinfo)
downsample_init (compress_info_ptr cinfo)
{
/* no work for now */
}
/*
* Subsample pixel values of a single component.
* This version only handles integral sampling ratios.
* Downsample pixel values of a single component.
* This version handles arbitrary integral sampling ratios, without smoothing.
* Note that this version is not actually used for customary 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)
int_downsample (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;
long outcol, outcol_h; /* outcol_h == outcol*h_expand */
JSAMPROW inptr, outptr;
INT32 outvalue;
/* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
#ifdef DEBUG /* 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");
ERREXIT(cinfo->emethods, "Bogus downsample parameters");
#endif
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
@@ -58,10 +80,11 @@ subsample (compress_info_ptr cinfo, int which_component,
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
outptr = output_data[outrow];
for (outcol = 0; outcol < output_cols; outcol++) {
for (outcol = 0, outcol_h = 0; outcol < output_cols;
outcol++, outcol_h += h_expand) {
outvalue = 0;
for (v = 0; v < v_expand; v++) {
inptr = input_data[inrow+v] + (outcol*h_expand);
inptr = input_data[inrow+v] + outcol_h;
for (h = 0; h < h_expand; h++) {
outvalue += (INT32) GETJSAMPLE(*inptr++);
}
@@ -74,30 +97,307 @@ subsample (compress_info_ptr cinfo, int which_component,
/*
* Subsample pixel values of a single component.
* This version handles the special case of a full-size component.
* Downsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
* without smoothing.
*/
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)
h2v1_downsample (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 */
int outrow;
long outcol;
register JSAMPROW inptr, outptr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
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 downsample parameters");
#endif
for (outrow = 0; outrow < output_rows; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ 1) >> 1);
inptr += 2;
}
}
}
/*
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* without smoothing.
*/
METHODDEF void
h2v2_downsample (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)
{
int inrow, outrow;
long outcol;
register JSAMPROW inptr0, inptr1, outptr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
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 downsample parameters");
#endif
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ 2) >> 2);
inptr0 += 2; inptr1 += 2;
}
inrow += 2;
}
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* without smoothing.
*/
METHODDEF void
fullsize_downsample (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)
{
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
}
#ifdef INPUT_SMOOTHING_SUPPORTED
/*
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* with smoothing.
*/
METHODDEF void
h2v2_smooth_downsample (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)
{
int inrow, outrow;
long colctr;
register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
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 downsample parameters");
#endif
/* We don't bother to form the individual "smoothed" input pixel values;
* we can directly compute the output which is the average of the four
* smoothed values. Each of the four member pixels contributes a fraction
* (1-8*SF) to its own smoothed image and a fraction SF to each of the three
* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
* output. The four corner-adjacent neighbor pixels contribute a fraction
* SF to just one smoothed pixel, or SF/4 to the final output; while the
* eight edge-adjacent neighbors contribute SF to each of two smoothed
* pixels, or SF/2 overall. In order to use integer arithmetic, these
* factors are scaled by 2^16 = 65536.
* Also recall that SF = smoothing_factor / 1024.
*/
memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
if (inrow == 0)
above_ptr = above[input_rows-1];
else
above_ptr = input_data[inrow-1];
if (inrow >= input_rows-2)
below_ptr = below[0];
else
below_ptr = input_data[inrow+2];
/* Special case for first column: pretend column -1 is same as column 0 */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
neighsum += neighsum;
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
/* sum of pixels directly mapped to this output element */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
/* sum of edge-neighbor pixels */
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
/* The edge-neighbors count twice as much as corner-neighbors */
neighsum += neighsum;
/* Add in the corner-neighbors */
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
/* form final output scaled up by 2^16 */
membersum = membersum * memberscale + neighsum * neighscale;
/* round, descale and output it */
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
neighsum += neighsum;
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
inrow += 2;
}
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* with smoothing.
*/
METHODDEF void
fullsize_smooth_downsample (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)
{
int outrow;
long colctr;
register JSAMPROW inptr, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
int colsum, lastcolsum, nextcolsum;
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
/* Each of the eight neighbor pixels contributes a fraction SF to the
* smoothed pixel, while the main pixel contributes (1-8*SF). In order
* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
* Also recall that SF = smoothing_factor / 1024.
*/
memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
for (outrow = 0; outrow < output_rows; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
if (outrow == 0)
above_ptr = above[input_rows-1];
else
above_ptr = input_data[outrow-1];
if (outrow >= input_rows-1)
below_ptr = below[0];
else
below_ptr = input_data[outrow+1];
/* Special case for first column */
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
GETJSAMPLE(*inptr);
membersum = GETJSAMPLE(*inptr++);
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
neighsum = colsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
lastcolsum = colsum; colsum = nextcolsum;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
membersum = GETJSAMPLE(*inptr++);
above_ptr++; below_ptr++;
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
lastcolsum = colsum; colsum = nextcolsum;
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + colsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
}
}
#endif /* INPUT_SMOOTHING_SUPPORTED */
/*
* Clean up after a scan.
*/
METHODDEF void
subsample_term (compress_info_ptr cinfo)
downsample_term (compress_info_ptr cinfo)
{
/* no work for now */
}
@@ -105,31 +405,56 @@ subsample_term (compress_info_ptr cinfo)
/*
* The method selection routine for subsampling.
* The method selection routine for downsampling.
* Note that we must select a routine for each component.
*/
GLOBAL void
jselsubsample (compress_info_ptr cinfo)
jseldownsample (compress_info_ptr cinfo)
{
short ci;
jpeg_component_info * compptr;
boolean smoothok = TRUE;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
ERREXIT(cinfo->emethods, "CCIR601 downsampling 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");
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor)
cinfo->methods->downsample[ci] = fullsize_smooth_downsample;
else
#endif
cinfo->methods->downsample[ci] = fullsize_downsample;
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
smoothok = FALSE;
cinfo->methods->downsample[ci] = h2v1_downsample;
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor)
cinfo->methods->downsample[ci] = h2v2_smooth_downsample;
else
#endif
cinfo->methods->downsample[ci] = h2v2_downsample;
} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
smoothok = FALSE;
cinfo->methods->downsample[ci] = int_downsample;
} else
ERREXIT(cinfo->emethods, "Fractional downsampling not implemented yet");
}
cinfo->methods->subsample_init = subsample_init;
cinfo->methods->subsample_term = subsample_term;
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor && !smoothok)
TRACEMS(cinfo->emethods, 0,
"Smoothing not supported with nonstandard sampling ratios");
#endif
cinfo->methods->downsample_init = downsample_init;
cinfo->methods->downsample_term = downsample_term;
}

View File

@@ -1,18 +1,18 @@
/*
* jdarith.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* and entropy_decode_init/term.
*/
#include "jinclude.h"
#ifdef ARITH_CODING_SUPPORTED
#ifdef D_ARITH_CODING_SUPPORTED
/*
@@ -39,4 +39,4 @@ jseldarithmetic (decompress_info_ptr cinfo)
}
}
#endif /* ARITH_CODING_SUPPORTED */
#endif /* D_ARITH_CODING_SUPPORTED */

210
jdcolor.c
View File

@@ -1,7 +1,7 @@
/*
* jdcolor.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -13,34 +13,112 @@
#include "jinclude.h"
/**************** YCbCr -> RGB conversion: most common case **************/
/*
* 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.
* The conversion equations to be implemented are therefore
* R = Y + 1.40200 * Cr
* G = Y - 0.34414 * Cb - 0.71414 * Cr
* B = Y + 1.77200 * Cb
* where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
*
* To avoid floating-point arithmetic, we represent the fractional constants
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
* the products by 2^16, with appropriate rounding, to get the correct answer.
* Notice that Y, being an integral input, does not contribute any fraction
* so it need not participate in the rounding.
*
* For even more speed, we avoid doing any multiplications in the inner loop
* by precalculating the constants times Cb and Cr for all possible values.
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
* for 12-bit samples it is still acceptable. It's not very reasonable for
* 16-bit samples, but if you want lossless storage you shouldn't be changing
* colorspace anyway.
* The Cr=>R and Cb=>B values can be rounded to integers in advance; the
* values for the G calculation are left scaled up, since we must add them
* together before rounding.
*/
#ifdef SIXTEEN_BIT_SAMPLES
#define SCALEBITS 14 /* avoid overflow */
#else
#define SCALEBITS 16 /* speedier right-shift on some machines */
#endif
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
static int * Cr_r_tab; /* => table for Cr to R conversion */
static int * Cb_b_tab; /* => table for Cb to B conversion */
static INT32 * Cr_g_tab; /* => table for Cr to G conversion */
static INT32 * Cb_g_tab; /* => table for Cb to G conversion */
/*
* Initialize for colorspace conversion.
*/
METHODDEF void
colorout_init (decompress_info_ptr cinfo)
ycc_rgb_init (decompress_info_ptr cinfo)
{
/* no work needed */
INT32 i, x2;
SHIFT_TEMPS
Cr_r_tab = (int *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(int));
Cb_b_tab = (int *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(int));
Cr_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
Cb_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
for (i = 0; i <= MAXJSAMPLE; i++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
/* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */
x2 = 2*i - MAXJSAMPLE; /* twice x */
/* Cr=>R value is nearest int to 1.40200 * x */
Cr_r_tab[i] = (int)
RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS);
/* Cb=>B value is nearest int to 1.77200 * x */
Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
Cr_g_tab[i] = (- FIX(0.71414/2)) * x2;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF;
}
}
/*
* 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,
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
register INT32 y, u, v, x;
#ifdef SIXTEEN_BIT_SAMPLES
register INT32 y;
register UINT16 cb, cr;
#else
register int y, cb, cr;
#endif
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr0, outptr1, outptr2;
register long col;
register long width = cinfo->image_width;
register int row;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
register int * Crrtab = Cr_r_tab;
register int * Cbbtab = Cb_b_tab;
register INT32 * Crgtab = Cr_g_tab;
register INT32 * Cbgtab = Cb_g_tab;
int row;
SHIFT_TEMPS
for (row = 0; row < num_rows; row++) {
inptr0 = input_data[0][row];
@@ -49,45 +127,63 @@ ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows,
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;
for (col = 0; col < num_cols; col++) {
y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
/* 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++ = (JSAMPLE) (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++ = (JSAMPLE) (x >> 10);
x = y + 1815*u + 512; /* blue */
if (x < 0) x = 0;
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
*outptr2++ = (JSAMPLE) (x >> 10);
outptr0[col] = range_limit[y + Crrtab[cr]]; /* red */
outptr1[col] = range_limit[y + /* green */
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
outptr2[col] = range_limit[y + Cbbtab[cb]]; /* blue */
}
}
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
ycc_rgb_term (decompress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/**************** Cases other than YCbCr -> RGB **************/
/*
* Initialize for colorspace conversion.
*/
METHODDEF void
null_init (decompress_info_ptr cinfo)
/* colorout_init for cases where no setup is needed */
{
/* no work needed */
}
/*
* Color conversion for no colorspace change: just copy the data.
*/
METHODDEF void
null_convert (decompress_info_ptr cinfo, int num_rows,
null_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
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);
num_rows, num_cols);
}
}
@@ -99,11 +195,11 @@ null_convert (decompress_info_ptr cinfo, int num_rows,
*/
METHODDEF void
grayscale_convert (decompress_info_ptr cinfo, int num_rows,
grayscale_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
num_rows, cinfo->image_width);
num_rows, num_cols);
}
@@ -112,12 +208,14 @@ grayscale_convert (decompress_info_ptr cinfo, int num_rows,
*/
METHODDEF void
colorout_term (decompress_info_ptr cinfo)
null_term (decompress_info_ptr cinfo)
/* colorout_term for cases where no teardown is needed */
{
/* no work needed */
}
/*
* The method selection routine for output colorspace conversion.
*/
@@ -125,6 +223,8 @@ colorout_term (decompress_info_ptr cinfo)
GLOBAL void
jseldcolor (decompress_info_ptr cinfo)
{
int ci;
/* Make sure num_components agrees with jpeg_color_space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
@@ -133,8 +233,8 @@ jseldcolor (decompress_info_ptr cinfo)
break;
case CS_RGB:
case CS_YIQ:
case CS_YCbCr:
case CS_YIQ:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
break;
@@ -149,38 +249,49 @@ jseldcolor (decompress_info_ptr cinfo)
break;
}
/* Set color_out_comps and conversion method based on requested space */
/* Set color_out_comps and conversion method based on requested space. */
/* Also clear the component_needed flags for any unused components, */
/* so that earlier pipeline stages can avoid useless computation. */
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->jpeg_color_space == CS_YIQ) {
cinfo->methods->color_convert = grayscale_convert;
else
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
/* For color->grayscale conversion, only the Y (0) component is needed */
for (ci = 1; ci < cinfo->num_components; ci++)
cinfo->cur_comp_info[ci]->component_needed = FALSE;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
break;
case CS_RGB:
cinfo->color_out_comps = 3;
if (cinfo->jpeg_color_space == CS_YCbCr)
if (cinfo->jpeg_color_space == CS_YCbCr) {
cinfo->methods->color_convert = ycc_rgb_convert;
else if (cinfo->jpeg_color_space == CS_RGB)
cinfo->methods->colorout_init = ycc_rgb_init;
cinfo->methods->colorout_term = ycc_rgb_term;
} 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
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
break;
default:
ERREXIT(cinfo->emethods, "Unsupported output colorspace");
/* Permit null conversion from CMYK or YCbCr to same output space */
if (cinfo->out_color_space == cinfo->jpeg_color_space) {
cinfo->color_out_comps = cinfo->num_components;
cinfo->methods->color_convert = null_convert;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
} else /* unsupported non-null conversion */
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
break;
}
@@ -188,7 +299,4 @@ jseldcolor (decompress_info_ptr cinfo)
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;
}

View File

@@ -1,7 +1,7 @@
/*
* jddeflts.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -13,19 +13,69 @@
#include "jinclude.h"
/* Default do-nothing progress monitoring routine.
* This can be overridden by a user interface that wishes to
* provide progress monitoring; just set methods->progress_monitor
* after j_d_defaults is done. The routine will be called periodically
* during the decompression process.
*
* During any one pass, loopcounter increases from 0 up to (not including)
* looplimit; the step size is not necessarily 1. Both the step size and
* the limit may differ between passes. The expected total number of passes
* is in cinfo->total_passes, and the number of passes already completed is
* in cinfo->completed_passes. Thus the fraction of work completed may be
* estimated as
* completed_passes + (loopcounter/looplimit)
* ------------------------------------------
* total_passes
* ignoring the fact that the passes may not be equal amounts of work.
*
* When decompressing, the total_passes figure is an estimate that may be
* on the high side; completed_passes will jump by more than one if some
* passes are skipped.
*/
METHODDEF void
progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit)
{
/* do nothing */
}
/* Default comment-block processing routine.
* This can be overridden by an application that wishes to examine
* COM blocks found in the JPEG file. The default routine does nothing.
* CAUTION: the comment processing routine MUST call JGETC() exactly
* comment_length times to read the comment data, whether it intends
* to do anything with the data or not!
* Keep in mind that (a) there may be more than one COM block in a file;
* (b) there's no guarantee that what's in the block is ASCII data.
*/
METHODDEF void
process_comment (decompress_info_ptr cinfo, long comment_length)
{
while (comment_length-- > 0) {
(void) JGETC(cinfo);
}
}
/*
* Reload the input buffer after it's been emptied, and return the next byte.
* See the JGETC macro for calling conditions.
* See the JGETC macro for calling conditions. Note in particular that
* read_jpeg_data may NOT return EOF. If no more data is available, it must
* exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker).
* In the present implementation, we insert an EOI marker; this might not be
* appropriate for non-JFIF file formats, but it usually allows us to handle
* a truncated JFIF file.
*
* This routine is used only if the system-dependent user interface passes
* standard_buffering = TRUE to j_d_defaults. Otherwise, the UI must supply
* a corresponding routine. Note that in any case, this routine is likely
* to be used only for JFIF or similar serial-access JPEG file formats.
* The input file control module for a random-access format such as TIFF/JPEG
* would need to override the read_jpeg_data method with its own routine.
*
* This routine would need to be replaced if reading JPEG data from something
* other than a stdio stream.
* This routine can be overridden by the system-dependent user interface,
* in case the data source is not a stdio stream or some other special
* condition applies. Note, however, that this capability only applies for
* JFIF or similar serial-access JPEG file formats. The input file control
* module for a random-access format such as TIFF/JPEG would most likely
* override the read_jpeg_data method with its own routine.
*/
METHODDEF int
@@ -33,12 +83,16 @@ read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
cinfo->bytes_in_buffer = (int) FREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
if (cinfo->bytes_in_buffer <= 0)
ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
if (cinfo->bytes_in_buffer <= 0) {
WARNMS(cinfo->emethods, "Premature EOF in JPEG file");
cinfo->next_input_byte[0] = (char) 0xFF;
cinfo->next_input_byte[1] = (char) 0xD9; /* EOI marker */
cinfo->bytes_in_buffer = 2;
}
return JGETC(cinfo);
}
@@ -53,19 +107,43 @@ read_jpeg_data (decompress_info_ptr cinfo)
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*
* standard_buffering should be TRUE if the JPEG data is to come from
* a stdio stream and the user interface isn't interested in changing
* the normal input-buffering logic. If FALSE is passed, the user
* interface must provide its own read_jpeg_data method and must
* set up its own input buffer. (Alternately, you can pass TRUE to
* let the buffer be allocated here, then override read_jpeg_data with
* your own routine.)
* standard_buffering should be TRUE to cause an input buffer to be allocated
* (the normal case); if FALSE, the user interface must provide a buffer.
* This option is most useful in the case that the buffer must not be freed
* at the end of an image. (For example, when reading a sequence of images
* from a single file, the remaining data in the buffer represents the
* start of the next image and mustn't be discarded.) To handle this,
* allocate the input buffer yourself at startup, WITHOUT using alloc_small
* (probably a direct call to malloc() instead). Then pass FALSE on each
* call to j_d_defaults to ensure the buffer state is not modified.
*
* If the source of the JPEG data is not a stdio stream, override the
* read_jpeg_data method with your own routine after calling j_d_defaults.
* You can still use the standard buffer if it's appropriate.
*
* CAUTION: if you want to decompress multiple images per run, it's necessary
* to call j_d_defaults before *each* call to jpeg_decompress, since subsidiary
* structures like the quantization tables are automatically freed during
* cleanup.
*/
GLOBAL void
j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
/* NB: the external methods must already be set up. */
{
short i;
/* Initialize pointers as needed to mark stuff unallocated. */
/* Outer application may fill in default tables for abbreviated files... */
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->colormap = NULL;
/* Default to RGB output */
/* UI can override by changing out_color_space */
cinfo->out_color_space = CS_RGB;
@@ -81,7 +159,7 @@ j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
cinfo->quantize_colors = FALSE;
/* but set reasonable default parameters for quantization, */
/* so that turning on quantize_colors is sufficient to do something useful */
cinfo->two_pass_quantize = FALSE; /* may change to TRUE later */
cinfo->two_pass_quantize = TRUE;
cinfo->use_dithering = TRUE;
cinfo->desired_number_of_colors = 256;
@@ -89,29 +167,19 @@ j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
cinfo->do_block_smoothing = FALSE;
cinfo->do_pixel_smoothing = FALSE;
/* Allocate memory for input buffer, unless outer application provides it. */
if (standard_buffering) {
/* 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 */
/* Install standard buffer-reloading method. */
cinfo->methods->read_jpeg_data = read_jpeg_data;
}
}
/* This routine releases storage allocated by j_d_defaults.
* Note that freeing the method pointer structs and the decompress_info_struct
* itself are the responsibility of the user interface.
*
* standard_buffering must agree with what was passed to j_d_defaults.
*/
GLOBAL void
j_d_free_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
{
if (standard_buffering) {
(*cinfo->emethods->free_small) ((void *) cinfo->input_buffer);
}
/* Install standard buffer-reloading method (outer code may override). */
cinfo->methods->read_jpeg_data = read_jpeg_data;
/* Install default do-nothing progress monitoring method. */
cinfo->methods->progress_monitor = progress_monitor;
/* Install default comment-block processing method. */
cinfo->methods->process_comment = process_comment;
}

404
jdhuff.c
View File

@@ -1,13 +1,13 @@
/*
* jdhuff.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
* and entropy_decode_init/term.
*/
#include "jinclude.h"
@@ -19,18 +19,19 @@ static decompress_info_ptr dcinfo;
static INT32 get_buffer; /* current bit-extraction buffer */
static int bits_left; /* # of unused bits in it */
static boolean printed_eod; /* flag to suppress multiple end-of-data msgs */
LOCAL void
fix_huff_tbl (HUFF_TBL * htbl)
/* Compute derived values for a Huffman table */
{
int p, i, l, lastp, si;
int p, i, l, si;
int lookbits, ctr;
char huffsize[257];
UINT16 huffcode[257];
UINT16 code;
/* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
/* Figure C.1: make table of Huffman code length for each symbol */
/* Note that this is in code-length order. */
p = 0;
@@ -39,9 +40,8 @@ fix_huff_tbl (HUFF_TBL * htbl)
huffsize[p++] = (char) l;
}
huffsize[p] = 0;
lastp = p;
/* Figure 7.3.5.4.2.2: generate the codes themselves */
/* Figure C.2: generate the codes themselves */
/* Note that this is in code-length order. */
code = 0;
@@ -55,142 +55,230 @@ fix_huff_tbl (HUFF_TBL * htbl)
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 */
/* Figure F.15: generate decoding tables for bit-sequential decoding */
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 */
htbl->priv.dec.valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
htbl->priv.dec.mincode[l] = huffcode[p]; /* minimum code of length l */
p += htbl->bits[l];
htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
htbl->priv.dec.maxcode[l] = huffcode[p-1]; /* maximum code of length l */
} else {
htbl->maxcode[l] = -1;
htbl->priv.dec.maxcode[l] = -1; /* -1 if no codes of this length */
}
}
htbl->priv.dec.maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
/* Compute lookahead tables to speed up decoding.
* First we set all the table entries to 0, indicating "too long";
* then we iterate through the Huffman codes that are short enough and
* fill in all the entries that correspond to bit sequences starting
* with that code.
*/
MEMZERO(htbl->priv.dec.look_nbits, SIZEOF(htbl->priv.dec.look_nbits));
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
htbl->priv.dec.look_nbits[lookbits] = l;
htbl->priv.dec.look_sym[lookbits] = htbl->huffval[p];
lookbits++;
}
}
}
htbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
}
/* Extract the next N bits from the input stream (N <= 15) */
/*
* Code for extracting the next N bits from the input stream.
* (N never exceeds 15 for JPEG data.)
* This needs to go as fast as possible!
*
* We read source bytes into get_buffer and dole out bits as needed.
* If get_buffer already contains enough bits, they are fetched in-line
* by the macros check_bit_buffer and get_bits. When there aren't enough
* bits, fill_bit_buffer is called; it will attempt to fill get_buffer to
* the "high water mark" (not just to the number of bits needed; this reduces
* the function-call overhead cost of entering fill_bit_buffer).
* On return, fill_bit_buffer guarantees that get_buffer contains at least
* the requested number of bits --- dummy zeroes are inserted if necessary.
*
* On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
* of get_buffer to be used. (On machines with wider words, an even larger
* buffer could be used.) However, on some machines 32-bit shifts are
* relatively slow and take time proportional to the number of places shifted.
* (This is true with most PC compilers, for instance.) In this case it may
* be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
* average shift distance at the cost of more calls to fill_bit_buffer.
*/
LOCAL int
get_bits (int nbits)
#ifdef SLOW_SHIFT_32
#define MIN_GET_BITS 15 /* minimum allowable value */
#else
#define MIN_GET_BITS 25 /* max value for 32-bit get_buffer */
#endif
LOCAL void
fill_bit_buffer (int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
int result;
while (nbits > bits_left) {
int c = JGETC(dcinfo);
/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
/* (It is assumed that no request will be for more than that many bits.) */
while (bits_left < MIN_GET_BITS) {
register int c = JGETC(dcinfo);
get_buffer <<= 8;
get_buffer |= 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);
if (c == 0xFF) {
int c2 = JGETC(dcinfo);
if (c2 != 0) {
/* Oops, it's actually a marker indicating end of compressed data. */
/* Better put it back for use later */
JUNGETC(c2,dcinfo);
JUNGETC(c,dcinfo);
/* There should be enough bits still left in the data segment; */
/* if so, just break out of the while loop. */
if (bits_left >= nbits)
break;
/* Uh-oh. Report corrupted data to user and stuff zeroes into
* the data stream, so that we can produce some kind of image.
* Note that this will be repeated for each byte demanded for the
* rest of the segment; this is a bit slow but not unreasonably so.
* The main thing is to avoid getting a zillion warnings, hence
* we use a flag to ensure that only one warning appears.
*/
if (! printed_eod) {
WARNMS(dcinfo->emethods, "Corrupt JPEG data: premature end of data segment");
printed_eod = TRUE;
}
c = 0; /* insert a zero byte into bit buffer */
}
}
/* OK, load c into get_buffer */
get_buffer = (get_buffer << 8) | c;
bits_left += 8;
}
bits_left -= nbits;
result = ((int) (get_buffer >> bits_left)) & ((1 << nbits) - 1);
return result;
}
/* Macro to make things go at some speed! */
#define get_bit() (bits_left ? \
((int) (get_buffer >> (--bits_left))) & 1 : \
get_bits(1))
/*
* These macros provide the in-line portion of bit fetching.
* Correct usage is:
* check_bit_buffer(n); ensure there are N bits in get_buffer
* val = get_bits(n); fetch N bits
* The value n should be a simple variable, not an expression, because it
* is evaluated multiple times.
* peek_bits() fetches next N bits without removing them from the buffer.
*/
#define check_bit_buffer(nbits) \
{ if (bits_left < (nbits)) fill_bit_buffer(nbits); }
#define get_bits(nbits) \
(((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
#define peek_bits(nbits) \
(((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
/* Figure 13.4.2.3.2: extract next coded symbol from input stream */
/*
* Routines to extract next Huffman-coded symbol from input bit stream.
* We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
* without looping. Usually, more than 95% of the Huffman codes will be 8
* or fewer bits long. The few overlength codes are handled with a loop.
* The primary case is made a macro for speed reasons; the secondary
* routine slow_DECODE is rarely entered and need not be inline code.
*
* Notes about the huff_DECODE macro:
* 1. The first if-test is coded to call fill_bit_buffer only when necessary.
* 2. If the lookahead succeeds, we need only decrement bits_left to remove
* the proper number of bits from get_buffer.
* 3. If the lookahead table contains no entry, the next code must be
* more than HUFF_LOOKAHEAD bits long.
* 4. Near the end of the data segment, we may fail to get enough bits
* for a lookahead. In that case, we do it the hard way.
*/
#define huff_DECODE(htbl,result) \
{ register int nb, look; \
if (bits_left >= HUFF_LOOKAHEAD || \
(fill_bit_buffer(0), bits_left >= HUFF_LOOKAHEAD)) { \
look = peek_bits(HUFF_LOOKAHEAD); \
if ((nb = htbl->priv.dec.look_nbits[look]) != 0) { \
bits_left -= nb; \
result = htbl->priv.dec.look_sym[look]; \
} else \
result = slow_DECODE(htbl, HUFF_LOOKAHEAD+1); \
} else \
result = slow_DECODE(htbl, 1); \
}
LOCAL int
huff_DECODE (HUFF_TBL * htbl)
slow_DECODE (HUFF_TBL * htbl, int min_bits)
{
int l, p;
INT32 code;
code = get_bit();
l = 1;
while (code > htbl->maxcode[l]) {
code = (code << 1) + get_bit();
register int l = min_bits;
register INT32 code;
/* huff_DECODE has determined that the code is at least min_bits */
/* bits long, so fetch that many bits in one swoop. */
check_bit_buffer(l);
code = get_bits(l);
/* Collect the rest of the Huffman code one bit at a time. */
/* This is per Figure F.16 in the JPEG spec. */
while (code > htbl->priv.dec.maxcode[l]) {
code <<= 1;
check_bit_buffer(1);
code |= get_bits(1);
l++;
}
/* With garbage input we may reach the sentinel value l = 17. */
if (l > 16) {
ERREXIT(dcinfo->emethods, "Corrupted data in JPEG file");
WARNMS(dcinfo->emethods, "Corrupt JPEG data: bad Huffman code");
return 0; /* fake a zero as the safest result */
}
p = (int) (htbl->valptr[l] + (code - htbl->mincode[l]));
return (int) htbl->huffval[p];
return htbl->huffval[ htbl->priv.dec.valptr[l] +
((int) (code - htbl->priv.dec.mincode[l])) ];
}
/* Figure 13.4.2.1.1: extend sign bit */
/* Figure F.12: extend sign bit.
* On some machines, a shift and add will be faster than a table lookup.
*/
/* NB: on some compilers this will only work for s > 0 */
#ifdef AVOID_TABLES
#define huff_EXTEND(x, s) ((x) < (1 << ((s)-1)) ? \
(x) + (-1 << (s)) + 1 : \
(x))
#define huff_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
#else
/* Decode a single block's worth of coefficients */
/* Note that only the difference is returned for the DC coefficient */
#define huff_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
LOCAL void
decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
{
int s, k, r, n;
static const int extend_test[16] = /* entry n is 2**(n-1) */
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
/* zero out the coefficient block */
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
MEMZERO((void *) block, SIZEOF(JBLOCK));
/* Section 13.4.2.1: decode the DC coefficient difference */
s = huff_DECODE(dctbl);
if (s) {
r = get_bits(s);
s = huff_EXTEND(r, s);
}
block[0] = 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 += n;
r = get_bits(s);
block[k] = huff_EXTEND(r, s);
} else {
if (n != 15)
break;
k += 15;
}
}
}
#endif /* AVOID_TABLES */
/*
@@ -199,7 +287,7 @@ decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
*/
METHODDEF void
huff_decoder_init (decompress_info_ptr cinfo)
decoder_init (decompress_info_ptr cinfo)
{
short ci;
jpeg_component_info * compptr;
@@ -207,6 +295,7 @@ huff_decoder_init (decompress_info_ptr cinfo)
/* Initialize static variables */
dcinfo = cinfo;
bits_left = 0;
printed_eod = FALSE;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
@@ -238,30 +327,33 @@ process_restart (decompress_info_ptr cinfo)
int c, nbytes;
short ci;
/* Throw away any partial unread byte */
/* Throw away any unused bits remaining in bit buffer */
nbytes = bits_left / 8; /* count any full bytes loaded into buffer */
bits_left = 0;
printed_eod = FALSE; /* next segment can get another warning */
/* 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++;
/* we don't increment nbytes here since extra FFs are legal */
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 != 1)
WARNMS2(cinfo->emethods,
"Corrupt JPEG data: %d extraneous bytes before marker 0x%02x",
nbytes-1, c);
if (nbytes != 2)
TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before RST%d",
nbytes-2, cinfo->next_restart_num);
else
if (c != (RST0 + cinfo->next_restart_num)) {
/* Uh-oh, the restart markers have been messed up too. */
/* Let the file-format module try to figure out how to resync. */
(*cinfo->methods->resync_to_restart) (cinfo, c);
} else
TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num);
/* Re-initialize DC predictions to 0 */
@@ -270,19 +362,49 @@ process_restart (decompress_info_ptr cinfo)
/* Update restart state */
cinfo->restarts_to_go = cinfo->restart_interval;
cinfo->next_restart_num++;
cinfo->next_restart_num &= 7;
cinfo->next_restart_num = (cinfo->next_restart_num + 1) & 7;
}
/* ZAG[i] is the natural-order position of the i'th element of zigzag order.
* If the incoming data is corrupted, decode_mcu could attempt to
* reference values beyond the end of the array. To avoid a wild store,
* we put some extra zeroes after the real entries.
*/
static const short ZAG[DCTSIZE2+16] = {
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,
0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
0, 0, 0, 0, 0, 0, 0, 0
};
/*
* Decode and return one MCU's worth of Huffman-compressed coefficients.
* This routine also handles quantization descaling and zigzag reordering
* of coefficient values.
*
* The i'th block of the MCU is stored into the block pointed to by
* MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
* (Wholesale zeroing is usually a little faster than retail...)
*/
METHODDEF void
huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data)
{
register int s, k, r;
short blkn, ci;
register JBLOCKROW block;
register QUANT_TBL_PTR quanttbl;
HUFF_TBL *dctbl;
HUFF_TBL *actbl;
jpeg_component_info * compptr;
/* Account for restart interval, process restart marker if needed */
@@ -292,15 +414,53 @@ huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
cinfo->restarts_to_go--;
}
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
block = MCU_data[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]);
quanttbl = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
actbl = cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no];
dctbl = cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no];
/* Decode a single block's worth of coefficients */
/* Section F.2.2.1: decode the DC coefficient difference */
huff_DECODE(dctbl, s);
if (s) {
check_bit_buffer(s);
r = get_bits(s);
s = huff_EXTEND(r, s);
}
/* 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];
s += cinfo->last_dc_val[ci];
cinfo->last_dc_val[ci] = (JCOEF) s;
/* Descale and output the DC coefficient (assumes ZAG[0] = 0) */
(*block)[0] = (JCOEF) (((JCOEF) s) * quanttbl[0]);
/* Section F.2.2.2: decode the AC coefficients */
/* Since zero values are skipped, output area must be zeroed beforehand */
for (k = 1; k < DCTSIZE2; k++) {
huff_DECODE(actbl, s);
r = s >> 4;
s &= 15;
if (s) {
k += r;
check_bit_buffer(s);
r = get_bits(s);
s = huff_EXTEND(r, s);
/* Descale coefficient and output in natural (dezigzagged) order */
(*block)[ZAG[k]] = (JCOEF) (((JCOEF) s) * quanttbl[k]);
} else {
if (r != 15)
break;
k += 15;
}
}
}
}
@@ -310,7 +470,7 @@ huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
*/
METHODDEF void
huff_decoder_term (decompress_info_ptr cinfo)
decoder_term (decompress_info_ptr cinfo)
{
/* No work needed */
}
@@ -324,8 +484,8 @@ 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;
cinfo->methods->entropy_decode_init = decoder_init;
cinfo->methods->entropy_decode = decode_mcu;
cinfo->methods->entropy_decode_term = decoder_term;
}
}

469
jdmain.c
View File

@@ -1,11 +1,11 @@
/*
* jdmain.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
* This file contains a command-line 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
@@ -18,12 +18,22 @@
* 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.
* To simplify script writing, the "-outfile" switch is provided. The syntax
* djpeg [options] -outfile outputfile inputfile
* works regardless of which command line style is used.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#include <ctype.h> /* to declare isupper(), tolower() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
@@ -37,16 +47,21 @@
#define WRITE_BINARY "wb"
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#ifdef VMS
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
#else
#define EXIT_SUCCESS 0
#endif
#endif
#include "jversion.h" /* for version message */
/*
* PD version of getopt(3).
*/
#include "egetopt.c"
/*
* This list defines the known output image formats
* (not all of which need be supported by a given version).
@@ -117,18 +132,251 @@ d_ui_method_selection (decompress_info_ptr cinfo)
}
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* see -Dsignal_catcher=_abort in CFLAGS. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static external_methods_ptr emethods; /* for access to free_all */
GLOBAL void
signal_catcher (int signum)
{
if (emethods != NULL) {
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
* See jddeflts.c for explanation of the information used.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit)
{
if (cinfo->total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
cinfo->completed_passes+1, cinfo->total_passes,
(int) (loopcounter*100L/looplimit));
} else {
fprintf(stderr, "\r %3d%% ",
(int) (loopcounter*100L/looplimit));
}
fflush(stderr);
}
#endif
/*
* Argument-parsing code.
* The switch parser is designed to be useful with DOS-style command line
* syntax, ie, intermixed switches and file names, where only the switches
* to the left of a given file name affect processing of that file.
* The main program in this file doesn't actually use this capability...
*/
static char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (char * progname)
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-G] [-P] [-R] [-T] [-b] [-g] [-q colors] [-2] [-D] [-d]");
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, " inputfile outputfile\n");
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, " [inputfile]\n");
fprintf(stderr, "[inputfile]\n");
#endif
exit(2);
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
#ifdef GIF_SUPPORTED
fprintf(stderr, " -gif Select GIF output format\n");
#endif
#ifdef PPM_SUPPORTED
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format (default)\n");
#endif
fprintf(stderr, " -quantize N Same as -colors N\n");
#ifdef RLE_SUPPORTED
fprintf(stderr, " -rle Select Utah RLE output format\n");
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Select Targa output format\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef BLOCK_SMOOTHING_SUPPORTED
fprintf(stderr, " -blocksmooth Apply cross-block smoothing\n");
#endif
fprintf(stderr, " -grayscale Force grayscale output\n");
fprintf(stderr, " -nodither Don't use dithering in quantization\n");
#ifdef QUANT_1PASS_SUPPORTED
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
#endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
exit(EXIT_FAILURE);
}
LOCAL boolean
keymatch (char * arg, const char * keyword, int minchars)
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
/* keyword is the constant keyword (must be lower case already), */
/* minchars is length of minimum legal abbreviation. */
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
LOCAL int
parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen,
int argc, char **argv)
/* Initialize cinfo with default switch settings, then parse option switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
*/
{
int argn;
char * arg;
/* (Re-)initialize the system-dependent error and memory managers. */
jselerror(cinfo->emethods); /* error/trace message routines */
jselmemmgr(cinfo->emethods); /* memory allocation routines */
cinfo->methods->d_ui_method_selection = d_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = cinfo->emethods;
#endif
/* Set up default JPEG parameters. */
j_d_defaults(cinfo, TRUE);
requested_fmt = DEFAULT_FMT; /* set default output file format */
outfilename = NULL;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "blocksmooth", 1)) {
/* Enable cross-block smoothing. */
cinfo->do_block_smoothing = TRUE;
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
/* Do color quantization. */
int val;
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &val) != 1)
usage();
cinfo->desired_number_of_colors = val;
cinfo->quantize_colors = TRUE;
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
cinfo->emethods->trace_level++;
} else if (keymatch(arg, "gif", 1)) {
/* GIF output format. */
requested_fmt = FMT_GIF;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force monochrome output. */
cinfo->out_color_space = CS_GRAYSCALE;
} else if (keymatch(arg, "maxmemory", 1)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
char ch = 'x';
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
usage();
if (ch == 'm' || ch == 'M')
lval *= 1000L;
cinfo->emethods->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nodither", 3)) {
/* Suppress dithering in color quantization. */
cinfo->use_dithering = FALSE;
} else if (keymatch(arg, "onepass", 1)) {
/* Use fast one-pass quantization. */
cinfo->two_pass_quantize = FALSE;
} else if (keymatch(arg, "outfile", 3)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
/* PPM/PGM output format. */
requested_fmt = FMT_PPM;
} else if (keymatch(arg, "rle", 1)) {
/* RLE output format. */
requested_fmt = FMT_RLE;
} else if (keymatch(arg, "targa", 1)) {
/* Targa output format. */
requested_fmt = FMT_TARGA;
} else {
usage(); /* bogus switch */
}
}
return argn; /* return index of next arg (file name) */
}
@@ -136,116 +384,103 @@ usage (char * progname)
* The main program.
*/
GLOBAL void
GLOBAL int
main (int argc, char **argv)
{
struct decompress_info_struct cinfo;
struct decompress_methods_struct dc_methods;
struct external_methods_struct e_methods;
int c;
struct Decompress_info_struct cinfo;
struct Decompress_methods_struct dc_methods;
struct External_methods_struct e_methods;
int file_index;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
/* Initialize the system-dependent method pointers. */
progname = argv[0];
/* Set up links to method structures. */
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;
/* Set up default JPEG parameters. */
j_d_defaults(&cinfo, TRUE);
requested_fmt = DEFAULT_FMT; /* set default output file format */
/* Install, but don't yet enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = NULL;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Scan command line options, adjust parameters */
while ((c = egetopt(argc, argv, "GPRTbdgq:2D")) != EOF)
switch (c) {
case 'G': /* GIF output format. */
requested_fmt = FMT_GIF;
break;
case 'P': /* PPM output format. */
requested_fmt = FMT_PPM;
break;
case 'R': /* RLE output format. */
requested_fmt = FMT_RLE;
break;
case 'T': /* Targa output format. */
requested_fmt = FMT_TARGA;
break;
case 'b': /* Enable cross-block smoothing. */
cinfo.do_block_smoothing = TRUE;
break;
case 'd': /* Debugging. */
e_methods.trace_level++;
break;
case 'g': /* Force grayscale output. */
cinfo.out_color_space = CS_GRAYSCALE;
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': /* Suppress dithering in color quantization. */
cinfo.use_dithering = FALSE;
break;
case '?':
default:
usage(argv[0]);
break;
}
/* Scan command line: set up compression parameters, find file names. */
/* If -d appeared, print version identification */
if (e_methods.trace_level > 0)
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
/* Select the input and output files */
file_index = parse_switches(&cinfo, 0, argc, argv);
#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 */
cinfo.input_file = stdin; /* default input file */
cinfo.output_file = stdout; /* always the output file */
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);
/* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) {
if (file_index != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
outfilename = argv[file_index+1];
} else {
if (file_index != argc-1) {
fprintf(stderr, "%s: must name one input and one output file\n",
progname);
usage();
}
}
#else
/* Unix style: expect zero or one file name */
if (file_index < argc-1) {
fprintf(stderr, "%s: only one input file\n", progname);
usage();
}
#endif /* TWO_FILE_COMMANDLINE */
/* Open the input file. */
if (file_index < argc) {
if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
exit(EXIT_FAILURE);
}
} else {
/* default input file is stdin */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdin), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
exit(EXIT_FAILURE);
}
} else {
/* default output file is stdout */
#ifdef USE_SETMODE /* need to hack file mode? */
setmode(fileno(stdout), O_BINARY);
#endif
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
cinfo.output_file = stdout;
#endif
}
/* Set up to read a JFIF or baseline-JPEG file. */
/* A smarter UI would inspect the first few bytes of the input file */
@@ -256,16 +491,24 @@ main (int argc, char **argv)
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
#endif
#ifdef PROGRESS_REPORT
/* Start up progress display, unless trace output is on */
if (e_methods.trace_level == 0)
dc_methods.progress_monitor = progress_monitor;
#endif
/* Do it to it! */
jpeg_decompress(&cinfo);
/* Release memory. */
j_d_free_defaults(&cinfo, TRUE);
#ifdef MEM_STATS
if (e_methods.trace_level > 0) /* Optional memory-usage statistics */
j_mem_stats();
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (e_methods.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(0);
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

View File

@@ -1,7 +1,7 @@
/*
* jdmaster.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -19,8 +19,8 @@ d_per_scan_method_selection (decompress_info_ptr cinfo)
{
/* MCU disassembly */
jseldmcu(cinfo);
/* Un-subsampling of pixels */
jselunsubsample(cinfo);
/* Upsampling of pixels */
jselupsample(cinfo);
}
@@ -31,27 +31,19 @@ d_initial_method_selection (decompress_info_ptr cinfo)
/* 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 */
/* NB: this may change the component_needed flags */
jseldcolor(cinfo);
/* Color quantization */
/* Color quantization selection rules */
#ifdef QUANT_1PASS_SUPPORTED
#ifndef QUANT_2PASS_SUPPORTED
#ifdef QUANT_2PASS_SUPPORTED
/* We have both, check for conditions in which 1-pass should be used */
if (cinfo->num_components != 3 || cinfo->jpeg_color_space != CS_YCbCr)
cinfo->two_pass_quantize = FALSE; /* 2-pass only handles YCbCr input */
if (cinfo->out_color_space == CS_GRAYSCALE)
cinfo->two_pass_quantize = FALSE; /* Should use 1-pass for grayscale out */
#else /* not QUANT_2PASS_SUPPORTED */
cinfo->two_pass_quantize = FALSE; /* only have 1-pass */
#endif
#else /* not QUANT_1PASS_SUPPORTED */
@@ -71,6 +63,23 @@ d_initial_method_selection (decompress_info_ptr cinfo)
jsel2quantize(cinfo);
#endif
/* Cross-block smoothing */
#ifdef BLOCK_SMOOTHING_SUPPORTED
jselbsmooth(cinfo);
#else
cinfo->do_block_smoothing = FALSE;
#endif
/* Entropy decoding: either Huffman or arithmetic coding. */
#ifdef D_ARITH_CODING_SUPPORTED
jseldarithmetic(cinfo);
#else
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Arithmetic coding not supported");
}
#endif
jseldhuffman(cinfo);
/* Pipeline control */
jseldpipeline(cinfo);
/* Overall control (that's me!) */
@@ -100,7 +109,7 @@ initial_setup (decompress_info_ptr cinfo)
}
/* Compute logical subsampled dimensions of components */
/* Compute logical downsampled 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
@@ -121,16 +130,9 @@ initial_setup (decompress_info_ptr cinfo)
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;
}
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
/* Read the JPEG file header markers; everything up through the first SOS
* marker is read now. NOTE: the user interface must have initialized the
@@ -151,30 +153,24 @@ jpeg_decompress (decompress_info_ptr cinfo)
d_initial_method_selection(cinfo);
/* Initialize the output file & other modules as needed */
/* (color_quant and entropy_decoder are inited by pipeline controller) */
/* (modules needing per-scan init are called by pipeline controller) */
(*cinfo->methods->output_init) (cinfo);
(*cinfo->methods->colorout_init) (cinfo);
if (cinfo->quantize_colors)
(*cinfo->methods->color_quant_init) (cinfo);
/* And let the pipeline controller do the rest. */
(*cinfo->methods->d_pipeline_controller) (cinfo);
/* Finish output file, release working storage, etc */
if (cinfo->quantize_colors)
(*cinfo->methods->color_quant_term) (cinfo);
(*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]);
}
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
}

165
jdmcu.c
View File

@@ -1,49 +1,18 @@
/*
* jdmcu.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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
* This file contains MCU disassembly and IDCT control routines.
* These routines are invoked via the disassemble_MCU, reverse_DCT, 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.
@@ -53,19 +22,21 @@ METHODDEF void
disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCK MCU_data[1];
JBLOCKROW 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];
/* Pre-zero the target area to speed up entropy decoder */
/* (we assume wholesale zeroing is faster than retail) */
jzero_far((void FAR *) image_data[0][0],
(size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK)));
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Point to the proper spot in the image array for this MCU */
MCU_data[0] = image_data[0][0] + 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);
}
}
@@ -79,30 +50,127 @@ METHODDEF void
disassemble_interleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
JBLOCKROW 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;
/* Pre-zero the target area to speed up entropy decoder */
/* (we assume wholesale zeroing is faster than retail) */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
jzero_far((void FAR *) image_data[ci][ypos],
(size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK)));
}
}
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 */
/* Point to the proper spots in the image array for this MCU */
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);
MCU_data[blkn] = image_ptr;
image_ptr++;
blkn++;
}
}
}
/* Fetch the coefficient data */
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
}
}
/*
* Perform inverse DCT on each block in an MCU row's worth of data;
* output the results into a sample array starting at row start_row.
* NB: start_row can only be nonzero when dealing with a single-component
* scan; otherwise we'd have to pass different offsets for different
* components, since the heights of interleaved MCU rows can vary.
* But the pipeline controller logic is such that this is not necessary.
*/
METHODDEF void
reverse_DCT (decompress_info_ptr cinfo,
JBLOCKIMAGE coeff_data, JSAMPIMAGE output_data, int start_row)
{
DCTBLOCK block;
JBLOCKROW browptr;
JSAMPARRAY srowptr;
jpeg_component_info * compptr;
long blocksperrow, bi;
short numrows, ri;
short ci;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* don't bother to IDCT an uninteresting component */
if (! compptr->component_needed)
continue;
/* calculate size of an MCU row in this component */
blocksperrow = compptr->downsampled_width / DCTSIZE;
numrows = compptr->MCU_height;
/* iterate through all blocks in MCU row */
for (ri = 0; ri < numrows; ri++) {
browptr = coeff_data[ci][ri];
srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
for (bi = 0; bi < blocksperrow; bi++) {
/* copy the data into a local DCTBLOCK. This allows for change of
* representation (if DCTELEM != JCOEF). On 80x86 machines it also
* brings the data back from FAR storage to NEAR storage.
*/
{ register JCOEFPTR elemptr = browptr[bi];
register DCTELEM *localblkptr = block;
register int elem = DCTSIZE2;
while (--elem >= 0)
*localblkptr++ = (DCTELEM) *elemptr++;
}
j_rev_dct(block); /* perform inverse DCT */
/* Output the data into the sample array.
* Note change from signed to unsigned representation:
* DCT calculation works with values +-CENTERJSAMPLE,
* but sample arrays always hold 0..MAXJSAMPLE.
* We have to do range-limiting because of quantization errors in the
* DCT/IDCT phase. We use the sample_range_limit[] table to do this
* quickly; the CENTERJSAMPLE offset is folded into table indexing.
*/
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
register JSAMPLE *range_limit = cinfo->sample_range_limit +
CENTERJSAMPLE;
#if DCTSIZE != 8
register int elemc;
#endif
register int elemr;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = srowptr[elemr] + (bi * DCTSIZE);
#if DCTSIZE == 8 /* unroll the inner loop */
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
*elemptr++ = range_limit[*localblkptr++];
#else
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*elemptr++ = range_limit[*localblkptr++];
}
#endif
}
}
}
}
}
}
@@ -141,6 +209,7 @@ jseldmcu (decompress_info_ptr cinfo)
cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
else
cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
cinfo->methods->reverse_DCT = reverse_DCT;
cinfo->methods->disassemble_init = disassemble_init;
cinfo->methods->disassemble_term = disassemble_term;
}

902
jdpipe.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +1,69 @@
/*
* jdsample.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* This file contains upsampling routines.
* These routines are invoked via the upsample and
* upsample_init/term methods.
*
* An excellent reference for image resampling is
* Digital Image Warping, George Wolberg, 1990.
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*/
#include "jinclude.h"
/*
* Initialize for un-subsampling a scan.
* Initialize for upsampling a scan.
*/
METHODDEF void
unsubsample_init (decompress_info_ptr cinfo)
upsample_init (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* Un-subsample pixel values of a single component.
* This version only handles integral sampling ratios.
* Upsample pixel values of a single component.
* This version handles any integral sampling ratios.
*
* This is not used for typical JPEG files, so it need not be fast.
* Nor, for that matter, is it particularly accurate: the algorithm is
* simple replication of the input pixel onto the corresponding output
* pixels. The hi-falutin sampling literature refers to this as a
* "box filter". A box filter tends to introduce visible artifacts,
* so if you are actually going to use 3:1 or 4:1 sampling ratios
* you would be well advised to improve this code.
*/
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)
int_upsample (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;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
register short h_expand, h;
short v_expand, v;
int inrow, outrow;
long incol;
JSAMPROW inptr, outptr;
JSAMPLE invalue;
register long incol;
/* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
#ifdef DEBUG /* 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");
ERREXIT(cinfo->emethods, "Bogus upsample parameters");
#endif
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
@@ -71,19 +85,154 @@ unsubsample (decompress_info_ptr cinfo, int which_component,
/*
* Un-subsample pixel values of a single component.
* Upsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical.
*
* The upsampling algorithm is linear interpolation between pixel centers,
* also known as a "triangle filter". This is a good compromise between
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
* of the way between input pixel centers.
*/
METHODDEF void
h2v1_upsample (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)
{
register JSAMPROW inptr, outptr;
register int invalue;
int inrow;
register long colctr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
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 upsample parameters");
#endif
for (inrow = 0; inrow < input_rows; inrow++) {
inptr = input_data[inrow];
outptr = output_data[inrow];
/* Special case for first column */
invalue = GETJSAMPLE(*inptr++);
*outptr++ = (JSAMPLE) invalue;
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
for (colctr = input_cols - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = GETJSAMPLE(*inptr++) * 3;
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 2) >> 2);
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 2) >> 2);
*outptr++ = (JSAMPLE) invalue;
}
}
/*
* Upsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 2:1 vertical.
*
* The upsampling algorithm is linear interpolation between pixel centers,
* also known as a "triangle filter". This is a good compromise between
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
* of the way between input pixel centers.
*/
METHODDEF void
h2v2_upsample (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)
{
register JSAMPROW inptr0, inptr1, outptr;
#ifdef EIGHT_BIT_SAMPLES
register int thiscolsum, lastcolsum, nextcolsum;
#else
register INT32 thiscolsum, lastcolsum, nextcolsum;
#endif
int inrow, outrow, v;
register long colctr;
#ifdef DEBUG /* for debugging pipeline controller */
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
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 upsample parameters");
#endif
outrow = 0;
for (inrow = 0; inrow < input_rows; inrow++) {
for (v = 0; v < 2; v++) {
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) { /* next nearest is row above */
if (inrow == 0)
inptr1 = above[input_rows-1];
else
inptr1 = input_data[inrow-1];
} else { /* next nearest is row below */
if (inrow == input_rows-1)
inptr1 = below[0];
else
inptr1 = input_data[inrow+1];
}
outptr = output_data[outrow++];
/* Special case for first column */
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
for (colctr = input_cols - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 8) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
}
/* Special case for last column */
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
}
}
}
/*
* Upsample 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)
fullsize_upsample (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 */
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
#endif
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
}
@@ -95,7 +244,7 @@ fullsize_unsubsample (decompress_info_ptr cinfo, int which_component,
*/
METHODDEF void
unsubsample_term (decompress_info_ptr cinfo)
upsample_term (decompress_info_ptr cinfo)
{
/* no work for now */
}
@@ -103,31 +252,37 @@ unsubsample_term (decompress_info_ptr cinfo)
/*
* The method selection routine for unsubsampling.
* The method selection routine for upsampling.
* Note that we must select a routine for each component.
*/
GLOBAL void
jselunsubsample (decompress_info_ptr cinfo)
jselupsample (decompress_info_ptr cinfo)
{
short ci;
jpeg_component_info * compptr;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
ERREXIT(cinfo->emethods, "CCIR601 upsampling 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;
cinfo->methods->upsample[ci] = fullsize_upsample;
else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor)
cinfo->methods->upsample[ci] = h2v1_upsample;
else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor)
cinfo->methods->upsample[ci] = h2v2_upsample;
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;
cinfo->methods->upsample[ci] = int_upsample;
else
ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
ERREXIT(cinfo->emethods, "Fractional upsampling not implemented yet");
}
cinfo->methods->unsubsample_init = unsubsample_init;
cinfo->methods->unsubsample_term = unsubsample_term;
cinfo->methods->upsample_init = upsample_init;
cinfo->methods->upsample_term = upsample_term;
}

View File

@@ -1,7 +1,7 @@
/*
* jerror.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -13,9 +13,9 @@
* 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.
* the portable JPEG code doesn't use setjmp/longjmp. You should make sure
* that free_all is called either within error_exit or after the return to
* the outer-level routine.
*
* These routines are used by both the compression and decompression code.
*/
@@ -25,8 +25,12 @@
#include <stdlib.h> /* to declare exit() */
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1
#endif
static external_methods_ptr methods; /* saved for access to message_parm */
static external_methods_ptr methods; /* saved for access to message_parm, free_all */
METHODDEF void
@@ -44,8 +48,9 @@ trace_message (const char *msgtext)
METHODDEF void
error_exit (const char *msgtext)
{
trace_message(msgtext);
exit(1);
(*methods->trace_message) (msgtext);
(*methods->free_all) (); /* clean up memory allocation */
exit(EXIT_FAILURE);
}
@@ -58,10 +63,19 @@ error_exit (const char *msgtext)
GLOBAL void
jselerror (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for msg parm access */
methods = emethods; /* save struct addr for later access */
emethods->error_exit = error_exit;
emethods->trace_message = trace_message;
emethods->trace_level = 0; /* default = no tracing */
emethods->num_warnings = 0; /* no warnings emitted yet */
/* By default, the first corrupt-data warning will be displayed,
* but additional ones will appear only if trace level is at least 3.
* A corrupt data file could generate many warnings, so it's a good idea
* to suppress additional messages except at high tracing levels.
*/
emethods->first_warning_level = 0;
emethods->more_warning_level = 3;
}

422
jfwddct.c
View File

@@ -1,226 +1,298 @@
/*
* jfwddct.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
* The primary algorithm described there uses 11 multiplies and 29 adds.
* We use their alternate method with 12 multiplies and 32 adds.
* The advantage of this method is that no data path contains more than one
* multiplication; this allows a very simple and accurate implementation in
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#include "jinclude.h"
/* We assume that right shift corresponds to signed division by 2 with
* rounding towards minus infinity. This is correct for typical "arithmetic
* shift" instructions that shift in copies of the sign bit. But some
* C compilers implement >> with an unsigned shift. For these machines you
* must define RIGHT_SHIFT_IS_UNSIGNED.
* RIGHT_SHIFT provides a signed right shift of an INT32 quantity.
* It is only applied with constant shift counts.
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS INT32 shift_temp;
#define RIGHT_SHIFT(x,shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~0) << (32-(shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* The poop on this scaling stuff is as follows:
/*
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D DCT step produces outputs which are a factor of sqrt(N)
* larger than the true DCT outputs. The final outputs are therefore
* a factor of N larger than desired; since N=8 this can be cured by
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D DCT,
* because the y0 and y4 outputs need not be divided by sqrt(N).
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
* a problem to do in integer arithmetic. We multiply all the constants
* by DCT_SCALE and convert them to integer constants (thus retaining
* LG2_DCT_SCALE bits of precision in the constants). After doing a
* multiplication we have to divide the product by DCT_SCALE, with proper
* rounding, to produce the correct output. The division can be implemented
* cheaply as a right shift of LG2_DCT_SCALE bits. The DCT equations also
* specify an additional division by 2 on the final outputs; this can be
* folded into the right-shift by shifting one more bit (see UNFIXH).
* by CONST_SCALE and convert them to integer constants (thus retaining
* CONST_BITS bits of precision in the constants). After doing a
* multiplication we have to divide the product by CONST_SCALE, with proper
* rounding, to produce the correct output. This division can be done
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
* as long as possible so that partial sums can be added together with
* full fractional precision.
*
* If you are planning to recode this in assembler, you might want to set
* LG2_DCT_SCALE to 15. This loses a bit of precision, but then all the
* multiplications are between 16-bit quantities (given 8-bit JSAMPLEs!)
* so you could use a signed 16x16=>32 bit multiply instruction instead of
* full 32x32 multiply. Unfortunately there's no way to describe such a
* multiply portably in C, so we've gone for the extra bit of accuracy here.
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (To scale up 12-bit sample data, an
* intermediate INT32 array would be needed.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 25. Error analysis
* shows that the values given below are the most effective.
*/
#ifdef EIGHT_BIT_SAMPLES
#define LG2_DCT_SCALE 16
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */
#define CONST_BITS 13
#define PASS1_BITS 0 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
#define CONST_SCALE (ONE << CONST_BITS)
/* In some places we shift the inputs left by a couple more bits, */
/* so that they can be added to fractional results without too much */
/* loss of precision. */
#define LG2_OVERSCALE 2
#define OVERSCALE (ONE << LG2_OVERSCALE)
#define OVERSHIFT(x) ((x) <<= LG2_OVERSCALE)
/* Convert a positive real constant to an integer scaled by CONST_SCALE. */
/* Scale a fractional constant by DCT_SCALE */
#define FIX(x) ((INT32) ((x) * DCT_SCALE + 0.5))
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Scale a fractional constant by DCT_SCALE/OVERSCALE */
/* Such a constant can be multiplied with an overscaled input */
/* to produce something that's scaled by DCT_SCALE */
#define FIXO(x) ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
/* Descale and correctly round a value that's scaled by DCT_SCALE */
#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
/* Same with an additional division by 2, ie, correctly rounded UNFIX(x/2) */
#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
/* Take a value scaled by DCT_SCALE and round to integer scaled by OVERSCALE */
#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)),\
LG2_DCT_SCALE-LG2_OVERSCALE)
/* Here are the constants we need */
/* SIN_i_j is sine of i*pi/j, scaled by DCT_SCALE */
/* COS_i_j is cosine of i*pi/j, scaled by DCT_SCALE */
#define SIN_1_4 FIX(0.707106781)
#define COS_1_4 SIN_1_4
#define SIN_1_8 FIX(0.382683432)
#define COS_1_8 FIX(0.923879533)
#define SIN_3_8 COS_1_8
#define COS_3_8 SIN_1_8
#define SIN_1_16 FIX(0.195090322)
#define COS_1_16 FIX(0.980785280)
#define SIN_7_16 COS_1_16
#define COS_7_16 SIN_1_16
#define SIN_3_16 FIX(0.555570233)
#define COS_3_16 FIX(0.831469612)
#define SIN_5_16 COS_3_16
#define COS_5_16 SIN_3_16
/* OSIN_i_j is sine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */
/* OCOS_i_j is cosine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */
#define OSIN_1_4 FIXO(0.707106781)
#define OCOS_1_4 OSIN_1_4
#define OSIN_1_8 FIXO(0.382683432)
#define OCOS_1_8 FIXO(0.923879533)
#define OSIN_3_8 OCOS_1_8
#define OCOS_3_8 OSIN_1_8
#define OSIN_1_16 FIXO(0.195090322)
#define OCOS_1_16 FIXO(0.980785280)
#define OSIN_7_16 OCOS_1_16
#define OCOS_7_16 OSIN_1_16
#define OSIN_3_16 FIXO(0.555570233)
#define OCOS_3_16 FIXO(0.831469612)
#define OSIN_5_16 OCOS_3_16
#define OCOS_5_16 OSIN_3_16
/*
* Perform a 1-dimensional DCT.
* Note that this code is specialized to the case DCTSIZE = 8.
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
INLINE
LOCAL void
fast_dct_8 (DCTELEM *in, int stride)
{
/* many tmps have nonoverlapping lifetime -- flashy register colourers
* should be able to do this lot very well
*/
INT32 in0, in1, in2, in3, in4, in5, in6, in7;
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 tmp14, tmp15, tmp16, tmp17;
INT32 tmp25, tmp26;
SHIFT_TEMPS
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;
in[ 0] = (DCTELEM) UNFIXH((tmp10 + tmp11) * SIN_1_4);
in[stride*4] = (DCTELEM) UNFIXH((tmp10 - tmp11) * COS_1_4);
in[stride*2] = (DCTELEM) UNFIXH(tmp13*COS_1_8 + tmp12*SIN_1_8);
in[stride*6] = (DCTELEM) UNFIXH(tmp13*SIN_1_8 - tmp12*COS_1_8);
#if CONST_BITS == 13
#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_175875602 FIX(1.175875602)
#define FIX_1_501321110 FIX(1.501321110)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_1_961570560 FIX(1.961570560)
#define FIX_2_053119869 FIX(2.053119869)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_072711026 FIX(3.072711026)
#endif
tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4);
tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4);
OVERSHIFT(tmp4);
OVERSHIFT(tmp7);
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
/* tmp4, tmp7, tmp15, tmp16 are overscaled by OVERSCALE */
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
tmp14 = tmp4 + tmp15;
tmp25 = tmp4 - tmp15;
tmp26 = tmp7 - tmp16;
tmp17 = tmp7 + tmp16;
in[stride ] = (DCTELEM) UNFIXH(tmp17*OCOS_1_16 + tmp14*OSIN_1_16);
in[stride*7] = (DCTELEM) UNFIXH(tmp17*OCOS_7_16 - tmp14*OSIN_7_16);
in[stride*5] = (DCTELEM) UNFIXH(tmp26*OCOS_5_16 + tmp25*OSIN_5_16);
in[stride*3] = (DCTELEM) UNFIXH(tmp26*OCOS_3_16 - tmp25*OSIN_3_16);
}
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
*/
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
#ifndef MULTIPLY /* default definition */
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the forward DCT on one block of samples.
*
* A 2-D DCT can be done by 1-D DCT on each row
* followed by 1-D DCT on each column.
*/
GLOBAL void
j_fwd_dct (DCTBLOCK data)
{
int i;
for (i = 0; i < DCTSIZE; i++)
fast_dct_8(data+i*DCTSIZE, 1);
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
SHIFT_TEMPS
for (i = 0; i < DCTSIZE; i++)
fast_dct_8(data+i, DCTSIZE);
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true DCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp6 = dataptr[1] - dataptr[6];
tmp2 = dataptr[2] + dataptr[5];
tmp5 = dataptr[2] - dataptr[5];
tmp3 = dataptr[3] + dataptr[4];
tmp4 = dataptr[3] - dataptr[4];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
*/
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
CONST_BITS-PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
* i0..i3 in the paper are tmp4..tmp7 here.
*/
z1 = tmp4 + tmp7;
z2 = tmp5 + tmp6;
z3 = tmp4 + tmp6;
z4 = tmp5 + tmp7;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
*/
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+3);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
CONST_BITS+PASS1_BITS+3);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
* i0..i3 in the paper are tmp4..tmp7 here.
*/
z1 = tmp4 + tmp7;
z2 = tmp5 + tmp6;
z3 = tmp4 + tmp6;
z4 = tmp5 + tmp7;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
CONST_BITS+PASS1_BITS+3);
dataptr++; /* advance pointer to next column */
}
}

View File

@@ -1,7 +1,7 @@
/*
* jinclude.h
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -31,7 +31,7 @@
* 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.)
* (Well, we did cheat a bit in jmemmgr.c, but only if MEM_STATS is defined.)
*/
#include <stdio.h>
@@ -67,30 +67,34 @@
* CAUTION: argument order is different from underlying functions!
*/
#define FREAD(file,buf,sizeofbuf) \
#define JFREAD(file,buf,sizeofbuf) \
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
#define FWRITE(file,buf,sizeofbuf) \
#define JFWRITE(file,buf,sizeofbuf) \
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
/*
* 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().
* Some systems may declare memset and memcpy in <memory.h>.
*
* NOTE: we assume the size parameters to these functions are of type size_t.
* Insert casts in these macros if not!
* Change the casts in these macros if not!
*/
#ifdef INCLUDES_ARE_ANSI
#include <string.h>
#define MEMZERO(voidptr,size) memset((voidptr), 0, (size))
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#else /* not ANSI */
#ifdef BSD
#include <strings.h>
#define MEMZERO(voidptr,size) bzero((voidptr), (size))
#define memcpy(dest,src,size) bcopy((src), (dest), (size))
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
#else /* not BSD, assume Sys V or compatible */
#include <string.h>
#define MEMZERO(voidptr,size) memset((voidptr), 0, (size))
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#endif /* BSD */
#endif /* ANSI */

157
jmemansi.c Normal file
View File

@@ -0,0 +1,157 @@
/*
* jmemansi.c (jmemsys.c)
*
* Copyright (C) 1992, 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 a simple generic implementation of the system-
* dependent portion of the JPEG memory manager. This implementation
* assumes that you have the ANSI-standard library routine tmpfile().
* Also, the problem of determining the amount of memory available
* is shoved onto the user.
*/
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
#define SEEK_SET 0 /* if not, assume 0 is correct */
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total memory requested so far */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
*/
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
METHODDEF void
read_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
}
METHODDEF void
close_backing_store (backing_store_ptr info)
{
fclose(info->temp_file);
/* Since this implementation uses tmpfile() to create the file,
* no explicit file deletion is needed.
*/
}
/*
* Initial opening of a backing-store object.
*
* This version uses tmpfile(), which constructs a suitable file name
* behind the scenes. We don't have to use temp_name[] at all;
* indeed, we can't even find out the actual name of the temp file.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
if ((info->temp_file = tmpfile()) == NULL)
ERREXIT(methods, "Failed to create temporary file");
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
}
GLOBAL void
jmem_term (void)
{
/* no work */
}

634
jmemdos.c Normal file
View File

@@ -0,0 +1,634 @@
/*
* jmemdos.c (jmemsys.c)
*
* Copyright (C) 1992, 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 an MS-DOS-compatible implementation of the system-
* dependent portion of the JPEG memory manager. Temporary data can be
* stored in extended or expanded memory as well as in regular DOS files.
*
* If you use this file, you must be sure that NEED_FAR_POINTERS is defined
* if you compile in a small-data memory model; it should NOT be defined if
* you use a large-data memory model. This file is not recommended if you
* are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
* Also, this code will NOT work if struct fields are aligned on greater than
* 2-byte boundaries.
*
* Based on code contributed by Ge' Weijers.
*/
/*
* If you have both extended and expanded memory, you may want to change the
* order in which they are tried in jopen_backing_store. On a 286 machine
* expanded memory is usually faster, since extended memory access involves
* an expensive protected-mode-and-back switch. On 386 and better, extended
* memory is usually faster. As distributed, the code tries extended memory
* first (what? not everyone has a 386? :-).
*
* You can disable use of extended/expanded memory entirely by altering these
* definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
*/
#ifndef XMS_SUPPORTED
#define XMS_SUPPORTED 1
#endif
#ifndef EMS_SUPPORTED
#define EMS_SUPPORTED 1
#endif
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free(), getenv() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
extern char * getenv PP((const char * name));
#endif
#ifdef NEED_FAR_POINTERS
#ifdef __TURBOC__
/* These definitions work for Borland C (Turbo C) */
#include <alloc.h> /* need farmalloc(), farfree() */
#define far_malloc(x) farmalloc(x)
#define far_free(x) farfree(x)
#else
/* 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
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#else
#define READ_BINARY "rb"
#endif
/*
* Declarations for assembly-language support routines (see jmemdosa.asm).
*
* The functions are declared "far" as are all pointer arguments;
* this ensures the assembly source code will work regardless of the
* compiler memory model. We assume "short" is 16 bits, "long" is 32.
*/
typedef void far * XMSDRIVER; /* actually a pointer to code */
typedef struct { /* registers for calling XMS driver */
unsigned short ax, dx, bx;
void far * ds_si;
} XMScontext;
typedef struct { /* registers for calling EMS driver */
unsigned short ax, dx, bx;
void far * ds_si;
} EMScontext;
EXTERN short far jdos_open PP((short far * handle, char far * filename));
EXTERN short far jdos_close PP((short handle));
EXTERN short far jdos_seek PP((short handle, long offset));
EXTERN short far jdos_read PP((short handle, void far * buffer,
unsigned short count));
EXTERN short far jdos_write PP((short handle, void far * buffer,
unsigned short count));
EXTERN void far jxms_getdriver PP((XMSDRIVER far *));
EXTERN void far jxms_calldriver PP((XMSDRIVER, XMScontext far *));
EXTERN short far jems_available PP((void));
EXTERN void far jems_calldriver PP((EMScontext far *));
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total FAR memory requested so far */
/*
* Selection of a file name for a temporary file.
* This is highly system-dependent, and you may want to customize it.
*/
static int next_file_num; /* to distinguish among several temp files */
LOCAL void
select_file_name (char * fname)
{
const char * env;
char * ptr;
FILE * tfile;
/* Keep generating file names till we find one that's not in use */
for (;;) {
/* Get temp directory name from environment TMP or TEMP variable;
* if none, use "."
*/
if ((env = (const char *) getenv("TMP")) == NULL)
if ((env = (const char *) getenv("TEMP")) == NULL)
env = ".";
if (*env == '\0') /* null string means "." */
env = ".";
ptr = fname; /* copy name to fname */
while (*env != '\0')
*ptr++ = *env++;
if (ptr[-1] != '\\' && ptr[-1] != '/')
*ptr++ = '\\'; /* append backslash if not in env variable */
/* Append a suitable file name */
next_file_num++; /* advance counter */
sprintf(ptr, "JPG%03d.TMP", next_file_num);
/* Probe to see if file name is already in use */
if ((tfile = fopen(fname, READ_BINARY)) == NULL)
break;
fclose(tfile); /* oops, it's there; close tfile & try again */
}
}
/*
* Near-memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
/* near data space is NOT counted in total_used */
#ifndef NEED_FAR_POINTERS
total_used += sizeofobject;
#endif
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* Far-memory allocation and freeing
*/
#ifdef NEED_FAR_POINTERS
GLOBAL void FAR *
jget_large (size_t sizeofobject)
{
total_used += sizeofobject;
return (void FAR *) far_malloc(sizeofobject);
}
GLOBAL void
jfree_large (void FAR * object)
{
far_free(object);
}
#endif
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
/*
* For MS-DOS we support three types of backing storage:
* 1. Conventional DOS files. We access these by direct DOS calls rather
* than via the stdio package. This provides a bit better performance,
* but the real reason is that the buffers to be read or written are FAR.
* The stdio library for small-data memory models can't cope with that.
* 2. Extended memory, accessed per the XMS V2.0 specification.
* 3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
* You'll need copies of those specs to make sense of the related code.
* The specs are available by Internet FTP from SIMTEL20 and its various
* mirror sites; see microsoft/xms20.arc and info/limems41.zip.
*/
/*
* Access methods for a DOS file.
*/
METHODDEF void
read_file_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (jdos_seek(info->handle.file_handle, file_offset))
ERREXIT(methods, "seek failed on temporary file");
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
if (byte_count > 65535L) /* safety check */
ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
if (jdos_read(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "read failed on temporary file");
}
METHODDEF void
write_file_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (jdos_seek(info->handle.file_handle, file_offset))
ERREXIT(methods, "seek failed on temporary file");
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
if (byte_count > 65535L) /* safety check */
ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
if (jdos_write(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "write failed on temporary file --- out of disk space?");
}
METHODDEF void
close_file_store (backing_store_ptr info)
{
jdos_close(info->handle.file_handle); /* close the file */
remove(info->temp_name); /* delete the file */
/* If your system doesn't have remove(), try unlink() instead.
* remove() is the ANSI-standard name for this function, but
* unlink() was more common in pre-ANSI systems.
*/
TRACEMS1(methods, 1, "Closed DOS file %d", info->handle.file_handle);
}
LOCAL boolean
open_file_store (backing_store_ptr info, long total_bytes_needed)
{
short handle;
char tracemsg[TEMP_NAME_LENGTH+40];
select_file_name(info->temp_name);
if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name);
ERREXIT(methods, tracemsg); /* jopen_backing_store will fail anyway */
return FALSE;
}
info->handle.file_handle = handle;
info->read_backing_store = read_file_store;
info->write_backing_store = write_file_store;
info->close_backing_store = close_file_store;
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Opened DOS file %d %s", handle, info->temp_name);
TRACEMS(methods, 1, tracemsg);
return TRUE; /* succeeded */
}
/*
* Access methods for extended memory.
*/
#if XMS_SUPPORTED
static XMSDRIVER xms_driver; /* saved address of XMS driver */
typedef union { /* either long offset or real-mode pointer */
long offset;
void far * ptr;
} XMSPTR;
typedef struct { /* XMS move specification structure */
long length;
XMSH src_handle;
XMSPTR src;
XMSH dst_handle;
XMSPTR dst;
} XMSspec;
#define ODD(X) (((X) & 1L) != 0)
METHODDEF void
read_xms_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
XMSspec spec;
char endbuffer[2];
/* The XMS driver can't cope with an odd length, so handle the last byte
* specially if byte_count is odd. We don't expect this to be common.
*/
spec.length = byte_count & (~ 1L);
spec.src_handle = info->handle.xms_handle;
spec.src.offset = file_offset;
spec.dst_handle = 0;
spec.dst.ptr = buffer_address;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "read from extended memory failed");
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
}
}
METHODDEF void
write_xms_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
XMSspec spec;
char endbuffer[2];
/* The XMS driver can't cope with an odd length, so handle the last byte
* specially if byte_count is odd. We don't expect this to be common.
*/
spec.length = byte_count & (~ 1L);
spec.src_handle = 0;
spec.src.ptr = buffer_address;
spec.dst_handle = info->handle.xms_handle;
spec.dst.offset = file_offset;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "write to extended memory failed");
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
write_xms_store(info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
}
}
METHODDEF void
close_xms_store (backing_store_ptr info)
{
XMScontext ctx;
ctx.dx = info->handle.xms_handle;
ctx.ax = 0x0a00;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
TRACEMS1(methods, 1, "Freed XMS handle %u", info->handle.xms_handle);
/* we ignore any error return from the driver */
}
LOCAL boolean
open_xms_store (backing_store_ptr info, long total_bytes_needed)
{
XMScontext ctx;
/* Get address of XMS driver */
jxms_getdriver((XMSDRIVER far *) & xms_driver);
if (xms_driver == NULL)
return FALSE; /* no driver to be had */
/* Get version number, must be >= 2.00 */
ctx.ax = 0x0000;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax < (unsigned short) 0x0200)
return FALSE;
/* Try to get space (expressed in kilobytes) */
ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
ctx.ax = 0x0900;
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
return FALSE;
/* Succeeded, save the handle and away we go */
info->handle.xms_handle = ctx.dx;
info->read_backing_store = read_xms_store;
info->write_backing_store = write_xms_store;
info->close_backing_store = close_xms_store;
TRACEMS1(methods, 1, "Obtained XMS handle %u", ctx.dx);
return TRUE; /* succeeded */
}
#endif /* XMS_SUPPORTED */
/*
* Access methods for expanded memory.
*/
#if EMS_SUPPORTED
/* The EMS move specification structure requires word and long fields aligned
* at odd byte boundaries. Some compilers will align struct fields at even
* byte boundaries. While it's usually possible to force byte alignment,
* that causes an overall performance penalty and may pose problems in merging
* JPEG into a larger application. Instead we accept some rather dirty code
* here. Note this code would fail if the hardware did not allow odd-byte
* word & long accesses, but all 80x86 CPUs do.
*/
typedef void far * EMSPTR;
typedef union { /* EMS move specification structure */
long length; /* It's easy to access first 4 bytes */
char bytes[18]; /* Misaligned fields in here! */
} EMSspec;
/* Macros for accessing misaligned fields */
#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset])))
#define SRC_TYPE(spec) FIELD_AT(spec,4,char)
#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH)
#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short)
#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short)
#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR)
#define DST_TYPE(spec) FIELD_AT(spec,11,char)
#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH)
#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short)
#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short)
#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR)
#define EMSPAGESIZE 16384L /* gospel, see the EMS specs */
#define HIBYTE(W) (((W) >> 8) & 0xFF)
#define LOBYTE(W) ((W) & 0xFF)
METHODDEF void
read_ems_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
SRC_TYPE(spec) = 1;
SRC_HANDLE(spec) = info->handle.ems_handle;
SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
DST_TYPE(spec) = 0;
DST_HANDLE(spec) = 0;
DST_PTR(spec) = buffer_address;
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x5700; /* move memory region */
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
ERREXIT(methods, "read from expanded memory failed");
}
METHODDEF void
write_ems_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
SRC_TYPE(spec) = 0;
SRC_HANDLE(spec) = 0;
SRC_PTR(spec) = buffer_address;
DST_TYPE(spec) = 1;
DST_HANDLE(spec) = info->handle.ems_handle;
DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
ctx.ds_si = (void far *) & spec;
ctx.ax = 0x5700; /* move memory region */
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
ERREXIT(methods, "write to expanded memory failed");
}
METHODDEF void
close_ems_store (backing_store_ptr info)
{
EMScontext ctx;
ctx.ax = 0x4500;
ctx.dx = info->handle.ems_handle;
jems_calldriver((EMScontext far *) & ctx);
TRACEMS1(methods, 1, "Freed EMS handle %u", info->handle.ems_handle);
/* we ignore any error return from the driver */
}
LOCAL boolean
open_ems_store (backing_store_ptr info, long total_bytes_needed)
{
EMScontext ctx;
/* Is EMS driver there? */
if (! jems_available())
return FALSE;
/* Get status, make sure EMS is OK */
ctx.ax = 0x4000;
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
return FALSE;
/* Get version, must be >= 4.0 */
ctx.ax = 0x4600;
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
return FALSE;
/* Try to allocate requested space */
ctx.ax = 0x4300;
ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
jems_calldriver((EMScontext far *) & ctx);
if (HIBYTE(ctx.ax) != 0)
return FALSE;
/* Succeeded, save the handle and away we go */
info->handle.ems_handle = ctx.dx;
info->read_backing_store = read_ems_store;
info->write_backing_store = write_ems_store;
info->close_backing_store = close_ems_store;
TRACEMS1(methods, 1, "Obtained EMS handle %u", ctx.dx);
return TRUE; /* succeeded */
}
#endif /* EMS_SUPPORTED */
/*
* Initial opening of a backing-store object.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
/* Try extended memory, then expanded memory, then regular file. */
#if XMS_SUPPORTED
if (open_xms_store(info, total_bytes_needed))
return;
#endif
#if EMS_SUPPORTED
if (open_ems_store(info, total_bytes_needed))
return;
#endif
if (open_file_store(info, total_bytes_needed))
return;
ERREXIT(methods, "Failed to create temporary file");
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
}
GLOBAL void
jmem_term (void)
{
/* Microsoft C, at least in v6.00A, will not successfully reclaim freed
* blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
*/
#ifdef NEED_FHEAPMIN
_fheapmin();
#endif
}

135
jmemdos.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* jmemdos.h (jmemsys.h)
*
* Copyright (C) 1992, 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 include file defines the interface between the system-independent
* and system-dependent portions of the JPEG memory manager. (The system-
* independent portion is jmemmgr.c; there are several different versions
* of the system-dependent portion, and of this file for that matter.)
*
* This version is suitable for MS-DOS (80x86) implementations.
*/
/*
* These two functions are used to allocate and release small chunks of
* memory (typically the total amount requested through jget_small is
* no more than 20Kb or so). Behavior should be the same as for the
* standard library functions malloc and free; in particular, jget_small
* returns NULL on failure. On most systems, these ARE malloc and free.
* On an 80x86 machine using small-data memory model, these manage near heap.
*/
EXTERN void * jget_small PP((size_t sizeofobject));
EXTERN void jfree_small PP((void * object));
/*
* These two functions are used to allocate and release large chunks of
* memory (up to the total free space designated by jmem_available).
* The interface is the same as above, except that on an 80x86 machine,
* far pointers are used. On other systems these ARE the same as above.
*/
#ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */
EXTERN void FAR * jget_large PP((size_t sizeofobject));
EXTERN void jfree_large PP((void FAR * object));
#else
#define jget_large(sizeofobject) jget_small(sizeofobject)
#define jfree_large(object) jfree_small(object)
#endif
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
* be requested in a single call on jget_large (and jget_small for that
* matter, but that case should never come into play). This macro is needed
* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
* On machines with flat address spaces, any large constant may be used here.
*/
#define MAX_ALLOC_CHUNK 65440L /* leave room for malloc overhead */
/*
* This routine computes the total space available for allocation by
* jget_large. If more space than this is needed, backing store will be used.
* NOTE: any memory already allocated must not be counted.
*
* There is a minimum space requirement, corresponding to the minimum
* feasible buffer sizes; jmemmgr.c will request that much space even if
* jmem_available returns zero. The maximum space needed, enough to hold
* all working storage in memory, is also passed in case it is useful.
*
* It is OK for jmem_available to underestimate the space available (that'll
* just lead to more backing-store access than is really necessary).
* However, an overestimate will lead to failure. Hence it's wise to subtract
* a slop factor from the true available space, especially if jget_small space
* comes from the same pool. 5% should be enough.
*
* On machines with lots of virtual memory, any large constant may be returned.
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
/*
* This structure holds whatever state is needed to access a single
* backing-store object. The read/write/close method pointers are called
* by jmemmgr.c to manipulate the backing-store object; all other fields
* are private to the system-dependent backing store routines.
*/
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
typedef unsigned short XMSH; /* type of extended-memory handles */
typedef unsigned short EMSH; /* type of expanded-memory handles */
typedef union {
short file_handle; /* DOS file handle if it's a temp file */
XMSH xms_handle; /* handle if it's a chunk of XMS */
EMSH ems_handle; /* handle if it's a chunk of EMS */
} handle_union;
typedef struct backing_store_struct * backing_store_ptr;
typedef struct backing_store_struct {
/* Methods for reading/writing/closing this backing-store object */
METHOD(void, read_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, write_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, close_backing_store, (backing_store_ptr info));
/* Private fields for system-dependent backing-store management */
/* For the MS-DOS environment, we need: */
handle_union handle; /* reference to backing-store storage object */
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
} backing_store_info;
/*
* Initial opening of a backing-store object. This must fill in the
* read/write/close pointers in the object. The read/write routines
* may take an error exit if the specified maximum file size is exceeded.
* (If jmem_available always returns a large value, this routine can just
* take an error exit.)
*/
EXTERN void jopen_backing_store PP((backing_store_ptr info,
long total_bytes_needed));
/*
* These routines take care of any system-dependent initialization and
* cleanup required. The system methods struct address should be saved
* by jmem_init in case an error exit must be taken. jmem_term may assume
* that all requested memory has been freed and that all opened backing-
* store objects have been closed.
* NB: jmem_term may be called more than once, and must behave reasonably
* if that happens.
*/
EXTERN void jmem_init PP((external_methods_ptr emethods));
EXTERN void jmem_term PP((void));

379
jmemdosa.asm Normal file
View File

@@ -0,0 +1,379 @@
;
; jmemdosa.asm
;
; Copyright (C) 1992, 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 low-level interface routines to support the MS-DOS
; backing store manager (jmemdos.c). Routines are provided to access disk
; files through direct DOS calls, and to access XMS and EMS drivers.
;
; This file should assemble with Microsoft's MASM or any compatible
; assembler (including Borland's Turbo Assembler). If you haven't got
; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
;
; To minimize dependence on the C compiler's register usage conventions,
; we save and restore all 8086 registers, even though most compilers only
; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return
; values, which everybody returns in AX.
;
; Based on code contributed by Ge' Weijers.
;
JMEMDOSA_TXT segment byte public 'CODE'
assume cs:JMEMDOSA_TXT
public _jdos_open
public _jdos_close
public _jdos_seek
public _jdos_read
public _jdos_write
public _jxms_getdriver
public _jxms_calldriver
public _jems_available
public _jems_calldriver
;
; short far jdos_open (short far * handle, char far * filename)
;
; Create and open a temporary file
;
_jdos_open proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov cx,0 ; normal file attributes
lds dx,dword ptr [bp+10] ; get filename pointer
mov ah,3ch ; create file
int 21h
jc open_err ; if failed, return error code
lds bx,dword ptr [bp+6] ; get handle pointer
mov word ptr [bx],ax ; save the handle
xor ax,ax ; return zero for OK
open_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_open endp
;
; short far jdos_close (short handle)
;
; Close the file handle
;
_jdos_close proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
mov ah,3eh ; close file
int 21h
jc close_err ; if failed, return error code
xor ax,ax ; return zero for OK
close_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_close endp
;
; short far jdos_seek (short handle, long offset)
;
; Set file position
;
_jdos_seek proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
mov dx,word ptr [bp+8] ; LS offset
mov cx,word ptr [bp+10] ; MS offset
mov ax,4200h ; absolute seek
int 21h
jc seek_err ; if failed, return error code
xor ax,ax ; return zero for OK
seek_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_seek endp
;
; short far jdos_read (short handle, void far * buffer, unsigned short count)
;
; Read from file
;
_jdos_read proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
lds dx,dword ptr [bp+8] ; buffer address
mov cx,word ptr [bp+12] ; number of bytes
mov ah,3fh ; read file
int 21h
jc read_err ; if failed, return error code
cmp ax,word ptr [bp+12] ; make sure all bytes were read
je read_ok
mov ax,1 ; else return 1 for not OK
jmp short read_err
read_ok: xor ax,ax ; return zero for OK
read_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_read endp
;
; short far jdos_write (short handle, void far * buffer, unsigned short count)
;
; Write to file
;
_jdos_write proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov bx,word ptr [bp+6] ; file handle
lds dx,dword ptr [bp+8] ; buffer address
mov cx,word ptr [bp+12] ; number of bytes
mov ah,40h ; write file
int 21h
jc write_err ; if failed, return error code
cmp ax,word ptr [bp+12] ; make sure all bytes written
je write_ok
mov ax,1 ; else return 1 for not OK
jmp short write_err
write_ok: xor ax,ax ; return zero for OK
write_err: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jdos_write endp
;
; void far jxms_getdriver (XMSDRIVER far *)
;
; Get the address of the XMS driver, or NULL if not available
;
_jxms_getdriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov ax,4300h ; call multiplex interrupt with
int 2fh ; a magic cookie, hex 4300
cmp al,80h ; AL should contain hex 80
je xmsavail
xor dx,dx ; no XMS driver available
xor ax,ax ; return a nil pointer
jmp short xmsavail_done
xmsavail: mov ax,4310h ; fetch driver address with
int 2fh ; another magic cookie
mov dx,es ; copy address to dx:ax
mov ax,bx
xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value
mov word ptr es:[bx],ax
mov word ptr es:[bx+2],dx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jxms_getdriver endp
;
; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
;
; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
; These are loaded, the XMS call is performed, and the new values of the
; AX,DX,BX registers are written back to the context structure.
;
_jxms_calldriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
les bx,dword ptr [bp+10] ; get XMScontext pointer
mov ax,word ptr es:[bx] ; load registers
mov dx,word ptr es:[bx+2]
mov si,word ptr es:[bx+6]
mov ds,word ptr es:[bx+8]
mov bx,word ptr es:[bx+4]
call dword ptr [bp+6] ; call the driver
mov cx,bx ; save returned BX for a sec
les bx,dword ptr [bp+10] ; get XMScontext pointer
mov word ptr es:[bx],ax ; put back ax,dx,bx
mov word ptr es:[bx+2],dx
mov word ptr es:[bx+4],cx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jxms_calldriver endp
;
; short far jems_available (void)
;
; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
;
_jems_available proc far
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
mov ax,3567h ; get interrupt vector 67h
int 21h
push cs
pop ds
mov di,000ah ; check offs 10 in returned seg
lea si,ASCII_device_name ; against literal string
mov cx,8
cld
repe cmpsb
jne no_ems
mov ax,1 ; match, it's there
jmp short avail_done
no_ems: xor ax,ax ; it's not there
avail_done: pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
ret
ASCII_device_name db "EMMXXXX0"
_jems_available endp
;
; void far jems_calldriver (EMScontext far *)
;
; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
; These are loaded, the EMS trap is performed, and the new values of the
; AX,DX,BX registers are written back to the context structure.
;
_jems_calldriver proc far
push bp ; linkage
mov bp,sp
push si ; save all registers for safety
push di
push bx
push cx
push dx
push es
push ds
les bx,dword ptr [bp+6] ; get EMScontext pointer
mov ax,word ptr es:[bx] ; load registers
mov dx,word ptr es:[bx+2]
mov si,word ptr es:[bx+6]
mov ds,word ptr es:[bx+8]
mov bx,word ptr es:[bx+4]
int 67h ; call the EMS driver
mov cx,bx ; save returned BX for a sec
les bx,dword ptr [bp+6] ; get EMScontext pointer
mov word ptr es:[bx],ax ; put back ax,dx,bx
mov word ptr es:[bx+2],dx
mov word ptr es:[bx+4],cx
pop ds ; restore registers and exit
pop es
pop dx
pop cx
pop bx
pop di
pop si
pop bp
ret
_jems_calldriver endp
JMEMDOSA_TXT ends
end

1102
jmemmgr.c Normal file

File diff suppressed because it is too large Load Diff

251
jmemname.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* jmemname.c (jmemsys.c)
*
* Copyright (C) 1992, 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 a generic implementation of the system-dependent
* portion of the JPEG memory manager. This implementation assumes that
* you must explicitly construct a name for each temp file.
* Also, the problem of determining the amount of memory available
* is shoved onto the user.
*/
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
#define SEEK_SET 0 /* if not, assume 0 is correct */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define RW_BINARY "w+"
#else
#define READ_BINARY "rb"
#define RW_BINARY "w+b"
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
static long total_used; /* total memory requested so far */
/*
* Selection of a file name for a temporary file.
* This is system-dependent!
*
* The code as given is suitable for most Unix systems, and it is easily
* modified for most non-Unix systems. Some notes:
* 1. The temp file is created in the directory named by TEMP_DIRECTORY.
* The default value is /usr/tmp, which is the conventional place for
* creating large temp files on Unix. On other systems you'll probably
* want to change the file location. You can do this by editing the
* #define, or by defining TEMP_DIRECTORY in CFLAGS in the Makefile.
* For example, you might say
* CFLAGS= ... '-DTEMP_DIRECTORY="/tmp/"'
* Note that double quotes are needed in the text of the macro.
* With most make systems you have to put single quotes around the
* -D construct to preserve the double quotes.
* (Amiga SAS C has trouble with ":" and such in command-line options,
* so we've put in a special case for the preferred Amiga temp directory.)
*
* 2. If you need to change the file name as well as its location,
* you can override the TEMP_FILE_NAME macro. (Note that this is
* actually a printf format string; it must contain %s and %d.)
* Few people should need to do this.
*
* 3. mktemp() is used to ensure that multiple processes running
* simultaneously won't select the same file names. If your system
* doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
*
* 4. You probably want to define NEED_SIGNAL_CATCHER so that jcmain/jdmain
* will cause the temp files to be removed if you stop the program early.
*/
#ifndef TEMP_DIRECTORY /* so can override from Makefile */
#ifdef AMIGA
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */
#else
#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */
#endif
#endif
static int next_file_num; /* to distinguish among several temp files */
#ifdef NO_MKTEMP
#ifndef TEMP_FILE_NAME /* so can override from Makefile */
#define TEMP_FILE_NAME "%sJPG%03d.TMP"
#endif
LOCAL void
select_file_name (char * fname)
{
FILE * tfile;
/* Keep generating file names till we find one that's not in use */
for (;;) {
next_file_num++; /* advance counter */
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
if ((tfile = fopen(fname, READ_BINARY)) == NULL)
break;
fclose(tfile); /* oops, it's there; close tfile & try again */
}
}
#else /* ! NO_MKTEMP */
/* Note that mktemp() requires the initial filename to end in six X's */
#ifndef TEMP_FILE_NAME /* so can override from Makefile */
#define TEMP_FILE_NAME "%sJPG%dXXXXXX"
#endif
LOCAL void
select_file_name (char * fname)
{
next_file_num++; /* advance counter */
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
mktemp(fname); /* make sure file name is unique */
/* mktemp replaces the trailing XXXXXX with a unique string of characters */
}
#endif /* NO_MKTEMP */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
*/
/*
* This routine computes the total memory space available for allocation.
* It's impossible to do this in a portable way; our current solution is
* to make the user tell us (with a default value set at compile time).
* If you can actually get the available space, it's a good idea to subtract
* a slop factor of 5% or so.
*/
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return methods->max_memory_to_use - total_used;
}
/*
* Backing store (temporary file) management.
* Backing store objects are only used when the value returned by
* jmem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
METHODDEF void
read_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
long file_offset, long byte_count)
{
if (fseek(info->temp_file, file_offset, SEEK_SET))
ERREXIT(methods, "fseek failed on temporary file");
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
}
METHODDEF void
close_backing_store (backing_store_ptr info)
{
fclose(info->temp_file); /* close the file */
unlink(info->temp_name); /* delete the file */
/* If your system doesn't have unlink(), use remove() instead.
* remove() is the ANSI-standard name for this function, but if
* your system was ANSI you'd be using jmemansi.c, right?
*/
}
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
char tracemsg[TEMP_NAME_LENGTH+40];
select_file_name(info->temp_name);
if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) {
/* hack to get around ERREXIT's inability to handle string parameters */
sprintf(tracemsg, "Failed to create temporary file %s", info->temp_name);
ERREXIT(methods, tracemsg);
}
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
/* hack to get around TRACEMS' inability to handle string parameters */
sprintf(tracemsg, "Using temp file %s", info->temp_name);
TRACEMS(methods, 1, tracemsg);
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
}
GLOBAL void
jmem_term (void)
{
/* no work */
}

96
jmemnobs.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* jmemnobs.c (jmemsys.c)
*
* Copyright (C) 1992, 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 a really simple implementation of the system-
* dependent portion of the JPEG memory manager. This implementation
* assumes that no backing-store files are needed: all required space
* can be obtained from malloc().
* This is very portable in the sense that it'll compile on almost anything,
* but you'd better have lots of main memory (or virtual memory) if you want
* to process big images.
* Note that the max_memory_to_use option is ignored by this implementation.
*/
#include "jinclude.h"
#include "jmemsys.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare malloc(), free() */
#else
extern void * malloc PP((size_t size));
extern void free PP((void *ptr));
#endif
static external_methods_ptr methods; /* saved for access to error_exit */
/*
* Memory allocation and freeing are controlled by the regular library
* routines malloc() and free().
*/
GLOBAL void *
jget_small (size_t sizeofobject)
{
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
*/
/*
* This routine computes the total memory space available for allocation.
* Here we always say, "we got all you want bud!"
*/
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
{
return max_bytes_needed;
}
/*
* Backing store (temporary file) management.
* This should never be called and we just error out.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
ERREXIT(methods, "Backing store not supported");
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = 0;
}
GLOBAL void
jmem_term (void)
{
/* no work */
}

127
jmemsys.h Normal file
View File

@@ -0,0 +1,127 @@
/*
* jmemsys.h
*
* Copyright (C) 1992, 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 include file defines the interface between the system-independent
* and system-dependent portions of the JPEG memory manager. (The system-
* independent portion is jmemmgr.c; there are several different versions
* of the system-dependent portion, and of this file for that matter.)
*
* This is a "generic" skeleton that may need to be modified for particular
* systems. It should be usable as-is on the majority of non-MSDOS machines.
*/
/*
* These two functions are used to allocate and release small chunks of
* memory (typically the total amount requested through jget_small is
* no more than 20Kb or so). Behavior should be the same as for the
* standard library functions malloc and free; in particular, jget_small
* returns NULL on failure. On most systems, these ARE malloc and free.
* On an 80x86 machine using small-data memory model, these manage near heap.
*/
EXTERN void * jget_small PP((size_t sizeofobject));
EXTERN void jfree_small PP((void * object));
/*
* These two functions are used to allocate and release large chunks of
* memory (up to the total free space designated by jmem_available).
* The interface is the same as above, except that on an 80x86 machine,
* far pointers are used. On other systems these ARE the same as above.
*/
#ifdef NEED_FAR_POINTERS /* typically not needed except on 80x86 */
EXTERN void FAR * jget_large PP((size_t sizeofobject));
EXTERN void jfree_large PP((void FAR * object));
#else
#define jget_large(sizeofobject) jget_small(sizeofobject)
#define jfree_large(object) jfree_small(object)
#endif
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
* be requested in a single call on jget_large (and jget_small for that
* matter, but that case should never come into play). This macro is needed
* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
* On machines with flat address spaces, any large constant may be used here.
*/
#define MAX_ALLOC_CHUNK 1000000000L
/*
* This routine computes the total space available for allocation by
* jget_large. If more space than this is needed, backing store will be used.
* NOTE: any memory already allocated must not be counted.
*
* There is a minimum space requirement, corresponding to the minimum
* feasible buffer sizes; jmemmgr.c will request that much space even if
* jmem_available returns zero. The maximum space needed, enough to hold
* all working storage in memory, is also passed in case it is useful.
*
* It is OK for jmem_available to underestimate the space available (that'll
* just lead to more backing-store access than is really necessary).
* However, an overestimate will lead to failure. Hence it's wise to subtract
* a slop factor from the true available space, especially if jget_small space
* comes from the same pool. 5% should be enough.
*
* On machines with lots of virtual memory, any large constant may be returned.
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
/*
* This structure holds whatever state is needed to access a single
* backing-store object. The read/write/close method pointers are called
* by jmemmgr.c to manipulate the backing-store object; all other fields
* are private to the system-dependent backing store routines.
*/
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
typedef struct backing_store_struct * backing_store_ptr;
typedef struct backing_store_struct {
/* Methods for reading/writing/closing this backing-store object */
METHOD(void, read_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, write_backing_store, (backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
METHOD(void, close_backing_store, (backing_store_ptr info));
/* Private fields for system-dependent backing-store management */
/* For a typical implementation with temp files, we might need: */
FILE * temp_file; /* stdio reference to temp file */
char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
} backing_store_info;
/*
* Initial opening of a backing-store object. This must fill in the
* read/write/close pointers in the object. The read/write routines
* may take an error exit if the specified maximum file size is exceeded.
* (If jmem_available always returns a large value, this routine can just
* take an error exit.)
*/
EXTERN void jopen_backing_store PP((backing_store_ptr info,
long total_bytes_needed));
/*
* These routines take care of any system-dependent initialization and
* cleanup required. The system methods struct address should be saved
* by jmem_init in case an error exit must be taken. jmem_term may assume
* that all requested memory has been freed and that all opened backing-
* store objects have been closed.
* NB: jmem_term may be called more than once, and must behave reasonably
* if that happens.
*/
EXTERN void jmem_init PP((external_methods_ptr emethods));
EXTERN void jmem_term PP((void));

View File

@@ -1,7 +1,7 @@
/*
* jpegdata.h
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -67,7 +67,7 @@ typedef FILE * IFILEREF; /* source or dest of non-JPEG image data */
/*
* 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.
* 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
@@ -87,9 +87,9 @@ typedef FILE * IFILEREF; /* source or dest of non-JPEG image data */
#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;
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. */
@@ -154,17 +154,21 @@ typedef struct { /* Basic info about one component */
/* 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 */
/* the above are the logical dimensions of the downsampled 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 */
long downsampled_width; /* image width in samples, after expansion */
long downsampled_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!! */
/* This flag is used only for decompression. In cases where some of the */
/* components will be ignored (eg grayscale output from YCbCr image), */
/* we can skip IDCT etc. computations for the unused components. */
boolean component_needed; /* do we need the value of this component? */
} jpeg_component_info;
@@ -184,7 +188,12 @@ typedef QUANT_VAL QUANT_TBL[DCTSIZE2]; /* A quantization table */
typedef QUANT_VAL * QUANT_TBL_PTR; /* pointer to same */
typedef struct { /* A Huffman coding table */
/* Huffman coding tables.
*/
#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
typedef struct {
/* 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 */
@@ -195,14 +204,29 @@ typedef struct { /* A Huffman coding table */
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.
* Huffman compression & decompression modules. We use a union since only
* one set of fields is needed at a time.
*/
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[18]; /* largest code of length k (-1 if none) */
/* maxcode[17] is a sentinel to ensure huff_DECODE terminates */
short valptr[17]; /* huffval[] index of 1st symbol of length k */
union {
struct { /* encoding tables: */
UINT16 ehufco[256]; /* code for each symbol */
char ehufsi[256]; /* length of code for each symbol */
} enc;
struct { /* decoding tables: */
/* Basic tables: (element [0] of each array is unused) */
INT32 mincode[17]; /* smallest code of length k */
INT32 maxcode[18]; /* largest code of length k (-1 if none) */
/* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */
int valptr[17]; /* huffval[] index of 1st symbol of length k */
/* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
* the input data stream. If the next Huffman code is no more
* than HUFF_LOOKAHEAD bits long, we can obtain its length and
* the corresponding symbol directly from these tables.
*/
int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
} dec;
} priv;
} HUFF_TBL;
@@ -216,7 +240,7 @@ typedef struct { /* A Huffman coding table */
/* Working data for compression */
struct compress_info_struct {
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
@@ -252,6 +276,10 @@ struct compress_info_struct {
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
char * comment_text; /* Text for COM block, or NULL for no COM */
/* note: JPEG library will not free() the comment string, */
/* unless you allocate it via alloc_small(). */
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 */
@@ -271,8 +299,15 @@ struct compress_info_struct {
boolean interleave; /* TRUE=interleaved output, FALSE=not */
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
int smoothing_factor; /* 1..100, or 0 for no input smoothing */
UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
/* The restart interval can be specified in absolute MCUs by setting
* restart_interval, or in MCU rows by setting restart_in_rows
* (in which case the correct restart_interval will be figured
* for each scan).
*/
UINT16 restart_interval;/* MCUs per restart interval, or 0 for no restart */
int restart_in_rows; /* if > 0, MCU rows per restart interval */
/*
* These fields are computed during jpeg_compress startup
@@ -280,6 +315,13 @@ struct compress_info_struct {
short max_h_samp_factor; /* largest h_samp_factor */
short max_v_samp_factor; /* largest v_samp_factor */
/*
* These fields may be useful for progress monitoring
*/
int total_passes; /* number of passes expected */
int completed_passes; /* number of passes completed so far */
/*
* These fields are valid during any one scan
*/
@@ -298,16 +340,16 @@ struct compress_info_struct {
/* 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 */
UINT16 restarts_to_go; /* MCUs left in this restart interval */
short next_restart_num; /* # of next RSTn marker (0..7) */
};
typedef struct compress_info_struct * compress_info_ptr;
typedef struct Compress_info_struct * compress_info_ptr;
/* Working data for decompression */
struct decompress_info_struct {
struct Decompress_info_struct {
/*
* These fields shall be established by the user interface before
* calling jpeg_decompress.
@@ -332,10 +374,10 @@ struct decompress_info_struct {
/* 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 */
int desired_number_of_colors; /* max number of colors to use */
boolean do_block_smoothing; /* T = apply cross-block smoothing */
boolean do_pixel_smoothing; /* T = apply post-subsampling smoothing */
boolean do_pixel_smoothing; /* T = apply post-upsampling smoothing */
/*
* These fields are used for efficient buffering of data between read_jpeg_data
@@ -345,7 +387,8 @@ struct decompress_info_struct {
* 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.
* actually supplies the read_jpeg_data method. This is all handled by
* j_d_defaults in a typical implementation.
*/
char * input_buffer; /* start of buffer (private to input code) */
char * next_input_byte; /* => next byte to read from buffer */
@@ -385,7 +428,7 @@ struct decompress_info_struct {
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 */
UINT16 restart_interval;/* MCUs per restart interval, or 0 for no restart */
/*
* These fields are computed during jpeg_decompress startup
@@ -395,9 +438,28 @@ struct decompress_info_struct {
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 */
short final_out_comps; /* # of color components sent to put_pixel_rows */
/* (1 when quantizing colors, else same as color_out_comps) */
JSAMPLE * sample_range_limit; /* table for fast range-limiting */
/*
* When quantizing colors, the color quantizer leaves a pointer to the output
* colormap in these fields. The colormap is valid from the time put_color_map
* is called (must be before any put_pixel_rows calls) until shutdown (more
* specifically, until free_all is called to release memory).
*/
int actual_number_of_colors; /* actual number of entries */
JSAMPARRAY colormap; /* NULL if not valid */
/* map has color_out_comps rows * actual_number_of_colors columns */
/*
* These fields may be useful for progress monitoring
*/
int total_passes; /* number of passes expected */
int completed_passes; /* number of passes completed so far */
/*
* These fields are valid during any one scan
*/
@@ -416,11 +478,11 @@ struct decompress_info_struct {
/* 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 */
UINT16 restarts_to_go; /* MCUs left in this restart interval */
short next_restart_num; /* # of next RSTn marker (0..7) */
};
typedef struct decompress_info_struct * decompress_info_ptr;
typedef struct Decompress_info_struct * decompress_info_ptr;
/* Macros for reading data from the decompression input buffer */
@@ -436,7 +498,7 @@ typedef struct decompress_info_struct * decompress_info_ptr;
#endif
#define JUNGETC(ch,cinfo) ((cinfo)->bytes_in_buffer++, \
*(--((cinfo)->next_input_byte)) = (ch))
*(--((cinfo)->next_input_byte)) = (char) (ch))
#define MIN_UNGET 4 /* may always do at least 4 JUNGETCs */
@@ -455,7 +517,7 @@ typedef struct big_barray_control * big_barray_ptr;
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
* add -DINCOMPLETE_TYPES_BROKEN to CFLAGS in your Makefile. Then we will
* pseudo-define the structs as containing a single "dummy" field.
* The memory manager(s) #define AM_MEMORY_MANAGER before including this file,
* The memory managers #define AM_MEMORY_MANAGER before including this file,
* so that they can make their own definitions of the structs.
*/
@@ -473,22 +535,22 @@ 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, downsample_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, upsample_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,
@@ -504,21 +566,30 @@ typedef METHOD(void, quantize_caller_ptr, (decompress_info_ptr cinfo,
* decompression.
*/
struct external_methods_struct {
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. */
/* 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, (const char *msgtext));
METHOD(void, trace_message, (const 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 level 0 for important warning messages (nonfatal errors) */
/* Use levels 1, 2, 3 for successively more detailed trace options */
/* For recoverable corrupt-data errors, we emit a warning message and
* keep going. A surrounding application can check for bad data by
* seeing if num_warnings is nonzero at the end of processing.
*/
long num_warnings; /* number of corrupt-data warnings */
int first_warning_level; /* trace level for first warning */
int more_warning_level; /* trace level for subsequent warnings */
int message_parm[8]; /* store numeric parms for messages here */
/* Memory management */
@@ -526,21 +597,14 @@ struct external_methods_struct {
/* 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(void, free_small_sarray, (JSAMPARRAY ptr));
METHOD(JBLOCKARRAY, alloc_small_barray, (long blocksperrow,
long numrows));
METHOD(void, free_small_barray, (JBLOCKARRAY ptr,
long numrows));
METHOD(void, free_small_barray, (JBLOCKARRAY ptr));
METHOD(big_sarray_ptr, request_big_sarray, (long samplesperrow,
long numrows,
long unitheight));
@@ -558,11 +622,15 @@ struct external_methods_struct {
boolean writable));
METHOD(void, free_big_sarray, (big_sarray_ptr ptr));
METHOD(void, free_big_barray, (big_barray_ptr ptr));
METHOD(void, free_all, (void));
long max_memory_to_use; /* maximum amount of memory to use */
};
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is generally cinfo->emethods */
/* Fatal errors (print message and exit) */
#define ERREXIT(emeth,msg) ((*(emeth)->error_exit) (msg))
#define ERREXIT1(emeth,msg,p1) ((emeth)->message_parm[0] = (p1), \
(*(emeth)->error_exit) (msg))
@@ -581,6 +649,25 @@ struct external_methods_struct {
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we'll keep going, but the data is probably corrupt) */
/* Note that warning count is incremented as a side-effect! */
#define WARNMS(emeth,msg) \
MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \
(emeth)->more_warning_level : (emeth)->first_warning_level)){ \
(*(emeth)->trace_message) (msg); } )
#define WARNMS1(emeth,msg,p1) \
MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \
(emeth)->more_warning_level : (emeth)->first_warning_level)){ \
(emeth)->message_parm[0] = (p1); \
(*(emeth)->trace_message) (msg); } )
#define WARNMS2(emeth,msg,p1,p2) \
MAKESTMT( if ((emeth)->trace_level >= ((emeth)->num_warnings++ ? \
(emeth)->more_warning_level : (emeth)->first_warning_level)){ \
(emeth)->message_parm[0] = (p1); \
(emeth)->message_parm[1] = (p2); \
(*(emeth)->trace_message) (msg); } )
/* Informational/debugging messages */
#define TRACEMS(emeth,lvl,msg) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
(*(emeth)->trace_message) (msg); } )
@@ -613,15 +700,18 @@ struct external_methods_struct {
/* Methods used during JPEG compression. */
struct compress_methods_struct {
struct Compress_methods_struct {
/* Hook for user interface to get control after input_init */
METHOD(void, c_ui_method_selection, (compress_info_ptr cinfo));
/* Hook for user interface to do progress monitoring */
METHOD(void, progress_monitor, (compress_info_ptr cinfo,
long loopcounter, long looplimit));
/* 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 */
/* Color space and gamma conversion */
METHOD(void, colorin_init, (compress_info_ptr cinfo));
METHOD(void, get_sample_rows, (compress_info_ptr cinfo,
int rows_to_read,
@@ -632,11 +722,11 @@ struct compress_methods_struct {
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));
/* Downsample pixel values of a single component */
/* There can be a different downsample method for each component */
METHOD(void, downsample_init, (compress_info_ptr cinfo));
downsample_ptr downsample[MAX_COMPS_IN_SCAN];
METHOD(void, downsample_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));
@@ -649,10 +739,10 @@ struct compress_methods_struct {
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_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));
METHOD(void, entropy_encode_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));
@@ -672,28 +762,36 @@ struct compress_methods_struct {
/* Methods used during JPEG decompression. */
struct decompress_methods_struct {
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));
/* Hook for user interface to process comment blocks */
METHOD(void, process_comment, (decompress_info_ptr cinfo,
long comment_length));
/* Hook for user interface to do progress monitoring */
METHOD(void, progress_monitor, (decompress_info_ptr cinfo,
long loopcounter, long looplimit));
/* 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, resync_to_restart, (decompress_info_ptr cinfo,
int marker));
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_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));
JBLOCKROW *MCU_data));
METHOD(void, entropy_decode_term, (decompress_info_ptr cinfo));
/* MCU disassembly: fetch MCUs from entropy_decode, build coef array */
/* The reverse_DCT step is in the same module for symmetry reasons */
METHOD(void, disassemble_init, (decompress_info_ptr cinfo));
METHOD(void, disassemble_MCU, (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data));
METHOD(void, reverse_DCT, (decompress_info_ptr cinfo,
JBLOCKIMAGE coeff_data,
JSAMPIMAGE output_data, int start_row));
METHOD(void, disassemble_term, (decompress_info_ptr cinfo));
/* Cross-block smoothing */
METHOD(void, smooth_coefficients, (decompress_info_ptr cinfo,
@@ -702,15 +800,15 @@ struct decompress_methods_struct {
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 */
/* Upsample pixel values of a single component */
/* There can be a different upsample method for each component */
METHOD(void, upsample_init, (decompress_info_ptr cinfo));
upsample_ptr upsample[MAX_COMPS_IN_SCAN];
METHOD(void, upsample_term, (decompress_info_ptr cinfo));
/* Color space and gamma conversion */
METHOD(void, colorout_init, (decompress_info_ptr cinfo));
METHOD(void, color_convert, (decompress_info_ptr cinfo,
int num_rows,
int num_rows, long num_cols,
JSAMPIMAGE input_data,
JSAMPIMAGE output_data));
METHOD(void, colorout_term, (decompress_info_ptr cinfo));
@@ -722,7 +820,8 @@ struct decompress_methods_struct {
JSAMPARRAY output_data));
METHOD(void, color_quant_prescan, (decompress_info_ptr cinfo,
int num_rows,
JSAMPIMAGE image_data));
JSAMPIMAGE image_data,
JSAMPARRAY workspace));
METHOD(void, color_quant_doit, (decompress_info_ptr cinfo,
quantize_caller_ptr source_method));
METHOD(void, color_quant_term, (decompress_info_ptr cinfo));
@@ -761,7 +860,11 @@ EXTERN void j_c_defaults 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_c_free_defaults PP((compress_info_ptr cinfo));
/* advanced compression parameter setup aids */
EXTERN void j_add_quant_table PP((compress_info_ptr cinfo, int which_tbl,
const QUANT_VAL *basic_table,
int scale_factor, boolean force_baseline));
EXTERN int j_quality_scaling PP((int quality));
/* main entry for decompression */
EXTERN void jpeg_decompress PP((decompress_info_ptr cinfo));
@@ -769,8 +872,6 @@ EXTERN void jpeg_decompress PP((decompress_info_ptr cinfo));
/* default parameter setup for decompression */
EXTERN void j_d_defaults PP((decompress_info_ptr cinfo,
boolean standard_buffering));
EXTERN void j_d_free_defaults PP((decompress_info_ptr cinfo,
boolean standard_buffering));
/* forward DCT */
EXTERN void j_fwd_dct PP((DCTBLOCK data));
@@ -791,7 +892,7 @@ 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 jseldownsample 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: */
@@ -808,7 +909,7 @@ 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 jselupsample 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 */
@@ -822,13 +923,31 @@ EXTERN void jselwtarga PP((decompress_info_ptr cinfo)); /* jwrtarga.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 */
EXTERN void jselmemmgr PP((external_methods_ptr emethods)); /* jmemmgr.c */
/* debugging hook in jvirtmem.c */
#ifdef MEM_STATS
EXTERN void j_mem_stats PP((void));
/* We assume that right shift corresponds to signed division by 2 with
* rounding towards minus infinity. This is correct for typical "arithmetic
* shift" instructions that shift in copies of the sign bit. But some
* C compilers implement >> with an unsigned shift. For these machines you
* must define RIGHT_SHIFT_IS_UNSIGNED.
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
* It is only applied with constant shift counts. SHIFT_TEMPS must be
* included in the variables of any routine using RIGHT_SHIFT.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS INT32 shift_temp;
#define RIGHT_SHIFT(x,shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
/* Miscellaneous useful macros */
#undef MAX

549
jquant1.c
View File

@@ -1,7 +1,7 @@
/*
* jquant1.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -16,61 +16,253 @@
/*
* This implementation is a fairly dumb, quick-and-dirty quantizer;
* it's here mostly so that we can start working on colormapped output formats.
* The main purpose of 1-pass quantization is to provide a fast, if not very
* high quality, colormapped output capability. A 2-pass quantizer usually
* gives better visual quality; however, for quantized grayscale output this
* quantizer is perfectly adequate. Dithering is highly recommended with this
* quantizer, though you can turn it off if you really want to.
*
* 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.
* This implementation quantizes in the output colorspace. This has a couple
* of disadvantages: each pixel must be individually color-converted, and if
* the color conversion includes gamma correction then quantization is done in
* a nonlinear space, which is less desirable. The major advantage is that
* with the usual output color spaces (RGB, grayscale) an orthogonal grid of
* representative colors can be used, thus permitting the very simple and fast
* color lookup scheme used here. The standard JPEG colorspace (YCbCr) cannot
* be effectively handled this way, because only about a quarter of an
* orthogonal grid would fall within the gamut of realizable colors. Another
* advantage is that when the user wants quantized grayscale output from a
* color JPEG file, this quantizer can provide a high-quality result with no
* special hacking.
*
* The result almost always needs dithering to look decent.
* The gamma-correction problem could be eliminated by adjusting the grid
* spacing to counteract the gamma correction applied by color_convert.
* At this writing, gamma correction is not implemented by jdcolor, so
* nothing is done here.
*
* In 1-pass quantization the colormap must be chosen in advance of seeing the
* image. We use a map consisting of all combinations of Ncolors[i] color
* values for the i'th component. The Ncolors[] values are chosen so that
* their product, the total number of colors, is no more than that requested.
* (In most cases, the product will be somewhat less.)
*
* Since the colormap is orthogonal, the representative value for each color
* component can be determined without considering the other components;
* then these indexes can be combined into a colormap index by a standard
* N-dimensional-array-subscript calculation. Most of the arithmetic involved
* can be precalculated and stored in the lookup table colorindex[].
* colorindex[i][j] maps pixel value j in component i to the nearest
* representative value (grid plane) for that component; this index is
* multiplied by the array stride for component i, so that the
* index of the colormap entry closest to a given pixel value is just
* sum( colorindex[component-number][pixel-component-value] )
* Aside from being fast, this scheme allows for variable spacing between
* representative values with no additional lookup cost.
*/
#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 */
#define MAX_COMPONENTS 4 /* max components I can handle */
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]
* premultiplied as described above. Since colormap indexes must fit into
* JSAMPLEs, the entries of this array will too.
*/
static JSAMPARRAY input_buffer; /* color conversion workspace */
/* Since our input data is presented in the JPEG colorspace, we have to call
* color_convert to get it into the output colorspace. input_buffer is a
* one-row-high workspace for the result of color_convert.
*/
/* 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,
*
* Errors are accumulated into the array fserrors[], at a resolution of
* 1/16th of a pixel count. The error at a given pixel is propagated
* to its not-yet-processed 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.
*
* We can get away with a single array (holding one row's worth of errors)
* by using it to store the current row's errors at pixel columns not yet
* processed, but the next row's errors at columns already processed. We
* need only a few extra variables to hold the errors immediately around the
* current column. (If we are lucky, those variables are in registers, but
* even if not, they're probably cheaper to access than array elements are.)
*
* The fserrors[] array is indexed [component#][position].
* We provide (#columns + 2) entries per component; the extra entry at each
* end saves us from special-casing the first and last pixels.
*
* 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.
* segment to hold the error array; so it is allocated with alloc_medium.
*/
#ifdef EIGHT_BIT_SAMPLES
typedef INT16 FSERROR; /* 16 bits should be enough */
typedef int LOCFSERROR; /* use 'int' for calculation temps */
#else
typedef INT32 FSERROR; /* may need more than 16 bits? */
typedef INT32 FSERROR; /* may need more than 16 bits */
typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
#endif
typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
static FSERRPTR evenrowerrs, oddrowerrs; /* current-row and next-row errors */
static FSERRPTR fserrors[MAX_COMPONENTS]; /* accumulated errors */
static boolean on_odd_row; /* flag to remember which row we are on */
/*
* Policy-making subroutines for color_quant_init: these routines determine
* the colormap to be used. The rest of the module only assumes that the
* colormap is orthogonal.
*
* * select_ncolors decides how to divvy up the available colors
* among the components.
* * output_value defines the set of representative values for a component.
* * largest_input_value defines the mapping from input values to
* representative values for a component.
* Note that the latter two routines may impose different policies for
* different components, though this is not currently done.
*/
LOCAL int
select_ncolors (decompress_info_ptr cinfo, int Ncolors[])
/* Determine allocation of desired colors to components, */
/* and fill in Ncolors[] array to indicate choice. */
/* Return value is total number of colors (product of Ncolors[] values). */
{
int nc = cinfo->color_out_comps; /* number of color components */
int max_colors = cinfo->desired_number_of_colors;
int total_colors, iroot, i;
long temp;
boolean changed;
/* We can allocate at least the nc'th root of max_colors per component. */
/* Compute floor(nc'th root of max_colors). */
iroot = 1;
do {
iroot++;
temp = iroot; /* set temp = iroot ** nc */
for (i = 1; i < nc; i++)
temp *= iroot;
} while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
iroot--; /* now iroot = floor(root) */
/* Must have at least 2 color values per component */
if (iroot < 2)
ERREXIT1(cinfo->emethods, "Cannot quantize to fewer than %d colors",
(int) temp);
if (cinfo->out_color_space == CS_RGB && nc == 3) {
/* We provide a special policy for quantizing in RGB space.
* If 256 colors are requested, we allocate 8 red, 8 green, 4 blue levels;
* this corresponds to the common 3/3/2-bit scheme. For other totals,
* the counts are set so that the number of colors allocated to each
* component are roughly in the proportion R 3, G 4, B 2.
* For low color counts, it's easier to hardwire the optimal choices
* than try to tweak the algorithm to generate them.
*/
if (max_colors == 256) {
Ncolors[0] = 8; Ncolors[1] = 8; Ncolors[2] = 4;
return 256;
}
if (max_colors < 12) {
/* Fixed mapping for 8 colors */
Ncolors[0] = Ncolors[1] = Ncolors[2] = 2;
} else if (max_colors < 18) {
/* Fixed mapping for 12 colors */
Ncolors[0] = 2; Ncolors[1] = 3; Ncolors[2] = 2;
} else if (max_colors < 24) {
/* Fixed mapping for 18 colors */
Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 2;
} else if (max_colors < 27) {
/* Fixed mapping for 24 colors */
Ncolors[0] = 3; Ncolors[1] = 4; Ncolors[2] = 2;
} else if (max_colors < 36) {
/* Fixed mapping for 27 colors */
Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 3;
} else {
/* these weights are readily derived with a little algebra */
Ncolors[0] = (iroot * 266) >> 8; /* R weight is 1.0400 */
Ncolors[1] = (iroot * 355) >> 8; /* G weight is 1.3867 */
Ncolors[2] = (iroot * 177) >> 8; /* B weight is 0.6934 */
}
total_colors = Ncolors[0] * Ncolors[1] * Ncolors[2];
/* The above computation produces "floor" values, so we may be able to
* increment the count for one or more components without exceeding
* max_colors. We try in the order B, G, R.
*/
do {
changed = FALSE;
for (i = 2; i >= 0; i--) {
/* calculate new total_colors if Ncolors[i] is incremented */
temp = total_colors / Ncolors[i];
temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */
if (temp <= (long) max_colors) {
Ncolors[i]++; /* OK, apply the increment */
total_colors = (int) temp;
changed = TRUE;
}
}
} while (changed); /* loop until no increment is possible */
} else {
/* For any colorspace besides RGB, treat all the components equally. */
/* Initialize to iroot color values for each component */
total_colors = 1;
for (i = 0; i < nc; i++) {
Ncolors[i] = iroot;
total_colors *= iroot;
}
/* We may be able to increment the count for one or more components without
* exceeding max_colors, though we know not all can be incremented.
*/
for (i = 0; i < nc; i++) {
/* calculate new total_colors if Ncolors[i] is incremented */
temp = total_colors / Ncolors[i];
temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */
if (temp > (long) max_colors)
break; /* won't fit, done */
Ncolors[i]++; /* OK, apply the increment */
total_colors = (int) temp;
}
}
return total_colors;
}
LOCAL int
output_value (decompress_info_ptr cinfo, int ci, int j, int maxj)
/* Return j'th output value, where j will range from 0 to maxj */
/* The output values must fall in 0..MAXJSAMPLE in increasing order */
{
/* We always provide values 0 and MAXJSAMPLE for each component;
* any additional values are equally spaced between these limits.
* (Forcing the upper and lower values to the limits ensures that
* dithering can't produce a color outside the selected gamut.)
*/
return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
}
LOCAL int
largest_input_value (decompress_info_ptr cinfo, int ci, int j, int maxj)
/* Return largest input value that should map to j'th output value */
/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
{
/* Breakpoints are halfway between values returned by output_value */
return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
}
/*
* Initialize for one-pass color quantization.
*/
@@ -78,37 +270,22 @@ static boolean on_odd_row; /* flag to remember which row we are on */
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;
int total_colors; /* Number of distinct output colors */
int Ncolors[MAX_COMPONENTS]; /* # of values alloced to each component */
int i,j,k, nci, blksize, blkdist, ptr, val;
if (cinfo->color_out_comps > MAX_COMPONENTS)
/* Make sure my internal arrays won't overflow */
if (cinfo->num_components > MAX_COMPONENTS ||
cinfo->color_out_comps > MAX_COMPONENTS)
ERREXIT1(cinfo->emethods, "Cannot quantize more than %d color components",
MAX_COMPONENTS);
if (max_colors > (MAXJSAMPLE+1))
/* Make sure colormap indexes can be represented by JSAMPLEs */
if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
ERREXIT1(cinfo->emethods, "Cannot request more than %d quantized colors",
MAXJSAMPLE+1);
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;
}
/* Select number of colors for each component */
total_colors = select_ncolors(cinfo, Ncolors);
/* Report selected color counts */
if (cinfo->color_out_comps == 3)
@@ -136,7 +313,7 @@ color_quant_init (decompress_info_ptr cinfo)
blksize = blkdist / nci;
for (j = 0; j < nci; j++) {
/* Compute j'th output value (out of nci) for component */
val = (j * MAXJSAMPLE + (nci-1)/2) / (nci-1);
val = output_value(cinfo, i, j, nci-1);
/* Fill in all colormap entries that have this value of this component */
for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
/* fill in blksize entries beginning at ptr */
@@ -147,31 +324,66 @@ color_quant_init (decompress_info_ptr cinfo)
blkdist = blksize; /* blksize of this color is blkdist of next */
/* fill in colorindex entries for i'th color component */
/* in loop, val = index of current output value, */
/* and k = largest j that maps to current val */
val = 0;
k = largest_input_value(cinfo, i, 0, nci-1);
for (j = 0; j <= MAXJSAMPLE; j++) {
/* compute index of color closest to pixel value j */
val = (j * (nci-1) + CENTERJSAMPLE) / MAXJSAMPLE;
while (j > k) /* advance val if past boundary */
k = largest_input_value(cinfo, i, ++val, nci-1);
/* premultiply so that no multiplication needed in main processing */
colorindex[i][j] = (JSAMPLE) (val * blksize);
}
}
/* 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! */
/* Pass the colormap to the output module. */
/* NB: the output module may continue to use the colormap until shutdown. */
cinfo->colormap = colormap;
cinfo->actual_number_of_colors = total_colors;
(*cinfo->methods->put_color_map) (cinfo, total_colors, colormap);
/* Allocate workspace to hold one row of color-converted data */
input_buffer = (*cinfo->emethods->alloc_small_sarray)
(cinfo->image_width, (long) cinfo->color_out_comps);
/* Allocate Floyd-Steinberg workspace if necessary */
if (cinfo->use_dithering) {
size_t arraysize = (cinfo->image_width + 2L) * cinfo->color_out_comps
* SIZEOF(FSERROR);
size_t arraysize = (size_t) ((cinfo->image_width + 2L) * 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);
for (i = 0; i < cinfo->color_out_comps; i++) {
fserrors[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
/* Initialize the propagated errors to zero. */
jzero_far((void FAR *) fserrors[i], arraysize);
}
on_odd_row = FALSE;
}
}
/*
* Subroutines for color conversion methods.
*/
LOCAL void
do_color_conversion (decompress_info_ptr cinfo, JSAMPIMAGE input_data, int row)
/* Convert the indicated row of the input data into output colorspace */
/* in input_buffer. This requires a little trickery since color_convert */
/* expects to deal with 3-D arrays; fortunately we can fake it out */
/* at fairly low cost. */
{
short ci;
JSAMPARRAY input_hack[MAX_COMPONENTS];
JSAMPARRAY output_hack[MAX_COMPONENTS];
/* create JSAMPIMAGE pointing at specified row of input_data */
for (ci = 0; ci < cinfo->num_components; ci++)
input_hack[ci] = input_data[ci] + row;
/* Create JSAMPIMAGE pointing at input_buffer */
for (ci = 0; ci < cinfo->color_out_comps; ci++)
output_hack[ci] = &(input_buffer[ci]);
(*cinfo->methods->color_convert) (cinfo, 1, cinfo->image_width,
input_hack, output_hack);
}
@@ -185,19 +397,22 @@ color_quantize (decompress_info_ptr cinfo, int num_rows,
/* General case, no dithering */
{
register int pixcode, ci;
register JSAMPROW ptrout;
register long col;
register int row;
register long widthm1 = cinfo->image_width - 1;
int row;
long width = cinfo->image_width;
register int nc = cinfo->color_out_comps;
for (row = 0; row < num_rows; row++) {
for (col = widthm1; col >= 0; col--) {
do_color_conversion(cinfo, input_data, row);
ptrout = output_data[row];
for (col = 0; col < width; col++) {
pixcode = 0;
for (ci = 0; ci < nc; ci++) {
pixcode += GETJSAMPLE(colorindex[ci]
[GETJSAMPLE(input_data[ci][row][col])]);
[GETJSAMPLE(input_buffer[ci][col])]);
}
output_data[row][col] = (JSAMPLE) pixcode;
*ptrout++ = (JSAMPLE) pixcode;
}
}
}
@@ -211,18 +426,22 @@ color_quantize3 (decompress_info_ptr cinfo, int num_rows,
register int pixcode;
register JSAMPROW ptr0, ptr1, ptr2, ptrout;
register long col;
register int row;
register long width = cinfo->image_width;
int row;
JSAMPROW colorindex0 = colorindex[0];
JSAMPROW colorindex1 = colorindex[1];
JSAMPROW colorindex2 = colorindex[2];
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];
do_color_conversion(cinfo, input_data, row);
ptr0 = input_buffer[0];
ptr1 = input_buffer[1];
ptr2 = input_buffer[2];
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++)]);
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptr0++)]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptr1++)]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptr2++)]);
*ptrout++ = (JSAMPLE) pixcode;
}
}
@@ -234,86 +453,102 @@ 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;
register LOCFSERROR cur; /* current error or pixel value */
LOCFSERROR belowerr; /* error for pixel below cur */
LOCFSERROR bpreverr; /* error for below/prev col */
LOCFSERROR bnexterr; /* error for below/next col */
LOCFSERROR delta;
register FSERRPTR errorptr; /* => fserrors[] at column before current */
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
JSAMPROW colorindex_ci;
JSAMPROW colormap_ci;
int pixcode;
int dir; /* 1 for left-to-right, -1 for right-to-left */
int ci;
int nc = cinfo->color_out_comps;
int row;
long col_counter;
long width = cinfo->image_width;
JSAMPLE *range_limit = cinfo->sample_range_limit;
SHIFT_TEMPS
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] = (JSAMPLE) pixcode;
/* propagate error to adjacent pixels */
for (ci = 0; ci < nc; ci++) {
val = thisrowerr[ci] - (FSERROR) 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;
do_color_conversion(cinfo, input_data, row);
/* Initialize output values to 0 so can process components separately */
jzero_far((void FAR *) output_data[row],
(size_t) (width * SIZEOF(JSAMPLE)));
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buffer[ci];
output_ptr = output_data[row];
if (on_odd_row) {
/* work right to left in this row */
input_ptr += width - 1; /* so point to rightmost pixel */
output_ptr += width - 1;
dir = -1;
errorptr = fserrors[ci] + (width+1); /* point to entry after last column */
} else {
/* work left to right in this row */
dir = 1;
errorptr = fserrors[ci]; /* point to entry before first real column */
}
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] = (JSAMPLE) pixcode;
/* propagate error to adjacent pixels */
for (ci = 0; ci < nc; ci++) {
val = thisrowerr[ci] - (FSERROR) 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;
colorindex_ci = colorindex[ci];
colormap_ci = colormap[ci];
/* Preset error values: no error propagated to first pixel from left */
cur = 0;
/* and no error propagated to row below yet */
belowerr = bpreverr = 0;
for (col_counter = width; col_counter > 0; col_counter--) {
/* cur holds the error propagated from the previous pixel on the
* current line. Add the error propagated from the previous line
* to form the complete error correction term for this pixel, and
* round the error term (which is expressed * 16) to an integer.
* RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
* for either sign of the error value.
* Note: errorptr points to *previous* column's array entry.
*/
cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
/* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
* The maximum error is +- MAXJSAMPLE; this sets the required size
* of the range_limit array.
*/
cur += GETJSAMPLE(*input_ptr);
cur = GETJSAMPLE(range_limit[cur]);
/* Select output value, accumulate into output code for this pixel */
pixcode = GETJSAMPLE(colorindex_ci[cur]);
*output_ptr += (JSAMPLE) pixcode;
/* Compute actual representation error at this pixel */
/* Note: we can do this even though we don't have the final */
/* pixel code, because the colormap is orthogonal. */
cur -= GETJSAMPLE(colormap_ci[pixcode]);
/* Compute error fractions to be propagated to adjacent pixels.
* Add these into the running sums, and simultaneously shift the
* next-line error sums left by 1 column.
*/
bnexterr = cur;
delta = cur * 2;
cur += delta; /* form error * 3 */
errorptr[0] = (FSERROR) (bpreverr + cur);
cur += delta; /* form error * 5 */
bpreverr = belowerr + cur;
belowerr = bnexterr;
cur += delta; /* form error * 7 */
/* At this point cur contains the 7/16 error value to be propagated
* to the next pixel on the current line, and all the errors for the
* next line have been shifted over. We are therefore ready to move on.
*/
input_ptr += dir; /* advance input ptr to next column */
output_ptr += dir; /* advance output ptr to next column */
errorptr += dir; /* advance errorptr to current column */
}
on_odd_row = TRUE;
/* Post-loop cleanup: we must unload the final error value into the
* final fserrors[] entry. Note we need not unload belowerr because
* it is for the dummy column before or after the actual array.
*/
errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
}
on_odd_row = (on_odd_row ? FALSE : TRUE);
}
}
@@ -325,15 +560,9 @@ color_quantize_dither (decompress_info_ptr cinfo, int num_rows,
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);
}
/* no work (we let free_all release the workspace) */
/* Note that we *mustn't* free the colormap before free_all, */
/* since output module may use it! */
}
@@ -344,7 +573,7 @@ color_quant_term (decompress_info_ptr cinfo)
METHODDEF void
color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE image_data)
JSAMPIMAGE image_data, JSAMPARRAY workspace)
{
ERREXIT(cinfo->emethods, "Should not get here!");
}

1123
jquant2.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* jrdgif.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -62,7 +62,7 @@ static JSAMPARRAY colormap; /* the colormap to use */
#define INTERLACE 0x40 /* mask for bit signifying interlaced image */
#define COLORMAPFLAG 0x80 /* mask for bit signifying colormap presence */
#define ReadOK(file,buffer,len) (FREAD(file,buffer,len) == ((size_t) (len)))
#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
/* Static vars for GetCode and LZWReadByte */
@@ -196,7 +196,7 @@ GetCode (compress_info_ptr cinfo)
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");
WARNMS(cinfo->emethods, "Ran out of GIF bits");
return end_code; /* fake something useful */
}
/* preserve last two bytes of what we have -- assume code_size <= 16 */
@@ -205,7 +205,7 @@ GetCode (compress_info_ptr cinfo)
/* 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");
WARNMS(cinfo->emethods, "Ran out of GIF bits");
return end_code; /* fake something useful */
}
/* Reset counters */
@@ -249,43 +249,57 @@ LZWReadByte (compress_info_ptr cinfo)
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. */
/* which is expected 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;
code = clear_code; /* enables sharing code with Clear case */
} else {
/* If any codes are stacked from a previously read symbol, return them */
if (sp > symbol_stack)
return (int) *(--sp);
/* Time to read a new symbol */
code = GetCode(cinfo);
}
/* If any codes are stacked from a previously read symbol, return them */
if (sp > symbol_stack)
return (int) *(--sp);
code = GetCode(cinfo);
if (code == clear_code) {
/* Reinit static state, swallow any extra Clear codes, and return */
/* Reinit static state, swallow any extra Clear codes, and */
/* return next code, which is expected to be a raw byte. */
ReInitLZW();
do {
code = GetCode(cinfo);
} while (code == clear_code);
firstcode = oldcode = code; /* gotta reinit these too */
if (code > clear_code) { /* make sure it is a raw byte */
WARNMS(cinfo->emethods, "Corrupt data in GIF file");
code = 0; /* use something valid */
}
firstcode = oldcode = code; /* make firstcode, oldcode valid! */
return code;
}
if (code == end_code) {
/* Skip the rest of the image, unless GetCode already read terminator */
if (! out_of_blocks)
if (! out_of_blocks) {
SkipDataBlocks(cinfo);
return -1;
out_of_blocks = TRUE;
}
/* Complain that there's not enough data */
WARNMS(cinfo->emethods, "Premature end of GIF image");
/* Pad data with 0's */
return 0; /* fake something usable */
}
/* Normal raw byte or LZW symbol */
/* Got normal raw byte or LZW symbol */
incode = code; /* save for a moment */
if (code >= max_code) { /* special case for not-yet-defined symbol */
/* code == max_code is OK; anything bigger is bad data */
if (code > max_code) {
WARNMS(cinfo->emethods, "Corrupt data in GIF file");
incode = 0; /* prevent creation of loops in symbol table */
}
*sp++ = (UINT8) firstcode; /* it will be defined as oldcode/firstcode */
code = oldcode;
}
@@ -365,14 +379,14 @@ input_init (compress_info_ptr cinfo)
/* 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)
if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F')
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))
if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') &&
(hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a'))
TRACEMS3(cinfo->emethods, 1,
"Warning: unexpected GIF version number '%c%c%c'",
hdrbuf[3], hdrbuf[4], hdrbuf[5]);
@@ -418,13 +432,14 @@ input_init (compress_info_ptr cinfo)
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))
if (BitSet(hdrbuf[8], COLORMAPFLAG)) {
colormaplen = 2 << (hdrbuf[8] & 0x07);
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)
@@ -459,6 +474,7 @@ input_init (compress_info_ptr cinfo)
interlaced_image = (*cinfo->emethods->request_big_sarray)
((long) width, (long) height, 1L);
cinfo->methods->get_input_row = load_interlaced_image;
cinfo->total_passes++; /* count file reading as separate pass */
}
/* Return info about the image. */
@@ -466,7 +482,10 @@ input_init (compress_info_ptr cinfo)
cinfo->in_color_space = CS_RGB;
cinfo->image_width = width;
cinfo->image_height = height;
cinfo->data_precision = 8;
cinfo->data_precision = 8; /* always, even if 12-bit JSAMPLEs */
TRACEMS3(cinfo->emethods, 1, "%ux%ux%d GIF image",
(unsigned int) width, (unsigned int) height, colormaplen);
}
@@ -487,8 +506,7 @@ get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
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");
c = LZWReadByte(cinfo);
*ptr0++ = colormap[CM_RED][c];
*ptr1++ = colormap[CM_GREEN][c];
*ptr2++ = colormap[CM_BLUE][c];
@@ -508,20 +526,19 @@ 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++) {
(*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
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++ = (JSAMPLE) c;
*sptr++ = (JSAMPLE) LZWReadByte(cinfo);
}
}
cinfo->completed_passes++;
/* Replace method pointer so subsequent calls don't come here. */
cinfo->methods->get_input_row = get_interlaced_row;
@@ -590,14 +607,7 @@ get_interlaced_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
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);
/* no work (we let free_all release the workspace) */
}

224
jrdjfif.c
View File

@@ -1,23 +1,25 @@
/*
* jrdjfif.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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 code will handle "raw JPEG" and JFIF-convention JPEG files.
*
* You can also use this module to decode a raw-JPEG or JFIF-standard data
* stream that is embedded within a larger file. To do that, you must
* position the file to the JPEG SOI marker (0xFF/0xD8) that begins the
* data sequence to be decoded. If nothing better is possible, you can scan
* the file until you see the SOI marker, then use JUNGETC to push it back.
*
* 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.
* Therefore, this module is not dependent on any particular assumption about
* the data source; it need not be a stdio stream at all. (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.)
*
* These routines are invoked via the methods read_file_header,
* read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
@@ -85,7 +87,10 @@ typedef enum { /* JPEG marker codes */
/*
* 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.
* See the JGETC macro for calling conditions. Note in particular that
* read_jpeg_data may NOT return EOF. If no more data is available, it must
* exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker).
* For error recovery purposes, synthesizing an EOI marker is probably best.
*
* For this header control module, read_jpeg_data is supplied by the
* user interface. However, header formats that require random access
@@ -100,12 +105,16 @@ read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
cinfo->bytes_in_buffer = (int) FREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
if (cinfo->bytes_in_buffer <= 0)
ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
if (cinfo->bytes_in_buffer <= 0) {
WARNMS(cinfo->emethods, "Premature EOF in JPEG file");
cinfo->next_input_byte[0] = (char) 0xFF;
cinfo->next_input_byte[1] = (char) M_EOI;
cinfo->bytes_in_buffer = 2;
}
return JGETC(cinfo);
}
@@ -169,6 +178,8 @@ get_dht (decompress_info_ptr cinfo)
count += bits[i];
}
length -= 1 + 16;
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]);
@@ -176,13 +187,13 @@ get_dht (decompress_info_ptr cinfo)
bits[9], bits[10], bits[11], bits[12],
bits[13], bits[14], bits[15], bits[16]);
if (count > 256)
if (count > 256 || ((INT32) count) > length)
ERREXIT(cinfo->emethods, "Bogus DHT counts");
for (i = 0; i < count; i++)
huffval[i] = (UINT8) JGETC(cinfo);
length -= 1 + 16 + count;
length -= count;
if (index & 0x10) { /* AC table definition */
index -= 0x10;
@@ -197,10 +208,8 @@ get_dht (decompress_info_ptr cinfo)
if (*htblptr == NULL)
*htblptr = (HUFF_TBL *) (*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));
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
}
}
@@ -273,7 +282,7 @@ get_dqt (decompress_info_ptr cinfo)
}
for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo->emethods, 2, " %4d %4d %4d %4d %4d %4d %4d %4d",
TRACEMS8(cinfo->emethods, 2, " %4u %4u %4u %4u %4u %4u %4u %4u",
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]);
}
@@ -294,7 +303,7 @@ get_dri (decompress_info_ptr cinfo)
cinfo->restart_interval = (UINT16) get_2bytes(cinfo);
TRACEMS1(cinfo->emethods, 1,
"Define Restart Interval %d", cinfo->restart_interval);
"Define Restart Interval %u", cinfo->restart_interval);
}
@@ -316,15 +325,15 @@ get_app0 (decompress_info_ptr cinfo)
b[buffp] = (UINT8) JGETC(cinfo);
length -= JFIF_LEN;
if (b[0]=='J' && b[1]=='F' && b[2]=='I' && b[3]=='F' && b[4]==0) {
if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && 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",
/* Minor version should be 0..2, but try to process anyway if newer */
if (b[6] > 2)
TRACEMS2(cinfo->emethods, 1, "Warning: unknown JFIF revision number %d.%02d",
b[5], b[6]);
/* Save info */
cinfo->density_unit = b[7];
@@ -335,19 +344,41 @@ get_app0 (decompress_info_ptr cinfo)
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);
if (b[12] | b[13])
TRACEMS2(cinfo->emethods, 1, " with %d x %d thumbnail image",
b[12], b[13]);
if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3))
TRACEMS1(cinfo->emethods, 1,
"Warning: thumbnail image size does not match data length %u",
(int) length);
} else {
TRACEMS(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF)");
TRACEMS1(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF), length %u",
(int) length + JFIF_LEN);
}
} else {
TRACEMS1(cinfo->emethods, 1,
"Short APP0 marker, length %d", (int) length);
TRACEMS1(cinfo->emethods, 1, "Short APP0 marker, length %u", (int) length);
}
while (length-- > 0) /* skip any remaining data */
while (--length >= 0) /* skip any remaining data */
(void) JGETC(cinfo);
}
LOCAL void
get_com (decompress_info_ptr cinfo)
/* Process a COM marker */
/* Actually we just pass this off to an application-supplied routine */
{
INT32 length;
length = get_2bytes(cinfo) - 2;
TRACEMS1(cinfo->emethods, 1, "Comment, length %u", (int) length);
(*cinfo->methods->process_comment) (cinfo, (long) length);
}
LOCAL void
get_sof (decompress_info_ptr cinfo, int code)
/* Process a SOFn marker */
@@ -403,7 +434,8 @@ get_sof (decompress_info_ptr cinfo, int code)
compptr->h_samp_factor = (c >> 4) & 15;
compptr->v_samp_factor = (c ) & 15;
compptr->quant_tbl_no = JGETC(cinfo);
compptr->component_needed = TRUE; /* assume all components are wanted */
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);
@@ -498,27 +530,28 @@ next_marker (decompress_info_ptr cinfo)
c = JGETC(cinfo);
} while (c != 0xFF);
do { /* skip any duplicate FFs */
nbytes++;
/* we don't increment nbytes here since extra FFs are legal */
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);
if (nbytes != 1)
WARNMS2(cinfo->emethods,
"Corrupt JPEG data: %d extraneous bytes before marker 0x%02x",
nbytes-1, c);
return c;
}
LOCAL JPEG_MARKER
LOCAL int
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) {
for (;;) {
c = next_marker(cinfo);
switch (c) {
@@ -539,7 +572,7 @@ process_tables (decompress_info_ptr cinfo)
case M_SOI:
case M_EOI:
case M_SOS:
return ((JPEG_MARKER) c);
return c;
case M_DHT:
get_dht(cinfo);
@@ -560,6 +593,10 @@ process_tables (decompress_info_ptr cinfo)
case M_APP0:
get_app0(cinfo);
break;
case M_COM:
get_com(cinfo);
break;
case M_RST0: /* these are all parameterless */
case M_RST1:
@@ -573,7 +610,7 @@ process_tables (decompress_info_ptr cinfo)
TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
break;
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
default: /* must be DNL, DHP, EXP, APPn, JPGn, or RESn */
skip_variable(cinfo, c);
break;
}
@@ -591,11 +628,15 @@ 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");
/* Demand an SOI marker at the start of the file --- otherwise it's
* probably not a JPEG file at all. If the user interface wants to support
* nonstandard headers in front of the SOI, it must skip over them itself
* before calling jpeg_decompress().
*/
if (JGETC(cinfo) != 0xFF || JGETC(cinfo) != (int) M_SOI)
ERREXIT(cinfo->emethods, "Not a JPEG file");
get_soi(cinfo); /* OK, process SOI */
/* Process markers until SOF */
c = process_tables(cinfo);
@@ -638,7 +679,7 @@ read_file_header (decompress_info_ptr cinfo)
else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
else {
TRACEMS3(cinfo->emethods, 0,
TRACEMS3(cinfo->emethods, 1,
"Unrecognized component IDs %d %d %d, assuming YCbCr",
cid0, cid1, cid2);
cinfo->jpeg_color_space = CS_YCbCr;
@@ -687,6 +728,94 @@ read_scan_header (decompress_info_ptr cinfo)
}
/*
* The entropy decoder calls this routine if it finds a marker other than
* the restart marker it was expecting. (This code is *not* used unless
* a nonzero restart interval has been declared.) The passed parameter is
* the marker code actually found (might be anything, except 0 or FF).
* The desired restart marker is that indicated by cinfo->next_restart_num.
* This routine is supposed to apply whatever error recovery strategy seems
* appropriate in order to position the input stream to the next data segment.
* For some file formats (eg, TIFF) extra information such as tile boundary
* pointers may be available to help in this decision.
*
* This implementation is substantially constrained by wanting to treat the
* input as a data stream; this means we can't back up. (For instance, we
* generally can't fseek() if the input is a Unix pipe.) Therefore, we have
* only the following actions to work with:
* 1. Do nothing, let the entropy decoder resume at next byte of file.
* 2. Read forward until we find another marker, discarding intervening
* data. (In theory we could look ahead within the current bufferload,
* without having to discard data if we don't find the desired marker.
* This idea is not implemented here, in part because it makes behavior
* dependent on buffer size and chance buffer-boundary positions.)
* 3. Push back the passed marker (with JUNGETC). This will cause the
* entropy decoder to process an empty data segment, inserting dummy
* zeroes, and then re-read the marker we pushed back.
* #2 is appropriate if we think the desired marker lies ahead, while #3 is
* appropriate if the found marker is a future restart marker (indicating
* that we have missed the desired restart marker, probably because it got
* corrupted).
* We apply #2 or #3 if the found marker is a restart marker no more than
* two counts behind or ahead of the expected one. We also apply #2 if the
* found marker is not a legal JPEG marker code (it's certainly bogus data).
* If the found marker is a restart marker more than 2 counts away, we do #1
* (too much risk that the marker is erroneous; with luck we will be able to
* resync at some future point).
* For any valid non-restart JPEG marker, we apply #3. This keeps us from
* overrunning the end of a scan. An implementation limited to single-scan
* files might find it better to apply #2 for markers other than EOI, since
* any other marker would have to be bogus data in that case.
*/
METHODDEF void
resync_to_restart (decompress_info_ptr cinfo, int marker)
{
int desired = cinfo->next_restart_num;
int action = 1;
/* Always put up a warning. */
WARNMS2(cinfo->emethods,
"Corrupt JPEG data: found 0x%02x marker instead of RST%d",
marker, desired);
/* Outer loop handles repeated decision after scanning forward. */
for (;;) {
if (marker < (int) M_SOF0)
action = 2; /* invalid marker */
else if (marker < (int) M_RST0 || marker > (int) M_RST7)
action = 3; /* valid non-restart marker */
else {
if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
marker == ((int) M_RST0 + ((desired+2) & 7)))
action = 3; /* one of the next two expected restarts */
else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
marker == ((int) M_RST0 + ((desired-2) & 7)))
action = 2; /* a prior restart, so advance */
else
action = 1; /* desired restart or too far away */
}
TRACEMS2(cinfo->emethods, 4,
"At marker 0x%02x, recovery action %d", marker, action);
switch (action) {
case 1:
/* Let entropy decoder resume processing. */
return;
case 2:
/* Scan to the next marker, and repeat the decision loop. */
marker = next_marker(cinfo);
break;
case 3:
/* Put back this marker & return. */
/* Entropy decoder will be forced to process an empty segment. */
JUNGETC(marker, cinfo);
JUNGETC(0xFF, cinfo);
return;
}
}
}
/*
* Finish up after a compressed scan (series of read_jpeg_data calls);
* prepare for another read_scan_header call.
@@ -727,6 +856,7 @@ jselrjfif (decompress_info_ptr cinfo)
#if 0
cinfo->methods->read_jpeg_data = read_jpeg_data;
#endif
cinfo->methods->resync_to_restart = resync_to_restart;
cinfo->methods->read_scan_trailer = read_scan_trailer;
cinfo->methods->read_file_trailer = read_file_trailer;
}

154
jrdppm.c
View File

@@ -1,7 +1,7 @@
/*
* jrdppm.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -25,9 +25,6 @@
#ifdef PPM_SUPPORTED
static JSAMPLE * rescale; /* => maxval-remapping array, or NULL */
/* Portions of this code are based on the PBMPLUS library, which is:
**
** Copyright (C) 1988 by Jef Poskanzer.
@@ -41,6 +38,41 @@ static JSAMPLE * rescale; /* => maxval-remapping array, or NULL */
*/
/* Macros to deal with unsigned chars as efficiently as compiler allows */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char U_CHAR;
#define UCH(x) ((int) (x))
#else /* !HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char U_CHAR;
#define UCH(x) ((int) (x))
#else
typedef char U_CHAR;
#define UCH(x) ((int) (x) & 0xFF)
#endif
#endif /* HAVE_UNSIGNED_CHAR */
#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
/*
* On most systems, reading individual bytes with getc() is drastically less
* efficient than buffering a row at a time with fread(). But we must
* allocate the row buffer in near data space on PCs, because we are assuming
* small-data memory model, wherein fread() can't reach far memory. If you
* need to process very wide images on a PC, you may have to use the getc()
* approach. In that case, define USE_GETC_INPUT.
*/
#ifndef USE_GETC_INPUT
static U_CHAR * row_buffer; /* holds 1 pixel row's worth of raw input */
#endif
static JSAMPLE * rescale; /* => maxval-remapping array, or NULL */
LOCAL int
pbm_getc (FILE * file)
/* Read next char, skipping over any comments */
@@ -73,7 +105,7 @@ read_pbm_integer (compress_info_ptr cinfo)
ch = pbm_getc(cinfo->input_file);
if (ch == EOF)
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
} while (ch == ' ' || ch == '\t' || ch == '\n');
} while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
if (ch < '0' || ch > '9')
ERREXIT(cinfo->emethods, "Bogus data in PPM file");
@@ -145,6 +177,9 @@ get_text_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
}
#ifdef USE_GETC_INPUT
METHODDEF void
get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading raw-format PGM files with any maxval */
@@ -213,6 +248,92 @@ get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
}
#else /* use row buffering */
METHODDEF void
get_scaled_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading raw-format PGM files with any maxval */
{
register JSAMPROW ptr0;
register U_CHAR * row_bufferptr;
register long col;
if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
ptr0 = pixel_row[0];
row_bufferptr = row_buffer;
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = rescale[UCH(*row_bufferptr++)];
}
}
METHODDEF void
get_scaled_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading raw-format PPM files with any maxval */
{
register JSAMPROW ptr0, ptr1, ptr2;
register U_CHAR * row_bufferptr;
register long col;
if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
row_bufferptr = row_buffer;
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = rescale[UCH(*row_bufferptr++)];
*ptr1++ = rescale[UCH(*row_bufferptr++)];
*ptr2++ = rescale[UCH(*row_bufferptr++)];
}
}
METHODDEF void
get_raw_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading raw-format PGM files with maxval = MAXJSAMPLE */
{
register JSAMPROW ptr0;
register U_CHAR * row_bufferptr;
register long col;
if (! ReadOK(cinfo->input_file, row_buffer, cinfo->image_width))
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
ptr0 = pixel_row[0];
row_bufferptr = row_buffer;
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = (JSAMPLE) UCH(*row_bufferptr++);
}
}
METHODDEF void
get_raw_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading raw-format PPM files with maxval = MAXJSAMPLE */
{
register JSAMPROW ptr0, ptr1, ptr2;
register U_CHAR * row_bufferptr;
register long col;
if (! ReadOK(cinfo->input_file, row_buffer, 3 * cinfo->image_width))
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
row_bufferptr = row_buffer;
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = (JSAMPLE) UCH(*row_bufferptr++);
*ptr1++ = (JSAMPLE) UCH(*row_bufferptr++);
*ptr2++ = (JSAMPLE) UCH(*row_bufferptr++);
}
}
#endif /* USE_GETC_INPUT */
/*
* Read the file header; return image size and component count.
*/
@@ -232,17 +353,22 @@ input_init (compress_info_ptr cinfo)
h = read_pbm_integer(cinfo);
maxval = read_pbm_integer(cinfo);
if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
ERREXIT(cinfo->emethods, "Not a PPM file");
switch (c) {
case '2': /* it's a text-format PGM file */
cinfo->methods->get_input_row = get_text_gray_row;
cinfo->input_components = 1;
cinfo->in_color_space = CS_GRAYSCALE;
TRACEMS2(cinfo->emethods, 1, "%ux%u text PGM image", w, h);
break;
case '3': /* it's a text-format PPM file */
cinfo->methods->get_input_row = get_text_rgb_row;
cinfo->input_components = 3;
cinfo->in_color_space = CS_RGB;
TRACEMS2(cinfo->emethods, 1, "%ux%u text PPM image", w, h);
break;
case '5': /* it's a raw-format PGM file */
@@ -252,6 +378,12 @@ input_init (compress_info_ptr cinfo)
cinfo->methods->get_input_row = get_scaled_gray_row;
cinfo->input_components = 1;
cinfo->in_color_space = CS_GRAYSCALE;
#ifndef USE_GETC_INPUT
/* allocate space for row buffer: 1 byte/pixel */
row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
((size_t) (SIZEOF(U_CHAR) * (long) w));
#endif
TRACEMS2(cinfo->emethods, 1, "%ux%u PGM image", w, h);
break;
case '6': /* it's a raw-format PPM file */
@@ -261,6 +393,12 @@ input_init (compress_info_ptr cinfo)
cinfo->methods->get_input_row = get_scaled_rgb_row;
cinfo->input_components = 3;
cinfo->in_color_space = CS_RGB;
#ifndef USE_GETC_INPUT
/* allocate space for row buffer: 3 bytes/pixel */
row_buffer = (U_CHAR *) (*cinfo->emethods->alloc_small)
((size_t) (3 * SIZEOF(U_CHAR) * (long) w));
#endif
TRACEMS2(cinfo->emethods, 1, "%ux%u PPM image", w, h);
break;
default:
@@ -268,9 +406,6 @@ input_init (compress_info_ptr cinfo)
break;
}
if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
ERREXIT(cinfo->emethods, "Not a PPM file");
/* Compute the rescaling array if necessary */
/* This saves per-pixel calculation */
if (maxval == MAXJSAMPLE)
@@ -301,8 +436,7 @@ input_init (compress_info_ptr cinfo)
METHODDEF void
input_term (compress_info_ptr cinfo)
{
if (rescale != NULL)
(*cinfo->emethods->free_small) ((void *) rescale);
/* no work (we let free_all release the workspace) */
}

View File

@@ -1,7 +1,7 @@
/*
* jrdrle.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -157,6 +157,8 @@ input_init (compress_info_ptr cinfo)
cinfo->input_components = 3;
break;
}
cinfo->total_passes++; /* count file reading as separate pass */
}
@@ -282,6 +284,7 @@ load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
case GRAYSCALE:
case PSEUDOCOLOR:
for (row = 0; row < cinfo->image_height; row++) {
(*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
/*
* Read a row of the image directly into our big array.
* Too bad this doesn't seem to return any indication of errors :-(.
@@ -294,6 +297,7 @@ load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
case TRUECOLOR:
case DIRECTCOLOR:
for (row = 0; row < cinfo->image_height; row++) {
(*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
/*
* Read a row of the image directly into our big arrays.
* Too bad this doesn't seem to return any indication of errors :-(.
@@ -308,6 +312,7 @@ load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
}
break;
}
cinfo->completed_passes++;
/* Set up to call proper row-extraction routine in future */
switch (visual) {
@@ -338,18 +343,7 @@ load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
METHODDEF void
input_term (compress_info_ptr cinfo)
{
switch (visual) {
case GRAYSCALE:
case PSEUDOCOLOR:
(*cinfo->emethods->free_big_sarray) (image);
break;
case TRUECOLOR:
case DIRECTCOLOR:
(*cinfo->emethods->free_big_sarray) (red_channel);
(*cinfo->emethods->free_big_sarray) (green_channel);
(*cinfo->emethods->free_big_sarray) (blue_channel);
break;
}
/* no work (we let free_all release the workspace) */
}

View File

@@ -1,7 +1,7 @@
/*
* jrdtarga.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -41,7 +41,7 @@ typedef char U_CHAR;
#endif /* HAVE_UNSIGNED_CHAR */
#define ReadOK(file,buffer,len) (FREAD(file,buffer,len) == ((size_t) (len)))
#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
static JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
@@ -242,34 +242,14 @@ get_24bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
}
}
METHODDEF void
get_32bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading 32-bit pixels */
/* Attribute bits are ignored for now */
{
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
/* NOTE: there seems to be considerable confusion over whether the order
* of the bytes in a 32-bit Targa file is A,B,G,R or B,G,R,A.
* On Lee Crocker's authority, we think the attribute byte comes first.
* Make ATTR_BYTE_FIRST be 0 if you have files in which it comes last.
/*
* Targa also defines a 32-bit pixel format with order B,G,R,A.
* We presently ignore the attribute byte, so the code for reading
* these pixels is identical to the 24-bit routine above.
* This works because the actual pixel length is only known to read_pixel.
*/
#ifndef ATTR_BYTE_FIRST /* so you can say -DATTR_BYTE_FIRST=0 in Makefile */
#define ATTR_BYTE_FIRST 1 /* must be 0 or 1 */
#endif
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
(*read_pixel) (cinfo); /* Load next pixel into tga_pixel */
/* convert ABGR (or BGRA) to RGB order */
*ptr0++ = (JSAMPLE) UCH(tga_pixel[2+ATTR_BYTE_FIRST]);
*ptr1++ = (JSAMPLE) UCH(tga_pixel[1+ATTR_BYTE_FIRST]);
*ptr2++ = (JSAMPLE) UCH(tga_pixel[0+ATTR_BYTE_FIRST]);
}
}
#define get_32bit_row get_24bit_row
/*
@@ -314,10 +294,13 @@ preload_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* Read the data into a virtual array in input-file row order */
for (row = 0; row < cinfo->image_height; row++) {
(*cinfo->methods->progress_monitor) (cinfo, row, cinfo->image_height);
image_ptr = (*cinfo->emethods->access_big_sarray)
(whole_image, row * cinfo->input_components, TRUE);
(*get_pixel_row) (cinfo, image_ptr);
}
cinfo->completed_passes++;
/* Set up to read from the virtual array in unscrambled order */
cinfo->methods->get_input_row = get_memory_row;
current_row = 0;
@@ -386,6 +369,8 @@ input_init (compress_info_ptr cinfo)
get_pixel_row = get_8bit_row;
else
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
TRACEMS2(cinfo->emethods, 1, "%ux%u colormapped Targa image",
width, height);
break;
case 2: /* RGB image */
switch (pixel_size) {
@@ -402,6 +387,8 @@ input_init (compress_info_ptr cinfo)
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
break;
}
TRACEMS2(cinfo->emethods, 1, "%ux%u RGB Targa image",
width, height);
break;
case 3: /* Grayscale image */
components = 1;
@@ -410,6 +397,8 @@ input_init (compress_info_ptr cinfo)
get_pixel_row = get_8bit_gray_row;
else
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
TRACEMS2(cinfo->emethods, 1, "%ux%u grayscale Targa image",
width, height);
break;
default:
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
@@ -421,6 +410,7 @@ input_init (compress_info_ptr cinfo)
((long) width, (long) height * components,
(long) components);
cinfo->methods->get_input_row = preload_image;
cinfo->total_passes++; /* count file reading as separate pass */
} else {
whole_image = NULL;
cinfo->methods->get_input_row = get_pixel_row;
@@ -457,10 +447,7 @@ input_init (compress_info_ptr cinfo)
METHODDEF void
input_term (compress_info_ptr cinfo)
{
if (whole_image != NULL)
(*cinfo->emethods->free_big_sarray) (whole_image);
if (colormap != NULL)
(*cinfo->emethods->free_small_sarray) (colormap, 3L);
/* no work (we let free_all release the workspace) */
}

496
jrevdct.c
View File

@@ -1,229 +1,369 @@
/*
* jrevdct.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
* The primary algorithm described there uses 11 multiplies and 29 adds.
* We use their alternate method with 12 multiplies and 32 adds.
* The advantage of this method is that no data path contains more than one
* multiplication; this allows a very simple and accurate implementation in
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#include "jinclude.h"
/* We assume that right shift corresponds to signed division by 2 with
* rounding towards minus infinity. This is correct for typical "arithmetic
* shift" instructions that shift in copies of the sign bit. But some
* C compilers implement >> with an unsigned shift. For these machines you
* must define RIGHT_SHIFT_IS_UNSIGNED.
* RIGHT_SHIFT provides a signed right shift of an INT32 quantity.
* It is only applied with constant shift counts.
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS INT32 shift_temp;
#define RIGHT_SHIFT(x,shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~0) << (32-(shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* The poop on this scaling stuff is as follows:
/*
* A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
* larger than the true IDCT outputs. The final outputs are therefore
* a factor of N larger than desired; since N=8 this can be cured by
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D IDCT,
* because the y0 and y4 inputs need not be divided by sqrt(N).
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
* a problem to do in integer arithmetic. We multiply all the constants
* by DCT_SCALE and convert them to integer constants (thus retaining
* LG2_DCT_SCALE bits of precision in the constants). After doing a
* multiplication we have to divide the product by DCT_SCALE, with proper
* rounding, to produce the correct output. The division can be implemented
* cheaply as a right shift of LG2_DCT_SCALE bits. The DCT equations also
* specify an additional division by 2 on the final outputs; this can be
* folded into the right-shift by shifting one more bit (see UNFIXH).
* by CONST_SCALE and convert them to integer constants (thus retaining
* CONST_BITS bits of precision in the constants). After doing a
* multiplication we have to divide the product by CONST_SCALE, with proper
* rounding, to produce the correct output. This division can be done
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
* as long as possible so that partial sums can be added together with
* full fractional precision.
*
* If you are planning to recode this in assembler, you might want to set
* LG2_DCT_SCALE to 15. This loses a bit of precision, but then all the
* multiplications are between 16-bit quantities (given 8-bit JSAMPLEs!)
* so you could use a signed 16x16=>32 bit multiply instruction instead of
* full 32x32 multiply. Unfortunately there's no way to describe such a
* multiply portably in C, so we've gone for the extra bit of accuracy here.
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (To scale up 12-bit sample data further, an
* intermediate INT32 array would be needed.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
* shows that the values given below are the most effective.
*/
#ifdef EIGHT_BIT_SAMPLES
#define LG2_DCT_SCALE 16
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
#define CONST_SCALE (ONE << CONST_BITS)
/* In some places we shift the inputs left by a couple more bits, */
/* so that they can be added to fractional results without too much */
/* loss of precision. */
#define LG2_OVERSCALE 2
#define OVERSCALE (ONE << LG2_OVERSCALE)
#define OVERSHIFT(x) ((x) <<= LG2_OVERSCALE)
/* Convert a positive real constant to an integer scaled by CONST_SCALE. */
/* Scale a fractional constant by DCT_SCALE */
#define FIX(x) ((INT32) ((x) * DCT_SCALE + 0.5))
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Scale a fractional constant by DCT_SCALE/OVERSCALE */
/* Such a constant can be multiplied with an overscaled input */
/* to produce something that's scaled by DCT_SCALE */
#define FIXO(x) ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
/* Descale and correctly round a value that's scaled by DCT_SCALE */
#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
/* Same with an additional division by 2, ie, correctly rounded UNFIX(x/2) */
#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
/* Take a value scaled by DCT_SCALE and round to integer scaled by OVERSCALE */
#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)),\
LG2_DCT_SCALE-LG2_OVERSCALE)
/* Here are the constants we need */
/* SIN_i_j is sine of i*pi/j, scaled by DCT_SCALE */
/* COS_i_j is cosine of i*pi/j, scaled by DCT_SCALE */
#define SIN_1_4 FIX(0.707106781)
#define COS_1_4 SIN_1_4
#define SIN_1_8 FIX(0.382683432)
#define COS_1_8 FIX(0.923879533)
#define SIN_3_8 COS_1_8
#define COS_3_8 SIN_1_8
#define SIN_1_16 FIX(0.195090322)
#define COS_1_16 FIX(0.980785280)
#define SIN_7_16 COS_1_16
#define COS_7_16 SIN_1_16
#define SIN_3_16 FIX(0.555570233)
#define COS_3_16 FIX(0.831469612)
#define SIN_5_16 COS_3_16
#define COS_5_16 SIN_3_16
/* OSIN_i_j is sine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */
/* OCOS_i_j is cosine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */
#define OSIN_1_4 FIXO(0.707106781)
#define OCOS_1_4 OSIN_1_4
#define OSIN_1_8 FIXO(0.382683432)
#define OCOS_1_8 FIXO(0.923879533)
#define OSIN_3_8 OCOS_1_8
#define OCOS_3_8 OSIN_1_8
#define OSIN_1_16 FIXO(0.195090322)
#define OCOS_1_16 FIXO(0.980785280)
#define OSIN_7_16 OCOS_1_16
#define OCOS_7_16 OSIN_1_16
#define OSIN_3_16 FIXO(0.555570233)
#define OCOS_3_16 FIXO(0.831469612)
#define OSIN_5_16 OCOS_3_16
#define OCOS_5_16 OSIN_3_16
/*
* Perform a 1-dimensional inverse DCT.
* Note that this code is specialized to the case DCTSIZE = 8.
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
INLINE
LOCAL void
fast_idct_8 (DCTELEM *in, int stride)
{
/* many tmps have nonoverlapping lifetime -- flashy register colourers
* should be able to do this lot very well
*/
INT32 in0, in1, in2, in3, in4, in5, in6, in7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 tmp20, tmp21, tmp22, tmp23;
INT32 tmp30, tmp31;
INT32 tmp40, tmp41, tmp42, tmp43;
INT32 tmp50, tmp51, tmp52, tmp53;
SHIFT_TEMPS
#if CONST_BITS == 13
#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_175875602 FIX(1.175875602)
#define FIX_1_501321110 FIX(1.501321110)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_1_961570560 FIX(1.961570560)
#define FIX_2_053119869 FIX(2.053119869)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_072711026 FIX(3.072711026)
#endif
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];
/* These values are scaled by DCT_SCALE */
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
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;
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* These values are scaled by OVERSCALE */
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
*/
tmp30 = UNFIXO((in3 + in5) * COS_1_4);
tmp31 = UNFIXO((in3 - in5) * COS_1_4);
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
OVERSHIFT(in1);
OVERSHIFT(in7);
tmp40 = in1 + tmp30;
tmp41 = in7 + tmp31;
tmp42 = in1 - tmp30;
tmp43 = in7 - tmp31;
/* And these are scaled by DCT_SCALE */
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] = (DCTELEM) UNFIXH(tmp20 + tmp50);
in[stride ] = (DCTELEM) UNFIXH(tmp21 + tmp53);
in[stride*2] = (DCTELEM) UNFIXH(tmp22 + tmp52);
in[stride*3] = (DCTELEM) UNFIXH(tmp23 + tmp51);
in[stride*4] = (DCTELEM) UNFIXH(tmp23 - tmp51);
in[stride*5] = (DCTELEM) UNFIXH(tmp22 - tmp52);
in[stride*6] = (DCTELEM) UNFIXH(tmp21 - tmp53);
in[stride*7] = (DCTELEM) UNFIXH(tmp20 - tmp50);
}
#ifndef MULTIPLY /* default definition */
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the inverse DCT on one block of coefficients.
*
* A 2-D IDCT can be done by 1-D IDCT on each row
* followed by 1-D IDCT on each column.
*/
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);
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any row in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* row DCT calculations can be simplified this way.
*/
if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
dataptr[5] | dataptr[6] | dataptr[7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS);
dataptr[0] = dcval;
dataptr[1] = dcval;
dataptr[2] = dcval;
dataptr[3] = dcval;
dataptr[4] = dcval;
dataptr[5] = dcval;
dataptr[6] = dcval;
dataptr[7] = dcval;
dataptr += DCTSIZE; /* advance pointer to next row */
continue;
}
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[2];
z3 = (INT32) dataptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[7];
tmp1 = (INT32) dataptr[5];
tmp2 = (INT32) dataptr[3];
tmp3 = (INT32) dataptr[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Columns of zeroes can be exploited in the same way as we did with rows.
* However, the row calculation has created many nonzero AC terms, so the
* simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
#ifndef NO_ZERO_COLUMN_TEST
if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
dataptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3);
dataptr[DCTSIZE*0] = dcval;
dataptr[DCTSIZE*1] = dcval;
dataptr[DCTSIZE*2] = dcval;
dataptr[DCTSIZE*3] = dcval;
dataptr[DCTSIZE*4] = dcval;
dataptr[DCTSIZE*5] = dcval;
dataptr[DCTSIZE*6] = dcval;
dataptr[DCTSIZE*7] = dcval;
dataptr++; /* advance pointer to next column */
continue;
}
#endif
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[DCTSIZE*2];
z3 = (INT32) dataptr[DCTSIZE*6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[DCTSIZE*7];
tmp1 = (INT32) dataptr[DCTSIZE*5];
tmp2 = (INT32) dataptr[DCTSIZE*3];
tmp3 = (INT32) dataptr[DCTSIZE*1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr++; /* advance pointer to next column */
}
}

View File

@@ -1,7 +1,7 @@
/*
* jutils.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 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.
*
@@ -23,6 +23,26 @@ jround_up (long a, long b)
}
/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
* and coefficient-block arrays. This won't work on 80x86 because the arrays
* are FAR and we're assuming a small-pointer memory model. However, some
* DOS compilers provide far-pointer versions of memcpy() and memset() even
* in the small-model libraries. These will be used if USE_FMEM is defined.
* Otherwise, the routines below do it the hard way. (The performance cost
* is not all that great, because these routines aren't very heavily used.)
*/
#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */
#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size)
#define FMEMZERO(target,size) MEMZERO(target,size)
#else /* 80x86 case, define if we can */
#ifdef USE_FMEM
#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
#endif
#endif
GLOBAL void
jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
JSAMPARRAY output_array, int dest_row,
@@ -33,14 +53,11 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
* 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;
#ifdef FMEMCOPY
register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
#else
register size_t count = num_cols * SIZEOF(JSAMPLE);
register long count;
#endif
register int row;
@@ -50,11 +67,11 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
for (row = num_rows; row > 0; row--) {
inptr = *input_array++;
outptr = *output_array++;
#ifdef NEED_FAR_POINTERS
#ifdef FMEMCOPY
FMEMCOPY(outptr, inptr, count);
#else
for (count = num_cols; count > 0; count--)
*outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
#else
memcpy((void *) outptr, (void *) inptr, count);
#endif
}
}
@@ -64,23 +81,17 @@ 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
#ifdef FMEMCOPY
FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
#else
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++;
inptr = (JCOEFPTR) input_row;
outptr = (JCOEFPTR) output_row;
for (count = num_blocks * DCTSIZE2; count > 0; count--) {
*outptr++ = *inptr++;
}
#else
memcpy((void *) output_row, (void *) input_row,
(size_t) (num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))));
#endif
}
@@ -90,17 +101,14 @@ 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
#ifdef FMEMZERO
FMEMZERO(target, bytestozero);
#else
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
}

View File

@@ -1,7 +1,7 @@
/*
* jversion.h
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -9,6 +9,6 @@
*/
#define JVERSION "2 13-Dec-91"
#define JVERSION "4A 18-Feb-93"
#define JCOPYRIGHT "Copyright (C) 1991, Thomas G. Lane"
#define JCOPYRIGHT "Copyright (C) 1993, Thomas G. Lane"

View File

@@ -1,614 +0,0 @@
/*
* 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.
*/
#define AM_MEMORY_MANAGER /* we define big_Xarray_control structs */
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#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 */
/*
* When allocating 2-D arrays we can either ask malloc() for each row
* individually, or grab the whole space in one chunk. The latter is
* a lot faster on large arrays, but fails if malloc can't handle big
* requests, as is typically true on MS-DOS.
* We assume here that big malloc requests are safe whenever
* NEED_FAR_POINTERS is not defined, but you can change this if you are
* on a weird machine.
*/
#ifndef NEED_FAR_POINTERS
#define BIG_MALLOCS_OK /* safe to ask far_malloc for > 64Kb */
#endif
/*
* 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;
#ifdef BIG_MALLOCS_OK
JSAMPROW workspace;
#endif
long i;
#ifdef MEM_STATS
total_num_sarray++;
#ifdef BIG_MALLOCS_OK
total_bytes_sarray += numrows * samplesperrow * SIZEOF(JSAMPLE)
+ MALLOC_FAR_OVERHEAD;
#else
total_bytes_sarray += (samplesperrow * SIZEOF(JSAMPLE) + MALLOC_FAR_OVERHEAD)
* numrows;
#endif
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" */
#ifdef BIG_MALLOCS_OK
workspace = (JSAMPROW) far_malloc((size_t)
(numrows * samplesperrow * SIZEOF(JSAMPLE)));
if (workspace == NULL)
out_of_memory(3);
for (i = 0; i < numrows; i++) {
result[i] = workspace;
workspace += samplesperrow;
}
#else
for (i = 0; i < numrows; i++) {
result[i] = (JSAMPROW) far_malloc((size_t)
(samplesperrow * SIZEOF(JSAMPLE)));
if (result[i] == NULL)
out_of_memory(3);
}
#endif
return result;
}
METHODDEF void
free_small_sarray (JSAMPARRAY ptr, long numrows)
/* Free a "small" (all-in-memory) 2-D sample array */
{
/* Free the rows themselves; on 80x86 these are "far" */
#ifdef BIG_MALLOCS_OK
far_free((void FAR *) ptr[0]);
#else
long i;
for (i = 0; i < numrows; i++) {
far_free((void FAR *) ptr[i]);
}
#endif
/* 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;
#ifdef BIG_MALLOCS_OK
JBLOCKROW workspace;
#endif
long i;
#ifdef MEM_STATS
total_num_barray++;
#ifdef BIG_MALLOCS_OK
total_bytes_barray += numrows * blocksperrow * SIZEOF(JBLOCK)
+ MALLOC_FAR_OVERHEAD;
#else
total_bytes_barray += (blocksperrow * SIZEOF(JBLOCK) + MALLOC_FAR_OVERHEAD)
* numrows;
#endif
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" */
#ifdef BIG_MALLOCS_OK
workspace = (JBLOCKROW) far_malloc((size_t)
(numrows * blocksperrow * SIZEOF(JBLOCK)));
if (workspace == NULL)
out_of_memory(4);
for (i = 0; i < numrows; i++) {
result[i] = workspace;
workspace += blocksperrow;
}
#else
for (i = 0; i < numrows; i++) {
result[i] = (JBLOCKROW) far_malloc((size_t)
(blocksperrow * SIZEOF(JBLOCK)));
if (result[i] == NULL)
out_of_memory(4);
}
#endif
return result;
}
METHODDEF void
free_small_barray (JBLOCKARRAY ptr, long numrows)
/* Free a "small" (all-in-memory) 2-D coefficient-block array */
{
/* Free the rows themselves; on 80x86 these are "far" */
#ifdef BIG_MALLOCS_OK
far_free((void FAR *) ptr[0]);
#else
long i;
for (i = 0; i < numrows; i++) {
far_free((void FAR *) ptr[i]);
}
#endif
/* 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;
}

View File

@@ -1,7 +1,7 @@
/*
* jwrgif.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -98,22 +98,20 @@ flush_packet (void)
{
if (bytesinpkt > 0) { /* never write zero-length packet */
packetbuf[0] = (char) bytesinpkt++;
if (FWRITE(dcinfo->output_file, packetbuf, bytesinpkt)
if (JFWRITE(dcinfo->output_file, packetbuf, bytesinpkt)
!= (size_t) bytesinpkt)
ERREXIT(dcinfo->emethods, "Output file write error");
ERREXIT(dcinfo->emethods, "Output file write error --- out of disk space?");
bytesinpkt = 0;
}
}
LOCAL void
char_out (char c)
/* Add a character to current packet; flush to disk if necessary */
{
packetbuf[++bytesinpkt] = c;
if (bytesinpkt >= 255)
flush_packet();
}
#define CHAR_OUT(c) \
{ packetbuf[++bytesinpkt] = (char) (c); \
if (bytesinpkt >= 255) \
flush_packet(); \
}
/* Routine to convert variable-width codes into a byte stream */
@@ -127,14 +125,11 @@ 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_accum |= ((INT32) code) << cur_bits;
cur_bits += n_bits;
while (cur_bits >= 8) {
char_out((char) (cur_accum & 0xFF));
CHAR_OUT(cur_accum & 0xFF);
cur_accum >>= 8;
cur_bits -= 8;
}
@@ -270,7 +265,7 @@ compress_term (void)
output(EOFCode);
/* Flush the bit-packing buffer */
if (cur_bits > 0) {
char_out((char) (cur_accum & 0xFF));
CHAR_OUT(cur_accum & 0xFF);
}
/* Flush the packet buffer */
flush_packet();
@@ -305,27 +300,15 @@ emit_header (int num_colors, JSAMPARRAY colormap)
/* If colormap==NULL, synthesize a gray-scale colormap */
{
int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
int cshift = dcinfo->data_precision - 8;
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;
BitsPerPixel = 1;
while (num_colors > (1 << BitsPerPixel))
BitsPerPixel++;
ColorMapSize = 1 << BitsPerPixel;
if (BitsPerPixel <= 1)
InitCodeSize = 2;
@@ -335,7 +318,12 @@ emit_header (int num_colors, JSAMPARRAY colormap)
* Write the GIF header.
* Note that we generate a plain GIF87 header for maximum compatibility.
*/
(void) FWRITE(dcinfo->output_file, "GIF87a", 6);
putc('G', dcinfo->output_file);
putc('I', dcinfo->output_file);
putc('F', dcinfo->output_file);
putc('8', dcinfo->output_file);
putc('7', dcinfo->output_file);
putc('a', dcinfo->output_file);
/* Write the Logical Screen Descriptor */
put_word((UINT16) dcinfo->image_width);
put_word((UINT16) dcinfo->image_height);
@@ -346,17 +334,19 @@ emit_header (int num_colors, JSAMPARRAY colormap)
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 */
/* If the color map is more than 8 bits precision, */
/* we reduce it to 8 bits by shifting */
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);
putc(GETJSAMPLE(colormap[0][i]) >> cshift, dcinfo->output_file);
putc(GETJSAMPLE(colormap[1][i]) >> cshift, dcinfo->output_file);
putc(GETJSAMPLE(colormap[2][i]) >> cshift, dcinfo->output_file);
} else {
/* Grayscale "color map": possible if quantizing grayscale image */
put_3bytes(GETJSAMPLE(colormap[0][i]));
put_3bytes(GETJSAMPLE(colormap[0][i]) >> cshift);
}
} else {
/* Create a gray-scale map of num_colors values, range 0..255 */
@@ -461,11 +451,9 @@ output_term (decompress_info_ptr cinfo)
/* Make sure we wrote the output file OK */
fflush(cinfo->output_file);
if (ferror(cinfo->output_file))
ERREXIT(cinfo->emethods, "Output file write error");
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?");
/* 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);
/* no work (we let free_all release the workspace) */
}

View File

@@ -1,7 +1,7 @@
/*
* jwrjfif.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -36,15 +36,15 @@
/* Write some bytes from a (char *) buffer */
#define WRITE_BYTES(cinfo,dataptr,datacount) \
{ if (FWRITE(cinfo->output_file, dataptr, datacount) \
{ if (JFWRITE(cinfo->output_file, dataptr, datacount) \
!= (size_t) (datacount)) \
ERREXIT(cinfo->emethods, "Output file write error"); }
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); }
/* 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"); }
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); }
/* End of stdio-specific code. */
@@ -165,6 +165,9 @@ emit_dht (compress_info_ptr cinfo, int index, boolean is_ac)
} else {
htbl = cinfo->dc_huff_tbl_ptrs[index];
}
if (htbl == NULL)
ERREXIT1(cinfo->emethods, "Huffman table 0x%02x was not defined", index);
if (! htbl->sent_table) {
emit_marker(cinfo, M_DHT);
@@ -310,10 +313,10 @@ emit_jfif_app0 (compress_info_ptr cinfo)
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, 0x4A); /* Identifier: ASCII "JFIF" */
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0x49);
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0);
emit_byte(cinfo, 1); /* Major version */
emit_byte(cinfo, 1); /* Minor version */
@@ -325,6 +328,23 @@ emit_jfif_app0 (compress_info_ptr cinfo)
}
LOCAL void
emit_com (compress_info_ptr cinfo, char * dataptr, size_t datalen)
/* Emit a COM marker */
{
if ((unsigned) datalen <= (unsigned) 65533) { /* safety check */
emit_marker(cinfo, M_COM);
emit_2bytes(cinfo, (int) (datalen + 2)); /* length */
while (datalen--) {
emit_byte(cinfo, *dataptr);
dataptr++;
}
}
}
/*
* Write the file header.
*/
@@ -342,6 +362,10 @@ write_file_header (compress_info_ptr cinfo)
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
emit_jfif_app0(cinfo);
if (cinfo->comment_text != NULL) /* and an optional COM block */
emit_com(cinfo, cinfo->comment_text,
(size_t) (strlen(cinfo->comment_text)));
/* 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 */
@@ -360,9 +384,6 @@ write_file_header (compress_info_ptr cinfo)
}
/* 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;
@@ -415,6 +436,13 @@ write_scan_header (compress_info_ptr cinfo)
}
}
/* Emit DRI if required --- note that DRI value could change for each scan.
* If it doesn't, a tiny amount of space is wasted in multiple-scan files.
* We assume DRI will never be nonzero for one scan and zero for a later one.
*/
if (cinfo->restart_interval)
emit_dri(cinfo);
emit_sos(cinfo);
}

272
jwrppm.c
View File

@@ -1,12 +1,11 @@
/*
* jwrppm.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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).
* This file contains routines to write output images in PPM/PGM format.
*
* These routines may need modification for non-Unix environments or
* specialized applications. As they stand, they assume output to
@@ -31,7 +30,20 @@
#endif
static JSAMPARRAY color_map; /* saves color map passed by quantizer */
/*
* On most systems, writing individual bytes with putc() is drastically less
* efficient than buffering a row at a time for fwrite(). But we must
* allocate the row buffer in near data space on PCs, because we are assuming
* small-data memory model, wherein fwrite() can't reach far memory. If you
* need to process very wide images on a PC, you may have to use the putc()
* approach. Also, there are still a few systems around wherein fwrite() is
* actually implemented as a putc() loop, in which case this buffer is a waste
* of space. So the putc() method can be used by defining USE_PUTC_OUTPUT.
*/
#ifndef USE_PUTC_OUTPUT
static char * row_buffer; /* holds 1 pixel row's worth of output */
#endif
/*
@@ -45,10 +57,20 @@ output_init (decompress_info_ptr cinfo)
/* emit header for raw PGM format */
fprintf(cinfo->output_file, "P5\n%ld %ld\n%d\n",
cinfo->image_width, cinfo->image_height, 255);
#ifndef USE_PUTC_OUTPUT
/* allocate space for row buffer: 1 byte/pixel */
row_buffer = (char *) (*cinfo->emethods->alloc_small)
((size_t) (SIZEOF(char) * cinfo->image_width));
#endif
} 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);
#ifndef USE_PUTC_OUTPUT
/* allocate space for row buffer: 3 bytes/pixel */
row_buffer = (char *) (*cinfo->emethods->alloc_small)
((size_t) (3 * SIZEOF(char) * cinfo->image_width));
#endif
} else {
ERREXIT(cinfo->emethods, "PPM output must be grayscale or RGB");
}
@@ -59,6 +81,8 @@ output_init (decompress_info_ptr cinfo)
* Write some pixel data.
*/
#ifdef USE_PUTC_OUTPUT
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
@@ -66,83 +90,215 @@ put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
register long width = cinfo->image_width;
register int row;
long width = cinfo->image_width;
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++;
}
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++;
}
}
}
METHODDEF void
put_gray_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
for (col = width; col > 0; col--) {
putc(GETJSAMPLE(*ptr0), outfile);
ptr0++;
}
}
}
#else /* use row buffering */
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register char * row_bufferptr;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
ptr1 = pixel_data[1][row];
ptr2 = pixel_data[2][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
*row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
*row_bufferptr++ = (char) GETJSAMPLE(*ptr1++);
*row_bufferptr++ = (char) GETJSAMPLE(*ptr2++);
}
(void) JFWRITE(outfile, row_buffer, 3*width);
}
}
METHODDEF void
put_gray_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0;
register char * row_bufferptr;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
*row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
}
(void) JFWRITE(outfile, row_buffer, width);
}
}
#endif /* USE_PUTC_OUTPUT */
/*
* Write some pixel data when color quantization is in effect.
*/
#ifdef USE_PUTC_OUTPUT
METHODDEF void
put_demapped_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
put_demapped_rgb (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register JSAMPROW color_map1 = cinfo->colormap[1];
register JSAMPROW color_map2 = cinfo->colormap[2];
register int pixval;
register long col;
register long width = cinfo->image_width;
register int row;
long width = cinfo->image_width;
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++;
}
for (row = 0; row < num_rows; row++) {
ptr = pixel_data[0][row];
for (col = width; col > 0; col--) {
pixval = GETJSAMPLE(*ptr++);
putc(GETJSAMPLE(color_map0[pixval]), outfile);
putc(GETJSAMPLE(color_map1[pixval]), outfile);
putc(GETJSAMPLE(color_map2[pixval]), outfile);
}
}
}
METHODDEF void
put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register int pixval;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr = pixel_data[0][row];
for (col = width; col > 0; col--) {
pixval = GETJSAMPLE(*ptr++);
putc(GETJSAMPLE(color_map0[pixval]), outfile);
}
}
}
#else /* use row buffering */
METHODDEF void
put_demapped_rgb (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register char * row_bufferptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register JSAMPROW color_map1 = cinfo->colormap[1];
register JSAMPROW color_map2 = cinfo->colormap[2];
register int pixval;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr = pixel_data[0][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
pixval = GETJSAMPLE(*ptr++);
*row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
*row_bufferptr++ = (char) GETJSAMPLE(color_map1[pixval]);
*row_bufferptr++ = (char) GETJSAMPLE(color_map2[pixval]);
}
(void) JFWRITE(outfile, row_buffer, 3*width);
}
}
METHODDEF void
put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register char * row_bufferptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register int pixval;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr = pixel_data[0][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
pixval = GETJSAMPLE(*ptr++);
*row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
}
(void) JFWRITE(outfile, row_buffer, width);
}
}
#endif /* USE_PUTC_OUTPUT */
/*
* Write the color map.
* For PPM output, we just demap the output data!
* For PPM output, we just remember to 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;
if (cinfo->out_color_space == CS_RGB)
cinfo->methods->put_pixel_rows = put_demapped_rgb;
else
cinfo->methods->put_pixel_rows = put_demapped_gray;
}
@@ -153,10 +309,11 @@ put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
METHODDEF void
output_term (decompress_info_ptr cinfo)
{
/* No work except to make sure we wrote the output file OK */
/* No work except to make sure we wrote the output file OK; */
/* we let free_all release any workspace */
fflush(cinfo->output_file);
if (ferror(cinfo->output_file))
ERREXIT(cinfo->emethods, "Output file write error");
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?");
}
@@ -170,7 +327,10 @@ 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;
if (cinfo->out_color_space == CS_RGB)
cinfo->methods->put_pixel_rows = put_pixel_rows;
else
cinfo->methods->put_pixel_rows = put_gray_rows;
cinfo->methods->output_term = output_term;
}

View File

@@ -1,7 +1,7 @@
/*
* jwrrle.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -87,6 +87,8 @@ output_init (decompress_info_ptr cinfo)
output_colormap = NULL; /* No output colormap as yet */
number_colors = 0;
cur_output_row = 0; /* Start filling virtual arrays at row 0 */
cinfo->total_passes++; /* count file writing as separate pass */
}
@@ -136,7 +138,7 @@ put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
/* Allocate storage for RLE-style cmap, zero any extra entries */
cmapsize = cinfo->color_out_comps * CMAPLENGTH * SIZEOF(rle_map);
output_colormap = (rle_map *) (*cinfo->emethods->alloc_small) (cmapsize);
MEMZERO((void *) output_colormap, cmapsize);
MEMZERO(output_colormap, cmapsize);
/* Save away data in RLE format --- note 8-bit left shift! */
/* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
@@ -165,7 +167,7 @@ output_term (decompress_info_ptr cinfo)
long row;
/* Initialize the header info */
MEMZERO((void *) &header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */
MEMZERO(&header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */
header.rle_file = cinfo->output_file;
header.xmin = 0;
header.xmax = cinfo->image_width - 1;
@@ -192,25 +194,24 @@ output_term (decompress_info_ptr cinfo)
* and (b) we are not on a machine where FAR pointers differ from regular.
*/
for (row = cinfo->image_height-1; row >= 0; row--) {
(*cinfo->methods->progress_monitor) (cinfo, cinfo->image_height-row-1,
cinfo->image_height);
for (ci = 0; ci < cinfo->final_out_comps; ci++) {
output_rows[ci] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
(channels[ci], row, FALSE));
}
rle_putrow(output_rows, (int) cinfo->image_width, &header);
}
cinfo->completed_passes++;
/* Emit file trailer */
rle_puteof(&header);
fflush(cinfo->output_file);
if (ferror(cinfo->output_file))
ERREXIT(cinfo->emethods, "Output file write error");
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?");
/* Release memory */
for (ci = 0; ci < cinfo->final_out_comps; ci++) {
(*cinfo->emethods->free_big_sarray) (channels[ci]);
}
if (output_colormap != NULL)
(*cinfo->emethods->free_small) ((void *) output_colormap);
/* no work (we let free_all release the workspace) */
}

View File

@@ -1,7 +1,7 @@
/*
* jwrtarga.c
*
* Copyright (C) 1991, Thomas G. Lane.
* Copyright (C) 1991, 1992, 1993, 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.
*
@@ -32,7 +32,20 @@
#endif
static JSAMPARRAY color_map; /* saves color map passed by quantizer */
/*
* On most systems, writing individual bytes with putc() is drastically less
* efficient than buffering a row at a time for fwrite(). But we must
* allocate the row buffer in near data space on PCs, because we are assuming
* small-data memory model, wherein fwrite() can't reach far memory. If you
* need to process very wide images on a PC, you may have to use the putc()
* approach. Also, there are still a few systems around wherein fwrite() is
* actually implemented as a putc() loop, in which case this buffer is a waste
* of space. So the putc() method can be used by defining USE_PUTC_OUTPUT.
*/
#ifndef USE_PUTC_OUTPUT
static char * row_buffer; /* holds 1 pixel row's worth of output */
#endif
LOCAL void
@@ -42,7 +55,7 @@ write_header (decompress_info_ptr cinfo, int num_colors)
char targaheader[18];
/* Set unused fields of header to 0 */
MEMZERO((void *) targaheader, SIZEOF(targaheader));
MEMZERO(targaheader, SIZEOF(targaheader));
if (num_colors > 0) {
targaheader[1] = 1; /* color map type 1 */
@@ -70,7 +83,7 @@ write_header (decompress_info_ptr cinfo, int num_colors)
}
}
if (FWRITE(cinfo->output_file, targaheader, 18) != (size_t) 18)
if (JFWRITE(cinfo->output_file, targaheader, 18) != (size_t) 18)
ERREXIT(cinfo->emethods, "Could not write Targa header");
}
@@ -86,10 +99,20 @@ output_init (decompress_info_ptr cinfo)
/* Targa doesn't have a mapped grayscale format, so we will */
/* demap quantized gray output. Never emit a colormap. */
write_header(cinfo, 0);
#ifndef USE_PUTC_OUTPUT
/* allocate space for row buffer: 1 byte/pixel */
row_buffer = (char *) (*cinfo->emethods->alloc_small)
((size_t) (SIZEOF(char) * cinfo->image_width));
#endif
} else if (cinfo->out_color_space == CS_RGB) {
/* For quantized output, defer writing header until put_color_map time. */
if (! cinfo->quantize_colors)
write_header(cinfo, 0);
#ifndef USE_PUTC_OUTPUT
/* allocate space for row buffer: 3 bytes/pixel */
row_buffer = (char *) (*cinfo->emethods->alloc_small)
((size_t) (3 * SIZEOF(char) * cinfo->image_width));
#endif
} else {
ERREXIT(cinfo->emethods, "Targa output must be grayscale or RGB");
}
@@ -100,68 +123,163 @@ output_init (decompress_info_ptr cinfo)
* Write some pixel data.
*/
#ifdef USE_PUTC_OUTPUT
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
/* used for unquantized full-color output */
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
register long width = cinfo->image_width;
register int row;
long width = cinfo->image_width;
int row;
if (cinfo->final_out_comps == 1) {
/* here for grayscale or quantized color output */
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
for (col = width; col > 0; col--) {
putc(GETJSAMPLE(*ptr0), outfile);
ptr0++;
}
}
} else {
/* here for unquantized color output */
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(*ptr2), outfile); /* write in BGR order */
ptr2++;
putc(GETJSAMPLE(*ptr1), outfile);
ptr1++;
putc(GETJSAMPLE(*ptr0), outfile);
ptr0++;
}
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(*ptr2), outfile); /* write in BGR order */
ptr2++;
putc(GETJSAMPLE(*ptr1), outfile);
ptr1++;
putc(GETJSAMPLE(*ptr0), outfile);
ptr0++;
}
}
}
METHODDEF void
put_gray_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
/* used for grayscale OR quantized color output */
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
for (col = width; col > 0; col--) {
putc(GETJSAMPLE(*ptr0), outfile);
ptr0++;
}
}
}
#else /* use row buffering */
METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
/* used for unquantized full-color output */
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, ptr1, ptr2;
register char * row_bufferptr;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
ptr1 = pixel_data[1][row];
ptr2 = pixel_data[2][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
*row_bufferptr++ = (char) GETJSAMPLE(*ptr2++); /* BGR order */
*row_bufferptr++ = (char) GETJSAMPLE(*ptr1++);
*row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
}
(void) JFWRITE(outfile, row_buffer, 3*width);
}
}
METHODDEF void
put_gray_rows (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
/* used for grayscale OR quantized color output */
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0;
register char * row_bufferptr;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr0 = pixel_data[0][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
*row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
}
(void) JFWRITE(outfile, row_buffer, width);
}
}
#endif /* USE_PUTC_OUTPUT */
/*
* Write some demapped pixel data when color quantization is in effect.
* For Targa, this is only applied to grayscale data.
*/
#ifdef USE_PUTC_OUTPUT
METHODDEF void
put_demapped_rows (decompress_info_ptr cinfo, int num_rows,
put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register int pixval;
register long col;
register long width = cinfo->image_width;
register int row;
long width = cinfo->image_width;
int row;
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++;
pixval = GETJSAMPLE(*ptr++);
putc(GETJSAMPLE(color_map0[pixval]), outfile);
}
}
}
#else /* use row buffering */
METHODDEF void
put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE pixel_data)
{
FILE * outfile = cinfo->output_file;
register JSAMPROW ptr;
register char * row_bufferptr;
register JSAMPROW color_map0 = cinfo->colormap[0];
register int pixval;
register long col;
long width = cinfo->image_width;
int row;
for (row = 0; row < num_rows; row++) {
ptr = pixel_data[0][row];
row_bufferptr = row_buffer;
for (col = width; col > 0; col--) {
pixval = GETJSAMPLE(*ptr++);
*row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
}
(void) JFWRITE(outfile, row_buffer, width);
}
}
#endif /* USE_PUTC_OUTPUT */
/*
* Write the color map.
@@ -186,8 +304,7 @@ put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
putc(GETJSAMPLE(colormap[0][i]), outfile);
}
} else {
color_map = colormap; /* save for use in output */
cinfo->methods->put_pixel_rows = put_demapped_rows;
cinfo->methods->put_pixel_rows = put_demapped_gray;
}
}
@@ -202,7 +319,7 @@ 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");
ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?");
}
@@ -216,7 +333,10 @@ jselwtarga (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;
if (cinfo->out_color_space == CS_GRAYSCALE || cinfo->quantize_colors)
cinfo->methods->put_pixel_rows = put_gray_rows;
else
cinfo->methods->put_pixel_rows = put_pixel_rows;
cinfo->methods->output_term = output_term;
}

View File

@@ -1,6 +0,0 @@
L jcmain.mix jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix
L jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jwrjfif.mix
L jrdgif.mix jrdppm.mix jrdrle.mix jrdtarga.mix jutils.mix jvirtmem.mix
L jerror.mix
fa;
b cjpeg,8K,48K,

View File

@@ -1,23 +0,0 @@
jcmain.obj +
jcmaster.obj +
jcdeflts.obj +
jcarith.obj +
jccolor.obj +
jcexpand.obj +
jchuff.obj +
jcmcu.obj +
jcpipe.obj +
jcsample.obj +
jfwddct.obj +
jwrjfif.obj +
jrdgif.obj +
jrdppm.obj +
jrdrle.obj +
jrdtarga.obj +
jutils.obj +
jvirtmem.obj +
jerror.obj
cjpeg.exe /NOI
nul.map
nul.def

View File

@@ -1,4 +0,0 @@
jcmain.obj jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj jwrjfif.obj
jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj jutils.obj jvirtmem.obj
jerror.obj

37
makcjpeg.st Normal file
View File

@@ -0,0 +1,37 @@
; Project file for Independent JPEG Group's software
;
; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C.
; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de)
; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de).
;
; To use this file, rename it to CJPEG.PRJ.
; If you are using Turbo C, change filenames beginning with "PC..." to "TC..."
; Read SETUP instructions before trying to make the program!
;
;
; * * * Output file * * *
cjpeg.ttp
;
; * * * DEFINES * * *
.C[-DHAVE_STDC]
.C[-DINCLUDES_ARE_ANSI]
.C[-DNEED_SIGNAL_CATCHER] ; It's safer to have a signal catcher.
.C[-DTWO_FILE_COMMANDLINE] ; If you like the UNIX - style with
; I/O redirection, comment this line out.
.C[-DPROGRESS_REPORT] ; This enables the % progress indicator
;
; * * * COMPILER OPTIONS * * *
.C[-P] ; absolute calls
.C[-M] ; and no string merging, folks
.C[-w-par] ; no "parameter xxxx unused"
.C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures
.C[-wsig] ; warn if significant digits may be lost
.C[-w-cln] ; no "constant is long" warnings
=
; * * * * List of modules * * * *
PCSTART.O
jcmain.c (jinclude.h,jconfig.h,jpegdata.h,jversion.h)
JPEG.LIB ; built by LIB_JPEG.PRJ
;PCFLTLIB.LIB ; floating point library -- you shouldn't need this
PCSTDLIB.LIB ; standard library
PCEXTLIB.LIB ; extended library

View File

@@ -1,6 +0,0 @@
L jdmain.mix jdmaster.mix jddeflts.mix jbsmooth.mix jdarith.mix jdcolor.mix
L jdhuff.mix jdmcu.mix jdpipe.mix jdsample.mix jquant1.mix jquant2.mix
L jrevdct.mix jrdjfif.mix jwrgif.mix jwrppm.mix jwrrle.mix jwrtarga.mix
L jutils.mix jvirtmem.mix jerror.mix
fa;
b djpeg,8K,48K,

View File

@@ -1,25 +0,0 @@
jdmain.obj +
jdmaster.obj +
jddeflts.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 +
jwrrle.obj +
jwrtarga.obj +
jutils.obj +
jvirtmem.obj +
jerror.obj
djpeg.exe /NOI
nul.map
nul.def

View File

@@ -1,4 +0,0 @@
jdmain.obj jdmaster.obj jddeflts.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 jwrrle.obj jwrtarga.obj
jutils.obj jvirtmem.obj jerror.obj

37
makdjpeg.st Normal file
View File

@@ -0,0 +1,37 @@
; Project file for Independent JPEG Group's software
;
; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C.
; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de)
; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de).
;
; To use this file, rename it to DJPEG.PRJ.
; If you are using Turbo C, change filenames beginning with "PC..." to "TC..."
; Read SETUP instructions before trying to make the program!
;
;
; * * * Output file * * *
djpeg.ttp
;
; * * * DEFINES * * *
.C[-DHAVE_STDC]
.C[-DINCLUDES_ARE_ANSI]
.C[-DNEED_SIGNAL_CATCHER] ; It's safer to have a signal catcher.
.C[-DTWO_FILE_COMMANDLINE] ; If you like the UNIX - style with
; I/O redirection, comment this line out.
.C[-DPROGRESS_REPORT] ; This enables the % progress indicator
;
; * * * COMPILER OPTIONS * * *
.C[-P] ; absolute calls
.C[-M] ; and no string merging, folks
.C[-w-par] ; no "parameter xxxx unused"
.C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures
.C[-wsig] ; warn if significant digits may be lost
.C[-w-cln] ; no "constant is long" warnings
=
; * * * * List of modules * * * *
PCSTART.O
jdmain.c (jinclude.h,jconfig.h,jpegdata.h,jversion.h)
JPEG.LIB ; built by LIB_JPEG.PRJ
;PCFLTLIB.LIB ; floating point library -- you shouldn't need this
PCSTDLIB.LIB ; standard library
PCEXTLIB.LIB ; extended library

View File

@@ -26,33 +26,42 @@ LDFLAGS=
LDLIBS=
# 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)
# linker
LN= $(CC)
# file deletion command
RM= rm -f
# library (.a) file creation command
AR= ar rc
# second step in .a creation (use "touch" if not needed)
AR2= ranlib
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.o jvirtmem.o jerror.o
COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o
# compression objectfiles
CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \
jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \
@@ -85,8 +94,13 @@ libjpeg.a: $(LIBOBJECTS)
$(AR) libjpeg.a $(LIBOBJECTS)
$(AR2) libjpeg.a
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
$(RM) *.o cjpeg djpeg libjpeg.a core testout.ppm testout.jpg
$(RM) *.o cjpeg djpeg libjpeg.a core testout.*
distribute:
$(RM) jpegsrc.tar*
@@ -94,10 +108,12 @@ distribute:
compress -v jpegsrc.tar
test: cjpeg djpeg
$(RM) testout.ppm testout.jpg
$(RM) testout.ppm testout.gif testout.jpg
./djpeg testorig.jpg >testout.ppm
./djpeg -gif testorig.jpg >testout.gif
./cjpeg testimg.ppm >testout.jpg
cmp testimg.ppm testout.ppm
cmp testimg.gif testout.gif
cmp testimg.jpg testout.jpg
@@ -107,7 +123,7 @@ 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 jversion.h egetopt.c
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -116,7 +132,7 @@ jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
jddeflts.o : jddeflts.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 jversion.h egetopt.c
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -127,7 +143,7 @@ jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.o : jfwddct.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
jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
@@ -138,3 +154,4 @@ jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

173
makefile.bcc Normal file
View File

@@ -0,0 +1,173 @@
# Makefile for Independent JPEG Group's software
# This makefile is suitable for Borland C (Turbo C) on MS-DOS.
# It is set up for Borland C++, revision 3.0 or later.
# For older versions (pre-3.0), replace "-O2" with "-O -G -Z" in CFLAGS.
# If you have an even older version of Turbo C, you may be able to make it
# work by saying "CC= tcc" below. (Very early versions of Turbo C++,
# like 1.01, are so buggy that you may as well forget it.)
# Thanks to Tom Wright and Ge' Weijers for this file.
# Read SETUP instructions before saying "make" !!
# The name of your C compiler:
CC= bcc
# You may need to adjust these cc options:
CFLAGS= -DHAVE_STDC -DINCLUDES_ARE_ANSI \
-ms -DMSDOS -DUSE_FMEM -DINCOMPLETE_TYPES_BROKEN -w-par -O2
# -DHAVE_STDC -DINCLUDES_ARE_ANSI enable ANSI-C features (we DON'T want -A)
# -ms selects small memory model for most efficient code
# -DMSDOS enables DOS-specific code
# -DUSE_FMEM indicates we have _fmemcpy() and _fmemset()
# -DINCOMPLETE_TYPES_BROKEN suppresses bogus warning about undefined structures
# -w-par suppresses warnings about unused function parameters
# -O2 enables full code optimization (for pre-3.0 Borland C++, use -O -G -Z)
# If you run up against DOS' 128-character limit on command line length,
# you can get rid of some of the -D switches by adding equivalent #define
# commands to the head of jinclude.h.
# Link-time cc options:
LDFLAGS= -ms
# memory model option here must match CFLAGS!
# need linker response file because file list > 128 chars
RFILE= libjpeg.ans
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj jmemdosa.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj
COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS)
# decompression objectfiles
DLIBOBJECTS= jdmaster.obj jddeflts.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 \
jwrrle.obj jwrtarga.obj
DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS)
# These objectfiles are included in libjpeg.lib
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
all: cjpeg.exe djpeg.exe
# 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) $(RFILE)
del libjpeg.lib
tlib @$(RFILE)
# linker response file for same
$(RFILE) : Makefile
del $(RFILE)
echo libjpeg.lib & >$(RFILE)
echo +jcmaster.obj +jcdeflts.obj +jcarith.obj +jccolor.obj & >>$(RFILE)
echo +jcexpand.obj +jchuff.obj +jcmcu.obj +jcpipe.obj & >>$(RFILE)
echo +jcsample.obj +jfwddct.obj +jwrjfif.obj +jrdgif.obj & >>$(RFILE)
echo +jrdppm.obj +jrdrle.obj +jrdtarga.obj +jdmaster.obj & >>$(RFILE)
echo +jddeflts.obj +jbsmooth.obj +jdarith.obj +jdcolor.obj & >>$(RFILE)
echo +jdhuff.obj +jdmcu.obj +jdpipe.obj +jdsample.obj & >>$(RFILE)
echo +jquant1.obj +jquant2.obj +jrevdct.obj +jrdjfif.obj & >>$(RFILE)
echo +jwrgif.obj +jwrppm.obj +jwrrle.obj +jwrtarga.obj & >>$(RFILE)
echo +jutils.obj +jerror.obj +jmemmgr.obj +jmemsys.obj & >>$(RFILE)
echo +jmemdosa.obj >>$(RFILE)
cjpeg.exe: jcmain.obj libjpeg.lib
$(CC) $(LDFLAGS) -ecjpeg.exe jcmain.obj libjpeg.lib
djpeg.exe: jdmain.obj libjpeg.lib
$(CC) $(LDFLAGS) -edjpeg.exe jdmain.obj libjpeg.lib
.c.obj:
$(CC) $(CFLAGS) -c $<
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
del *.obj
del libjpeg.lib
del cjpeg.exe
del djpeg.exe
del testout.*
test:
del testout.*
djpeg -outfile testout.ppm testorig.jpg
djpeg -gif -outfile testout.gif testorig.jpg
cjpeg -outfile testout.jpg testimg.ppm
fc /b testimg.ppm testout.ppm
fc /b testimg.gif testout.gif
fc /b testimg.jpg testout.jpg
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
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h
jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h
jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.obj : jfwddct.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
jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h
jrdtarga.obj : jrdtarga.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
jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h
jmemdosa.obj : jmemdosa.asm
tasm /mx jmemdosa.asm

141
makefile.icc Normal file
View File

@@ -0,0 +1,141 @@
# Makefile for Independent JPEG Group's software
# This makefile is for Intel's Code Builder 32-bit DOS/Windows compiler.
# Thanks to Bailey Brown.
# Read SETUP instructions before saying "make" !!
# The name of your C compiler:
CC= icc
# You may want to adjust these cc options:
CFLAGS= /O3 /Ll /DTWO_FILE_COMMANDLINE
# Link-time cc options:
LDFLAGS= /F /xregion=4M
# /F removes floating-point support, which we don't need.
# /xregionsize sets virtual memory region size.
# To link any special libraries, add the necessary -l commands here.
LDLIBS=
# miscellaneous OS-dependent stuff
# linker
LN= $(CC)
# library (.lib) file creation command
AR= lib32
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj
COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS)
# decompression objectfiles
DLIBOBJECTS= jdmaster.obj jddeflts.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 \
jwrrle.obj jwrtarga.obj
DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS)
# These objectfiles are included in libjpeg.lib
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
all: cjpeg.exe djpeg.exe
# By default, libjpeg.lib is not built unless you explicitly request it.
# You can add libjpeg.lib to the line above if you want it built by default.
cjpeg.exe: $(COBJECTS)
echo $(COBJECTS) >cjpeg.rsp
$(LN) $(LDFLAGS) /ecjpeg.exe @cjpeg.rsp $(LDLIBS)
djpeg.exe: $(DOBJECTS)
echo $(DOBJECTS) >djpeg.rsp
$(LN) $(LDFLAGS) /edjpeg.exe @djpeg.rsp $(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)
del libjpeg.lib
$(AR) libjpeg.lib nobackup batch <makljpeg.icc
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
test: cjpeg.exe djpeg.exe
del testout.*
djpeg -outfile testout.ppm testorig.jpg
djpeg -gif -outfile testout.gif testorig.jpg
cjpeg -outfile testout.jpg testimg.ppm
fc /b testimg.ppm testout.ppm
fc /b testimg.gif testout.gif
fc /b testimg.jpg testout.jpg
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
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h
jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h
jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.obj : jfwddct.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
jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h
jrdtarga.obj : jrdtarga.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
jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

View File

@@ -1,7 +1,8 @@
# Makefile for Independent JPEG Group's software
# This makefile is for Amiga systems using Manx Aztec C ver 5.x.
# Thanks to D.J. James for this version.
# Use jmemname.c as the system-dependent memory manager.
# Thanks to D.J. James (djjames@cup.portal.com) for this version.
# Read SETUP instructions before saying "make" !!
@@ -9,10 +10,17 @@
CC= cc
# You may need to adjust these cc options:
CFLAGS= -MC -MD -DTWO_FILE_COMMANDLINE
# uncomment for generic 68000 code (will work on any Amiga)
ARCHFLAGS= -sn
# uncomment for 68020/68030 code (faster, but won't run on 68000 CPU)
#ARCHFLAGS= -c2
CFLAGS= -MC -MD -DAMIGA -DTWO_FILE_COMMANDLINE -DNEED_SIGNAL_CATCHER \
-Dsignal_catcher=_abort -DSHORTxSHORT_32 $(ARCHFLAGS) -spfam -r4
# Link-time cc options:
LDFLAGS=
LDFLAGS= -g
# To link any special libraries, add the necessary -l commands here.
LDLIBS= -lml -lcl
@@ -30,23 +38,28 @@ AR= lb
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.o jvirtmem.o jerror.o
COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o
# compression objectfiles
CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \
jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \
@@ -78,8 +91,13 @@ libjpeg.lib: $(LIBOBJECTS)
-$(RM) libjpeg.lib
$(AR) libjpeg.lib $(LIBOBJECTS)
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
-$(RM) *.o cjpeg djpeg libjpeg.lib core testout.ppm testout.jpg
-$(RM) *.o cjpeg djpeg libjpeg.lib core testout.*
distribute:
-$(RM) jpegsrc.tar*
@@ -87,10 +105,12 @@ distribute:
compress -v jpegsrc.tar
test: cjpeg djpeg
-$(RM) testout.ppm testout.jpg
djpeg testorig.jpg testout.ppm
cjpeg testimg.ppm testout.jpg
-$(RM) testout.ppm testout.gif testout.jpg
djpeg -outfile testout.ppm testorig.jpg
djpeg -gif -outfile testout.gif testorig.jpg
cjpeg -outfile testout.jpg testimg.ppm
cmp testimg.ppm testout.ppm
cmp testimg.gif testout.gif
cmp testimg.jpg testout.jpg
@@ -100,7 +120,7 @@ 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 jversion.h egetopt.c
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -109,7 +129,7 @@ jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
jddeflts.o : jddeflts.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 jversion.h egetopt.c
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -120,7 +140,7 @@ jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.o : jfwddct.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
jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
@@ -131,3 +151,4 @@ jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

View File

@@ -25,23 +25,28 @@ LDFLAGS= /Fm /F 2000 # /F hhhh sets stack size (in hex)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jvirtmem.obj jerror.obj
COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj jmemdosa.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
@@ -63,6 +68,11 @@ LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
cl $(CFLAGS) /c $*.c
lib libjpeg -+$*.obj;
# inference rule for assembly code
.asm.obj:
masm /mx $*;
lib libjpeg -+$*.obj;
jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h
@@ -76,7 +86,7 @@ jcexpand.obj : jcexpand.c jinclude.h jconfig.h jpegdata.h
jchuff.obj : jchuff.c jinclude.h jconfig.h jpegdata.h
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h
cl $(CFLAGS) /c $*.c
jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpegdata.h
@@ -95,7 +105,7 @@ jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h
jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h
cl $(CFLAGS) /c $*.c
jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpegdata.h
@@ -118,7 +128,7 @@ 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
jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.h
jrdjfif.obj : jrdjfif.c jinclude.h jconfig.h jpegdata.h
@@ -140,6 +150,9 @@ jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h
jmemdosa.obj : jmemdosa.asm
cjpeg.exe: $(COBJECTS)

View File

@@ -1,46 +1,61 @@
# Makefile for Independent JPEG Group's software
# This makefile is for Microsoft C for MS-DOS, version 6.x (use NMAKE).
# This makefile is for Microsoft C for MS-DOS, version 6.00A and up.
# Use NMAKE, not Microsoft's brain-damaged MAKE.
# Thanks to Alan Wright and Chris Turner of Olivetti Research Ltd.
# Read SETUP instructions before saying "make" !!
# Read SETUP instructions before saying "nmake" !!
# compiler flags. -D gives a #define to the sources:
# -O default optimisation
# -AS small memory model (or use -AM for medium model)
# -Ox maximum safe optimisation
# -W3 warning level 3
# -Za ANSI conformance, defines__STDC__ but undefines far
# -Za ANSI conformance, defines __STDC__ but undefines far
# and near, so we DON'T use it.
# -D__STDC__ pretend we have full ANSI compliance. MSC is near
# enough anyway
# -DHAVE_STDC indicate we do have all the ANSI language features
# -DINCLUDES_ARE_ANSI and all the ANSI include files.
# -DMSDOS we are on an MSDOS machine
# -DUSE_FMEM we have _fmemcpy() and _fmemset()
# -DNEED_FHEAPMIN our heap management routines are broken
# -DSHORTxLCONST_32 enables compiler-specific multiply optimization
# -DMEM_STATS enable memory usage statistics (optional)
# -c compile, don't link (implicit in inference rules)
# You might also want to add -G2 if you have an 80286, etc.
# If you run up against DOS' 128-character limit on command line length,
# you can get rid of some of the -D switches by adding equivalent #define
# commands to the head of jinclude.h.
CFLAGS = -c -O -W3 -D__STDC__ -DMSDOS
CFLAGS = -AS -Ox -W3 -DHAVE_STDC -DINCLUDES_ARE_ANSI -DMSDOS -DUSE_FMEM -DNEED_FHEAPMIN -DSHORTxLCONST_32
# need linker response file because file list > 128 chars
RFILE = libjpeg.ans
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jvirtmem.obj jerror.obj
COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj jmemdosa.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
@@ -58,7 +73,57 @@ LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
all: cjpeg.exe djpeg.exe
# default rules in nmake will use cflags and compile the list below
# 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) $(RFILE)
del libjpeg.lib
lib @$(RFILE) ;
# linker response file for same
$(RFILE) : Makefile
del $(RFILE)
echo libjpeg.lib >$(RFILE)
# silly want-to-create-it prompt:
echo y >>$(RFILE)
echo +jcmaster.obj +jcdeflts.obj +jcarith.obj +jccolor.obj & >>$(RFILE)
echo +jcexpand.obj +jchuff.obj +jcmcu.obj +jcpipe.obj & >>$(RFILE)
echo +jcsample.obj +jfwddct.obj +jwrjfif.obj +jrdgif.obj & >>$(RFILE)
echo +jrdppm.obj +jrdrle.obj +jrdtarga.obj +jdmaster.obj & >>$(RFILE)
echo +jddeflts.obj +jbsmooth.obj +jdarith.obj +jdcolor.obj & >>$(RFILE)
echo +jdhuff.obj +jdmcu.obj +jdpipe.obj +jdsample.obj & >>$(RFILE)
echo +jquant1.obj +jquant2.obj +jrevdct.obj +jrdjfif.obj & >>$(RFILE)
echo +jwrgif.obj +jwrppm.obj +jwrrle.obj +jwrtarga.obj & >>$(RFILE)
echo +jutils.obj +jerror.obj +jmemmgr.obj +jmemsys.obj & >>$(RFILE)
echo +jmemdosa.obj >>$(RFILE)
cjpeg.exe: jcmain.obj libjpeg.lib
link /STACK:4096 /EXEPACK jcmain.obj, cjpeg.exe, , libjpeg.lib, ;
djpeg.exe: jdmain.obj libjpeg.lib
link /STACK:4096 /EXEPACK jdmain.obj, djpeg.exe, , libjpeg.lib, ;
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
del *.obj
del libjpeg.lib
del cjpeg.exe
del djpeg.exe
del testout.*
test:
del testout.*
djpeg -outfile testout.ppm testorig.jpg
djpeg -gif -outfile testout.gif testorig.jpg
cjpeg -outfile testout.jpg testimg.ppm
fc /b testimg.ppm testout.ppm
fc /b testimg.gif testout.gif
fc /b testimg.jpg testout.jpg
jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h
jcarith.obj : jcarith.c jinclude.h jconfig.h jpegdata.h
@@ -66,7 +131,7 @@ 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
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.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
@@ -75,7 +140,7 @@ jdarith.obj : jdarith.c jinclude.h jconfig.h jpegdata.h
jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpegdata.h
jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h
jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.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
@@ -86,7 +151,7 @@ jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.obj : jfwddct.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
jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
@@ -97,12 +162,6 @@ jwrgif.obj : jwrgif.c jinclude.h jconfig.h jpegdata.h
jwrppm.obj : jwrppm.c jinclude.h jconfig.h jpegdata.h
jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.obj : jwrtarga.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
jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h
jmemdosa.obj : jmemdosa.asm
masm /mx $*;

143
makefile.mms Normal file
View File

@@ -0,0 +1,143 @@
# Makefile for Independent JPEG Group's software
# This makefile is for use with MMS on VAX/VMS systems.
# Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu)
# and Tim Bell (tbell@netcom.com) for their help.
# Read SETUP instructions before saying "MMS" !!
CFLAGS= $(CFLAGS) /NoDebug /Optimize /Define = (TWO_FILE_COMMANDLINE,HAVE_STDC,INCLUDES_ARE_ANSI)
OPT= Sys$Disk:[]MAKVMS.OPT
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj
COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS)
# decompression objectfiles
DLIBOBJECTS= jdmaster.obj jddeflts.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 \
jwrrle.obj jwrtarga.obj
DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS)
# These objectfiles are included in libjpeg.olb
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
# objectfile lists with commas --- what a crock
COBJLIST= jcmain.obj,jcmaster.obj,jcdeflts.obj,jcarith.obj,jccolor.obj,\
jcexpand.obj,jchuff.obj,jcmcu.obj,jcpipe.obj,jcsample.obj,\
jfwddct.obj,jwrjfif.obj,jrdgif.obj,jrdppm.obj,jrdrle.obj,\
jrdtarga.obj,jutils.obj,jerror.obj,jmemmgr.obj,jmemsys.obj
DOBJLIST= jdmain.obj,jdmaster.obj,jddeflts.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,jwrrle.obj,jwrtarga.obj,jutils.obj,jerror.obj,\
jmemmgr.obj,jmemsys.obj
LIBOBJLIST= jcmaster.obj,jcdeflts.obj,jcarith.obj,jccolor.obj,jcexpand.obj,\
jchuff.obj,jcmcu.obj,jcpipe.obj,jcsample.obj,jfwddct.obj,\
jwrjfif.obj,jrdgif.obj,jrdppm.obj,jrdrle.obj,jrdtarga.obj,\
jdmaster.obj,jddeflts.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,\
jwrrle.obj,jwrtarga.obj,jutils.obj,jerror.obj,jmemmgr.obj,\
jmemsys.obj
.first
@ Define Sys Sys$Library
# By default, libjpeg.olb is not built unless you explicitly request it.
# You can add libjpeg.olb to the next line if you want it built by default.
ALL : cjpeg.exe djpeg.exe
@ Continue
cjpeg.exe : $(COBJECTS)
$(LINK) $(LFLAGS) /Executable = cjpeg.exe $(COBJLIST),$(OPT)/Option
djpeg.exe : $(DOBJECTS)
$(LINK) $(LFLAGS) /Executable = djpeg.exe $(DOBJLIST),$(OPT)/Option
# libjpeg.olb 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.olb : $(LIBOBJECTS)
Library /Create libjpeg.olb $(LIBOBJLIST)
clean :
@- Set Protection = Owner:RWED *.*;-1
@- Set Protection = Owner:RWED *.OBJ
- Purge /NoLog /NoConfirm *.*
- Delete /NoLog /NoConfirm *.OBJ;
test : cjpeg.exe djpeg.exe
mcr sys$disk:[]djpeg testorig.jpg testout.ppm
mcr sys$disk:[]djpeg -gif testorig.jpg testout.gif
mcr sys$disk:[]cjpeg testimg.ppm testout.jpg
- Backup /Compare/Log testimg.ppm testout.ppm
- Backup /Compare/Log testimg.gif testout.gif
- Backup /Compare/Log testimg.jpg testout.jpg
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
jcmain.obj : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jddeflts.obj : jddeflts.c jinclude.h jconfig.h jpegdata.h
jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpegdata.h
jdmain.obj : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.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
jquant1.obj : jquant1.c jinclude.h jconfig.h jpegdata.h
jquant2.obj : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.obj : jfwddct.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
jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
jrdrle.obj : jrdrle.c jinclude.h jconfig.h jpegdata.h
jrdtarga.obj : jrdtarga.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
jwrrle.obj : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.obj : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.obj : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

View File

@@ -1,117 +0,0 @@
# 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.
# Read SETUP instructions before saying "make" !!
# The name of your C compiler:
CC=pc
# You may need to adjust these cc options:
MODEL=m
CFLAGS= -dMSDOS -m$(MODEL)
# In particular:
# Add -dMEM_STATS to enable gathering of memory usage statistics.
# Link-time cc options:
LDFLAGS=
LDLIBS=
# miscellaneous OS-dependent stuff
# linker
LN=pcl
# file deletion command
RM=del
# library (.mix) file creation command
AR=merge
# source files (independently compilable files)
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 jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.mix jvirtmem.mix jerror.mix
# compression objectfiles
CLIBOBJECTS= jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jwrjfif.mix jrdgif.mix jrdppm.mix jrdrle.mix jrdtarga.mix
COBJECTS= jcmain.mix $(CLIBOBJECTS) $(COMOBJECTS)
# decompression objectfiles
DLIBOBJECTS= jdmaster.mix jddeflts.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 jwrrle.mix jwrtarga.mix
DOBJECTS= jdmain.mix $(DLIBOBJECTS) $(COMOBJECTS)
# These objectfiles are included in libjpeg.mix
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
all: cjpeg.exe djpeg.exe
# By default, libjpeg.mix is not built unless you explicitly request it.
# You can add libjpeg.mix to the line above if you want it built by default.
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 jversion.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
jddeflts.mix : jddeflts.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 jversion.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
jquant1.mix : jquant1.c jinclude.h jconfig.h jpegdata.h
jquant2.mix : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.mix : jfwddct.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
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
jrdrle.mix : jrdrle.c jinclude.h jconfig.h jpegdata.h
jrdtarga.mix : jrdtarga.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
jwrrle.mix : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.mix : jwrtarga.c jinclude.h jconfig.h jpegdata.h

View File

@@ -1,34 +1,41 @@
# Makefile for Independent JPEG Group's software
# This makefile is for Amiga systems using SAS C 5.10b.
# Contributed by Ed Hanway (sisd!jeh@uunet.uu.net).
# This makefile is for Amiga systems using SAS C 6.0 and up.
# Thanks to Ed Hanway, Mark Rinfret, and Jim Zepeda.
# Read SETUP instructions before saying "make" !!
# Use jmemname.c as the system-dependent memory manager.
# The name of your C compiler:
CC= lc
CC= sc
# Uncomment the following lines for generic 680x0 version
ARCHFLAGS=
ARCHFLAGS= cpu=any
SUFFIX=
# Uncomment the following lines for 68030-only version
#ARCHFLAGS= -m3
#ARCHFLAGS= cpu=68030
#SUFFIX=.030
# You may need to adjust these cc options:
CFLAGS= -v -b -rr -O -j104 -D__STDC__ -DTWO_FILE_COMMANDLINE -DINCOMPLETE_TYPES_BROKEN $(ARCHFLAGS)
# -j104 disables warnings for mismatched const qualifiers
CFLAGS= nostackcheck data=near parms=register optimize $(ARCHFLAGS) \
ignore=104 ignore=304 ignore=306 \
define HAVE_STDC define INCLUDES_ARE_ANSI \
define AMIGA define TWO_FILE_COMMANDLINE \
define NO_MKTEMP define NEED_SIGNAL_CATCHER define SHORTxSHORT_32
# ignore=104 disables warnings for mismatched const qualifiers
# ignore=304 disables warnings for variables being optimized out
# ignore=306 disables warnings for the inlining of functions
# Link-time cc options:
LDFLAGS= SC SD ND BATCH
# To link any special libraries, add the necessary commands here.
LDLIBS= LIB LIB:lcr.lib
LDLIBS= LIB LIB:scm.lib LIB:sc.lib
# miscellaneous OS-dependent stuff
# linker
LN= blink
LN= slink
# file deletion command
RM= delete quiet
# library (.lib) file creation command
@@ -39,23 +46,28 @@ AR= oml
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.o jvirtmem.o jerror.o
COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o
# compression objectfiles
CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \
jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \
@@ -97,8 +109,13 @@ libjpeg.lib: $(LIBOBJECTS)
-$(RM) libjpeg.lib
$(AR) libjpeg.lib r $(LIBOBJECTS)
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
-$(RM) *.o cjpeg djpeg cjpeg.030 djpeg.030 libjpeg.lib core testout.ppm testout.jpg
-$(RM) *.o cjpeg djpeg cjpeg.030 djpeg.030 libjpeg.lib core testout.*
distribute:
-$(RM) jpegsrc.tar*
@@ -106,10 +123,12 @@ distribute:
compress -v jpegsrc.tar
test: cjpeg djpeg
-$(RM) testout.ppm testout.jpg
djpeg testorig.jpg testout.ppm
cjpeg testimg.ppm testout.jpg
-$(RM) testout.ppm testout.gif testout.jpg
djpeg -outfile testout.ppm testorig.jpg
djpeg -gif -outfile testout.gif testorig.jpg
cjpeg -outfile testout.jpg testimg.ppm
cmp testimg.ppm testout.ppm
cmp testimg.gif testout.gif
cmp testimg.jpg testout.jpg
@@ -119,7 +138,7 @@ 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 jversion.h egetopt.c
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -128,7 +147,7 @@ jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
jddeflts.o : jddeflts.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 jversion.h egetopt.c
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -139,7 +158,7 @@ jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.o : jfwddct.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
jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
@@ -150,3 +169,4 @@ jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

View File

@@ -1,113 +0,0 @@
# Makefile for Independent JPEG Group's software
# This makefile is suitable for Borland C (Turbo C) on MS-DOS.
# It is set up for Borland C++ revision 2.0; if you have an older
# version of Turbo C, you need to say "CC= tc" below.
# Thanks to Tom Wright for this version.
# Read SETUP instructions before saying "make" !!
# The name of your C compiler:
CC= bcc
# You may need to adjust these cc options:
CFLAGS= -c -ml -DINCOMPLETE_TYPES_BROKEN
# -DINCOMPLETE_TYPES_BROKEN suppresses warnings about undefined structures
# Link-time cc options:
LDFLAGS= -ml
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.obj jvirtmem.obj jerror.obj
# compression objectfiles
CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj
COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS)
# decompression objectfiles
DLIBOBJECTS= jdmaster.obj jddeflts.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 \
jwrrle.obj jwrtarga.obj
DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS)
# These objectfiles are included in libjpeg.lib
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
all: cjpeg.exe djpeg.exe
cjpeg.exe: $(COBJECTS)
$(CC) $(LDFLAGS) -ecjpeg.exe @makcjpeg.lst
djpeg.exe: $(DOBJECTS)
$(CC) $(LDFLAGS) -edjpeg.exe @makdjpeg.lst
.c.obj:
$(CC) $(CFLAGS) $<
test:
del testout.*
djpeg testorig.jpg testout.ppm
cjpeg testimg.ppm testout.jpg
fc testimg.ppm testout.ppm
fc 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 jversion.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
jddeflts.o : jddeflts.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 jversion.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
jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h
jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.o : jfwddct.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
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
jrdrle.o : jrdrle.c jinclude.h jconfig.h jpegdata.h
jrdtarga.o : jrdtarga.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
jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h

View File

@@ -28,33 +28,42 @@ LDFLAGS=
LDLIBS=
# 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)
# linker
LN= $(CC)
# file deletion command
RM= rm -f
# library (.a) file creation command
AR= ar rc
# second step in .a creation (use "touch" if not needed)
AR2= ranlib
# source files (independently compilable files)
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 \
jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c \
jvirtmem.c jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c \
jwrjfif.c jwrgif.c jwrppm.c jwrrle.c jwrtarga.c
jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \
jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \
jwrppm.c jwrrle.c jwrtarga.c
# virtual source files (not present in distribution file, see SETUP)
VIRTSOURCES= jmemsys.c
# system-dependent implementations of virtual source files
SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \
jmemdosa.asm
# files included by source files
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h egetopt.c
INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h
# documentation, test, and support files
DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules
MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk makefile.tc \
makcjpeg.lst makdjpeg.lst makefile.pwc makcjpeg.cf makdjpeg.cf \
makljpeg.cf
OTHERFILES= ansi2knr.c config.c
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(INCLUDES) $(OTHERFILES) \
$(TESTFILES)
makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \
makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \
makvms.opt
OTHERFILES= ansi2knr.c ckconfig.c example.c
TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg
DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \
$(OTHERFILES) $(TESTFILES)
# objectfiles common to cjpeg and djpeg
COMOBJECTS= jutils.o jvirtmem.o jerror.o
COMOBJECTS= jutils.o jerror.o jmemmgr.o jmemsys.o
# compression objectfiles
CLIBOBJECTS= jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o jchuff.o \
jcmcu.o jcpipe.o jcsample.o jfwddct.o jwrjfif.o jrdgif.o jrdppm.o \
@@ -100,8 +109,13 @@ libjpeg.a: ansi2knr $(LIBOBJECTS)
$(AR) libjpeg.a $(LIBOBJECTS)
$(AR2) libjpeg.a
jmemsys.c:
echo You must select a system-dependent jmemsys.c file.
echo Please read the SETUP directions.
exit 1
clean:
$(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core tmpansi.* testout.ppm testout.jpg
$(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core tmpansi.* testout.*
distribute:
$(RM) jpegsrc.tar*
@@ -109,10 +123,12 @@ distribute:
compress -v jpegsrc.tar
test: cjpeg djpeg
$(RM) testout.ppm testout.jpg
$(RM) testout.ppm testout.gif testout.jpg
./djpeg testorig.jpg >testout.ppm
./djpeg -gif testorig.jpg >testout.gif
./cjpeg testimg.ppm >testout.jpg
cmp testimg.ppm testout.ppm
cmp testimg.gif testout.gif
cmp testimg.jpg testout.jpg
@@ -122,7 +138,7 @@ 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 jversion.h egetopt.c
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -131,7 +147,7 @@ jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
jddeflts.o : jddeflts.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 jversion.h egetopt.c
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h jversion.h
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
@@ -142,7 +158,7 @@ jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
jfwddct.o : jfwddct.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
jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpegdata.h jmemsys.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
@@ -153,3 +169,4 @@ jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
jwrrle.o : jwrrle.c jinclude.h jconfig.h jpegdata.h
jwrtarga.o : jwrtarga.c jinclude.h jconfig.h jpegdata.h
jmemsys.o : jmemsys.c jinclude.h jconfig.h jpegdata.h jmemsys.h

74
makefile.vms Normal file
View File

@@ -0,0 +1,74 @@
$! Makefile for Independent JPEG Group's software
$!
$! This is a command procedure for use on VAX/VMS systems that do not have MMS.
$! It builds the JPEG software by brute force, recompiling everything whether
$! or not it is necessary. It then runs the basic self-test.
$! Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu)
$! and Tim Bell (tbell@netcom.com) for their help.
$!
$! Read SETUP instructions before running this!!
$!
$ DoCompile := CC /NoDebug /Optimize /Define = (TWO_FILE_COMMANDLINE,HAVE_STDC,INCLUDES_ARE_ANSI)
$!
$ DoCompile jcmain.c
$ DoCompile jdmain.c
$ DoCompile jcmaster.c
$ DoCompile jcdeflts.c
$ DoCompile jcarith.c
$ DoCompile jccolor.c
$ DoCompile jcexpand.c
$ DoCompile jchuff.c
$ DoCompile jcmcu.c
$ DoCompile jcpipe.c
$ DoCompile jcsample.c
$ DoCompile jfwddct.c
$ DoCompile jwrjfif.c
$ DoCompile jrdgif.c
$ DoCompile jrdppm.c
$ DoCompile jrdrle.c
$ DoCompile jrdtarga.c
$ DoCompile jdmaster.c
$ DoCompile jddeflts.c
$ DoCompile jbsmooth.c
$ DoCompile jdarith.c
$ DoCompile jdcolor.c
$ DoCompile jdhuff.c
$ DoCompile jdmcu.c
$ DoCompile jdpipe.c
$ DoCompile jdsample.c
$ DoCompile jquant1.c
$ DoCompile jquant2.c
$ DoCompile jrevdct.c
$ DoCompile jrdjfif.c
$ DoCompile jwrgif.c
$ DoCompile jwrppm.c
$ DoCompile jwrrle.c
$ DoCompile jwrtarga.c
$ DoCompile jutils.c
$ DoCompile jerror.c
$ DoCompile jmemmgr.c
$ DoCompile jmemsys.c
$!
$ Library /Create libjpeg.olb jcmaster.obj,jcdeflts.obj,jcarith.obj, -
jccolor.obj,jcexpand.obj,jchuff.obj,jcmcu.obj,jcpipe.obj, -
jcsample.obj,jfwddct.obj,jwrjfif.obj,jrdgif.obj,jrdppm.obj, -
jrdrle.obj,jrdtarga.obj,jdmaster.obj,jddeflts.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,jwrrle.obj,jwrtarga.obj,jutils.obj, -
jerror.obj,jmemmgr.obj,jmemsys.obj
$!
$ Link /Executable = cjpeg.exe jcmain.obj,libjpeg.olb/Library,Sys$Disk:[]MAKVMS.OPT/Option
$!
$ Link /Executable = djpeg.exe jdmain.obj,libjpeg.olb/Library,Sys$Disk:[]MAKVMS.OPT/Option
$!
$! Run the self-test
$!
$ mcr sys$disk:[]djpeg testorig.jpg testout.ppm
$ mcr sys$disk:[]djpeg -gif testorig.jpg testout.gif
$ mcr sys$disk:[]cjpeg testimg.ppm testout.jpg
$ Backup /Compare/Log testimg.ppm testout.ppm
$ Backup /Compare/Log testimg.gif testout.gif
$ Backup /Compare/Log testimg.jpg testout.jpg
$!
$ Exit

View File

@@ -1,6 +0,0 @@
jcmaster.mix,jcdeflts.mix,jcarith.mix,jccolor.mix,jcexpand.mix,jchuff.mix
jcmcu.mix,jcpipe.mix,jcsample.mix,jfwddct.mix,jwrjfif.mix,jrdgif.mix
jrdppm.mix,jrdrle.mix,jrdtarga.mix,jdmaster.mix,jddeflts.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
jwrrle.mix,jwrtarga.mix,jutils.mix,jvirtmem.mix,jerror.mix

38
makljpeg.icc Normal file
View File

@@ -0,0 +1,38 @@
add jcmaster.obj
add jcdeflts.obj
add jcarith.obj
add jccolor.obj
add jcexpand.obj
add jchuff.obj
add jcmcu.obj
add jcpipe.obj
add jcsample.obj
add jfwddct.obj
add jwrjfif.obj
add jrdgif.obj
add jrdppm.obj
add jrdrle.obj
add jrdtarga.obj
add jdmaster.obj
add jddeflts.obj
add jbsmooth.obj
add jdarith.obj
add jdcolor.obj
add jdhuff.obj
add jdmcu.obj
add jdpipe.obj
add jdsample.obj
add jquant1.obj
add jquant2.obj
add jrevdct.obj
add jrdjfif.obj
add jwrgif.obj
add jwrppm.obj
add jwrrle.obj
add jwrtarga.obj
add jutils.obj
add jerror.obj
add jmemmgr.obj
add jmemsys.obj
update
quit

63
makljpeg.st Normal file
View File

@@ -0,0 +1,63 @@
; Project file for Independent JPEG Group's software
;
; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C.
; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de)
; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de).
;
; To use this file, rename it to LIB_JPEG.PRJ.
; Read SETUP instructions before trying to make the library!
;
;
; * * * Output file * * *
jpeg.lib
;
; * * * DEFINES * * *
.C[-DHAVE_STDC]
.C[-DINCLUDES_ARE_ANSI]
;
; * * * COMPILER OPTIONS * * *
.C[-P] ; absolute calls
.C[-M] ; and no string merging, folks
.C[-w-par] ; no "parameter xxxx unused"
.C[-DINCOMPLETE_TYPES_BROKEN] ; suppress warnings about undefined structures
.C[-wsig] ; warn if significant digits may be lost
.C[-w-cln] ; no "constant is long" warnings
.L[-J] ; link new Obj-format (so we get a library)
=
; * * * * List of modules * * * *
jbsmooth.c (jinclude.h,jconfig.h,jpegdata.h)
jcarith.c (jinclude.h,jconfig.h,jpegdata.h)
jccolor.c (jinclude.h,jconfig.h,jpegdata.h)
jcdeflts.c (jinclude.h,jconfig.h,jpegdata.h)
jcexpand.c (jinclude.h,jconfig.h,jpegdata.h)
jchuff.c (jinclude.h,jconfig.h,jpegdata.h)
jcmaster.c (jinclude.h,jconfig.h,jpegdata.h)
jcmcu.c (jinclude.h,jconfig.h,jpegdata.h)
jcpipe.c (jinclude.h,jconfig.h,jpegdata.h)
jcsample.c (jinclude.h,jconfig.h,jpegdata.h)
jdarith.c (jinclude.h,jconfig.h,jpegdata.h)
jdcolor.c (jinclude.h,jconfig.h,jpegdata.h)
jddeflts.c (jinclude.h,jconfig.h,jpegdata.h)
jdhuff.c (jinclude.h,jconfig.h,jpegdata.h)
jdmaster.c (jinclude.h,jconfig.h,jpegdata.h)
jdmcu.c (jinclude.h,jconfig.h,jpegdata.h)
jdpipe.c (jinclude.h,jconfig.h,jpegdata.h)
jdsample.c (jinclude.h,jconfig.h,jpegdata.h)
jerror.c (jinclude.h,jconfig.h,jpegdata.h)
jquant1.c (jinclude.h,jconfig.h,jpegdata.h)
jquant2.c (jinclude.h,jconfig.h,jpegdata.h)
jfwddct.c (jinclude.h,jconfig.h,jpegdata.h)
jrevdct.c (jinclude.h,jconfig.h,jpegdata.h)
jutils.c (jinclude.h,jconfig.h,jpegdata.h)
jmemmgr.c (jinclude.h,jconfig.h,jpegdata.h,jmemsys.h)
jrdjfif.c (jinclude.h,jconfig.h,jpegdata.h)
jrdgif.c (jinclude.h,jconfig.h,jpegdata.h)
jrdppm.c (jinclude.h,jconfig.h,jpegdata.h)
jrdrle.c (jinclude.h,jconfig.h,jpegdata.h)
jrdtarga.c (jinclude.h,jconfig.h,jpegdata.h)
jwrjfif.c (jinclude.h,jconfig.h,jpegdata.h)
jwrgif.c (jinclude.h,jconfig.h,jpegdata.h)
jwrppm.c (jinclude.h,jconfig.h,jpegdata.h)
jwrrle.c (jinclude.h,jconfig.h,jpegdata.h)
jwrtarga.c (jinclude.h,jconfig.h,jpegdata.h)
jmemsys.c (jinclude.h,jconfig.h,jpegdata.h,jmemsys.h)

3
makvms.opt Normal file
View File

@@ -0,0 +1,3 @@
! a pointer to the VAX/VMS C Run-Time Shareable Library
! This file is needed by makefile.mms and makefile.vms
Sys$Library:VAXCRTL.EXE /Share

BIN
testimg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB