Compare commits

...

3 Commits

Author SHA1 Message Date
Thomas G. Lane
36a4ccccd3 The Independent JPEG Group's JPEG software v5 2015-07-29 15:28:00 -05:00
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
152 changed files with 33149 additions and 17185 deletions

View File

@@ -1,77 +0,0 @@
CHANGELOG for Independent JPEG Group's JPEG software
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
--------------------
Documentation improved a little --- there are man pages now.
Installation instructions moved from README to a separate file SETUP.
New program config.c is provided to help you get the configuration options
right. This should make installation a lot more foolproof.
Sense of djpeg -D switch reversed: dithering is now ON by default.
RLE image file support added (thanks to Mike Lijewski).
Targa image file support added (thanks to Lee Crocker).
PPM input now accepts all PPM and PGM files.
Bug fix: on machines where 'int' is 16 bits, high-Q-setting JPEG files
were not decoded correctly.
Numerous changes to improve portability. There should be few or no compiler
warnings now.
Makefiles cleaned up; defaults now appropriate for production use rather than
debugging.
Subroutine interface cleaned up. If you wrote code based on version 1's
jcmain/jdmain, you'll need to change it, but it should get a little shorter
and simpler.
Version 1 7-Oct-91
--------------------
Initial public release.

537
README
View File

@@ -1,294 +1,130 @@
The Independent JPEG Group's JPEG software
==========================================
README for release 3 of 17-Mar-92
==================================
README for release 5 of 24-Sep-94
=================================
This distribution contains the third official release of the Independent JPEG
This distribution contains the fifth public release of the Independent JPEG
Group's free JPEG software. You are welcome to redistribute this software and
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
For installation instructions, see file SETUP; for usage instructions, see
file USAGE (or the cjpeg.1 and djpeg.1 manual pages).
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 still undergoing revision. Updated versions may be obtained
by FTP or UUCP to UUNET and other archive sites; see ARCHIVE LOCATIONS below
for details.
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Jim
Boucher, Lee Crocker, George Phillips, Davide Rossi, Ge' Weijers, and other
members of the Independent JPEG Group.
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.
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz,
Lee Crocker, Ge' Weijers, and other members of the Independent JPEG Group.
IJG is not associated with the official ISO JPEG standards committee.
DISCLAIMER
==========
DOCUMENTATION ROADMAP
=====================
THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED. It is not guaranteed to be
useful for anything, nor to be compatible with subsequent releases, nor to be
an accurate implementation of the JPEG standard. (See LEGAL ISSUES for even
more disclaimers.)
This file contains the following sections:
Please report any problems with this software to jpeg-info@uunet.uu.net.
OVERVIEW General description of JPEG and the IJG software.
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
REFERENCES Where to learn more about JPEG.
ARCHIVE LOCATIONS Where to find newer versions of this software.
RELATED SOFTWARE Other stuff you should get.
FILE FORMAT WARS Software *not* to get.
TO DO Plans for future IJG releases.
Other documentation files in the distribution are:
User documentation:
install.doc How to configure and install the IJG software.
usage.doc Usage instructions for cjpeg, djpeg, rdjpgcom, wrjpgcom.
*.1 Unix-style man pages for programs (same info as usage.doc).
change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.doc How to use the JPEG library in your own programs.
example.c Sample code for calling the JPEG library.
structure.doc Overview of the JPEG library's internal structure.
filelist.doc Road map of IJG files.
coderules.doc Coding style rules --- please read if you contribute code.
Please read at least the files install.doc and usage.doc. Useful information
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
If you want to understand how the JPEG code works, we suggest reading one or
more of the REFERENCES, then looking at the documentation files (in roughly
the order listed) before diving into the code.
WHAT'S HERE
===========
OVERVIEW
========
This distribution contains C software to implement JPEG image compression and
This package 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
We provide a set of library routines for reading and writing JPEG image files,
plus two simple applications "cjpeg" and "djpeg", which use the library to
perform conversion between JPEG and some other popular image file formats.
The library is intended to be reused in other applications.
This 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, hierarchical, or lossless processes defined in the standard.
(Support for progressive mode may be offered in a future release.)
The present software is not far beyond 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 of the
library if not required for a particular application. We have also included
two simple applications for inserting and extracting textual comments in
JFIF files.
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
functionality and speed as time goes on.
* As the basis for other JPEG programs. For example, you could incorporate
the decompressor into a general image viewing package by replacing the
output module with write-to-screen functions. For an implementation on
specific hardware, you might want to replace some of the inner loops with
assembly code. For a non-command-line-driven system, you might want a
different user interface. (Members of the group will be producing Macintosh
and Amiga versions with more appropriate user interfaces, for example.)
* As a toolkit for experimentation with JPEG and JPEG-like algorithms. Most
of the individual decisions you might want to mess with are packaged up into
separate modules. For example, the details of color-space conversion and
subsampling techniques are each localized in one compressor and one
decompressor module. You'd probably also want to extend the user interface
to give you more detailed control over the JPEG compression parameters.
In particular, we welcome the use of this software as a component of commercial
products; no royalty is required.
ARCHIVE LOCATIONS
=================
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.v3.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).
You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum
(GO PICS), library 10; this version will be file jpsrc3.zip.
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.
SUPPORTING SOFTWARE
===================
You will probably want Jef Poskanzer's PBMPLUS image software, which provides
many useful operations on PPM-format image files. In particular, it can
convert PPM images to and from a wide range of other formats. You can FTP
this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or
ftp.ee.lbl.gov (pbmplus*.tar.Z). Unfortunately PBMPLUS is not nearly as
portable as the JPEG software is; you are likely to have difficulty making it
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. 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; you may
also prefer xloadimage for viewing if you have a 24-bit display. Caveat user.)
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
==============================
Handmade Software's shareware PC program GIF2JPG produces files that are
totally incompatible with our programs. They use a proprietary format that is
an amalgam of GIF and JPEG representations. However, you can force GIF2JPG
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, many 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
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.
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!
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.
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.
Mechanics: 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:
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.
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).
The JPEG standard does not specify all details of an interchangeable file
format. For the omitted details we follow the "JFIF" conventions, revision
1.01. A copy of the JFIF spec is available from:
Literature Department
C-Cube Microsystems, Inc.
399A West Trimble Road
San Jose, CA 95131
(408) 944-6300
The same source can supply copies of the draft JPEG-in-TIFF documents
(Appendixes O and P to the TIFF spec). PostScript versions of these
documents 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 obtain the
JFIF document; "send app_o_ps from jpeg" and "send app_p_ps from jpeg" will
produce the TIFF documents. Send the message "help" if you have trouble.
If you want to understand this implementation, start by reading the
"architecture" documentation file. Please read "codingrules" if you want to
contribute any code.
We welcome the use of this software as a component of commercial products.
No royalty is required, but we do ask for an acknowledgement in product
documentation, as described under LEGAL ISSUES.
LEGAL ISSUES
============
In plain English:
1. We don't promise that this software works. (But if you find any bugs,
please let us know!)
2. You can use this software for whatever you want. You don't have to pay us.
3. You may not pretend that you wrote this software. If you use it in a
program, you must acknowledge somewhere in your documentation that
you've used the IJG code.
In legalese:
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
This software is copyright (C) 1991, 1992, Thomas G. Lane.
This software is copyright (C) 1991, 1992, 1993, 1994, Thomas G. Lane.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
@@ -305,10 +141,14 @@ 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".
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
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
@@ -321,40 +161,189 @@ 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 IJG code, this does not limit you more than
the foregoing paragraphs do.
The configuration script "configure" was produced by GNU Autoconf. Again,
the FSF copyright terms apply only to configure, not to the IJG code; and
again, that does not limit your use of the object code.
It appears that the arithmetic coding option of the JPEG spec is covered by
patents owned by IBM and AT&T, as well as a pending Japanese patent of
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,
contact jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.)
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
legally be used without obtaining one or more licenses. For this reason,
support for arithmetic coding has been removed from the free JPEG software.
(Since arithmetic coding provides only a marginal gain over the unpatented
Huffman mode, it is unlikely that very many implementations will support it.)
So far as we are aware, there are no patent restrictions on the remaining
code.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."
REFERENCES
==========
We highly recommend reading one or more of these references before trying to
understand the innards of the 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.) If you don't have the CACM issue
handy, a PostScript file containing a revised version of Wallace's article is
available at ftp.uu.net, graphics/jpeg/wallace.ps.gz. 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.
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...
The best full description of JPEG is the textbook "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, 638 pp.
The 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 we highly recommend it.
The JPEG standard itself is not available electronically; you must order a
paper copy through ISO. (Unless you feel a need to own a certified official
copy, we 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, or
from Global Engineering Documents at (800) 854-7179. (ANSI doesn't take
credit card orders, but Global does.) It's not cheap: as of 1992, ANSI was
charging $95 for Part 1 and $47 for Part 2, plus 7% shipping/handling. The
standard is divided into two parts, Part 1 being the actual specification,
while Part 2 covers compliance testing methods. Part 1 is titled "Digital
Compression and Coding of Continuous-tone Still Images, Part 1: Requirements
and guidelines" and has document number ISO/IEC IS 10918-1. As of mid-1994,
Part 2 is still at Draft International Standard status. It is titled "Digital
Compression and Coding of Continuous-tone Still Images, Part 2: Compliance
testing" and has document number ISO/IEC DIS 10918-2. (The document number
will change to IS 10918-2 when final approval is obtained.) A Part 3,
covering extensions, is likely to appear in draft form in late 1994.
The JPEG standard does not specify all details of an interchangeable file
format. For the omitted details we follow the "JFIF" conventions, revision
1.02. A copy of the JFIF spec is available from:
Literature Department
C-Cube Microsystems, Inc.
1778 McCarthy Blvd.
Milpitas, CA 95035
phone (408) 944-6300, fax (408) 944-6314
A PostScript version of this document is available at ftp.uu.net, file
graphics/jpeg/jfif.ps.gz. 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
redesign effort is currently underway to correct these problems; it is
expected to result in a new, incompatible, spec. IJG intends to support the
corrected version of TIFF when the new spec is issued.
ARCHIVE LOCATIONS
=================
The "official" archive site for this software is ftp.uu.net (Internet
address 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 graphics/jpeg/jpegsrc.v5.tar.gz. If you are on the Internet, you
can retrieve files from ftp.uu.net by standard anonymous FTP. If you don't
have FTP access, UUNET's archives are also available via UUCP; contact
help@uunet.uu.net for information on retrieving files that way.
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 GRAPHSUP); this version will be file jpsrc5.zip in library 15. Again,
CompuServe is not guaranteed to have the very 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.181.0.24). 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".
RELATED SOFTWARE
================
Numerous viewing and image manipulation programs now support JPEG. (Quite a
few of them use this library to do so.) The JPEG FAQ described above lists
some of the more popular free and shareware viewers, and tells where to
obtain them on Internet.
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
PBMPLUS image software, which provides many useful operations on PPM-format
image files. In particular, it can convert PPM images to and from a wide
range of other formats. You can obtain this package by FTP from ftp.x.org
(contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). There is also
a newer update of this package called NETPBM, available from
wuarchive.wustl.edu under directory /graphics/graphics/packages/NetPBM/.
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software
is; you are likely to have difficulty making it work on any non-Unix machine.
A different free JPEG implementation, written by the PVRG group at Stanford,
is available from havefun.stanford.edu in directory pub/jpeg. This program
is designed for research and experimentation rather than production use;
it is slower, harder to use, and less portable than the IJG code, but it
implements a larger subset of the JPEG standard. In particular, it supports
lossless JPEG.
FILE FORMAT WARS
================
Some JPEG programs produce files that are not compatible with our library.
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 it has
become the de facto standard. JFIF is a minimal or "low end" representation.
Work is also going forward to incorporate JPEG compression into the TIFF
standard, for use in "high end" applications that need to record a lot of
additional data about an image. We intend to support TIFF 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 TIFF/JPEG!
TO DO
=====
Many of the modules need fleshing out to provide more complete
implementations, or to provide faster paths for common cases.
Improving the speed will be the next big work item for the JPEG group.
In future versions, we are considering supporting progressive JPEG
compression, the upcoming JPEG Part 3 extensions, and other improvements.
We'd appreciate it if people would compile and check out the code on as wide a
variety of systems as possible, and report any portability problems
encountered (with solutions, if possible). Checks of file compatibility with
other JPEG implementations would also be of interest. Finally, we would
appreciate code profiles showing where the most time is spent, especially on
unusual systems.
As always, speeding things up is high on our priority list.
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.

368
SETUP
View File

@@ -1,368 +0,0 @@
SETUP instructions for the Independent JPEG Group's JPEG software
=================================================================
This file explains how to configure and compile the JPEG software. We have
tried to make this software extremely portable and flexible, so that it can be
adapted to almost any environment. The downside of this decision is that the
installation process is not very automatic; you will need at least a little
familiarity with C programming and program build procedures for your system.
This file contains general instructions, then sections of specific hints for
certain systems. You may save yourself considerable time if you scan the
whole file before starting to do anything.
Before installing the software you must unpack the distributed source code.
Since you are reading this file, you have probably already succeeded in this
task. However, there is one potential trap if you are on a non-Unix system:
you may need to convert these files to the local standard text file format
(for example, if you are on MS-DOS you probably have to convert LF end-of-line
to CR/LF). If so, apply the conversion to all the files EXCEPT those whose
names begin with "test". The test files contain binary data; if you change
them in any way then the self-test will give bad results.
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
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.bcc: for Borland C (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.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
ANSI C or not. Actually you should start with makefile.ansi whenever your
compiler supports ANSI-style function definitions; you don't need full ANSI
compatibility. The difference between the two makefiles is that makefile.unix
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 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 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 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. 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. 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.)
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
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 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.
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.
STEP 3: SELECT SYSTEM-DEPENDENT FILES
=====================================
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 by that name 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 pre-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.
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 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).
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 5: TEST
============
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 -G 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 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, 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 your choice of jmemsys.c was anything other than jmemnobs.c, you should
also test that temporary-file usage works. Try "djpeg -G -m 0 testorig.jpg"
and make sure its output matches testimg.gif. If you have any really large
images handy, try compressing them with -o and/or decompressing with -G
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 fast 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.
OPTIONAL STUFF
==============
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
follows:
1. #define RLE_SUPPORTED in jconfig.h or in the Makefile.
2. Add a -I option to CFLAGS in the Makefile for the directory
containing the URT .h files (typically the "include"
subdirectory of the URT distribution).
3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
the directory containing the URT "librle.a" file (typically the
"lib" subdirectory of the URT distribution).
If you want to incorporate the JPEG code as subroutines in a larger program,
we recommend that you make libjpeg.a. (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.
If you need to make a smaller version of the JPEG software, some optional
functions can be removed at compile time. See the xxx_SUPPORTED #defines in
jconfig.h. If at all possible, we recommend that you leave in decoder support
for all valid JPEG files, to ensure that you can read anyone's output.
Restricting your encoder, or removing optional functions like block smoothing,
won't hurt compatibility. Taking out support for image file formats that you
don't use is the most painless way to make the programs smaller.
NOTES FOR SPECIFIC SYSTEMS
==========================
We welcome reports on changes needed for systems not mentioned here.
Submit 'em to jpeg-info@uunet.uu.net. Also, ckconfig.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.
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.
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 V2, line 42 of jchuff.c and line 38 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.
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
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 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).
Macintosh Think C:
You'll have to prepare project files for cjpeg and djpeg; we don't include
those in the distribution since they are not text files. The COBJECTS and
DOBJECTS lists in makefile.unix show which files should be included in each
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 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.)
jcmain and jdmain are set up to provide the usual command-line interface
by means of Think's ccommand() library routine. Anybody want to write a
more Mac-like interface for us?
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
those 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. For these 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.
MS-DOS, DJGPP:
The file egetopt.c conflicts with some library routines in DJGPP 1.05.
Remove #include "egetopt.c" from jcmain.c and jdmain.c, and in each of
those files change the egetopt(...) call to getopt(...). This will be
fixed more cleanly in some future version. Use makefile.ansi, and put
"-DTWO_FILE_COMMANDLINE" (but *not* -DMSDOS) in CFLAGS.
MS-DOS, Microsoft C:
Some 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.
makefile.mc6 (MS C 6.x makefile) has not been tested since jmemdosa.asm
was added; we'd appreciate hearing whether it works or not.
Sun:
Don't forget to add -DBSD to CFLAGS. If you are using GCC on SunOS 4.0.1 or
earlier, you will need to add -DNONANSI_INCLUDES to CFLAGS (your compiler may
be ANSI, but your system include files aren't). I've gotten conflicting
reports on whether this is still necessary on SunOS 4.1 or later.

212
USAGE
View File

@@ -1,212 +0,0 @@
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 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 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.
NOTE: at some point we will probably redesign the user interface, so the
command line switches described here will change.
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.
On Unix-like systems, you say:
cjpeg [switches] [imagefile] >jpegfile
or
djpeg [switches] [jpegfile] >imagefile
The programs read the specified input file, or standard input if none is
named. They always write to standard output (with trace/error messages to
standard error). These conventions are handy for piping images between
programs.
On most non-Unix systems, you say:
cjpeg [switches] imagefile jpegfile
or
djpeg [switches] jpegfile imagefile
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.)
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. 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.
CJPEG DETAILS
The command line switches for cjpeg are:
-Q quality 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 somewhat slower and needs much more memory.
Image quality and speed of decompression are unaffected
by -o.
-T 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.
-I Generate noninterleaved JPEG file (not yet supported).
-a 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.
-m memory 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, -m 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
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.)
-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.
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.)
DJPEG DETAILS
The command line switches for djpeg are:
-G Select GIF output format (implies -q, with default
of 256 colors).
-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.
-R Select RLE output format. Requires URT library.
-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.
-g Force gray-scale output even if input is color.
-q N Quantize to N colors. This reduces the number of
colors 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 quantize to 256 or fewer colors.
-D 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.
-D is ignored unless you also say -q or -G.
-1 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.
-1 is ignored unless you also say -q or -G. Also,
the one-pass method is always used for gray-scale
output (the two-pass method is no improvement then).
-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.
-d Enable debug printout. More -d's give more printout.
Also, version information is printed at startup.
-m memory 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, -m 4m selects 4000000 bytes. If more
space is needed, temporary files will be used.
HINTS
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 -o 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 -Q settings
to make very small JPEG files; the percentage improvement is often a lot more
than it is on larger files.
The default memory usage limit (-m) is set when the software is compiled.
If you get an "insufficient memory" error, try specifying a smaller -m value,
even -m 0 to use the absolute minimum space. You may want to recompile with
a smaller default value if this happens often.
djpeg with two-pass color quantization requires a good deal of space; on
MS-DOS machines it may run out of memory even with -m 0. In that case you
can still decompress, with some loss of image quality, by specifying -1
for one-pass quantization.
If more space is needed than will fit in the available main memory (as
determined by -m), 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 -o (for cjpeg) or specify -1 (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.

19
ansi2knr.1 Normal file
View File

@@ -0,0 +1,19 @@
.TH ANSI2KNR 1 "31 December 1990"
.SH NAME
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
.SH SYNOPSIS
.I ansi2knr
input_file output_file
.SH DESCRIPTION
If no output_file is supplied, output goes to stdout.
.br
There are no error messages.
.sp
.I ansi2knr
recognizes functions by seeing a non-keyword identifier at the left margin, followed by a left parenthesis, with a right parenthesis as the last character on the line. It will recognize a multi-line header if the last character on each line but the last is a left parenthesis or comma. These algorithms ignore whitespace and comments, except that the function name must be the first thing on the line.
.sp
The following constructs will confuse it:
.br
- Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call).
.br
- Macros that tinker with the syntax of the function header.

View File

@@ -1,30 +1,26 @@
/* Copyright (C) 1989, 1991, 1993 Aladdin Enterprises. All rights reserved. */
/* ansi2knr.c */
/* Convert ANSI function declarations to K&R syntax */
/*
* 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.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
ansi2knr is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
to the GNU General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
ansi2knr, but only under the conditions described in the GNU
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
given to you along with ansi2knr so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies. */
copies.
*/
/*
---------- Here is the GhostScript file COPYING, referred to above ----------
---------- Here is the GNU GPL file COPYING, referred to above ----------
----- These terms do NOT apply to the JPEG software itself; see README ------
GHOSTSCRIPT GENERAL PUBLIC LICENSE
@@ -169,28 +165,26 @@ INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
BY ANY OTHER PARTY.
-------------------- End of file COPYING ------------------------------
*/
/* ansi2knr.c */
/* Convert ANSI function declarations to K&R syntax */
#include <stdio.h>
#include <ctype.h>
#ifdef BSD
#include <strings.h>
#define strchr index
#else
#ifdef VMS
extern char *strcat(), *strchr(), *strcpy(), *strupr();
extern int strcmp(), strlen(), strncmp();
extern int strlen(), strncmp();
#else
#include <string.h>
#endif
#endif
/* malloc and free should be declared in stdlib.h, */
/* but if you've got a K&R compiler, they probably aren't. */
#ifdef MSDOS
#include <malloc.h>
#else
@@ -204,34 +198,41 @@ BY ANY OTHER PARTY.
#endif
/* Usage:
ansi2knr input_file output_file
ansi2knr input_file [output_file]
* If no output_file is supplied, output goes to stdout.
* There are no error messages.
*
* ansi2knr recognizes functions by seeing a non-keyword identifier
* at the left margin, followed by a left parenthesis,
* with a right parenthesis as the last character on the line.
* It will recognize a multi-line header if the last character
* on each line but the last is a left parenthesis or comma.
* It will recognize a multi-line header provided that the last character
* of the last line of the header is a right parenthesis,
* and no intervening line ends with a left brace or a semicolon.
* These algorithms ignore whitespace and comments, except that
* the function name must be the first thing on the line.
* The following constructs will confuse it:
- Any other construct that starts at the left margin and
follows the above syntax (such as a macro or function call).
- Macros that tinker with the syntax of the function header.
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Macros that tinker with the syntax of the function header.
*/
/* Scanning macros */
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
int
/* Forward references */
char *skipspace();
int writeblanks();
int test1();
int convert1();
/* The main program */
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 +254,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 +264,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 +274,7 @@ main(argc, argv)
line = buf;
}
if ( line != buf ) fputs(buf, out);
free(buf);
fclose(out);
fclose(in);
return 0;
@@ -327,9 +332,9 @@ test1(buf)
switch ( *bend )
{
case ')': contin = 1; break;
case '(':
case ',': contin = -1; break;
default: return 0; /* not a function */
case '{':
case ';': return 0; /* not a function */
default: contin = -1;
}
while ( isidchar(*p) ) p++;
endfn = p;
@@ -365,13 +370,16 @@ int
convert1(buf, out)
char *buf;
FILE *out;
{ char *endfn = strchr(buf, '(') + 1;
{ char *endfn;
register char *p;
char **breaks;
unsigned num_breaks = 2; /* for testing */
char **btop;
char **bp;
char **ap;
/* Pre-ANSI implementations don't agree on whether strchr */
/* is called strchr or index, so we open-code it here. */
for ( endfn = buf; *(endfn++) != '('; ) ;
top: p = endfn;
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
if ( breaks == 0 )

File diff suppressed because it is too large Load Diff

135
cderror.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* cderror.h
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the cjpeg/djpeg
* applications. These strings are not needed as part of the JPEG library
* proper.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
*/
/* To define the enum list of message codes, include this file without
* defining JMAKE_MSG_TABLE. To create the message string table, include it
* again with JMAKE_MSG_TABLE defined (this should be done in just one module).
*/
#ifdef JMAKE_MSG_TABLE
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define addon_message_table cdMsgTable
#endif
const char * const addon_message_table[] = {
#define JMESSAGE(code,string) string ,
#else /* not JMAKE_MSG_TABLE */
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_MSG_TABLE */
JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
#ifdef BMP_SUPPORTED
JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
#endif /* BMP_SUPPORTED */
#ifdef GIF_SUPPORTED
JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
JMESSAGE(JTRC_GIF_BADVERSION,
"Warning: unexpected GIF version number '%c%c%c'")
JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
#endif /* GIF_SUPPORTED */
#ifdef PPM_SUPPORTED
JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
JMESSAGE(JERR_PPM_NOT, "Not a PPM file")
JMESSAGE(JTRC_PGM, "%ux%u PGM image")
JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
JMESSAGE(JTRC_PPM, "%ux%u PPM image")
JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
#endif /* PPM_SUPPORTED */
#ifdef RLE_SUPPORTED
JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
#endif /* RLE_SUPPORTED */
#ifdef TARGA_SUPPORTED
JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
#else
JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
#endif /* TARGA_SUPPORTED */
JMESSAGE(JERR_BAD_CMAP_FILE,
"Color map file is invalid or of unsupported format")
JMESSAGE(JERR_TOO_MANY_COLORS,
"Output file format cannot handle %d colormap entries")
JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
#ifdef TARGA_SUPPORTED
JMESSAGE(JERR_UNKNOWN_FORMAT,
"Unrecognized input file format --- perhaps you need -targa")
#else
JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
#endif
JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
#ifdef JMAKE_MSG_TABLE
NULL
};
#else /* not JMAKE_MSG_TABLE */
JMSG_LASTADDONCODE
} ADDON_MESSAGE_CODE;
#endif /* JMAKE_MSG_TABLE */
#undef JMESSAGE

124
cdjpeg.h Normal file
View File

@@ -0,0 +1,124 @@
/*
* cdjpeg.h
*
* Copyright (C) 1994, 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 common declarations for the sample applications
* cjpeg and djpeg. It is NOT used by the core JPEG library.
*/
#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h" /* get library error codes too */
#include "cderror.h" /* get application-specific error codes */
/*
* Object interface for cjpeg's source file decoding modules
*/
typedef struct cjpeg_source_struct * cjpeg_source_ptr;
struct cjpeg_source_struct {
JMETHOD(void, start_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(void, finish_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
FILE *input_file;
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
/*
* Object interface for djpeg's output file encoding modules
*/
typedef struct djpeg_dest_struct * djpeg_dest_ptr;
struct djpeg_dest_struct {
/* start_output is called after jpeg_start_decompress finishes.
* The color map will be ready at this time, if one is needed.
*/
JMETHOD(void, start_output, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo));
/* Emit the specified number of pixel rows from the buffer. */
JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo,
JDIMENSION rows_supplied));
/* Finish up at the end of the image. */
JMETHOD(void, finish_output, (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo));
/* Target file spec; filled in by djpeg.c after object is created. */
FILE * output_file;
/* Output pixel-row buffer. Created by module init or start_output.
* Width is cinfo->output_width * cinfo->output_components;
* height is buffer_height.
*/
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
/*
* cjpeg/djpeg may need to perform extra passes to convert to or from
* the source/destination file format. The JPEG library does not know
* about these passes, but we'd like them to be counted by the progress
* monitor. We use an expanded progress monitor object to hold the
* additional pass count.
*/
struct cdjpeg_progress_mgr {
struct jpeg_progress_mgr pub; /* fields known to JPEG library */
int completed_extra_passes; /* extra passes completed */
int total_extra_passes; /* total extra */
/* last printed percentage stored here to avoid multiple printouts */
int percent_done;
};
typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jinit_read_bmp jIRdBMP
#define jinit_write_bmp jIWrBMP
#define jinit_read_gif jIRdGIF
#define jinit_write_gif jIWrGIF
#define jinit_read_ppm jIRdPPM
#define jinit_write_ppm jIWrPPM
#define jinit_read_rle jIRdRLE
#define jinit_write_rle jIWrRLE
#define jinit_read_targa jIRdTarga
#define jinit_write_targa jIWrTarga
#define read_color_map RdCMap
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Module selection routines for I/O modules. */
EXTERN cjpeg_source_ptr jinit_read_bmp JPP((j_compress_ptr cinfo));
EXTERN djpeg_dest_ptr jinit_write_bmp JPP((j_decompress_ptr cinfo,
boolean is_os2));
EXTERN cjpeg_source_ptr jinit_read_gif JPP((j_compress_ptr cinfo));
EXTERN djpeg_dest_ptr jinit_write_gif JPP((j_decompress_ptr cinfo));
EXTERN cjpeg_source_ptr jinit_read_ppm JPP((j_compress_ptr cinfo));
EXTERN djpeg_dest_ptr jinit_write_ppm JPP((j_decompress_ptr cinfo));
EXTERN cjpeg_source_ptr jinit_read_rle JPP((j_compress_ptr cinfo));
EXTERN djpeg_dest_ptr jinit_write_rle JPP((j_decompress_ptr cinfo));
EXTERN cjpeg_source_ptr jinit_read_targa JPP((j_compress_ptr cinfo));
EXTERN djpeg_dest_ptr jinit_write_targa JPP((j_decompress_ptr cinfo));
/* Other global routines */
EXTERN void read_color_map JPP((j_decompress_ptr cinfo, FILE * infile));

39
change.log Normal file
View File

@@ -0,0 +1,39 @@
CHANGE LOG for Independent JPEG Group's JPEG software
Version 5 24-Sep-94
--------------------
Version 5 represents a nearly complete redesign and rewrite of the IJG
software. Major user-visible changes include:
* Automatic configuration simplifies installation for most Unix systems.
* A range of speed vs. image quality tradeoffs are supported.
This includes resizing of an image during decompression: scaling down
by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
* New programs rdjpgcom and wrjpgcom allow insertion and extraction
of text comments in a JPEG file.
The application programmer's interface to the library has changed completely.
Notable improvements include:
* We have eliminated the use of callback routines for handling the
uncompressed image data. The application now sees the library as a
set of routines that it calls to read or write image data on a
scanline-by-scanline basis.
* The application image data is represented in a conventional interleaved-
pixel format, rather than as a separate array for each color channel.
This can save a copying step in many programs.
* The handling of compressed data has been cleaned up: the application can
supply routines to source or sink the compressed data. It is possible to
suspend processing on source/sink buffer overrun, although this is not
supported in all operating modes.
* All static state has been eliminated from the library, so that multiple
instances of compression or decompression can be active concurrently.
* JPEG abbreviated datastream formats are supported, ie, quantization and
Huffman tables can be stored separately from the image data.
* And not only that, but the documentation of the library has improved
considerably!
The last widely used release before the version 5 rewrite was version 4A of
18-Feb-93. Change logs before that point have been discarded, since they
are not of much interest after the rewrite.

278
cjpeg.1
View File

@@ -1,16 +1,10 @@
.TH CJPEG 1 "28 February 1992"
.TH CJPEG 1 "30 August 1994"
.SH NAME
cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS
.B cjpeg
[
.BI \-Q " quality"
]
[
.B \-oTIad
]
[
.BI \-m " memory"
.I options
]
[
.I filename
@@ -21,108 +15,250 @@ 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
format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster
The currently supported input file formats are: PPM (PBMPLUS color
format), PGM (PBMPLUS gray-scale format), BMP, 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 somewhat slower and needs much more memory. Image quality and speed of
decompression are unaffected by
.BR \-o .
.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.
.TP
.BI \-m " memory"
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 \-m 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
treat the input as Targa format.
For most Targa files, you won't need this switch.
.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.
.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. Use
.B \-baseline
if you need to ensure compatibility at low quality values.)
.PP
Switches for advanced users:
.TP
.B \-dct int
Use integer DCT method (default).
.TP
.B \-dct fast
Use fast integer DCT (less accurate).
.TP
.B \-dct float
Use floating-point DCT method.
The floating-point method is the most accurate, but will be the slowest unless
your machine has very fast floating-point hardware. Also note that results of
the floating-point method may vary slightly across machines, while the integer
methods should give the same results everywhere. The fast integer method is
much less accurate than the other two.
.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
.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 \-outfile " name"
Send output image to the named file, not to standard output.
.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 \-baseline
Force a baseline JPEG file to be generated. This clamps quantization values
to 8 bits even at low quality settings.
.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
.BI \-quality " N"
is also specified, the values in the file are scaled according to
.BR cjpeg 's
quality scaling curve.
.TP
.BI \-qslots " N[,...]"
Select which quantization table to use for each color component. By default,
table 0 is used for luminance and table 1 for chrominance components.
.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 HINTS
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
.BR cjpeg 's
.B \-quality
and
.B \-smooth
options to get a satisfactory conversion.
.B \-smooth 10
or so is often helpful.
.PP
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.
.PP
The
.B \-optimize
option to
.B 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.
.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 djpeg (1),
.BR rdjpgcom (1),
.BR wrjpgcom (1)
.br
.BR ppm (5),
.BR pgm (5)
@@ -132,13 +268,13 @@ Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
.SH AUTHOR
Independent JPEG Group
.SH BUGS
Arithmetic coding and interleaved output not yet supported.
Arithmetic coding is not supported for legal reasons.
.PP
Not all variants of Targa file format are supported.
Not all variants of BMP and Targa file formats 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.

877
cjpeg.c Normal file
View File

@@ -0,0 +1,877 @@
/*
* cjpeg.c
*
* Copyright (C) 1991-1994, 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 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
* compile-time switch TWO_FILE_COMMANDLINE:
* cjpeg [options] inputfile outputfile
* cjpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* 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 "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#define JMAKE_MSG_TABLE
#include "cderror.h" /* create message string table */
#include "jversion.h" /* for version message */
#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()'s parameter macros */
/* If you have setmode() but not <io.h>, just delete this line: */
#include <io.h> /* to declare setmode() */
#endif
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks declares it here */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#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
#ifndef EXIT_WARNING
#ifdef VMS
#define EXIT_WARNING 1 /* VMS is very nonstandard */
#else
#define EXIT_WARNING 2
#endif
#endif
/*
* This routine determines what format the input file is,
* and selects the appropriate input-reading module.
*
* To determine which family of input formats the file belongs to,
* we may look only at the first byte of the file, since C does not
* guarantee that more than one character can be pushed back with ungetc.
* Looking at additional bytes would require one of these approaches:
* 1) assume we can fseek() the input file (fails for piped input);
* 2) assume we can push back more than one character (works in
* some C implementations, but unportable);
* 3) provide our own buffering (breaks input readers that want to use
* stdio directly, such as the RLE library);
* or 4) don't put back the data, and modify the input_init methods to assume
* they start reading after the start of file (also breaks RLE library).
* #1 is attractive for MS-DOS but is untenable on Unix.
*
* The most portable solution for file types that can't be identified by their
* first byte is to make the user tell us what they are. This is also the
* only approach for "raw" file types that contain only arbitrary values.
* 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 provide a switch to force Targa input mode.
*/
static boolean is_targa; /* records user -targa switch */
LOCAL cjpeg_source_ptr
select_file_type (j_compress_ptr cinfo, FILE * infile)
{
int c;
if (is_targa) {
#ifdef TARGA_SUPPORTED
return jinit_read_targa(cinfo);
#else
ERREXIT(cinfo, JERR_TGA_NOTCOMP);
#endif
}
if ((c = getc(infile)) == EOF)
ERREXIT(cinfo, JERR_INPUT_EMPTY);
if (ungetc(c, infile) == EOF)
ERREXIT(cinfo, JERR_UNGETC_FAILED);
switch (c) {
#ifdef BMP_SUPPORTED
case 'B':
return jinit_read_bmp(cinfo);
#endif
#ifdef GIF_SUPPORTED
case 'G':
return jinit_read_gif(cinfo);
#endif
#ifdef PPM_SUPPORTED
case 'P':
return jinit_read_ppm(cinfo);
#endif
#ifdef RLE_SUPPORTED
case 'R':
return jinit_read_rle(cinfo);
#endif
#ifdef TARGA_SUPPORTED
case 0x00:
return jinit_read_targa(cinfo);
#endif
default:
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
break;
}
return NULL; /* suppress compiler warnings */
}
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static j_common_ptr sig_cinfo;
GLOBAL void
signal_catcher (int signum)
{
if (sig_cinfo != NULL) {
if (sig_cinfo->err != NULL) /* turn off trace output */
sig_cinfo->err->trace_level = 0;
jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (j_common_ptr cinfo)
{
cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
if (percent_done != prog->percent_done) {
prog->percent_done = percent_done;
if (total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
prog->pub.completed_passes + prog->completed_extra_passes + 1,
total_passes, percent_done);
} else {
fprintf(stderr, "\r %3d%% ", percent_done);
}
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 const char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
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");
#ifdef DCT_ISLOW_SUPPORTED
fprintf(stderr, " -dct int Use integer DCT method%s\n",
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
#endif
#ifdef DCT_IFAST_SUPPORTED
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
#endif
#ifdef DCT_FLOAT_SUPPORTED
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#endif
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, " -outfile name Specify name for output file\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
fprintf(stderr, " -baseline Force baseline output\n");
#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, " -qslots N[,...] Set component quantization tables\n");
fprintf(stderr, " -sample HxV[,...] Set component 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 (j_compress_ptr cinfo, char * filename, int scale_factor,
boolean force_baseline)
/* 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.
* NOTE: does not affect the qslots mapping, which will default to selecting
* table 0 for luminance (or primary) components, 1 for chrominance components.
* You must use -qslots if you want a different component->table mapping.
*/
{
/* 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 int 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;
unsigned int table[DCTSIZE2];
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] = (unsigned int) 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]] = (unsigned int) val;
}
jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
tblno++;
}
fclose(fp);
}
LOCAL void
set_quant_slots (j_compress_ptr cinfo, char *arg)
/* Process a quantization-table-selectors parameter string, of the form
* N[,N,...]
* If there are more components than parameters, the last value is replicated.
*/
{
int val = 0; /* default table # */
int ci;
char ch;
for (ci = 0; ci < MAX_COMPONENTS; ci++) {
if (*arg) {
ch = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c", &val, &ch) < 1)
usage();
if (ch != ',')
usage(); /* syntax check */
if (val < 0 || val >= NUM_QUANT_TBLS) {
fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
NUM_QUANT_TBLS-1);
exit(EXIT_FAILURE);
}
cinfo->comp_info[ci].quant_tbl_no = val;
while (*arg && *arg++ != ',') /* advance to next segment of arg string */
;
} else {
/* reached end of parameter, set remaining components to last table */
cinfo->comp_info[ci].quant_tbl_no = val;
}
}
}
LOCAL void
set_sample_factors (j_compress_ptr cinfo, char *arg)
/* Process a sample-factors parameter string, of the form
* HxV[,HxV,...]
* If there are more components than parameters, "1x1" is assumed.
*/
{
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 (j_compress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real)
/* Parse optional 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.)
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
* processing.
*/
{
int argn;
char * arg;
int quality; /* -quality parameter */
int q_scale_factor; /* scaling percentage for -qtables */
boolean force_baseline;
char * qtablefile = NULL; /* saves -qtables filename if any */
char * qslotsarg = NULL; /* saves -qslots parm if any */
char * samplearg = NULL; /* saves -sample parm if any */
/* Set up default JPEG parameters. */
/* Note that default -quality level need not, and does not,
* match the default scaling for an explicit -qtables argument.
*/
quality = 75; /* default -quality value */
q_scale_factor = 100; /* default to no scaling for -qtables */
force_baseline = FALSE; /* by default, allow 16-bit quantizers */
is_targa = FALSE;
outfilename = NULL;
cinfo->err->trace_level = 0;
/* 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, "baseline", 1)) {
/* Force baseline output (8-bit quantizer values). */
force_baseline = TRUE;
} else if (keymatch(arg, "dct", 2)) {
/* Select DCT algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else
usage();
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
static boolean printed_version = FALSE;
if (! printed_version) {
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
printed_version = TRUE;
}
cinfo->err->trace_level++;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
} else if (keymatch(arg, "maxmemory", 3)) {
/* 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->mem->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", 4)) {
/* 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). */
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &quality) != 1)
usage();
/* Change scale factor in case -qtables is present. */
q_scale_factor = jpeg_quality_scaling(quality);
} else if (keymatch(arg, "qslots", 2)) {
/* Quantization table slot numbers. */
if (++argn >= argc) /* advance to next argument */
usage();
qslotsarg = argv[argn];
/* Must delay setting qslots until after we have processed any
* colorspace-determining switches, since jpeg_set_colorspace sets
* default quant table numbers.
*/
} 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 = (unsigned int) lval;
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
} else {
cinfo->restart_in_rows = (int) lval;
/* restart_interval will be computed during startup */
}
} else if (keymatch(arg, "sample", 2)) {
/* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */
usage();
samplearg = argv[argn];
/* Must delay setting sample factors until after we have processed any
* colorspace-determining switches, since jpeg_set_colorspace sets
* default sampling factors.
*/
} 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 (for_real) {
/* Set quantization tables for selected quality. */
/* Some or all may be overridden if -qtables is present. */
jpeg_set_quality(cinfo, quality, force_baseline);
if (qtablefile != NULL) /* process -qtables if it was present */
read_quant_tables(cinfo, qtablefile, q_scale_factor, force_baseline);
if (qslotsarg != NULL) /* process -qslots if it was present */
set_quant_slots(cinfo, qslotsarg);
if (samplearg != NULL) /* process -sample if it was present */
set_sample_factors(cinfo, samplearg);
}
return argn; /* return index of next arg (file name) */
}
/*
* The main program.
*/
GLOBAL int
main (int argc, char **argv)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress;
#endif
int file_index;
cjpeg_source_ptr src_mgr;
FILE * input_file;
FILE * output_file;
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "cjpeg"; /* in case C library doesn't provide it */
/* Initialize the JPEG compression object with default error handling. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
/* Add some application-specific error messages (from cderror.h) */
jerr.addon_message_table = addon_message_table;
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
jerr.last_addon_message = JMSG_LASTADDONCODE;
/* Now safe to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
sig_cinfo = (j_common_ptr) &cinfo;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Initialize JPEG parameters.
* Much of this may be overridden later.
* In particular, we don't yet know the input file's color space,
* but we need to provide some value for jpeg_set_defaults() to work.
*/
cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
jpeg_set_defaults(&cinfo);
/* Scan command line to find file names.
* It is convenient to use just one switch-parsing routine, but the switch
* values read here are ignored; we will rescan the switches after opening
* the input file.
*/
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
#ifdef TWO_FILE_COMMANDLINE
/* 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 ((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 ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((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 ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
output_file = stdout;
#endif
}
#ifdef PROGRESS_REPORT
/* Enable progress display, unless trace output is on */
if (jerr.trace_level == 0) {
progress.pub.progress_monitor = progress_monitor;
progress.completed_extra_passes = 0;
progress.total_extra_passes = 0;
progress.percent_done = -1;
cinfo.progress = &progress.pub;
}
#endif
/* Figure out the input file format, and set up to read it. */
src_mgr = select_file_type(&cinfo, input_file);
src_mgr->input_file = input_file;
/* Read the input file header to obtain file size & colorspace. */
(*src_mgr->start_input) (&cinfo, src_mgr);
/* Now that we know input colorspace, fix colorspace-dependent defaults */
jpeg_default_colorspace(&cinfo);
/* Adjust default compression parameters by re-parsing the options */
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
/* Specify data destination for compression */
jpeg_stdio_dest(&cinfo, output_file);
/* Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Process data */
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
}
/* Finish compression and release memory */
(*src_mgr->finish_input) (&cinfo, src_mgr);
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (jerr.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

View File

@@ -1,7 +1,7 @@
/*
* ckconfig.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, 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.
*/
@@ -11,12 +11,8 @@
* software for installation on a particular system. The idea is to try to
* compile and execute this program. If your compiler fails to compile the
* program, make changes as indicated in the comments below. Once you can
* compile the program, run it, and it will tell you how to set the various
* switches in jconfig.h and in your Makefile.
*
* This could all be done automatically if we could assume we were on a Unix
* system, but we don't want to assume that, so you'll have to edit and
* recompile this program until it works.
* compile the program, run it, and it will produce a "jconfig.h" file for
* your system.
*
* As a general rule, each time you try to compile this program,
* pay attention only to the *first* error message you get from the compiler.
@@ -31,66 +27,58 @@
/* First we must see if your system has the include files we need.
* We start out with the assumption that your system follows the ANSI
* conventions for include files. If you get any error in the next dozen
* lines, undefine INCLUDES_ARE_ANSI.
* We start out with the assumption that your system has all the ANSI-standard
* include files. If you get any error trying to include one of these files,
* undefine the corresponding HAVE_xxx symbol.
*/
#define INCLUDES_ARE_ANSI /* replace 'define' by 'undef' if error here */
#ifdef INCLUDES_ARE_ANSI /* this will be skipped if you undef... */
#include <stdio.h> /* If you ain't got this, you ain't got C. */
#ifdef __SASC /* Amiga SAS C provides size_t in stddef.h. */
#include <stddef.h> /* (They are wrong...) */
#endif
#include <string.h> /* size_t might be here too. */
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
#include <stdlib.h> /* Check other ANSI includes we use. */
#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */
#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */
#include <stddef.h>
#endif
/* If your system doesn't follow the ANSI conventions, we have to figure out
* what it does follow. If you didn't get an error before this line, you can
* ignore everything down to "#define HAVE_ANSI_DEFINITIONS".
*/
#ifndef INCLUDES_ARE_ANSI /* skip these tests if INCLUDES_ARE_ANSI */
#define HAVE_STDLIB_H /* same thing for stdlib.h */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdio.h> /* If you ain't got this, you ain't got C. */
/* jinclude.h will try to include <sys/types.h> if you don't set
* INCLUDES_ARE_ANSI. We need to test whether that include file is provided.
* If you get an error here, undefine HAVE_TYPES_H.
*/
#define HAVE_TYPES_H
#ifdef HAVE_TYPES_H
#include <sys/types.h>
#endif
/* We have to see if your string functions are defined by
* strings.h (BSD convention) or string.h (everybody else).
* We try the non-BSD convention first; define BSD if the compiler
* says it can't find string.h.
* strings.h (old BSD convention) or string.h (everybody else).
* We try the non-BSD convention first; define NEED_BSD_STRINGS
* if the compiler says it can't find string.h.
*/
#undef BSD
#undef NEED_BSD_STRINGS
#ifdef BSD
#ifdef NEED_BSD_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
/* Usually size_t is defined in stdio.h, sys/types.h, and/or string.h.
* If not, you'll get an error on the "typedef size_t my_size_t;" line below.
* In that case, you'll have to search through your system library to
* figure out which include file defines "size_t". Look for a line that
* says "typedef something-or-other size_t;" (stddef.h and stdlib.h are
* good places to look first). Then, change the line below that says
* "#include <someincludefile.h>" to instead include the file
* you found size_t in, and define NEED_SPECIAL_INCLUDE.
/* On some systems (especially older Unix machines), type size_t is
* defined only in the include file <sys/types.h>. If you get a failure
* on the size_t test below, try defining NEED_SYS_TYPES_H.
*/
#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */
#ifdef NEED_SYS_TYPES_H
#include <sys/types.h>
#endif
/* Usually type size_t is defined in one of the include files we've included
* above. If not, you'll get an error on the "typedef size_t my_size_t;" line.
* In that case, first try defining NEED_SYS_TYPES_H just above.
* If that doesn't work, you'll have to search through your system library
* to figure out which include file defines "size_t". Look for a line that
* says "typedef something-or-other size_t;". Then, change the line below
* that says "#include <someincludefile.h>" to instead include the file
* you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find
* type size_t anywhere, try replacing "#include <someincludefile.h>" with
* "typedef unsigned int size_t;".
*/
#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
@@ -102,20 +90,16 @@ typedef size_t my_size_t; /* The payoff: do we have size_t now? */
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
#endif /* INCLUDES_ARE_ANSI */
/* The next question is whether your compiler supports ANSI-style function
* definitions. You need to know this in order to choose between using
* prototypes. You need to know this in order to choose between using
* makefile.ansi and using makefile.unix.
* The #define line below is set to assume you have ANSI function definitions.
* If you get an error in this group of lines, undefine HAVE_ANSI_DEFINITIONS.
* The #define line below is set to assume you have ANSI function prototypes.
* If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
*/
#define HAVE_ANSI_DEFINITIONS
#define HAVE_PROTOTYPES
#ifdef HAVE_ANSI_DEFINITIONS
#ifdef HAVE_PROTOTYPES
int testfunction (int arg1, int * arg2); /* check prototypes */
struct methods_struct { /* check method-pointer declarations */
@@ -129,7 +113,7 @@ int testfunction (int arg1, int * arg2) /* check definitions */
return arg2[arg1];
}
int testfunction1 (void) /* check void arg list */
int test2function (void) /* check void arg list */
{
return 0;
}
@@ -167,12 +151,21 @@ unsigned short un_short;
#define HAVE_VOID
#ifdef HAVE_VOID
/* Caution: a C++ compiler will insist on complete prototypes */
typedef void * void_ptr; /* check void * */
typedef void (*void_func) (); /* check ptr to function returning void */
#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
typedef void (*void_func) (int a, int b);
#else
typedef void (*void_func) ();
#endif
void testfunction2 (arg1, arg2) /* check void function result */
#ifdef HAVE_PROTOTYPES /* check void function result */
void test3function (void_ptr arg1, void_func arg2)
#else
void test3function (arg1, arg2)
void_ptr arg1;
void_func arg2;
#endif
{
char * locptr = (char *) arg1; /* check casting to and from void * */
arg1 = (void *) locptr;
@@ -190,214 +183,220 @@ void testfunction2 (arg1, arg2) /* check void function result */
#ifdef HAVE_CONST
static const int carray[3] = {1, 2, 3};
int testfunction3 (arg1)
#ifdef HAVE_PROTOTYPES
int test4function (const int arg1)
#else
int test4function (arg1)
const int arg1;
#endif
{
return carray[arg1];
}
#endif
/* If you get an error or warning about this structure definition,
* define INCOMPLETE_TYPES_BROKEN.
*/
#undef INCOMPLETE_TYPES_BROKEN
#ifndef INCOMPLETE_TYPES_BROKEN
typedef struct undefined_structure * undef_struct_ptr;
#endif
/* If you get an error about duplicate names,
* define NEED_SHORT_EXTERNAL_NAMES.
*/
#undef NEED_SHORT_EXTERNAL_NAMES
#ifndef NEED_SHORT_EXTERNAL_NAMES
int possibly_duplicate_function ()
{
return 0;
}
int possibly_dupli_function ()
{
return 1;
}
#endif
/************************************************************************
* OK, that's it. You should not have to change anything beyond this
* point in order to compile and execute this program. (You might get
* some warnings, but you can ignore them.)
* When you run the program, it will make a couple more tests that it
* can do automatically, and then it will print out a summary of the changes
* that you need to make to the makefile and jconfig.h.
* can do automatically, and then it will create jconfig.h and print out
* any additional suggestions it has.
************************************************************************
*/
static int any_changes = 0;
int new_change ()
{
if (! any_changes) {
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");
any_changes = 1;
}
printf("\n"); /* blank line before each problem report */
return 0;
}
int test_char_sign (arg)
#ifdef HAVE_PROTOTYPES
int is_char_signed (int arg)
#else
int is_char_signed (arg)
int arg;
#endif
{
if (arg == 189) { /* expected result for unsigned char */
new_change();
printf("You should add -DCHAR_IS_UNSIGNED to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define CHAR_IS_UNSIGNED */ in jconfig.h.\n");
printf("(Be sure to delete the space before the # character too.)\n");
return 0; /* type char is unsigned */
}
else if (arg != -67) { /* expected result for signed char */
new_change();
printf("Hmm, it seems 'char' is less than eight bits wide on your machine.\n");
printf("I fear the JPEG software will not work at all.\n");
printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
printf("I fear the JPEG software will not work at all.\n\n");
}
return 0;
return 1; /* assume char is signed otherwise */
}
int test_shifting (arg)
#ifdef HAVE_PROTOTYPES
int is_shifting_signed (long arg)
#else
int is_shifting_signed (arg)
long arg;
#endif
/* See whether right-shift on a long is signed or not. */
{
long res = arg >> 4;
if (res == 0x80817F4L) { /* expected result for unsigned */
new_change();
printf("You must add -DRIGHT_SHIFT_IS_UNSIGNED to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define RIGHT_SHIFT_IS_UNSIGNED */ in jconfig.h.\n");
if (res == -0x7F7E80CL) { /* expected result for signed shift */
return 1; /* right shift is signed */
}
else if (res != -0x7F7E80CL) { /* expected result for signed */
new_change();
printf("Right shift isn't acting as I expect it to.\n");
printf("I fear the JPEG software will not work at all.\n");
/* see if unsigned-shift hack will fix it. */
/* we can't just test exact value since it depends on width of long... */
res |= (~0L) << (32-4);
if (res == -0x7F7E80CL) { /* expected result now? */
return 0; /* right shift is unsigned */
}
return 0;
printf("Right shift isn't acting as I expect it to.\n");
printf("I fear the JPEG software will not work at all.\n\n");
return 0; /* try it with unsigned anyway */
}
#ifdef HAVE_PROTOTYPES
int main (int argc, char ** argv)
#else
int main (argc, argv)
int argc;
char ** argv;
#endif
{
char signed_char_check = (char) (-67);
FILE *outfile;
printf("Results of configuration check for Independent JPEG Group's software:\n");
printf("\nIf there's not a specific makefile provided for your compiler,\n");
#ifdef HAVE_ANSI_DEFINITIONS
printf("you should use makefile.ansi as the starting point for your Makefile.\n");
#else
printf("you should use makefile.unix as the starting point for your Makefile.\n");
#endif
/* Check whether we have all the ANSI features, */
/* and whether this agrees with __STDC__ being predefined. */
#ifdef __STDC__
#define HAVE_STDC /* ANSI compilers won't allow redefining __STDC__ */
#endif
#ifdef HAVE_ANSI_DEFINITIONS
#ifdef HAVE_UNSIGNED_CHAR
#ifdef HAVE_UNSIGNED_SHORT
#ifdef HAVE_CONST
#define HAVE_ALL_ANSI_FEATURES
#endif
#endif
#endif
#endif
#ifdef HAVE_ALL_ANSI_FEATURES
#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 -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 HAVE_STDC
new_change();
printf("Your compiler claims to be ANSI-compliant, but it is lying!\n");
printf("Delete the line #define HAVE_STDC near the beginning of jconfig.h.\n");
#undef HAVE_STDC
#endif
#endif /* HAVE_ALL_ANSI_FEATURES */
#ifndef HAVE_STDC
#ifdef HAVE_ANSI_DEFINITIONS
new_change();
printf("You should add -DPROTO to CFLAGS, or else take out the several\n");
printf("#ifdef/#else/#endif lines surrounding #define PROTO in jconfig.h.\n");
printf("(Leave only one #define PROTO line.)\n");
#endif
#ifdef HAVE_UNSIGNED_CHAR
#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 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 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 HAVE_STDC/#endif lines surrounding it in jconfig.h.\n");
#endif
#endif /* HAVE_UNSIGNED_CHAR */
#ifdef HAVE_CONST
new_change();
printf("You should delete the #define const line from jconfig.h.\n");
#endif
#endif /* HAVE_STDC */
test_char_sign((int) signed_char_check);
test_shifting(-0x7F7E80B1L);
#ifndef HAVE_VOID
new_change();
printf("You should add -Dvoid=char to CFLAGS,\n");
printf("or else remove the /* */ comment marks from the line\n");
printf("/* #define void char */ in jconfig.h.\n");
printf("(Be sure to delete the space before the # character too.)\n");
#endif
#ifdef INCLUDES_ARE_ANSI
#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 __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");
#endif
#ifdef NEED_SPECIAL_INCLUDE
new_change();
printf("In jinclude.h, change the line reading #include <sys/types.h>\n");
printf("to instead include the file you found size_t in.\n");
#else /* !NEED_SPECIAL_INCLUDE */
#ifndef HAVE_TYPES_H
new_change();
printf("In jinclude.h, delete the line reading #include <sys/types.h>.\n");
#endif
#endif /* NEED_SPECIAL_INCLUDE */
#ifdef BSD
new_change();
printf("You should add -DBSD to CFLAGS, or else add\n");
printf("#define BSD at the beginning of jinclude.h (NOT jconfig.h).\n");
#endif
#endif /* INCLUDES_ARE_ANSI */
if (any_changes) {
printf("\nI think that's everything...\n");
} else {
printf("\nI think jconfig.h is OK as distributed.\n");
/* Attempt to write jconfig.h */
if ((outfile = fopen("jconfig.h", "w")) == NULL) {
printf("Failed to write jconfig.h\n");
return 1;
}
return any_changes;
/* Write out all the info */
fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
fprintf(outfile, "/* see jconfig.doc for explanations */\n\n");
#ifdef HAVE_PROTOTYPES
fprintf(outfile, "#define HAVE_PROTOTYPES\n");
#else
fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
#endif
#ifdef HAVE_UNSIGNED_CHAR
fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
#else
fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
#endif
#ifdef HAVE_UNSIGNED_SHORT
fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
#else
fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
#endif
#ifdef HAVE_VOID
fprintf(outfile, "/* #define void char */\n");
#else
fprintf(outfile, "#define void char\n");
#endif
#ifdef HAVE_CONST
fprintf(outfile, "/* #define const */\n");
#else
fprintf(outfile, "#define const\n");
#endif
if (is_char_signed((int) signed_char_check))
fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
else
fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
#ifdef HAVE_STDDEF_H
fprintf(outfile, "#define HAVE_STDDEF_H\n");
#else
fprintf(outfile, "#undef HAVE_STDDEF_H\n");
#endif
#ifdef HAVE_STDLIB_H
fprintf(outfile, "#define HAVE_STDLIB_H\n");
#else
fprintf(outfile, "#undef HAVE_STDLIB_H\n");
#endif
#ifdef NEED_BSD_STRINGS
fprintf(outfile, "#define NEED_BSD_STRINGS\n");
#else
fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
#endif
#ifdef NEED_SYS_TYPES_H
fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
#else
fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
#endif
fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
#ifdef NEED_SHORT_EXTERNAL_NAMES
fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
#else
fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
#endif
#ifdef INCOMPLETE_TYPES_BROKEN
fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
#else
fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
#endif
fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
if (is_shifting_signed(-0x7F7E80B1L))
fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
else
fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n");
fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n");
fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n");
fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n");
fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n");
fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n");
fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n");
fprintf(outfile, "#undef DONT_USE_B_MODE\n");
fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n");
fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
/* Close the jconfig.h file */
fclose(outfile);
/* User report */
printf("Configuration check for Independent JPEG Group's software done.\n");
printf("\nI have written the jconfig.h file for you.\n\n");
#ifdef HAVE_PROTOTYPES
printf("You should use makefile.ansi as the starting point for your Makefile.\n");
#else
printf("You should use makefile.unix as the starting point for your Makefile.\n");
#endif
#ifdef NEED_SPECIAL_INCLUDE
printf("\nYou'll need to change jconfig.h to include the system include file\n");
printf("that you found type size_t in, or add a direct definition of type\n");
printf("size_t if that's what you used. Just add it to the end.\n");
#endif
return 0;
}

118
coderules.doc Normal file
View File

@@ -0,0 +1,118 @@
IJG JPEG LIBRARY: CODING RULES
Copyright (C) 1991-1994, 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.
Since numerous people will be contributing code and bug fixes, it's important
to establish a common coding style. The goal of using similar coding styles
is much more important than the details of just what that style is.
In general we follow the recommendations of "Recommended C Style and Coding
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
Brader). This document is available in the IJG FTP archive (see
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
Block comments should be laid out thusly:
/*
* Block comments in this style.
*/
We indent statements in K&R style, e.g.,
if (test) {
then-part;
} else {
else-part;
}
with two spaces per indentation level. (This indentation convention is
handled automatically by GNU Emacs and many other text editors.)
Multi-word names should be written in lower case with underscores, e.g.,
multi_word_name (not multiWordName). Preprocessor symbols and enum constants
are similar but upper case (MULTI_WORD_NAME). Names should be unique within
the first fifteen characters. (On some older systems, global names must be
unique within six characters. We accommodate this without cluttering the
source code by using macros to substitute shorter names.)
We use function prototypes everywhere; we rely on automatic source code
transformation to feed prototype-less C compilers. Transformation is done
by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript).
ansi2knr is not very bright, so it imposes a format requirement on function
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
should be written in the following style:
LOCAL int *
function_name (int a, char *b)
{
code...
}
Note that each function definition is prefixed with GLOBAL, LOCAL, or
METHODDEF. These macros expand to "static" or nothing as appropriate.
They provide a readable indication of the routine's usage and can readily be
changed for special needs. (For instance, all routines can be made global for
use with debuggers or code profilers that require it.)
ansi2knr does not transform method declarations (function pointers in
structs). We handle these with a macro JMETHOD, defined as
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
which is used like this:
struct function_pointers {
JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp));
JMETHOD(void, term_entropy_encoder, (void));
};
Note the set of parentheses surrounding the parameter list.
A similar solution is used for external function declarations (see the JPP
macro).
If the code is to work on non-ANSI compilers, we cannot rely on a prototype
declaration to coerce actual parameters into the right types. Therefore, use
explicit casts on actual parameters whenever the actual parameter type is not
identical to the formal parameter. Beware of implicit conversions to "int".
It seems there are some non-ANSI compilers in which the sizeof() operator
is defined to return int, yet size_t is defined as long. Needless to say,
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
so that the result is guaranteed to be of type size_t.
The JPEG library is intended to be used within larger programs. Furthermore,
we want it to be reentrant so that it can be used by applications that process
multiple images concurrently. The following rules support these requirements:
1. Avoid direct use of file I/O, "malloc", error report printouts, etc;
pass these through the common routines provided.
2. Minimize global namespace pollution. Functions should be declared static
wherever possible. (Note that our method-based calling conventions help this
a lot: in many modules only the initialization function will ever need to be
called directly, so only that function need be externally visible.) All
global function names should begin with "jpeg_", and should have an
abbreviated name (unique in the first six characters) substituted by macro
when NEED_SHORT_EXTERNAL_NAMES is set.
3. Don't use global variables; anything that must be used in another module
should be in the common data structures.
4. Don't use static variables except for read-only constant tables. Variables
that should be private to a module can be placed into private structures (see
the system architecture document, structure.doc).
5. Source file names should begin with "j" for files that are part of the
library proper; source files that are not part of the library, such as cjpeg.c
and djpeg.c, do not begin with "j". Keep source file names to eight
characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep
compression and decompression code in separate source files --- some
applications may want only one half of the library.
Note: these rules (particularly #4) are not followed religiously in the
modules that are used in cjpeg/djpeg but are not part of the JPEG library
proper. Those modules are not really intended to be used in other
applications.

View File

@@ -1,99 +0,0 @@
JPEG SYSTEM CODING RULES 27-SEP-91
Since numerous people will be contributing code and bug fixes, it's important
to establish a common coding style. The goal of using similar coding styles
is much more important than the details of just what that style is.
I suggest we follow the recommendations of "Recommended C Style and Coding
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
Brader). I have placed a copy of this document in the jpeg FTP archive (see
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
Unless someone has a real strong objection, let's do block comments thusly:
/*
* Block comments in this style.
*/
and indent statements in K&R style, e.g.,
if (test) {
then-part;
} else {
else-part;
}
I suggest that multi-word names be written in the style multi_word_name
rather than multiWordName, but I am open to argument on this.
I would like to use function prototypes everywhere, and rely on automatic
source code transformation to feed non-ANSI C compilers. The best tool
I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
ansi2knr is not very bright, so it imposes a format requirement on function
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
should be written in the following style:
static int *
function_name (int a, char *b)
{
code...
}
ansi2knr won't help with method declarations (function pointers in structs).
I suggest we use a macro to declare method pointers, something like this:
#ifdef PROTO
#define METHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define METHOD(type,methodname,arglist) type (*methodname) ()
#endif
which is used like this:
struct function_pointers {
METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
METHOD(void, term_entropy_encoder, (void));
};
Note the set of parentheses surrounding the parameter list.
A similar solution is used for external function declarations (see the PP
macro in jpegdata.h).
If the code is to work on non-ANSI compilers, you cannot rely on a prototype
declaration to coerce actual parameters into the right types. Therefore, use
explicit casts on actual parameters whenever the actual parameter type is not
identical to the formal parameter. Beware of implicit conversions to "int".
It seems there are some non-ANSI compilers in which the sizeof() operator
is defined to return int, while size_t is defined as long. Needless to say,
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
so that the result is guaranteed to be of type size_t.
We can expect that the JPEG compressor and decompressor will be incorporated
into larger programs. Therefore, the following rules are important:
1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
pass these through the common routines provided.
2. Assume that the JPEG code may be invoked more than once per program run;
therefore, do not rely on static initialization of variables, and be careful
to release all allocated storage at the end of processing.
3. Minimize global namespace pollution. Functions should be declared static
wherever possible. (Note that our method-based calling conventions help this
a lot: in many modules only the method-selector function will ever need to be
called directly, so only that function need be externally visible.) All
global function names should begin with "j", and should be unique in the first
six characters for portability reasons.
Don't use global variables at all; anything that must be used in another
module should be put into parameters (there'll be some large structs passed
around for this purpose).
4. Source file names should also begin with "j"; remember to keep them to
eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
Do not put code for both compression and decompression into the same source
file.

1168
configure vendored Executable file

File diff suppressed because it is too large Load Diff

257
djpeg.1
View File

@@ -1,16 +1,10 @@
.TH DJPEG 1 "28 February 1992"
.TH DJPEG 1 "28 August 1994"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
.B djpeg
[
.B \-GPRTgD1bd
]
[
.BI \-q " colors"
]
[
.BI \-m " memory"
.I options
]
[
.I filename
@@ -20,94 +14,223 @@ 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.)
and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP,
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).
.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 \-fast
Select recommended processing options for fast, low quality output. (The
default options are chosen for highest quality output.) Currently, this is
equivalent to \fB\-dct fast \-nosmooth \-onepass \-dither ordered\fR.
.TP
.B \-T
.B \-grayscale
Force gray-scale output even if JPEG file is color. Useful for viewing on
monochrome displays; also,
.B djpeg
runs noticeably faster in this mode.
.TP
.BI \-scale " M/N"
Scale the output image by a factor M/N. Currently the scale factor must be
1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your
screen; also,
.B djpeg
runs much faster when scaling down the output.
.TP
.B \-bmp
Select BMP output format (Windows flavor). 8-bit colormapped format is
emitted if
.B \-colors
or
.B \-grayscale
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
format is emitted.
.TP
.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 \-os2
Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is
emitted if
.B \-colors
or
.B \-grayscale
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
format is emitted.
.TP
.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 \-g
Force gray-scale output even if input is color.
.B \-dct int
Use integer DCT method (default).
.TP
.BI \-q " N"
Quantize to N colors. This reduces the number of colors 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 quantize to 256 or fewer colors.
.B \-dct fast
Use fast integer DCT (less accurate).
.TP
.B \-D
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 .
.B \-D
is ignored unless you also say
.B \-q
or
.BR \-G .
.B \-dct float
Use floating-point DCT method.
The floating-point method is the most accurate, but will be the slowest unless
your machine has very fast floating-point hardware. Also note that results of
the floating-point method may vary slightly across machines, while the integer
methods should give the same results everywhere. The fast integer method is
much less accurate than the other two.
.TP
.B \-1
.B \-dither fs
Use Floyd-Steinberg dithering in color quantization.
.TP
.B \-dither ordered
Use ordered dithering in color quantization.
.TP
.B \-dither none
Do not use dithering in color quantization.
By default, Floyd-Steinberg dithering is applied when quantizing colors; this
is slow but usually produces the best results. Ordered dither is a compromise
between speed and quality; no dithering is fast but usually looks awful. Note
that these switches have no effect unless color quantization is being done.
Ordered dither is only available in
.B \-onepass
mode.
.TP
.BI \-map " file"
Quantize to the colors used in the specified image file. This is useful for
producing multiple files with identical color maps, or for forcing a
predefined set of colors to be used. The
.I file
must be a GIF or PPM file. This option overrides
.B \-colors
and
.BR \-onepass .
.TP
.B \-nosmooth
Use a faster, lower-quality upsampling routine.
.TP
.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 \-1
.B \-onepass
is ignored unless you also say
.B \-q
or
.BR \-G .
.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 \-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.
.TP
.B \-d
Enable debug printout. More
.BR \-d 's
give more output. Also, version information is printed at startup.
.TP
.BI \-m " memory"
.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 \-m 4m
.B \-max 4m
selects 4000000 bytes. If more space is needed, temporary files will be used.
.TP
.BI \-outfile " name"
Send output image to the named file, not to standard output.
.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 .
.SH EXAMPLES
.LP
This example decompresses the JPEG file foo.jpg, quantizes to 256 colors,
and saves the output in GIF format in foo.gif:
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.gif
.SH HINTS
To get a quick preview of an image, use the
.B \-grayscale
and/or
.B \-scale
switches.
.B \-grayscale \-scale 1/8
is the fastest case.
.PP
Several options are available that trade off image quality to gain speed.
.B \-fast
turns on the recommended settings.
.PP
.B \-dct fast
and/or
.B \-nosmooth
gain speed at a small sacrifice in quality.
When producing a color-quantized image,
.B \-onepass \-dither ordered
is fast but much lower quality than the default behavior.
.B \-dither none
may give acceptable results in two-pass mode, but is seldom tolerable in
one-pass mode.
.PP
If you are fortunate enough to have very fast floating point hardware,
.B \-dct float
may be even faster than \fB\-dct fast\fR.
.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 cjpeg (1),
.BR rdjpgcom (1),
.BR wrjpgcom (1)
.br
.BR ppm (5),
.BR pgm (5)
@@ -119,4 +242,4 @@ Independent JPEG Group
.SH BUGS
Arithmetic coding is not supported for legal reasons.
.PP
Not as fast as we'd like.
Still not as fast as we'd like.

736
djpeg.c Normal file
View File

@@ -0,0 +1,736 @@
/*
* djpeg.c
*
* Copyright (C) 1991-1994, 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 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
* compile-time switch TWO_FILE_COMMANDLINE:
* djpeg [options] inputfile outputfile
* djpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
* 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 "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#define JMAKE_MSG_TABLE
#include "cderror.h" /* create message string table */
#include "jversion.h" /* for version message */
#include <ctype.h> /* to declare isupper(),tolower(),isprint() */
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef USE_SETMODE
#include <fcntl.h> /* to declare setmode()'s parameter macros */
/* If you have setmode() but not <io.h>, just delete this line: */
#include <io.h> /* to declare setmode() */
#endif
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks declares it here */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#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
#ifndef EXIT_WARNING
#ifdef VMS
#define EXIT_WARNING 1 /* VMS is very nonstandard */
#else
#define EXIT_WARNING 2
#endif
#endif
/*
* This list defines the known output image formats
* (not all of which need be supported by a given version).
* You can change the default output format by defining DEFAULT_FMT;
* indeed, you had better do so if you undefine PPM_SUPPORTED.
*/
typedef enum {
FMT_BMP, /* BMP format (Windows flavor) */
FMT_GIF, /* GIF format */
FMT_OS2, /* BMP format (OS/2 flavor) */
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
FMT_RLE, /* RLE format */
FMT_TARGA, /* Targa format */
FMT_TIFF /* TIFF format */
} IMAGE_FORMATS;
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
#define DEFAULT_FMT FMT_PPM
#endif
static IMAGE_FORMATS requested_fmt;
/*
* Signal catcher to ensure that temporary files are removed before aborting.
* NB: for Amiga Manx C this is actually a global routine named _abort();
* we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
*/
#ifdef NEED_SIGNAL_CATCHER
static j_common_ptr sig_cinfo;
GLOBAL void
signal_catcher (int signum)
{
if (sig_cinfo != NULL) {
if (sig_cinfo->err != NULL) /* turn off trace output */
sig_cinfo->err->trace_level = 0;
jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
}
exit(EXIT_FAILURE);
}
#endif
/*
* Optional routine to display a percent-done figure on stderr.
*/
#ifdef PROGRESS_REPORT
METHODDEF void
progress_monitor (j_common_ptr cinfo)
{
cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
if (percent_done != prog->percent_done) {
prog->percent_done = percent_done;
if (total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
prog->pub.completed_passes + prog->completed_extra_passes + 1,
total_passes, percent_done);
} else {
fprintf(stderr, "\r %3d%% ", percent_done);
}
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 const char * progname; /* program name for error messages */
static char * outfilename; /* for -outfile switch */
LOCAL void
usage (void)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s [switches] ", progname);
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, "inputfile outputfile\n");
#else
fprintf(stderr, "[inputfile]\n");
#endif
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
fprintf(stderr, " -fast Fast, low-quality processing\n");
fprintf(stderr, " -grayscale Force grayscale output\n");
#ifdef IDCT_SCALING_SUPPORTED
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
#endif
#ifdef BMP_SUPPORTED
fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
(DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
#endif
#ifdef GIF_SUPPORTED
fprintf(stderr, " -gif Select GIF output format%s\n",
(DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
#endif
#ifdef BMP_SUPPORTED
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
(DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
#endif
#ifdef PPM_SUPPORTED
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
(DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
#endif
#ifdef RLE_SUPPORTED
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
#endif
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Select Targa output format%s\n",
(DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef DCT_ISLOW_SUPPORTED
fprintf(stderr, " -dct int Use integer DCT method%s\n",
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
#endif
#ifdef DCT_IFAST_SUPPORTED
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
#endif
#ifdef DCT_FLOAT_SUPPORTED
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#endif
fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
fprintf(stderr, " -dither none Don't use dithering in quantization\n");
fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
#ifdef QUANT_2PASS_SUPPORTED
fprintf(stderr, " -map FILE Map to colors used in named image file\n");
#endif
fprintf(stderr, " -nosmooth Don't use high-quality upsampling\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, " -outfile name Specify name for output file\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 (j_decompress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real)
/* Parse optional 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.)
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
* processing.
*/
{
int argn;
char * arg;
/* Set up default JPEG parameters. */
requested_fmt = DEFAULT_FMT; /* set default output file format */
outfilename = NULL;
cinfo->err->trace_level = 0;
/* 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, "bmp", 1)) {
/* BMP output format. */
requested_fmt = FMT_BMP;
} 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, "dct", 2)) {
/* Select IDCT algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else
usage();
} else if (keymatch(arg, "dither", 2)) {
/* Select dithering algorithm. */
if (++argn >= argc) /* advance to next argument */
usage();
if (keymatch(argv[argn], "fs", 2)) {
cinfo->dither_mode = JDITHER_FS;
} else if (keymatch(argv[argn], "none", 2)) {
cinfo->dither_mode = JDITHER_NONE;
} else if (keymatch(argv[argn], "ordered", 2)) {
cinfo->dither_mode = JDITHER_ORDERED;
} else
usage();
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
/* On first -d, print version identification */
static boolean printed_version = FALSE;
if (! printed_version) {
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
printed_version = TRUE;
}
cinfo->err->trace_level++;
} else if (keymatch(arg, "fast", 1)) {
/* Select recommended processing options for quick-and-dirty output. */
cinfo->two_pass_quantize = FALSE;
cinfo->dither_mode = JDITHER_ORDERED;
if (! cinfo->quantize_colors) /* don't override an earlier -colors */
cinfo->desired_number_of_colors = 216;
cinfo->dct_method = JDCT_FASTEST;
cinfo->do_fancy_upsampling = FALSE;
} 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 = JCS_GRAYSCALE;
} else if (keymatch(arg, "map", 3)) {
/* Quantize to a color map taken from an input file. */
if (++argn >= argc) /* advance to next argument */
usage();
if (for_real) { /* too expensive to do twice! */
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
FILE * mapfile;
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
exit(EXIT_FAILURE);
}
read_color_map(cinfo, mapfile);
fclose(mapfile);
cinfo->quantize_colors = TRUE;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
} else if (keymatch(arg, "maxmemory", 3)) {
/* 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->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "nosmooth", 3)) {
/* Suppress fancy upsampling */
cinfo->do_fancy_upsampling = FALSE;
} else if (keymatch(arg, "onepass", 3)) {
/* Use fast one-pass quantization. */
cinfo->two_pass_quantize = FALSE;
} else if (keymatch(arg, "os2", 3)) {
/* BMP output format (OS/2 flavor). */
requested_fmt = FMT_OS2;
} else if (keymatch(arg, "outfile", 4)) {
/* 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, "scale", 1)) {
/* Scale the output image by a fraction M/N. */
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d/%d",
&cinfo->scale_num, &cinfo->scale_denom) != 2)
usage();
} 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) */
}
/*
* Marker processor for COM markers.
* This replaces the library's built-in processor, which just skips the marker.
* We want to print out the marker as text, if possible.
* Note this code relies on a non-suspending data source.
*/
LOCAL unsigned int
jpeg_getc (j_decompress_ptr cinfo)
/* Read next byte */
{
struct jpeg_source_mgr * datasrc = cinfo->src;
if (datasrc->bytes_in_buffer == 0) {
if (! (*datasrc->fill_input_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
datasrc->bytes_in_buffer--;
return GETJOCTET(*datasrc->next_input_byte++);
}
METHODDEF boolean
COM_handler (j_decompress_ptr cinfo)
{
boolean traceit = (cinfo->err->trace_level >= 1);
INT32 length;
unsigned int ch;
unsigned int lastch = 0;
length = jpeg_getc(cinfo) << 8;
length += jpeg_getc(cinfo);
length -= 2; /* discount the length word itself */
if (traceit)
fprintf(stderr, "Comment, length %ld:\n", (long) length);
while (--length >= 0) {
ch = jpeg_getc(cinfo);
if (traceit) {
/* Emit the character in a readable form.
* Nonprintables are converted to \nnn form,
* while \ is converted to \\.
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
*/
if (ch == '\r') {
fprintf(stderr, "\n");
} else if (ch == '\n') {
if (lastch != '\r')
fprintf(stderr, "\n");
} else if (ch == '\\') {
fprintf(stderr, "\\\\");
} else if (isprint(ch)) {
putc(ch, stderr);
} else {
fprintf(stderr, "\\%03o", ch);
}
lastch = ch;
}
}
if (traceit)
fprintf(stderr, "\n");
return TRUE;
}
/*
* The main program.
*/
GLOBAL int
main (int argc, char **argv)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress;
#endif
int file_index;
djpeg_dest_ptr dest_mgr = NULL;
FILE * input_file;
FILE * output_file;
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "djpeg"; /* in case C library doesn't provide it */
/* Initialize the JPEG decompression object with default error handling. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
/* Add some application-specific error messages (from cderror.h) */
jerr.addon_message_table = addon_message_table;
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
jerr.last_addon_message = JMSG_LASTADDONCODE;
/* Insert custom COM marker processor. */
jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
/* Now safe to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
sig_cinfo = (j_common_ptr) &cinfo;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Scan command line to find file names. */
/* It is convenient to use just one switch-parsing routine, but the switch
* values read here are ignored; we will rescan the switches after opening
* the input file.
* (Exception: tracing level set here controls verbosity for COM markers
* found during jpeg_read_header...)
*/
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
#ifdef TWO_FILE_COMMANDLINE
/* 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 ((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 ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdin\n", progname);
exit(EXIT_FAILURE);
}
#else
input_file = stdin;
#endif
}
/* Open the output file. */
if (outfilename != NULL) {
if ((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 ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open stdout\n", progname);
exit(EXIT_FAILURE);
}
#else
output_file = stdout;
#endif
}
#ifdef PROGRESS_REPORT
/* Enable progress display, unless trace output is on */
if (jerr.trace_level == 0) {
progress.pub.progress_monitor = progress_monitor;
progress.completed_extra_passes = 0;
progress.total_extra_passes = 0;
progress.percent_done = -1;
cinfo.progress = &progress.pub;
}
#endif
/* Specify data source for decompression */
jpeg_stdio_src(&cinfo, input_file);
/* Read file header, set default decompression parameters */
(void) jpeg_read_header(&cinfo, TRUE);
/* Adjust default decompression parameters by re-parsing the options */
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
/* Initialize the output module now to let it override any crucial
* option settings (for instance, GIF wants to force color quantization).
*/
switch (requested_fmt) {
#ifdef BMP_SUPPORTED
case FMT_BMP:
dest_mgr = jinit_write_bmp(&cinfo, FALSE);
break;
case FMT_OS2:
dest_mgr = jinit_write_bmp(&cinfo, TRUE);
break;
#endif
#ifdef GIF_SUPPORTED
case FMT_GIF:
dest_mgr = jinit_write_gif(&cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case FMT_PPM:
dest_mgr = jinit_write_ppm(&cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case FMT_RLE:
dest_mgr = jinit_write_rle(&cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case FMT_TARGA:
dest_mgr = jinit_write_targa(&cinfo);
break;
#endif
default:
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
break;
}
dest_mgr->output_file = output_file;
/* Start decompressor */
jpeg_start_decompress(&cinfo);
/* Write output file header */
(*dest_mgr->start_output) (&cinfo, dest_mgr);
/* Process data */
while (cinfo.output_scanline < cinfo.output_height) {
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
dest_mgr->buffer_height);
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
}
#ifdef PROGRESS_REPORT
/* Hack: count final pass as done in case finish_output does an extra pass.
* The library won't have updated completed_passes.
*/
progress.pub.completed_passes = progress.pub.total_passes;
#endif
/* Finish decompression and release memory.
* I must do it in this order because output module has allocated memory
* of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
*/
(*dest_mgr->finish_output) (&cinfo, dest_mgr);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
#ifdef PROGRESS_REPORT
/* Clear away progress display */
if (jerr.trace_level == 0) {
fprintf(stderr, "\r \r");
fflush(stderr);
}
#endif
/* All done. */
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

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

817
example.c
View File

@@ -1,31 +1,29 @@
/*
* 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 IJG code as a subroutine library
* to read or write JPEG image files. You should look at this code in
* conjunction with the documentation file libjpeg.doc.
*
* 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.
* This code will not do anything useful as-is, but it may be helpful as a
* skeleton for constructing routines that call the JPEG library.
*
* 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 <stdio.h>
/*
* 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 file for users of JPEG library.
* You will need to have included system headers that define at least
* the typedefs FILE and size_t before you can include jpeglib.h.
* (stdio.h is sufficient on ANSI-conforming systems.)
* You may also wish to include "jerror.h".
*/
#include "jinclude.h"
#include "jpeglib.h"
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
@@ -45,580 +43,375 @@
/*
* 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.)
* IMAGE DATA FORMATS:
*
* 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.
* The standard input image format is a rectangular array of pixels, with
* each pixel having the same number of "component" values (color channels).
* Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
* If you are working with color data, then the color values for each pixel
* must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
* RGB color.
*
* For this example, we'll assume that this data structure matches the way
* our application has stored the image in memory, so we can just pass a
* pointer to our image buffer. In particular, let's say that the image is
* RGB color and is described by:
*/
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.
*/
}
extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
extern int image_height; /* Number of rows in image */
extern int image_width; /* Number of columns in image */
/*
* 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.
* Sample routine for JPEG compression. We assume that the target file name
* and a compression quality factor are passed in.
*/
GLOBAL void
write_JPEG_file (char * filename)
write_JPEG_file (char * filename, int quality)
{
/* 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.
/* This struct contains the JPEG compression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
* It is possible to have several such structures, representing multiple
* compression/decompression processes, in existence at once. We refer
* to any one struct (and its associated working data) as a "JPEG object".
*/
struct compress_info_struct cinfo;
struct compress_methods_struct c_methods;
struct external_methods_struct e_methods;
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
* take the easy way out and use the standard error handler, which will
* print a message on stderr and call exit() if compression fails.
*/
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
/* 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.
*/
/* Step 1: allocate and initialize JPEG compression object */
/* Here, set up pointers to your own routines for input data handling
* and post-init parameter selection.
/* We have to set up the error handler first, in case the initialization
* step fails. (Unlikely, but it could happen if you are out of memory.)
* This routine fills in the contents of struct jerr, and returns jerr's
* address which we place into the link field in cinfo.
*/
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;
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/* 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.)
*/
/* Step 2: specify data destination (eg, a file) */
/* Note: steps 2 and 3 can be done in either order. */
/* 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.
/* Here we use the library-supplied code to send compressed data to a
* stdio stream. You can also write your own code to do something else.
* 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) {
if ((outfile = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
jpeg_stdio_dest(&cinfo, outfile);
/* Here we go! */
jpeg_compress(&cinfo);
/* Step 3: set parameters for compression */
/* 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.
/* First we supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_space before calling this,
* since the defaults depend on the source color space.)
*/
jpeg_set_defaults(&cinfo);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
/* Step 4: Start compressor */
/* TRUE ensures that we will write a complete interchange-JPEG file.
* Pass TRUE unless you are very sure of what you're doing.
*/
jpeg_start_compress(&cinfo, TRUE);
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
/* Here we use the library's state variable cinfo.next_scanline as the
* loop counter, so that we don't have to keep track ourselves.
* To keep things simple, we pass one scanline per call; you can pass
* more if you wish, though.
*/
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* After finish_compress, we can close the output file. */
fclose(outfile);
/* Step 7: release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
/* And we're done! */
}
/*
* SOME FINE POINTS:
*
* In the above loop, we ignored the return value of jpeg_write_scanlines,
* which is the number of scanlines actually written. We could get away
* with this because we were only relying on the value of cinfo.next_scanline,
* which will be incremented correctly. If you maintain additional loop
* variables then you should be careful to increment them properly.
* Actually, for output to a stdio stream you needn't worry, because
* then jpeg_write_scanlines will write all the lines passed (or else exit
* with a fatal error). Partial writes can only occur if you use a data
* destination module that can demand suspension of the compressor.
* (If you don't know what that's for, you don't need it.)
*
* 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.)
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*
* Scanlines MUST be supplied 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 rdtarga.c or rdbmp.c for examples of handling bottom-to-top
* source data using the JPEG code's internal virtual-array mechanisms.
*/
/******************** 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_data, 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.
* It's a bit more refined than the above, in that we show:
* (a) how to modify the JPEG library's standard error-reporting behavior;
* (b) how to allocate workspace using the library's memory manager.
*
* 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 are 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.
* Just to make this example a little different from the first one, we'll
* assume that we do not intend to put the whole image into an in-memory
* buffer, but to send it line-by-line someplace else. We need a one-
* scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
* memory manager allocate it for us. This approach is actually quite useful
* because we don't need to remember to deallocate the buffer separately: it
* will go away automatically when the JPEG object is cleaned up.
*/
/*
* 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.
* ERROR HANDLING:
*
* 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).
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* Our example here shows how to override the "error_exit" method so that
* control is returned to the library's caller when a fatal error occurs,
* rather than calling exit() as the standard error_exit method does.
*
* We use C's setjmp/longjmp facility to return control. This means that the
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
my_error_exit (j_common_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;
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* 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;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
/*
* 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.
* Sample routine for JPEG decompression. We assume that the source file name
* is passed in. We want to return 1 on success, 0 on error.
*/
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.
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
struct decompress_info_struct cinfo;
struct decompress_methods_struct dc_methods;
struct external_methods_struct e_methods;
struct jpeg_decompress_struct cinfo;
/* We use our private extension JPEG error handler. */
struct my_error_mgr jerr;
/* More stuff */
FILE * infile; /* source file */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
/* Select the input and output files.
* In this example we want to open the input file before doing anything else,
/* 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) {
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
cinfo.output_file = NULL; /* if no actual output file involved */
/* Step 1: allocate and initialize JPEG decompression object */
/* 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 */
/* prepare setjmp context for possible exit from error_exit */
if (setjmp(setjmp_buffer)) {
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerr.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.
* We need to clean up the JPEG object, close the input file, and return.
*/
fclose(cinfo.input_file);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 0;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* 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.
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src(&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* 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;
/* Step 4: set parameters for decompression */
/* 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.
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* 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.
/* Step 5: Start decompressor */
jpeg_start_decompress(&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height) {
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
put_scanline_someplace(buffer[0], row_stride);
}
/* Step 7: Finish decompression */
(void) jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Set up to read a JFIF or baseline-JPEG file. */
/* This is the only JPEG file format currently supported. */
jselrjfif(&cinfo);
/* Step 8: Release JPEG decompression object */
/* Here we go! */
jpeg_decompress(&cinfo);
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_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);
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.
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
fclose(infile);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
return 1;
}
/*
* SOME FINE POINTS:
*
* In the above code, we ignored the return value of jpeg_read_scanlines,
* which is the number of scanlines actually read. We could get away with
* this because we asked for only one line at a time and we weren't using
* a suspending data source. See libjpeg.doc for more info.
*
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
* we should have done it beforehand to ensure that the space would be
* counted against the JPEG max_memory setting. In some systems the above
* code would risk an out-of-memory error. However, in general we don't
* know the output image dimensions before jpeg_start_decompress(), unless we
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
*
* Scanlines are returned in the same order as they appear in the JPEG file,
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
* you can use one of the virtual arrays provided by the JPEG memory manager
* to invert the data. See wrbmp.c for an example.
*
* As with compression, some operating modes may require temporary files.
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*/

185
filelist.doc Normal file
View File

@@ -0,0 +1,185 @@
IJG JPEG LIBRARY: FILE LIST
Copyright (C) 1994, 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.
Here is a road map to the files in the IJG JPEG distribution. The
distribution includes the JPEG library proper, plus two application
programs ("cjpeg" and "djpeg") which use the library to convert JPEG
files to and from some other popular image formats. There are also
two stand-alone applications, "rdjpgcom" and "wrjpgcom".
THE JPEG LIBRARY
================
Include files:
jpeglib.h JPEG library's exported data and function declarations.
jconfig.h Configuration declarations. Note: this file is not present
in the distribution; it is generated during installation.
jmorecfg.h Additional configuration declarations; need not be changed
for a standard installation.
jerror.h Declares JPEG library's error and trace message codes.
jinclude.h Central include file used by library's .c files.
jpegint.h JPEG library's internal data structures.
jdct.h Private declarations for forward & reverse DCT subsystems.
jmemsys.h Private declarations for memory management subsystem.
jversion.h Version information.
Applications using the library should include jpeglib.h (which in turn
includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included
if the application needs to reference individual JPEG error codes. The
other include files are intended for internal use and would not normally
be included by an application program. (cjpeg/djpeg do use jinclude.h,
since its function is to improve portability of the whole IJG distribution.
Most other applications will directly include the system include files they
want, and hence won't need jinclude.h.)
C source code files:
These files contain most of the functions intended to be called directly by
an application program:
jcapi.c Application program interface routines for compression.
jdapi.c Application program interface routines for decompression.
jcomapi.c Application program interface routines common to compression
and decompression.
jcparam.c Compression parameter setting helper routines.
Compression side of the library:
jcmaster.c Master control: determines which other modules to use.
jcmainct.c Main buffer controller (preprocessor => JPEG compressor).
jcprepct.c Preprocessor buffer controller.
jccoefct.c Buffer controller for DCT coefficient buffer.
jccolor.c Color space conversion.
jcsample.c Downsampling.
jcdctmgr.c DCT manager (DCT implementation selection & control).
jfdctint.c Forward DCT using slow-but-accurate integer method.
jfdctfst.c Forward DCT using faster, less accurate integer method.
jfdctflt.c Forward DCT using floating-point arithmetic.
jchuff.c Huffman entropy coding.
jcmarker.c JPEG marker writing.
jdatadst.c Data destination manager for stdio output.
Decompression side of the library:
jdmaster.c Master control: determines which other modules to use.
jdmainct.c Main buffer controller (JPEG decompressor => postprocessor).
jdcoefct.c Buffer controller for DCT coefficient buffer.
jdpostct.c Postprocessor buffer controller.
jdmarker.c JPEG marker reading.
jdhuff.c Huffman entropy decoding.
jddctmgr.c IDCT manager (IDCT implementation selection & control).
jidctint.c Inverse DCT using slow-but-accurate integer method.
jidctfst.c Inverse DCT using faster, less accurate integer method.
jidctflt.c Inverse DCT using floating-point arithmetic.
jidctred.c Inverse DCTs with reduced-size outputs.
jdsample.c Upsampling.
jdcolor.c Color space conversion.
jdmerge.c Merged upsampling/color conversion (faster, lower quality).
jquant1.c One-pass color quantization using a fixed-spacing colormap.
jquant2.c Two-pass color quantization using a custom-generated colormap.
Also handles one-pass quantization to an externally given map.
jdatasrc.c Data source manager for stdio input.
Support files for both compression and decompression:
jerror.c Standard error handling routines (application replaceable).
jmemmgr.c System-independent (more or less) memory management code.
jutils.c Miscellaneous utility routines.
jmemmgr.c relies on a system-dependent memory management module. The IJG
distribution includes the following implementations of the system-dependent
module:
jmemnobs.c "No backing store": assumes adequate virtual memory exists.
jmemansi.c Makes temporary files with ANSI-standard routine tmpfile().
jmemname.c Makes temporary files with program-generated file names.
jmemdos.c Custom implementation for MS-DOS: knows about extended and
expanded memory as well as temporary files.
Exactly one of the system-dependent modules should be configured into an
installed JPEG library (see install.doc for hints about which one to use).
On unusual systems you may find it worthwhile to make a special
system-dependent memory manager.
Non-C source code files:
jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in
MS-DOS-specific configurations of the JPEG library.
CJPEG/DJPEG
===========
Include files:
cdjpeg.h Declarations shared by cjpeg/djpeg modules.
cderror.h Additional error and trace message codes for cjpeg/djpeg.
C source code files:
cjpeg.c Main program for cjpeg.
djpeg.c Main program for djpeg.
rdcolmap.c Code to read a colormap file for djpeg's "-map" option.
Image file reader modules for cjpeg:
rdbmp.c BMP file input.
rdgif.c GIF file input.
rdppm.c PPM/PGM file input.
rdrle.c Utah RLE file input.
rdtarga.c Targa file input.
Image file writer modules for djpeg:
wrbmp.c BMP file output.
wrgif.c GIF file output.
wrppm.c PPM/PGM file output.
wrrle.c Utah RLE file output.
wrtarga.c Targa file output.
RDJPGCOM/WRJPGCOM
=================
C source code files:
rdjpgcom.c Stand-alone rdjpgcom application.
wrjpgcom.c Stand-alone wrjpgcom application.
These programs do not depend on the IJG library. They do use
jconfig.h and jinclude.h, simply to improve portability.
ADDITIONAL FILES
================
Documentation (see README for a guide to the documentation files):
README Master documentation file.
*.doc Other documentation files.
*.1 Documentation in Unix man page format.
change.log Version-to-version change highlights.
example.c Sample code for calling JPEG library.
Configuration/installation files and programs (see install.doc for more info):
configure Unix shell script to perform automatic configuration.
ckconfig.c Program to generate jconfig.h on non-Unix systems.
jconfig.doc Template for making jconfig.h by hand.
makefile.* Sample makefiles for particular systems.
jconfig.* Sample jconfig.h for particular systems.
ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of
L. Peter Deutsch and Aladdin Enterprises).
Test files (see install.doc for test procedure):
test*.* Source and comparison files for confidence test.
These are binary image files, NOT text files.

745
install.doc Normal file
View File

@@ -0,0 +1,745 @@
INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software
Copyright (C) 1991-1994, 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 explains how to configure and install the IJG software. We have
tried to make this software extremely portable and flexible, so that it can be
adapted to almost any environment. The downside of this decision is that the
installation process is complicated. We have provided shortcuts to simplify
the task on common systems. But in any case, you will need at least a little
familiarity with C programming and program build procedures for your system.
If you are only using this software as part of a larger program, the larger
program's installation procedure may take care of configuring the IJG code.
For example, Ghostscript's installation script will configure the IJG code.
You don't need to read this file if you just want to compile Ghostscript.
If you are on a Unix machine, you may not need to read this file at all.
Try doing
./configure
make
make test
If that doesn't complain, do
make install
(better do "make -n install" first to see if the makefile will put the files
where you want them). Read further if you run into snags or want to customize
the code for your system.
TABLE OF CONTENTS
-----------------
Before you start
Configuring the software:
using the automatic "configure" script
using one of the supplied jconfig and makefile files
by hand
Building the software
Testing the software
Installing the software
Optional stuff
Optimization
Hints for specific systems
BEFORE YOU START
================
Before installing the software you must unpack the distributed source code.
Since you are reading this file, you have probably already succeeded in this
task. However, there is a potential for error if you needed to convert the
files to the local standard text file format (for example, if you are on
MS-DOS you may have converted LF end-of-line to CR/LF). You must apply
such conversion to all the files EXCEPT those whose names begin with "test".
The test files contain binary data; if you change them in any way then the
self-test will give bad results.
Please check the last section of this file to see if there are hints for the
specific machine or compiler you are using.
CONFIGURING THE SOFTWARE
========================
To configure the IJG code for your system, you need to create two files:
* jconfig.h: contains values for system-dependent #define symbols.
* Makefile: controls the compilation process.
(On a non-Unix machine, you may create "project files" or some other
substitute for a Makefile. jconfig.h is needed in any environment.)
We provide three different ways to generate these files:
* On a Unix system, you can just run the "configure" script.
* We provide sample jconfig files and makefiles for popular machines;
if your machine matches one of the samples, just copy the right sample
files to jconfig.h and Makefile.
* If all else fails, read the instructions below and make your own files.
Configuring the software using the automatic "configure" script
---------------------------------------------------------------
If you are on a Unix machine, you can just type
./configure
and let the configure script construct appropriate configuration files.
If you're using "csh" on an old version of System V, you might need to type
sh configure
instead to prevent csh from trying to execute configure itself.
Expect configure to run for a few minutes, particularly on slower machines;
it works by compiling a series of test programs.
Configure was created with GNU Autoconf and it follows the usual conventions
for GNU configure scripts. It makes a few assumptions that you may want to
override. You can do this by providing optional switches to configure:
* Configure will use gcc (GNU C compiler) if it's available, otherwise cc.
To force a particular compiler to be selected, use the CC option, for example
./configure CC='cc'
The same method can be used to include any unusual compiler switches.
For example, on HP-UX you probably want to say
./configure CC='cc -Aa'
to get HP's compiler to run in ANSI mode.
* Configure will set up the makefile so that "make install" will install files
into /usr/local/bin, /usr/local/man, etc. You can specify an installation
prefix other than "/usr/local" by giving configure the option "--prefix=PATH".
* If you don't have a lot of swap space, you may need to enable the IJG
software's internal virtual memory mechanism. To do this, give the option
"--with-maxmem=N" where N is the default maxmemory limit in megabytes.
This is discussed in more detail under "Selecting a memory manager", below.
You probably don't need to worry about this on reasonably-sized Unix machines,
unless you plan to process very large images.
Configure has some other features that are useful if you are cross-compiling
or working in a network of multiple machine types; but if you need those
features, you probably already know how to use them.
Configuring the software using one of the supplied jconfig and makefile files
-----------------------------------------------------------------------------
If you have one of these systems, you can just use the provided configuration
files:
Makefile jconfig file System and/or compiler
makefile.manx jconfig.manx Amiga, Manx Aztec C
makefile.sas jconfig.sas Amiga, SAS C
mak*jpeg.st jconfig.st Atari ST/STE/TT, Pure C or Turbo C
makefile.bcc jconfig.bcc MS-DOS, Borland C (Turbo C)
makefile.dj jconfig.dj MS-DOS, DJGPP (Delorie's port of GNU C)
makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C version 6.x and up
makefile.mms jconfig.vms Digital VMS, with MMS software
makefile.vms jconfig.vms Digital VMS, without MMS software
Copy the proper jconfig file to jconfig.h and the makefile to Makefile
(or whatever your system uses as the standard makefile name). For the
Atari, we provide three project files; see the Atari hints below.
Configuring the software by hand
--------------------------------
First, generate a jconfig.h file. If you are moderately familiar with C,
the comments in jconfig.doc should be enough information to do this; just
copy jconfig.doc to jconfig.h and edit it appropriately. Otherwise, you may
prefer to use the ckconfig.c program. You will need to compile and execute
ckconfig.c by hand --- we hope you know at least enough to do that.
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 ckconfig.c according to the directions given in ckconfig.c. Once
you get it to run, it will write a suitable jconfig.h file, and will also
print out some advice about which makefile to use.
You may also want to look at the canned jconfig files, if there is one for a
system similar to yours.
Second, select a makefile and copy it to Makefile (or whatever your system
uses as the standard makefile name). The most generic makefiles we provide
are
makefile.ansi: if your C compiler supports function prototypes
makefile.unix: if not.
(You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES"
in jconfig.h.) You may want to start from one of the other makefiles if
there is one for a system similar to yours.
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. 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, djpeg, rdjpgcom, and wrjpgcom. See
the file lists in any of the makefiles to find out which files go into each
program. Note that the provided makefiles all make a "library" file libjpeg
first, but you don't have to do that if you don't want to; the file lists
identify which source files are actually needed for compression,
decompression, or both. 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).
Here are comments about some specific configuration decisions you'll
need to make:
Command line style
------------------
cjpeg and djpeg can use a Unix-like command line style which supports
redirection and piping, like this:
cjpeg inputfile >outputfile
cjpeg <inputfile >outputfile
source program | cjpeg >outputfile
The simpler "two file" command line style is just
cjpeg inputfile outputfile
You may prefer the two-file style, particularly if you don't have pipes.
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 some MS-DOS compilers, for
example. If you're not on a Unix system, it's 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 safely use the Unix command line style, by defining USE_FDOPEN or
USE_SETMODE respectively.)
To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE".
Selecting a memory manager
--------------------------
The IJG code is capable of working on images that are too big to fit in main
memory; data is swapped out to temporary files as necessary. However, the
code to do this is rather system-dependent. We provide four different
memory managers:
* jmemansi.c This version 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 creates named temporary files. 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 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 work with.
* jmemdos.c This should be used with most 16-bit MS-DOS compilers.
See the system-specific notes about MS-DOS for more info.
IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in
jconfig.h, and include the assembly file jmemdosa.asm in the
programs. The supplied makefiles and jconfig files for
MS-DOS compilers already do both.
To use a particular memory manager, change the SYSDEPMEM variable in your
makefile to equal the corresponding object file name (for example, jmemansi.o
or jmemansi.obj for jmemansi.c).
If you have plenty of (real or virtual) main memory, just use jmemnobs.c.
"Plenty" means about 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 DEFAULT_MAX_MEM setting to a
reasonable value for your system (either by adding a #define for
DEFAULT_MAX_MEM to jconfig.h, 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 only.
Extended/expanded memory is handled separately by jmemdos.c.)
BUILDING THE SOFTWARE
=====================
Now you should be able to compile the software. Just say "make" (or
whatever's necessary to start the compilation). Have a cup of coffee.
Here are some things that could go wrong:
If your compiler complains about undefined structures, you should be able to
shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h.
If you have trouble with missing system include files or inclusion of the
wrong ones, read jinclude.h. This shouldn't happen if you used configure
or ckconfig.c to set up jconfig.h.
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. There
are also a few configuration checks that may give "unreachable code" warnings.
Any other warning deserves investigation.
If you don't have a getenv() library routine, define NO_GETENV.
Also see the system-specific hints, below.
TESTING THE SOFTWARE
====================
As a quick test of functionality we've included a small sample image in
several forms:
testorig.jpg Starting point for the djpeg tests.
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 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 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 programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you
need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t.
Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h. A less likely
configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE
as long should take care of that one.
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 the
configuration step 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 makefiles all
use the latter style and therefore do not exercise stdin/stdout! If this
check fails, try recompiling cjpeg.c and djpeg.c with USE_SETMODE or
USE_FDOPEN. If it still doesn't work, better use two-file style.
(rdjpgcom.c and wrjpgcom.c will also need to be recompiled.)
If you chose a memory manager 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 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.
INSTALLING THE SOFTWARE
=======================
Once you're done with the above steps, you can install the software by
copying the executable files (cjpeg, djpeg, rdjpgcom, and wrjpgcom) to
wherever you normally install programs. On Unix systems, you'll also want
to put the man pages (cjpeg.1, djpeg.1, rdjpgcom.1, wrjpgcom.1) in the
man-page directory. The canned makefiles don't support this step since
there's such a wide variety of installation procedures on different systems.
If you generated a Makefile with the "configure" script, you can just say
make install
to install the programs and their man pages into the standard places.
(You'll probably need to be root to do this.) We recommend first saying
make -n install
to see where configure thought the files should go. You may need to edit
the Makefile, particularly if your system's conventions for man page
filenames don't match what configure expects.
If you want to install the library file libjpeg.a and the include files j*.h
(for use in compiling other programs besides cjpeg/djpeg), then say
make install-lib
OPTIONAL STUFF
==============
Progress monitor:
If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display
of percent-done progress reports. The routines provided in cjpeg.c/djpeg.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.1 or later, you can enable RLE
support as follows:
1. #define RLE_SUPPORTED in jconfig.h.
2. Add a -I option to CFLAGS in the Makefile for the directory
containing the URT .h files (typically the "include"
subdirectory of the URT distribution).
3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
the directory containing the URT "librle.a" file (typically the
"lib" subdirectory of the URT distribution).
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
jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in
decoder support for all valid JPEG files, to ensure that you can read anyone's
output. Taking out support for image file formats that you don't use is the
most painless way to make the programs smaller. Another possibility is to
remove some of the DCT methods: in particular, the "IFAST" method may not be
enough faster than the others to be worth keeping on your machine. (If you
do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST
to a supported method, by adding a #define in jconfig.h.)
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.
Repeat the self-test after any optimization to make sure that you haven't
broken anything.
The integer 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 MULTIPLYxxx macro definitions in
jdct.h. 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), 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 jconfig files
already contain #define switches to select appropriate MULTIPLYxxx
definitions.)
If your machine has sufficiently fast floating point hardware, you may find
that the float DCT method is faster than the integer DCT methods, even
after tweaking the integer multiply macros. In that case you may want to
make the float DCT be the default method. (The only objection to this is
that float DCT results may vary slightly across machines.) To do that, add
"#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h. Even if you don't change
the default, you should redefine JDCT_FASTEST, which is the method selected
by djpeg's -fast switch. Don't forget to update the documentation files
(usage.doc and/or cjpeg.1, djpeg.1) to agree with what you've done.
If access to "short" arrays is slow on your machine, it may be a win to
define type JCOEF as int rather than short. This will cost a good deal of
memory though, particularly in some multi-pass modes, so don't do it unless
you have memory to burn and short is REALLY slow.
If your compiler can compile function calls in-line, make sure the INLINE
macro in jmorecfg.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.
HINTS FOR SPECIFIC SYSTEMS
==========================
We welcome reports on changes needed for systems not mentioned here. Submit
'em to jpeg-info@uunet.uu.net. Also, if configure or ckconfig.c is wrong
about how to configure the JPEG software for your system, please let us know.
Acorn RISC OS:
(Thanks to Simon Middleton for these hints on compiling with Desktop C.)
After renaming the files according to Acorn conventions, take a copy of
makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and
change these definitions as indicated:
CFLAGS= -throwback -IC: -Wn
LDLIBS=C:o.Stubs
SYSDEPMEM=jmemansi.o
LN=Link
AR=LibFile -c -o
Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'. Remove the
lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h'
dependency section.
Copy jconfig.doc to jconfig.h. Edit jconfig.h to define TWO_FILE_COMMANDLINE
and CHAR_IS_UNSIGNED.
Run the makefile using !AMU not !Make. If you want to use the 'clean' and
'test' makefile entries then you will have to fiddle with the syntax a bit
and rename the test files.
Amiga:
SAS C 6.50 reportedly is too buggy to compile the IJG code properly.
A patch to update to 6.51 is available from SAS or AmiNet FTP sites.
Atari ST/STE/TT:
Copy the project files makcjpeg.st, makdjpeg.st, and makljpeg.st to cjpeg.prj,
djpeg.prj, and libjpeg.prj respectively. The project files should work as-is
with Pure C. For Turbo C, change library filenames "PC..." to "TC..." in
cjpeg.prj and djpeg.prj. Note that libjpeg.prj selects jmemansi.c as the
recommended memory manager. You'll probably want to adjust the
DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K less than
your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into jconfig.h
to do this.
To use the 68881/68882 coprocessor for the floating point DCT, add the
compiler option "-8" to the project files and replace PCFLTLIB.LIB with
PC881LIB.LIB in cjpeg.prj and djpeg.prj. Or if you don't have a
coprocessor, you may prefer to remove the float DCT code by undefining
DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float
code will be too slow to be useful). In that case, you can delete
PCFLTLIB.LIB from the project files.
Note that you must make libjpeg.lib before making cjpeg.ttp or djpeg.ttp.
You'll have to perform the self-test by hand.
We haven't bothered to include project files for rdjpgcom and wrjpgcom.
Those source files should just be compiled by themselves; they don't
depend on the JPEG library.
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 old versions of Cray's Standard C (prior to 3.1). If you
still have an old compiler, 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 V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c).
[This bug may or may not still occur with the current IJG code, but it's
probably a dead issue anyway...]
HP-UX:
If you have HP-UX 7.05 or later with the "software development" C compiler,
you should run the compiler in ANSI mode. If using the configure script,
say
./configure CC='cc -Aa'
(or -Ae if you prefer). If configuring by hand, use makefile.ansi and 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 system, then you must use makefile.unix
(and do NOT add -Aa); or just run configure without the CC option.
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
use makefile.unix, or run configure without the CC option.
Macintosh, MPW:
We don't directly support MPW in the current release, but Larry Rosenstein
ported an earlier version of the IJG code 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, files /pub/lsr/pbmplus-port*.
Macintosh, Metrowerks CodeWarrior:
Metrowerks release DR2 has problems with the IJG code; don't use it. Release
DR3.5 or later should be OK.
The command-line-style interface can be used by defining USE_CCOMMAND and
TWO_FILE_COMMANDLINE (see next entry for more details).
On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended
float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power
of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
Macintosh, Think C:
The supplied user-interface files (cjpeg.c and djpeg.c) are set up to provide
a Unix-style command line interface. You can use this interface on the Mac
by means of Think's ccommand() library routine. However, a much better
Mac-style user interface has been prepared by Jim Brunner. You can obtain
the additional source code needed for that user interface by FTP to
sumex-aim.stanford.edu, file /info-mac/dev/src/jpeg-convert-c.hqx. Jim's
documentation also includes more detailed build instructions for Think C.
(Jim is working on updating this code to work with v5 of the IJG library,
but it wasn't ready as of v5 release time. Should be out before too long.)
If you want to build the minimal command line version, proceed as follows.
You'll have to prepare project files for the programs; we don't include any
in the distribution since they are not text files. Use the file lists in
any of the supplied makefiles as a guide. 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; we recommend dividing compression and decompression
modules. Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is
called. You must also define TWO_FILE_COMMANDLINE because stdin/stdout
don't handle binary data correctly.
On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float.
jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2.
Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
MIPS R3000:
MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O
if you have that compiler version. (Use "cc -V" to check the version.)
Note that the R3000 chip is found in workstations from DEC and others.
MS-DOS, generic comments for 16-bit compilers:
The IJG code is designed to be compiled in 80x86 "small" or "medium" memory
models (i.e., data pointers are 16 bits unless explicitly declared "far";
code pointers can be either size). You may be able to use small model to
compile cjpeg or djpeg by itself, but you will probably have to use medium
model for any larger application. This won't make much difference in
performance. You *will* take a noticeable performance hit if you use a
large-data memory model, and you should avoid "huge" model if at all
possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use
a small-data memory model; be sure it is NOT defined if you use a large-data
model. (The supplied makefiles and jconfig files for Borland and Microsoft C
compile in medium model and define NEED_FAR_POINTERS.)
The DOS-specific memory manager, jmemdos.c, should be used if possible.
It needs some assembly-code routines which are in jmemdosa.asm; make sure
your makefile assembles that file and includes it in the library. If you
don't have a suitable assembler, you can get pre-assembled object files for
jmemdosa by FTP from ftp.uu.net: graphics/jpeg/jdosaobj.zip.
When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set
MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If your
C library's far-heap malloc() can't allocate blocks that large, reduce
MAX_ALLOC_CHUNK to whatever it can handle.
If you can't use jmemdos.c for some reason --- for example, because you
don't have an assembler to assemble jmemdosa.asm --- you'll have to fall
back to jmemansi.c or jmemname.c. You'll probably still need to set
MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc()
more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c,
you will have to compile in a large-data memory model in order to get the
right stdio library. Too bad.
wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB
work area to hold the comment text. If your C library's malloc can't
handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.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_SETMODE or USE_FDOPEN 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 supplied
makefiles do NOT use stdin/stdout.
MS-DOS, generic comments for 32-bit compilers:
None of the above comments about memory models apply if you are using a
32-bit 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.
You'll still need to be careful about binary I/O through stdin/stdout.
See the last paragraph of the previous section.
MS-DOS, Borland C:
If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
jconfig.bcc includes #define USE_SETMODE. (fdopen does not work correctly.)
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.
MS-DOS, DJGPP:
Use a recent version of DJGPP (1.11 or better). If you prefer two-file
command line style, change the supplied jconfig.dj to define
TWO_FILE_COMMANDLINE. makefile.dj is set up to generate only COFF files
(cjpeg, djpeg, etc) when you say make. After testing, say "make exe" to
make executables with stub.exe, or "make standalone" if you want executables
that include go32. You will probably need to tweak the makefile's pointer to
go32.exe to do "make standalone".
MS-DOS, Microsoft C:
If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
jconfig.mc6 includes #define USE_SETMODE. (fdopen does not work correctly.)
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 jerror.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 -debug -debug, but at least you can compile.
Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn
off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it
still generates bad code if you enable loop optimizations (-Ol or -Ox).
MS C 8.0 reportedly fails to compile jquant1.c if optimization is turned off
(yes, off).
SGI:
Set "AR2= ar -ts" rather than "AR2= ranlib" in the Makefile. If you are
using configure, you should say
./configure RANLIB='ar -ts'
VMS:
On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1"
qualifier with MMS when building the JPEG package.
VAX/VMS v5.5-1 may have problems with the test step of the build procedure
reporting differences when it compares the original and test GIF and JPG
images. If the error points to the last block of the files, it is most
likely bogus and may be safely ignored. It seems to be because the files
are Stream_LF and Backup/Compare has difficulty with the (presumably) null
padded files. This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1.

View File

@@ -1,118 +0,0 @@
/*
* jbsmooth.c
*
* 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 cross-block smoothing routines.
* These routines are invoked via the smooth_coefficients method.
*/
#include "jinclude.h"
#ifdef BLOCK_SMOOTHING_SUPPORTED
/*
* Cross-block coefficient smoothing.
*/
METHODDEF void
smooth_coefficients (decompress_info_ptr cinfo,
jpeg_component_info *compptr,
JBLOCKROW above,
JBLOCKROW currow,
JBLOCKROW below,
JBLOCKROW output)
{
QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
long blocks_in_row = compptr->subsampled_width / DCTSIZE;
long col;
/* First, copy the block row as-is.
* This takes care of the first & last blocks in the row, the top/bottom
* special cases, and the higher-order coefficients in each block.
*/
jcopy_block_row(currow, output, blocks_in_row);
/* Now apply the smoothing calculation, but not to any blocks on the
* edges of the image.
*/
if (above != NULL && below != NULL) {
for (col = 1; col < blocks_in_row-1; col++) {
/* See section K.8 of the JPEG standard.
*
* As I understand it, this produces approximations
* for the low frequency AC components, based on the
* DC values of the block and its eight neighboring blocks.
* (Thus it can't be used for blocks on the image edges.)
*/
/* The layout of these variables corresponds to text and figure in K.8 */
JCOEF DC1, DC2, DC3;
JCOEF DC4, DC5, DC6;
JCOEF DC7, DC8, DC9;
long AC01, AC02;
long AC10, AC11;
long AC20;
DC1 = above [col-1][0];
DC2 = above [col ][0];
DC3 = above [col+1][0];
DC4 = currow[col-1][0];
DC5 = currow[col ][0];
DC6 = currow[col+1][0];
DC7 = below [col-1][0];
DC8 = below [col ][0];
DC9 = below [col+1][0];
#define DIVIDE_256(x) x = ( (x) < 0 ? -((128-(x))/256) : ((x)+128)/256 )
AC01 = (36 * (DC4 - DC6));
DIVIDE_256(AC01);
AC10 = (36 * (DC2 - DC8));
DIVIDE_256(AC10);
AC20 = (9 * (DC2 + DC8 - 2*DC5));
DIVIDE_256(AC20);
AC11 = (5 * ((DC1 - DC3) - (DC7 - DC9)));
DIVIDE_256(AC11);
AC02 = (9 * (DC4 + DC6 - 2*DC5));
DIVIDE_256(AC02);
/* I think that this checks to see if the quantisation
* on the transmitting side would have produced this
* answer. If so, then we use our (hopefully better)
* estimate.
*/
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define COND_ASSIGN(_ac,_n,_z) if ((ABS(output[col][_n] - (_ac))<<1) <= Qptr[_z]) output[col][_n] = (JCOEF) (_ac)
COND_ASSIGN(AC01, 1, 1);
COND_ASSIGN(AC02, 2, 5);
COND_ASSIGN(AC10, 8, 2);
COND_ASSIGN(AC11, 9, 4);
COND_ASSIGN(AC20, 16, 3);
}
}
}
/*
* The method selection routine for cross-block smoothing.
*/
GLOBAL void
jselbsmooth (decompress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->smooth_coefficients = smooth_coefficients;
}
#endif /* BLOCK_SMOOTHING_SUPPORTED */

369
jcapi.c Normal file
View File

@@ -0,0 +1,369 @@
/*
* jcapi.c
*
* Copyright (C) 1994, 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 application interface code for the compression half of
* the JPEG library. Most of the routines intended to be called directly by
* an application are in this file. But also see jcparam.c for
* parameter-setup helper routines, and jcomapi.c for routines shared by
* compression and decompression.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Initialization of a JPEG compression object.
* The error manager must already be set up (in case memory manager fails).
*/
GLOBAL void
jpeg_create_compress (j_compress_ptr cinfo)
{
int i;
/* For debugging purposes, zero the whole master structure.
* But error manager pointer is already there, so save and restore it.
*/
{
struct jpeg_error_mgr * err = cinfo->err;
MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
cinfo->err = err;
}
cinfo->is_decompressor = FALSE;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr((j_common_ptr) cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
cinfo->dest = NULL;
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->input_gamma = 1.0; /* in case application forgets */
/* OK, I'm ready */
cinfo->global_state = CSTATE_START;
}
/*
* Destruction of a JPEG compression object
*/
GLOBAL void
jpeg_destroy_compress (j_compress_ptr cinfo)
{
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
}
/*
* Forcibly suppress or un-suppress all quantization and Huffman tables.
* Marks all currently defined tables as already written (if suppress)
* or not written (if !suppress). This will control whether they get emitted
* by a subsequent jpeg_start_compress call.
*
* This routine is exported for use by applications that want to produce
* abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
* since it is called by jpeg_start_compress, we put it here --- otherwise
* jcparam.o would be linked whether the application used it or not.
*/
GLOBAL void
jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
{
int i;
JQUANT_TBL * qtbl;
JHUFF_TBL * htbl;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
qtbl->sent_table = suppress;
}
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
htbl->sent_table = suppress;
if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
htbl->sent_table = suppress;
}
}
/*
* Compression initialization.
* Before calling this, all parameters and a data destination must be set up.
*
* We require a write_all_tables parameter as a failsafe check when writing
* multiple datastreams from the same compression object. Since prior runs
* will have left all the tables marked sent_table=TRUE, a subsequent run
* would emit an abbreviated stream (no tables) by default. This may be what
* is wanted, but for safety's sake it should not be the default behavior:
* programmers should have to make a deliberate choice to emit abbreviated
* images. Therefore the documentation and examples should encourage people
* to pass write_all_tables=TRUE; then it will take active thought to do the
* wrong thing.
*/
GLOBAL void
jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (write_all_tables)
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
jinit_master_compress(cinfo);
/* Set up for the first pass */
(*cinfo->master->prepare_for_pass) (cinfo);
/* Ready for application to drive first pass through jpeg_write_scanlines
* or jpeg_write_raw_data.
*/
cinfo->next_scanline = 0;
cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
}
/*
* Write some scanlines of data to the JPEG compressor.
*
* The return value will be the number of lines actually written.
* This should be less than the supplied num_lines only in case that
* the data destination module has requested suspension of the compressor,
* or if more than image_height scanlines are passed in.
*
* Note: we warn about excess calls to jpeg_write_scanlines() since
* this likely signals an application programmer error. However,
* excess scanlines passed in the last valid call are *silently* ignored,
* so that the application need not adjust num_lines for end-of-image
* when using a multiple-scanline buffer.
*/
GLOBAL JDIMENSION
jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
JDIMENSION num_lines)
{
JDIMENSION row_ctr, rows_left;
if (cinfo->global_state != CSTATE_SCANNING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline >= cinfo->image_height)
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
cinfo->progress->pass_limit = (long) cinfo->image_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Give master control module another chance if this is first call to
* jpeg_write_scanlines. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_scanlines.
*/
if (cinfo->master->call_pass_startup)
(*cinfo->master->pass_startup) (cinfo);
/* Ignore any extra scanlines at bottom of image. */
rows_left = cinfo->image_height - cinfo->next_scanline;
if (num_lines > rows_left)
num_lines = rows_left;
row_ctr = 0;
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
cinfo->next_scanline += row_ctr;
return row_ctr;
}
/*
* Alternate entry point to write raw data.
* Processes exactly one iMCU row per call.
*/
GLOBAL JDIMENSION
jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION num_lines)
{
JDIMENSION mcu_ctr, lines_per_MCU_row;
if (cinfo->global_state != CSTATE_RAW_OK)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline >= cinfo->image_height) {
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
cinfo->progress->pass_limit = (long) cinfo->image_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Give master control module another chance if this is first call to
* jpeg_write_raw_data. This lets output of the frame/scan headers be
* delayed so that application can write COM, etc, markers between
* jpeg_start_compress and jpeg_write_raw_data.
*/
if (cinfo->master->call_pass_startup)
(*cinfo->master->pass_startup) (cinfo);
/* Verify that at least one iMCU row has been passed. */
lines_per_MCU_row = cinfo->max_v_samp_factor * DCTSIZE;
if (num_lines < lines_per_MCU_row)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Directly compress the row. */
mcu_ctr = 0;
(*cinfo->coef->compress_data) (cinfo, data, &mcu_ctr);
/* If compressor did not consume the whole row, then we must need to
* suspend processing; this is not currently supported.
*/
if (mcu_ctr != cinfo->MCUs_per_row)
ERREXIT(cinfo, JERR_CANT_SUSPEND);
/* OK, we processed one iMCU row. */
cinfo->next_scanline += lines_per_MCU_row;
return lines_per_MCU_row;
}
/*
* Finish JPEG compression.
*
* If a multipass operating mode was selected, this may do a great deal of
* work including most of the actual output.
*/
GLOBAL void
jpeg_finish_compress (j_compress_ptr cinfo)
{
JDIMENSION iMCU_row, mcu_ctr;
if (cinfo->global_state != CSTATE_SCANNING &&
cinfo->global_state != CSTATE_RAW_OK)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->next_scanline < cinfo->image_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
/* Terminate first pass */
(*cinfo->master->finish_pass) (cinfo);
/* Perform any remaining passes */
while (! cinfo->master->is_last_pass) {
(*cinfo->master->prepare_for_pass) (cinfo);
for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) iMCU_row;
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer.
*/
mcu_ctr = 0;
(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL, &mcu_ctr);
if (mcu_ctr != cinfo->MCUs_per_row)
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
(*cinfo->master->finish_pass) (cinfo);
}
/* Write EOI, do final cleanup */
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort((j_common_ptr) cinfo);
}
/*
* Write a special marker.
* This is only recommended for writing COM or APPn markers.
* Must be called after jpeg_start_compress() and before
* first call to jpeg_write_scanlines() or jpeg_write_raw_data().
*/
GLOBAL void
jpeg_write_marker (j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen)
{
if (cinfo->next_scanline != 0 ||
(cinfo->global_state != CSTATE_SCANNING &&
cinfo->global_state != CSTATE_RAW_OK))
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
(*cinfo->marker->write_any_marker) (cinfo, marker, dataptr, datalen);
}
/*
* Alternate compression function: just write an abbreviated table file.
* Before calling this, all parameters and a data destination must be set up.
*
* To produce a pair of files containing abbreviated tables and abbreviated
* image data, one would proceed as follows:
*
* initialize JPEG object
* set JPEG parameters
* set destination to table file
* jpeg_write_tables(cinfo);
* set destination to image file
* jpeg_start_compress(cinfo, FALSE);
* write data...
* jpeg_finish_compress(cinfo);
*
* jpeg_write_tables has the side effect of marking all tables written
* (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
* will not re-emit the tables unless it is passed write_all_tables=TRUE.
*/
GLOBAL void
jpeg_write_tables (j_compress_ptr cinfo)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Initialize the marker writer ... bit of a crock to do it here. */
jinit_marker_writer(cinfo);
/* Write them tables! */
(*cinfo->marker->write_tables_only) (cinfo);
/* And clean up. */
(*cinfo->dest->term_destination) (cinfo);
/* We can use jpeg_abort to release memory ... is this necessary? */
jpeg_abort((j_common_ptr) cinfo);
}
/*
* Abort processing of a JPEG compression operation,
* but don't destroy the object itself.
*/
GLOBAL void
jpeg_abort_compress (j_compress_ptr cinfo)
{
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
}

View File

@@ -1,42 +0,0 @@
/*
* jcarith.c
*
* 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.
*/
#include "jinclude.h"
#ifdef ARITH_CODING_SUPPORTED
/*
* The arithmetic coding option of the JPEG standard specifies Q-coding,
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
* At this time it does not appear to be legal for the Independent JPEG
* Group to distribute software that implements arithmetic coding.
* We have therefore removed arithmetic coding support from the
* distributed source code.
*
* We're not happy about it either.
*/
/*
* The method selection routine for arithmetic entropy encoding.
*/
GLOBAL void
jselcarithmetic (compress_info_ptr cinfo)
{
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
}
}
#endif /* ARITH_CODING_SUPPORTED */

414
jccoefct.c Normal file
View File

@@ -0,0 +1,414 @@
/*
* jccoefct.c
*
* Copyright (C) 1994, 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 coefficient buffer controller for compression.
* This controller is the top level of the JPEG compressor proper.
* The coefficient buffer lies between forward-DCT and entropy encoding steps.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* We use a full-image coefficient buffer when doing Huffman optimization,
* and also for writing multiple-scan JPEG files. In all cases, the DCT
* step is run during the first pass, and subsequent passes need only read
* the buffered coefficients.
*/
#ifdef ENTROPY_OPT_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#else
#ifdef C_MULTISCAN_FILES_SUPPORTED
#define FULL_COEF_BUFFER_SUPPORTED
#endif
#endif
/* Private buffer controller object */
typedef struct {
struct jpeg_c_coef_controller pub; /* public fields */
JDIMENSION MCU_row_num; /* keep track of MCU row # within image */
/* For single-pass compression, it's sufficient to buffer just one MCU
* (although this may prove a bit slow in practice). We allocate a
* workspace of MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
* MCU constructed and sent. (On 80x86, the workspace is FAR even though
* it's not really very big; this is to keep the module interfaces unchanged
* when a large coefficient buffer is necessary.)
* In multi-pass modes, this array points to the current MCU's blocks
* within the virtual arrays.
*/
JBLOCKROW MCU_buffer[MAX_BLOCKS_IN_MCU];
/* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
} my_coef_controller;
typedef my_coef_controller * my_coef_ptr;
/* Forward declarations */
METHODDEF void compress_data
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr));
#ifdef FULL_COEF_BUFFER_SUPPORTED
METHODDEF void compress_first_pass
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr));
METHODDEF void compress_output
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
coef->MCU_row_num = 0;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (coef->whole_image[0] != NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_data;
break;
#ifdef FULL_COEF_BUFFER_SUPPORTED
case JBUF_SAVE_AND_PASS:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_first_pass;
break;
case JBUF_CRANK_DEST:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_output;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data in the single-pass case.
* Up to one MCU row is processed (less if suspension is forced).
*
* NB: input_buf contains a plane for each component in image.
* For single pass, this is the same as the components in the scan.
*/
METHODDEF void
compress_data (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_MCU_row = cinfo->MCU_rows_in_scan - 1;
int blkn, bi, ci, yindex, blockcnt;
JDIMENSION ypos, xpos;
jpeg_component_info *compptr;
/* Loop to write as much as one whole MCU row */
for (MCU_col_num = *in_mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) {
/* Determine where data comes from in input_buf and do the DCT thing.
* Each call on forward_DCT processes a horizontal row of DCT blocks
* as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
* sequentially. Dummy blocks at the right or bottom edge are filled in
* specially. The data in them does not matter for image reconstruction,
* so we fill them with values that will encode to the smallest amount of
* data, viz: all zeroes in the AC entries, DC entries equal to previous
* block's DC value. (Thanks to Thomas Kinsman for this idea.)
*/
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
: compptr->last_col_width;
xpos = MCU_col_num * compptr->MCU_sample_width;
ypos = 0;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->MCU_row_num < last_MCU_row ||
yindex < compptr->last_row_height) {
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], coef->MCU_buffer[blkn],
ypos, xpos, (JDIMENSION) blockcnt);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
}
}
} else {
/* Create a whole row of dummy blocks at the bottom of the image. */
jzero_far((void FAR *) coef->MCU_buffer[blkn],
compptr->MCU_width * SIZEOF(JBLOCK));
for (bi = 0; bi < compptr->MCU_width; bi++) {
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
}
}
blkn += compptr->MCU_width;
ypos += DCTSIZE;
}
}
/* Try to write the MCU. In event of a suspension failure, we will
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
*/
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer))
break; /* suspension forced; exit loop */
}
if (MCU_col_num > last_MCU_col)
coef->MCU_row_num++; /* advance if we finished the row */
*in_mcu_ctr = MCU_col_num;
}
#ifdef FULL_COEF_BUFFER_SUPPORTED
/*
* Process some data in the first pass of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* This amount of data is read from the source buffer, DCT'd and quantized,
* and saved into the virtual arrays. We also generate suitable dummy blocks
* as needed at the right and lower edges. (The dummy blocks are constructed
* in the virtual arrays, which have been padded appropriately.) This makes
* it possible for subsequent passes not to worry about real vs. dummy blocks.
*
* We must also emit the data to the entropy encoder. This is conveniently
* done by calling compress_output() after we've loaded the current strip
* of the virtual arrays.
*
* NB: input_buf contains a plane for each component in image. All
* components are DCT'd and loaded into the virtual arrays in this pass.
* However, it may be that only a subset of the components are emitted to
* the entropy encoder during this first pass; be careful about looking
* at the scan-dependent variables (MCU dimensions, etc).
*/
METHODDEF void
compress_first_pass (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_MCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION blocks_across, MCUs_across, MCUindex;
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
JCOEF lastDC;
jpeg_component_info *compptr;
JBLOCKARRAY buffer;
JBLOCKROW thisblockrow, lastblockrow;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
coef->MCU_row_num * compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->MCU_row_num < last_MCU_row)
block_rows = compptr->v_samp_factor;
else {
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
blocks_across = compptr->width_in_blocks;
h_samp_factor = compptr->h_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
ndummy = (int) (blocks_across % h_samp_factor);
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks.
*/
for (block_row = 0; block_row < block_rows; block_row++) {
thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
(JDIMENSION) (block_row * DCTSIZE),
(JDIMENSION) 0, blocks_across);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
lastDC = thisblockrow[-1][0];
for (bi = 0; bi < ndummy; bi++) {
thisblockrow[bi][0] = lastDC;
}
}
}
/* If at end of image, create dummy block rows as needed.
* The tricky part here is that within each MCU, we want the DC values
* of the dummy blocks to match the last real block's DC value.
* This squeezes a few more bytes out of the resulting file...
*/
if (coef->MCU_row_num == last_MCU_row) {
blocks_across += ndummy; /* include lower right corner */
MCUs_across = blocks_across / h_samp_factor;
for (block_row = block_rows; block_row < compptr->v_samp_factor;
block_row++) {
thisblockrow = buffer[block_row];
lastblockrow = buffer[block_row-1];
jzero_far((void FAR *) thisblockrow,
(size_t) (blocks_across * SIZEOF(JBLOCK)));
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
lastDC = lastblockrow[h_samp_factor-1][0];
for (bi = 0; bi < h_samp_factor; bi++) {
thisblockrow[bi][0] = lastDC;
}
thisblockrow += h_samp_factor; /* advance to next MCU in row */
lastblockrow += h_samp_factor;
}
}
}
}
/* NB: compress_output will increment MCU_row_num */
/* Emit data to the entropy encoder, sharing code with subsequent passes */
compress_output(cinfo, input_buf, in_mcu_ctr);
}
/*
* Process some data in subsequent passes of a multi-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the scan.
* The data is obtained from the virtual arrays and fed to the entropy coder.
*
* Note that output suspension is not supported during multi-pass operation,
* so the complete MCU row will always be emitted to the entropy encoder
* before returning.
*
* NB: input_buf is ignored; it is likely to be a NULL pointer.
*/
METHODDEF void
compress_output (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset, num_MCU_rows;
JDIMENSION remaining_rows, start_col;
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
JBLOCKROW buffer_ptr;
jpeg_component_info *compptr;
/* Align the virtual buffers for the components used in this scan.
* NB: during first pass, this is safe only because the buffers will
* already be aligned properly, so jmemmgr.c won't need to do any I/O.
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
coef->MCU_row_num * compptr->v_samp_factor, FALSE);
}
/* In an interleaved scan, we process exactly one MCU row.
* In a noninterleaved scan, we need to process v_samp_factor MCU rows,
* each of which contains a single block row.
*/
if (cinfo->comps_in_scan == 1) {
compptr = cinfo->cur_comp_info[0];
num_MCU_rows = compptr->v_samp_factor;
/* but watch out for the bottom of the image */
remaining_rows = cinfo->MCU_rows_in_scan -
coef->MCU_row_num * compptr->v_samp_factor;
if (remaining_rows < (JDIMENSION) num_MCU_rows)
num_MCU_rows = (int) remaining_rows;
} else {
num_MCU_rows = 1;
}
/* Loop to process one whole iMCU row */
for (yoffset = 0; yoffset < num_MCU_rows; yoffset++) {
for (MCU_col_num = 0; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) {
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to write the MCU. */
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
ERREXIT(cinfo, JERR_CANT_SUSPEND); /* not supported */
}
}
}
coef->MCU_row_num++; /* advance to next iMCU row */
*in_mcu_ctr = cinfo->MCUs_per_row;
}
#endif /* FULL_COEF_BUFFER_SUPPORTED */
/*
* Initialize coefficient buffer controller.
*/
GLOBAL void
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
int ci, i;
jpeg_component_info *compptr;
JBLOCKROW buffer;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_coef_controller));
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
coef->pub.start_pass = start_pass_coef;
/* Create the coefficient buffer. */
if (need_full_buffer) {
#ifdef FULL_COEF_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
/* Note memmgr implicitly pads the vertical direction. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
(long) compptr->h_samp_factor),
compptr->height_in_blocks,
(JDIMENSION) compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
} else {
/* We only need a single-MCU buffer. */
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
for (i = 0; i < MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
}
coef->whole_image[0] = NULL; /* flag for no virtual arrays */
}
}

464
jccolor.c
View File

@@ -1,237 +1,449 @@
/*
* jccolor.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains input colorspace conversion routines.
* These routines are invoked via the methods get_sample_rows
* and colorin_init/term.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
/* Private subobject */
typedef struct {
struct jpeg_color_converter pub; /* public fields */
/* Private state for RGB->YCC conversion */
INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
} my_color_converter;
typedef my_color_converter * my_cconvert_ptr;
/**************** RGB -> YCbCr conversion: most common case **************/
/*
* Initialize for colorspace conversion.
*/
METHODDEF void
colorin_init (compress_info_ptr cinfo)
{
/* Allocate a workspace for the result of get_input_row. */
pixel_row = (*cinfo->emethods->alloc_small_sarray)
(cinfo->image_width, (long) cinfo->input_components);
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
*/
/*
* This version handles RGB -> YCbCr conversion.
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
* 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
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B
* where Cb and Cr must be incremented by MAXJSAMPLE/2 to create a
* nonnegative output value.
* (These numbers are derived from TIFF Appendix O, draft of 4/10/91.)
* 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^14 (about 4 digits precision); we have to divide
* the products by 2^14, with appropriate rounding, to get the correct answer.
* 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 could avoid any multiplications in the inner loop
* 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.
* This is not currently implemented.
* 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.
*/
#define SCALEBITS 14
#define SCALEBITS 16 /* speediest right-shift on some machines */
#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).
*/
#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 RGB->YCC colorspace conversion.
*/
METHODDEF void
get_rgb_ycc_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
rgb_ycc_start (j_compress_ptr cinfo)
{
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;
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
INT32 * rgb_ycc_tab;
INT32 i;
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++);
/* Allocate and fill in the conversion tables. */
cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(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;
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
*
* Note that we change from the application's interleaved-pixel format
* to our internal noninterleaved, one-plane-per-component format.
* The input buffer is therefore three times as wide as the output buffer.
*
* A starting row offset is provided only for the output buffer. The caller
* can easily adjust the passed input_buf value to accommodate any row
* offset required on that side.
*/
METHODDEF void
rgb_ycc_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int r, g, b;
register INT32 * ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]);
g = GETJSAMPLE(inptr[RGB_GREEN]);
b = GETJSAMPLE(inptr[RGB_BLUE]);
inptr += RGB_PIXELSIZE;
/* 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++ = (JSAMPLE)
(( FIX(0.29900)*r + FIX(0.58700)*g + FIX(0.11400)*b
+ ONE_HALF) >> SCALEBITS);
outptr0[col] = (JSAMPLE)
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
>> SCALEBITS);
/* Cb */
*outptr1++ = (JSAMPLE)
(((-FIX(0.16874))*r - FIX(0.33126)*g + FIX(0.50000)*b
+ ONE_HALF*(MAXJSAMPLE+1)) >> SCALEBITS);
outptr1[col] = (JSAMPLE)
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
>> SCALEBITS);
/* Cr */
*outptr2++ = (JSAMPLE)
(( FIX(0.50000)*r - FIX(0.41869)*g - FIX(0.08131)*b
+ ONE_HALF*(MAXJSAMPLE+1)) >> SCALEBITS);
outptr2[col] = (JSAMPLE)
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
>> SCALEBITS);
}
}
}
/**************** Cases other than RGB -> YCbCr **************/
/*
* Convert some rows of samples 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_start has been called (we only use the Y tables).
*/
METHODDEF void
rgb_gray_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int r, g, b;
register INT32 * ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr = output_buf[0][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]);
g = GETJSAMPLE(inptr[RGB_GREEN]);
b = GETJSAMPLE(inptr[RGB_BLUE]);
inptr += RGB_PIXELSIZE;
/* Y */
outptr[col] = (JSAMPLE)
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
>> SCALEBITS);
}
}
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* This version handles grayscale (no conversion).
* Convert some rows of samples to the JPEG colorspace.
* This version handles Adobe-style CMYK->YCCK conversion,
* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
* conversion as above, while passing K (black) unchanged.
* We assume rgb_ycc_start has been called.
*/
METHODDEF void
get_grayscale_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
cmyk_ycck_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
int row;
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int r, g, b;
register INT32 * ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2, outptr3;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace (gamma mapping needed here) */
jcopy_sample_rows(pixel_row, 0, image_data[0], row,
1, cinfo->image_width);
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
outptr3 = output_buf[3][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
/* K passes through as-is */
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
inptr += 4;
/* 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);
}
}
}
/*
* Fetch some rows of pixels from get_input_row and convert to the
* JPEG colorspace.
* Convert some rows of samples to the JPEG colorspace.
* This version handles grayscale output with no conversion.
* The source can be either plain grayscale or YCbCr (since Y == gray).
*/
METHODDEF void
grayscale_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->image_width;
int instride = cinfo->input_components;
while (--num_rows >= 0) {
inptr = *input_buf++;
outptr = output_buf[0][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
inptr += instride;
}
}
}
/*
* Convert some rows of samples to the JPEG colorspace.
* This version handles multi-component colorspaces without conversion.
* We assume input_components == num_components.
*/
METHODDEF void
get_noconvert_rows (compress_info_ptr cinfo,
int rows_to_read, JSAMPIMAGE image_data)
null_convert (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows)
{
int row, ci;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
register int ci;
int nc = cinfo->num_components;
JDIMENSION num_cols = cinfo->image_width;
for (row = 0; row < rows_to_read; row++) {
/* Read one row from the source file */
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
/* Convert colorspace (gamma mapping needed here) */
for (ci = 0; ci < cinfo->input_components; ci++) {
jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
1, cinfo->image_width);
while (--num_rows >= 0) {
/* It seems fastest to make a separate pass for each component. */
for (ci = 0; ci < nc; ci++) {
inptr = *input_buf;
outptr = output_buf[ci][output_row];
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
inptr += nc;
}
}
input_buf++;
output_row++;
}
}
/*
* Finish up at the end of the file.
* Empty method for start_pass.
*/
METHODDEF void
colorin_term (compress_info_ptr cinfo)
null_method (j_compress_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
/* no work needed */
}
/*
* The method selection routine for input colorspace conversion.
* Module initialization routine for input colorspace conversion.
*/
GLOBAL void
jselccolor (compress_info_ptr cinfo)
jinit_color_converter (j_compress_ptr cinfo)
{
my_cconvert_ptr cconvert;
cconvert = (my_cconvert_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_color_converter));
cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
/* set start_pass to null method until we find out differently */
cconvert->pub.start_pass = null_method;
/* Make sure input_components agrees with in_color_space */
switch (cinfo->in_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->input_components != 1)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case CS_RGB:
case CS_YCbCr:
case CS_YIQ:
case JCS_RGB:
#if RGB_PIXELSIZE != 3
if (cinfo->input_components != RGB_PIXELSIZE)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
#endif /* else share code with YCbCr */
case JCS_YCbCr:
if (cinfo->input_components != 3)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case CS_CMYK:
case JCS_CMYK:
case JCS_YCCK:
if (cinfo->input_components != 4)
ERREXIT(cinfo->emethods, "Bogus input colorspace");
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported input colorspace");
default: /* JCS_UNKNOWN can be anything */
if (cinfo->input_components < 1)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
}
/* Check num_components, set conversion method based on requested space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->num_components != 1)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_GRAYSCALE)
cinfo->methods->get_sample_rows = get_grayscale_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_GRAYSCALE)
cconvert->pub.color_convert = grayscale_convert;
else if (cinfo->in_color_space == JCS_RGB) {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_gray_convert;
} else if (cinfo->in_color_space == JCS_YCbCr)
cconvert->pub.color_convert = grayscale_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_YCbCr:
case JCS_RGB:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_RGB)
cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
else if (cinfo->in_color_space == CS_YCbCr)
cinfo->methods->get_sample_rows = get_noconvert_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_CMYK:
case JCS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_RGB) {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_ycc_convert;
} else if (cinfo->in_color_space == JCS_YCbCr)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_CMYK:
if (cinfo->num_components != 4)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
if (cinfo->in_color_space == CS_CMYK)
cinfo->methods->get_sample_rows = get_noconvert_rows;
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_CMYK)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
case JCS_YCCK:
if (cinfo->num_components != 4)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
if (cinfo->in_color_space == JCS_CMYK) {
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = cmyk_ycck_convert;
} else if (cinfo->in_color_space == JCS_YCCK)
cconvert->pub.color_convert = null_convert;
else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default: /* allow null conversion of JCS_UNKNOWN */
if (cinfo->jpeg_color_space != cinfo->in_color_space ||
cinfo->num_components != cinfo->input_components)
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
cconvert->pub.color_convert = null_convert;
break;
}
cinfo->methods->colorin_init = colorin_init;
cinfo->methods->colorin_term = colorin_term;
}

398
jcdctmgr.c Normal file
View File

@@ -0,0 +1,398 @@
/*
* jcdctmgr.c
*
* Copyright (C) 1994, 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 forward-DCT management logic.
* This code selects a particular DCT implementation to be used,
* and it performs related housekeeping chores including coefficient
* quantization.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
/* Private subobject for this module */
typedef struct {
struct jpeg_forward_dct pub; /* public fields */
/* Pointer to the DCT routine actually in use */
forward_DCT_method_ptr do_dct;
/* The actual post-DCT divisors --- not identical to the quant table
* entries, because of scaling (especially for an unnormalized DCT).
* Each table is given in zigzag order.
*/
DCTELEM * divisors[NUM_QUANT_TBLS];
#ifdef DCT_FLOAT_SUPPORTED
/* Same as above for the floating-point case. */
float_DCT_method_ptr do_float_dct;
FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
#endif
} my_fdct_controller;
typedef my_fdct_controller * my_fdct_ptr;
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
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,
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
};
/*
* Initialize for a processing pass.
* Verify that all referenced Q-tables are present, and set up
* the divisor table for each one.
* In the current implementation, DCT of all components is done during
* the first pass, even if only some components will be output in the
* first scan. Hence all components should be examined here.
*/
METHODDEF void
start_pass_fdctmgr (j_compress_ptr cinfo)
{
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
int ci, qtblno, i;
jpeg_component_info *compptr;
JQUANT_TBL * qtbl;
DCTELEM * dtbl;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
qtblno = compptr->quant_tbl_no;
/* Make sure specified quantization table is present */
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
qtbl = cinfo->quant_tbl_ptrs[qtblno];
/* Compute divisors for this quant table */
/* We may do this more than once for same table, but it's not a big deal */
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
/* For LL&M IDCT method, divisors are equal to raw quantization
* coefficients multiplied by 8 (to counteract scaling).
*/
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
}
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
{
/* For AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
*/
#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits: in natural order */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
};
SHIFT_TEMPS
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
dtbl[i] = (DCTELEM)
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
(INT32) aanscales[ZAG[i]]),
CONST_BITS-3);
}
}
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
{
/* For float AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
* What's actually stored is 1/divisor so that the inner loop can
* use a multiplication rather than a division.
*/
FAST_FLOAT * fdtbl;
int row, col;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379
};
if (fdct->float_divisors[qtblno] == NULL) {
fdct->float_divisors[qtblno] = (FAST_FLOAT *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(FAST_FLOAT));
}
fdtbl = fdct->float_divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
row = ZAG[i] >> 3;
col = ZAG[i] & 7;
fdtbl[i] = (FAST_FLOAT)
(1.0 / (((double) qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col] * 8.0)));
}
}
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
}
}
/*
* Perform forward DCT on one or more blocks of a component.
*
* The input samples are taken from the sample_data[] array starting at
* position start_row/start_col, and moving to the right for any additional
* blocks. The quantized, zigzagged coefficients are returned in coef_blocks[].
*/
METHODDEF void
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
forward_DCT_method_ptr do_dct = fdct->do_dct;
DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
JDIMENSION bi;
sample_data += start_row; /* fold in the vertical offset once */
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
/* Load data into workspace, applying unsigned->signed conversion */
{ register DCTELEM *workspaceptr;
register JSAMPROW elemptr;
register int elemr;
workspaceptr = workspace;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
#else
{ register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
}
}
#endif
}
}
/* Perform the DCT */
(*do_dct) (workspace);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
{ register DCTELEM temp, qval;
register int i;
register JCOEFPTR output_ptr = coef_blocks[bi];
for (i = 0; i < DCTSIZE2; i++) {
qval = divisors[i];
temp = workspace[ZAG[i]];
/* 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) if (a >= b) a /= b; else a = 0
#endif
if (temp < 0) {
temp = -temp;
temp += qval>>1; /* for rounding */
DIVIDE_BY(temp, qval);
temp = -temp;
} else {
temp += qval>>1; /* for rounding */
DIVIDE_BY(temp, qval);
}
output_ptr[i] = (JCOEF) temp;
}
}
}
}
#ifdef DCT_FLOAT_SUPPORTED
METHODDEF void
forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
float_DCT_method_ptr do_dct = fdct->do_float_dct;
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
JDIMENSION bi;
sample_data += start_row; /* fold in the vertical offset once */
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
/* Load data into workspace, applying unsigned->signed conversion */
{ register FAST_FLOAT *workspaceptr;
register JSAMPROW elemptr;
register int elemr;
workspaceptr = workspace;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
#else
{ register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
}
}
#endif
}
}
/* Perform the DCT */
(*do_dct) (workspace);
/* Quantize/descale the coefficients, and store into coef_blocks[] */
{ register FAST_FLOAT temp;
register int i;
register JCOEFPTR output_ptr = coef_blocks[bi];
for (i = 0; i < DCTSIZE2; i++) {
/* Apply the quantization and scaling factor */
temp = workspace[ZAG[i]] * divisors[i];
/* Round to nearest integer.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
* The maximum coefficient size is +-16K (for 12-bit data), so this
* code should work for either 16-bit or 32-bit ints.
*/
output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
}
}
}
}
#endif /* DCT_FLOAT_SUPPORTED */
/*
* Initialize FDCT manager.
*/
GLOBAL void
jinit_forward_dct (j_compress_ptr cinfo)
{
my_fdct_ptr fdct;
int i;
fdct = (my_fdct_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_fdct_controller));
cinfo->fdct = (struct jpeg_forward_dct *) fdct;
fdct->pub.start_pass = start_pass_fdctmgr;
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
fdct->pub.forward_DCT = forward_DCT;
fdct->do_dct = jpeg_fdct_islow;
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
fdct->pub.forward_DCT = forward_DCT;
fdct->do_dct = jpeg_fdct_ifast;
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
fdct->pub.forward_DCT = forward_DCT_float;
fdct->do_float_dct = jpeg_fdct_float;
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
/* Mark divisor tables unallocated */
for (i = 0; i < NUM_QUANT_TBLS; i++) {
fdct->divisors[i] = NULL;
#ifdef DCT_FLOAT_SUPPORTED
fdct->float_divisors[i] = NULL;
#endif
}
}

View File

@@ -1,371 +0,0 @@
/*
* jcdeflts.c
*
* 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 optional default-setting code for the JPEG compressor.
* User interfaces do not have to use this file, but those that don't use it
* must know a lot more about the innards of the JPEG code.
*/
#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 */
}
/*
* Table setup routines
*/
LOCAL void
add_huff_table (compress_info_ptr cinfo,
HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
/* Define a Huffman table */
{
if (*htblptr == NULL)
*htblptr = (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));
/* Initialize sent_table FALSE so table will be written to JPEG file.
* In an application where we are writing non-interchange JPEG files,
* it might be desirable to save space by leaving default Huffman tables
* out of the file. To do that, just initialize sent_table = TRUE...
*/
(*htblptr)->sent_table = FALSE;
}
LOCAL void
std_huff_tables (compress_info_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG 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 };
static const UINT8 dc_luminance_val[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 dc_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static const UINT8 dc_chrominance_val[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 ac_luminance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static const UINT8 ac_luminance_val[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static const UINT8 ac_chrominance_bits[17] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static const UINT8 ac_chrominance_val[] =
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
dc_luminance_bits, dc_luminance_val);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
ac_luminance_bits, ac_luminance_val);
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
dc_chrominance_bits, dc_chrominance_val);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
ac_chrominance_bits, ac_chrominance_val);
}
/* This is the sample quantization table given in 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 in j_set_quality, below.)
*/
static const QUANT_VAL std_luminance_quant_tbl[DCTSIZE2] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static const QUANT_VAL std_chrominance_quant_tbl[DCTSIZE2] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
LOCAL void
add_quant_table (compress_info_ptr cinfo, int which_tbl,
const QUANT_VAL *basic_table, int scale_factor,
boolean force_baseline)
/* Define a quantization table equal to the basic_table times */
/* a scale factor (given as a percentage) */
{
QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
int i;
long temp;
if (*qtblptr == NULL)
*qtblptr = (QUANT_TBL_PTR) (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
for (i = 0; i < DCTSIZE2; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
#ifdef EIGHT_BIT_SAMPLES
if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */
#else
if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */
#endif
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
(*qtblptr)[i] = (QUANT_VAL) temp;
}
}
GLOBAL void
j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting. */
/* The 'quality' factor should be 0 (terrible) to 100 (very good). */
/* Quality 50 corresponds to the JPEG basic tables given above; */
/* quality 100 results in no quantization scaling at all. */
/* If force_baseline is TRUE, quantization table entries are limited */
/* to 0..255 for JPEG baseline compatibility; this is only an issue */
/* for quality settings below 24. */
{
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if (quality <= 0) quality = 1;
if (quality > 100) quality = 100;
/* Convert quality rating to a percentage scaling of the basic tables.
* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
* note that at Q=100 the scaling is 0, which will cause add_quant_table
* to make all the table entries 1 (hence, no quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
if (quality < 50)
quality = 5000 / quality;
else
quality = 200 - quality*2;
/* Set up two quantization tables using the specified quality scaling */
add_quant_table(cinfo, 0, std_luminance_quant_tbl, quality, force_baseline);
add_quant_table(cinfo, 1, std_chrominance_quant_tbl, quality, force_baseline);
}
/* Default parameter setup for compression.
*
* User interfaces that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*
* See above for the meaning of the 'quality' and 'force_baseline' parameters.
* Typically, the application's default quality setting will be passed to this
* routine. A later call on j_set_quality() can be used to change to a
* user-specified quality setting.
*
* This routine sets up for a color image; to output a grayscale image,
* do this first and call j_monochrome_default() afterwards.
* (The latter can be called within c_ui_method_selection, so the
* choice can depend on the input file header.)
* Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr,
* you should also change the component ID codes, and you should NOT emit
* a JFIF header (set write_JFIF_header = FALSE).
*
* CAUTION: if you want to compress multiple images per run, it's 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
j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline)
/* NB: the external methods must already be set up. */
{
short i;
jpeg_component_info * compptr;
/* Initialize pointers as needed to mark stuff unallocated. */
cinfo->comp_info = NULL;
for (i = 0; i < NUM_QUANT_TBLS; i++)
cinfo->quant_tbl_ptrs[i] = NULL;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
cinfo->dc_huff_tbl_ptrs[i] = NULL;
cinfo->ac_huff_tbl_ptrs[i] = NULL;
}
cinfo->data_precision = 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 */
/* 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 *)
(*cinfo->emethods->alloc_small) (4 * SIZEOF(jpeg_component_info));
/* Note: we allocate a 4-entry comp_info array so that user interface can
* easily change over to CMYK color space if desired.
*/
compptr = &cinfo->comp_info[0];
compptr->component_index = 0;
compptr->component_id = 1; /* JFIF specifies IDs 1,2,3 */
compptr->h_samp_factor = 2; /* default to 2x2 subsamples of chrominance */
compptr->v_samp_factor = 2;
compptr->quant_tbl_no = 0; /* use tables 0 for luminance */
compptr->dc_tbl_no = 0;
compptr->ac_tbl_no = 0;
compptr = &cinfo->comp_info[1];
compptr->component_index = 1;
compptr->component_id = 2;
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
compptr->dc_tbl_no = 1;
compptr->ac_tbl_no = 1;
compptr = &cinfo->comp_info[2];
compptr->component_index = 2;
compptr->component_id = 3;
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
compptr->dc_tbl_no = 1;
compptr->ac_tbl_no = 1;
/* Set up two quantization tables using the specified quality scaling */
j_set_quality(cinfo, quality, force_baseline);
/* Set up two Huffman tables in case user interface wants Huffman coding */
std_huff_tables(cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo->arith_dc_L[i] = 0;
cinfo->arith_dc_U[i] = 1;
cinfo->arith_ac_K[i] = 5;
}
/* Use Huffman coding, not arithmetic coding, by default */
cinfo->arith_code = FALSE;
/* Color images are interleaved by default */
cinfo->interleave = TRUE;
/* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE;
/* By default, use the simpler non-cosited sampling alignment */
cinfo->CCIR601_sampling = FALSE;
/* No restart markers */
cinfo->restart_interval = 0;
/* Install default do-nothing progress monitoring method. */
cinfo->methods->progress_monitor = progress_monitor;
}
GLOBAL void
j_monochrome_default (compress_info_ptr cinfo)
/* Change the j_c_defaults() values to emit a monochrome JPEG file. */
{
jpeg_component_info * compptr;
cinfo->jpeg_color_space = CS_GRAYSCALE;
cinfo->num_components = 1;
/* Set single component to 1x1 subsampling */
compptr = &cinfo->comp_info[0];
compptr->h_samp_factor = 1;
compptr->v_samp_factor = 1;
}

View File

@@ -1,75 +0,0 @@
/*
* jcexpand.c
*
* 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 image edge-expansion routines.
* These routines are invoked via the edge_expand method.
*/
#include "jinclude.h"
/*
* Expand an image so that it is a multiple of the MCU dimensions.
* This is to be accomplished by duplicating the rightmost column
* and/or bottommost row of pixels. The image has not yet been
* subsampled, so all components have the same dimensions.
*/
METHODDEF void
edge_expand (compress_info_ptr cinfo,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPIMAGE image_data)
{
/* Expand horizontally */
if (input_cols < output_cols) {
register JSAMPROW ptr;
register JSAMPLE pixval;
register long count;
register int row;
short ci;
long numcols = output_cols - input_cols;
for (ci = 0; ci < cinfo->num_components; ci++) {
for (row = 0; row < input_rows; row++) {
ptr = image_data[ci][row] + (input_cols-1);
pixval = GETJSAMPLE(*ptr++);
for (count = numcols; count > 0; count--)
*ptr++ = pixval;
}
}
}
/* Expand vertically */
/* This happens only once at the bottom of the image, */
/* so it needn't be super-efficient */
if (input_rows < output_rows) {
register int row;
short ci;
JSAMPARRAY this_component;
for (ci = 0; ci < cinfo->num_components; ci++) {
this_component = image_data[ci];
for (row = input_rows; row < output_rows; row++) {
jcopy_sample_rows(this_component, input_rows-1, this_component, row,
1, output_cols);
}
}
}
}
/*
* The method selection routine for edge expansion.
*/
GLOBAL void
jselexpand (compress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->edge_expand = edge_expand;
}

793
jchuff.c

File diff suppressed because it is too large Load Diff

358
jcmain.c
View File

@@ -1,358 +0,0 @@
/*
* jcmain.c
*
* 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 a trivial test user interface for the JPEG compressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* cjpeg [options] inputfile outputfile
* cjpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#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.
*
* To determine which family of input formats the file belongs to,
* we may look only at the first byte of the file, since C does not
* guarantee that more than one character can be pushed back with ungetc.
* Looking at additional bytes would require one of these approaches:
* 1) assume we can fseek() the input file (fails for piped input);
* 2) assume we can push back more than one character (works in
* some C implementations, but unportable);
* 3) provide our own buffering as is done in djpeg (breaks input readers
* that want to use stdio directly, such as the RLE library);
* or 4) don't put back the data, and modify the input_init methods to assume
* they start reading after the start of file (also breaks RLE library).
* #1 is attractive for MS-DOS but is untenable on Unix.
*
* The most portable solution for file types that can't be identified by their
* first byte is to make the user tell us what they are. This is also the
* only approach for "raw" file types that contain only arbitrary values.
* 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.
*/
static boolean is_targa; /* records user -T switch */
LOCAL void
select_file_type (compress_info_ptr cinfo)
{
int c;
if (is_targa) {
#ifdef TARGA_SUPPORTED
jselrtarga(cinfo);
#else
ERREXIT(cinfo->emethods, "Targa support was not compiled");
#endif
return;
}
if ((c = getc(cinfo->input_file)) == EOF)
ERREXIT(cinfo->emethods, "Empty input file");
switch (c) {
#ifdef GIF_SUPPORTED
case 'G':
jselrgif(cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case 'P':
jselrppm(cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case 'R':
jselrrle(cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case 0x00:
jselrtarga(cinfo);
break;
#endif
default:
#ifdef TARGA_SUPPORTED
ERREXIT(cinfo->emethods, "Unrecognized input file format --- did you forget -T ?");
#else
ERREXIT(cinfo->emethods, "Unrecognized input file format");
#endif
break;
}
if (ungetc(c, cinfo->input_file) == EOF)
ERREXIT(cinfo->emethods, "ungetc failed");
}
/*
* This routine gets control after the input file header has been read.
* It must determine what output JPEG file format is to be written,
* and make any other compression parameter changes that are desirable.
*/
METHODDEF void
c_ui_method_selection (compress_info_ptr cinfo)
{
/* If the input is gray scale, generate a monochrome JPEG file. */
if (cinfo->in_color_space == CS_GRAYSCALE)
j_monochrome_default(cinfo);
/* For now, always select JFIF output format. */
#ifdef JFIF_SUPPORTED
jselwjfif(cinfo);
#else
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
#endif
}
/*
* 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)
{
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
exit(EXIT_FAILURE);
}
#endif
LOCAL void
usage (char * progname)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-Q quality 0..100] [-o] [-T] [-I] [-a] [-d] [-m mem]");
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, " inputfile outputfile\n");
#else
fprintf(stderr, " [inputfile]\n");
#endif
exit(EXIT_FAILURE);
}
/*
* The main program.
*/
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;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
/* Initialize the system-dependent method pointers. */
cinfo.methods = &c_methods;
cinfo.emethods = &e_methods;
jselerror(&e_methods); /* error/trace message routines */
jselmemmgr(&e_methods); /* memory allocation routines */
c_methods.c_ui_method_selection = c_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = &e_methods;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* 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:Taom:d")) != 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(EXIT_FAILURE);
#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(EXIT_FAILURE);
#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(EXIT_FAILURE);
#endif
break;
case 'm': /* Maximum memory in Kb (or Mb with 'm'). */
{ long lval;
char ch = 'x';
if (optarg == NULL)
usage(argv[0]);
if (sscanf(optarg, "%ld%c", &lval, &ch) < 1)
usage(argv[0]);
if (ch == 'm' || ch == 'M')
lval *= 1000L;
e_methods.max_memory_to_use = lval * 1000L;
}
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);
/* Select the input and output files */
#ifdef TWO_FILE_COMMANDLINE
if (optind != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
usage(argv[0]);
}
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
exit(EXIT_FAILURE);
}
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(EXIT_FAILURE);
}
#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(EXIT_FAILURE);
}
}
#endif /* TWO_FILE_COMMANDLINE */
/* Figure out the input file format, and set up to read it. */
select_file_type(&cinfo);
/* Do it to it! */
jpeg_compress(&cinfo);
/* All done. */
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

298
jcmainct.c Normal file
View File

@@ -0,0 +1,298 @@
/*
* jcmainct.c
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main buffer controller for compression.
* The main buffer lies between the pre-processor and the JPEG
* compressor proper; it holds downsampled data in the JPEG colorspace.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Note: currently, there is no operating mode in which a full-image buffer
* is needed at this step. If there were, that mode could not be used with
* "raw data" input, since this module is bypassed in that case. However,
* we've left the code here for possible use in special applications.
*/
#undef FULL_MAIN_BUFFER_SUPPORTED
/* Private buffer controller object */
typedef struct {
struct jpeg_c_main_controller pub; /* public fields */
JDIMENSION cur_mcu_row; /* number of current iMCU row */
JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
JDIMENSION mcu_ctr; /* counts MCUs output from current row */
boolean suspended; /* remember if we suspended output */
J_BUF_MODE pass_mode; /* current operating mode */
/* If using just a strip buffer, this points to the entire set of buffers
* (we allocate one for each component). In the full-image case, this
* points to the currently accessible strips of the virtual arrays.
*/
JSAMPARRAY buffer[MAX_COMPONENTS];
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* If using full-image storage, this array holds pointers to virtual-array
* control blocks for each component. Unused if not full-image storage.
*/
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
#endif
} my_main_controller;
typedef my_main_controller * my_main_ptr;
/* Forward declarations */
METHODDEF void process_data_simple_main
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
#ifdef FULL_MAIN_BUFFER_SUPPORTED
METHODDEF void process_data_buffer_main
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
/* Do nothing in raw-data mode. */
if (cinfo->raw_data_in)
return;
main->cur_mcu_row = 0; /* initialize counters */
main->rowgroup_ctr = 0;
main->mcu_ctr = 0;
main->suspended = FALSE;
main->pass_mode = pass_mode; /* save mode for use by process_data */
switch (pass_mode) {
case JBUF_PASS_THRU:
#ifdef FULL_MAIN_BUFFER_SUPPORTED
if (main->whole_image[0] != NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
main->pub.process_data = process_data_simple_main;
break;
#ifdef FULL_MAIN_BUFFER_SUPPORTED
case JBUF_SAVE_SOURCE:
case JBUF_CRANK_DEST:
case JBUF_SAVE_AND_PASS:
if (main->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
main->pub.process_data = process_data_buffer_main;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data.
* This routine handles the simple pass-through mode,
* where we have only a strip buffer.
*/
METHODDEF void
process_data_simple_main (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
while (main->cur_mcu_row < cinfo->total_iMCU_rows) {
/* Read input data if we haven't filled the main buffer yet */
if (main->rowgroup_ctr < DCTSIZE)
(*cinfo->prep->pre_process_data) (cinfo,
input_buf, in_row_ctr, in_rows_avail,
main->buffer, &main->rowgroup_ctr,
(JDIMENSION) DCTSIZE);
/* If we don't have a full iMCU row buffered, return to application for
* more data. Note that preprocessor will always pad to fill the iMCU row
* at the bottom of the image.
*/
if (main->rowgroup_ctr != DCTSIZE)
return;
/* Send the completed row to the compressor */
(*cinfo->coef->compress_data) (cinfo, main->buffer, &main->mcu_ctr);
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if (main->mcu_ctr < cinfo->MCUs_per_row) {
if (! main->suspended) {
(*in_row_ctr)--;
main->suspended = TRUE;
}
return;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if (main->suspended) {
(*in_row_ctr)++;
main->suspended = FALSE;
}
main->mcu_ctr = 0;
main->rowgroup_ctr = 0;
main->cur_mcu_row++;
}
}
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/*
* Process some data.
* This routine handles all of the modes that use a full-size buffer.
*/
METHODDEF void
process_data_buffer_main (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci;
jpeg_component_info *compptr;
boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
while (main->cur_mcu_row < cinfo->total_iMCU_rows) {
/* Realign the virtual buffers if at the start of an iMCU row. */
if (main->rowgroup_ctr == 0) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, main->whole_image[ci],
main->cur_mcu_row * (compptr->v_samp_factor * DCTSIZE), writing);
}
/* In a read pass, pretend we just read some source data. */
if (! writing) {
*in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
main->rowgroup_ctr = DCTSIZE;
}
}
/* If a write pass, read input data until the current iMCU row is full. */
/* Note: preprocessor will pad if necessary to fill the last iMCU row. */
if (writing) {
(*cinfo->prep->pre_process_data) (cinfo,
input_buf, in_row_ctr, in_rows_avail,
main->buffer, &main->rowgroup_ctr,
(JDIMENSION) DCTSIZE);
/* Return to application if we need more data to fill the iMCU row. */
if (main->rowgroup_ctr < DCTSIZE)
return;
}
/* Emit data, unless this is a sink-only pass. */
if (main->pass_mode != JBUF_SAVE_SOURCE) {
(*cinfo->coef->compress_data) (cinfo, main->buffer, &main->mcu_ctr);
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
if (main->mcu_ctr < cinfo->MCUs_per_row) {
if (! main->suspended) {
(*in_row_ctr)--;
main->suspended = TRUE;
}
return;
}
/* We did finish the row. Undo our little suspension hack if a previous
* call suspended; then mark the main buffer empty.
*/
if (main->suspended) {
(*in_row_ctr)++;
main->suspended = FALSE;
}
}
/* If get here, we are done with this iMCU row. Mark buffer empty. */
main->mcu_ctr = 0;
main->rowgroup_ctr = 0;
main->cur_mcu_row++;
}
}
#endif /* FULL_MAIN_BUFFER_SUPPORTED */
/*
* Initialize main buffer controller.
*/
GLOBAL void
jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main;
int ci;
jpeg_component_info *compptr;
main = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_main_controller));
cinfo->main = (struct jpeg_c_main_controller *) main;
main->pub.start_pass = start_pass_main;
/* We don't need to create a buffer in raw-data mode. */
if (cinfo->raw_data_in)
return;
/* Create the buffer. It holds downsampled data, so each component
* may be of a different size.
*/
if (need_full_buffer) {
#ifdef FULL_MAIN_BUFFER_SUPPORTED
/* Allocate a full-image virtual array for each component */
/* Note we implicitly pad the bottom to a multiple of the iMCU height */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * DCTSIZE,
compptr->height_in_blocks * DCTSIZE,
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
} else {
#ifdef FULL_MAIN_BUFFER_SUPPORTED
main->whole_image[0] = NULL; /* flag for no virtual arrays */
#endif
/* Allocate a strip buffer for each component */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * DCTSIZE,
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
}
}
}

605
jcmarker.c Normal file
View File

@@ -0,0 +1,605 @@
/*
* jcmarker.c
*
* Copyright (C) 1991-1994, 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 JPEG datastream markers.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0,
M_SOF1 = 0xc1,
M_SOF2 = 0xc2,
M_SOF3 = 0xc3,
M_SOF5 = 0xc5,
M_SOF6 = 0xc6,
M_SOF7 = 0xc7,
M_JPG = 0xc8,
M_SOF9 = 0xc9,
M_SOF10 = 0xca,
M_SOF11 = 0xcb,
M_SOF13 = 0xcd,
M_SOF14 = 0xce,
M_SOF15 = 0xcf,
M_DHT = 0xc4,
M_DAC = 0xcc,
M_RST0 = 0xd0,
M_RST1 = 0xd1,
M_RST2 = 0xd2,
M_RST3 = 0xd3,
M_RST4 = 0xd4,
M_RST5 = 0xd5,
M_RST6 = 0xd6,
M_RST7 = 0xd7,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
M_DQT = 0xdb,
M_DNL = 0xdc,
M_DRI = 0xdd,
M_DHP = 0xde,
M_EXP = 0xdf,
M_APP0 = 0xe0,
M_APP1 = 0xe1,
M_APP2 = 0xe2,
M_APP3 = 0xe3,
M_APP4 = 0xe4,
M_APP5 = 0xe5,
M_APP6 = 0xe6,
M_APP7 = 0xe7,
M_APP8 = 0xe8,
M_APP9 = 0xe9,
M_APP10 = 0xea,
M_APP11 = 0xeb,
M_APP12 = 0xec,
M_APP13 = 0xed,
M_APP14 = 0xee,
M_APP15 = 0xef,
M_JPG0 = 0xf0,
M_JPG13 = 0xfd,
M_COM = 0xfe,
M_TEM = 0x01,
M_ERROR = 0x100
} JPEG_MARKER;
/*
* Basic output routines.
*
* Note that we do not support suspension while writing a marker.
* Therefore, an application using suspension must ensure that there is
* enough buffer space for the initial markers (typ. 600-700 bytes) before
* calling jpeg_start_compress, and enough space to write the trailing EOI
* (a few bytes) before calling jpeg_finish_compress. Multipass compression
* modes are not supported at all with suspension, so those two are the only
* points where markers will be written.
*/
LOCAL void
emit_byte (j_compress_ptr cinfo, int val)
/* Emit a byte */
{
struct jpeg_destination_mgr * dest = cinfo->dest;
*(dest->next_output_byte)++ = (JOCTET) val;
if (--dest->free_in_buffer == 0) {
if (! (*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
}
LOCAL void
emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
/* Emit a marker code */
{
emit_byte(cinfo, 0xFF);
emit_byte(cinfo, (int) mark);
}
LOCAL void
emit_2bytes (j_compress_ptr cinfo, int value)
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
{
emit_byte(cinfo, (value >> 8) & 0xFF);
emit_byte(cinfo, value & 0xFF);
}
/*
* Routines to write specific marker types.
*/
LOCAL int
emit_dqt (j_compress_ptr cinfo, int index)
/* Emit a DQT marker */
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
{
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
int prec;
int i;
if (qtbl == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
prec = 0;
for (i = 0; i < DCTSIZE2; i++) {
if (qtbl->quantval[i] > 255)
prec = 1;
}
if (! qtbl->sent_table) {
emit_marker(cinfo, M_DQT);
emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
emit_byte(cinfo, index + (prec<<4));
for (i = 0; i < DCTSIZE2; i++) {
if (prec)
emit_byte(cinfo, qtbl->quantval[i] >> 8);
emit_byte(cinfo, qtbl->quantval[i] & 0xFF);
}
qtbl->sent_table = TRUE;
}
return prec;
}
LOCAL void
emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
/* Emit a DHT marker */
{
JHUFF_TBL * htbl;
int length, i;
if (is_ac) {
htbl = cinfo->ac_huff_tbl_ptrs[index];
index += 0x10; /* output index has AC bit set */
} else {
htbl = cinfo->dc_huff_tbl_ptrs[index];
}
if (htbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
if (! htbl->sent_table) {
emit_marker(cinfo, M_DHT);
length = 0;
for (i = 1; i <= 16; i++)
length += htbl->bits[i];
emit_2bytes(cinfo, length + 2 + 1 + 16);
emit_byte(cinfo, index);
for (i = 1; i <= 16; i++)
emit_byte(cinfo, htbl->bits[i]);
for (i = 0; i < length; i++)
emit_byte(cinfo, htbl->huffval[i]);
htbl->sent_table = TRUE;
}
}
LOCAL void
emit_dac (j_compress_ptr cinfo)
/* Emit a DAC marker */
/* Since the useful info is so small, we want to emit all the tables in */
/* one DAC marker. Therefore this routine does its own scan of the table. */
{
#ifdef C_ARITH_CODING_SUPPORTED
char dc_in_use[NUM_ARITH_TBLS];
char ac_in_use[NUM_ARITH_TBLS];
int length, i;
jpeg_component_info *compptr;
for (i = 0; i < NUM_ARITH_TBLS; i++)
dc_in_use[i] = ac_in_use[i] = 0;
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
dc_in_use[compptr->dc_tbl_no] = 1;
ac_in_use[compptr->ac_tbl_no] = 1;
}
length = 0;
for (i = 0; i < NUM_ARITH_TBLS; i++)
length += dc_in_use[i] + ac_in_use[i];
emit_marker(cinfo, M_DAC);
emit_2bytes(cinfo, length*2 + 2);
for (i = 0; i < NUM_ARITH_TBLS; i++) {
if (dc_in_use[i]) {
emit_byte(cinfo, i);
emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
}
if (ac_in_use[i]) {
emit_byte(cinfo, i + 0x10);
emit_byte(cinfo, cinfo->arith_ac_K[i]);
}
}
#endif /* C_ARITH_CODING_SUPPORTED */
}
LOCAL void
emit_dri (j_compress_ptr cinfo)
/* Emit a DRI marker */
{
emit_marker(cinfo, M_DRI);
emit_2bytes(cinfo, 4); /* fixed length */
emit_2bytes(cinfo, (int) cinfo->restart_interval);
}
LOCAL void
emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
/* Emit a SOF marker */
{
int ci;
jpeg_component_info *compptr;
emit_marker(cinfo, code);
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
/* Make sure image isn't bigger than SOF field can handle */
if ((long) cinfo->image_height > 65535L ||
(long) cinfo->image_width > 65535L)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
emit_byte(cinfo, cinfo->data_precision);
emit_2bytes(cinfo, (int) cinfo->image_height);
emit_2bytes(cinfo, (int) cinfo->image_width);
emit_byte(cinfo, cinfo->num_components);
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
emit_byte(cinfo, compptr->component_id);
emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
emit_byte(cinfo, compptr->quant_tbl_no);
}
}
LOCAL void
emit_sos (j_compress_ptr cinfo)
/* Emit a SOS marker */
{
int i;
jpeg_component_info *compptr;
emit_marker(cinfo, M_SOS);
emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
emit_byte(cinfo, cinfo->comps_in_scan);
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
emit_byte(cinfo, compptr->component_id);
emit_byte(cinfo, (compptr->dc_tbl_no << 4) + compptr->ac_tbl_no);
}
emit_byte(cinfo, 0); /* Spectral selection start */
emit_byte(cinfo, DCTSIZE2-1); /* Spectral selection end */
emit_byte(cinfo, 0); /* Successive approximation */
}
LOCAL void
emit_jfif_app0 (j_compress_ptr cinfo)
/* Emit a JFIF-compliant APP0 marker */
{
/*
* Length of APP0 block (2 bytes)
* Block ID (4 bytes - ASCII "JFIF")
* Zero byte (1 byte to terminate the ID string)
* Version Major, Minor (2 bytes - 0x01, 0x01)
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
* Xdpu (2 bytes - dots per unit horizontal)
* Ydpu (2 bytes - dots per unit vertical)
* Thumbnail X size (1 byte)
* Thumbnail Y size (1 byte)
*/
emit_marker(cinfo, M_APP0);
emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0x49);
emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0);
/* We currently emit version code 1.01 since we use no 1.02 features.
* This may avoid complaints from some older decoders.
*/
emit_byte(cinfo, 1); /* Major version */
emit_byte(cinfo, 1); /* Minor version */
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
emit_2bytes(cinfo, (int) cinfo->X_density);
emit_2bytes(cinfo, (int) cinfo->Y_density);
emit_byte(cinfo, 0); /* No thumbnail image */
emit_byte(cinfo, 0);
}
LOCAL void
emit_adobe_app14 (j_compress_ptr cinfo)
/* Emit an Adobe APP14 marker */
{
/*
* Length of APP14 block (2 bytes)
* Block ID (5 bytes - ASCII "Adobe")
* Version Number (2 bytes - currently 100)
* Flags0 (2 bytes - currently 0)
* Flags1 (2 bytes - currently 0)
* Color transform (1 byte)
*
* Although Adobe TN 5116 mentions Version = 101, all the Adobe files
* now in circulation seem to use Version = 100, so that's what we write.
*
* We write the color transform byte as 1 if the JPEG color space is
* YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
* whether the encoder performed a transformation, which is pretty useless.
*/
emit_marker(cinfo, M_APP14);
emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
emit_byte(cinfo, 0x64);
emit_byte(cinfo, 0x6F);
emit_byte(cinfo, 0x62);
emit_byte(cinfo, 0x65);
emit_2bytes(cinfo, 100); /* Version */
emit_2bytes(cinfo, 0); /* Flags0 */
emit_2bytes(cinfo, 0); /* Flags1 */
switch (cinfo->jpeg_color_space) {
case JCS_YCbCr:
emit_byte(cinfo, 1); /* Color transform = 1 */
break;
case JCS_YCCK:
emit_byte(cinfo, 2); /* Color transform = 2 */
break;
default:
emit_byte(cinfo, 0); /* Color transform = 0 */
break;
}
}
/*
* This routine is exported for possible use by applications.
* The intended use is to emit COM or APPn markers after calling
* jpeg_start_compress() and before the first jpeg_write_scanlines() call
* (hence, after write_file_header but before write_frame_header).
* Other uses are not guaranteed to produce desirable results.
*/
METHODDEF void
write_any_marker (j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen)
/* Emit an arbitrary marker with parameters */
{
if (datalen <= (unsigned int) 65533) { /* safety check */
emit_marker(cinfo, (JPEG_MARKER) marker);
emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
while (datalen--) {
emit_byte(cinfo, *dataptr);
dataptr++;
}
}
}
/*
* Write datastream header.
* This consists of an SOI and optional APPn markers.
* We recommend use of the JFIF marker, but not the Adobe marker,
* when using YCbCr or grayscale data. The JFIF marker should NOT
* be used for any other JPEG colorspace. The Adobe marker is helpful
* to distinguish RGB, CMYK, and YCCK colorspaces.
* Note that an application can write additional header markers after
* jpeg_start_decompress returns.
*/
METHODDEF void
write_file_header (j_compress_ptr cinfo)
{
emit_marker(cinfo, M_SOI); /* first the SOI */
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
emit_jfif_app0(cinfo);
if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
emit_adobe_app14(cinfo);
}
/*
* Write frame header.
* This consists of DQT and SOFn markers.
* Note that we do not emit the SOF until we have emitted the DQT(s).
* This avoids compatibility problems with incorrect implementations that
* try to error-check the quant table numbers as soon as they see the SOF.
*/
METHODDEF void
write_frame_header (j_compress_ptr cinfo)
{
int ci, prec;
boolean is_baseline;
jpeg_component_info *compptr;
/* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables.
*/
prec = 0;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
}
/* now prec is nonzero iff there are any 16-bit quant tables. */
/* Check for a non-baseline specification.
* Note we assume that Huffman table numbers won't be changed later.
*/
is_baseline = TRUE;
if (cinfo->arith_code || (cinfo->data_precision != 8))
is_baseline = FALSE;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
is_baseline = FALSE;
}
if (prec && is_baseline) {
is_baseline = FALSE;
/* If it's baseline except for quantizer size, warn the user */
TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
}
/* Emit the proper SOF marker */
if (cinfo->arith_code)
emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
else if (is_baseline)
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
else
emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
}
/*
* Write scan header.
* This consists of DHT or DAC markers, optional DRI, and SOS.
* Compressed data will be written following the SOS.
*/
METHODDEF void
write_scan_header (j_compress_ptr cinfo)
{
int i;
jpeg_component_info *compptr;
if (cinfo->arith_code) {
/* Emit arith conditioning info. We may have some duplication
* if the file has multiple scans, but it's so small it's hardly
* worth worrying about.
*/
emit_dac(cinfo);
} else {
/* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables.
*/
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
}
}
/* 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);
}
/*
* Write datastream trailer.
*/
METHODDEF void
write_file_trailer (j_compress_ptr cinfo)
{
emit_marker(cinfo, M_EOI);
}
/*
* Write an abbreviated table-specification datastream.
* This consists of SOI, DQT and DHT tables, and EOI.
* Any table that is defined and not marked sent_table = TRUE will be
* emitted. Note that all tables will be marked sent_table = TRUE at exit.
*/
METHODDEF void
write_tables_only (j_compress_ptr cinfo)
{
int i;
emit_marker(cinfo, M_SOI);
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if (cinfo->quant_tbl_ptrs[i] != NULL)
(void) emit_dqt(cinfo, i);
}
if (! cinfo->arith_code) {
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, FALSE);
if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, TRUE);
}
}
emit_marker(cinfo, M_EOI);
}
/*
* Initialize the marker writer module.
*/
GLOBAL void
jinit_marker_writer (j_compress_ptr cinfo)
{
/* Create the subobject */
cinfo->marker = (struct jpeg_marker_writer *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(struct jpeg_marker_writer));
/* Initialize method pointers */
cinfo->marker->write_any_marker = write_any_marker;
cinfo->marker->write_file_header = write_file_header;
cinfo->marker->write_frame_header = write_frame_header;
cinfo->marker->write_scan_header = write_scan_header;
cinfo->marker->write_file_trailer = write_file_trailer;
cinfo->marker->write_tables_only = write_tables_only;
}

View File

@@ -1,133 +1,387 @@
/*
* jcmaster.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main control for the JPEG compressor.
* The system-dependent (user interface) code should call jpeg_compress()
* after doing appropriate setup of the compress_info_struct parameter.
* This file contains master control logic for the JPEG compressor.
* These routines are concerned with selecting the modules to be executed
* and with determining the number of passes and the work to be done in each
* pass.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
METHODDEF void
c_per_scan_method_selection (compress_info_ptr cinfo)
/* Central point for per-scan method selection */
{
/* Edge expansion */
jselexpand(cinfo);
/* Subsampling of pixels */
jselsubsample(cinfo);
/* MCU extraction */
jselcmcu(cinfo);
}
/* Private state */
typedef struct {
struct jpeg_comp_master pub; /* public fields */
int pass_number; /* eventually need more complex state... */
} my_comp_master;
typedef my_comp_master * my_master_ptr;
/*
* Support routines that do various essential calculations.
*/
LOCAL void
c_initial_method_selection (compress_info_ptr cinfo)
/* Central point for initial method selection */
initial_setup (j_compress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
/* Input image reading method selection is already done. */
/* So is output file header formatting (both are done by user interface). */
/* Gamma and color space conversion */
jselccolor(cinfo);
/* Entropy encoding: either Huffman or arithmetic coding. */
#ifdef ARITH_CODING_SUPPORTED
jselcarithmetic(cinfo);
#else
cinfo->arith_code = FALSE; /* force Huffman mode */
#endif
jselchuffman(cinfo);
/* Pipeline control */
jselcpipeline(cinfo);
/* Overall control (that's me!) */
cinfo->methods->c_per_scan_method_selection = c_per_scan_method_selection;
}
LOCAL void
initial_setup (compress_info_ptr cinfo)
/* Do computations that are needed before initial method selection */
{
short ci;
int ci;
jpeg_component_info *compptr;
long samplesperrow;
JDIMENSION jd_samplesperrow;
/* Sanity check on image dimensions */
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|| cinfo->num_components <= 0 || cinfo->input_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
if ((long) jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */
if (cinfo->data_precision != BITS_IN_JSAMPLE)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */
if (cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
/* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1;
cinfo->max_v_samp_factor = 1;
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo->emethods, "Bogus sampling factors");
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor);
}
/* Compute dimensions of components */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* For compression, we never do DCT scaling. */
compptr->DCT_scaled_size = DCTSIZE;
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE;
}
/* Compute number of fully interleaved MCU rows (number of times that
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
}
LOCAL void
per_scan_setup (j_compress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{
int ci, mcublks, tmp;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan == 1) {
/* Noninterleaved (single-component) scan */
compptr = cinfo->cur_comp_info[0];
/* Overall image size in MCUs */
cinfo->MCUs_per_row = compptr->width_in_blocks;
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
/* For noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
compptr->MCU_sample_width = DCTSIZE;
compptr->last_col_width = 1;
compptr->last_row_height = 1;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
} else {
/* Interleaved (multi-component) scan */
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
MAX_COMPS_IN_SCAN);
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Sampling factors give # of blocks of component in each MCU */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
}
/* Compute logical subsampled dimensions of components */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+ cinfo->max_h_samp_factor - 1)
/ cinfo->max_h_samp_factor;
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+ cinfo->max_v_samp_factor - 1)
/ cinfo->max_v_samp_factor;
/* 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 = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
}
}
/*
* This is the main entry point to the JPEG compressor.
* Master selection of compression modules.
* This is done once at the start of processing an image. We determine
* which modules will be used and give them appropriate initialization calls.
*/
LOCAL void
master_selection (j_compress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
initial_setup(cinfo);
master->pass_number = 0;
/* There's not a lot of smarts here right now, but it'll get more
* complicated when we have multiple implementations available...
*/
/* Preprocessing */
if (! cinfo->raw_data_in) {
jinit_color_converter(cinfo);
jinit_downsampler(cinfo);
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
}
/* Forward DCT */
jinit_forward_dct(cinfo);
/* Entropy encoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
#ifdef C_ARITH_CODING_SUPPORTED
jinit_arith_encoder(cinfo);
#else
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
#endif
} else
jinit_huff_encoder(cinfo);
/* For now, a full buffer is needed only for Huffman optimization. */
jinit_c_coef_controller(cinfo, cinfo->optimize_coding);
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
/* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later.
* This lets application insert special markers after the SOI.
*/
(*cinfo->marker->write_file_header) (cinfo);
}
/*
* Per-pass setup.
* This is called at the beginning of each pass. We determine which modules
* will be active during this pass and give them appropriate start_pass calls.
* We also set is_last_pass to indicate whether any more passes will be
* required.
*/
METHODDEF void
prepare_for_pass (j_compress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
int ci;
int npasses;
/* ???? JUST A QUICK CROCK FOR NOW ??? */
/* For now, handle only single interleaved output scan; */
/* we support two passes for Huffman optimization. */
/* Prepare for single scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPS_IN_SCAN);
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
per_scan_setup(cinfo);
if (! cinfo->optimize_coding) {
/* Standard single-pass case */
npasses = 1;
master->pub.call_pass_startup = TRUE;
master->pub.is_last_pass = TRUE;
if (! cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
}
(*cinfo->fdct->start_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo, FALSE);
(*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU);
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
} else {
npasses = 2;
switch (master->pass_number) {
case 0:
/* Huffman optimization: run all modules, gather statistics */
master->pub.call_pass_startup = FALSE;
master->pub.is_last_pass = FALSE;
if (! cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
}
(*cinfo->fdct->start_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo, TRUE);
(*cinfo->coef->start_pass) (cinfo, JBUF_SAVE_AND_PASS);
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
break;
case 1:
/* Second pass: reread data from coefficient buffer */
master->pub.is_last_pass = TRUE;
(*cinfo->entropy->start_pass) (cinfo, FALSE);
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
/* We emit frame/scan headers now */
(*cinfo->marker->write_frame_header) (cinfo);
(*cinfo->marker->write_scan_header) (cinfo);
break;
}
}
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
cinfo->progress->completed_passes = master->pass_number;
cinfo->progress->total_passes = npasses;
}
master->pass_number++;
}
/*
* Special start-of-pass hook.
* This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
* In single-pass processing, we need this hook because we don't want to
* write frame/scan headers during jpeg_start_compress; we want to let the
* application write COM markers etc. between jpeg_start_compress and the
* jpeg_write_scanlines loop.
* In multi-pass processing, this routine is not used.
*/
METHODDEF void
pass_startup (j_compress_ptr cinfo)
{
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
(*cinfo->marker->write_frame_header) (cinfo);
(*cinfo->marker->write_scan_header) (cinfo);
}
/*
* Finish up at end of pass.
*/
METHODDEF void
finish_pass_master (j_compress_ptr cinfo)
{
/* More complex logic later ??? */
/* The entropy coder needs an end-of-pass call, either to analyze
* statistics or to flush its output buffer.
*/
(*cinfo->entropy->finish_pass) (cinfo);
}
/*
* Initialize master compression control.
* This creates my own subrecord and also performs the master selection phase,
* which causes other modules to create their subrecords.
*/
GLOBAL void
jpeg_compress (compress_info_ptr cinfo)
jinit_master_compress (j_compress_ptr cinfo)
{
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
my_master_ptr master;
/* Read the input file header: determine image size & component count.
* NOTE: the user interface must have initialized the input_init method
* pointer (eg, by calling jselrppm) before calling me.
* The other file reading methods (get_input_row etc.) were probably
* set at the same time, but could be set up by input_init itself,
* or by c_ui_method_selection.
*/
(*cinfo->methods->input_init) (cinfo);
master = (my_master_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_comp_master));
cinfo->master = (struct jpeg_comp_master *) master;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
/* Give UI a chance to adjust compression parameters and select */
/* output file format based on results of input_init. */
(*cinfo->methods->c_ui_method_selection) (cinfo);
/* Now select methods for compression steps. */
initial_setup(cinfo);
c_initial_method_selection(cinfo);
/* Initialize the output file & other modules as needed */
/* (entropy_encoder is inited by pipeline controller) */
(*cinfo->methods->colorin_init) (cinfo);
(*cinfo->methods->write_file_header) (cinfo);
/* And let the pipeline controller do the rest. */
(*cinfo->methods->c_pipeline_controller) (cinfo);
/* Finish output file, release working storage, etc */
(*cinfo->methods->write_file_trailer) (cinfo);
(*cinfo->methods->colorin_term) (cinfo);
(*cinfo->methods->input_term) (cinfo);
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
master_selection(cinfo);
}

212
jcmcu.c
View File

@@ -1,212 +0,0 @@
/*
* jcmcu.c
*
* 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 MCU extraction routines and quantization scaling.
* These routines are invoked via the extract_MCUs and
* extract_init/term methods.
*/
#include "jinclude.h"
/*
* If this file is compiled with -DDCT_ERR_STATS, it will reverse-DCT each
* block and sum the total errors across the whole picture. This provides
* a convenient method of using real picture data to test the roundoff error
* of a DCT algorithm. DCT_ERR_STATS should *not* be defined for a production
* compression program, since compression is much slower with it defined.
* Also note that jrevdct.o must be linked into the compressor when this
* switch is defined.
*/
#ifdef DCT_ERR_STATS
static int dcterrorsum; /* these hold the error statistics */
static int dcterrormax;
static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine */
#endif
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
static const short ZAG[DCTSIZE2] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
LOCAL void
extract_block (JSAMPARRAY input_data, int start_row, long start_col,
JBLOCK output_data, QUANT_TBL_PTR quanttbl)
/* Extract one 8x8 block from the specified location in the sample array; */
/* perform forward DCT, quantization scaling, and zigzag reordering on it. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
DCTBLOCK block;
#ifdef DCT_ERR_STATS
DCTBLOCK svblock; /* saves input data for comparison */
#endif
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
#if DCTSIZE != 8
register short elemc;
#endif
register short elemr;
for (elemr = DCTSIZE; elemr > 0; elemr--) {
elemptr = input_data[start_row++] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
#else
for (elemc = DCTSIZE; elemc > 0; elemc--) {
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
}
#endif
}
}
#ifdef DCT_ERR_STATS
memcpy((void *) svblock, (void *) block, SIZEOF(DCTBLOCK));
#endif
j_fwd_dct(block);
{ register JCOEF temp;
register short i;
for (i = 0; i < DCTSIZE2; i++) {
temp = (JCOEF) block[ZAG[i]];
/* divide by *quanttbl, ensuring proper rounding */
if (temp < 0) {
temp = -temp;
temp += *quanttbl>>1;
temp /= *quanttbl;
temp = -temp;
} else {
temp += *quanttbl>>1;
temp /= *quanttbl;
}
*output_data++ = temp;
quanttbl++;
}
}
#ifdef DCT_ERR_STATS
j_rev_dct(block);
{ register int diff;
register short i;
for (i = 0; i < DCTSIZE2; i++) {
diff = block[i] - svblock[i];
if (diff < 0) diff = -diff;
dcterrorsum += diff;
if (dcterrormax < diff) dcterrormax = diff;
}
dctcoefcount += DCTSIZE2;
}
#endif
}
/*
* Extract samples in MCU order, process & hand off to output_method.
* The input is always exactly N MCU rows worth of data.
*/
METHODDEF void
extract_MCUs (compress_info_ptr cinfo,
JSAMPIMAGE image_data,
int num_mcu_rows,
MCU_output_method_ptr output_method)
{
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
int mcurow;
long mcuindex;
short blkn, ci, xpos, ypos;
jpeg_component_info * compptr;
QUANT_TBL_PTR quant_ptr;
for (mcurow = 0; mcurow < num_mcu_rows; mcurow++) {
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Extract data from the image array, DCT it, and quantize it */
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
extract_block(image_data[ci],
(mcurow * compptr->MCU_height + ypos)*DCTSIZE,
(mcuindex * compptr->MCU_width + xpos)*DCTSIZE,
MCU_data[blkn], quant_ptr);
blkn++;
}
}
}
/* Send the MCU whereever the pipeline controller wants it to go */
(*output_method) (cinfo, MCU_data);
}
}
}
/*
* Initialize for processing a scan.
*/
METHODDEF void
extract_init (compress_info_ptr cinfo)
{
/* no work for now */
#ifdef DCT_ERR_STATS
dcterrorsum = dcterrormax = dctcoefcount = 0;
#endif
}
/*
* Clean up after a scan.
*/
METHODDEF void
extract_term (compress_info_ptr cinfo)
{
/* no work for now */
#ifdef DCT_ERR_STATS
TRACEMS3(cinfo->emethods, 0, "DCT roundoff errors = %d/%d, max = %d",
dcterrorsum, dctcoefcount, dcterrormax);
#endif
}
/*
* The method selection routine for MCU extraction.
*/
GLOBAL void
jselcmcu (compress_info_ptr cinfo)
{
/* just one implementation for now */
cinfo->methods->extract_init = extract_init;
cinfo->methods->extract_MCUs = extract_MCUs;
cinfo->methods->extract_term = extract_term;
}

94
jcomapi.c Normal file
View File

@@ -0,0 +1,94 @@
/*
* jcomapi.c
*
* Copyright (C) 1994, 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 application interface routines that are used for both
* compression and decompression.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Abort processing of a JPEG compression or decompression operation,
* but don't destroy the object itself.
*
* For this, we merely clean up all the nonpermanent memory pools.
* Note that temp files (virtual arrays) are not allowed to belong to
* the permanent pool, so we will be able to close all temp files here.
* Closing a data source or destination, if necessary, is the application's
* responsibility.
*/
GLOBAL void
jpeg_abort (j_common_ptr cinfo)
{
int pool;
/* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
(*cinfo->mem->free_pool) (cinfo, pool);
}
/* Reset overall state for possible reuse of object */
cinfo->global_state = (cinfo->is_decompressor ? DSTATE_START : CSTATE_START);
}
/*
* Destruction of a JPEG object.
*
* Everything gets deallocated except the master jpeg_compress_struct itself
* and the error manager struct. Both of these are supplied by the application
* and must be freed, if necessary, by the application. (Often they are on
* the stack and so don't need to be freed anyway.)
* Closing a data source or destination, if necessary, is the application's
* responsibility.
*/
GLOBAL void
jpeg_destroy (j_common_ptr cinfo)
{
/* We need only tell the memory manager to release everything. */
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
if (cinfo->mem != NULL)
(*cinfo->mem->self_destruct) (cinfo);
cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
cinfo->global_state = 0; /* mark it destroyed */
}
/*
* Convenience routines for allocating quantization and Huffman tables.
* (Would jutils.c be a more reasonable place to put these?)
*/
GLOBAL JQUANT_TBL *
jpeg_alloc_quant_table (j_common_ptr cinfo)
{
JQUANT_TBL *tbl;
tbl = (JQUANT_TBL *)
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
tbl->sent_table = FALSE; /* make sure this is false in any new table */
return tbl;
}
GLOBAL JHUFF_TBL *
jpeg_alloc_huff_table (j_common_ptr cinfo)
{
JHUFF_TBL *tbl;
tbl = (JHUFF_TBL *)
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
tbl->sent_table = FALSE; /* make sure this is false in any new table */
return tbl;
}

44
jconfig.auto Normal file
View File

@@ -0,0 +1,44 @@
/* jconfig.auto --- source file edited by configure script */
/* see jconfig.doc for explanations */
#undef HAVE_PROTOTYPES
#undef HAVE_UNSIGNED_CHAR
#undef HAVE_UNSIGNED_SHORT
#undef void
#undef const
#undef CHAR_IS_UNSIGNED
#undef HAVE_STDDEF_H
#undef HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS
#undef NEED_SHORT_EXTERNAL_NAMES
/* Define this if you get warnings about undefined structures. */
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#undef INLINE
/* These are for configuring the JPEG memory manager. */
#undef DEFAULT_MAX_MEM
#undef NO_MKTEMP
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#undef TWO_FILE_COMMANDLINE
#undef NEED_SIGNAL_CATCHER
#undef DONT_USE_B_MODE
/* Define this if you want percent-done progress reports from cjpeg/djpeg. */
#undef PROGRESS_REPORT
#endif /* JPEG_CJPEG_DJPEG */

44
jconfig.bcc Normal file
View File

@@ -0,0 +1,44 @@
/* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#define NEED_FAR_POINTERS /* for small or medium memory model */
#undef NEED_SHORT_EXTERNAL_NAMES
#define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */
#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */
#define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE
#define USE_SETMODE /* Borland has setmode() */
#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

38
jconfig.dj Normal file
View File

@@ -0,0 +1,38 @@
/* jconfig.dj --- jconfig.h for DJGPP (Delorie's GNU C port) on MS-DOS. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#undef TWO_FILE_COMMANDLINE /* optional */
#define USE_SETMODE /* Needed to make one-file style work in DJGPP */
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

155
jconfig.doc Normal file
View File

@@ -0,0 +1,155 @@
/*
* jconfig.doc
*
* Copyright (C) 1991-1994, 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 documents the configuration options that are required to
* customize the JPEG software for a particular system.
*
* The actual configuration options for a particular installation are stored
* in jconfig.h. On many machines, jconfig.h can be generated automatically
* or copied from one of the "canned" jconfig files that we supply. But if
* you need to generate a jconfig.h file by hand, this file tells you how.
*
* DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
* EDIT A COPY NAMED JCONFIG.H.
*/
/*
* These symbols indicate the properties of your machine or compiler.
* #define the symbol if yes, #undef it if no.
*/
/* Does your compiler support function prototypes?
* (If not, you also need to use ansi2knr, see install.doc)
*/
#define HAVE_PROTOTYPES
/* Does your compiler support the declaration "unsigned char" ?
* How about "unsigned short" ?
*/
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define "const" as empty if your compiler doesn't know the "const" keyword.
*/
/* #define const */
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
*/
#undef CHAR_IS_UNSIGNED
/* Define this if your system has an ANSI-conforming <stddef.h> file.
*/
#define HAVE_STDDEF_H
/* Define this if your system has an ANSI-conforming <stdlib.h> file.
*/
#define HAVE_STDLIB_H
/* Define this if your system does not have an ANSI/SysV <string.h>,
* but does have a BSD-style <strings.h>.
*/
#undef NEED_BSD_STRINGS
/* Define this if your system does not provide typedef size_t in any of the
* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
* <sys/types.h> instead.
*/
#undef NEED_SYS_TYPES_H
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
* unless you are using a large-data memory model or 80386 flat-memory mode.
* On less brain-damaged CPUs this symbol must not be defined.
* (Defining this symbol causes large data structures to be referenced through
* "far" pointers and to be allocated with a special version of malloc.)
*/
#undef NEED_FAR_POINTERS
/* Define this if your linker needs global names to be unique in less
* than the first 15 characters.
*/
#undef NEED_SHORT_EXTERNAL_NAMES
/* Although a real ANSI C compiler can deal perfectly well with pointers to
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
* define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
* actually get "missing structure definition" warnings or errors while
* compiling the JPEG code.
*/
#undef INCOMPLETE_TYPES_BROKEN
/*
* The following options affect code selection within the JPEG library,
* but they don't need to be visible to applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS has been defined.
*/
#ifdef JPEG_INTERNALS
/* 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.
*/
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
/*
* The remaining options do not affect the JPEG library proper,
* but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
* Other applications can ignore these.
*/
#ifdef JPEG_CJPEG_DJPEG
/* These defines indicate which image (non-JPEG) file formats are allowed. */
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
/* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if
* your system can't cope with binary I/O to stdin/stdout. See comments at
* head of cjpeg.c or djpeg.c.
*/
#undef TWO_FILE_COMMANDLINE
/* 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.
*/
#undef NEED_SIGNAL_CATCHER
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
* This is necessary on systems that distinguish text files from binary files,
* and is harmless on most systems that don't. If you have one of the rare
* systems that complains about the "b" spec, define this symbol.
*/
#undef DONT_USE_B_MODE
/* Define this if you want percent-done progress reports from cjpeg/djpeg.
*/
#undef PROGRESS_REPORT
#endif /* JPEG_CJPEG_DJPEG */

339
jconfig.h
View File

@@ -1,339 +0,0 @@
/*
* jconfig.h
*
* 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 preprocessor declarations that help customize
* the JPEG software for a particular application, machine, or compiler.
* Edit these declarations as needed (or add -D flags to the Makefile).
*/
/*
* These symbols indicate the properties of your machine or compiler.
* The conditional definitions given may do the right thing already,
* but you'd best look them over closely, especially if your compiler
* does not handle full ANSI C. An ANSI-compliant C compiler should
* provide all the necessary features; __STDC__ is supposed to be
* predefined by such compilers.
*/
/*
* 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 HAVE_STDC /* ANSI C compilers always have prototypes */
#define PROTO
#else
#ifdef __cplusplus /* So do C++ compilers */
#define PROTO
#endif
#endif
/* Does your compiler support the declaration "unsigned char" ? */
/* How about "unsigned short" ? */
#ifdef HAVE_STDC /* ANSI C compilers must support both */
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
#endif
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then it doesn't matter very much.
*/
/* #define CHAR_IS_UNSIGNED */
/* Define this if your compiler implements ">>" on signed values as a logical
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
* which is the normal and rational definition.
*/
/* #define RIGHT_SHIFT_IS_UNSIGNED */
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define const as empty if your compiler doesn't know the "const" keyword. */
/* (Even if it does, defining const as empty won't break anything.) */
#ifndef HAVE_STDC /* ANSI C and C++ compilers should know it. */
#ifndef __cplusplus
#define const
#endif
#endif
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
* unless you are using a large-data memory model or 80386 flat-memory mode.
* On less brain-damaged CPUs this symbol must not be defined.
* (Defining this symbol causes large data structures to be referenced through
* "far" pointers and to be allocated with a special version of malloc.)
*/
#ifdef MSDOS
#define NEED_FAR_POINTERS
#endif
/* 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.
*/
/* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if
* your system can't cope with binary I/O to stdin/stdout. See comments at
* head of jcmain.c or jdmain.c.
*/
#ifdef MSDOS /* two-file style is needed for PCs */
#define TWO_FILE_COMMANDLINE
#endif
#ifdef THINK_C /* 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
* systems that complains about the "b" spec, define this symbol.
*/
/* #define DONT_USE_B_MODE */
/* If you're getting bored, that's the end of the symbols you HAVE to
* worry about. Go fix the makefile and compile.
*/
/* On a few systems, type boolean and/or macros FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* In that case you need only comment out these definitions.
*/
typedef int boolean;
#undef FALSE /* in case these macros already exist */
#undef TRUE
#define FALSE 0 /* values of boolean */
#define TRUE 1
/* This defines the size of the I/O buffers for entropy compression
* and decompression; you could reduce it if memory is tight.
*/
#define JPEG_BUF_SIZE 4096 /* bytes */
/* These symbols determine the JPEG functionality supported. */
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* program file. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
#undef ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#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 (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.) */
/* more capability options later, no doubt */
/*
* Define exactly one of these three symbols to indicate whether you want
* 8-bit, 12-bit, or 16-bit sample (pixel component) values. 8-bit is the
* default and is nearly always the right thing to use. You can use 12-bit if
* you need to support image formats with more than 8 bits of resolution in a
* color value. 16-bit should only be used for the lossless JPEG mode (not
* currently supported). Note that 12- and 16-bit values take up twice as
* much memory as 8-bit!
* 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
#undef TWELVE_BIT_SAMPLES
#undef SIXTEEN_BIT_SAMPLES
/*
* The remaining definitions don't need to be hand-edited in most cases.
* You may need to change these if you have a machine with unusual data
* types; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* First define the representation of a single pixel element value. */
#ifdef EIGHT_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
* If you have only signed chars, and you are more worried about speed than
* memory usage, it might be a win to make JSAMPLE be short.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not CHAR_IS_UNSIGNED */
typedef char JSAMPLE;
#define GETJSAMPLE(value) ((value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define BITS_IN_JSAMPLE 8
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* EIGHT_BIT_SAMPLES */
#ifdef TWELVE_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..4095. */
/* On nearly all machines "short" will do nicely. */
typedef short JSAMPLE;
#define GETJSAMPLE(value) (value)
#define BITS_IN_JSAMPLE 12
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* TWELVE_BIT_SAMPLES */
#ifdef SIXTEEN_BIT_SAMPLES
/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short JSAMPLE;
#define GETJSAMPLE(value) (value)
#else /* not HAVE_UNSIGNED_SHORT */
/* If int is 32 bits this'll be horrendously inefficient storage-wise.
* But since we don't actually support 16-bit samples (ie lossless coding) yet,
* I'm not going to worry about making a smarter definition ...
*/
typedef unsigned int JSAMPLE;
#define GETJSAMPLE(value) (value)
#endif /* HAVE_UNSIGNED_SHORT */
#define BITS_IN_JSAMPLE 16
#define MAXJSAMPLE 65535
#define CENTERJSAMPLE 32768
#endif /* SIXTEEN_BIT_SAMPLES */
/* Here we define the representation of a DCT frequency coefficient.
* This should be a signed 16-bit value; "short" is usually right.
* It's important that this be exactly 16 bits, no more and no less;
* more will cost you a BIG hit of memory, less will give wrong answers.
*/
typedef short JCOEF;
/* The remaining typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char UINT8;
#else /* not CHAR_IS_UNSIGNED */
typedef short UINT8;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold signed 32-bit values; if your machine happens */
/* to have 64-bit longs, you might want to change this. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
typedef long INT32;
#endif

43
jconfig.manx Normal file
View File

@@ -0,0 +1,43 @@
/* jconfig.manx --- jconfig.h for Amiga systems using Manx Aztec C ver 5.x. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */
#define SHORTxSHORT_32 /* produces better DCT code with Aztec C */
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE
#define NEED_SIGNAL_CATCHER
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#define signal_catcher _abort /* hack for Aztec C naming requirements */
#endif /* JPEG_CJPEG_DJPEG */

52
jconfig.mc6 Normal file
View File

@@ -0,0 +1,52 @@
/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#define NEED_FAR_POINTERS /* for small or medium memory model */
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */
#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */
#define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */
#define NEED_FHEAPMIN /* far heap management routines are broken */
#define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */
/* Note: the above define is known to improve the code with Microsoft C 6.00A.
* I do not know whether it is good for later compiler versions.
* Please report any info on this point to jpeg-info@uunet.uu.net.
*/
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE
#define USE_SETMODE /* Microsoft has setmode() */
#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

43
jconfig.sas Normal file
View File

@@ -0,0 +1,43 @@
/* jconfig.sas --- jconfig.h for Amiga systems using SAS C 6.0 and up. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */
#define NO_MKTEMP /* SAS C doesn't have mktemp() */
#define SHORTxSHORT_32 /* produces better DCT code with SAS C */
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE
#define NEED_SIGNAL_CATCHER
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

39
jconfig.st Normal file
View File

@@ -0,0 +1,39 @@
/* jconfig.st --- jconfig.h for Atari ST/STE/TT using Pure C or Turbo C. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS
#undef NEED_SHORT_EXTERNAL_NAMES
#define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#define ALIGN_TYPE long /* apparently double is a weird size? */
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE /* optional -- undef if you like Unix style */
#define NEED_SIGNAL_CATCHER /* needed if you use jmemname.c */
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

37
jconfig.vms Normal file
View File

@@ -0,0 +1,37 @@
/* jconfig.vms --- jconfig.h for use on Digital VMS. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#define TWO_FILE_COMMANDLINE /* Needed on VMS */
#undef NEED_SIGNAL_CATCHER
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */

443
jcparam.c Normal file
View File

@@ -0,0 +1,443 @@
/*
* jcparam.c
*
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains optional default-setting code for the JPEG compressor.
* Applications do not have to use this file, but those that don't use it
* must know a lot more about the innards of the JPEG code.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Quantization table setup routines
*/
GLOBAL void
jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
const unsigned int *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.
*/
{
JQUANT_TBL ** qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
int i;
long temp;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (*qtblptr == NULL)
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
for (i = 0; i < DCTSIZE2; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
(*qtblptr)->quantval[i] = (UINT16) temp;
}
/* Initialize sent_table FALSE so table will be written to JPEG file. */
(*qtblptr)->sent_table = FALSE;
}
GLOBAL void
jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for
* applications that insist on a linear percentage scaling.
*/
{
/* 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.
*/
static const unsigned int 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 unsigned int 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
};
/* Set up two quantization tables using the specified scaling */
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
scale_factor, force_baseline);
}
GLOBAL int
jpeg_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;
/* 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 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.
*/
if (quality < 50)
quality = 5000 / quality;
else
quality = 200 - quality*2;
return quality;
}
GLOBAL void
jpeg_set_quality (j_compress_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 three routines directly.
*/
{
/* Convert user 0-100 rating to percentage scaling */
quality = jpeg_quality_scaling(quality);
/* Set up standard quality tables */
jpeg_set_linear_quality(cinfo, quality, force_baseline);
}
/*
* Huffman table setup routines
*/
LOCAL void
add_huff_table (j_compress_ptr cinfo,
JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
/* Define a Huffman table */
{
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
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. */
(*htblptr)->sent_table = FALSE;
}
LOCAL void
std_huff_tables (j_compress_ptr cinfo)
/* 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 bits_dc_luminance[17] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
static const UINT8 val_dc_luminance[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 bits_dc_chrominance[17] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static const UINT8 val_dc_chrominance[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static const UINT8 bits_ac_luminance[17] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static const UINT8 val_ac_luminance[] =
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static const UINT8 bits_ac_chrominance[17] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static const UINT8 val_ac_chrominance[] =
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
bits_dc_luminance, val_dc_luminance);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
bits_ac_luminance, val_ac_luminance);
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
bits_dc_chrominance, val_dc_chrominance);
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
bits_ac_chrominance, val_ac_chrominance);
}
/*
* Default parameter setup for compression.
*
* Applications that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* is the recommended approach since, if we add any new parameters,
* your code will still work (they'll be set to reasonable defaults).
*/
GLOBAL void
jpeg_set_defaults (j_compress_ptr cinfo)
{
int i;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Allocate comp_info array large enough for maximum component count.
* Array is made permanent in case application wants to compress
* multiple images at same param settings.
*/
if (cinfo->comp_info == NULL)
cinfo->comp_info = (jpeg_component_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
MAX_COMPONENTS * SIZEOF(jpeg_component_info));
/* Initialize everything not dependent on the color space */
cinfo->data_precision = BITS_IN_JSAMPLE;
/* Set up two quantization tables using default quality of 75 */
jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */
std_huff_tables(cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo->arith_dc_L[i] = 0;
cinfo->arith_dc_U[i] = 1;
cinfo->arith_ac_K[i] = 5;
}
/* Expect normal source image, not raw downsampled data */
cinfo->raw_data_in = FALSE;
/* Use Huffman coding, not arithmetic coding, by default */
cinfo->arith_code = FALSE;
/* Color images are interleaved by default */
cinfo->interleave = TRUE;
/* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE;
/* 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;
/* By default, use the simpler non-cosited sampling alignment */
cinfo->CCIR601_sampling = FALSE;
/* No input smoothing */
cinfo->smoothing_factor = 0;
/* DCT algorithm preference */
cinfo->dct_method = JDCT_DEFAULT;
/* No restart markers */
cinfo->restart_interval = 0;
cinfo->restart_in_rows = 0;
/* Fill in default JFIF marker parameters. Note that whether the marker
* will actually be written is determined by jpeg_set_colorspace.
*/
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;
/* Choose JPEG colorspace based on input space, set defaults accordingly */
jpeg_default_colorspace(cinfo);
}
/*
* Select an appropriate JPEG colorspace for in_color_space.
*/
GLOBAL void
jpeg_default_colorspace (j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
case JCS_RGB:
jpeg_set_colorspace(cinfo, JCS_YCbCr);
break;
case JCS_YCbCr:
jpeg_set_colorspace(cinfo, JCS_YCbCr);
break;
case JCS_CMYK:
jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
break;
case JCS_YCCK:
jpeg_set_colorspace(cinfo, JCS_YCCK);
break;
case JCS_UNKNOWN:
jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
break;
default:
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
}
}
/*
* Set the JPEG colorspace, and choose colorspace-dependent default values.
*/
GLOBAL void
jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
{
jpeg_component_info * compptr;
int ci;
#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
(compptr = &cinfo->comp_info[index], \
compptr->component_index = (index), \
compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \
compptr->v_samp_factor = (vsamp), \
compptr->quant_tbl_no = (quant), \
compptr->dc_tbl_no = (dctbl), \
compptr->ac_tbl_no = (actbl) )
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* For all colorspaces, we use Q and Huff tables 0 for luminance components,
* tables 1 for chrominance components.
*/
cinfo->jpeg_color_space = colorspace;
cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
switch (colorspace) {
case JCS_GRAYSCALE:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 1;
/* JFIF specifies component ID 1 */
SET_COMP(0, 1, 1,1, 0, 0,0);
break;
case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3;
SET_COMP(0, 'R', 1,1, 0, 0,0);
SET_COMP(1, 'G', 1,1, 0, 0,0);
SET_COMP(2, 'B', 1,1, 0, 0,0);
break;
case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 1,1, 1, 1,1);
SET_COMP(2, 3, 1,1, 1, 1,1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4;
SET_COMP(0, 'C', 1,1, 0, 0,0);
SET_COMP(1, 'M', 1,1, 0, 0,0);
SET_COMP(2, 'Y', 1,1, 0, 0,0);
SET_COMP(3, 'K', 1,1, 0, 0,0);
break;
case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4;
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 1,1, 1, 1,1);
SET_COMP(2, 3, 1,1, 1, 1,1);
SET_COMP(3, 4, 2,2, 0, 0,0);
break;
case JCS_UNKNOWN:
cinfo->num_components = cinfo->input_components;
if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
for (ci = 0; ci < cinfo->num_components; ci++) {
SET_COMP(ci, ci, 1,1, 0, 0,0);
}
break;
default:
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
}
}

720
jcpipe.c
View File

@@ -1,720 +0,0 @@
/*
* jcpipe.c
*
* 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 compression pipeline controllers.
* These routines are invoked via the c_pipeline_controller method.
*
* There are four basic pipeline controllers, one for each combination of:
* single-scan JPEG file (single component or fully interleaved)
* vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
*
* optimization of entropy encoding parameters
* vs. usage of default encoding parameters.
*
* Note that these conditions determine the needs for "big" arrays:
* multiple scans imply a big array for splitting the color components;
* entropy encoding optimization needs a big array for the MCU data.
*
* All but the simplest controller (single-scan, no optimization) can be
* compiled out through configuration options, if you need to make a minimal
* implementation.
*/
#include "jinclude.h"
/*
* About the data structures:
*
* The processing chunk size for subsampling is referred to in this file as
* a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
* any component after subsampling, or Vmax (max_v_samp_factor) unsubsampled
* rows. In an interleaved scan each MCU row contains exactly DCTSIZE row
* groups of each component in the scan. In a noninterleaved scan an MCU row
* is one row of blocks, which might not be an integral number of row groups;
* for convenience we use a buffer of the same size as in interleaved scans,
* and process Vk MCU rows in each burst of subsampling.
* To provide context for the subsampling step, we have to retain the last
* two row groups of the previous MCU row while reading in the next MCU row
* (or set of Vk MCU rows). To do this without copying data about, we create
* a rather strange data structure. Exactly DCTSIZE+2 row groups of samples
* are allocated, but we create two different sets of pointers to this array.
* The second set swaps the last two pairs of row groups. By working
* alternately with the two sets of pointers, we can access the data in the
* desired order.
*/
/*
* Utility routines: common code for pipeline controllers
*/
LOCAL void
interleaved_scan_setup (compress_info_ptr cinfo)
/* Compute all derived info for an interleaved (multi-component) scan */
/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
{
short ci, mcublks;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->MCUs_per_row = (cinfo->image_width
+ cinfo->max_h_samp_factor*DCTSIZE - 1)
/ (cinfo->max_h_samp_factor*DCTSIZE);
cinfo->MCU_rows_in_scan = (cinfo->image_height
+ cinfo->max_v_samp_factor*DCTSIZE - 1)
/ (cinfo->max_v_samp_factor*DCTSIZE);
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* for interleaved scan, sampling factors give # of blocks per component */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
/* compute physical dimensions of component */
compptr->subsampled_width = jround_up(compptr->true_comp_width,
(long) (compptr->MCU_width*DCTSIZE));
compptr->subsampled_height = jround_up(compptr->true_comp_height,
(long) (compptr->MCU_height*DCTSIZE));
/* Sanity check */
if (compptr->subsampled_width !=
(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
ERREXIT(cinfo->emethods, "I'm confused about the image width");
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
LOCAL void
noninterleaved_scan_setup (compress_info_ptr cinfo)
/* Compute all derived info for a noninterleaved (single-component) scan */
/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
{
jpeg_component_info *compptr = cinfo->cur_comp_info[0];
/* for noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
/* compute physical dimensions of component */
compptr->subsampled_width = jround_up(compptr->true_comp_width,
(long) DCTSIZE);
compptr->subsampled_height = jround_up(compptr->true_comp_height,
(long) DCTSIZE);
cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
}
LOCAL void
alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
long fullsize_width)
/* Create a pre-subsampling data buffer having the desired structure */
/* (see comments at head of file) */
{
short ci, vs, i;
vs = cinfo->max_v_samp_factor; /* row group height */
/* Get top-level space for array pointers */
fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
/* Allocate the real storage */
fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
(fullsize_width,
(long) (vs * (DCTSIZE+2)));
/* Create space for the scrambled-order pointers */
fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
(vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
/* Duplicate the first DCTSIZE-2 row groups */
for (i = 0; i < vs * (DCTSIZE-2); i++) {
fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
}
/* Copy the last four row groups in swapped order */
for (i = 0; i < vs * 2; i++) {
fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
}
}
}
#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;
for (ci = 0; ci < cinfo->num_components; ci++) {
/* Free the real storage */
(*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
/* Free the scrambled-order pointers */
(*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
}
/* Free the top-level space */
(*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
(*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
}
#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). */
/* above, current, below are indexes of row groups in fullsize_data; */
/* out is the index of the target row group in subsampled_data. */
/* Special case: above, below can be -1 to indicate top, bottom of image. */
{
jpeg_component_info *compptr;
JSAMPARRAY above_ptr, below_ptr;
JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
short ci, vs, i;
vs = cinfo->max_v_samp_factor; /* row group height */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = & cinfo->comp_info[ci];
if (above >= 0)
above_ptr = fullsize_data[ci] + above * vs;
else {
/* Top of image: make a dummy above-context with copies of 1st row */
/* We assume current=0 in this case */
for (i = 0; i < vs; i++)
dummy[i] = fullsize_data[ci][0];
above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
}
if (below >= 0)
below_ptr = fullsize_data[ci] + below * vs;
else {
/* Bot of image: make a dummy below-context with copies of last row */
for (i = 0; i < vs; i++)
dummy[i] = fullsize_data[ci][(current+1)*vs-1];
below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
}
(*cinfo->methods->subsample[ci])
(cinfo, (int) ci,
fullsize_width, (int) vs,
compptr->subsampled_width, (int) compptr->v_samp_factor,
above_ptr,
fullsize_data[ci] + current * vs,
below_ptr,
subsampled_data[ci] + out * compptr->v_samp_factor);
}
}
/* These vars are initialized by the pipeline controller for use by
* MCU_output_catcher.
* To avoid a lot of row-pointer overhead, we cram as many MCUs into each
* row of whole_scan_MCUs as we can get without exceeding 64KB per row.
*/
#define MAX_WHOLE_ROW_BLOCKS ((int) (65500 / SIZEOF(JBLOCK))) /* max blocks/row */
static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
static int MCUs_in_big_row; /* # of MCUs in each row of whole_scan_MCUs */
static long next_whole_row; /* next row to access in whole_scan_MCUs */
static int next_MCU_index; /* next MCU in current row */
METHODDEF void
MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
/* Output method for siphoning off extract_MCUs output into a big array */
{
static JBLOCKARRAY rowptr;
if (next_MCU_index >= MCUs_in_big_row) {
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
next_whole_row, TRUE);
next_whole_row++;
next_MCU_index = 0;
}
/*
* note that on 80x86, the cast applied to MCU_data implies
* near to far pointer conversion.
*/
jcopy_block_row((JBLOCKROW) MCU_data,
rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
(long) cinfo->blocks_in_MCU);
next_MCU_index++;
}
METHODDEF void
dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
/* The method may be either the entropy encoder or some routine supplied */
/* by the entropy optimizer. */
{
/* On an 80x86 machine, the entropy encoder expects the passed data block
* to be in NEAR memory (for performance reasons), so we have to copy it
* back from the big array to a local array. On less brain-damaged CPUs
* we needn't do that.
*/
#ifdef NEED_FAR_POINTERS
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
#endif
long mcurow, mcuindex, next_row;
int next_index;
JBLOCKARRAY rowptr = NULL; /* init only to suppress compiler complaint */
next_row = 0;
next_index = MCUs_in_big_row;
for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
(*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,
next_row, FALSE);
next_row++;
next_index = 0;
}
#ifdef NEED_FAR_POINTERS
jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
(JBLOCKROW) MCU_data, /* casts near to far pointer! */
(long) cinfo->blocks_in_MCU);
(*output_method) (cinfo, MCU_data);
#else
(*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
#endif
next_index++;
}
}
cinfo->completed_passes++;
}
/*
* Compression pipeline controller used for single-scan files
* with no optimization of entropy parameters.
*/
METHODDEF void
single_ccontroller (compress_info_ptr cinfo)
{
int rows_in_mem; /* # of sample rows in full-size buffers */
long fullsize_width; /* # of samples per row in full-size buffers */
long cur_pixel_row; /* counts # of pixel rows processed */
long mcu_rows_output; /* # of MCU rows actually emitted */
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
/* Work buffer for pre-subsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for subsampled data */
JSAMPIMAGE subsampled_data;
int rows_this_time;
short ci, whichss, i;
/* Prepare for single scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
if (cinfo->comps_in_scan == 1) {
noninterleaved_scan_setup(cinfo);
/* Vk block rows constitute the same number of MCU rows */
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
} else {
interleaved_scan_setup(cinfo);
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
cinfo->total_passes++;
/* Compute dimensions of full-size pixel buffers */
/* Note these are the same whether interleaved or not. */
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
fullsize_width = jround_up(cinfo->image_width,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before subsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* subsampled_data is sample data after subsampling */
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].subsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
/* Tell the memory manager to instantiate big arrays.
* We don't need any big arrays in this controller,
* but some other module (like the input file reader) may need one.
*/
(*cinfo->emethods->alloc_big_arrays)
((long) 0, /* no more small sarrays */
(long) 0, /* no more small barrays */
(long) 0); /* no more "medium" objects */
/* Initialize output file & do per-scan object init */
(*cinfo->methods->write_scan_header) (cinfo);
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
(*cinfo->methods->entropy_encoder_init) (cinfo);
(*cinfo->methods->subsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
mcu_rows_output = 0;
whichss = 1; /* arrange to start with fullsize_data[0] */
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*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. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
fullsize_data[whichss]);
(*cinfo->methods->edge_expand) (cinfo,
cinfo->image_width, rows_this_time,
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Subsample the data (all components) */
/* First time through is a special case */
if (cur_pixel_row) {
/* Subsample last row group of previous set */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's subsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
mcu_rows_per_loop,
cinfo->methods->entropy_encode);
mcu_rows_output += mcu_rows_per_loop;
/* Subsample first row group of this set */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (DCTSIZE+1), (short) 0, (short) 1,
(short) 0);
} else {
/* Subsample first row group with dummy above-context */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Subsample second through next-to-last row groups of this set */
for (i = 1; i <= DCTSIZE-2; i++) {
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (i-1), (short) i, (short) (i+1),
(short) i);
}
} /* end of outer loop */
/* Subsample the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* Dump the remaining data (may be less than full height if uninterleaved) */
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
cinfo->methods->entropy_encode);
/* Finish output file */
(*cinfo->methods->extract_term) (cinfo);
(*cinfo->methods->subsample_term) (cinfo);
(*cinfo->methods->entropy_encoder_term) (cinfo);
(*cinfo->methods->write_scan_trailer) (cinfo);
cinfo->completed_passes++;
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
/*
* Compression pipeline controller used for single-scan files
* with optimization of entropy parameters.
*/
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF void
single_eopt_ccontroller (compress_info_ptr cinfo)
{
int rows_in_mem; /* # of sample rows in full-size buffers */
long fullsize_width; /* # of samples per row in full-size buffers */
long cur_pixel_row; /* counts # of pixel rows processed */
long mcu_rows_output; /* # of MCU rows actually emitted */
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
/* Work buffer for pre-subsampling data (see comments at head of file) */
JSAMPIMAGE fullsize_data[2];
/* Work buffer for subsampled data */
JSAMPIMAGE subsampled_data;
int rows_this_time;
int blocks_in_big_row;
short ci, whichss, i;
/* Prepare for single scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
if (cinfo->comps_in_scan == 1) {
noninterleaved_scan_setup(cinfo);
/* Vk block rows constitute the same number of MCU rows */
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
} else {
interleaved_scan_setup(cinfo);
/* in an interleaved scan, one MCU row contains Vk block rows */
mcu_rows_per_loop = 1;
}
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. */
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
fullsize_width = jround_up(cinfo->image_width,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
/* Allocate working memory: */
/* fullsize_data is sample data before subsampling */
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
/* subsampled_data is sample data after subsampling */
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(JSAMPARRAY));
for (ci = 0; ci < cinfo->num_components; ci++) {
subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
(cinfo->comp_info[ci].subsampled_width,
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
}
/* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
/* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
((long) blocks_in_big_row,
(long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
+ MCUs_in_big_row-1) / MCUs_in_big_row,
1L); /* unit height is 1 row */
next_whole_row = 0; /* init output ptr for MCU_output_catcher */
next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
/* Tell the memory manager to instantiate big arrays */
(*cinfo->emethods->alloc_big_arrays)
((long) 0, /* no more small sarrays */
(long) 0, /* no more small barrays */
(long) 0); /* no more "medium" objects */
/* Do per-scan object init */
(*cinfo->methods->subsample_init) (cinfo);
(*cinfo->methods->extract_init) (cinfo);
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
/* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
mcu_rows_output = 0;
whichss = 1; /* arrange to start with fullsize_data[0] */
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
cur_pixel_row += rows_in_mem) {
(*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. */
rows_this_time = (int) MIN((long) rows_in_mem,
cinfo->image_height - cur_pixel_row);
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
fullsize_data[whichss]);
(*cinfo->methods->edge_expand) (cinfo,
cinfo->image_width, rows_this_time,
fullsize_width, rows_in_mem,
fullsize_data[whichss]);
/* Subsample the data (all components) */
/* First time through is a special case */
if (cur_pixel_row) {
/* Subsample last row group of previous set */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
(short) (DCTSIZE-1));
/* and dump the previous set's subsampled data */
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
mcu_rows_per_loop,
MCU_output_catcher);
mcu_rows_output += mcu_rows_per_loop;
/* Subsample first row group of this set */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (DCTSIZE+1), (short) 0, (short) 1,
(short) 0);
} else {
/* Subsample first row group with dummy above-context */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (-1), (short) 0, (short) 1,
(short) 0);
}
/* Subsample second through next-to-last row groups of this set */
for (i = 1; i <= DCTSIZE-2; i++) {
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (i-1), (short) i, (short) (i+1),
(short) i);
}
} /* end of outer loop */
/* Subsample the last row group with dummy below-context */
/* Note whichss points to last buffer side used */
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
(short) (DCTSIZE-1));
/* Dump the remaining data (may be less than full height if uninterleaved) */
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
MCU_output_catcher);
/* Clean up after that stuff, then find the optimal entropy parameters */
(*cinfo->methods->extract_term) (cinfo);
(*cinfo->methods->subsample_term) (cinfo);
cinfo->completed_passes++;
(*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
/* Emit scan to output file */
/* Note: we can't do write_scan_header until entropy parameters are set! */
(*cinfo->methods->write_scan_header) (cinfo);
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
(*cinfo->methods->entropy_encoder_init) (cinfo);
dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
(*cinfo->methods->entropy_encoder_term) (cinfo);
(*cinfo->methods->write_scan_trailer) (cinfo);
/* Release working memory */
/* (no work -- we let free_all release what's needful) */
}
#endif /* ENTROPY_OPT_SUPPORTED */
/*
* Compression pipeline controller used for multiple-scan files
* with no optimization of entropy parameters.
*/
#ifdef MULTISCAN_FILES_SUPPORTED
METHODDEF void
multi_ccontroller (compress_info_ptr cinfo)
{
ERREXIT(cinfo->emethods, "Not implemented yet");
}
#endif /* MULTISCAN_FILES_SUPPORTED */
/*
* Compression pipeline controller used for multiple-scan files
* with optimization of entropy parameters.
*/
#ifdef MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF void
multi_eopt_ccontroller (compress_info_ptr cinfo)
{
ERREXIT(cinfo->emethods, "Not implemented yet");
}
#endif /* ENTROPY_OPT_SUPPORTED */
#endif /* MULTISCAN_FILES_SUPPORTED */
/*
* The method selection routine for compression pipeline controllers.
*/
GLOBAL void
jselcpipeline (compress_info_ptr cinfo)
{
if (cinfo->interleave || cinfo->num_components == 1) {
/* single scan needed */
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->optimize_coding)
cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
else
#endif
cinfo->methods->c_pipeline_controller = single_ccontroller;
} else {
/* multiple scans needed */
#ifdef MULTISCAN_FILES_SUPPORTED
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->optimize_coding)
cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
else
#endif
cinfo->methods->c_pipeline_controller = multi_ccontroller;
#else
ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
#endif
}
}

371
jcprepct.c Normal file
View File

@@ -0,0 +1,371 @@
/*
* jcprepct.c
*
* Copyright (C) 1994, 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 compression preprocessing controller.
* This controller manages the color conversion, downsampling,
* and edge expansion steps.
*
* Most of the complexity here is associated with buffering input rows
* as required by the downsampler. See the comments at the head of
* jcsample.c for the downsampler's needs.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* At present, jcsample.c can request context rows only for smoothing.
* In the future, we might also need context rows for CCIR601 sampling
* or other more-complex downsampling procedures. The code to support
* context rows should be compiled only if needed.
*/
#ifdef INPUT_SMOOTHING_SUPPORTED
#define CONTEXT_ROWS_SUPPORTED
#endif
/*
* For the simple (no-context-row) case, we just need to buffer one
* row group's worth of pixels for the downsampling step. At the bottom of
* the image, we pad to a full row group by replicating the last pixel row.
* The downsampler's last output row is then replicated if needed to pad
* out to a full iMCU row.
*
* When providing context rows, we must buffer three row groups' worth of
* pixels. Three row groups are physically allocated, but the row pointer
* arrays are made five row groups high, with the extra pointers above and
* below "wrapping around" to point to the last and first real row groups.
* This allows the downsampler to access the proper context rows.
* At the top and bottom of the image, we create dummy context rows by
* copying the first or last real pixel row. This copying could be avoided
* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
* trouble on the compression side.
*/
/* Private buffer controller object */
typedef struct {
struct jpeg_c_prep_controller pub; /* public fields */
/* Downsampling input buffer. This buffer holds color-converted data
* until we have enough to do a downsample step.
*/
JSAMPARRAY color_buf[MAX_COMPONENTS];
JDIMENSION rows_to_go; /* counts rows remaining in source image */
int next_buf_row; /* index of next row to store in color_buf */
#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
int this_row_group; /* starting row index of group to process */
int next_buf_stop; /* downsample when we reach this index */
#endif
} my_prep_controller;
typedef my_prep_controller * my_prep_ptr;
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
if (pass_mode != JBUF_PASS_THRU)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
/* Initialize total-height counter for detecting bottom of image */
prep->rows_to_go = cinfo->image_height;
/* Mark the conversion buffer empty */
prep->next_buf_row = 0;
#ifdef CONTEXT_ROWS_SUPPORTED
/* Preset additional state variables for context mode.
* These aren't used in non-context mode, so we needn't test which mode.
*/
prep->this_row_group = 0;
/* Set next_buf_stop to stop after two row groups have been read in. */
prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
#endif
}
/*
* Expand an image vertically from height input_rows to height output_rows,
* by duplicating the bottom row.
*/
LOCAL void
expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
int input_rows, int output_rows)
{
register int row;
for (row = input_rows; row < output_rows; row++) {
jcopy_sample_rows(image_data, input_rows-1, image_data, row,
1, num_cols);
}
}
/*
* Process some data in the simple no-context case.
*
* Preprocessor output data is counted in "row groups". A row group
* is defined to be v_samp_factor sample rows of each component.
* Downsampling will produce this much data from each max_v_samp_factor
* input rows.
*/
METHODDEF void
pre_process_data (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int numrows, ci;
JDIMENSION inrows;
jpeg_component_info * compptr;
while (*in_row_ctr < in_rows_avail &&
*out_row_group_ctr < out_row_groups_avail) {
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
numrows = (int) MIN((JDIMENSION) numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
(JDIMENSION) prep->next_buf_row,
numrows);
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
prep->rows_to_go -= numrows;
/* If at bottom of image, pad to fill the conversion buffer. */
if (prep->rows_to_go == 0 &&
prep->next_buf_row < cinfo->max_v_samp_factor) {
for (ci = 0; ci < cinfo->num_components; ci++) {
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
prep->next_buf_row, cinfo->max_v_samp_factor);
}
prep->next_buf_row = cinfo->max_v_samp_factor;
}
/* If we've filled the conversion buffer, empty it. */
if (prep->next_buf_row == cinfo->max_v_samp_factor) {
(*cinfo->downsample->downsample) (cinfo,
prep->color_buf, (JDIMENSION) 0,
output_buf, *out_row_group_ctr);
prep->next_buf_row = 0;
(*out_row_group_ctr)++;
}
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
if (prep->rows_to_go == 0 &&
*out_row_group_ctr < out_row_groups_avail) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
expand_bottom_edge(output_buf[ci],
compptr->width_in_blocks * DCTSIZE,
(int) (*out_row_group_ctr * compptr->v_samp_factor),
(int) (out_row_groups_avail * compptr->v_samp_factor));
}
*out_row_group_ctr = out_row_groups_avail;
break; /* can exit outer loop without test */
}
}
}
#ifdef CONTEXT_ROWS_SUPPORTED
/*
* Process some data in the context case.
*/
METHODDEF void
pre_process_context (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int numrows, ci;
int buf_height = cinfo->max_v_samp_factor * 3;
JDIMENSION inrows;
jpeg_component_info * compptr;
while (*out_row_group_ctr < out_row_groups_avail) {
if (*in_row_ctr < in_rows_avail) {
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = prep->next_buf_stop - prep->next_buf_row;
numrows = (int) MIN((JDIMENSION) numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
(JDIMENSION) prep->next_buf_row,
numrows);
/* Pad at top of image, if first time through */
if (prep->rows_to_go == cinfo->image_height) {
for (ci = 0; ci < cinfo->num_components; ci++) {
int row;
for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
jcopy_sample_rows(prep->color_buf[ci], 0,
prep->color_buf[ci], -row,
1, cinfo->image_width);
}
}
}
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
prep->rows_to_go -= numrows;
} else {
/* Return for more data, unless we are at the bottom of the image. */
if (prep->rows_to_go != 0)
break;
}
/* If at bottom of image, pad to fill the conversion buffer. */
if (prep->rows_to_go == 0 &&
prep->next_buf_row < prep->next_buf_stop) {
for (ci = 0; ci < cinfo->num_components; ci++) {
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
prep->next_buf_row, prep->next_buf_stop);
}
prep->next_buf_row = prep->next_buf_stop;
}
/* If we've gotten enough data, downsample a row group. */
if (prep->next_buf_row == prep->next_buf_stop) {
(*cinfo->downsample->downsample) (cinfo,
prep->color_buf,
(JDIMENSION) prep->this_row_group,
output_buf, *out_row_group_ctr);
(*out_row_group_ctr)++;
/* Advance pointers with wraparound as necessary. */
prep->this_row_group += cinfo->max_v_samp_factor;
if (prep->this_row_group >= buf_height)
prep->this_row_group = 0;
if (prep->next_buf_row >= buf_height)
prep->next_buf_row = 0;
prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
}
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
if (prep->rows_to_go == 0 &&
*out_row_group_ctr < out_row_groups_avail) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
expand_bottom_edge(output_buf[ci],
compptr->width_in_blocks * DCTSIZE,
(int) (*out_row_group_ctr * compptr->v_samp_factor),
(int) (out_row_groups_avail * compptr->v_samp_factor));
}
*out_row_group_ctr = out_row_groups_avail;
break; /* can exit outer loop without test */
}
}
}
/*
* Create the wrapped-around downsampling input buffer needed for context mode.
*/
LOCAL void
create_context_buffer (j_compress_ptr cinfo)
{
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
int rgroup_height = cinfo->max_v_samp_factor;
int ci, i;
jpeg_component_info * compptr;
JSAMPARRAY true_buffer, fake_buffer;
/* Grab enough space for fake row pointers for all the components;
* we need five row groups' worth of pointers for each component.
*/
fake_buffer = (JSAMPARRAY)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(cinfo->num_components * 5 * rgroup_height) *
SIZEOF(JSAMPROW));
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Allocate the actual buffer space (3 row groups) for this component.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
true_buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
(JDIMENSION) (3 * rgroup_height));
/* Copy true buffer row pointers into the middle of the fake row array */
MEMCOPY(fake_buffer + rgroup_height, true_buffer,
3 * rgroup_height * SIZEOF(JSAMPROW));
/* Fill in the above and below wraparound pointers */
for (i = 0; i < rgroup_height; i++) {
fake_buffer[i] = true_buffer[2 * rgroup_height + i];
fake_buffer[4 * rgroup_height + i] = true_buffer[i];
}
prep->color_buf[ci] = fake_buffer + rgroup_height;
fake_buffer += 5 * rgroup_height; /* point to space for next component */
}
}
#endif /* CONTEXT_ROWS_SUPPORTED */
/*
* Initialize preprocessing controller.
*/
GLOBAL void
jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
{
my_prep_ptr prep;
int ci;
jpeg_component_info * compptr;
if (need_full_buffer) /* safety check */
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
prep = (my_prep_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_prep_controller));
cinfo->prep = (struct jpeg_c_prep_controller *) prep;
prep->pub.start_pass = start_pass_prep;
/* Allocate the color conversion buffer.
* We make the buffer wide enough to allow the downsampler to edge-expand
* horizontally within the buffer, if it so chooses.
*/
if (cinfo->downsample->need_context_rows) {
/* Set up to provide context rows */
#ifdef CONTEXT_ROWS_SUPPORTED
prep->pub.pre_process_data = pre_process_context;
create_context_buffer(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
/* No context, just make it tall enough for one row group */
prep->pub.pre_process_data = pre_process_data;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
(JDIMENSION) cinfo->max_v_samp_factor);
}
}
}

View File

@@ -1,67 +1,171 @@
/*
* jcsample.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, 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.
*
* Downsampling input data is counted in "row groups". A row group
* is defined to be max_v_samp_factor pixel rows of each component,
* from which the downsampler produces v_samp_factor sample rows.
* A single row group is processed in each call to the downsampler module.
*
* The downsampler is responsible for edge-expansion of its output data
* to fill an integral number of DCT blocks horizontally. The source buffer
* may be modified if it is helpful for this purpose (the source buffer is
* allocated wide enough to correspond to the desired output width).
* The caller (the prep controller) is responsible for vertical padding.
*
* The downsampler may request "context rows" by setting need_context_rows
* during startup. In this case, the input arrays will contain at least
* one row group's worth of pixels above and below the passed-in data;
* the caller will create dummy rows at image top and bottom by replicating
* the first or last real pixel row.
*
* 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.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Pointer to routine to downsample a single component */
typedef JMETHOD(void, downsample1_ptr,
(j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data));
/* Private subobject */
typedef struct {
struct jpeg_downsampler pub; /* public fields */
/* Downsampling method pointers, one per component */
downsample1_ptr methods[MAX_COMPONENTS];
} my_downsampler;
typedef my_downsampler * my_downsample_ptr;
/*
* Initialize for subsampling a scan.
* Initialize for a downsampling pass.
*/
METHODDEF void
subsample_init (compress_info_ptr cinfo)
start_pass_downsample (j_compress_ptr cinfo)
{
/* no work for now */
}
/*
* Subsample pixel values of a single component.
* This version only handles integral sampling ratios.
* Expand a component horizontally from width input_cols to width output_cols,
* by duplicating the rightmost samples.
*/
LOCAL void
expand_right_edge (JSAMPARRAY image_data, int num_rows,
JDIMENSION input_cols, JDIMENSION output_cols)
{
register JSAMPROW ptr;
register JSAMPLE pixval;
register int count;
int row;
int numcols = (int) (output_cols - input_cols);
if (numcols > 0) {
for (row = 0; row < num_rows; row++) {
ptr = image_data[row] + input_cols;
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
for (count = numcols; count > 0; count--)
*ptr++ = pixval;
}
}
}
/*
* Do downsampling for a whole row group (all components).
*
* In this version we simply downsample each component independently.
*/
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)
sep_downsample (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
{
my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
int ci;
jpeg_component_info * compptr;
JSAMPARRAY in_ptr, out_ptr;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
in_ptr = input_buf[ci] + in_row_index;
out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
}
}
/*
* Downsample pixel values of a single component.
* One row group is processed per call.
* This version handles arbitrary integral sampling ratios, without smoothing.
* Note that this version is not actually used for customary sampling ratios.
*/
METHODDEF void
int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, 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;
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
JSAMPROW inptr, outptr;
INT32 outvalue;
/* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
if (output_rows != compptr->v_samp_factor ||
input_rows != cinfo->max_v_samp_factor ||
(output_cols % compptr->h_samp_factor) != 0 ||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
ERREXIT(cinfo->emethods, "Bogus subsample parameters");
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
numpix = h_expand * v_expand;
numpix2 = numpix/2;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * h_expand);
inrow = 0;
for (outrow = 0; outrow < output_rows; outrow++) {
for (outrow = 0; outrow < compptr->v_samp_factor; 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,62 +178,342 @@ 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 special case of a full-size component,
* 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)
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
if (input_cols != output_cols || input_rows != output_rows) /* DEBUG */
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
/* Copy the data */
jcopy_sample_rows(input_data, 0, output_data, 0,
cinfo->max_v_samp_factor, cinfo->image_width);
/* Edge-expand */
expand_right_edge(output_data, cinfo->max_v_samp_factor,
cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
}
/*
* Clean up after a scan.
* Downsample pixel values of a single component.
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
* without smoothing.
*
* A note about the "bias" calculations: when rounding fractional values to
* integer, we do not want to always round 0.5 up to the next integer.
* If we did that, we'd introduce a noticeable bias towards larger values.
* Instead, this code is arranged so that 0.5 will be rounded up or down at
* alternate pixel locations (a simple ordered dither pattern).
*/
METHODDEF void
subsample_term (compress_info_ptr cinfo)
h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
/* no work for now */
int outrow;
JDIMENSION outcol;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr, outptr;
register int bias;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * 2);
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
bias = 0; /* bias = 0,1,0,1,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ bias) >> 1);
bias ^= 1; /* 0=>1, 1=>0 */
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 (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION outcol;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr0, inptr1, outptr;
register int bias;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data, cinfo->max_v_samp_factor,
cinfo->image_width, output_cols * 2);
inrow = 0;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
bias = 1; /* bias = 1,2,1,2,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ bias) >> 2);
bias ^= 3; /* 1=>2, 2=>1 */
inptr0 += 2; inptr1 += 2;
}
inrow += 2;
}
}
#ifdef INPUT_SMOOTHING_SUPPORTED
/*
* The method selection routine for subsampling.
* Downsample pixel values of a single component.
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
* with smoothing. One row of context is required.
*/
METHODDEF void
h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION colctr;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
cinfo->image_width, output_cols * 2);
/* 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 < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
inptr1 = input_data[inrow+1];
above_ptr = input_data[inrow-1];
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 + 32768) >> 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 + 32768) >> 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 + 32768) >> 16);
inrow += 2;
}
}
/*
* Downsample pixel values of a single component.
* This version handles the special case of a full-size component,
* with smoothing. One row of context is required.
*/
METHODDEF void
fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
JDIMENSION colctr;
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
register JSAMPROW inptr, above_ptr, below_ptr, outptr;
INT32 membersum, neighsum, memberscale, neighscale;
int colsum, lastcolsum, nextcolsum;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
cinfo->image_width, output_cols);
/* 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 < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
above_ptr = input_data[outrow-1];
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 + 32768) >> 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 + 32768) >> 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 + 32768) >> 16);
}
}
#endif /* INPUT_SMOOTHING_SUPPORTED */
/*
* Module initialization routine for downsampling.
* Note that we must select a routine for each component.
*/
GLOBAL void
jselsubsample (compress_info_ptr cinfo)
jinit_downsampler (j_compress_ptr cinfo)
{
short ci;
my_downsample_ptr downsample;
int ci;
jpeg_component_info * compptr;
boolean smoothok = TRUE;
downsample = (my_downsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_downsampler));
cinfo->downsample = (struct jpeg_downsampler *) downsample;
downsample->pub.start_pass = start_pass_downsample;
downsample->pub.downsample = sep_downsample;
downsample->pub.need_context_rows = FALSE;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Verify we can handle the sampling factors, and set up method pointers */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
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) {
downsample->methods[ci] = fullsize_smooth_downsample;
downsample->pub.need_context_rows = TRUE;
} else
#endif
downsample->methods[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;
downsample->methods[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) {
downsample->methods[ci] = h2v2_smooth_downsample;
downsample->pub.need_context_rows = TRUE;
} else
#endif
downsample->methods[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;
downsample->methods[ci] = int_downsample;
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
}
cinfo->methods->subsample_init = subsample_init;
cinfo->methods->subsample_term = subsample_term;
#ifdef INPUT_SMOOTHING_SUPPORTED
if (cinfo->smoothing_factor && !smoothok)
TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
#endif
}

438
jdapi.c Normal file
View File

@@ -0,0 +1,438 @@
/*
* jdapi.c
*
* Copyright (C) 1994, 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 application interface code for the decompression half of
* the JPEG library. Most of the routines intended to be called directly by
* an application are in this file. But also see jcomapi.c for routines
* shared by compression and decompression.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* Initialization of a JPEG decompression object.
* The error manager must already be set up (in case memory manager fails).
*/
GLOBAL void
jpeg_create_decompress (j_decompress_ptr cinfo)
{
int i;
/* For debugging purposes, zero the whole master structure.
* But error manager pointer is already there, so save and restore it.
*/
{
struct jpeg_error_mgr * err = cinfo->err;
MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
cinfo->err = err;
}
cinfo->is_decompressor = TRUE;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr((j_common_ptr) cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
cinfo->src = 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->sample_range_limit = NULL;
/* Initialize marker processor so application can override methods
* for COM, APPn markers before calling jpeg_read_header.
*/
cinfo->marker = NULL;
jinit_marker_reader(cinfo);
/* OK, I'm ready */
cinfo->global_state = DSTATE_START;
}
/*
* Destruction of a JPEG decompression object
*/
GLOBAL void
jpeg_destroy_decompress (j_decompress_ptr cinfo)
{
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
}
/*
* Install a special processing method for COM or APPn markers.
*/
GLOBAL void
jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
jpeg_marker_parser_method routine)
{
if (marker_code == JPEG_COM)
cinfo->marker->process_COM = routine;
else if (marker_code >= JPEG_APP0 && marker_code <= JPEG_APP0+15)
cinfo->marker->process_APPn[marker_code-JPEG_APP0] = routine;
else
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
}
/*
* Set default decompression parameters.
*/
LOCAL void
default_decompress_parms (j_decompress_ptr cinfo)
{
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
/* Note application may override our guesses. */
switch (cinfo->num_components) {
case 1:
cinfo->jpeg_color_space = JCS_GRAYSCALE;
cinfo->out_color_space = JCS_GRAYSCALE;
break;
case 3:
if (cinfo->saw_JFIF_marker) {
cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
} else if (cinfo->saw_Adobe_marker) {
switch (cinfo->Adobe_transform) {
case 0:
cinfo->jpeg_color_space = JCS_RGB;
break;
case 1:
cinfo->jpeg_color_space = JCS_YCbCr;
break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
break;
}
} else {
/* Saw no special markers, try to guess from the component IDs */
int cid0 = cinfo->comp_info[0].component_id;
int cid1 = cinfo->comp_info[1].component_id;
int cid2 = cinfo->comp_info[2].component_id;
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
else {
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
}
}
/* Always guess RGB is proper output colorspace. */
cinfo->out_color_space = JCS_RGB;
break;
case 4:
if (cinfo->saw_Adobe_marker) {
switch (cinfo->Adobe_transform) {
case 0:
cinfo->jpeg_color_space = JCS_CMYK;
break;
case 2:
cinfo->jpeg_color_space = JCS_YCCK;
break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
break;
}
} else {
/* No special markers, assume straight CMYK. */
cinfo->jpeg_color_space = JCS_CMYK;
}
cinfo->out_color_space = JCS_CMYK;
break;
default:
cinfo->jpeg_color_space = JCS_UNKNOWN;
cinfo->out_color_space = JCS_UNKNOWN;
break;
}
/* Set defaults for other decompression parameters. */
cinfo->scale_num = 1; /* 1:1 scaling */
cinfo->scale_denom = 1;
cinfo->output_gamma = 1.0;
cinfo->raw_data_out = FALSE;
cinfo->quantize_colors = FALSE;
/* We set these in case application only sets quantize_colors. */
cinfo->two_pass_quantize = TRUE;
cinfo->dither_mode = JDITHER_FS;
cinfo->desired_number_of_colors = 256;
cinfo->colormap = NULL;
/* DCT algorithm preference */
cinfo->dct_method = JDCT_DEFAULT;
cinfo->do_fancy_upsampling = TRUE;
}
/*
* Decompression startup: read start of JPEG datastream to see what's there.
* Need only initialize JPEG object and supply a data source before calling.
*
* This routine will read as far as the first SOS marker (ie, actual start of
* compressed data), and will save all tables and parameters in the JPEG
* object. It will also initialize the decompression parameters to default
* values, and finally return JPEG_HEADER_OK. On return, the application may
* adjust the decompression parameters and then call jpeg_start_decompress.
* (Or, if the application only wanted to determine the image parameters,
* the data need not be decompressed. In that case, call jpeg_abort or
* jpeg_destroy to release any temporary space.)
* If an abbreviated (tables only) datastream is presented, the routine will
* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
* re-use the JPEG object to read the abbreviated image datastream(s).
* It is unnecessary (but OK) to call jpeg_abort in this case.
* The JPEG_SUSPENDED return code only occurs if the data source module
* requests suspension of the decompressor. In this case the application
* should load more source data and then re-call jpeg_read_header to resume
* processing.
* If a non-suspending data source is used and require_image is TRUE, then the
* return code need not be inspected since only JPEG_HEADER_OK is possible.
*/
GLOBAL int
jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
{
int retcode;
if (cinfo->global_state == DSTATE_START) {
/* First-time actions: reset appropriate modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
(*cinfo->marker->reset_marker_reader) (cinfo);
(*cinfo->src->init_source) (cinfo);
cinfo->global_state = DSTATE_INHEADER;
} else if (cinfo->global_state != DSTATE_INHEADER) {
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
retcode = (*cinfo->marker->read_markers) (cinfo);
switch (retcode) {
case JPEG_HEADER_OK: /* Found SOS, prepare to decompress */
/* Set up default parameters based on header data */
default_decompress_parms(cinfo);
/* Set global state: ready for start_decompress */
cinfo->global_state = DSTATE_READY;
break;
case JPEG_HEADER_TABLES_ONLY: /* Found EOI before any SOS */
if (cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOF_NO_SOS);
if (require_image) /* Complain if application wants an image */
ERREXIT(cinfo, JERR_NO_IMAGE);
/* We need not do any cleanup since only permanent storage (for DQT, DHT)
* has been allocated.
*/
/* Set global state: ready for a new datastream */
cinfo->global_state = DSTATE_START;
break;
case JPEG_SUSPENDED: /* Had to suspend before end of headers */
/* no work */
break;
}
return retcode;
}
/*
* Decompression initialization.
* jpeg_read_header must be completed before calling this.
*
* If a multipass operating mode was selected, this will do all but the
* last pass, and thus may take a great deal of time.
*/
GLOBAL void
jpeg_start_decompress (j_decompress_ptr cinfo)
{
JDIMENSION chunk_ctr, last_chunk_ctr;
if (cinfo->global_state != DSTATE_READY)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Perform master selection of active modules */
jinit_master_decompress(cinfo);
/* Do all but the final (output) pass, and set up for that one. */
for (;;) {
(*cinfo->master->prepare_for_pass) (cinfo);
if (cinfo->master->is_last_pass)
break;
chunk_ctr = 0;
while (chunk_ctr < cinfo->main->num_chunks) {
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) chunk_ctr;
cinfo->progress->pass_limit = (long) cinfo->main->num_chunks;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Process some data */
last_chunk_ctr = chunk_ctr;
(*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
&chunk_ctr, (JDIMENSION) 0);
if (chunk_ctr == last_chunk_ctr) /* check for failure to make progress */
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
(*cinfo->master->finish_pass) (cinfo);
}
/* Ready for application to drive last pass through jpeg_read_scanlines
* or jpeg_read_raw_data.
*/
cinfo->output_scanline = 0;
cinfo->global_state = (cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING);
}
/*
* Read some scanlines of data from the JPEG decompressor.
*
* The return value will be the number of lines actually read.
* This may be less than the number requested in several cases,
* including bottom of image, data source suspension, and operating
* modes that emit multiple scanlines at a time.
*
* Note: we warn about excess calls to jpeg_read_scanlines() since
* this likely signals an application programmer error. However,
* an oversize buffer (max_lines > scanlines remaining) is not an error.
*/
GLOBAL JDIMENSION
jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
JDIMENSION max_lines)
{
JDIMENSION row_ctr;
if (cinfo->global_state != DSTATE_SCANNING)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->output_scanline >= cinfo->output_height)
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
cinfo->progress->pass_limit = (long) cinfo->output_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Process some data */
row_ctr = 0;
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
cinfo->output_scanline += row_ctr;
return row_ctr;
}
/*
* Alternate entry point to read raw data.
* Processes exactly one MCU row per call.
*/
GLOBAL JDIMENSION
jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION max_lines)
{
JDIMENSION lines_per_MCU_row;
if (cinfo->global_state != DSTATE_RAW_OK)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (cinfo->output_scanline >= cinfo->output_height) {
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
cinfo->progress->pass_limit = (long) cinfo->output_height;
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
}
/* Verify that at least one MCU row can be returned. */
lines_per_MCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
if (max_lines < lines_per_MCU_row)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Decompress directly into user's buffer. */
if (! (*cinfo->coef->decompress_data) (cinfo, data))
return 0; /* suspension forced, can do nothing more */
/* OK, we processed one MCU row. */
cinfo->output_scanline += lines_per_MCU_row;
return lines_per_MCU_row;
}
/*
* Finish JPEG decompression.
*
* This will normally just verify the file trailer and release temp storage.
*
* Returns FALSE if suspended. The return value need be inspected only if
* a suspending data source is used.
*/
GLOBAL boolean
jpeg_finish_decompress (j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) {
/* Terminate final pass */
if (cinfo->output_scanline < cinfo->output_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
(*cinfo->master->finish_pass) (cinfo);
cinfo->global_state = DSTATE_STOPPING;
} else if (cinfo->global_state != DSTATE_STOPPING) {
/* Repeat call after a suspension? */
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Check for EOI in source file, unless master control already read it */
if (! cinfo->master->eoi_processed) {
switch ((*cinfo->marker->read_markers) (cinfo)) {
case JPEG_HEADER_OK: /* Found SOS!? */
ERREXIT(cinfo, JERR_EOI_EXPECTED);
break;
case JPEG_HEADER_TABLES_ONLY: /* Found EOI, A-OK */
break;
case JPEG_SUSPENDED: /* Suspend, come back later */
return FALSE;
}
}
/* Do final cleanup */
(*cinfo->src->term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort((j_common_ptr) cinfo);
return TRUE;
}
/*
* Abort processing of a JPEG decompression operation,
* but don't destroy the object itself.
*/
GLOBAL void
jpeg_abort_decompress (j_decompress_ptr cinfo)
{
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
}

View File

@@ -1,42 +0,0 @@
/*
* jdarith.c
*
* 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.
*/
#include "jinclude.h"
#ifdef ARITH_CODING_SUPPORTED
/*
* The arithmetic coding option of the JPEG standard specifies Q-coding,
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
* At this time it does not appear to be legal for the Independent JPEG
* Group to distribute software that implements arithmetic coding.
* We have therefore removed arithmetic coding support from the
* distributed source code.
*
* We're not happy about it either.
*/
/*
* The method selection routine for arithmetic entropy decoding.
*/
GLOBAL void
jseldarithmetic (decompress_info_ptr cinfo)
{
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
}
}
#endif /* ARITH_CODING_SUPPORTED */

151
jdatadst.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* jdatadst.c
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains compression data destination routines for the case of
* emitting JPEG data to a file (or any stdio stream). While these routines
* are sufficient for most applications, some will want to use a different
* destination manager.
* IMPORTANT: we assume that fwrite() will correctly transcribe an array of
* JOCTETs into 8-bit-wide elements on external storage. If char is wider
* than 8 bits on your machine, you may need to do some tweaking.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/* Expanded data destination object for stdio output */
typedef struct {
struct jpeg_destination_mgr pub; /* public fields */
FILE * outfile; /* target stream */
JOCTET * buffer; /* start of buffer */
} my_destination_mgr;
typedef my_destination_mgr * my_dest_ptr;
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
METHODDEF void
init_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
METHODDEF boolean
empty_output_buffer (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
(size_t) OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF void
term_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
if (datacount > 0) {
if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
}
fflush(dest->outfile);
/* Make sure we wrote the output file OK */
if (ferror(dest->outfile))
ERREXIT(cinfo, JERR_FILE_WRITE);
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
GLOBAL void
jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
{
my_dest_ptr dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_destination_mgr));
}
dest = (my_dest_ptr) cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->outfile = outfile;
}

209
jdatasrc.c Normal file
View File

@@ -0,0 +1,209 @@
/*
* jdatasrc.c
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains decompression data source routines for the case of
* reading JPEG data from a file (or any stdio stream). While these routines
* are sufficient for most applications, some will want to use a different
* source manager.
* IMPORTANT: we assume that fread() will correctly transcribe an array of
* JOCTETs from 8-bit-wide elements on external storage. If char is wider
* than 8 bits on your machine, you may need to do some tweaking.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/* Expanded data source object for stdio input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
FILE * infile; /* source stream */
JOCTET * buffer; /* start of buffer */
boolean start_of_file; /* have we gotten any data yet? */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
METHODDEF void
init_source (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
* This is correct behavior for reading a series of images from one source.
*/
src->start_of_file = TRUE;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In typical applications, this should read fresh data into the buffer
* (ignoring the current state of next_input_byte & bytes_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been reloaded. It is not necessary to
* fill the buffer entirely, only to obtain at least one more byte.
*
* There is no such thing as an EOF return. If the end of the file has been
* reached, the routine has a choice of ERREXIT() or inserting fake data into
* the buffer. In most cases, generating a warning message and inserting a
* fake EOI marker is the best course of action --- this will allow the
* decompressor to output however much of the image is there. However,
* the resulting error message is misleading if the real problem is an empty
* input file, so we handle that case specially.
*
* In applications that need to be able to suspend compression due to input
* not being available yet, a FALSE return indicates that no more data can be
* obtained right now, but more may be forthcoming later. In this situation,
* the decompressor will return to its caller (with an indication of the
* number of scanlines it has read, if any). The application should resume
* decompression after it has loaded more data into the input buffer. Note
* that there are substantial restrictions on the use of suspension --- see
* the documentation.
*
* When suspending, the decompressor will back up to a convenient restart point
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point must be rescanned after resumption, so move it to
* the front of the buffer rather than discarding it.
*/
METHODDEF boolean
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
size_t nbytes;
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
nbytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
METHODDEF void
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
* it doesn't work on pipes. Not clear that being smart is worth
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) fill_input_buffer(cinfo);
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF void
term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
GLOBAL void
jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
{
my_src_ptr src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
src = (my_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * SIZEOF(JOCTET));
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = infile;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
}

359
jdcoefct.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* jdcoefct.c
*
* Copyright (C) 1994, 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 coefficient buffer controller for decompression.
* This controller is the top level of the JPEG decompressor proper.
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private buffer controller object */
typedef struct {
struct jpeg_d_coef_controller pub; /* public fields */
JDIMENSION MCU_col_num; /* saves next MCU column to process */
JDIMENSION MCU_row_num; /* keep track of MCU row # within image */
/* In single-pass modes without block smoothing, it's sufficient to buffer
* just one MCU (although this may prove a bit slow in practice).
* We allocate a workspace of MAX_BLOCKS_IN_MCU coefficient blocks,
* and let the entropy decoder write into that workspace each time.
* (On 80x86, the workspace is FAR even though it's not really very big;
* this is to keep the module interfaces unchanged when a large coefficient
* buffer is necessary.)
* In multi-pass modes, this array points to the current MCU's blocks
* within the virtual arrays.
*/
JBLOCKROW MCU_buffer[MAX_BLOCKS_IN_MCU];
/* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
} my_coef_controller;
typedef my_coef_controller * my_coef_ptr;
/* Forward declarations */
METHODDEF boolean decompress_data
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
#ifdef D_MULTISCAN_FILES_SUPPORTED
METHODDEF boolean decompress_read
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
METHODDEF boolean decompress_output
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_coef (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
coef->MCU_col_num = 0;
coef->MCU_row_num = 0;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (coef->whole_image[0] != NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.decompress_data = decompress_data;
break;
#ifdef D_MULTISCAN_FILES_SUPPORTED
case JBUF_SAVE_SOURCE:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.decompress_data = decompress_read;
break;
case JBUF_CRANK_DEST:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.decompress_data = decompress_output;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data in the single-pass case.
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
* Returns TRUE if it completed a row, FALSE if not (suspension).
*
* NB: output_buf contains a plane for each component in image.
* For single pass, this is the same as the components in the scan.
*/
METHODDEF boolean
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_MCU_row = cinfo->MCU_rows_in_scan - 1;
int blkn, ci, xindex, yindex, useful_width;
JSAMPARRAY output_ptr;
JDIMENSION start_col, output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
/* Loop to process as much as one whole MCU row */
for (MCU_col_num = coef->MCU_col_num; MCU_col_num <= last_MCU_col;
MCU_col_num++) {
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
jzero_far((void FAR *) coef->MCU_buffer[0],
(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; return with row unfinished */
coef->MCU_col_num = MCU_col_num; /* update my state */
return FALSE;
}
/* Determine where data should go in output_buf and do the IDCT thing.
* We skip dummy blocks at the right and bottom edges (but blkn gets
* incremented past them!). Note the inner loop relies on having
* allocated the MCU_buffer[] blocks sequentially.
*/
blkn = 0; /* index of current DCT block within MCU */
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) {
blkn += compptr->MCU_blocks;
continue;
}
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
: compptr->last_col_width;
output_ptr = output_buf[ci];
start_col = MCU_col_num * compptr->MCU_sample_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->MCU_row_num < last_MCU_row ||
yindex < compptr->last_row_height) {
output_col = start_col;
for (xindex = 0; xindex < useful_width; xindex++) {
(*inverse_DCT) (cinfo, compptr,
(JCOEFPTR) coef->MCU_buffer[blkn+xindex],
output_ptr, output_col);
output_col += compptr->DCT_scaled_size;
}
}
blkn += compptr->MCU_width;
output_ptr += compptr->DCT_scaled_size;
}
}
}
/* We finished the row successfully */
coef->MCU_col_num = 0; /* prepare for next row */
coef->MCU_row_num++;
return TRUE;
}
#ifdef D_MULTISCAN_FILES_SUPPORTED
/*
* Process some data: handle an input pass for a multiple-scan file.
* We read the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the scan.
* No data is returned; we just stash it in the virtual arrays.
*
* Returns TRUE if it completed a row, FALSE if not (suspension).
* Currently, the suspension case is not supported.
*/
METHODDEF boolean
decompress_read (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset, num_MCU_rows;
JDIMENSION total_width, remaining_rows, start_col;
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
JBLOCKROW buffer_ptr;
jpeg_component_info *compptr;
/* Align the virtual buffers for the components used in this scan. */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
coef->MCU_row_num * compptr->v_samp_factor, TRUE);
/* Entropy decoder expects buffer to be zeroed. */
total_width = (JDIMENSION) jround_up((long) compptr->width_in_blocks,
(long) compptr->h_samp_factor);
for (yindex = 0; yindex < compptr->v_samp_factor; yindex++) {
jzero_far((void FAR *) buffer[ci][yindex],
(size_t) (total_width * SIZEOF(JBLOCK)));
}
}
/* In an interleaved scan, we process exactly one MCU row.
* In a noninterleaved scan, we need to process v_samp_factor MCU rows,
* each of which contains a single block row.
*/
if (cinfo->comps_in_scan == 1) {
compptr = cinfo->cur_comp_info[0];
num_MCU_rows = compptr->v_samp_factor;
/* but watch out for the bottom of the image */
remaining_rows = cinfo->MCU_rows_in_scan -
coef->MCU_row_num * compptr->v_samp_factor;
if (remaining_rows < (JDIMENSION) num_MCU_rows)
num_MCU_rows = (int) remaining_rows;
} else {
num_MCU_rows = 1;
}
/* Loop to process one whole iMCU row */
for (yoffset = 0; yoffset < num_MCU_rows; yoffset++) {
for (MCU_col_num = 0; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) {
/* Construct list of pointers to DCT blocks belonging to this MCU */
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to fetch the MCU. */
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
ERREXIT(cinfo, JERR_CANT_SUSPEND); /* not supported */
}
}
}
coef->MCU_row_num++;
return TRUE;
}
/*
* Process some data: output from the virtual arrays after reading is done.
* Always emits one fully interleaved MCU row ("iMCU" row).
* Always returns TRUE --- suspension is not possible.
*
* NB: output_buf contains a plane for each component in image.
*/
METHODDEF boolean
decompress_output (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_MCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num;
int ci, block_row, block_rows;
JBLOCKARRAY buffer;
JBLOCKROW buffer_ptr;
JSAMPARRAY output_ptr;
JDIMENSION output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
if (! compptr->component_needed)
continue;
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[ci],
coef->MCU_row_num * compptr->v_samp_factor, FALSE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->MCU_row_num < last_MCU_row)
block_rows = compptr->v_samp_factor;
else {
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
inverse_DCT = cinfo->idct->inverse_DCT[ci];
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row];
output_col = 0;
for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
output_ptr, output_col);
buffer_ptr++;
output_col += compptr->DCT_scaled_size;
}
output_ptr += compptr->DCT_scaled_size;
}
}
coef->MCU_row_num++;
return TRUE;
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */
/*
* Initialize coefficient buffer controller.
*/
GLOBAL void
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
int ci, i;
jpeg_component_info *compptr;
JBLOCKROW buffer;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_coef_controller));
cinfo->coef = (struct jpeg_d_coef_controller *) coef;
coef->pub.start_pass = start_pass_coef;
/* Create the coefficient buffer. */
if (need_full_buffer) {
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
/* Note memmgr implicitly pads the vertical direction. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
(long) compptr->h_samp_factor),
compptr->height_in_blocks,
(JDIMENSION) compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif
} else {
/* We only need a single-MCU buffer. */
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
for (i = 0; i < MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
}
coef->whole_image[0] = NULL; /* flag for no virtual arrays */
}
}

372
jdcolor.c
View File

@@ -1,16 +1,31 @@
/*
* jdcolor.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains output colorspace conversion routines.
* These routines are invoked via the methods color_convert
* and colorout_init/term.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private subobject */
typedef struct {
struct jpeg_color_deconverter pub; /* public fields */
/* Private state for YCC->RGB conversion */
int * Cr_r_tab; /* => table for Cr to R conversion */
int * Cb_b_tab; /* => table for Cb to B conversion */
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
} my_color_deconverter;
typedef my_color_deconverter * my_cconvert_ptr;
/**************** YCbCr -> RGB conversion: most common case **************/
@@ -23,274 +38,337 @@
* 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 Appendix O, draft of 4/10/91.)
* (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^14 (about 4 digits precision); we have to divide
* the products by 2^14, with appropriate rounding, to get the correct answer.
* 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 table entries); 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
* 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.
*/
#define SCALEBITS 14
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
static INT16 * Cr_r_tab; /* => table for Cr to R conversion */
static INT16 * 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.
* Initialize for YCC->RGB colorspace conversion.
*/
METHODDEF void
ycc_rgb_init (decompress_info_ptr cinfo)
ycc_rgb_start (j_decompress_ptr cinfo)
{
#ifdef SIXTEEN_BIT_SAMPLES
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
INT32 i, x2;
#else
int i, x2; /* smart compiler may do 16x16=>32 multiply */
#endif
SHIFT_TEMPS
Cr_r_tab = (INT16 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT16));
Cb_b_tab = (INT16 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT16));
Cr_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
Cb_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
((MAXJSAMPLE+1) * SIZEOF(INT32));
cconvert->Cr_r_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
cconvert->Cb_b_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
cconvert->Cr_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
cconvert->Cb_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(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] = (INT16)
cconvert->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] = (INT16)
cconvert->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;
cconvert->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;
cconvert->Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF;
}
}
/*
* Convert some rows of samples to the output colorspace.
*
* Note that we change from noninterleaved, one-plane-per-component format
* to interleaved-pixel format. The output buffer is therefore three times
* as wide as the input buffer.
* A starting row offset is provided only for the input buffer. The caller
* can easily adjust the passed output_buf value to accommodate any row
* offset required on that side.
*/
METHODDEF void
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
ycc_rgb_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
#ifdef SIXTEEN_BIT_SAMPLES
register UINT16 y, cb, cr;
register INT32 x;
#else
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int y, cb, cr;
register int x;
#endif
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr0, outptr1, outptr2;
long col;
int row;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
register int * Crrtab = cconvert->Cr_r_tab;
register int * Cbbtab = cconvert->Cb_b_tab;
register INT32 * Crgtab = cconvert->Cr_g_tab;
register INT32 * Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
for (row = 0; row < num_rows; row++) {
inptr0 = input_data[0][row];
inptr1 = input_data[1][row];
inptr2 = input_data[2][row];
outptr0 = output_data[0][row];
outptr1 = output_data[1][row];
outptr2 = output_data[2][row];
for (col = num_cols; col > 0; col--) {
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
while (--num_rows >= 0) {
inptr0 = input_buf[0][input_row];
inptr1 = input_buf[1][input_row];
inptr2 = input_buf[2][input_row];
input_row++;
outptr = *output_buf++;
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.
*/
x = y + Cr_r_tab[cr]; /* red */
if (x < 0) x = 0;
else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
*outptr0++ = (JSAMPLE) x;
x = y + ((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr], SCALEBITS));
if (x < 0) x = 0;
else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
*outptr1++ = (JSAMPLE) x;
x = y + Cb_b_tab[cb]; /* blue */
if (x < 0) x = 0;
else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
*outptr2++ = (JSAMPLE) x;
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
outptr[RGB_GREEN] = range_limit[y +
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
outptr += RGB_PIXELSIZE;
}
}
}
/*
* 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.
* Color conversion for no colorspace change: just copy the data,
* converting from separate-planes to interleaved representation.
*/
METHODDEF void
null_init (decompress_info_ptr cinfo)
/* colorout_init for cases where no setup is needed */
null_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
/* no work needed */
}
register JSAMPROW inptr, outptr;
register JDIMENSION count;
register int num_components = cinfo->output_components;
JDIMENSION num_cols = cinfo->output_width;
int ci;
/*
* Color conversion for no colorspace change: just copy the data.
*/
METHODDEF void
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, num_cols);
while (--num_rows >= 0) {
for (ci = 0; ci < num_components; ci++) {
inptr = input_buf[ci][input_row];
outptr = output_buf[0] + ci;
for (count = num_cols; count > 0; count--) {
*outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
outptr += num_components;
}
}
input_row++;
output_buf++;
}
}
/*
* Color conversion for grayscale: just copy the data.
* This also works for YCbCr/YIQ -> grayscale conversion, in which
* This also works for YCbCr -> grayscale conversion, in which
* we just copy the Y (luminance) component and ignore chrominance.
*/
METHODDEF void
grayscale_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
grayscale_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
num_rows, num_cols);
jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
num_rows, cinfo->output_width);
}
/*
* Finish up at the end of the file.
* Adobe-style YCCK->CMYK conversion.
* We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
* conversion as above, while passing K (black) unchanged.
* We assume ycc_rgb_start has been called.
*/
METHODDEF void
null_term (decompress_info_ptr cinfo)
/* colorout_term for cases where no teardown is needed */
ycck_cmyk_convert (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows)
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
register int * Crrtab = cconvert->Cr_r_tab;
register int * Cbbtab = cconvert->Cb_b_tab;
register INT32 * Crgtab = cconvert->Cr_g_tab;
register INT32 * Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
inptr0 = input_buf[0][input_row];
inptr1 = input_buf[1][input_row];
inptr2 = input_buf[2][input_row];
inptr3 = input_buf[3][input_row];
input_row++;
outptr = *output_buf++;
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.
*/
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS)))];
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
/* K passes through unchanged */
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
outptr += 4;
}
}
}
/*
* Empty method for start_pass.
*/
METHODDEF void
null_method (j_decompress_ptr cinfo)
{
/* no work needed */
}
/*
* The method selection routine for output colorspace conversion.
* Module initialization routine for output colorspace conversion.
*/
GLOBAL void
jseldcolor (decompress_info_ptr cinfo)
jinit_color_deconverter (j_decompress_ptr cinfo)
{
my_cconvert_ptr cconvert;
int ci;
cconvert = (my_cconvert_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_color_deconverter));
cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
/* set start_pass to null method until we find out differently */
cconvert->pub.start_pass = null_method;
/* Make sure num_components agrees with jpeg_color_space */
switch (cinfo->jpeg_color_space) {
case CS_GRAYSCALE:
case JCS_GRAYSCALE:
if (cinfo->num_components != 1)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case CS_RGB:
case CS_YCbCr:
case CS_YIQ:
case JCS_RGB:
case JCS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case CS_CMYK:
case JCS_CMYK:
case JCS_YCCK:
if (cinfo->num_components != 4)
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
default:
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
default: /* JCS_UNKNOWN can be anything */
if (cinfo->num_components < 1)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
}
/* Set color_out_comps and conversion method based on requested space */
/* Set out_color_components 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->methods->color_convert = grayscale_convert;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
case JCS_GRAYSCALE:
cinfo->out_color_components = 1;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
cinfo->jpeg_color_space == JCS_YCbCr) {
cconvert->pub.color_convert = grayscale_convert;
/* For color->grayscale conversion, only the Y (0) component is needed */
for (ci = 1; ci < cinfo->num_components; ci++)
cinfo->comp_info[ci].component_needed = FALSE;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case CS_RGB:
cinfo->color_out_comps = 3;
if (cinfo->jpeg_color_space == CS_YCbCr) {
cinfo->methods->color_convert = ycc_rgb_convert;
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;
cinfo->methods->colorout_init = null_init;
cinfo->methods->colorout_term = null_term;
case JCS_RGB:
cinfo->out_color_components = RGB_PIXELSIZE;
if (cinfo->jpeg_color_space == JCS_YCbCr) {
cconvert->pub.start_pass = ycc_rgb_start;
cconvert->pub.color_convert = ycc_rgb_convert;
} else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
cconvert->pub.color_convert = null_convert;
} else
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_CMYK:
cinfo->out_color_components = 4;
if (cinfo->jpeg_color_space == JCS_YCCK) {
cconvert->pub.start_pass = ycc_rgb_start;
cconvert->pub.color_convert = ycck_cmyk_convert;
} else if (cinfo->jpeg_color_space == JCS_CMYK) {
cconvert->pub.color_convert = null_convert;
} else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default:
/* Permit null conversion from CMYK or YCbCr to same output space */
/* Permit null conversion 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;
cinfo->out_color_components = cinfo->num_components;
cconvert->pub.color_convert = null_convert;
} else /* unsupported non-null conversion */
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
}
if (cinfo->quantize_colors)
cinfo->final_out_comps = 1; /* single colormapped output component */
cinfo->output_components = 1; /* single colormapped output component */
else
cinfo->final_out_comps = cinfo->color_out_comps;
cinfo->output_components = cinfo->out_color_components;
}

176
jdct.h Normal file
View File

@@ -0,0 +1,176 @@
/*
* jdct.h
*
* Copyright (C) 1994, 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 contains common declarations for the forward and
* inverse DCT modules. These declarations are private to the DCT managers
* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
* The individual DCT algorithms are kept in separate files to ease
* machine-dependent tuning (e.g., assembly coding).
*/
/*
* A forward DCT routine is given a pointer to a work area of type DCTELEM[];
* the DCT is to be performed in-place in that buffer. Type DCTELEM is int
* for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
* implementations use an array of type FAST_FLOAT, instead.)
* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
* The DCT outputs are returned scaled up by a factor of 8; they therefore
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
* convention improves accuracy in integer implementations and saves some
* work in floating-point ones.
* Quantization of the output coefficients is done by jcdctmgr.c.
*/
#if BITS_IN_JSAMPLE == 8
typedef int DCTELEM; /* 16 or 32 bits is fine */
#else
typedef INT32 DCTELEM; /* must have 32 bits */
#endif
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
/*
* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
* to an output sample array. The routine must dequantize the input data as
* well as perform the IDCT; for dequantization, it uses the multiplier table
* pointed to by compptr->dct_table. The output data is to be placed into the
* sample array starting at a specified column. (Any row offset needed will
* be applied to the array pointer before it is passed to the IDCT code.)
* Note that the number of samples emitted by the IDCT routine is
* DCT_scaled_size * DCT_scaled_size.
*/
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
/*
* Each IDCT routine has its own ideas about the best dct_table element type.
*/
typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
#if BITS_IN_JSAMPLE == 8
typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
#else
typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
#endif
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
/*
* Each IDCT routine is responsible for range-limiting its results and
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
* be quite far out of range if the input data is corrupt, so a bulletproof
* range-limiting step is required. We use a mask-and-table-lookup method
* to do the combined operations quickly. See the comments with
* prepare_range_limit_table (in jdmaster.c) for more info.
*/
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_fdct_islow jFDislow
#define jpeg_fdct_ifast jFDifast
#define jpeg_fdct_float jFDfloat
#define jpeg_idct_islow jRDislow
#define jpeg_idct_ifast jRDifast
#define jpeg_idct_float jRDfloat
#define jpeg_idct_4x4 jRD4x4
#define jpeg_idct_2x2 jRD2x2
#define jpeg_idct_1x1 jRD1x1
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Extern declarations for the forward and inverse DCT routines. */
EXTERN void jpeg_fdct_islow JPP((DCTELEM * data));
EXTERN void jpeg_fdct_ifast JPP((DCTELEM * data));
EXTERN void jpeg_fdct_float JPP((FAST_FLOAT * data));
EXTERN void jpeg_idct_islow
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN void jpeg_idct_ifast
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN void jpeg_idct_float
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN void jpeg_idct_4x4
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN void jpeg_idct_2x2
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
EXTERN void jpeg_idct_1x1
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
/*
* Macros for handling fixed-point arithmetic; these are used by many
* but not all of the DCT/IDCT modules.
*
* All values are expected to be of type INT32.
* Fractional constants are scaled left by CONST_BITS bits.
* CONST_BITS is defined within each module using these macros,
* and may differ from one module to the next.
*/
#define ONE ((INT32) 1)
#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
* thus causing a lot of useless floating-point operations at run time.
*/
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* 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.
*/
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* This macro is used only when the two inputs will actually be no more than
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
* full 32x32 multiply. This provides a useful speedup on many machines.
* Unfortunately there is no way to specify a 16x16->32 multiply portably
* in C, but some C compilers will do the right thing if you provide the
* correct combination of casts.
*/
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#ifndef MULTIPLY16C16 /* default definition */
#define MULTIPLY16C16(var,const) ((var) * (const))
#endif
/* Same except both inputs are variables. */
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
#endif
#ifndef MULTIPLY16V16 /* default definition */
#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
#endif

282
jddctmgr.c Normal file
View File

@@ -0,0 +1,282 @@
/*
* jddctmgr.c
*
* Copyright (C) 1994, 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 inverse-DCT management logic.
* This code selects a particular IDCT implementation to be used,
* and it performs related housekeeping chores. No code in this file
* is executed per IDCT step, only during pass setup.
*
* Note that the IDCT routines are responsible for performing coefficient
* dequantization as well as the IDCT proper. This module sets up the
* dequantization multiplier table needed by the IDCT routine.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
/* Private subobject for this module */
typedef struct {
struct jpeg_inverse_dct pub; /* public fields */
/* Record the IDCT method type actually selected for each component */
J_DCT_METHOD real_method[MAX_COMPONENTS];
} my_idct_controller;
typedef my_idct_controller * my_idct_ptr;
/* 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 int 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
};
/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
* so be sure to compile that code if either ISLOW or SCALING is requested.
*/
#ifdef DCT_ISLOW_SUPPORTED
#define PROVIDE_ISLOW_TABLES
#else
#ifdef IDCT_SCALING_SUPPORTED
#define PROVIDE_ISLOW_TABLES
#endif
#endif
/*
* Initialize for an input scan.
*
* Verify that all referenced Q-tables are present, and set up
* the multiplier table for each one.
* With a multiple-scan JPEG file, this is called during each input scan,
* NOT during the final output pass where the IDCT is actually done.
* The purpose is to save away the current Q-table contents just in case
* the encoder changes tables between scans. This decoder will dequantize
* any component using the Q-table which was current at the start of the
* first scan using that component.
*/
METHODDEF void
start_input_pass (j_decompress_ptr cinfo)
{
my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
int ci, qtblno, i;
jpeg_component_info *compptr;
JQUANT_TBL * qtbl;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
qtblno = compptr->quant_tbl_no;
/* Make sure specified quantization table is present */
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
qtbl = cinfo->quant_tbl_ptrs[qtblno];
/* Create multiplier table from quant table, unless we already did so. */
if (compptr->dct_table != NULL)
continue;
switch (idct->real_method[compptr->component_index]) {
#ifdef PROVIDE_ISLOW_TABLES
case JDCT_ISLOW:
{
/* For LL&M IDCT method, multipliers are equal to raw quantization
* coefficients, but are stored in natural order as ints.
*/
ISLOW_MULT_TYPE * ismtbl;
compptr->dct_table =
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(ISLOW_MULT_TYPE));
ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[ZIG[i]];
}
}
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
{
/* For AA&N IDCT method, multipliers are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* For integer operation, the multiplier table is to be scaled by
* IFAST_SCALE_BITS. The multipliers are stored in natural order.
*/
IFAST_MULT_TYPE * ifmtbl;
#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
};
SHIFT_TEMPS
compptr->dct_table =
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(IFAST_MULT_TYPE));
ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
ifmtbl[i] = (IFAST_MULT_TYPE)
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[ZIG[i]],
(INT32) aanscales[i]),
CONST_BITS-IFAST_SCALE_BITS);
}
}
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
{
/* For float AA&N IDCT method, multipliers are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* The multipliers are stored in natural order.
*/
FLOAT_MULT_TYPE * fmtbl;
int row, col;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379
};
compptr->dct_table =
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * SIZEOF(FLOAT_MULT_TYPE));
fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
i = 0;
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fmtbl[i] = (FLOAT_MULT_TYPE)
((double) qtbl->quantval[ZIG[i]] *
aanscalefactor[row] * aanscalefactor[col]);
i++;
}
}
}
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
}
}
/*
* Prepare for an output pass that will actually perform IDCTs.
*
* start_input_pass should already have been done for all components
* of interest; we need only verify that this is true.
* Note that uninteresting components are not required to have loaded tables.
* This allows the master controller to stop before reading the whole file
* if it has obtained the data for the interesting component(s).
*/
METHODDEF void
start_output_pass (j_decompress_ptr cinfo)
{
jpeg_component_info *compptr;
int ci;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (! compptr->component_needed)
continue;
if (compptr->dct_table == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, compptr->quant_tbl_no);
}
}
/*
* Initialize IDCT manager.
*/
GLOBAL void
jinit_inverse_dct (j_decompress_ptr cinfo)
{
my_idct_ptr idct;
int ci;
jpeg_component_info *compptr;
idct = (my_idct_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_idct_controller));
cinfo->idct = (struct jpeg_inverse_dct *) idct;
idct->pub.start_input_pass = start_input_pass;
idct->pub.start_output_pass = start_output_pass;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
compptr->dct_table = NULL; /* initialize tables to "not prepared" */
switch (compptr->DCT_scaled_size) {
#ifdef IDCT_SCALING_SUPPORTED
case 1:
idct->pub.inverse_DCT[ci] = jpeg_idct_1x1;
idct->real_method[ci] = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
case 2:
idct->pub.inverse_DCT[ci] = jpeg_idct_2x2;
idct->real_method[ci] = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
case 4:
idct->pub.inverse_DCT[ci] = jpeg_idct_4x4;
idct->real_method[ci] = JDCT_ISLOW; /* jidctred uses islow-style table */
break;
#endif
case DCTSIZE:
switch (cinfo->dct_method) {
#ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
idct->pub.inverse_DCT[ci] = jpeg_idct_islow;
idct->real_method[ci] = JDCT_ISLOW;
break;
#endif
#ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST:
idct->pub.inverse_DCT[ci] = jpeg_idct_ifast;
idct->real_method[ci] = JDCT_IFAST;
break;
#endif
#ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT:
idct->pub.inverse_DCT[ci] = jpeg_idct_float;
idct->real_method[ci] = JDCT_FLOAT;
break;
#endif
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
break;
default:
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
break;
}
}
}

View File

@@ -1,154 +0,0 @@
/*
* jddeflts.c
*
* 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 optional default-setting code for the JPEG decompressor.
* User interfaces do not have to use this file, but those that don't use it
* must know more about the innards of the JPEG code.
*/
#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 */
}
/*
* Reload the input buffer after it's been emptied, and return the next byte.
* See the JGETC macro for calling conditions.
*
* 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
read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
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");
return JGETC(cinfo);
}
/* Default parameter setup for decompression.
*
* User interfaces that don't choose to use this routine must do their
* own setup of all these parameters. Alternately, you can call this
* to establish defaults and then alter parameters selectively. This
* 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 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;
cinfo->jpeg_color_space = CS_UNKNOWN;
/* Setting any other value in jpeg_color_space overrides heuristics in */
/* jrdjfif.c. That might be useful when reading non-JFIF JPEG files, */
/* but ordinarily the UI shouldn't change it. */
/* Default to no gamma correction of output */
cinfo->output_gamma = 1.0;
/* Default to no color quantization */
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 = TRUE;
cinfo->use_dithering = TRUE;
cinfo->desired_number_of_colors = 256;
/* Default to no smoothing */
cinfo->do_block_smoothing = FALSE;
cinfo->do_pixel_smoothing = FALSE;
/* Allocate memory for input buffer, unless outer application provides it. */
if (standard_buffering) {
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 (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;
}

748
jdhuff.c
View File

@@ -1,34 +1,172 @@
/*
* jdhuff.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, 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.
*
* Much of the complexity here has to do with supporting input suspension.
* If the data source module demands suspension, we want to be able to back
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent JPEG
* objects only upon successful completion of an MCU.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Static variables to avoid passing 'round extra parameters */
/* Derived data constructed for each Huffman table */
static decompress_info_ptr dcinfo;
#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
static INT32 get_buffer; /* current bit-extraction buffer */
static int bits_left; /* # of unused bits in it */
typedef struct {
/* 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 */
/* Back link to public Huffman table (needed only in slow_DECODE) */
JHUFF_TBL *pub;
/* 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 */
} D_DERIVED_TBL;
/* Expanded entropy decoder object for Huffman decoding.
*
* The savable_state subrecord contains fields that change within an MCU,
* but must not be updated permanently until we complete the MCU.
*/
typedef struct {
INT32 get_buffer; /* current bit-extraction buffer */
int bits_left; /* # of unused bits in it */
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest,src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest,src) \
((dest).get_buffer = (src).get_buffer, \
(dest).bits_left = (src).bits_left, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct {
struct jpeg_entropy_decoder pub; /* public fields */
savable_state saved; /* Bit buffer & DC state at start of MCU */
/* These fields are NOT loaded into local working state. */
unsigned int restarts_to_go; /* MCUs left in this restart interval */
boolean printed_eod; /* flag to suppress extra end-of-data msgs */
/* Pointers to derived tables (these workspaces have image lifespan) */
D_DERIVED_TBL * dc_derived_tbls[NUM_HUFF_TBLS];
D_DERIVED_TBL * ac_derived_tbls[NUM_HUFF_TBLS];
} huff_entropy_decoder;
typedef huff_entropy_decoder * huff_entropy_ptr;
/* Working state while scanning an MCU.
* This struct contains all the fields that are needed by subroutines.
*/
typedef struct {
int unread_marker; /* nonzero if we have hit a marker */
const JOCTET * next_input_byte; /* => next byte to read from source */
size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
savable_state cur; /* Current bit buffer & DC state */
j_decompress_ptr cinfo; /* fill_bit_buffer needs access to this */
} working_state;
/* Forward declarations */
LOCAL void fix_huff_tbl JPP((j_decompress_ptr cinfo, JHUFF_TBL * htbl,
D_DERIVED_TBL ** pdtbl));
/*
* Initialize for a Huffman-compressed scan.
*/
METHODDEF void
start_pass_huff_decoder (j_decompress_ptr cinfo)
{
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info * compptr;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
dctbl = compptr->dc_tbl_no;
actbl = compptr->ac_tbl_no;
/* Make sure requested tables are present */
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
if (actbl < 0 || actbl >= NUM_HUFF_TBLS ||
cinfo->ac_huff_tbl_ptrs[actbl] == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
/* Compute derived values for Huffman tables */
/* We may do this more than once for a table, but it's not expensive */
fix_huff_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[dctbl],
& entropy->dc_derived_tbls[dctbl]);
fix_huff_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[actbl],
& entropy->ac_derived_tbls[actbl]);
/* Initialize DC predictions to 0 */
entropy->saved.last_dc_val[ci] = 0;
}
/* Initialize private state variables */
entropy->saved.bits_left = 0;
entropy->printed_eod = FALSE;
/* Initialize restart counter */
entropy->restarts_to_go = cinfo->restart_interval;
}
LOCAL void
fix_huff_tbl (HUFF_TBL * htbl)
/* Compute derived values for a Huffman table */
fix_huff_tbl (j_decompress_ptr cinfo, JHUFF_TBL * htbl, D_DERIVED_TBL ** pdtbl)
/* Compute the derived values for a Huffman table */
{
D_DERIVED_TBL *dtbl;
int p, i, l, si;
int lookbits, ctr;
char huffsize[257];
UINT16 huffcode[257];
UINT16 code;
unsigned int huffcode[257];
unsigned int code;
/* Allocate a workspace if we haven't already done so. */
if (*pdtbl == NULL)
*pdtbl = (D_DERIVED_TBL *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(D_DERIVED_TBL));
dtbl = *pdtbl;
dtbl->pub = htbl; /* fill in back link */
/* Figure C.1: make table of Huffman code length for each symbol */
/* Note that this is in code-length order. */
@@ -55,271 +193,495 @@ fix_huff_tbl (HUFF_TBL * htbl)
si++;
}
/* We don't bother to fill in the encoding tables ehufco[] and ehufsi[], */
/* since they are not used for decoding. */
/* Figure F.15: 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 */
dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
p += htbl->bits[l];
htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
} else {
htbl->maxcode[l] = -1;
dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
}
}
dtbl->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(dtbl->look_nbits, SIZEOF(dtbl->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--) {
dtbl->look_nbits[lookbits] = l;
dtbl->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).
* Note that fill_bit_buffer may return FALSE to indicate suspension.
* On TRUE 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
* quite 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 boolean
fill_bit_buffer (working_state * state, int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
int result;
/* Copy heavily used state fields into locals (hopefully registers) */
register const JOCTET * next_input_byte = state->next_input_byte;
register size_t bytes_in_buffer = state->bytes_in_buffer;
register INT32 get_buffer = state->cur.get_buffer;
register int bits_left = state->cur.bits_left;
register int c;
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) {
/* Attempt to read a byte */
if (state->unread_marker != 0)
goto no_more_data; /* can't advance past a marker */
if (bytes_in_buffer == 0) {
if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
return FALSE;
next_input_byte = state->cinfo->src->next_input_byte;
bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
}
bytes_in_buffer--;
c = GETJOCTET(*next_input_byte++);
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) {
do {
if (bytes_in_buffer == 0) {
if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
return FALSE;
next_input_byte = state->cinfo->src->next_input_byte;
bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
}
bytes_in_buffer--;
c = GETJOCTET(*next_input_byte++);
} while (c == 0xFF);
if (c == 0) {
/* Found FF/00, which represents an FF data byte */
c = 0xFF;
} else {
/* Oops, it's actually a marker indicating end of compressed data. */
/* Better put it back for use later */
state->unread_marker = c;
no_more_data:
/* There should be enough bits still left in the data segment; */
/* if so, just break out of the outer 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 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 (! ((huff_entropy_ptr) state->cinfo->entropy)->printed_eod) {
WARNMS(state->cinfo, JWRN_HIT_MARKER);
((huff_entropy_ptr) state->cinfo->entropy)->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;
/* Unload the local registers */
state->next_input_byte = next_input_byte;
state->bytes_in_buffer = bytes_in_buffer;
state->cur.get_buffer = get_buffer;
state->cur.bits_left = bits_left;
return TRUE;
}
/* 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.
* Use check_bit_buffer to ensure there are N bits in get_buffer
* before using get_bits, peek_bits, or drop_bits.
* check_bit_buffer(state,n,action);
* Ensure there are N bits in get_buffer; if suspend, take action.
* val = get_bits(state,n);
* Fetch next N bits.
* val = peek_bits(state,n);
* Fetch next N bits without removing them from the buffer.
* drop_bits(state,n);
* Discard next N bits.
* The value N should be a simple variable, not an expression, because it
* is evaluated multiple times.
*/
#define check_bit_buffer(state,nbits,action) \
{ if ((state).cur.bits_left < (nbits)) \
if (! fill_bit_buffer(&(state), nbits)) \
{ action; } }
#define get_bits(state,nbits) \
(((int) ((state).cur.get_buffer >> ((state).cur.bits_left -= (nbits)))) & ((1<<(nbits))-1))
#define peek_bits(state,nbits) \
(((int) ((state).cur.get_buffer >> ((state).cur.bits_left - (nbits)))) & ((1<<(nbits))-1))
#define drop_bits(state,nbits) \
((state).cur.bits_left -= (nbits))
/* Figure F.16: extract next coded symbol from input stream */
/*
* Code for extracting 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. 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.
* 2. If the lookahead table contains no entry, the next code must be
* more than HUFF_LOOKAHEAD bits long.
* 3. slow_DECODE returns -1 if forced to suspend.
*/
#define huff_DECODE(result,state,htbl,donelabel) \
{ if (state.cur.bits_left < HUFF_LOOKAHEAD) { \
if (! fill_bit_buffer(&state, 0)) return FALSE; \
if (state.cur.bits_left < HUFF_LOOKAHEAD) { \
if ((result = slow_DECODE(&state, htbl, 1)) < 0) return FALSE; \
goto donelabel; \
} \
} \
{ register int nb, look; \
look = peek_bits(state, HUFF_LOOKAHEAD); \
if ((nb = htbl->look_nbits[look]) != 0) { \
drop_bits(state, nb); \
result = htbl->look_sym[look]; \
} else { \
if ((result = slow_DECODE(&state, htbl, HUFF_LOOKAHEAD+1)) < 0) \
return FALSE; \
} \
} \
donelabel:; \
}
LOCAL int
huff_DECODE (HUFF_TBL * htbl)
slow_DECODE (working_state * state, D_DERIVED_TBL * htbl, int min_bits)
{
int l, p;
INT32 code;
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(*state, l, return -1);
code = get_bits(*state, l);
/* Collect the rest of the Huffman code one bit at a time. */
/* This is per Figure F.16 in the JPEG spec. */
code = get_bit();
l = 1;
while (code > htbl->maxcode[l]) {
code = (code << 1) + get_bit();
code <<= 1;
check_bit_buffer(*state, 1, return -1);
code |= get_bits(*state, 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(state->cinfo, JWRN_HUFF_BAD_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->pub->huffval[ htbl->valptr[l] +
((int) (code - htbl->mincode[l])) ];
}
/* Figure F.12: extend sign bit */
/* NB: on some compilers this will only work for s > 0 */
#define huff_EXTEND(x, s) ((x) < (1 << ((s)-1)) ? \
(x) + (-1 << (s)) + 1 : \
(x))
/* Decode a single block's worth of coefficients */
/* Note that only the difference is returned for the DC coefficient */
LOCAL void
decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
{
int s, k, r, n;
/* zero out the coefficient block */
MEMZERO((void *) block, SIZEOF(JBLOCK));
/* Section F.2.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 F.2.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;
}
}
}
/*
* Initialize for a Huffman-compressed scan.
* This is invoked after reading the SOS marker.
/* Figure F.12: extend sign bit.
* On some machines, a shift and add will be faster than a table lookup.
*/
METHODDEF void
huff_decoder_init (decompress_info_ptr cinfo)
{
short ci;
jpeg_component_info * compptr;
#ifdef AVOID_TABLES
/* Initialize static variables */
dcinfo = cinfo;
bits_left = 0;
#define huff_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Make sure requested tables are present */
if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
/* Compute derived values for Huffman tables */
/* We may do this more than once for same table, but it's not a big deal */
fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
/* Initialize DC predictions to 0 */
cinfo->last_dc_val[ci] = 0;
}
#else
/* Initialize restart stuff */
cinfo->restarts_to_go = cinfo->restart_interval;
cinfo->next_restart_num = 0;
}
#define huff_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
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 };
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 };
#endif /* AVOID_TABLES */
/*
* Check for a restart marker & resynchronize decoder.
* Returns FALSE if must suspend.
*/
LOCAL void
process_restart (decompress_info_ptr cinfo)
LOCAL boolean
process_restart (j_decompress_ptr cinfo)
{
int c, nbytes;
short ci;
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
int ci;
/* Throw away any partial unread byte */
bits_left = 0;
/* Throw away any unused bits remaining in bit buffer; */
/* include any full bytes in next_marker's count of discarded bytes */
cinfo->marker->discarded_bytes += entropy->saved.bits_left / 8;
entropy->saved.bits_left = 0;
/* Scan for next JPEG marker */
nbytes = 0;
do {
do { /* skip any non-FF bytes */
nbytes++;
c = JGETC(cinfo);
} while (c != 0xFF);
do { /* skip any duplicate FFs */
nbytes++;
c = JGETC(cinfo);
} while (c == 0xFF);
} while (c == 0); /* repeat if it was a stuffed FF/00 */
if (c != (RST0 + cinfo->next_restart_num))
ERREXIT2(cinfo->emethods, "Found 0x%02x marker instead of RST%d",
c, cinfo->next_restart_num);
if (nbytes != 2)
TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before RST%d",
nbytes-2, cinfo->next_restart_num);
else
TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num);
/* Advance past the RSTn marker */
if (! (*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
cinfo->last_dc_val[ci] = 0;
entropy->saved.last_dc_val[ci] = 0;
/* Update restart state */
cinfo->restarts_to_go = cinfo->restart_interval;
cinfo->next_restart_num++;
cinfo->next_restart_num &= 7;
/* Reset restart counter */
entropy->restarts_to_go = cinfo->restart_interval;
entropy->printed_eod = FALSE; /* next segment can get another warning */
return TRUE;
}
/* 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 int 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.
* The coefficients are reordered from zigzag order into natural array order,
* but are not dequantized.
*
* 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...)
*
* Returns FALSE if data source requested suspension. In that case no
* changes have been made to permanent state. (Exception: some output
* coefficients may already have been assigned. This is harmless for
* this module, but would not work for decoding progressive JPEG.)
*/
METHODDEF void
huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
METHODDEF boolean
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
short blkn, ci;
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
register int s, k, r;
int blkn, ci;
JBLOCKROW block;
working_state state;
D_DERIVED_TBL * dctbl;
D_DERIVED_TBL * actbl;
jpeg_component_info * compptr;
/* Account for restart interval, process restart marker if needed */
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (cinfo->restarts_to_go == 0)
process_restart(cinfo);
cinfo->restarts_to_go--;
if (entropy->restarts_to_go == 0)
if (! process_restart(cinfo))
return FALSE;
}
/* Load up working state */
state.unread_marker = cinfo->unread_marker;
state.next_input_byte = cinfo->src->next_input_byte;
state.bytes_in_buffer = cinfo->src->bytes_in_buffer;
ASSIGN_STATE(state.cur, entropy->saved);
state.cinfo = cinfo;
/* 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]);
dctbl = entropy->dc_derived_tbls[compptr->dc_tbl_no];
actbl = entropy->ac_derived_tbls[compptr->ac_tbl_no];
/* Decode a single block's worth of coefficients */
/* Section F.2.2.1: decode the DC coefficient difference */
huff_DECODE(s, state, dctbl, label1);
if (s) {
check_bit_buffer(state, s, return FALSE);
r = get_bits(state, s);
s = huff_EXTEND(r, s);
}
/* Shortcut if component's values are not interesting */
if (! compptr->component_needed)
goto skip_ACs;
/* 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 += state.cur.last_dc_val[ci];
state.cur.last_dc_val[ci] = s;
/* Output the DC coefficient (assumes ZAG[0] = 0) */
(*block)[0] = (JCOEF) s;
/* Do we need to decode the AC coefficients for this component? */
if (compptr->DCT_scaled_size > 1) {
/* Section F.2.2.2: decode the AC coefficients */
/* Since zeroes are skipped, output area must be cleared beforehand */
for (k = 1; k < DCTSIZE2; k++) {
huff_DECODE(s, state, actbl, label2);
r = s >> 4;
s &= 15;
if (s) {
k += r;
check_bit_buffer(state, s, return FALSE);
r = get_bits(state, s);
s = huff_EXTEND(r, s);
/* Output coefficient in natural (dezigzagged) order */
(*block)[ZAG[k]] = (JCOEF) s;
} else {
if (r != 15)
break;
k += 15;
}
}
} else {
skip_ACs:
/* Section F.2.2.2: decode the AC coefficients */
/* In this path we just discard the values */
for (k = 1; k < DCTSIZE2; k++) {
huff_DECODE(s, state, actbl, label3);
r = s >> 4;
s &= 15;
if (s) {
k += r;
check_bit_buffer(state, s, return FALSE);
drop_bits(state, s);
} else {
if (r != 15)
break;
k += 15;
}
}
}
}
/* Completed MCU, so update state */
cinfo->unread_marker = state.unread_marker;
cinfo->src->next_input_byte = state.next_input_byte;
cinfo->src->bytes_in_buffer = state.bytes_in_buffer;
ASSIGN_STATE(entropy->saved, state.cur);
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
return TRUE;
}
/*
* Finish up at the end of a Huffman-compressed scan.
*/
METHODDEF void
huff_decoder_term (decompress_info_ptr cinfo)
{
/* No work needed */
}
/*
* The method selection routine for Huffman entropy decoding.
* Module initialization routine for Huffman entropy decoding.
*/
GLOBAL void
jseldhuffman (decompress_info_ptr cinfo)
jinit_huff_decoder (j_decompress_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;
huff_entropy_ptr entropy;
int i;
entropy = (huff_entropy_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(huff_entropy_decoder));
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
entropy->pub.start_pass = start_pass_huff_decoder;
entropy->pub.decode_mcu = decode_mcu;
/* Mark tables unallocated */
for (i = 0; i < NUM_HUFF_TBLS; i++) {
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
}
}

323
jdmain.c
View File

@@ -1,323 +0,0 @@
/*
* jdmain.c
*
* 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 a trivial test user interface for the JPEG decompressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
*
* Two different command line styles are permitted, depending on the
* compile-time switch TWO_FILE_COMMANDLINE:
* djpeg [options] inputfile outputfile
* djpeg [options] [inputfile]
* In the second style, output is always to standard output, which you'd
* normally redirect to a file or pipe to some other program. Input is
* either from a named file or from standard input (typically redirected).
* The second style is convenient on Unix but is unhelpful on systems that
* don't support pipes. Also, you MUST use the first style if your system
* doesn't do binary I/O to stdin/stdout.
*/
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h> /* to declare signal() */
#endif
#ifdef THINK_C
#include <console.h> /* command-line reader for Macintosh */
#endif
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#define WRITE_BINARY "w"
#else
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#endif
#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).
* You can change the default output format by defining DEFAULT_FMT;
* indeed, you had better do so if you undefine PPM_SUPPORTED.
*/
typedef enum {
FMT_GIF, /* GIF format */
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
FMT_RLE, /* RLE format */
FMT_TARGA, /* Targa format */
FMT_TIFF /* TIFF format */
} IMAGE_FORMATS;
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
#define DEFAULT_FMT FMT_PPM
#endif
static IMAGE_FORMATS requested_fmt;
/*
* This routine gets control after the input file header has been read.
* It must determine what output file format is to be written,
* and make any other decompression parameter changes that are desirable.
*/
METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
{
/* if grayscale or CMYK input, force similar output; */
/* else leave the output colorspace as set by options. */
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
cinfo->out_color_space = CS_GRAYSCALE;
else if (cinfo->jpeg_color_space == CS_CMYK)
cinfo->out_color_space = CS_CMYK;
/* select output file format */
/* Note: jselwxxx routine may make additional parameter changes,
* such as forcing color quantization if it's a colormapped format.
*/
switch (requested_fmt) {
#ifdef GIF_SUPPORTED
case FMT_GIF:
jselwgif(cinfo);
break;
#endif
#ifdef PPM_SUPPORTED
case FMT_PPM:
jselwppm(cinfo);
break;
#endif
#ifdef RLE_SUPPORTED
case FMT_RLE:
jselwrle(cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED
case FMT_TARGA:
jselwtarga(cinfo);
break;
#endif
default:
ERREXIT(cinfo->emethods, "Unsupported output file format");
break;
}
}
/*
* 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)
{
emethods->trace_level = 0; /* turn off trace output */
(*emethods->free_all) (); /* clean up memory allocation & temp files */
exit(EXIT_FAILURE);
}
#endif
LOCAL void
usage (char * progname)
/* complain about bad command line */
{
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-G] [-P] [-R] [-T] [-b] [-g] [-q colors] [-1] [-D] [-d] [-m mem]");
#ifdef TWO_FILE_COMMANDLINE
fprintf(stderr, " inputfile outputfile\n");
#else
fprintf(stderr, " [inputfile]\n");
#endif
exit(EXIT_FAILURE);
}
/*
* The main program.
*/
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;
/* On Mac, fetch a command line. */
#ifdef THINK_C
argc = ccommand(&argv);
#endif
/* Initialize the system-dependent method pointers. */
cinfo.methods = &dc_methods;
cinfo.emethods = &e_methods;
jselerror(&e_methods); /* error/trace message routines */
jselmemmgr(&e_methods); /* memory allocation routines */
dc_methods.d_ui_method_selection = d_ui_method_selection;
/* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
emethods = &e_methods;
signal(SIGINT, signal_catcher);
#ifdef SIGTERM /* not all systems have SIGTERM */
signal(SIGTERM, signal_catcher);
#endif
#endif
/* Set up default JPEG parameters. */
j_d_defaults(&cinfo, TRUE);
requested_fmt = DEFAULT_FMT; /* set default output file format */
/* Scan command line options, adjust parameters */
while ((c = egetopt(argc, argv, "GPRTbgq:1Dm:d")) != 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 '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 '1': /* Use fast one-pass quantization. */
cinfo.two_pass_quantize = FALSE;
break;
case 'D': /* Suppress dithering in color quantization. */
cinfo.use_dithering = FALSE;
break;
case 'm': /* Maximum memory in Kb (or Mb with 'm'). */
{ long lval;
char ch = 'x';
if (optarg == NULL)
usage(argv[0]);
if (sscanf(optarg, "%ld%c", &lval, &ch) < 1)
usage(argv[0]);
if (ch == 'm' || ch == 'M')
lval *= 1000L;
e_methods.max_memory_to_use = lval * 1000L;
}
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 DJPEG, version %s\n%s\n",
JVERSION, JCOPYRIGHT);
/* Select the input and output files */
#ifdef TWO_FILE_COMMANDLINE
if (optind != argc-2) {
fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
usage(argv[0]);
}
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
exit(EXIT_FAILURE);
}
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(EXIT_FAILURE);
}
#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(EXIT_FAILURE);
}
}
#endif /* TWO_FILE_COMMANDLINE */
/* Set up to read a JFIF or baseline-JPEG file. */
/* A smarter UI would inspect the first few bytes of the input file */
/* to determine its type. */
#ifdef JFIF_SUPPORTED
jselrjfif(&cinfo);
#else
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
#endif
/* Do it to it! */
jpeg_decompress(&cinfo);
/* All done. */
exit(EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
}

531
jdmainct.c Normal file
View File

@@ -0,0 +1,531 @@
/*
* jdmainct.c
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main buffer controller for decompression.
* The main buffer lies between the JPEG decompressor proper and the
* post-processor; it holds downsampled data in the JPEG colorspace.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/*
* In the current system design, the main buffer need never be a full-image
* buffer; any full-height buffers will be found inside the coefficient or
* postprocessing controllers. Nonetheless, the main controller is not
* trivial. Its responsibility is to provide context rows for upsampling/
* rescaling, and doing this in an efficient fashion is a bit tricky.
*
* Postprocessor input data is counted in "row groups". A row group
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
* sample rows of each component. (We require DCT_scaled_size values to be
* chosen such that these numbers are integers. In practice DCT_scaled_size
* values will likely be powers of two, so we actually have the stronger
* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
* Upsampling will typically produce max_v_samp_factor pixel rows from each
* row group (times any additional scale factor that the upsampler is
* applying).
*
* The coefficient controller will deliver data to us one iMCU row at a time;
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
* to one row of MCUs when the image is fully interleaved.) Note that the
* number of sample rows varies across components, but the number of row
* groups does not. Some garbage sample rows may be included in the last iMCU
* row at the bottom of the image.
*
* Depending on the vertical scaling algorithm used, the upsampler may need
* access to the sample row(s) above and below its current input row group.
* The upsampler is required to set need_context_rows TRUE at global selection
* time if so. When need_context_rows is FALSE, this controller can simply
* obtain one iMCU row at a time from the coefficient controller and dole it
* out as row groups to the postprocessor.
*
* When need_context_rows is TRUE, this controller guarantees that the buffer
* passed to postprocessing contains at least one row group's worth of samples
* above and below the row group(s) being processed. Note that the context
* rows "above" the first passed row group appear at negative row offsets in
* the passed buffer. At the top and bottom of the image, the required
* context rows are manufactured by duplicating the first or last real sample
* row; this avoids having special cases in the upsampling inner loops.
*
* The amount of context is fixed at one row group just because that's a
* convenient number for this controller to work with. The existing
* upsamplers really only need one sample row of context. An upsampler
* supporting arbitrary output rescaling might wish for more than one row
* group of context when shrinking the image; tough, we don't handle that.
* (This is justified by the assumption that downsizing will be handled mostly
* by adjusting the DCT_scaled_size values, so that the actual scale factor at
* the upsample step needn't be much less than one.)
*
* To provide the desired context, we have to retain the last two row groups
* of one iMCU row while reading in the next iMCU row. (The last row group
* can't be processed until we have another row group for its below-context,
* and so we have to save the next-to-last group too for its above-context.)
* We could do this most simply by copying data around in our buffer, but
* that'd be very slow. We can avoid copying any data by creating a rather
* strange pointer structure. Here's how it works. We allocate a workspace
* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
* of row groups per iMCU row). We create two sets of redundant pointers to
* the workspace. Labeling the physical row groups 0 to M+1, the synthesized
* pointer lists look like this:
* M+1 M-1
* master pointer --> 0 master pointer --> 0
* 1 1
* ... ...
* M-3 M-3
* M-2 M
* M-1 M+1
* M M-2
* M+1 M-1
* 0 0
* We read alternate iMCU rows using each master pointer; thus the last two
* row groups of the previous iMCU row remain un-overwritten in the workspace.
* The pointer lists are set up so that the required context rows appear to
* be adjacent to the proper places when we pass the pointer lists to the
* upsampler.
*
* The above pictures describe the normal state of the pointer lists.
* At top and bottom of the image, we diddle the pointer lists to duplicate
* the first or last sample row as necessary (this is cheaper than copying
* sample rows around).
*
* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
* situation each iMCU row provides only one row group so the buffering logic
* must be different (eg, we must read two iMCU rows before we can emit the
* first row group). For now, we simply do not support providing context
* rows when min_DCT_scaled_size is 1. That combination seems unlikely to
* be worth providing --- if someone wants a 1/8th-size preview, they probably
* want it quick and dirty, so a context-free upsampler is sufficient.
*/
/* Private buffer controller object */
typedef struct {
struct jpeg_d_main_controller pub; /* public fields */
/* Pointer to allocated workspace (M or M+2 row groups). */
JSAMPARRAY buffer[MAX_COMPONENTS];
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
/* Remaining fields are only used in the context case. */
/* These are the master pointers to the funny-order pointer lists. */
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
int whichptr; /* indicates which pointer set is now in use */
int context_state; /* process_data state machine status */
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
} my_main_controller;
typedef my_main_controller * my_main_ptr;
/* context_state values: */
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
/* Forward declarations */
METHODDEF void process_data_simple_main
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
METHODDEF void process_data_context_main
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
#ifdef D_MULTISCAN_FILES_SUPPORTED
METHODDEF void process_data_input_only
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
#endif
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF void process_data_crank_post
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
#endif
LOCAL void
make_funny_pointers (j_decompress_ptr cinfo)
/* Create the funny pointer lists discussed in the comments above.
* The actual workspace is already allocated (in main->buffer),
* we just have to make the curiously ordered lists.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup;
int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY buf, xbuf0, xbuf1;
/* Get top-level space for component array pointers.
* We alloc both arrays with one call to save a few cycles.
*/
main->xbuffer[0] = (JSAMPIMAGE)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
/* Get space for pointer lists --- M+4 row groups in each list.
* We alloc both pointer lists with one call to save a few cycles.
*/
xbuf0 = (JSAMPARRAY)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
xbuf0 += rgroup; /* want one row group at negative offsets */
main->xbuffer[0][ci] = xbuf0;
xbuf1 = xbuf0 + (rgroup * (M + 4));
main->xbuffer[1][ci] = xbuf1;
/* First copy the workspace pointers as-is */
buf = main->buffer[ci];
for (i = 0; i < rgroup * (M + 2); i++) {
xbuf0[i] = xbuf1[i] = buf[i];
}
/* In the second list, put the last four row groups in swapped order */
for (i = 0; i < rgroup * 2; i++) {
xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
}
/* The wraparound pointers at top and bottom will be filled later
* (see set_wraparound_pointers, below). Initially we want the "above"
* pointers to duplicate the first actual data line. This only needs
* to happen in xbuffer[0].
*/
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[0];
}
}
}
LOCAL void
set_wraparound_pointers (j_decompress_ptr cinfo)
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
* This changes the pointer list state from top-of-image to the normal state.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup;
int M = cinfo->min_DCT_scaled_size;
jpeg_component_info *compptr;
JSAMPARRAY xbuf0, xbuf1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
xbuf0 = main->xbuffer[0][ci];
xbuf1 = main->xbuffer[1][ci];
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
}
}
}
LOCAL void
set_bottom_pointers (j_decompress_ptr cinfo)
/* Change the pointer lists to duplicate the last sample row at the bottom
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
*/
{
my_main_ptr main = (my_main_ptr) cinfo->main;
int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Count sample rows in one iMCU row and in one row group */
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
/* Count nondummy sample rows remaining for this component */
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
if (rows_left == 0) rows_left = iMCUheight;
/* Count nondummy row groups. Should get same answer for each component,
* so we need only do it once.
*/
if (ci == 0) {
main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
}
/* Duplicate the last real sample row rgroup*2 times; this pads out the
* last partial rowgroup and ensures at least one full rowgroup of context.
*/
xbuf = main->xbuffer[main->whichptr][ci];
for (i = 0; i < rgroup * 2; i++) {
xbuf[rows_left + i] = xbuf[rows_left-1];
}
}
}
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
/* Processing chunks are output rows except in JBUF_CRANK_SOURCE mode. */
main->pub.num_chunks = cinfo->output_height;
switch (pass_mode) {
case JBUF_PASS_THRU:
/* Do nothing if raw-data mode. */
if (cinfo->raw_data_out)
return;
if (cinfo->upsample->need_context_rows) {
main->pub.process_data = process_data_context_main;
make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
main->context_state = CTX_PREPARE_FOR_IMCU;
main->iMCU_row_ctr = 0;
} else {
/* Simple case with no context needed */
main->pub.process_data = process_data_simple_main;
}
main->buffer_full = FALSE; /* Mark buffer empty */
main->rowgroup_ctr = 0;
break;
#ifdef D_MULTISCAN_FILES_SUPPORTED
case JBUF_CRANK_SOURCE:
/* Reading a multi-scan file, just crank the decompressor */
main->pub.process_data = process_data_input_only;
/* decompressor needs to be called once for each (equivalent) iMCU row */
main->pub.num_chunks = cinfo->total_iMCU_rows;
break;
#endif
#ifdef QUANT_2PASS_SUPPORTED
case JBUF_CRANK_DEST:
/* For last pass of 2-pass quantization, just crank the postprocessor */
main->pub.process_data = process_data_crank_post;
break;
#endif
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
/*
* Process some data.
* This handles the simple case where no context is required.
*/
METHODDEF void
process_data_simple_main (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
JDIMENSION rowgroups_avail;
/* Read input data if we haven't filled the main buffer yet */
if (! main->buffer_full) {
if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
return; /* suspension forced, can do nothing more */
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
/* Note: at the bottom of the image, we may pass extra garbage row groups
* to the postprocessor. The postprocessor has to check for bottom
* of image anyway (at row resolution), so no point in us doing it too.
*/
/* Feed the postprocessor */
(*cinfo->post->post_process_data) (cinfo, main->buffer,
&main->rowgroup_ctr, rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
if (main->rowgroup_ctr >= rowgroups_avail) {
main->buffer_full = FALSE;
main->rowgroup_ctr = 0;
}
}
/*
* Process some data.
* This handles the case where context rows must be provided.
*/
METHODDEF void
process_data_context_main (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_main_ptr main = (my_main_ptr) cinfo->main;
/* Read input data if we haven't filled the main buffer yet */
if (! main->buffer_full) {
if (! (*cinfo->coef->decompress_data) (cinfo,
main->xbuffer[main->whichptr]))
return; /* suspension forced, can do nothing more */
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
main->iMCU_row_ctr++; /* count rows received */
}
/* Postprocessor typically will not swallow all the input data it is handed
* in one call (due to filling the output buffer first). Must be prepared
* to exit and restart. This switch lets us keep track of how far we got.
* Note that each case falls through to the next on successful completion.
*/
switch (main->context_state) {
case CTX_POSTPONED_ROW:
/* Call postprocessor using previously set pointers for postponed row */
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
&main->rowgroup_ctr, main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
if (main->rowgroup_ctr < main->rowgroups_avail)
return; /* Need to suspend */
main->context_state = CTX_PREPARE_FOR_IMCU;
if (*out_row_ctr >= out_rows_avail)
return; /* Postprocessor exactly filled output buf */
/*FALLTHROUGH*/
case CTX_PREPARE_FOR_IMCU:
/* Prepare to process first M-1 row groups of this iMCU row */
main->rowgroup_ctr = 0;
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
/* Check for bottom of image: if so, tweak pointers to "duplicate"
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
*/
if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
set_bottom_pointers(cinfo);
main->context_state = CTX_PROCESS_IMCU;
/*FALLTHROUGH*/
case CTX_PROCESS_IMCU:
/* Call postprocessor using previously set pointers */
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
&main->rowgroup_ctr, main->rowgroups_avail,
output_buf, out_row_ctr, out_rows_avail);
if (main->rowgroup_ctr < main->rowgroups_avail)
return; /* Need to suspend */
/* After the first iMCU, change wraparound pointers to normal state */
if (main->iMCU_row_ctr == 1)
set_wraparound_pointers(cinfo);
/* Prepare to load new iMCU row using other xbuffer list */
main->whichptr ^= 1; /* 0=>1 or 1=>0 */
main->buffer_full = FALSE;
/* Still need to process last row group of this iMCU row, */
/* which is saved at index M+1 of the other xbuffer */
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
main->context_state = CTX_POSTPONED_ROW;
}
}
/*
* Process some data.
* Initial passes in a multiple-scan file: just call the decompressor,
* which will save data in its internal buffer, but return nothing.
*/
#ifdef D_MULTISCAN_FILES_SUPPORTED
METHODDEF void
process_data_input_only (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
if (! (*cinfo->coef->decompress_data) (cinfo, (JSAMPIMAGE) NULL))
return; /* suspension forced, can do nothing more */
*out_row_ctr += 1; /* OK, we did one iMCU row */
}
#endif /* D_MULTISCAN_FILES_SUPPORTED */
/*
* Process some data.
* Final pass of two-pass quantization: just call the postprocessor.
* Source data will be the postprocessor controller's internal buffer.
*/
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF void
process_data_crank_post (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
(*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
(JDIMENSION *) NULL, (JDIMENSION) 0,
output_buf, out_row_ctr, out_rows_avail);
}
#endif /* QUANT_2PASS_SUPPORTED */
/*
* Initialize main buffer controller.
*/
GLOBAL void
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main;
int ci, rgroup, ngroups;
jpeg_component_info *compptr;
main = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_main_controller));
cinfo->main = (struct jpeg_d_main_controller *) main;
main->pub.start_pass = start_pass_main;
if (need_full_buffer) /* shouldn't happen */
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
/* In raw-data mode, we don't need a workspace. This module doesn't
* do anything useful in that mode, except pass calls through to the
* coef controller in CRANK_SOURCE mode (ie, reading a multiscan file).
*/
if (cinfo->raw_data_out)
return;
/* Allocate the workspace.
* ngroups is the number of row groups we need.
*/
if (cinfo->upsample->need_context_rows) {
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
ERREXIT(cinfo, JERR_NOTIMPL);
ngroups = cinfo->min_DCT_scaled_size + 2;
} else {
ngroups = cinfo->min_DCT_scaled_size;
}
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size; /* height of a row group of component */
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * compptr->DCT_scaled_size,
(JDIMENSION) (rgroup * ngroups));
}
}

1052
jdmarker.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,173 +1,648 @@
/*
* jdmaster.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the main control for the JPEG decompressor.
* The system-dependent (user interface) code should call jpeg_decompress()
* after doing appropriate setup of the decompress_info_struct parameter.
* This file contains master control logic for the JPEG decompressor.
* These routines are concerned with selecting the modules to be executed
* and with determining the number of passes and the work to be done in each
* pass.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
METHODDEF void
d_per_scan_method_selection (decompress_info_ptr cinfo)
/* Central point for per-scan method selection */
/* Private state */
typedef enum {
main_pass, /* read and process a single-scan file */
preread_pass, /* read one scan of a multi-scan file */
output_pass, /* primary processing pass for multi-scan */
post_pass /* optional post-pass for 2-pass quant. */
} D_PASS_TYPE;
typedef struct {
struct jpeg_decomp_master pub; /* public fields */
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
D_PASS_TYPE pass_type; /* the type of the current pass */
int pass_number; /* # of passes completed */
int total_passes; /* estimated total # of passes needed */
boolean need_post_pass; /* are we using full two-pass quantization? */
} my_decomp_master;
typedef my_decomp_master * my_master_ptr;
/*
* Determine whether merged upsample/color conversion should be used.
* CRUCIAL: this must match the actual capabilities of jdmerge.c!
*/
LOCAL boolean
use_merged_upsample (j_decompress_ptr cinfo)
{
/* MCU disassembly */
jseldmcu(cinfo);
/* Un-subsampling of pixels */
jselunsubsample(cinfo);
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Merging is the equivalent of plain box-filter upsampling */
if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
return FALSE;
/* jdmerge.c only supports YCC=>RGB color conversion */
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
cinfo->out_color_space != JCS_RGB ||
cinfo->out_color_components != RGB_PIXELSIZE)
return FALSE;
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo->comp_info[0].h_samp_factor != 2 ||
cinfo->comp_info[1].h_samp_factor != 1 ||
cinfo->comp_info[2].h_samp_factor != 1 ||
cinfo->comp_info[0].v_samp_factor > 2 ||
cinfo->comp_info[1].v_samp_factor != 1 ||
cinfo->comp_info[2].v_samp_factor != 1)
return FALSE;
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
return FALSE;
/* ??? also need to test for upsample-time rescaling, when & if supported */
/* by golly, it'll work... */
return TRUE;
#else
return FALSE;
#endif
}
LOCAL void
d_initial_method_selection (decompress_info_ptr cinfo)
/* Central point for initial method selection (after reading file header) */
/*
* Support routines that do various essential calculations.
*
* jpeg_calc_output_dimensions is exported for possible use by application.
* Hence it mustn't do anything that can't be done twice.
*/
GLOBAL void
jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
/* JPEG file scanning method selection is already done. */
/* So is output file format selection (both are done by user interface). */
/* Entropy decoding: either Huffman or arithmetic coding. */
#ifdef ARITH_CODING_SUPPORTED
jseldarithmetic(cinfo);
#else
if (cinfo->arith_code) {
ERREXIT(cinfo->emethods, "Arithmetic coding not supported");
}
#endif
jseldhuffman(cinfo);
/* Cross-block smoothing */
#ifdef BLOCK_SMOOTHING_SUPPORTED
jselbsmooth(cinfo);
#else
cinfo->do_block_smoothing = FALSE;
#endif
/* Gamma and color space conversion */
jseldcolor(cinfo);
/* Color quantization selection rules */
#ifdef QUANT_1PASS_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 */
#ifdef QUANT_2PASS_SUPPORTED
cinfo->two_pass_quantize = TRUE; /* only have 2-pass */
#else /* not QUANT_2PASS_SUPPORTED */
if (cinfo->quantize_colors) {
ERREXIT(cinfo->emethods, "Color quantization was not compiled");
}
#endif
#endif
#ifdef QUANT_1PASS_SUPPORTED
jsel1quantize(cinfo);
#endif
#ifdef QUANT_2PASS_SUPPORTED
jsel2quantize(cinfo);
#endif
/* Pipeline control */
jseldpipeline(cinfo);
/* Overall control (that's me!) */
cinfo->methods->d_per_scan_method_selection = d_per_scan_method_selection;
}
LOCAL void
initial_setup (decompress_info_ptr cinfo)
/* Do computations that are needed before initial method selection */
{
short ci;
int ci;
jpeg_component_info *compptr;
/* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1;
cinfo->max_v_samp_factor = 1;
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo->emethods, "Bogus sampling factors");
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor);
}
/* Compute logical subsampled dimensions of components */
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
+ cinfo->max_h_samp_factor - 1)
/ cinfo->max_h_samp_factor;
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
+ cinfo->max_v_samp_factor - 1)
/ cinfo->max_v_samp_factor;
/* Compute actual output image dimensions and DCT scaling choices. */
#ifdef IDCT_SCALING_SUPPORTED
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
/* Provide 1/8 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 8L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 8L);
cinfo->min_DCT_scaled_size = 1;
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
/* Provide 1/4 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 4L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 4L);
cinfo->min_DCT_scaled_size = 2;
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
/* Provide 1/2 scaling */
cinfo->output_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width, 2L);
cinfo->output_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height, 2L);
cinfo->min_DCT_scaled_size = 4;
} else {
/* Provide 1/1 scaling */
cinfo->output_width = cinfo->image_width;
cinfo->output_height = cinfo->image_height;
cinfo->min_DCT_scaled_size = DCTSIZE;
}
/* In selecting the actual DCT scaling for each component, we try to
* scale up the chroma components via IDCT scaling rather than upsampling.
* This saves time if the upsampler gets to use 1:1 scaling.
* Note this code assumes that the supported DCT scalings are powers of 2.
*/
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
int ssize = cinfo->min_DCT_scaled_size;
while (ssize < DCTSIZE &&
(compptr->h_samp_factor * ssize * 2 <=
cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
(compptr->v_samp_factor * ssize * 2 <=
cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
ssize = ssize * 2;
}
compptr->DCT_scaled_size = ssize;
}
#else /* !IDCT_SCALING_SUPPORTED */
/* Hardwire it to "no scaling" */
cinfo->output_width = cinfo->image_width;
cinfo->output_height = cinfo->image_height;
cinfo->min_DCT_scaled_size = DCTSIZE;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
compptr->DCT_scaled_size = DCTSIZE;
}
#endif /* IDCT_SCALING_SUPPORTED */
/* Report number of components in selected colorspace. */
/* Probably this should be in the color conversion module... */
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
cinfo->out_color_components = 1;
break;
case JCS_RGB:
#if RGB_PIXELSIZE != 3
cinfo->out_color_components = RGB_PIXELSIZE;
break;
#endif /* else share code with YCbCr */
case JCS_YCbCr:
cinfo->out_color_components = 3;
break;
case JCS_CMYK:
case JCS_YCCK:
cinfo->out_color_components = 4;
break;
default: /* else must be same colorspace as in file */
cinfo->out_color_components = cinfo->num_components;
break;
}
cinfo->output_components = (cinfo->quantize_colors ? 1 :
cinfo->out_color_components);
/* See if upsampler will want to emit more than one row at a time */
if (use_merged_upsample(cinfo))
cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
else
cinfo->rec_outbuf_height = 1;
/* Compute various sampling-related dimensions.
* Some of these are of interest to the application if it is dealing with
* "raw" (not upsampled) output, so we do the calculations here.
*/
/* Compute dimensions of components */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples, after IDCT scaling */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width *
(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
(long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height *
(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
(long) (cinfo->max_v_samp_factor * DCTSIZE));
/* Mark component needed, until color conversion says otherwise */
compptr->component_needed = TRUE;
}
/* Compute number of fully interleaved MCU rows (number of times that
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
}
LOCAL void
per_scan_setup (j_decompress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
{
int ci, mcublks, tmp;
jpeg_component_info *compptr;
if (cinfo->comps_in_scan == 1) {
/* Noninterleaved (single-component) scan */
compptr = cinfo->cur_comp_info[0];
/* Overall image size in MCUs */
cinfo->MCUs_per_row = compptr->width_in_blocks;
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
/* For noninterleaved scan, always one block per MCU */
compptr->MCU_width = 1;
compptr->MCU_height = 1;
compptr->MCU_blocks = 1;
compptr->MCU_sample_width = compptr->DCT_scaled_size;
compptr->last_col_width = 1;
compptr->last_row_height = 1;
/* Prepare array describing MCU composition */
cinfo->blocks_in_MCU = 1;
cinfo->MCU_membership[0] = 0;
} else {
/* Interleaved (multi-component) scan */
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
MAX_COMPS_IN_SCAN);
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->image_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
cinfo->blocks_in_MCU = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Sampling factors give # of blocks of component in each MCU */
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
}
}
}
}
/*
* This is the main entry point to the JPEG decompressor.
* Several decompression processes need to range-limit values to the range
* 0..MAXJSAMPLE; the input value may fall somewhat outside this range
* due to noise introduced by quantization, roundoff error, etc. These
* processes are inner loops and need to be as fast as possible. On most
* machines, particularly CPUs with pipelines or instruction prefetch,
* a (subscript-check-less) C table lookup
* x = sample_range_limit[x];
* is faster than explicit tests
* if (x < 0) x = 0;
* else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
* These processes all use a common table prepared by the routine below.
*
* For most steps we can mathematically guarantee that the initial value
* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
* limiting step (just after the IDCT), a wildly out-of-range value is
* possible if the input data is corrupt. To avoid any chance of indexing
* off the end of memory and getting a bad-pointer trap, we perform the
* post-IDCT limiting thus:
* x = range_limit[x & MASK];
* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
* samples. Under normal circumstances this is more than enough range and
* a correct output will be generated; with bogus input data the mask will
* cause wraparound, and we will safely generate a bogus-but-in-range output.
* For the post-IDCT step, we want to convert the data from signed to unsigned
* representation by adding CENTERJSAMPLE at the same time that we limit it.
* So the post-IDCT limiting table ends up looking like this:
* CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
* MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
* 0,1,...,CENTERJSAMPLE-1
* Negative inputs select values from the upper half of the table after
* masking.
*
* We can save some space by overlapping the start of the post-IDCT table
* with the simpler range limiting table. The post-IDCT table begins at
* sample_range_limit + CENTERJSAMPLE.
*
* Note that the table is allocated in near data space on PCs; it's small
* enough and used often enough to justify this.
*/
LOCAL void
prepare_range_limit_table (j_decompress_ptr cinfo)
/* Allocate and fill in the sample_range_limit table */
{
JSAMPLE * table;
int i;
table = (JSAMPLE *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
cinfo->sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++)
table[i] = (JSAMPLE) i;
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
MEMZERO(table + (2 * (MAXJSAMPLE+1)),
(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
}
/*
* Master selection of decompression modules.
* This is done once at the start of processing an image. We determine
* which modules will be used and give them appropriate initialization calls.
*
* Note that this is called only after jpeg_read_header has finished.
* We therefore know what is in the SOF and (first) SOS markers.
*/
LOCAL void
master_selection (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
long samplesperrow;
JDIMENSION jd_samplesperrow;
/* Initialize dimensions and other stuff */
jpeg_calc_output_dimensions(cinfo);
prepare_range_limit_table(cinfo);
/* Width of an output scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
if ((long) jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* Initialize my private state */
master->pub.eoi_processed = FALSE;
master->pass_number = 0;
master->need_post_pass = FALSE;
if (cinfo->comps_in_scan == cinfo->num_components) {
master->pass_type = main_pass;
master->total_passes = 1;
} else {
#ifdef D_MULTISCAN_FILES_SUPPORTED
master->pass_type = preread_pass;
/* Assume there is a separate scan for each component; */
/* if partially interleaved, we'll increment pass_number appropriately */
master->total_passes = cinfo->num_components + 1;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
master->using_merged_upsample = use_merged_upsample(cinfo);
/* There's not a lot of smarts here right now, but it'll get more
* complicated when we have multiple implementations available...
*/
/* Color quantizer selection */
if (cinfo->quantize_colors) {
if (cinfo->raw_data_out)
ERREXIT(cinfo, JERR_NOTIMPL);
#ifdef QUANT_2PASS_SUPPORTED
/* 2-pass quantizer only works in 3-component color space.
* We use the "2-pass" code in a single pass if a colormap is given.
*/
if (cinfo->out_color_components != 3)
cinfo->two_pass_quantize = FALSE;
else if (cinfo->colormap != NULL)
cinfo->two_pass_quantize = TRUE;
#else
/* Force 1-pass quantize if we don't have 2-pass code compiled. */
cinfo->two_pass_quantize = FALSE;
#endif
if (cinfo->two_pass_quantize) {
#ifdef QUANT_2PASS_SUPPORTED
if (cinfo->colormap == NULL) {
master->need_post_pass = TRUE;
master->total_passes++;
}
jinit_2pass_quantizer(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
#ifdef QUANT_1PASS_SUPPORTED
jinit_1pass_quantizer(cinfo);
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
}
}
/* Post-processing: in particular, color conversion first */
if (! cinfo->raw_data_out) {
if (master->using_merged_upsample) {
#ifdef UPSAMPLE_MERGING_SUPPORTED
jinit_merged_upsampler(cinfo); /* does color conversion too */
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
jinit_color_deconverter(cinfo);
jinit_upsampler(cinfo);
}
jinit_d_post_controller(cinfo, master->need_post_pass);
}
/* Inverse DCT */
jinit_inverse_dct(cinfo);
/* Entropy decoding: either Huffman or arithmetic coding. */
if (cinfo->arith_code) {
#ifdef D_ARITH_CODING_SUPPORTED
jinit_arith_decoder(cinfo);
#else
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
#endif
} else
jinit_huff_decoder(cinfo);
jinit_d_coef_controller(cinfo, (master->pass_type == preread_pass));
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
/* Note that main controller is initialized even in raw-data mode. */
/* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
}
/*
* Per-pass setup.
* This is called at the beginning of each pass. We determine which modules
* will be active during this pass and give them appropriate start_pass calls.
* We also set is_last_pass to indicate whether any more passes will be
* required.
*/
METHODDEF void
prepare_for_pass (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
switch (master->pass_type) {
case main_pass:
/* Set up to read and decompress single-scan file in one pass */
per_scan_setup(cinfo);
master->pub.is_last_pass = ! master->need_post_pass;
if (! cinfo->raw_data_out) {
if (! master->using_merged_upsample)
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->upsample->start_pass) (cinfo);
if (cinfo->quantize_colors)
(*cinfo->cquantize->start_pass) (cinfo, master->need_post_pass);
(*cinfo->post->start_pass) (cinfo,
(master->need_post_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
}
(*cinfo->idct->start_input_pass) (cinfo);
(*cinfo->idct->start_output_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo);
(*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU);
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
break;
#ifdef D_MULTISCAN_FILES_SUPPORTED
case preread_pass:
/* Read (another) scan of a multi-scan file */
per_scan_setup(cinfo);
master->pub.is_last_pass = FALSE;
(*cinfo->idct->start_input_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo);
(*cinfo->coef->start_pass) (cinfo, JBUF_SAVE_SOURCE);
(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_SOURCE);
break;
case output_pass:
/* All scans read, now do the IDCT and subsequent processing */
master->pub.is_last_pass = ! master->need_post_pass;
if (! cinfo->raw_data_out) {
if (! master->using_merged_upsample)
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->upsample->start_pass) (cinfo);
if (cinfo->quantize_colors)
(*cinfo->cquantize->start_pass) (cinfo, master->need_post_pass);
(*cinfo->post->start_pass) (cinfo,
(master->need_post_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
}
(*cinfo->idct->start_output_pass) (cinfo);
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
break;
#endif /* D_MULTISCAN_FILES_SUPPORTED */
#ifdef QUANT_2PASS_SUPPORTED
case post_pass:
/* Final pass of 2-pass quantization */
master->pub.is_last_pass = TRUE;
(*cinfo->cquantize->start_pass) (cinfo, FALSE);
(*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
break;
#endif /* QUANT_2PASS_SUPPORTED */
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
cinfo->progress->completed_passes = master->pass_number;
cinfo->progress->total_passes = master->total_passes;
}
}
/*
* Finish up at end of pass.
* In multi-scan mode, we must read next scan header and set the next
* pass_type correctly for prepare_for_pass.
*/
METHODDEF void
finish_pass_master (j_decompress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
switch (master->pass_type) {
case main_pass:
case output_pass:
if (cinfo->quantize_colors)
(*cinfo->cquantize->finish_pass) (cinfo);
master->pass_number++;
master->pass_type = post_pass; /* in case need_post_pass is true */
break;
#ifdef D_MULTISCAN_FILES_SUPPORTED
case preread_pass:
/* Count one pass done for each component in this scan */
master->pass_number += cinfo->comps_in_scan;
switch ((*cinfo->marker->read_markers) (cinfo)) {
case JPEG_HEADER_OK: /* Found SOS, do another preread pass */
break;
case JPEG_HEADER_TABLES_ONLY: /* Found EOI, no more preread passes */
master->pub.eoi_processed = TRUE;
master->pass_type = output_pass;
break;
case JPEG_SUSPENDED:
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
break;
#endif /* D_MULTISCAN_FILES_SUPPORTED */
#ifdef QUANT_2PASS_SUPPORTED
case post_pass:
(*cinfo->cquantize->finish_pass) (cinfo);
/* there will be no more passes, don't bother to change state */
break;
#endif /* QUANT_2PASS_SUPPORTED */
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
}
/*
* Initialize master decompression control.
* This creates my own subrecord and also performs the master selection phase,
* which causes other modules to create their subrecords.
*/
GLOBAL void
jpeg_decompress (decompress_info_ptr cinfo)
jinit_master_decompress (j_decompress_ptr cinfo)
{
/* Init pass counts to 0 --- total_passes is adjusted in method selection */
cinfo->total_passes = 0;
cinfo->completed_passes = 0;
my_master_ptr master;
/* Read the JPEG file header markers; everything up through the first SOS
* marker is read now. NOTE: the user interface must have initialized the
* read_file_header method pointer (eg, by calling jselrjfif or jselrtiff).
* The other file reading methods (read_scan_header etc.) were probably
* set at the same time, but could be set up by read_file_header itself.
*/
(*cinfo->methods->read_file_header) (cinfo);
if (! ((*cinfo->methods->read_scan_header) (cinfo)))
ERREXIT(cinfo->emethods, "Empty JPEG file");
master = (my_master_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_decomp_master));
cinfo->master = (struct jpeg_decomp_master *) master;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.finish_pass = finish_pass_master;
/* Give UI a chance to adjust decompression parameters and select */
/* output file format based on info from file header. */
(*cinfo->methods->d_ui_method_selection) (cinfo);
/* Now select methods for decompression steps. */
initial_setup(cinfo);
d_initial_method_selection(cinfo);
/* Initialize the output file & other modules as needed */
/* (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);
(*cinfo->emethods->free_all) ();
/* My, that was easy, wasn't it? */
master_selection(cinfo);
}

219
jdmcu.c
View File

@@ -1,219 +0,0 @@
/*
* jdmcu.c
*
* 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 MCU disassembly routines and quantization descaling.
* 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)
{
const short * zagptr = ZAG;
short i;
for (i = DCTSIZE2-1; i >= 0; i--) {
(*outputptr)[*zagptr++] = (*input++) * (*quanttbl++);
}
}
/*
* Fetch one MCU row from entropy_decode, build coefficient array.
* This version is used for noninterleaved (single-component) scans.
*/
METHODDEF void
disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCK MCU_data[1];
long mcuindex;
jpeg_component_info * compptr;
QUANT_TBL_PTR quant_ptr;
/* this is pretty easy since there is one component and one block per MCU */
compptr = cinfo->cur_comp_info[0];
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Fetch the coefficient data */
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
/* Descale, reorder, and distribute it into the image array */
qdescale_zig(MCU_data[0], image_data[0][0] + mcuindex, quant_ptr);
}
}
/*
* Fetch one MCU row from entropy_decode, build coefficient array.
* This version is used for interleaved (multi-component) scans.
*/
METHODDEF void
disassemble_interleaved_MCU (decompress_info_ptr cinfo,
JBLOCKIMAGE image_data)
{
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
long mcuindex;
short blkn, ci, xpos, ypos;
jpeg_component_info * compptr;
QUANT_TBL_PTR quant_ptr;
JBLOCKROW image_ptr;
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
/* Fetch the coefficient data */
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
/* Descale, reorder, and distribute it into the image array */
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width);
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
qdescale_zig(MCU_data[blkn], image_ptr, quant_ptr);
image_ptr++;
blkn++;
}
}
}
}
}
/*
* 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;
long blocksperrow, bi;
short numrows, ri;
short ci;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
/* calculate size of an MCU row in this component */
blocksperrow = cinfo->cur_comp_info[ci]->subsampled_width / DCTSIZE;
numrows = cinfo->cur_comp_info[ci]->MCU_height;
/* iterate through all blocks in MCU row */
for (ri = 0; ri < numrows; ri++) {
browptr = coeff_data[ci][ri];
srowptr = output_data[ci] + (ri * DCTSIZE + start_row);
for (bi = 0; bi < blocksperrow; bi++) {
/* copy the data into a local DCTBLOCK. This allows for change of
* representation (if DCTELEM != JCOEF). On 80x86 machines it also
* brings the data back from FAR storage to NEAR storage.
*/
{ register JCOEFPTR elemptr = browptr[bi];
register DCTELEM *localblkptr = block;
register short elem = DCTSIZE2;
while (--elem >= 0)
*localblkptr++ = (DCTELEM) *elemptr++;
}
j_rev_dct(block); /* perform inverse DCT */
/* output the data into the sample array.
* Note change from signed to unsigned representation:
* DCT calculation works with values +-CENTERJSAMPLE,
* but sample arrays always hold 0..MAXJSAMPLE.
* Have to do explicit range-limiting because of quantization errors
* and so forth in the DCT/IDCT phase.
*/
{ register JSAMPROW elemptr;
register DCTELEM *localblkptr = block;
register short elemr, elemc;
register DCTELEM temp;
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = srowptr[elemr] + (bi * DCTSIZE);
for (elemc = 0; elemc < DCTSIZE; elemc++) {
temp = (*localblkptr++) + CENTERJSAMPLE;
if (temp < 0) temp = 0;
else if (temp > MAXJSAMPLE) temp = MAXJSAMPLE;
*elemptr++ = (JSAMPLE) temp;
}
}
}
}
}
}
}
/*
* Initialize for processing a scan.
*/
METHODDEF void
disassemble_init (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* Clean up after a scan.
*/
METHODDEF void
disassemble_term (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* The method selection routine for MCU disassembly.
*/
GLOBAL void
jseldmcu (decompress_info_ptr cinfo)
{
if (cinfo->comps_in_scan == 1)
cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
else
cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
cinfo->methods->reverse_DCT = reverse_DCT;
cinfo->methods->disassemble_init = disassemble_init;
cinfo->methods->disassemble_term = disassemble_term;
}

389
jdmerge.c Normal file
View File

@@ -0,0 +1,389 @@
/*
* jdmerge.c
*
* Copyright (C) 1994, 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 code for merged upsampling/color conversion.
*
* This file combines functions from jdsample.c and jdcolor.c;
* read those files first to understand what's going on.
*
* When the chroma components are to be upsampled by simple replication
* (ie, box filtering), we can save some work in color conversion by
* calculating all the output pixels corresponding to a pair of chroma
* samples at one time. In the conversion equations
* R = Y + K1 * Cr
* G = Y + K2 * Cb + K3 * Cr
* B = Y + K4 * Cb
* only the Y term varies among the group of pixels corresponding to a pair
* of chroma samples, so the rest of the terms can be calculated just once.
* At typical sampling ratios, this eliminates half or three-quarters of the
* multiplications needed for color conversion.
*
* This file currently provides implementations for the following cases:
* YCbCr => RGB color conversion only.
* Sampling ratios of 2h1v or 2h2v.
* No scaling needed at upsample time.
* Corner-aligned (non-CCIR601) sampling alignment.
* Other special cases could be added, but in most applications these are
* the only common cases. (For uncommon cases we fall back on the more
* general code in jdsample.c and jdcolor.c.)
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Private subobject */
typedef struct {
struct jpeg_upsampler pub; /* public fields */
/* Pointer to routine to do actual upsampling/conversion of one row group */
JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf));
/* Private state for YCC->RGB conversion */
int * Cr_r_tab; /* => table for Cr to R conversion */
int * Cb_b_tab; /* => table for Cb to B conversion */
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
/* For 2:1 vertical sampling, we produce two output rows at a time.
* We need a "spare" row buffer to hold the second output row if the
* application provides just a one-row buffer; we also use the spare
* to discard the dummy last row if the image height is odd.
*/
JSAMPROW spare_row;
boolean spare_full; /* T if spare buffer is occupied */
JDIMENSION out_row_width; /* samples per output row */
JDIMENSION rows_to_go; /* counts rows remaining in image */
} my_upsampler;
typedef my_upsampler * my_upsample_ptr;
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
/*
* Initialize for an upsampling pass.
*/
METHODDEF void
start_pass_merged_upsample (j_decompress_ptr cinfo)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
INT32 i, x2;
SHIFT_TEMPS
/* Mark the spare buffer empty */
upsample->spare_full = FALSE;
/* Initialize total-height counter for detecting bottom of image */
upsample->rows_to_go = cinfo->output_height;
/* Initialize the YCC=>RGB conversion tables.
* This is taken directly from jdcolor.c; see that file for more info.
*/
upsample->Cr_r_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
upsample->Cb_b_tab = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(int));
upsample->Cr_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
upsample->Cb_g_tab = (INT32 *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(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 */
upsample->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 */
upsample->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
upsample->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 */
upsample->Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF;
}
}
/*
* Control routine to do upsampling (and color conversion).
*
* The control routine just handles the row buffering considerations.
*/
METHODDEF void
merged_2v_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
/* 2:1 vertical sampling case: may need a spare row. */
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
JSAMPROW work_ptrs[2];
JDIMENSION num_rows; /* number of rows returned to caller */
if (upsample->spare_full) {
/* If we have a spare row saved from a previous cycle, just return it. */
jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
1, upsample->out_row_width);
num_rows = 1;
upsample->spare_full = FALSE;
} else {
/* Figure number of rows to return to caller. */
num_rows = 2;
/* Not more than the distance to the end of the image. */
if (num_rows > upsample->rows_to_go)
num_rows = upsample->rows_to_go;
/* And not more than what the client can accept: */
out_rows_avail -= *out_row_ctr;
if (num_rows > out_rows_avail)
num_rows = out_rows_avail;
/* Create output pointer array for upsampler. */
work_ptrs[0] = output_buf[*out_row_ctr];
if (num_rows > 1) {
work_ptrs[1] = output_buf[*out_row_ctr + 1];
} else {
work_ptrs[1] = upsample->spare_row;
upsample->spare_full = TRUE;
}
/* Now do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
}
/* Adjust counts */
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
/* When the buffer is emptied, declare this input row group consumed */
if (! upsample->spare_full)
(*in_row_group_ctr)++;
}
METHODDEF void
merged_1v_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
/* 1:1 vertical sampling case: much easier, never need a spare row. */
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
/* Just do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
output_buf + *out_row_ctr);
/* Adjust counts */
(*out_row_ctr)++;
(*in_row_group_ctr)++;
}
/*
* These are the routines invoked by the control routines to do
* the actual upsampling/conversion. One row group is processed per call.
*
* Note: since we may be writing directly into application-supplied buffers,
* we have to be honest about the output width; we can't assume the buffer
* has been rounded up to an even width.
*/
/*
* Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
*/
METHODDEF void
h2v1_merged_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
int * Crrtab = upsample->Cr_r_tab;
int * Cbbtab = upsample->Cb_b_tab;
INT32 * Crgtab = upsample->Cr_g_tab;
INT32 * Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr0 = input_buf[0][in_row_group_ctr];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr = output_buf[0];
/* Loop for each pair of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
outptr += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr0++);
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
outptr += RGB_PIXELSIZE;
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
}
}
/*
* Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
*/
METHODDEF void
h2v2_merged_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
JSAMPARRAY output_buf)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
register JSAMPLE * range_limit = cinfo->sample_range_limit;
int * Crrtab = upsample->Cr_r_tab;
int * Cbbtab = upsample->Cb_b_tab;
INT32 * Crgtab = upsample->Cr_g_tab;
INT32 * Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr00 = input_buf[0][in_row_group_ctr*2];
inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
outptr1 = output_buf[1];
/* Loop for each group of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr00++);
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
outptr1 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
outptr1 += RGB_PIXELSIZE;
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
y = GETJSAMPLE(*inptr01);
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
}
}
/*
* Module initialization routine for merged upsampling/color conversion.
*
* NB: this is called under the conditions determined by use_merged_upsample()
* in jdmaster.c. That routine MUST correspond to the actual capabilities
* of this module; no safety checks are made here.
*/
GLOBAL void
jinit_merged_upsampler (j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
upsample = (my_upsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_upsampler));
cinfo->upsample = (struct jpeg_upsampler *) upsample;
upsample->pub.start_pass = start_pass_merged_upsample;
upsample->pub.need_context_rows = FALSE;
upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
if (cinfo->max_v_samp_factor == 2) {
upsample->pub.upsample = merged_2v_upsample;
upsample->upmethod = h2v2_merged_upsample;
/* Allocate a spare row buffer */
upsample->spare_row = (JSAMPROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
} else {
upsample->pub.upsample = merged_1v_upsample;
upsample->upmethod = h2v1_merged_upsample;
/* No spare row needed */
upsample->spare_row = NULL;
}
}
#endif /* UPSAMPLE_MERGING_SUPPORTED */

1008
jdpipe.c

File diff suppressed because it is too large Load Diff

275
jdpostct.c Normal file
View File

@@ -0,0 +1,275 @@
/*
* jdpostct.c
*
* Copyright (C) 1994, 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 decompression postprocessing controller.
* This controller manages the upsampling, color conversion, and color
* quantization/reduction steps; specifically, it controls the buffering
* between upsample/color conversion and color quantization/reduction.
*
* If no color quantization/reduction is required, then this module has no
* work to do, and it just hands off to the upsample/color conversion code.
* An integrated upsample/convert/quantize process would replace this module
* entirely.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Private buffer controller object */
typedef struct {
struct jpeg_d_post_controller pub; /* public fields */
/* Color quantization source buffer: this holds output data from
* the upsample/color conversion step to be passed to the quantizer.
* For two-pass color quantization, we need a full-image buffer;
* for one-pass operation, a strip buffer is sufficient.
*/
jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
JDIMENSION strip_height; /* buffer size in rows */
/* for two-pass mode only: */
JDIMENSION starting_row; /* row # of first row in current strip */
JDIMENSION next_row; /* index of next row to fill/empty in strip */
} my_post_controller;
typedef my_post_controller * my_post_ptr;
/* Forward declarations */
METHODDEF void post_process_1pass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF void post_process_prepass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
METHODDEF void post_process_2pass
JPP((j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
#endif
/*
* Initialize for a processing pass.
*/
METHODDEF void
start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (cinfo->quantize_colors) {
/* Single-pass processing with color quantization. */
post->pub.post_process_data = post_process_1pass;
} else {
/* For single-pass processing without color quantization,
* I have no work to do; just call the upsampler directly.
*/
post->pub.post_process_data = cinfo->upsample->upsample;
}
break;
#ifdef QUANT_2PASS_SUPPORTED
case JBUF_SAVE_AND_PASS:
/* First pass of 2-pass quantization */
if (post->whole_image == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
post->pub.post_process_data = post_process_prepass;
break;
case JBUF_CRANK_DEST:
/* Second pass of 2-pass quantization */
if (post->whole_image == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
post->pub.post_process_data = post_process_2pass;
break;
#endif /* QUANT_2PASS_SUPPORTED */
default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
post->starting_row = post->next_row = 0;
}
/*
* Process some data in the one-pass (strip buffer) case.
* This is used for color precision reduction as well as one-pass quantization.
*/
METHODDEF void
post_process_1pass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION num_rows, max_rows;
/* Fill the buffer, but not more than what we can dump out in one go. */
/* Note we rely on the upsampler to detect bottom of image. */
max_rows = out_rows_avail - *out_row_ctr;
if (max_rows > post->strip_height)
max_rows = post->strip_height;
num_rows = 0;
(*cinfo->upsample->upsample) (cinfo,
input_buf, in_row_group_ctr, in_row_groups_avail,
post->buffer, &num_rows, max_rows);
/* Quantize and emit data. */
(*cinfo->cquantize->color_quantize) (cinfo,
post->buffer, output_buf + *out_row_ctr, (int) num_rows);
*out_row_ctr += num_rows;
}
#ifdef QUANT_2PASS_SUPPORTED
/*
* Process some data in the first pass of 2-pass quantization.
*/
METHODDEF void
post_process_prepass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION old_next_row, num_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, post->whole_image, post->starting_row, TRUE);
}
/* Upsample some data (up to a strip height's worth). */
old_next_row = post->next_row;
(*cinfo->upsample->upsample) (cinfo,
input_buf, in_row_group_ctr, in_row_groups_avail,
post->buffer, &post->next_row, post->strip_height);
/* Allow quantizer to scan new data. No data is emitted, */
/* but we advance out_row_ctr so outer loop can tell when we're done. */
if (post->next_row > old_next_row) {
num_rows = post->next_row - old_next_row;
(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
(JSAMPARRAY) NULL, (int) num_rows);
*out_row_ctr += num_rows;
}
/* Advance if we filled the strip. */
if (post->next_row >= post->strip_height) {
post->starting_row += post->strip_height;
post->next_row = 0;
}
}
/*
* Process some data in the second pass of 2-pass quantization.
*/
METHODDEF void
post_process_2pass (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_post_ptr post = (my_post_ptr) cinfo->post;
JDIMENSION num_rows, max_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, post->whole_image, post->starting_row, FALSE);
}
/* Determine number of rows to emit. */
num_rows = post->strip_height - post->next_row; /* available in strip */
max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
if (num_rows > max_rows)
num_rows = max_rows;
/* We have to check bottom of image here, can't depend on upsampler. */
max_rows = cinfo->output_height - post->starting_row;
if (num_rows > max_rows)
num_rows = max_rows;
/* Quantize and emit data. */
(*cinfo->cquantize->color_quantize) (cinfo,
post->buffer + post->next_row, output_buf + *out_row_ctr,
(int) num_rows);
*out_row_ctr += num_rows;
/* Advance if we filled the strip. */
post->next_row += num_rows;
if (post->next_row >= post->strip_height) {
post->starting_row += post->strip_height;
post->next_row = 0;
}
}
#endif /* QUANT_2PASS_SUPPORTED */
/*
* Initialize postprocessing controller.
*/
GLOBAL void
jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_post_ptr post;
post = (my_post_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_post_controller));
cinfo->post = (struct jpeg_d_post_controller *) post;
post->pub.start_pass = start_pass_dpost;
post->whole_image = NULL; /* flag for no virtual arrays */
/* Create the quantization buffer, if needed */
if (cinfo->quantize_colors) {
/* The buffer strip height is max_v_samp_factor, which is typically
* an efficient number of rows for upsampling to return.
* (In the presence of output rescaling, we might want to be smarter?)
*/
post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
if (need_full_buffer) {
/* Two-pass color quantization: need full-image storage. */
#ifdef QUANT_2PASS_SUPPORTED
post->whole_image = (*cinfo->mem->request_virt_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->output_width * cinfo->out_color_components,
cinfo->output_height, post->strip_height);
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
#endif /* QUANT_2PASS_SUPPORTED */
} else {
/* One-pass color quantization: just make a strip buffer. */
post->buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->output_width * cinfo->out_color_components,
post->strip_height);
}
}
}

View File

@@ -1,220 +1,478 @@
/*
* jdsample.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, 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.
*
* Upsampling input data is counted in "row groups". A row group
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
* sample rows of each component. Upsampling will normally produce
* max_v_samp_factor pixel rows from each row group (but this could vary
* if the upsampler is applying a scale factor of its own).
*
* 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.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
/* Pointer to routine to upsample a single component */
typedef JMETHOD(void, upsample1_ptr,
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
/* Private subobject */
typedef struct {
struct jpeg_upsampler pub; /* public fields */
/* Color conversion buffer. When using separate upsampling and color
* conversion steps, this buffer holds one upsampled row group until it
* has been color converted and output.
* Note: we do not allocate any storage for component(s) which are full-size,
* ie do not need rescaling. The corresponding entry of color_buf[] is
* simply set to point to the input data array, thereby avoiding copying.
*/
JSAMPARRAY color_buf[MAX_COMPONENTS];
/* Per-component upsampling method pointers */
upsample1_ptr methods[MAX_COMPONENTS];
int next_row_out; /* counts rows emitted from color_buf */
JDIMENSION rows_to_go; /* counts rows remaining in image */
/* Height of an input row group for each component. */
int rowgroup_height[MAX_COMPONENTS];
/* These arrays save pixel expansion factors so that int_expand need not
* recompute them each time. They are unused for other upsampling methods.
*/
UINT8 h_expand[MAX_COMPONENTS];
UINT8 v_expand[MAX_COMPONENTS];
} my_upsampler;
typedef my_upsampler * my_upsample_ptr;
/*
* Initialize for un-subsampling a scan.
* Initialize for an upsampling pass.
*/
METHODDEF void
unsubsample_init (decompress_info_ptr cinfo)
start_pass_upsample (j_decompress_ptr cinfo)
{
/* no work for now */
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
/* Mark the conversion buffer empty */
upsample->next_row_out = cinfo->max_v_samp_factor;
/* Initialize total-height counter for detecting bottom of image */
upsample->rows_to_go = cinfo->output_height;
}
/*
* Control routine to do upsampling (and color conversion).
*
* In this version we upsample each component independently.
* We upsample one row group into the conversion buffer, then apply
* color conversion a row at a time.
*/
METHODDEF void
sep_upsample (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
int ci;
jpeg_component_info * compptr;
JDIMENSION num_rows;
/* Fill the conversion buffer, if it's empty */
if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Invoke per-component upsample method. Notice we pass a POINTER
* to color_buf[ci], so that fullsize_upsample can change it.
*/
(*upsample->methods[ci]) (cinfo, compptr,
input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
upsample->color_buf + ci);
}
upsample->next_row_out = 0;
}
/* Color-convert and emit rows */
/* How many we have in the buffer: */
num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
/* Not more than the distance to the end of the image. Need this test
* in case the image height is not a multiple of max_v_samp_factor:
*/
if (num_rows > upsample->rows_to_go)
num_rows = upsample->rows_to_go;
/* And not more than what the client can accept: */
out_rows_avail -= *out_row_ctr;
if (num_rows > out_rows_avail)
num_rows = out_rows_avail;
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
(JDIMENSION) upsample->next_row_out,
output_buf + *out_row_ctr,
(int) num_rows);
/* Adjust counts */
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
upsample->next_row_out += num_rows;
/* When the buffer is emptied, declare this input row group consumed */
if (upsample->next_row_out >= cinfo->max_v_samp_factor)
(*in_row_group_ctr)++;
}
/*
* These are the routines invoked by sep_upsample to upsample pixel values
* of a single component. One row group is processed per call.
*/
/*
* For full-size components, we just make color_buf[ci] point at the
* input buffer, and thus avoid copying any data. Note that this is
* safe only because sep_upsample doesn't declare the input row group
* "consumed" until we are done color converting and emitting it.
*/
METHODDEF void
fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
*output_data_ptr = input_data;
}
/*
* This is a no-op version used for "uninteresting" components.
* These components will not be referenced by color conversion.
*/
METHODDEF void
noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
*output_data_ptr = NULL; /* safety check */
}
/*
* Un-subsample 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
int_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 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
register short h_expand, h;
short v_expand, v;
register int h;
JSAMPROW outend;
int h_expand, v_expand;
int inrow, outrow;
register long incol;
#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");
#endif
h_expand = upsample->h_expand[compptr->component_index];
v_expand = upsample->v_expand[compptr->component_index];
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
outrow = 0;
for (inrow = 0; inrow < input_rows; inrow++) {
for (v = 0; v < v_expand; v++) {
inptr = input_data[inrow];
outptr = output_data[outrow++];
for (incol = 0; incol < input_cols; incol++) {
invalue = GETJSAMPLE(*inptr++);
for (h = 0; h < h_expand; h++) {
*outptr++ = invalue;
}
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
/* Generate one output row with proper horizontal expansion */
inptr = input_data[inrow];
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
for (h = h_expand; h > 0; h--) {
*outptr++ = invalue;
}
}
/* Generate any additional output rows by duplicating the first one */
if (v_expand > 1) {
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
v_expand-1, cinfo->output_width);
}
inrow++;
outrow += v_expand;
}
}
/*
* Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
* It's still a box filter.
*/
METHODDEF void
h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
JSAMPROW outend;
int inrow;
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
inptr = input_data[inrow];
outptr = output_data[inrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
*outptr++ = invalue;
*outptr++ = invalue;
}
}
}
/*
* Un-subsample pixel values of a single component.
* This version handles the extremely common case of
* horizontal expansion by 2 and any integral vertical expansion.
* Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
* It's still a box filter.
*/
METHODDEF void
h2_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)
h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
short v_expand, v;
JSAMPROW outend;
int inrow, outrow;
register long incol;
#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");
#endif
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
/* The subsampled image width will always be a multiple of DCTSIZE,
* so we can unroll the inner loop.
*/
outrow = 0;
for (inrow = 0; inrow < input_rows; inrow++) {
for (v = 0; v < v_expand; v++) {
inptr = input_data[inrow];
outptr = output_data[outrow++];
#if DCTSIZE == 8
for (incol = 0; incol < input_cols; incol += DCTSIZE) {
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
}
#else /* nonstandard DCTSIZE */
for (incol = 0; incol < input_cols; incol++) {
invalue = GETJSAMPLE(*inptr++);
*outptr++ = invalue;
*outptr++ = invalue;
}
#endif
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
inptr = input_data[inrow];
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
*outptr++ = invalue;
*outptr++ = invalue;
}
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
1, cinfo->output_width);
inrow++;
outrow += 2;
}
}
/*
* Un-subsample pixel values of a single component.
* This version handles the special case of a full-size component.
* Fancy processing for 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.
*
* A note about the "bias" calculations: when rounding fractional values to
* integer, we do not want to always round 0.5 up to the next integer.
* If we did that, we'd introduce a noticeable bias towards larger values.
* Instead, this code is arranged so that 0.5 will be rounded up or down at
* alternate pixel locations (a simple ordered dither pattern).
*/
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)
h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
#ifdef DEBUG /* for debugging pipeline controller */
if (input_cols != output_cols || input_rows != output_rows)
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register int invalue;
register JDIMENSION colctr;
int inrow;
for (inrow = 0; inrow < cinfo->max_v_samp_factor; 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 = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = GETJSAMPLE(*inptr++) * 3;
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
*outptr++ = (JSAMPLE) invalue;
}
}
/*
* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
* Again a triangle filter; see comments for h2v1 case, above.
*
* It is OK for us to reference the adjacent input rows because we demanded
* context from the main buffer controller (see initialization code).
*/
METHODDEF void
h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr0, inptr1, outptr;
#if BITS_IN_JSAMPLE == 8
register int thiscolsum, lastcolsum, nextcolsum;
#else
register INT32 thiscolsum, lastcolsum, nextcolsum;
#endif
register JDIMENSION colctr;
int inrow, outrow, v;
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
inrow = outrow = 0;
while (outrow < cinfo->max_v_samp_factor) {
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 */
inptr1 = input_data[inrow-1];
else /* next nearest is row below */
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 + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
for (colctr = compptr->downsampled_width - 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 + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
}
/* Special case for last column */
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
}
inrow++;
}
}
/*
* Clean up after a scan.
*/
METHODDEF void
unsubsample_term (decompress_info_ptr cinfo)
{
/* no work for now */
}
/*
* The method selection routine for unsubsampling.
* Note that we must select a routine for each component.
* Module initialization routine for upsampling.
*/
GLOBAL void
jselunsubsample (decompress_info_ptr cinfo)
jinit_upsampler (j_decompress_ptr cinfo)
{
short ci;
my_upsample_ptr upsample;
int ci;
jpeg_component_info * compptr;
boolean need_buffer, do_fancy;
int h_in_group, v_in_group, h_out_group, v_out_group;
if (cinfo->CCIR601_sampling)
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
upsample = (my_upsample_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_upsampler));
cinfo->upsample = (struct jpeg_upsampler *) upsample;
upsample->pub.start_pass = start_pass_upsample;
upsample->pub.upsample = sep_upsample;
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
compptr->v_samp_factor == cinfo->max_v_samp_factor)
cinfo->methods->unsubsample[ci] = fullsize_unsubsample;
else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
cinfo->methods->unsubsample[ci] = h2_unsubsample;
else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
cinfo->methods->unsubsample[ci] = int_unsubsample;
else
ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
* so don't ask for it.
*/
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
/* Verify we can handle the sampling factors, select per-component methods,
* and create storage as needed.
*/
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Compute size of an "input group" after IDCT scaling. This many samples
* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
*/
h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size;
v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
cinfo->min_DCT_scaled_size;
h_out_group = cinfo->max_h_samp_factor;
v_out_group = cinfo->max_v_samp_factor;
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
need_buffer = TRUE;
if (! compptr->component_needed) {
/* Don't bother to upsample an uninteresting component. */
upsample->methods[ci] = noop_upsample;
need_buffer = FALSE;
} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
/* Fullsize components can be processed without any work. */
upsample->methods[ci] = fullsize_upsample;
need_buffer = FALSE;
} else if (h_in_group * 2 == h_out_group &&
v_in_group == v_out_group) {
/* Special cases for 2h1v upsampling */
if (do_fancy && compptr->downsampled_width > 2)
upsample->methods[ci] = h2v1_fancy_upsample;
else
upsample->methods[ci] = h2v1_upsample;
} else if (h_in_group * 2 == h_out_group &&
v_in_group * 2 == v_out_group) {
/* Special cases for 2h2v upsampling */
if (do_fancy && compptr->downsampled_width > 2) {
upsample->methods[ci] = h2v2_fancy_upsample;
upsample->pub.need_context_rows = TRUE;
} else
upsample->methods[ci] = h2v2_upsample;
} else if ((h_out_group % h_in_group) == 0 &&
(v_out_group % v_in_group) == 0) {
/* Generic integral-factors upsampling method */
upsample->methods[ci] = int_upsample;
upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
if (need_buffer) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) cinfo->output_width,
(long) cinfo->max_h_samp_factor),
(JDIMENSION) cinfo->max_v_samp_factor);
}
}
cinfo->methods->unsubsample_init = unsubsample_init;
cinfo->methods->unsubsample_term = unsubsample_term;
}

213
jerror.c
View File

@@ -1,72 +1,211 @@
/*
* jerror.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains simple error-reporting and trace-message routines.
* These are suitable for Unix-like systems and others where writing to
* stderr is the right thing to do. If the JPEG software is integrated
* into a larger application, you may well need to replace these.
*
* The error_exit() routine should not return to its caller. Within a
* larger application, you might want to have it do a longjmp() to return
* control to the outer user interface routine. This should work since
* the portable JPEG code doesn't use setjmp/longjmp. You should make sure
* that free_all is called either within error_exit or after the return to
* the outer-level routine.
* stderr is the right thing to do. Many applications will want to replace
* some or all of these routines.
*
* These routines are used by both the compression and decompression code.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h> /* to declare exit() */
#endif
#include "jpeglib.h"
#include "jversion.h"
#include "jerror.h" /* get error codes */
#define JMAKE_MSG_TABLE
#include "jerror.h" /* create message string table */
#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, free_all */
/*
* Error exit handler: must not return to caller.
*
* Applications may override this if they want to get control back after
* an error. Typically one would longjmp somewhere instead of exiting.
* The setjmp buffer can be made a private field within an expanded error
* handler object. Note that the info needed to generate an error message
* is stored in the error object, so you can generate the message now or
* later, at your convenience.
* You should make sure that the JPEG object is cleaned up (with jpeg_abort
* or jpeg_destroy) at some point.
*/
METHODDEF void
trace_message (const char *msgtext)
error_exit (j_common_ptr cinfo)
{
fprintf(stderr, msgtext,
methods->message_parm[0], methods->message_parm[1],
methods->message_parm[2], methods->message_parm[3],
methods->message_parm[4], methods->message_parm[5],
methods->message_parm[6], methods->message_parm[7]);
fprintf(stderr, "\n");
}
/* Always display the message */
(*cinfo->err->output_message) (cinfo);
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
METHODDEF void
error_exit (const char *msgtext)
{
trace_message(msgtext);
(*methods->free_all) (); /* clean up memory allocation */
exit(EXIT_FAILURE);
}
/*
* The method selection routine for simple error handling.
* The system-dependent setup routine should call this routine
* to install the necessary method pointers in the supplied struct.
* Actual output of an error or trace message.
* Applications may override this method to send JPEG messages somewhere
* other than stderr.
*/
GLOBAL void
jselerror (external_methods_ptr emethods)
METHODDEF void
output_message (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for later access */
char buffer[JMSG_LENGTH_MAX];
emethods->error_exit = error_exit;
emethods->trace_message = trace_message;
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
emethods->trace_level = 0; /* default = no tracing */
/* Send it to stderr, adding a newline */
fprintf(stderr, "%s\n", buffer);
}
/*
* Decide whether to emit a trace or warning message.
* msg_level is one of:
* -1: recoverable corrupt-data warning, may want to abort.
* 0: important advisory messages (always display to user).
* 1: first level of tracing detail.
* 2,3,...: successively more detailed tracing messages.
* An application might override this method if it wanted to abort on warnings
* or change the policy about which messages to display.
*/
METHODDEF void
emit_message (j_common_ptr cinfo, int msg_level)
{
struct jpeg_error_mgr * err = cinfo->err;
if (msg_level < 0) {
/* It's a warning message. Since corrupt files may generate many warnings,
* the policy implemented here is to show only the first warning,
* unless trace_level >= 3.
*/
if (err->num_warnings == 0 || err->trace_level >= 3)
(*err->output_message) (cinfo);
/* Always count warnings in num_warnings. */
err->num_warnings++;
} else {
/* It's a trace message. Show it if trace_level >= msg_level. */
if (err->trace_level >= msg_level)
(*err->output_message) (cinfo);
}
}
/*
* Format a message string for the most recent JPEG error or message.
* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
* characters. Note that no '\n' character is added to the string.
* Few applications should need to override this method.
*/
METHODDEF void
format_message (j_common_ptr cinfo, char * buffer)
{
struct jpeg_error_mgr * err = cinfo->err;
int msg_code = err->msg_code;
const char * msgtext = NULL;
const char * msgptr;
char ch;
boolean isstring;
/* Look up message string in proper table */
if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
msgtext = err->jpeg_message_table[msg_code];
} else if (err->addon_message_table != NULL &&
msg_code >= err->first_addon_message &&
msg_code <= err->last_addon_message) {
msgtext = err->addon_message_table[msg_code - err->first_addon_message];
}
/* Defend against bogus message number */
if (msgtext == NULL) {
err->msg_parm.i[0] = msg_code;
msgtext = err->jpeg_message_table[0];
}
/* Check for string parameter, as indicated by %s in the message text */
isstring = FALSE;
msgptr = msgtext;
while ((ch = *msgptr++) != '\0') {
if (ch == '%') {
if (*msgptr == 's') isstring = TRUE;
break;
}
}
/* Format the message into the passed buffer */
if (isstring)
sprintf(buffer, msgtext, err->msg_parm.s);
else
sprintf(buffer, msgtext,
err->msg_parm.i[0], err->msg_parm.i[1],
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
err->msg_parm.i[6], err->msg_parm.i[7]);
}
/*
* Reset error state variables at start of a new image.
* This is called during compression startup to reset trace/error
* processing to default state, without losing any application-specific
* method pointers. An application might possibly want to override
* this method if it has additional error processing state.
*/
METHODDEF void
reset_error_mgr (j_common_ptr cinfo)
{
cinfo->err->num_warnings = 0;
/* trace_level is not reset since it is an application-supplied parameter */
cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
}
/*
* Fill in the standard error-handling methods in a jpeg_error_mgr object.
* Typical call is:
* struct jpeg_compress_struct cinfo;
* struct jpeg_error_mgr err;
*
* cinfo.err = jpeg_std_error(&err);
* after which the application may override some of the methods.
*/
GLOBAL struct jpeg_error_mgr *
jpeg_std_error (struct jpeg_error_mgr * err)
{
err->error_exit = error_exit;
err->emit_message = emit_message;
err->output_message = output_message;
err->format_message = format_message;
err->reset_error_mgr = reset_error_mgr;
err->trace_level = 0; /* default = no tracing */
err->num_warnings = 0; /* no warnings emitted yet */
err->msg_code = 0; /* may be useful as a flag for "no error" */
/* Initialize message table pointers */
err->jpeg_message_table = jpeg_message_table;
err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
err->addon_message_table = NULL;
err->first_addon_message = 0; /* for safety */
err->last_addon_message = 0;
return err;
}

264
jerror.h Normal file
View File

@@ -0,0 +1,264 @@
/*
* jerror.h
*
* Copyright (C) 1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the JPEG library.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
* A set of error-reporting macros are defined too. Some applications using
* the JPEG library may wish to include this file to get the error codes
* and/or the macros.
*/
/* To define the enum list of message codes, include this file without
* defining JMAKE_MSG_TABLE. To create the message string table, include it
* again with JMAKE_MSG_TABLE defined (this should be done in just one module).
*/
#ifdef JMAKE_MSG_TABLE
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_message_table jMsgTable
#endif
const char * const jpeg_message_table[] = {
#define JMESSAGE(code,string) string ,
#else /* not JMAKE_MSG_TABLE */
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_MSG_TABLE */
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
JMESSAGE(JERR_ARITH_NOTIMPL,
"Sorry, there are legal restrictions on arithmetic coding")
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts")
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
JMESSAGE(JERR_FILE_READ, "Input file read error")
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
JMESSAGE(JERR_JFIF_MAJOR, "Unsupported JFIF revision number %d.%02d")
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
JMESSAGE(JERR_QUANT_COMPONENTS,
"Cannot quantize more than %d color components")
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
JMESSAGE(JERR_TFILE_WRITE,
"Write failed on temporary file --- out of disk space?")
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
JMESSAGE(JMSG_VERSION, JVERSION)
JMESSAGE(JTRC_16BIT_TABLES,
"Caution: quantization tables are too coarse for baseline JPEG")
JMESSAGE(JTRC_ADOBE,
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
JMESSAGE(JTRC_EOI, "End Of Image")
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_MINOR, "Warning: unknown JFIF revision number %d.%02d")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
JMESSAGE(JTRC_RST, "RST%d")
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
"Smoothing not supported with nonstandard sampling ratios")
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
JMESSAGE(JTRC_SOI, "Start of Image")
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
JMESSAGE(JTRC_UNKNOWN_IDS,
"Unrecognized component IDs %d %d %d, assuming YCbCr")
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
JMESSAGE(JWRN_EXTRANEOUS_DATA,
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
JMESSAGE(JWRN_MUST_RESYNC,
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
#ifdef JMAKE_MSG_TABLE
NULL
};
#else /* not JMAKE_MSG_TABLE */
JMSG_LASTMSGCODE
} J_MESSAGE_CODE;
#endif /* JMAKE_MSG_TABLE */
#undef JMESSAGE
#ifndef JMAKE_MSG_TABLE
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#endif /* JMAKE_MSG_TABLE */

168
jfdctflt.c Normal file
View File

@@ -0,0 +1,168 @@
/*
* jfdctflt.c
*
* Copyright (C) 1994, 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 floating-point implementation of the
* forward DCT (Discrete Cosine Transform).
*
* This implementation should be more accurate than either of the integer
* DCT implementations. However, it may not give the same results on all
* machines because of differences in roundoff behavior. Speed will depend
* on the hardware's floating point capacity.
*
* 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.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with a fixed-point
* implementation, accuracy is lost due to imprecise representation of the
* scaled quantization values. However, that problem does not arise if
* we use floating point arithmetic.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_FLOAT_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL void
jpeg_fdct_float (FAST_FLOAT * data)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
FAST_FLOAT *dataptr;
int ctr;
/* Pass 1: process rows. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dataptr[DCTSIZE*4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
dataptr[DCTSIZE*6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
dataptr[DCTSIZE*3] = z13 - z2;
dataptr[DCTSIZE*1] = z11 + z4;
dataptr[DCTSIZE*7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_FLOAT_SUPPORTED */

224
jfdctfst.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* jfdctfst.c
*
* Copyright (C) 1994, 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 fast, not so accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* 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.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with fixed-point math,
* accuracy is lost due to imprecise representation of the scaled
* quantization values. The smaller the quantization table entry, the less
* precise the scaled value, so this implementation does worse with high-
* quality-setting files than with low-quality ones.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_IFAST_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling decisions are generally the same as in the LL&M algorithm;
* see jfdctint.c for more details. However, we choose to descale
* (right shift) multiplication products as soon as they are formed,
* rather than carrying additional fractional bits into subsequent additions.
* This compromises accuracy slightly, but it lets us save a few shifts.
* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
* everywhere except in the multiplications proper; this saves a good deal
* of work on 16-bit-int machines.
*
* Again to save a few shifts, the intermediate results between pass 1 and
* pass 2 are not upscaled, but are represented only to integral precision.
*
* A final compromise is to represent the multiplicative constants to only
* 8 fractional bits, rather than 13. This saves some shifting work on some
* machines, and may also reduce the cost of multiplication (since there
* are fewer one-bits in the constants).
*/
#define CONST_BITS 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...)
*/
#if CONST_BITS == 8
#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
#else
#define FIX_0_382683433 FIX(0.382683433)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_707106781 FIX(0.707106781)
#define FIX_1_306562965 FIX(1.306562965)
#endif
/* We can gain a little more speed, with a further compromise in accuracy,
* by omitting the addition in a descaling shift. This yields an incorrectly
* rounded result half the time...
*/
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
#define DESCALE(x,n) RIGHT_SHIFT(x, n)
#endif
/* Multiply a DCTELEM variable by an INT32 constant, and immediately
* descale to yield a DCTELEM result.
*/
#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL void
jpeg_fdct_ifast (DCTELEM * data)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
DCTELEM z1, z2, z3, z4, z5, z11, z13;
DCTELEM *dataptr;
int ctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dataptr[DCTSIZE*4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
dataptr[DCTSIZE*6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
dataptr[DCTSIZE*3] = z13 - z2;
dataptr[DCTSIZE*1] = z11 + z4;
dataptr[DCTSIZE*7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_IFAST_SUPPORTED */

283
jfdctint.c Normal file
View File

@@ -0,0 +1,283 @@
/*
* jfdctint.c
*
* Copyright (C) 1991-1994, 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 slow-but-accurate integer implementation of the
* forward DCT (Discrete Cosine Transform).
*
* 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.
*
* 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.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_ISLOW_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/*
* 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).
* In the IJG code, this factor of 8 is removed by the quantization step
* (in jcdctmgr.c), NOT in this module.
*
* 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 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.
*
* 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. (For 12-bit sample data, the intermediate
* array is INT32 anyway.)
*
* 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.
*/
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* 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...)
*/
#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
/* 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.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the forward DCT on one block of samples.
*/
GLOBAL void
jpeg_fdct_islow (DCTELEM * data)
{
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
DCTELEM *dataptr;
int ctr;
SHIFT_TEMPS
/* 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 (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
*/
dataptr = data;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
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);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*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[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
CONST_BITS+PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
}
#endif /* DCT_ISLOW_SUPPORTED */

208
jfwddct.c
View File

@@ -1,208 +0,0 @@
/*
* jfwddct.c
*
* 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.
*/
#include "jinclude.h"
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* The poop on this scaling stuff is as follows:
*
* 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).
*
* 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.
*/
#ifdef EIGHT_BIT_SAMPLES
#define LG2_DCT_SCALE 16
#else
#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
/* 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)
/* Scale a fractional constant by DCT_SCALE */
#define FIX(x) ((INT32) ((x) * DCT_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 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 pass, rowctr;
register DCTELEM *inptr, *outptr;
DCTBLOCK workspace;
/* Each iteration of the inner loop performs one 8-point 1-D DCT.
* It reads from a *row* of the input matrix and stores into a *column*
* of the output matrix. In the first pass, we read from the data[] array
* and store into the local workspace[]. In the second pass, we read from
* the workspace[] array and store into data[], thus performing the
* equivalent of a columnar DCT pass with no variable array indexing.
*/
inptr = data; /* initialize pointers for first pass */
outptr = workspace;
for (pass = 1; pass >= 0; pass--) {
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* many tmps have nonoverlapping lifetime -- flashy register colourers
* should be able to do this lot very well
*/
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 tmp14, tmp15, tmp16, tmp17;
INT32 tmp25, tmp26;
SHIFT_TEMPS
tmp0 = inptr[7] + inptr[0];
tmp1 = inptr[6] + inptr[1];
tmp2 = inptr[5] + inptr[2];
tmp3 = inptr[4] + inptr[3];
tmp4 = inptr[3] - inptr[4];
tmp5 = inptr[2] - inptr[5];
tmp6 = inptr[1] - inptr[6];
tmp7 = inptr[0] - inptr[7];
tmp10 = tmp3 + tmp0;
tmp11 = tmp2 + tmp1;
tmp12 = tmp1 - tmp2;
tmp13 = tmp0 - tmp3;
outptr[ 0] = (DCTELEM) UNFIXH((tmp10 + tmp11) * SIN_1_4);
outptr[DCTSIZE*4] = (DCTELEM) UNFIXH((tmp10 - tmp11) * COS_1_4);
outptr[DCTSIZE*2] = (DCTELEM) UNFIXH(tmp13*COS_1_8 + tmp12*SIN_1_8);
outptr[DCTSIZE*6] = (DCTELEM) UNFIXH(tmp13*SIN_1_8 - tmp12*COS_1_8);
tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4);
tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4);
OVERSHIFT(tmp4);
OVERSHIFT(tmp7);
/* tmp4, tmp7, tmp15, tmp16 are overscaled by OVERSCALE */
tmp14 = tmp4 + tmp15;
tmp25 = tmp4 - tmp15;
tmp26 = tmp7 - tmp16;
tmp17 = tmp7 + tmp16;
outptr[DCTSIZE ] = (DCTELEM) UNFIXH(tmp17*OCOS_1_16 + tmp14*OSIN_1_16);
outptr[DCTSIZE*7] = (DCTELEM) UNFIXH(tmp17*OCOS_7_16 - tmp14*OSIN_7_16);
outptr[DCTSIZE*5] = (DCTELEM) UNFIXH(tmp26*OCOS_5_16 + tmp25*OSIN_5_16);
outptr[DCTSIZE*3] = (DCTELEM) UNFIXH(tmp26*OCOS_3_16 - tmp25*OSIN_3_16);
inptr += DCTSIZE; /* advance inptr to next row */
outptr++; /* advance outptr to next column */
}
/* end of pass; in case it was pass 1, set up for pass 2 */
inptr = workspace;
outptr = data;
}
}

241
jidctflt.c Normal file
View File

@@ -0,0 +1,241 @@
/*
* jidctflt.c
*
* Copyright (C) 1994, 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 floating-point implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* This implementation should be more accurate than either of the integer
* IDCT implementations. However, it may not give the same results on all
* machines because of differences in roundoff behavior. Speed will depend
* on the hardware's floating point capacity.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with a fixed-point
* implementation, accuracy is lost due to imprecise representation of the
* scaled quantization values. However, that problem does not arise if
* we use floating point arithmetic.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_FLOAT_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce a float result.
*/
#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL void
jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
FAST_FLOAT z5, z10, z11, z12, z13;
JCOEFPTR inptr;
FLOAT_MULT_TYPE * quantptr;
FAST_FLOAT * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* 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 column 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
* column DCT calculations can be simplified this way.
*/
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
inptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z11 = tmp4 + tmp7;
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
wsptr[DCTSIZE*0] = tmp0 + tmp7;
wsptr[DCTSIZE*7] = tmp0 - tmp7;
wsptr[DCTSIZE*1] = tmp1 + tmp6;
wsptr[DCTSIZE*6] = tmp1 - tmp6;
wsptr[DCTSIZE*2] = tmp2 + tmp5;
wsptr[DCTSIZE*5] = tmp2 - tmp5;
wsptr[DCTSIZE*4] = tmp3 + tmp4;
wsptr[DCTSIZE*3] = tmp3 - tmp4;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column calculation has created many nonzero AC terms, so
* the simplification applies less often (typically 5% to 10% of the time).
* And testing floats for zero is relatively expensive, so we don't bother.
*/
/* Even part */
tmp10 = wsptr[0] + wsptr[4];
tmp11 = wsptr[0] - wsptr[4];
tmp13 = wsptr[2] + wsptr[6];
tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
z13 = wsptr[5] + wsptr[3];
z10 = wsptr[5] - wsptr[3];
z11 = wsptr[1] + wsptr[7];
z12 = wsptr[1] - wsptr[7];
tmp7 = z11 + z13;
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7;
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
/* Final output stage: scale down by a factor of 8 and range-limit */
outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
& RANGE_MASK];
outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
& RANGE_MASK];
outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
& RANGE_MASK];
outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
& RANGE_MASK];
outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_FLOAT_SUPPORTED */

362
jidctfst.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* jidctfst.c
*
* Copyright (C) 1994, 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 fast, not so accurate integer implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
* JPEG textbook (see REFERENCES section in file README). The following code
* is based directly on figure 4-8 in P&M.
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
* possible to arrange the computation so that many of the multiplies are
* simple scalings of the final outputs. These multiplies can then be
* folded into the multiplications or divisions by the JPEG quantization
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
* to be done in the DCT itself.
* The primary disadvantage of this method is that with fixed-point math,
* accuracy is lost due to imprecise representation of the scaled
* quantization values. The smaller the quantization table entry, the less
* precise the scaled value, so this implementation does worse with high-
* quality-setting files than with low-quality ones.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_IFAST_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling decisions are generally the same as in the LL&M algorithm;
* see jidctint.c for more details. However, we choose to descale
* (right shift) multiplication products as soon as they are formed,
* rather than carrying additional fractional bits into subsequent additions.
* This compromises accuracy slightly, but it lets us save a few shifts.
* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
* everywhere except in the multiplications proper; this saves a good deal
* of work on 16-bit-int machines.
*
* The dequantized coefficients are not integers because the AA&N scaling
* factors have been incorporated. We represent them scaled up by PASS1_BITS,
* so that the first and second IDCT rounds have the same input scaling.
* For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
* avoid a descaling shift; this compromises accuracy rather drastically
* for small quantization table entries, but it saves a lot of shifts.
* For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
* so we use a much larger scaling factor to preserve accuracy.
*
* A final compromise is to represent the multiplicative constants to only
* 8 fractional bits, rather than 13. This saves some shifting work on some
* machines, and may also reduce the cost of multiplication (since there
* are fewer one-bits in the constants).
*/
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 8
#define PASS1_BITS 2
#else
#define CONST_BITS 8
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* 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...)
*/
#if CONST_BITS == 8
#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */
#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */
#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */
#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */
#else
#define FIX_1_082392200 FIX(1.082392200)
#define FIX_1_414213562 FIX(1.414213562)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_2_613125930 FIX(2.613125930)
#endif
/* We can gain a little more speed, with a further compromise in accuracy,
* by omitting the addition in a descaling shift. This yields an incorrectly
* rounded result half the time...
*/
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
#define DESCALE(x,n) RIGHT_SHIFT(x, n)
#endif
/* Multiply a DCTELEM variable by an INT32 constant, and immediately
* descale to yield a DCTELEM result.
*/
#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce a DCTELEM result. For 8-bit data a 16x16->16
* multiplication will do. For 12-bit data, the multiplier table is
* declared INT32, so a 32-bit multiply will be used.
*/
#if BITS_IN_JSAMPLE == 8
#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
#else
#define DEQUANTIZE(coef,quantval) \
DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
#endif
/* Like DESCALE, but applies to a DCTELEM and produces an int.
* We assume that int right shift is unsigned if INT32 right shift is.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS DCTELEM ishift_temp;
#define IRIGHT_SHIFT(x,shft) \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (32-(shft))) : \
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
#ifdef USE_ACCURATE_ROUNDING
#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
#else
#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
#endif
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL void
jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
DCTELEM z5, z10, z11, z12, z13;
JCOEFPTR inptr;
IFAST_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS /* for DESCALE */
ISHIFT_TEMPS /* for IDESCALE */
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* 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 column 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
* column DCT calculations can be simplified this way.
*/
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
inptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z11 = tmp4 + tmp7;
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column 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_ROW_TEST
if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[4] | wsptr[5] | wsptr[6] |
wsptr[7]) == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
outptr[4] = dcval;
outptr[5] = dcval;
outptr[6] = dcval;
outptr[7] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
- tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
tmp1 = tmp11 + tmp12;
tmp2 = tmp11 - tmp12;
/* Odd part */
z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
/* Final output stage: scale down by a factor of 8 and range-limit */
outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
& RANGE_MASK];
outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
& RANGE_MASK];
outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
& RANGE_MASK];
outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
& RANGE_MASK];
outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
& RANGE_MASK];
outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
& RANGE_MASK];
outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
& RANGE_MASK];
outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_IFAST_SUPPORTED */

388
jidctint.c Normal file
View File

@@ -0,0 +1,388 @@
/*
* jidctint.c
*
* Copyright (C) 1991-1994, 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 slow-but-accurate integer implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
* must also perform dequantization of the input coefficients.
*
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
* on each row (or vice versa, but it's more convenient to emit a row at
* a time). Direct algorithms are also available, but they are much more
* complex and seem not to be any faster when reduced to code.
*
* 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.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef DCT_ISLOW_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/*
* 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 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.
*
* 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.
*/
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* 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...)
*/
#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
/* 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.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce an int result. In this module, both inputs and result
* are 16 bits or less, so either int or short multiply will work.
*/
#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients.
*/
GLOBAL void
jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* 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 column 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
* column DCT calculations can be simplified this way.
*/
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
inptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
wsptr[DCTSIZE*4] = dcval;
wsptr[DCTSIZE*5] = dcval;
wsptr[DCTSIZE*6] = dcval;
wsptr[DCTSIZE*7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
continue;
}
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp0 = (z2 + z3) << CONST_BITS;
tmp1 = (z2 - z3) << 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 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[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 */
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
inptr++; /* advance pointers to next column */
quantptr++;
wsptr++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr] + output_col;
/* Rows of zeroes can be exploited in the same way as we did with columns.
* However, the column 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_ROW_TEST
if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[4] | wsptr[5] | wsptr[6] |
wsptr[7]) == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
outptr[4] = dcval;
outptr[5] = dcval;
outptr[6] = dcval;
outptr[7] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) wsptr[2];
z3 = (INT32) wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[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) wsptr[7];
tmp1 = (INT32) wsptr[5];
tmp2 = (INT32) wsptr[3];
tmp3 = (INT32) wsptr[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 */
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
#endif /* DCT_ISLOW_SUPPORTED */

397
jidctred.c Normal file
View File

@@ -0,0 +1,397 @@
/*
* jidctred.c
*
* Copyright (C) 1994, 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 inverse-DCT routines that produce reduced-size output:
* either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
*
* The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
* algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step
* with an 8-to-4 step that produces the four averages of two adjacent outputs
* (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
* These steps were derived by computing the corresponding values at the end
* of the normal LL&M code, then simplifying as much as possible.
*
* 1x1 is trivial: just take the DC coefficient divided by 8.
*
* See jidctint.c for additional comments.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#ifdef IDCT_SCALING_SUPPORTED
/*
* This module is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* Scaling is the same as in jidctint.c. */
#if BITS_IN_JSAMPLE == 8
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
/* 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...)
*/
#if CONST_BITS == 13
#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */
#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */
#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */
#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */
#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */
#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */
#else
#define FIX_0_211164243 FIX(0.211164243)
#define FIX_0_509795579 FIX(0.509795579)
#define FIX_0_601344887 FIX(0.601344887)
#define FIX_0_720959822 FIX(0.720959822)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_850430095 FIX(0.850430095)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_061594337 FIX(1.061594337)
#define FIX_1_272758580 FIX(1.272758580)
#define FIX_1_451774981 FIX(1.451774981)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_2_172734803 FIX(2.172734803)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_624509785 FIX(3.624509785)
#endif
/* 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.
* For 12-bit samples, a full 32-bit multiplication will be needed.
*/
#if BITS_IN_JSAMPLE == 8
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
#else
#define MULTIPLY(var,const) ((var) * (const))
#endif
/* Dequantize a coefficient by multiplying it by the multiplier-table
* entry; produce an int result. In this module, both inputs and result
* are 16 bits or less, so either int or short multiply will work.
*/
#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 4x4 output block.
*/
GLOBAL void
jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp2, tmp10, tmp12;
INT32 z1, z2, z3, z4;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE*4]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process column 4, because second pass won't use it */
if (ctr == DCTSIZE-4)
continue;
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
inptr[DCTSIZE*5] | inptr[DCTSIZE*6] | inptr[DCTSIZE*7]) == 0) {
/* AC terms all zero; we need not examine term 4 for 4x4 output */
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
wsptr[DCTSIZE*2] = dcval;
wsptr[DCTSIZE*3] = dcval;
continue;
}
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp0 <<= (CONST_BITS+1);
z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
}
/* Pass 2: process 4 rows from work array, store into output array. */
wsptr = workspace;
for (ctr = 0; ctr < 4; ctr++) {
outptr = output_buf[ctr] + output_col;
/* It's not clear whether a zero row test is worthwhile here ... */
#ifndef NO_ZERO_ROW_TEST
if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[5] | wsptr[6] |
wsptr[7]) == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
outptr[2] = dcval;
outptr[3] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
+ MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
z1 = (INT32) wsptr[7];
z2 = (INT32) wsptr[5];
z3 = (INT32) wsptr[3];
z4 = (INT32) wsptr[1];
tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
CONST_BITS+PASS1_BITS+3+1)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 2x2 output block.
*/
GLOBAL void
jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
INT32 tmp0, tmp10, z1;
JCOEFPTR inptr;
ISLOW_MULT_TYPE * quantptr;
int * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
int workspace[DCTSIZE*2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process columns 2,4,6 */
if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
continue;
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*3] |
inptr[DCTSIZE*5] | inptr[DCTSIZE*7]) == 0) {
/* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
continue;
}
/* Even part */
z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp10 = z1 << (CONST_BITS+2);
/* Odd part */
z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
/* Final output stage */
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
}
/* Pass 2: process 2 rows from work array, store into output array. */
wsptr = workspace;
for (ctr = 0; ctr < 2; ctr++) {
outptr = output_buf[ctr] + output_col;
/* It's not clear whether a zero row test is worthwhile here ... */
#ifndef NO_ZERO_ROW_TEST
if ((wsptr[1] | wsptr[3] | wsptr[5] | wsptr[7]) == 0) {
/* AC terms all zero */
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
& RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
wsptr += DCTSIZE; /* advance pointer to next row */
continue;
}
#endif
/* Even part */
tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
/* Odd part */
tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
+ MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
+ MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
+ MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
/* Final output stage */
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
CONST_BITS+PASS1_BITS+3+2)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
CONST_BITS+PASS1_BITS+3+2)
& RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a reduced-size 1x1 output block.
*/
GLOBAL void
jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
int dcval;
ISLOW_MULT_TYPE * quantptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
SHIFT_TEMPS
/* We hardly need an inverse DCT routine for this: just take the
* average pixel value, which is one-eighth of the DC coefficient.
*/
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
dcval = (int) DESCALE((INT32) dcval, 3);
output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
}
#endif /* IDCT_SCALING_SUPPORTED */

View File

@@ -1,53 +1,72 @@
/*
* jinclude.h
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This is the central file that's #include'd by all the JPEG .c files.
* Its purpose is to provide a single place to fix any problems with
* including the wrong system include files.
* You can edit these declarations if you use a system with nonstandard
* system include files.
* This file exists to provide a single place to fix any problems with
* including the wrong system include files. (Common problems are taken
* care of by the standard jconfig symbols, but on really weird systems
* you may have to edit this file.)
*
* NOTE: this file is NOT intended to be included by applications using the
* JPEG library. Most applications need only include jpeglib.h.
*/
/* Include auto-config file to find out which system include files we need. */
#include "jconfig.h" /* auto configuration options */
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
/*
* Normally the __STDC__ macro can be taken as indicating that the system
* include files conform to the ANSI C standard. However, if you are running
* GCC on a machine with non-ANSI system include files, that is not the case.
* In that case change the following, or add -DNONANSI_INCLUDES to your CFLAGS.
* We need the NULL macro and size_t typedef.
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
* pull in <sys/types.h> as well.
* Note that the core JPEG library does not require <stdio.h>;
* only the default error handler and data source/destination modules do.
* But we must pull it in because of the references to FILE in jpeglib.h.
* You can remove those references if you want to compile without <stdio.h>.
*/
#ifdef __STDC__
#ifndef NONANSI_INCLUDES
#define INCLUDES_ARE_ANSI /* this is what's tested before including */
#endif
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
/*
* <stdio.h> is included to get the FILE typedef and NULL macro.
* Note that the core portable-JPEG files do not actually do any I/O
* using the stdio library; only the user interface, error handler,
* and file reading/writing modules invoke any stdio functions.
* (Well, we did cheat a bit in jmemmgr.c, but only if MEM_STATS is defined.)
*/
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef NEED_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <stdio.h>
/*
* We need the size_t typedef, which defines the parameter type of malloc().
* In an ANSI-conforming implementation this is provided by <stdio.h>,
* but on non-ANSI systems it's more likely to be in <sys/types.h>.
* On some not-quite-ANSI systems you may find it in <stddef.h>.
* We need memory copying and zeroing functions, plus strncpy().
* 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.
* Change the casts in these macros if not!
*/
#ifndef INCLUDES_ARE_ANSI /* shouldn't need this if ANSI C */
#include <sys/types.h>
#endif
#ifdef __SASC /* Amiga SAS C provides it in stddef.h. */
#include <stddef.h>
#ifdef NEED_BSD_STRINGS
#include <strings.h>
#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 ANSI/SysV string lib */
#include <string.h>
#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
/*
@@ -58,12 +77,11 @@
* we always use this SIZEOF() macro in place of using sizeof() directly.
*/
#undef SIZEOF /* in case you included X11/xmd.h */
#define SIZEOF(object) ((size_t) sizeof(object))
/*
* fread() and fwrite() are always invoked through these macros.
* On some systems you may need to twiddle the argument casts.
* The modules that use fread() and fwrite() always invoke them through
* these macros. On some systems you may need to twiddle the argument casts.
* CAUTION: argument order is different from underlying functions!
*/
@@ -71,32 +89,3 @@
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
#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().
* NOTE: we assume the size parameters to these functions are of type size_t.
* Insert casts in these macros if not!
*/
#ifdef INCLUDES_ARE_ANSI
#include <string.h>
#define MEMZERO(voidptr,size) memset((voidptr), 0, (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))
#else /* not BSD, assume Sys V or compatible */
#include <string.h>
#define MEMZERO(voidptr,size) memset((voidptr), 0, (size))
#endif /* BSD */
#endif /* ANSI */
/* Now include the portable JPEG definition files. */
#include "jconfig.h"
#include "jpegdata.h"

View File

@@ -1,7 +1,7 @@
/*
* jmemansi.c (jmemsys.c)
* jmemansi.c
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1994, 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.
*
@@ -12,14 +12,14 @@
* is shoved onto the user.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jmemsys.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
#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));
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
extern void * malloc JPP((size_t size));
extern void free JPP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
@@ -27,34 +27,43 @@ extern void free PP((void *ptr));
#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)
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
* "Large" objects are treated the same as "small" ones.
* NB: although we include FAR keywords in the routine declarations,
* this file won't actually work in 80x86 small/medium model; at least,
* you probably won't be able to process useful-size images in only 64KB.
*/
GLOBAL void FAR *
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
return (void FAR *) malloc(sizeofobject);
}
GLOBAL void
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
free(object);
}
/*
* This routine computes the total memory space available for allocation.
@@ -69,46 +78,49 @@ jfree_small (void * object)
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
long max_bytes_needed, long already_allocated)
{
return methods->max_memory_to_use - total_used;
return cinfo->mem->max_memory_to_use - already_allocated;
}
/*
* 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
* jpeg_mem_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,
read_backing_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
ERREXIT(cinfo, JERR_TFILE_READ);
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
write_backing_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
ERREXIT(cinfo, JERR_TFILE_WRITE);
}
METHODDEF void
close_backing_store (backing_store_ptr info)
close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
{
fclose(info->temp_file);
/* Since this implementation uses tmpfile() to create the file,
@@ -121,15 +133,16 @@ close_backing_store (backing_store_ptr info)
* 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;
* behind the scenes. We don't have to use info->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)
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
if ((info->temp_file = tmpfile()) == NULL)
ERREXIT(methods, "Failed to create temporary file");
ERREXITS(cinfo, JERR_TFILE_CREATE, "");
info->read_backing_store = read_backing_store;
info->write_backing_store = write_backing_store;
info->close_backing_store = close_backing_store;
@@ -138,20 +151,17 @@ jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
* cleanup required.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
GLOBAL long
jpeg_mem_init (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
}
GLOBAL void
jmem_term (void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
}

264
jmemdos.c
View File

@@ -1,7 +1,7 @@
/*
* jmemdos.c (jmemsys.c)
* jmemdos.c
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1994, 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,8 @@
* 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.
*/
@@ -37,14 +39,15 @@
#endif
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jmemsys.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
#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));
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare these */
extern void * malloc JPP((size_t size));
extern void free JPP((void *ptr));
extern char * getenv JPP((const char * name));
#endif
#ifdef NEED_FAR_POINTERS
@@ -61,7 +64,12 @@ extern void free PP((void *ptr));
#define far_free(x) _ffree(x)
#endif
#endif
#else /* not NEED_FAR_POINTERS */
#define far_malloc(x) malloc(x)
#define far_free(x) free(x)
#endif /* NEED_FAR_POINTERS */
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
@@ -69,6 +77,10 @@ extern void free PP((void *ptr));
#define READ_BINARY "rb"
#endif
#if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */
MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
#endif
/*
* Declarations for assembly-language support routines (see jmemdosa.asm).
@@ -88,22 +100,17 @@ typedef struct { /* registers for calling EMS driver */
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,
EXTERN short far jdos_open JPP((short far * handle, char far * filename));
EXTERN short far jdos_close JPP((short handle));
EXTERN short far jdos_seek JPP((short handle, long offset));
EXTERN short far jdos_read JPP((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 */
EXTERN short far jdos_write JPP((short handle, void far * buffer,
unsigned short count));
EXTERN void far jxms_getdriver JPP((XMSDRIVER far *));
EXTERN void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
EXTERN short far jems_available JPP((void));
EXTERN void far jems_calldriver JPP((EMScontext far *));
/*
@@ -152,43 +159,34 @@ select_file_name (char * fname)
*/
GLOBAL void *
jget_small (size_t sizeofobject)
jpeg_get_small (j_common_ptr cinfo, 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)
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* Far-memory allocation and freeing
* "Large" objects are allocated in far memory, if possible
*/
#ifdef NEED_FAR_POINTERS
GLOBAL void FAR *
jget_large (size_t sizeofobject)
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
total_used += sizeofobject;
return (void FAR *) far_malloc(sizeofobject);
}
GLOBAL void
jfree_large (void FAR * object)
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
far_free(object);
}
#endif
/*
* This routine computes the total memory space available for allocation.
@@ -203,16 +201,17 @@ jfree_large (void FAR * object)
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
long max_bytes_needed, long already_allocated)
{
return methods->max_memory_to_use - total_used;
return cinfo->mem->max_memory_to_use - already_allocated;
}
/*
* 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
* jpeg_mem_available is less than the total space needed. You can dispense
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
*/
@@ -225,8 +224,9 @@ jmem_available (long min_bytes_needed, long max_bytes_needed)
* 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.
* The specs are available by Internet FTP from the SIMTEL archives
* (oak.oakland.edu and its various mirror sites). See files
* pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
*/
@@ -236,37 +236,39 @@ jmem_available (long min_bytes_needed, long max_bytes_needed)
METHODDEF void
read_file_store (backing_store_ptr info, void FAR * buffer_address,
read_file_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
/* 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");
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
if (jdos_read(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "read failed on temporary file");
ERREXIT(cinfo, JERR_TFILE_READ);
}
METHODDEF void
write_file_store (backing_store_ptr info, void FAR * buffer_address,
write_file_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
/* 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");
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
if (jdos_write(info->handle.file_handle, buffer_address,
(unsigned short) byte_count))
ERREXIT(methods, "write failed on temporary file --- out of disk space?");
ERREXIT(cinfo, JERR_TFILE_WRITE);
}
METHODDEF void
close_file_store (backing_store_ptr info)
close_file_store (j_common_ptr cinfo, backing_store_ptr info)
{
jdos_close(info->handle.file_handle); /* close the file */
remove(info->temp_name); /* delete the file */
@@ -274,26 +276,27 @@ close_file_store (backing_store_ptr info)
* 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);
TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
}
LOCAL boolean
open_file_store (backing_store_ptr info, long total_bytes_needed)
open_file_store (j_common_ptr cinfo, 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))
if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
/* might as well exit since jpeg_open_backing_store will fail anyway */
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
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);
TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
return TRUE; /* succeeded */
}
@@ -323,7 +326,8 @@ typedef struct { /* XMS move specification structure */
METHODDEF void
read_xms_store (backing_store_ptr info, void FAR * buffer_address,
read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
@@ -344,10 +348,10 @@ read_xms_store (backing_store_ptr info, void FAR * buffer_address,
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "read from extended memory failed");
ERREXIT(cinfo, JERR_XMS_READ);
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
read_xms_store(cinfo, info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
}
@@ -355,7 +359,8 @@ read_xms_store (backing_store_ptr info, void FAR * buffer_address,
METHODDEF void
write_xms_store (backing_store_ptr info, void FAR * buffer_address,
write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count)
{
XMScontext ctx;
@@ -376,33 +381,34 @@ write_xms_store (backing_store_ptr info, void FAR * buffer_address,
ctx.ax = 0x0b00; /* EMB move */
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
if (ctx.ax != 1)
ERREXIT(methods, "write to extended memory failed");
ERREXIT(cinfo, JERR_XMS_WRITE);
if (ODD(byte_count)) {
read_xms_store(info, (void FAR *) endbuffer,
read_xms_store(cinfo, 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,
write_xms_store(cinfo, info, (void FAR *) endbuffer,
file_offset + byte_count - 1L, 2L);
}
}
METHODDEF void
close_xms_store (backing_store_ptr info)
close_xms_store (j_common_ptr cinfo, 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);
TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, 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)
open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
XMScontext ctx;
@@ -429,7 +435,7 @@ open_xms_store (backing_store_ptr info, long total_bytes_needed)
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);
TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
return TRUE; /* succeeded */
}
@@ -442,21 +448,35 @@ open_xms_store (backing_store_ptr info, long total_bytes_needed)
#if EMS_SUPPORTED
typedef union { /* either offset/page or real-mode pointer */
struct { unsigned short offset, page; } ems;
void far * ptr;
} EMSPTR;
/* 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 struct { /* EMS move specification structure */
long length;
char src_type; /* 1 = EMS, 0 = conventional memory */
EMSH src_handle; /* use 0 if conventional memory */
EMSPTR src;
char dst_type;
EMSH dst_handle;
EMSPTR dst;
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)
@@ -464,68 +484,71 @@ typedef struct { /* EMS move specification structure */
METHODDEF void
read_ems_store (backing_store_ptr info, void FAR * buffer_address,
read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
spec.src_type = 1;
spec.src_handle = info->handle.ems_handle;
spec.src.ems.page = (unsigned short) (file_offset / EMSPAGESIZE);
spec.src.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE);
spec.dst_type = 0;
spec.dst_handle = 0;
spec.dst.ptr = buffer_address;
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");
ERREXIT(cinfo, JERR_EMS_READ);
}
METHODDEF void
write_ems_store (backing_store_ptr info, void FAR * buffer_address,
write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count)
{
EMScontext ctx;
EMSspec spec;
spec.length = byte_count;
spec.src_type = 0;
spec.src_handle = 0;
spec.src.ptr = buffer_address;
spec.dst_type = 1;
spec.dst_handle = info->handle.ems_handle;
spec.dst.ems.page = (unsigned short) (file_offset / EMSPAGESIZE);
spec.dst.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE);
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");
ERREXIT(cinfo, JERR_EMS_WRITE);
}
METHODDEF void
close_ems_store (backing_store_ptr info)
close_ems_store (j_common_ptr cinfo, 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);
TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, 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)
open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
EMScontext ctx;
@@ -557,7 +580,7 @@ open_ems_store (backing_store_ptr info, long total_bytes_needed)
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);
TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
return TRUE; /* succeeded */
}
@@ -569,40 +592,43 @@ open_ems_store (backing_store_ptr info, long total_bytes_needed)
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
jpeg_open_backing_store (j_common_ptr cinfo, 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))
if (open_xms_store(cinfo, info, total_bytes_needed))
return;
#endif
#if EMS_SUPPORTED
if (open_ems_store(info, total_bytes_needed))
if (open_ems_store(cinfo, info, total_bytes_needed))
return;
#endif
if (open_file_store(info, total_bytes_needed))
if (open_file_store(cinfo, info, total_bytes_needed))
return;
ERREXIT(methods, "Failed to create temporary file");
ERREXITS(cinfo, JERR_TFILE_CREATE, "");
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
* cleanup required.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
GLOBAL long
jpeg_mem_init (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
next_file_num = 0; /* initialize temp file name generator */
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
}
GLOBAL void
jmem_term (void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
/* 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
View File

@@ -1,135 +0,0 @@
/*
* 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 65400L
/*
* 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));

1303
jmemmgr.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* jmemname.c (jmemsys.c)
* jmemname.c
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1994, 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.
*
@@ -12,14 +12,14 @@
* is shoved onto the user.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jmemsys.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
#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));
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
extern void * malloc JPP((size_t size));
extern void free JPP((void *ptr));
#endif
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
@@ -35,11 +35,6 @@ extern void free PP((void *ptr));
#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!
@@ -50,14 +45,7 @@ static long total_used; /* total memory requested so far */
* 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.)
* #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h.
*
* 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
@@ -68,23 +56,19 @@ static long total_used; /* total memory requested so far */
* 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
* 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c
* 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
#ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */
#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 */
#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
#define TEMP_FILE_NAME "%sJPG%03d.TMP"
#endif
@@ -106,7 +90,7 @@ select_file_name (char * fname)
#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 */
#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
#define TEMP_FILE_NAME "%sJPG%dXXXXXX"
#endif
@@ -128,23 +112,37 @@ select_file_name (char * fname)
*/
GLOBAL void *
jget_small (size_t sizeofobject)
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
{
total_used += sizeofobject;
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
* "Large" objects are treated the same as "small" ones.
* NB: although we include FAR keywords in the routine declarations,
* this file won't actually work in 80x86 small/medium model; at least,
* you probably won't be able to process useful-size images in only 64KB.
*/
GLOBAL void FAR *
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
return (void FAR *) malloc(sizeofobject);
}
GLOBAL void
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
free(object);
}
/*
* This routine computes the total memory space available for allocation.
@@ -159,46 +157,49 @@ jfree_small (void * object)
#endif
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
long max_bytes_needed, long already_allocated)
{
return methods->max_memory_to_use - total_used;
return cinfo->mem->max_memory_to_use - already_allocated;
}
/*
* 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
* jpeg_mem_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,
read_backing_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
if (JFREAD(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fread failed on temporary file");
ERREXIT(cinfo, JERR_TFILE_READ);
}
METHODDEF void
write_backing_store (backing_store_ptr info, void FAR * buffer_address,
write_backing_store (j_common_ptr cinfo, 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");
ERREXIT(cinfo, JERR_TFILE_SEEK);
if (JFWRITE(info->temp_file, buffer_address, byte_count)
!= (size_t) byte_count)
ERREXIT(methods, "fwrite failed on temporary file --- out of disk space?");
ERREXIT(cinfo, JERR_TFILE_WRITE);
}
METHODDEF void
close_backing_store (backing_store_ptr info)
close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
{
fclose(info->temp_file); /* close the file */
unlink(info->temp_name); /* delete the file */
@@ -206,43 +207,42 @@ close_backing_store (backing_store_ptr info)
* remove() is the ANSI-standard name for this function, but if
* your system was ANSI you'd be using jmemansi.c, right?
*/
TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
}
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
{
char tracemsg[TEMP_NAME_LENGTH+40];
/*
* Initial opening of a backing-store object.
*/
GLOBAL void
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
select_file_name(info->temp_name);
if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL)
ERREXIT(methods, "Failed to create temporary file");
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
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);
TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
}
/*
* These routines take care of any system-dependent initialization and
* cleanup required. Keep in mind that jmem_term may be called more than
* once.
* cleanup required.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
GLOBAL long
jpeg_mem_init (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = DEFAULT_MAX_MEM;
total_used = 0;
next_file_num = 0;
next_file_num = 0; /* initialize temp file name generator */
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
}
GLOBAL void
jmem_term (void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
}

View File

@@ -1,7 +1,7 @@
/*
* jmemnobs.c (jmemsys.c)
* jmemnobs.c
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1994, 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.
*
@@ -15,42 +15,54 @@
* Note that the max_memory_to_use option is ignored by this implementation.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jmemsys.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
#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));
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
extern void * malloc JPP((size_t size));
extern void free JPP((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)
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
{
return (void *) malloc(sizeofobject);
}
GLOBAL void
jfree_small (void * object)
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
{
free(object);
}
/*
* We assume NEED_FAR_POINTERS is not defined and so the separate entry points
* jget_large, jfree_large are not needed.
* "Large" objects are treated the same as "small" ones.
* NB: although we include FAR keywords in the routine declarations,
* this file won't actually work in 80x86 small/medium model; at least,
* you probably won't be able to process useful-size images in only 64KB.
*/
GLOBAL void FAR *
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
{
return (void FAR *) malloc(sizeofobject);
}
GLOBAL void
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
{
free(object);
}
/*
* This routine computes the total memory space available for allocation.
@@ -58,7 +70,8 @@ jfree_small (void * object)
*/
GLOBAL long
jmem_available (long min_bytes_needed, long max_bytes_needed)
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
long max_bytes_needed, long already_allocated)
{
return max_bytes_needed;
}
@@ -66,31 +79,31 @@ jmem_available (long min_bytes_needed, long max_bytes_needed)
/*
* Backing store (temporary file) management.
* This should never be called and we just error out.
* Since jpeg_mem_available always promised the moon,
* this should never be called and we can just error out.
*/
GLOBAL void
jopen_backing_store (backing_store_ptr info, long total_bytes_needed)
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
ERREXIT(methods, "Backing store not supported");
ERREXIT(cinfo, JERR_NO_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.
* cleanup required. Here, there isn't any.
*/
GLOBAL void
jmem_init (external_methods_ptr emethods)
GLOBAL long
jpeg_mem_init (j_common_ptr cinfo)
{
methods = emethods; /* save struct addr for error exit access */
emethods->max_memory_to_use = 0;
return 0; /* just set max_memory_to_use to 0 */
}
GLOBAL void
jmem_term (void)
jpeg_mem_term (j_common_ptr cinfo)
{
/* no work */
}

171
jmemsys.h
View File

@@ -1,78 +1,107 @@
/*
* jmemsys.h
*
* Copyright (C) 1992, Thomas G. Lane.
* Copyright (C) 1992-1994, 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.)
* and system-dependent portions of the JPEG memory manager. No other
* modules need include it. (The system-independent portion is jmemmgr.c;
* there are several different versions of the system-dependent portion.)
*
* 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.
* This file works as-is for the system-dependent memory managers supplied
* in the IJG distribution. You may need to modify it if you write a
* custom memory manager. If system-dependent changes are needed in
* this file, the best method is to #ifdef them based on a configuration
* symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR.
*/
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_get_small jGetSmall
#define jpeg_free_small jFreeSmall
#define jpeg_get_large jGetLarge
#define jpeg_free_large jFreeLarge
#define jpeg_mem_available jMemAvail
#define jpeg_open_backing_store jOpenBackStore
#define jpeg_mem_init jMemInit
#define jpeg_mem_term jMemTerm
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/*
* 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.
* memory. (Typically the total amount requested through jpeg_get_small is
* no more than 20K or so; this will be requested in chunks of a few K each.)
* Behavior should be the same as for the standard library functions malloc
* and free; in particular, jpeg_get_small must return NULL on failure.
* On most systems, these ARE malloc and free. jpeg_free_small is passed the
* size of the object being freed, just in case it's needed.
* 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));
EXTERN void * jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
EXTERN void jpeg_free_small JPP((j_common_ptr cinfo, void * object,
size_t sizeofobject));
/*
* These two functions are used to allocate and release large chunks of
* memory (up to the total free space designated by jmem_available).
* memory (up to the total free space designated by jpeg_mem_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.
* far pointers are used. On most other machines these are identical to
* the jpeg_get/free_small routines; but we keep them separate anyway,
* in case a different allocation strategy is desirable for large chunks.
*/
#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
EXTERN void FAR * jpeg_get_large JPP((j_common_ptr cinfo,size_t sizeofobject));
EXTERN void jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
size_t sizeofobject));
/*
* 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
* be requested in a single call to jpeg_get_large (and jpeg_get_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.
* On those machines, we expect that jconfig.h will provide a proper value.
* On machines with 32-bit flat address spaces, any large constant may be used.
*
* NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
* size_t and will be a multiple of sizeof(align_type).
*/
#define MAX_ALLOC_CHUNK 1000000000L
#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
#define MAX_ALLOC_CHUNK 1000000000L
#endif
/*
* 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.
* This routine computes the total space still available for allocation by
* jpeg_get_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
* jpeg_mem_available returns zero. The maximum space needed, enough to hold
* all working storage in memory, is also passed in case it is useful.
* Finally, the total space already allocated is passed. If no better
* method is available, cinfo->mem->max_memory_to_use - already_allocated
* is often a suitable calculation.
*
* It is OK for jmem_available to underestimate the space available (that'll
* just lead to more backing-store access than is really necessary).
* It is OK for jpeg_mem_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.
* a slop factor from the true available space. 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));
EXTERN long jpeg_mem_available JPP((j_common_ptr cinfo,
long min_bytes_needed,
long max_bytes_needed,
long already_allocated));
/*
@@ -84,44 +113,70 @@ EXTERN long jmem_available PP((long min_bytes_needed, long max_bytes_needed));
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
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;
#endif /* USE_MSDOS_MEMMGR */
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;
/* Methods for reading/writing/closing this backing-store object */
JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
backing_store_ptr info,
void FAR * buffer_address,
long file_offset, long byte_count));
JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
backing_store_ptr info));
/* Private fields for system-dependent backing-store management */
#ifdef USE_MSDOS_MEMMGR
/* For the MS-DOS manager (jmemdos.c), we need: */
handle_union handle; /* reference to backing-store storage object */
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
#else
/* For a typical implementation with temp files, we need: */
FILE * temp_file; /* stdio reference to temp file */
char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
#endif
} 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.)
* (If jpeg_mem_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));
EXTERN void jpeg_open_backing_store JPP((j_common_ptr cinfo,
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.
* cleanup required. jpeg_mem_init will be called before anything is
* allocated (and, therefore, nothing in cinfo is of use except the error
* manager pointer). It should return a suitable default value for
* max_memory_to_use; this may subsequently be overridden by the surrounding
* application. (Note that max_memory_to_use is only important if
* jpeg_mem_available chooses to consult it ... no one else will.)
* jpeg_mem_term may assume that all requested memory has been freed and that
* all opened backing-store objects have been closed.
*/
EXTERN void jmem_init PP((external_methods_ptr emethods));
EXTERN void jmem_term PP((void));
EXTERN long jpeg_mem_init JPP((j_common_ptr cinfo));
EXTERN void jpeg_mem_term JPP((j_common_ptr cinfo));

339
jmorecfg.h Normal file
View File

@@ -0,0 +1,339 @@
/*
* jmorecfg.h
*
* Copyright (C) 1991-1994, 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 additional configuration options that customize the
* JPEG software for special applications or support machine-dependent
* optimizations. Most users will not need to touch this file.
*/
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/*
* Maximum number of components (color channels) allowed in JPEG image.
* To meet the letter of the JPEG spec, set this to 255. However, darn
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#define MAX_COMPONENTS 10 /* maximum number of image components */
/*
* Basic data types.
* You may need to change these if you have a machine with unusual data
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* Representation of a single sample (pixel element value).
* We frequently allocate large arrays of these, so it's important to keep
* them small. But if you have memory to burn and access to char or short
* arrays is very slow on your hardware, you might want to change these.
*/
#if 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.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef CHAR_IS_UNSIGNED
#define GETJSAMPLE(value) ((int) (value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* BITS_IN_JSAMPLE == 8 */
#if 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) ((int) (value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* BITS_IN_JSAMPLE == 12 */
/* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int
* if you have memory to burn and "short" is really slow.
*/
typedef short JCOEF;
/* Compressed datastreams are represented as arrays of JOCTET.
* These must be EXACTLY 8 bits wide, at least once they are written to
* external storage. Note that when using the stdio data source/destination
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef CHAR_IS_UNSIGNED
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char UINT8;
#else /* not CHAR_IS_UNSIGNED */
typedef short UINT8;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold at least signed 32-bit values. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
typedef long INT32;
#endif
/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
* "unsigned int" is sufficient on all machines. However, if you need to
* handle larger images and you don't mind deviating from the spec, you
* can change this datatype.
*/
typedef unsigned int JDIMENSION;
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
/* These defines are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions.
* Another application is to make all functions global for use with debuggers
* or code profilers that require it.
*/
#define METHODDEF static /* a function called through method pointers */
#define LOCAL static /* a function used only in its module */
#define GLOBAL /* a function referenced thru EXTERNs */
#define EXTERN extern /* a reference to a GLOBAL function */
/* Here is the pseudo-keyword for declaring pointers that must be "far"
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
* by just saying "FAR *" where such a pointer is needed. In a few places
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
*/
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
/*
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
*/
#ifndef HAVE_BOOLEAN
typedef int boolean;
#endif
#ifndef FALSE /* in case these macros already exist */
#define FALSE 0 /* values of boolean */
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* The remaining options affect code selection within the JPEG library,
* but they don't need to be visible to most applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
*/
#ifdef JPEG_INTERNALS
#define JPEG_INTERNAL_OPTIONS
#endif
#ifdef JPEG_INTERNAL_OPTIONS
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* library. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
/* Capability options common to encoder and decoder: */
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
/* 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? */
/* Note: if you selected 12-bit data 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 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 IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* more capability options later, no doubt */
/*
* Ordering of RGB data in scanlines passed to or from the application.
* If your application wants to deal with data in the order B,G,R, just
* change these macros. You can also deal with formats such as R,G,B,X
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
* the offsets will also change the order in which colormap data is organized.
* RESTRICTIONS:
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
* useful if you are using JPEG color spaces other than YCbCr or grayscale.
* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
* is not 3 (they don't understand about dummy color components!). So you
* can't use color quantization if you change that value.
*/
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
/* Definitions for speed-related optimizations. */
/* If your compiler supports inline functions, define INLINE
* as the inline keyword; otherwise define it as empty.
*/
#ifndef INLINE
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
#define INLINE __inline__
#endif
#ifndef INLINE
#define INLINE /* default is to define it as empty */
#endif
#endif
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
*/
#ifndef MULTIPLIER
#define MULTIPLIER int /* type for fastest integer multiply */
#endif
/* FAST_FLOAT should be either float or double, whichever is done faster
* by your compiler. (Note that this type is only used in the floating point
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
* Typically, float is faster in ANSI C compilers, while double is faster in
* pre-ANSI compilers (because they insist on converting to double anyway).
* The code below therefore chooses float if we have ANSI-style prototypes.
*/
#ifndef FAST_FLOAT
#ifdef HAVE_PROTOTYPES
#define FAST_FLOAT float
#else
#define FAST_FLOAT double
#endif
#endif
#endif /* JPEG_INTERNAL_OPTIONS */

View File

@@ -1,885 +0,0 @@
/*
* jpegdata.h
*
* 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 defines shared data structures for the various JPEG modules.
*/
/*
* You might need to change some of the following declarations if you are
* using the JPEG software within a surrounding application program
* or porting it to an unusual system.
*/
/* If the source or destination of image data is not to be stdio streams,
* these types may need work. You can replace them with some kind of
* pointer or indicator that is useful to you, or just ignore 'em.
* Note that the user interface and the various jrdxxx/jwrxxx modules
* will also need work for non-stdio input/output.
*/
typedef FILE * JFILEREF; /* source or dest of JPEG-compressed data */
typedef FILE * IFILEREF; /* source or dest of non-JPEG image data */
/* These defines are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions,
* as is shown below for use with C++. Another application would be to make
* all functions global for use with code profilers that require it.
* NOTE: the C++ test does the right thing if you are reading this include
* file in a C++ application to link to JPEG code that's been compiled with a
* regular C compiler. I'm not sure it works if you try to compile the JPEG
* code with C++.
*/
#define METHODDEF static /* a function called through method pointers */
#define LOCAL static /* a function used only in its module */
#define GLOBAL /* a function referenced thru EXTERNs */
#ifdef __cplusplus
#define EXTERN extern "C" /* a reference to a GLOBAL function */
#else
#define EXTERN extern /* a reference to a GLOBAL function */
#endif
/* Here is the pseudo-keyword for declaring pointers that must be "far"
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
* by just saying "FAR *" where such a pointer is needed. In a few places
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
*/
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
/* The remaining declarations are not system-dependent, we hope. */
/*
* NOTE: if you have an ancient, strict-K&R C compiler, it may choke on the
* similarly-named fields in compress_info_struct and decompress_info_struct.
* If this happens, you can get around it by rearranging the two structs so
* that the similarly-named fields appear first and in the same order in
* each struct. Since such compilers are now pretty rare, we haven't done
* this in the portable code, preferring to maintain a logical ordering.
*/
/* This macro is used to declare a "method", that is, a function pointer. */
/* We want to supply prototype parameters if the compiler can cope. */
/* Note that the arglist parameter must be parenthesized! */
#ifdef PROTO
#define METHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define METHOD(type,methodname,arglist) type (*methodname) ()
#endif
/* Forward references to lists of method pointers */
typedef struct external_methods_struct * external_methods_ptr;
typedef struct compress_methods_struct * compress_methods_ptr;
typedef struct decompress_methods_struct * decompress_methods_ptr;
/* Data structures for images containing either samples or coefficients. */
/* Note that the topmost (leftmost) index is always color component. */
/* On 80x86 machines, the image arrays are too big for near pointers, */
/* but the pointer arrays can fit in near memory. */
typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
/* The input and output data of the DCT transform subroutines are of
* the following type, which need not be the same as JCOEF.
* For example, on a machine with fast floating point, it might make sense
* to recode the DCT routines to use floating point; then DCTELEM would be
* 'float' or 'double'.
*/
typedef JCOEF DCTELEM;
typedef DCTELEM DCTBLOCK[DCTSIZE2];
/* Types for JPEG compression parameters and working tables. */
typedef enum { /* defines known color spaces */
CS_UNKNOWN, /* error/unspecified */
CS_GRAYSCALE, /* monochrome (only 1 component) */
CS_RGB, /* red/green/blue */
CS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
CS_YIQ, /* Y/I/Q */
CS_CMYK /* C/M/Y/K */
} COLOR_SPACE;
typedef struct { /* Basic info about one component */
/* These values are fixed over the whole image */
/* For compression, they must be supplied by the user interface; */
/* for decompression, they are read from the SOF marker. */
short component_id; /* identifier for this component (0..255) */
short component_index; /* its index in SOF or cinfo->comp_info[] */
short h_samp_factor; /* horizontal sampling factor (1..4) */
short v_samp_factor; /* vertical sampling factor (1..4) */
short quant_tbl_no; /* quantization table selector (0..3) */
/* These values may vary between scans */
/* For compression, they must be supplied by the user interface; */
/* for decompression, they are read from the SOS marker. */
short dc_tbl_no; /* DC entropy table selector (0..3) */
short ac_tbl_no; /* AC entropy table selector (0..3) */
/* These values are computed during compression or decompression startup */
long true_comp_width; /* component's image width in samples */
long true_comp_height; /* component's image height in samples */
/* the above are the logical dimensions of the subsampled image */
/* These values are computed before starting a scan of the component */
short MCU_width; /* number of blocks per MCU, horizontally */
short MCU_height; /* number of blocks per MCU, vertically */
short MCU_blocks; /* MCU_width * MCU_height */
long subsampled_width; /* image width in samples, after expansion */
long subsampled_height; /* image height in samples, after expansion */
/* the above are the true_comp_xxx values rounded up to multiples of */
/* the MCU dimensions; these are the working dimensions of the array */
/* as it is passed through the DCT or IDCT step. NOTE: these values */
/* differ depending on whether the component is interleaved or not!! */
} jpeg_component_info;
/* DCT coefficient quantization tables.
* For 8-bit precision, 'INT16' should be good enough for quantization values;
* for more precision, we go for the full 16 bits. 'INT16' provides a useful
* speedup on many machines (multiplication & division of JCOEFs by
* quantization values is a significant chunk of the runtime).
* Note: the values in a QUANT_TBL are always given in zigzag order.
*/
#ifdef EIGHT_BIT_SAMPLES
typedef INT16 QUANT_VAL; /* element of a quantization table */
#else
typedef UINT16 QUANT_VAL; /* element of a quantization table */
#endif
typedef QUANT_VAL QUANT_TBL[DCTSIZE2]; /* A quantization table */
typedef QUANT_VAL * QUANT_TBL_PTR; /* pointer to same */
typedef struct { /* A Huffman coding table */
/* These two fields directly represent the contents of a JPEG DHT marker */
UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
/* length k bits; bits[0] is unused */
UINT8 huffval[256]; /* The symbols, in order of incr code length */
/* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file.
*/
boolean sent_table; /* TRUE when table has been output */
/* The remaining fields are computed from the above to allow more efficient
* coding and decoding. These fields should be considered private to the
* Huffman compression & decompression modules.
*/
/* encoding tables: */
UINT16 ehufco[256]; /* code for each symbol */
char ehufsi[256]; /* length of code for each symbol */
/* decoding tables: (element [0] of each array is unused) */
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 */
} HUFF_TBL;
#define NUM_QUANT_TBLS 4 /* quantization tables are numbered 0..3 */
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
#define NUM_ARITH_TBLS 16 /* arith-coding tables are numbered 0..15 */
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
#define MAX_BLOCKS_IN_MCU 10 /* JPEG limit on # of blocks in an MCU */
/* Working data for compression */
struct compress_info_struct {
/*
* All of these fields shall be established by the user interface before
* calling jpeg_compress, or by the input_init or c_ui_method_selection
* methods.
* Most parameters can be set to reasonable defaults by j_c_defaults.
* Note that the UI must supply the storage for the main methods struct,
* though it sets only a few of the methods there.
*/
compress_methods_ptr methods; /* Points to list of methods to use */
external_methods_ptr emethods; /* Points to list of methods to use */
IFILEREF input_file; /* tells input routines where to read image */
JFILEREF output_file; /* tells output routines where to write JPEG */
long image_width; /* input image width */
long image_height; /* input image height */
short input_components; /* # of color components in input image */
short data_precision; /* bits of precision in image data */
COLOR_SPACE in_color_space; /* colorspace of input file */
COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
double input_gamma; /* image gamma of input file */
boolean write_JFIF_header; /* should a JFIF marker be written? */
/* These three values are not used by the JPEG code, only copied */
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
/* ratio is defined by X_density/Y_density even when density_unit=0. */
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
short num_components; /* # of color components in JPEG image */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined */
HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arithmetic-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arithmetic-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arithmetic-coding tables */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
boolean interleave; /* TRUE=interleaved output, FALSE=not */
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
/*
* These fields are computed during jpeg_compress startup
*/
short max_h_samp_factor; /* largest h_samp_factor */
short max_v_samp_factor; /* largest v_samp_factor */
/*
* These fields 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
*/
short comps_in_scan; /* # of JPEG components output this time */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
long MCUs_per_row; /* # of MCUs across the image */
long MCU_rows_in_scan; /* # of MCU rows in the image */
short blocks_in_MCU; /* # of DCT blocks per MCU */
short MCU_membership[MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
/* these fields are private data for the entropy encoder */
JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
UINT16 restarts_to_go; /* MDUs left in this restart interval */
short next_restart_num; /* # of next RSTn marker (0..7) */
};
typedef struct compress_info_struct * compress_info_ptr;
/* Working data for decompression */
struct decompress_info_struct {
/*
* These fields shall be established by the user interface before
* calling jpeg_decompress.
* Most parameters can be set to reasonable defaults by j_d_defaults.
* Note that the UI must supply the storage for the main methods struct,
* though it sets only a few of the methods there.
*/
decompress_methods_ptr methods; /* Points to list of methods to use */
external_methods_ptr emethods; /* Points to list of methods to use */
JFILEREF input_file; /* tells input routines where to read JPEG */
IFILEREF output_file; /* tells output routines where to write image */
/* these can be set at d_ui_method_selection time: */
COLOR_SPACE out_color_space; /* colorspace of output */
double output_gamma; /* image gamma wanted in output */
boolean quantize_colors; /* T if output is a colormapped format */
/* the following are ignored if not quantize_colors: */
boolean two_pass_quantize; /* use two-pass color quantization? */
boolean use_dithering; /* want color dithering? */
int desired_number_of_colors; /* max number of colors to use */
boolean do_block_smoothing; /* T = apply cross-block smoothing */
boolean do_pixel_smoothing; /* T = apply post-subsampling smoothing */
/*
* These fields are used for efficient buffering of data between read_jpeg_data
* and the entropy decoding object. By using a shared buffer, we avoid copying
* data and eliminate the need for an "unget" operation at the end of a scan.
* The actual source of the data is known only to read_jpeg_data; see the
* JGETC macro, below.
* Note: the user interface is expected to allocate the input_buffer and
* initialize bytes_in_buffer to 0. Also, for JFIF/raw-JPEG input, the UI
* actually supplies the read_jpeg_data method. 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 */
int bytes_in_buffer; /* # of bytes remaining in buffer */
/*
* These fields are set by read_file_header or read_scan_header
*/
long image_width; /* overall image width */
long image_height; /* overall image height */
short data_precision; /* bits of precision in image data */
COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
/* These three values are not used by the JPEG code, merely copied */
/* from the JFIF APP0 marker (if any). */
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
short num_components; /* # of color components in JPEG image */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined */
HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
/*
* These fields are computed during jpeg_decompress startup
*/
short max_h_samp_factor; /* largest h_samp_factor */
short max_v_samp_factor; /* largest v_samp_factor */
short color_out_comps; /* # of color components output by color_convert */
/* (need not match num_components) */
short final_out_comps; /* # of color components sent to put_pixel_rows */
/* (1 when quantizing colors, else same as color_out_comps) */
/*
* 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
*/
short comps_in_scan; /* # of JPEG components input this time */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
long MCUs_per_row; /* # of MCUs across the image */
long MCU_rows_in_scan; /* # of MCU rows in the image */
short blocks_in_MCU; /* # of DCT blocks per MCU */
short MCU_membership[MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
/* these fields are private data for the entropy encoder */
JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
UINT16 restarts_to_go; /* MDUs left in this restart interval */
short next_restart_num; /* # of next RSTn marker (0..7) */
};
typedef struct decompress_info_struct * decompress_info_ptr;
/* Macros for reading data from the decompression input buffer */
#ifdef CHAR_IS_UNSIGNED
#define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \
(*(cinfo)->methods->read_jpeg_data) (cinfo) : \
(int) (*(cinfo)->next_input_byte++) )
#else
#define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \
(*(cinfo)->methods->read_jpeg_data) (cinfo) : \
(int) (*(cinfo)->next_input_byte++) & 0xFF )
#endif
#define JUNGETC(ch,cinfo) ((cinfo)->bytes_in_buffer++, \
*(--((cinfo)->next_input_byte)) = (ch))
#define MIN_UNGET 4 /* may always do at least 4 JUNGETCs */
/* A virtual image has a control block whose contents are private to the
* memory manager module (and may differ between managers). The rest of the
* code only refers to virtual images by these pointer types, and never
* dereferences the pointer.
*/
typedef struct big_sarray_control * big_sarray_ptr;
typedef struct big_barray_control * big_barray_ptr;
/* Although a real ANSI C compiler can deal perfectly well with pointers to
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
* 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 managers #define AM_MEMORY_MANAGER before including this file,
* so that they can make their own definitions of the structs.
*/
#ifdef INCOMPLETE_TYPES_BROKEN
#ifndef AM_MEMORY_MANAGER
struct big_sarray_control { long dummy; };
struct big_barray_control { long dummy; };
#endif
#endif
/* Method types that need typedefs */
typedef METHOD(void, MCU_output_method_ptr, (compress_info_ptr cinfo,
JBLOCK *MCU_data));
typedef METHOD(void, MCU_output_caller_ptr, (compress_info_ptr cinfo,
MCU_output_method_ptr output_method));
typedef METHOD(void, subsample_ptr, (compress_info_ptr cinfo,
int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above,
JSAMPARRAY input_data,
JSAMPARRAY below,
JSAMPARRAY output_data));
typedef METHOD(void, unsubsample_ptr, (decompress_info_ptr cinfo,
int which_component,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPARRAY above,
JSAMPARRAY input_data,
JSAMPARRAY below,
JSAMPARRAY output_data));
typedef METHOD(void, quantize_method_ptr, (decompress_info_ptr cinfo,
int num_rows,
JSAMPIMAGE input_data,
JSAMPARRAY output_workspace));
typedef METHOD(void, quantize_caller_ptr, (decompress_info_ptr cinfo,
quantize_method_ptr quantize_method));
/* These structs contain function pointers for the various JPEG methods. */
/* Routines to be provided by the surrounding application, rather than the
* portable JPEG code proper. These are the same for compression and
* decompression.
*/
struct external_methods_struct {
/* User interface: error exit and trace message routines */
/* NOTE: the string msgtext parameters will eventually be replaced */
/* by an enumerated-type code so that non-English error messages */
/* can be substituted easily. This will not be done until all the */
/* code is in place, so that we know what messages are needed. */
METHOD(void, error_exit, (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 levels 1, 2, 3 for successively more detailed trace options */
int message_parm[8]; /* store numeric parms for messages here */
/* Memory management */
/* NB: alloc routines never return NULL. They exit to */
/* error_exit if not successful. */
METHOD(void *, alloc_small, (size_t sizeofobject));
METHOD(void, free_small, (void *ptr));
METHOD(void FAR *, alloc_medium, (size_t sizeofobject));
METHOD(void, free_medium, (void FAR *ptr));
METHOD(JSAMPARRAY, alloc_small_sarray, (long samplesperrow,
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));
METHOD(big_sarray_ptr, request_big_sarray, (long samplesperrow,
long numrows,
long unitheight));
METHOD(big_barray_ptr, request_big_barray, (long blocksperrow,
long numrows,
long unitheight));
METHOD(void, alloc_big_arrays, (long extra_small_samples,
long extra_small_blocks,
long extra_medium_space));
METHOD(JSAMPARRAY, access_big_sarray, (big_sarray_ptr ptr,
long start_row,
boolean writable));
METHOD(JBLOCKARRAY, access_big_barray, (big_barray_ptr ptr,
long start_row,
boolean writable));
METHOD(void, free_big_sarray, (big_sarray_ptr ptr));
METHOD(void, free_big_barray, (big_barray_ptr ptr));
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 */
#define ERREXIT(emeth,msg) ((*(emeth)->error_exit) (msg))
#define ERREXIT1(emeth,msg,p1) ((emeth)->message_parm[0] = (p1), \
(*(emeth)->error_exit) (msg))
#define ERREXIT2(emeth,msg,p1,p2) ((emeth)->message_parm[0] = (p1), \
(emeth)->message_parm[1] = (p2), \
(*(emeth)->error_exit) (msg))
#define ERREXIT3(emeth,msg,p1,p2,p3) ((emeth)->message_parm[0] = (p1), \
(emeth)->message_parm[1] = (p2), \
(emeth)->message_parm[2] = (p3), \
(*(emeth)->error_exit) (msg))
#define ERREXIT4(emeth,msg,p1,p2,p3,p4) ((emeth)->message_parm[0] = (p1), \
(emeth)->message_parm[1] = (p2), \
(emeth)->message_parm[2] = (p3), \
(emeth)->message_parm[3] = (p4), \
(*(emeth)->error_exit) (msg))
#define MAKESTMT(stuff) do { stuff } while (0)
#define TRACEMS(emeth,lvl,msg) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
(*(emeth)->trace_message) (msg); } )
#define TRACEMS1(emeth,lvl,msg,p1) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
(emeth)->message_parm[0] = (p1); \
(*(emeth)->trace_message) (msg); } )
#define TRACEMS2(emeth,lvl,msg,p1,p2) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
(emeth)->message_parm[0] = (p1); \
(emeth)->message_parm[1] = (p2); \
(*(emeth)->trace_message) (msg); } )
#define TRACEMS3(emeth,lvl,msg,p1,p2,p3) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
int * _mp = (emeth)->message_parm; \
*_mp++ = (p1); *_mp++ = (p2); *_mp = (p3); \
(*(emeth)->trace_message) (msg); } )
#define TRACEMS4(emeth,lvl,msg,p1,p2,p3,p4) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
int * _mp = (emeth)->message_parm; \
*_mp++ = (p1); *_mp++ = (p2); *_mp++ = (p3); *_mp = (p4); \
(*(emeth)->trace_message) (msg); } )
#define TRACEMS8(emeth,lvl,msg,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT( if ((emeth)->trace_level >= (lvl)) { \
int * _mp = (emeth)->message_parm; \
*_mp++ = (p1); *_mp++ = (p2); *_mp++ = (p3); *_mp++ = (p4); \
*_mp++ = (p5); *_mp++ = (p6); *_mp++ = (p7); *_mp = (p8); \
(*(emeth)->trace_message) (msg); } )
/* Methods used during JPEG compression. */
struct compress_methods_struct {
/* Hook for user interface to get control after input_init */
METHOD(void, c_ui_method_selection, (compress_info_ptr cinfo));
/* 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));
/* 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,
JSAMPIMAGE image_data));
METHOD(void, colorin_term, (compress_info_ptr cinfo));
/* Expand picture data at edges */
METHOD(void, edge_expand, (compress_info_ptr cinfo,
long input_cols, int input_rows,
long output_cols, int output_rows,
JSAMPIMAGE image_data));
/* Subsample pixel values of a single component */
/* There can be a different subsample method for each component */
METHOD(void, subsample_init, (compress_info_ptr cinfo));
subsample_ptr subsample[MAX_COMPS_IN_SCAN];
METHOD(void, subsample_term, (compress_info_ptr cinfo));
/* Extract samples in MCU order, process & hand off to output_method */
/* The input is always exactly N MCU rows worth of data */
METHOD(void, extract_init, (compress_info_ptr cinfo));
METHOD(void, extract_MCUs, (compress_info_ptr cinfo,
JSAMPIMAGE image_data,
int num_mcu_rows,
MCU_output_method_ptr output_method));
METHOD(void, extract_term, (compress_info_ptr cinfo));
/* Entropy encoding parameter optimization */
METHOD(void, entropy_optimize, (compress_info_ptr cinfo,
MCU_output_caller_ptr source_method));
/* Entropy encoding */
METHOD(void, entropy_encoder_init, (compress_info_ptr cinfo));
METHOD(void, entropy_encode, (compress_info_ptr cinfo,
JBLOCK *MCU_data));
METHOD(void, entropy_encoder_term, (compress_info_ptr cinfo));
/* JPEG file header construction */
METHOD(void, write_file_header, (compress_info_ptr cinfo));
METHOD(void, write_scan_header, (compress_info_ptr cinfo));
METHOD(void, write_jpeg_data, (compress_info_ptr cinfo,
char *dataptr,
int datacount));
METHOD(void, write_scan_trailer, (compress_info_ptr cinfo));
METHOD(void, write_file_trailer, (compress_info_ptr cinfo));
/* Pipeline control */
METHOD(void, c_pipeline_controller, (compress_info_ptr cinfo));
METHOD(void, entropy_output, (compress_info_ptr cinfo,
char *dataptr,
int datacount));
/* Overall control */
METHOD(void, c_per_scan_method_selection, (compress_info_ptr cinfo));
};
/* Methods used during JPEG decompression. */
struct decompress_methods_struct {
/* Hook for user interface to get control after reading file header */
METHOD(void, d_ui_method_selection, (decompress_info_ptr cinfo));
/* Hook for user interface to do progress monitoring */
METHOD(void, progress_monitor, (decompress_info_ptr cinfo,
long loopcounter, long looplimit));
/* JPEG file scanning */
METHOD(void, read_file_header, (decompress_info_ptr cinfo));
METHOD(boolean, read_scan_header, (decompress_info_ptr cinfo));
METHOD(int, read_jpeg_data, (decompress_info_ptr cinfo));
METHOD(void, read_scan_trailer, (decompress_info_ptr cinfo));
METHOD(void, read_file_trailer, (decompress_info_ptr cinfo));
/* Entropy decoding */
METHOD(void, entropy_decoder_init, (decompress_info_ptr cinfo));
METHOD(void, entropy_decode, (decompress_info_ptr cinfo,
JBLOCK *MCU_data));
METHOD(void, entropy_decoder_term, (decompress_info_ptr cinfo));
/* MCU disassembly: fetch MCUs from entropy_decode, build coef array */
/* 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,
jpeg_component_info *compptr,
JBLOCKROW above,
JBLOCKROW currow,
JBLOCKROW below,
JBLOCKROW output));
/* Un-subsample pixel values of a single component */
/* There can be a different unsubsample method for each component */
METHOD(void, unsubsample_init, (decompress_info_ptr cinfo));
unsubsample_ptr unsubsample[MAX_COMPS_IN_SCAN];
METHOD(void, unsubsample_term, (decompress_info_ptr cinfo));
/* Color space and gamma conversion */
METHOD(void, colorout_init, (decompress_info_ptr cinfo));
METHOD(void, color_convert, (decompress_info_ptr cinfo,
int num_rows, long num_cols,
JSAMPIMAGE input_data,
JSAMPIMAGE output_data));
METHOD(void, colorout_term, (decompress_info_ptr cinfo));
/* Color quantization */
METHOD(void, color_quant_init, (decompress_info_ptr cinfo));
METHOD(void, color_quantize, (decompress_info_ptr cinfo,
int num_rows,
JSAMPIMAGE input_data,
JSAMPARRAY output_data));
METHOD(void, color_quant_prescan, (decompress_info_ptr cinfo,
int num_rows,
JSAMPIMAGE image_data,
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));
/* Output image writing */
METHOD(void, output_init, (decompress_info_ptr cinfo));
METHOD(void, put_color_map, (decompress_info_ptr cinfo,
int num_colors, JSAMPARRAY colormap));
METHOD(void, put_pixel_rows, (decompress_info_ptr cinfo,
int num_rows,
JSAMPIMAGE pixel_data));
METHOD(void, output_term, (decompress_info_ptr cinfo));
/* Pipeline control */
METHOD(void, d_pipeline_controller, (decompress_info_ptr cinfo));
/* Overall control */
METHOD(void, d_per_scan_method_selection, (decompress_info_ptr cinfo));
};
/* External declarations for routines that aren't called via method ptrs. */
/* Note: use "j" as first char of names to minimize namespace pollution. */
/* The PP macro hides prototype parameters from compilers that can't cope. */
#ifdef PROTO
#define PP(arglist) arglist
#else
#define PP(arglist) ()
#endif
/* main entry for compression */
EXTERN void jpeg_compress PP((compress_info_ptr cinfo));
/* default parameter setup for compression */
EXTERN void j_c_defaults PP((compress_info_ptr cinfo, int quality,
boolean force_baseline));
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));
/* main entry for decompression */
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));
/* forward DCT */
EXTERN void j_fwd_dct PP((DCTBLOCK data));
/* inverse DCT */
EXTERN void j_rev_dct PP((DCTBLOCK data));
/* utility routines in jutils.c */
EXTERN long jround_up PP((long a, long b));
EXTERN void jcopy_sample_rows PP((JSAMPARRAY input_array, int source_row,
JSAMPARRAY output_array, int dest_row,
int num_rows, long num_cols));
EXTERN void jcopy_block_row PP((JBLOCKROW input_row, JBLOCKROW output_row,
long num_blocks));
EXTERN void jzero_far PP((void FAR * target, size_t bytestozero));
/* method selection routines for compression modules */
EXTERN void jselcpipeline PP((compress_info_ptr cinfo)); /* jcpipe.c */
EXTERN void jselchuffman PP((compress_info_ptr cinfo)); /* jchuff.c */
EXTERN void jselcarithmetic PP((compress_info_ptr cinfo)); /* jcarith.c */
EXTERN void jselexpand PP((compress_info_ptr cinfo)); /* jcexpand.c */
EXTERN void jselsubsample PP((compress_info_ptr cinfo)); /* jcsample.c */
EXTERN void jselcmcu PP((compress_info_ptr cinfo)); /* jcmcu.c */
EXTERN void jselccolor PP((compress_info_ptr cinfo)); /* jccolor.c */
/* The user interface should call one of these to select input format: */
EXTERN void jselrgif PP((compress_info_ptr cinfo)); /* jrdgif.c */
EXTERN void jselrppm PP((compress_info_ptr cinfo)); /* jrdppm.c */
EXTERN void jselrrle PP((compress_info_ptr cinfo)); /* jrdrle.c */
EXTERN void jselrtarga PP((compress_info_ptr cinfo)); /* jrdtarga.c */
/* and one of these to select output header format: */
EXTERN void jselwjfif PP((compress_info_ptr cinfo)); /* jwrjfif.c */
/* method selection routines for decompression modules */
EXTERN void jseldpipeline PP((decompress_info_ptr cinfo)); /* jdpipe.c */
EXTERN void jseldhuffman PP((decompress_info_ptr cinfo)); /* jdhuff.c */
EXTERN void jseldarithmetic PP((decompress_info_ptr cinfo)); /* jdarith.c */
EXTERN void jseldmcu PP((decompress_info_ptr cinfo)); /* jdmcu.c */
EXTERN void jselbsmooth PP((decompress_info_ptr cinfo)); /* jbsmooth.c */
EXTERN void jselunsubsample PP((decompress_info_ptr cinfo)); /* jdsample.c */
EXTERN void jseldcolor PP((decompress_info_ptr cinfo)); /* jdcolor.c */
EXTERN void jsel1quantize PP((decompress_info_ptr cinfo)); /* jquant1.c */
EXTERN void jsel2quantize PP((decompress_info_ptr cinfo)); /* jquant2.c */
/* The user interface should call one of these to select input format: */
EXTERN void jselrjfif PP((decompress_info_ptr cinfo)); /* jrdjfif.c */
/* and one of these to select output image format: */
EXTERN void jselwgif PP((decompress_info_ptr cinfo)); /* jwrgif.c */
EXTERN void jselwppm PP((decompress_info_ptr cinfo)); /* jwrppm.c */
EXTERN void jselwrle PP((decompress_info_ptr cinfo)); /* jwrrle.c */
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 jselmemmgr PP((external_methods_ptr emethods)); /* jmemmgr.c */
/* 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
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define RST0 0xD0 /* RST0 marker code */

361
jpegint.h Normal file
View File

@@ -0,0 +1,361 @@
/*
* jpegint.h
*
* Copyright (C) 1991-1994, 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 common declarations for the various JPEG modules.
* These declarations are considered internal to the JPEG library; most
* applications using the library shouldn't need to include this file.
*/
/* Declarations for both compression & decompression */
typedef enum { /* Operating modes for buffer controllers */
JBUF_PASS_THRU, /* Plain stripwise operation */
JBUF_CRANK_SOURCE, /* Run source subobject, no output expected */
/* Remaining modes require a full-image buffer to have been created */
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
} J_BUF_MODE;
/* Values of global_state field */
#define CSTATE_START 100 /* after create_compress */
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
#define DSTATE_START 200 /* after create_decompress */
#define DSTATE_INHEADER 201 /* read_header initialized but not done */
#define DSTATE_READY 202 /* read_header done, found image */
#define DSTATE_SCANNING 203 /* start_decompress done, read_scanlines OK */
#define DSTATE_RAW_OK 204 /* start_decompress done, read_raw_data OK */
#define DSTATE_STOPPING 205 /* done reading data, looking for EOI */
/* Declarations for compression modules */
/* Master control module */
struct jpeg_comp_master {
JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
/* State variables made visible to other modules */
boolean call_pass_startup; /* True if pass_startup must be called */
boolean is_last_pass; /* True during last pass */
};
/* Main buffer control (downsampled-data buffer) */
struct jpeg_c_main_controller {
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(void, process_data, (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail));
};
/* Compression preprocessing (downsampling input buffer control) */
struct jpeg_c_prep_controller {
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
JSAMPARRAY input_buf,
JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
JSAMPIMAGE output_buf,
JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail));
};
/* Coefficient buffer control */
struct jpeg_c_coef_controller {
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(void, compress_data, (j_compress_ptr cinfo,
JSAMPIMAGE input_buf,
JDIMENSION *in_mcu_ctr));
};
/* Colorspace conversion */
struct jpeg_color_converter {
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
JMETHOD(void, color_convert, (j_compress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
JDIMENSION output_row, int num_rows));
};
/* Downsampling */
struct jpeg_downsampler {
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
JMETHOD(void, downsample, (j_compress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
JSAMPIMAGE output_buf,
JDIMENSION out_row_group_index));
boolean need_context_rows; /* TRUE if need rows above & below */
};
/* Forward DCT (also controls coefficient quantization) */
struct jpeg_forward_dct {
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
/* perhaps this should be an array??? */
JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks));
};
/* Entropy encoding */
struct jpeg_entropy_encoder {
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
};
/* Marker writing */
struct jpeg_marker_writer {
/* write_any_marker is exported for use by applications */
/* Probably only COM and APPn markers should be written */
JMETHOD(void, write_any_marker, (j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen));
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
};
/* Declarations for decompression modules */
/* Master control module */
struct jpeg_decomp_master {
JMETHOD(void, prepare_for_pass, (j_decompress_ptr cinfo));
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
/* State variables made visible to other modules */
boolean is_last_pass; /* True during last pass */
boolean eoi_processed; /* True if EOI marker already read */
};
/* Main buffer control (downsampled-data buffer) */
struct jpeg_d_main_controller {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
/* During input-only passes, output_buf and out_rows_avail are ignored.
* out_row_ctr is incremented towards the limit num_chunks.
*/
JDIMENSION num_chunks; /* number of chunks to be processed in pass */
};
/* Coefficient buffer control */
struct jpeg_d_coef_controller {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(boolean, decompress_data, (j_decompress_ptr cinfo,
JSAMPIMAGE output_buf));
};
/* Decompression postprocessing (color quantization buffer control) */
struct jpeg_d_post_controller {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf,
JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
};
/* Marker reading & parsing */
struct jpeg_marker_reader {
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
/* Read markers until SOS or EOI.
* Returns same codes as are defined for jpeg_read_header,
* but HEADER_OK and HEADER_TABLES_ONLY merely indicate which marker type
* stopped the scan --- further validation is needed to declare file OK.
*/
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
/* Read a restart marker --- exported for use by entropy decoder only */
jpeg_marker_parser_method read_restart_marker;
/* Application-overridable marker processing methods */
jpeg_marker_parser_method process_COM;
jpeg_marker_parser_method process_APPn[16];
/* State of marker reader --- nominally internal, but applications
* supplying COM or APPn handlers might like to know the state.
*/
boolean saw_SOI; /* found SOI? */
boolean saw_SOF; /* found SOF? */
int next_restart_num; /* next restart number expected (0-7) */
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
};
/* Entropy decoding */
struct jpeg_entropy_decoder {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
JBLOCKROW *MCU_data));
};
/* Inverse DCT (also performs dequantization) */
typedef JMETHOD(void, inverse_DCT_method_ptr,
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col));
struct jpeg_inverse_dct {
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
/* It is useful to allow each component to have a separate IDCT method. */
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
};
/* Upsampling (note that upsampler must also call color converter) */
struct jpeg_upsampler {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf,
JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
JSAMPARRAY output_buf,
JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail));
boolean need_context_rows; /* TRUE if need rows above & below */
};
/* Colorspace conversion */
struct jpeg_color_deconverter {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
JSAMPIMAGE input_buf, JDIMENSION input_row,
JSAMPARRAY output_buf, int num_rows));
};
/* Color quantization or color precision reduction */
struct jpeg_color_quantizer {
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
int num_rows));
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
};
/* Miscellaneous useful macros */
#undef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
/* 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
/* Short forms of external names for systems with brain-damaged linkers. */
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jinit_master_compress jICMaster
#define jinit_c_main_controller jICMainC
#define jinit_c_prep_controller jICPrepC
#define jinit_c_coef_controller jICCoefC
#define jinit_color_converter jICColor
#define jinit_downsampler jIDownsampler
#define jinit_forward_dct jIFDCT
#define jinit_huff_encoder jIHEncoder
#define jinit_marker_writer jIMWriter
#define jinit_master_decompress jIDMaster
#define jinit_d_main_controller jIDMainC
#define jinit_d_coef_controller jIDCoefC
#define jinit_d_post_controller jIDPostC
#define jinit_marker_reader jIMReader
#define jinit_huff_decoder jIHDecoder
#define jinit_inverse_dct jIIDCT
#define jinit_upsampler jIUpsampler
#define jinit_color_deconverter jIDColor
#define jinit_1pass_quantizer jI1Quant
#define jinit_2pass_quantizer jI2Quant
#define jinit_merged_upsampler jIMUpsampler
#define jinit_memory_mgr jIMemMgr
#define jdiv_round_up jDivRound
#define jround_up jRound
#define jcopy_sample_rows jCopySamples
#define jcopy_block_row jCopyBlocks
#define jzero_far jZeroFar
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Compression module initialization routines */
EXTERN void jinit_master_compress JPP((j_compress_ptr cinfo));
EXTERN void jinit_c_main_controller JPP((j_compress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_c_prep_controller JPP((j_compress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_c_coef_controller JPP((j_compress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_color_converter JPP((j_compress_ptr cinfo));
EXTERN void jinit_downsampler JPP((j_compress_ptr cinfo));
EXTERN void jinit_forward_dct JPP((j_compress_ptr cinfo));
EXTERN void jinit_huff_encoder JPP((j_compress_ptr cinfo));
EXTERN void jinit_marker_writer JPP((j_compress_ptr cinfo));
/* Decompression module initialization routines */
EXTERN void jinit_master_decompress JPP((j_decompress_ptr cinfo));
EXTERN void jinit_d_main_controller JPP((j_decompress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_d_post_controller JPP((j_decompress_ptr cinfo,
boolean need_full_buffer));
EXTERN void jinit_marker_reader JPP((j_decompress_ptr cinfo));
EXTERN void jinit_huff_decoder JPP((j_decompress_ptr cinfo));
EXTERN void jinit_inverse_dct JPP((j_decompress_ptr cinfo));
EXTERN void jinit_upsampler JPP((j_decompress_ptr cinfo));
EXTERN void jinit_color_deconverter JPP((j_decompress_ptr cinfo));
EXTERN void jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
EXTERN void jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
EXTERN void jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
/* Memory manager initialization */
EXTERN void jinit_memory_mgr JPP((j_common_ptr cinfo));
/* Utility routines in jutils.c */
EXTERN long jdiv_round_up JPP((long a, long b));
EXTERN long jround_up JPP((long a, long b));
EXTERN void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
JSAMPARRAY output_array, int dest_row,
int num_rows, JDIMENSION num_cols));
EXTERN void jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
JDIMENSION num_blocks));
EXTERN void jzero_far JPP((void FAR * target, size_t bytestozero));
/* Suppress undefined-structure complaints if necessary. */
#ifdef INCOMPLETE_TYPES_BROKEN
#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
struct jvirt_sarray_control { long dummy; };
struct jvirt_barray_control { long dummy; };
#endif
#endif /* INCOMPLETE_TYPES_BROKEN */

930
jpeglib.h Normal file
View File

@@ -0,0 +1,930 @@
/*
* jpeglib.h
*
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the application interface for the JPEG library.
* Most applications using the library need only include this file,
* and perhaps jerror.h if they want to know the exact error codes.
*/
/*
* First we include the configuration files that record how this
* installation of the JPEG library is set up. jconfig.h can be
* generated automatically for many systems. jmorecfg.h contains
* manual configuration options that most people need not worry about.
*/
#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
#include "jconfig.h" /* widely used configuration options */
#endif
#include "jmorecfg.h" /* seldom changed options */
/* Version ID for the JPEG library.
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
*/
#define JPEG_LIB_VERSION 50 /* Version 5.0 */
/* Various constants determining the sizes of things.
* All of these are specified by the JPEG standard, so don't change them
* if you want to be compatible.
*/
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
#define MAX_BLOCKS_IN_MCU 10 /* JPEG limit on # of blocks in an MCU */
/* This macro is used to declare a "method", that is, a function pointer.
* We want to supply prototype parameters if the compiler can cope.
* Note that the arglist parameter must be parenthesized!
*/
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
/* Data structures for images (arrays of samples and of DCT coefficients).
* On 80x86 machines, the image arrays are too big for near pointers,
* but the pointer arrays can fit in near memory.
*/
typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
/* Types for JPEG compression parameters and working tables. */
/* DCT coefficient quantization tables. */
typedef struct {
/* This field directly represents the contents of a JPEG DQT marker.
* Note: the values are always given in zigzag order.
*/
UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
/* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* TRUE when table has been output */
} JQUANT_TBL;
/* Huffman coding tables. */
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 */
UINT8 huffval[256]; /* The symbols, in order of incr code length */
/* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* TRUE when table has been output */
} JHUFF_TBL;
/* Basic info about one component (color channel). */
typedef struct {
/* These values are fixed over the whole image. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOF marker. */
int component_id; /* identifier for this component (0..255) */
int component_index; /* its index in SOF or cinfo->comp_info[] */
int h_samp_factor; /* horizontal sampling factor (1..4) */
int v_samp_factor; /* vertical sampling factor (1..4) */
int quant_tbl_no; /* quantization table selector (0..3) */
/* These values may vary between scans. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOS marker. */
int dc_tbl_no; /* DC entropy table selector (0..3) */
int ac_tbl_no; /* AC entropy table selector (0..3) */
/* Remaining fields should be treated as private by applications. */
/* These values are computed during compression or decompression startup: */
/* Component's size in DCT blocks.
* Any dummy blocks added to complete an MCU are not counted; therefore
* these values do not depend on whether a scan is interleaved or not.
*/
JDIMENSION width_in_blocks;
JDIMENSION height_in_blocks;
/* Size of a DCT block in samples. Always DCTSIZE for compression.
* For decompression this is the size of the output from one DCT block,
* reflecting any scaling we choose to apply during the IDCT step.
* Values of 1,2,4,8 are likely to be supported. Note that different
* components may receive different IDCT scalings.
*/
int DCT_scaled_size;
/* The downsampled dimensions are the component's actual, unpadded number
* of samples at the main buffer (preprocessing/compression interface), thus
* downsampled_width = ceil(image_width * Hi/Hmax)
* and similarly for height. For decompression, IDCT scaling is included, so
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
*/
JDIMENSION downsampled_width; /* actual width in samples */
JDIMENSION downsampled_height; /* actual height in samples */
/* 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 most computations for the unused components.
*/
boolean component_needed; /* do we need the value of this component? */
/* These values are computed before starting a scan of the component: */
int MCU_width; /* number of blocks per MCU, horizontally */
int MCU_height; /* number of blocks per MCU, vertically */
int MCU_blocks; /* MCU_width * MCU_height */
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
int last_col_width; /* # of non-dummy blocks across in last MCU */
int last_row_height; /* # of non-dummy blocks down in last MCU */
/* Private per-component storage for DCT or IDCT subsystem. */
void * dct_table;
} jpeg_component_info;
/* Known color spaces. */
typedef enum {
JCS_UNKNOWN, /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */
JCS_RGB, /* red/green/blue */
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
JCS_CMYK, /* C/M/Y/K */
JCS_YCCK /* Y/Cb/Cr/K */
} J_COLOR_SPACE;
/* DCT/IDCT algorithm options. */
typedef enum {
JDCT_ISLOW, /* slow but accurate integer algorithm */
JDCT_IFAST, /* faster, less accurate integer method */
JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
} J_DCT_METHOD;
#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
#define JDCT_DEFAULT JDCT_ISLOW
#endif
#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
#define JDCT_FASTEST JDCT_IFAST
#endif
/* Dithering options for decompression. */
typedef enum {
JDITHER_NONE, /* no dithering */
JDITHER_ORDERED, /* simple ordered dither */
JDITHER_FS /* Floyd-Steinberg error diffusion dither */
} J_DITHER_MODE;
/* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \
struct jpeg_error_mgr * err; /* Error handler module */\
struct jpeg_memory_mgr * mem; /* Memory manager module */\
struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
boolean is_decompressor; /* so common code can tell which is which */\
int global_state /* for checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared
* to receive a pointer to this structure. There are no actual instances of
* jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
*/
struct jpeg_common_struct {
jpeg_common_fields; /* Fields common to both master struct types */
/* Additional fields follow in an actual jpeg_compress_struct or
* jpeg_decompress_struct. All three structs must agree on these
* initial fields! (This would be a lot cleaner in C++.)
*/
};
typedef struct jpeg_common_struct * j_common_ptr;
typedef struct jpeg_compress_struct * j_compress_ptr;
typedef struct jpeg_decompress_struct * j_decompress_ptr;
/* Master record for a compression instance */
struct jpeg_compress_struct {
jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
/* Destination for compressed data */
struct jpeg_destination_mgr * dest;
/* Description of source image --- these fields must be filled in by
* outer application before starting compression. in_color_space must
* be correct before you can even call jpeg_set_defaults().
*/
JDIMENSION image_width; /* input image width */
JDIMENSION image_height; /* input image height */
int input_components; /* # of color components in input image */
J_COLOR_SPACE in_color_space; /* colorspace of input image */
double input_gamma; /* image gamma of input image */
/* Compression parameters --- these fields must be set before calling
* jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
* initialize everything to reasonable defaults, then changing anything
* the application specifically wants to change. That way you won't get
* burnt when new parameters are added. Also note that there are several
* helper routines to simplify changing parameters.
*/
int data_precision; /* bits of precision in image data */
int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined */
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
boolean raw_data_in; /* TRUE=caller supplies downsampled data */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
boolean interleave; /* TRUE=interleaved output, FALSE=not */
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
int smoothing_factor; /* 1..100, or 0 for no input smoothing */
J_DCT_METHOD dct_method; /* DCT algorithm selector */
/* 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).
*/
unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
int restart_in_rows; /* if > 0, MCU rows per restart interval */
/* Parameters controlling emission of special markers. */
boolean write_JFIF_header; /* should a JFIF marker be written? */
/* These three values are not used by the JPEG code, merely copied */
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
/* ratio is defined by X_density/Y_density even when density_unit=0. */
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
boolean write_Adobe_marker; /* should an Adobe marker be written? */
/* State variable: index of next scanline to be written to
* jpeg_write_scanlines(). Application may use this to control its
* processing loop, e.g., "while (next_scanline < image_height)".
*/
JDIMENSION next_scanline; /* 0 .. image_height-1 */
/* Remaining fields are known throughout compressor, but generally
* should not be touched by a surrounding application.
*/
/*
* These fields are computed during compression startup
*/
int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
/* The coefficient controller receives data in units of MCU rows as defined
* for fully interleaved scans (whether the JPEG file is interleaved or not).
* There are v_samp_factor * DCTSIZE sample rows of each component in an
* "iMCU" (interleaved MCU) row.
*/
/*
* These fields are valid during any one scan.
* They describe the components and MCUs actually appearing in the scan.
*/
int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
/*
* Links to compression subobjects (methods and private variables of modules)
*/
struct jpeg_comp_master * master;
struct jpeg_c_main_controller * main;
struct jpeg_c_prep_controller * prep;
struct jpeg_c_coef_controller * coef;
struct jpeg_marker_writer * marker;
struct jpeg_color_converter * cconvert;
struct jpeg_downsampler * downsample;
struct jpeg_forward_dct * fdct;
struct jpeg_entropy_encoder * entropy;
};
/* Master record for a decompression instance */
struct jpeg_decompress_struct {
jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
/* Source of compressed data */
struct jpeg_source_mgr * src;
/* Basic description of image --- filled in by jpeg_read_header(). */
/* Application may inspect these values to decide how to process image. */
JDIMENSION image_width; /* nominal image width (from SOF marker) */
JDIMENSION image_height; /* nominal image height */
int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
/* Decompression processing parameters --- these fields must be set before
* calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
* them to default values.
*/
J_COLOR_SPACE out_color_space; /* colorspace for output */
unsigned int scale_num, scale_denom; /* fraction by which to scale image */
double output_gamma; /* image gamma wanted in output */
boolean raw_data_out; /* TRUE=downsampled data wanted */
boolean quantize_colors; /* TRUE=colormapped output wanted */
/* the following are ignored if not quantize_colors: */
boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
J_DITHER_MODE dither_mode; /* type of color dithering to use */
int desired_number_of_colors; /* max number of colors to use */
J_DCT_METHOD dct_method; /* DCT algorithm selector */
boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
/* Description of actual output image that will be returned to application.
* These fields are computed by jpeg_start_decompress().
* You can also use jpeg_calc_output_dimensions() to determine these values
* in advance of calling jpeg_start_decompress().
*/
JDIMENSION output_width; /* scaled image width */
JDIMENSION output_height; /* scaled image height */
int out_color_components; /* # of color components in out_color_space */
int output_components; /* # of color components returned */
/* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components.
*/
int rec_outbuf_height; /* min recommended height of scanline buffer */
/* If the buffer passed to jpeg_read_scanlines() is less than this many rows
* high, space and time will be wasted due to unnecessary data copying.
* Usually rec_outbuf_height will be 1 or 2, at most 4.
*/
/* When quantizing colors, the output colormap is described by these fields.
* The application can supply a colormap by setting colormap non-NULL before
* calling jpeg_start_decompress; otherwise a colormap is created during
* jpeg_start_decompress.
* The map has out_color_components rows and actual_number_of_colors columns.
*/
int actual_number_of_colors; /* number of entries in use */
JSAMPARRAY colormap; /* The color map as a 2-D pixel array */
/* State variable: index of next scaled scanline to be read from
* jpeg_read_scanlines(). Application may use this to control its
* processing loop, e.g., "while (output_scanline < output_height)".
*/
JDIMENSION output_scanline; /* 0 .. output_height-1 */
/* Internal JPEG parameters --- the application usually need not look at
* these fields.
*/
/* Quantization and Huffman tables are carried forward across input
* datastreams when processing abbreviated JPEG datastreams.
*/
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined */
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
/* These parameters are never carried across datastreams, since they
* are given in SOF/SOS markers or defined to be reset by SOI.
*/
int data_precision; /* bits of precision in image data */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
/* These fields record data obtained from optional markers recognized by
* the JPEG library.
*/
boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
/* Data copied from JFIF marker: */
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
UINT8 Adobe_transform; /* Color transform code from Adobe marker */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
/* Remaining fields are known throughout decompressor, but generally
* should not be touched by a surrounding application.
*/
/*
* These fields are computed during decompression startup
*/
int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */
int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be output by coef ctlr */
/* The coefficient controller outputs data in units of MCU rows as defined
* for fully interleaved scans (whether the JPEG file is interleaved or not).
* There are v_samp_factor * DCT_scaled_size sample rows of each component
* in an "iMCU" (interleaved MCU) row.
*/
JSAMPLE * sample_range_limit; /* table for fast range-limiting */
/*
* These fields are valid during any one scan.
* They describe the components and MCUs actually appearing in the scan.
*/
int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
/* This field is shared between entropy decoder and marker parser.
* It is either zero or the code of a JPEG marker that has been
* read from the data source, but has not yet been processed.
*/
int unread_marker;
/*
* Links to decompression subobjects (methods, private variables of modules)
*/
struct jpeg_decomp_master * master;
struct jpeg_d_main_controller * main;
struct jpeg_d_coef_controller * coef;
struct jpeg_d_post_controller * post;
struct jpeg_marker_reader * marker;
struct jpeg_entropy_decoder * entropy;
struct jpeg_inverse_dct * idct;
struct jpeg_upsampler * upsample;
struct jpeg_color_deconverter * cconvert;
struct jpeg_color_quantizer * cquantize;
};
/* "Object" declarations for JPEG modules that may be supplied or called
* directly by the surrounding application.
* As with all objects in the JPEG library, these structs only define the
* publicly visible methods and state variables of a module. Additional
* private fields may exist after the public ones.
*/
/* Error handler object */
struct jpeg_error_mgr {
/* Error exit handler: does not return to caller */
JMETHOD(void, error_exit, (j_common_ptr cinfo));
/* Conditionally emit a trace or warning message */
JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
/* Routine that actually outputs a trace or error message */
JMETHOD(void, output_message, (j_common_ptr cinfo));
/* Format a message string for the most recent JPEG error or message */
JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
/* Reset error state variables at start of a new image */
JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
/* The message ID code and any parameters are saved here.
* A message can have one string parameter or up to 8 int parameters.
*/
int msg_code;
#define JMSG_STR_PARM_MAX 80
union {
int i[8];
char s[JMSG_STR_PARM_MAX];
} msg_parm;
/* Standard state variables for error facility */
int trace_level; /* max msg_level that will be displayed */
/* For recoverable corrupt-data errors, we emit a warning message,
* but keep going unless emit_message chooses to abort. emit_message
* should count warnings in num_warnings. The 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 */
/* These fields point to the table(s) of error message strings.
* An application can change the table pointer to switch to a different
* message list (typically, to change the language in which errors are
* reported). Some applications may wish to add additional error codes
* that will be handled by the JPEG library error mechanism; the second
* table pointer is used for this purpose.
*
* First table includes all errors generated by JPEG library itself.
* Error code 0 is reserved for a "no such error string" message.
*/
const char * const * jpeg_message_table; /* Library errors */
int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
/* Second table can be added by application (see cjpeg/djpeg for example).
* It contains strings numbered first_addon_message..last_addon_message.
*/
const char * const * addon_message_table; /* Non-library errors */
int first_addon_message; /* code for first string in addon table */
int last_addon_message; /* code for last string in addon table */
};
/* Progress monitor object */
struct jpeg_progress_mgr {
JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
long pass_counter; /* work units completed in this pass */
long pass_limit; /* total number of work units in this pass */
int completed_passes; /* passes completed so far */
int total_passes; /* total number of passes expected */
};
/* Data destination object for compression */
struct jpeg_destination_mgr {
JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
JMETHOD(void, init_destination, (j_compress_ptr cinfo));
JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
JMETHOD(void, term_destination, (j_compress_ptr cinfo));
};
/* Data source object for decompression */
struct jpeg_source_mgr {
const JOCTET * next_input_byte; /* => next byte to read from buffer */
size_t bytes_in_buffer; /* # of bytes remaining in buffer */
JMETHOD(void, init_source, (j_decompress_ptr cinfo));
JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo));
JMETHOD(void, term_source, (j_decompress_ptr cinfo));
};
/* Memory manager object.
* Allocates "small" objects (a few K total), "large" objects (tens of K),
* and "really big" objects (virtual arrays with backing store if needed).
* The memory manager does not allow individual objects to be freed; rather,
* each created object is assigned to a pool, and whole pools can be freed
* at once. This is faster and more convenient than remembering exactly what
* to free, especially where malloc()/free() are not too speedy.
* NB: alloc routines never return NULL. They exit to error_exit if not
* successful.
*/
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
#define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
typedef struct jvirt_barray_control * jvirt_barray_ptr;
struct jpeg_memory_mgr {
/* Method pointers */
JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
size_t sizeofobject));
JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
size_t sizeofobject));
JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
JDIMENSION samplesperrow,
JDIMENSION numrows));
JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
JDIMENSION blocksperrow,
JDIMENSION numrows));
JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
int pool_id,
JDIMENSION samplesperrow,
JDIMENSION numrows,
JDIMENSION unitheight));
JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
int pool_id,
JDIMENSION blocksperrow,
JDIMENSION numrows,
JDIMENSION unitheight));
JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
jvirt_sarray_ptr ptr,
JDIMENSION start_row,
boolean writable));
JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
jvirt_barray_ptr ptr,
JDIMENSION start_row,
boolean writable));
JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
JMETHOD(void, self_destruct, (j_common_ptr cinfo));
/* Limit on memory allocation for this JPEG object. (Note that this is
* merely advisory, not a guaranteed maximum; it only affects the space
* used for virtual-array buffers.) May be changed by outer application
* after creating the JPEG object.
*/
long max_memory_to_use;
};
/* Routine signature for application-supplied marker processing methods.
* Need not pass marker code since it is stored in cinfo->unread_marker.
*/
typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
/* Declarations for routines called by application.
* The JPP macro hides prototype parameters from compilers that can't cope.
* Note JPP requires double parentheses.
*/
#ifdef HAVE_PROTOTYPES
#define JPP(arglist) arglist
#else
#define JPP(arglist) ()
#endif
/* Short forms of external names for systems with brain-damaged linkers.
* We shorten external names to be unique in the first six letters, which
* is good enough for all known systems.
* (If your compiler itself needs names to be unique in less than 15
* characters, you are out of luck. Get a better compiler.)
*/
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_std_error jStdError
#define jpeg_create_compress jCreaCompress
#define jpeg_create_decompress jCreaDecompress
#define jpeg_destroy_compress jDestCompress
#define jpeg_destroy_decompress jDestDecompress
#define jpeg_stdio_dest jStdDest
#define jpeg_stdio_src jStdSrc
#define jpeg_set_defaults jSetDefaults
#define jpeg_set_colorspace jSetColorspace
#define jpeg_default_colorspace jDefColorspace
#define jpeg_set_quality jSetQuality
#define jpeg_set_linear_quality jSetLQuality
#define jpeg_add_quant_table jAddQuantTable
#define jpeg_quality_scaling jQualityScaling
#define jpeg_suppress_tables jSuppressTables
#define jpeg_alloc_quant_table jAlcQTable
#define jpeg_alloc_huff_table jAlcHTable
#define jpeg_start_compress jStrtCompress
#define jpeg_write_scanlines jWrtScanlines
#define jpeg_finish_compress jFinCompress
#define jpeg_write_raw_data jWrtRawData
#define jpeg_write_marker jWrtMarker
#define jpeg_write_tables jWrtTables
#define jpeg_read_header jReadHeader
#define jpeg_start_decompress jStrtDecompress
#define jpeg_read_scanlines jReadScanlines
#define jpeg_finish_decompress jFinDecompress
#define jpeg_read_raw_data jReadRawData
#define jpeg_calc_output_dimensions jCalcDimensions
#define jpeg_set_marker_processor jSetMarker
#define jpeg_abort_compress jAbrtCompress
#define jpeg_abort_decompress jAbrtDecompress
#define jpeg_abort jAbort
#define jpeg_destroy jDestroy
#define jpeg_resync_to_restart jResyncRestart
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Default error-management setup */
EXTERN struct jpeg_error_mgr *jpeg_std_error JPP((struct jpeg_error_mgr *err));
/* Initialization and destruction of JPEG compression objects */
/* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx */
EXTERN void jpeg_create_compress JPP((j_compress_ptr cinfo));
EXTERN void jpeg_create_decompress JPP((j_decompress_ptr cinfo));
EXTERN void jpeg_destroy_compress JPP((j_compress_ptr cinfo));
EXTERN void jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
/* Standard data source and destination managers: stdio streams. */
/* Caller is responsible for opening the file before and closing after. */
EXTERN void jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
EXTERN void jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
/* Default parameter setup for compression */
EXTERN void jpeg_set_defaults JPP((j_compress_ptr cinfo));
/* Compression parameter setup aids */
EXTERN void jpeg_set_colorspace JPP((j_compress_ptr cinfo,
J_COLOR_SPACE colorspace));
EXTERN void jpeg_default_colorspace JPP((j_compress_ptr cinfo));
EXTERN void jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
boolean force_baseline));
EXTERN void jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
int scale_factor,
boolean force_baseline));
EXTERN void jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table,
int scale_factor,
boolean force_baseline));
EXTERN int jpeg_quality_scaling JPP((int quality));
EXTERN void jpeg_suppress_tables JPP((j_compress_ptr cinfo,
boolean suppress));
EXTERN JQUANT_TBL * jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
EXTERN JHUFF_TBL * jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
/* Main entry points for compression */
EXTERN void jpeg_start_compress JPP((j_compress_ptr cinfo,
boolean write_all_tables));
EXTERN JDIMENSION jpeg_write_scanlines JPP((j_compress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION num_lines));
EXTERN void jpeg_finish_compress JPP((j_compress_ptr cinfo));
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
EXTERN JDIMENSION jpeg_write_raw_data JPP((j_compress_ptr cinfo,
JSAMPIMAGE data,
JDIMENSION num_lines));
/* Write a special marker. See libjpeg.doc concerning safe usage. */
EXTERN void jpeg_write_marker JPP((j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen));
/* Alternate compression function: just write an abbreviated table file */
EXTERN void jpeg_write_tables JPP((j_compress_ptr cinfo));
/* Decompression startup: read start of JPEG datastream to see what's there */
EXTERN int jpeg_read_header JPP((j_decompress_ptr cinfo,
boolean require_image));
/* Return value is one of: */
#define JPEG_HEADER_OK 0 /* Found valid image datastream */
#define JPEG_HEADER_TABLES_ONLY 1 /* Found valid table-specs-only datastream */
#define JPEG_SUSPENDED 2 /* Had to suspend before end of headers */
/* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can
* give a suspension return (the stdio source module doesn't).
*/
/* Main entry points for decompression */
EXTERN void jpeg_start_decompress JPP((j_decompress_ptr cinfo));
EXTERN JDIMENSION jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION max_lines));
EXTERN boolean jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
EXTERN JDIMENSION jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
JSAMPIMAGE data,
JDIMENSION max_lines));
/* Precalculate output dimensions for current decompression parameters. */
EXTERN void jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
/* Install a special processing method for COM or APPn markers. */
EXTERN void jpeg_set_marker_processor JPP((j_decompress_ptr cinfo,
int marker_code,
jpeg_marker_parser_method routine));
/* If you choose to abort compression or decompression before completing
* jpeg_finish_(de)compress, then you need to clean up to release memory,
* temporary files, etc. You can just call jpeg_destroy_(de)compress
* if you're done with the JPEG object, but if you want to clean it up and
* reuse it, call this:
*/
EXTERN void jpeg_abort_compress JPP((j_compress_ptr cinfo));
EXTERN void jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
* flavor of JPEG object. These may be more convenient in some places.
*/
EXTERN void jpeg_abort JPP((j_common_ptr cinfo));
EXTERN void jpeg_destroy JPP((j_common_ptr cinfo));
/* Default restart-marker-resync procedure for use by data source modules */
EXTERN boolean jpeg_resync_to_restart JPP((j_decompress_ptr cinfo));
/* These marker codes are exported since applications and data source modules
* are likely to want to use them.
*/
#define JPEG_RST0 0xD0 /* RST0 marker code */
#define JPEG_EOI 0xD9 /* EOI marker code */
#define JPEG_APP0 0xE0 /* APP0 marker code */
#define JPEG_COM 0xFE /* COM marker code */
/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
* for structure definitions that are never filled in, keep it quiet by
* supplying dummy definitions for the various substructures.
*/
#ifdef INCOMPLETE_TYPES_BROKEN
#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
struct jvirt_sarray_control { long dummy; };
struct jvirt_barray_control { long dummy; };
struct jpeg_comp_master { long dummy; };
struct jpeg_c_main_controller { long dummy; };
struct jpeg_c_prep_controller { long dummy; };
struct jpeg_c_coef_controller { long dummy; };
struct jpeg_marker_writer { long dummy; };
struct jpeg_color_converter { long dummy; };
struct jpeg_downsampler { long dummy; };
struct jpeg_forward_dct { long dummy; };
struct jpeg_entropy_encoder { long dummy; };
struct jpeg_decomp_master { long dummy; };
struct jpeg_d_main_controller { long dummy; };
struct jpeg_d_coef_controller { long dummy; };
struct jpeg_d_post_controller { long dummy; };
struct jpeg_marker_reader { long dummy; };
struct jpeg_entropy_decoder { long dummy; };
struct jpeg_inverse_dct { long dummy; };
struct jpeg_upsampler { long dummy; };
struct jpeg_color_deconverter { long dummy; };
struct jpeg_color_quantizer { long dummy; };
#endif /* JPEG_INTERNALS */
#endif /* INCOMPLETE_TYPES_BROKEN */
/*
* The JPEG library modules define JPEG_INTERNALS before including this file.
* The internal structure declarations are read only when that is true.
* Applications using the library should not include jpegint.h, but may wish
* to include jerror.h.
*/
#ifdef JPEG_INTERNALS
#include "jpegint.h" /* fetch private declarations */
#include "jerror.h" /* fetch error codes too */
#endif

752
jquant1.c
View File

@@ -1,16 +1,18 @@
/*
* jquant1.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains 1-pass color quantization (color mapping) routines.
* These routines are invoked via the methods color_quantize
* and color_quant_init/term.
* These routines provide mapping to a fixed color map using equally spaced
* color values. Optional Floyd-Steinberg or ordered dithering is available.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#ifdef QUANT_1PASS_SUPPORTED
@@ -22,24 +24,6 @@
* quantizer is perfectly adequate. Dithering is highly recommended with this
* quantizer, though you can turn it off if you really want to.
*
* 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 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
@@ -58,65 +42,101 @@
* 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.
*
* If gamma correction has been applied in color conversion, it might be wise
* to adjust the color grid spacing so that the representative colors are
* equidistant in linear space. At this writing, gamma correction is not
* implemented by jdcolor, so nothing is done here.
*/
#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 as described above. Since colormap indexes must fit into
* JSAMPLEs, the entries of this array will too.
/* Declarations for ordered dithering.
*
* We use a standard 4x4 ordered dither array. The basic concept of ordered
* dithering is described in many references, for instance Dale Schumacher's
* chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
* In place of Schumacher's comparisons against a "threshold" value, we add a
* "dither" value to the input pixel and then round the result to the nearest
* output value. The dither value is equivalent to (0.5 - threshold) times
* the distance between output values. For ordered dithering, we assume that
* the output colors are equally spaced; if not, results will probably be
* worse, since the dither may be too much or too little at a given point.
*
* The normal calculation would be to form pixel value + dither, range-limit
* this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
* We can skip the separate range-limiting step by extending the colorindex
* table in both directions.
*/
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.
*/
#define ODITHER_SIZE 4 /* dimension of dither matrix */
#define ODITHER_CELLS (4*4) /* number of cells in dither matrix */
#define ODITHER_MASK 3 /* mask for wrapping around dither counters */
typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
/* Declarations for Floyd-Steinberg dithering.
*
* Errors are accumulated into the arrays evenrowerrs[] and oddrowerrs[].
* 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.
*
* In each of the xxxrowerrs[] arrays, indexing is [component#][position].
* 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.
* In evenrowerrs[], the entries for a component are stored left-to-right, but
* in oddrowerrs[] they are stored right-to-left. This means we always
* process the current row's error entries in increasing order and the next
* row's error entries in decreasing order, regardless of whether we are
* working L-to-R or R-to-L in the pixel data!
*
* 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_large.
*/
#ifdef EIGHT_BIT_SAMPLES
#if BITS_IN_JSAMPLE == 8
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[MAX_COMPONENTS]; /* errors for even rows */
static FSERRPTR oddrowerrs[MAX_COMPONENTS]; /* errors for odd rows */
static boolean on_odd_row; /* flag to remember which row we are on */
/* Private subobject */
#define MAX_Q_COMPS 4 /* max components I can handle */
typedef struct {
struct jpeg_color_quantizer pub; /* public fields */
JSAMPARRAY colorindex; /* Precomputed mapping for speed */
/* colorindex[i][j] = index of color closest to pixel value j in component i,
* premultiplied as described above. Since colormap indexes must fit into
* JSAMPLEs, the entries of this array will too.
*/
/* Variables for ordered dithering */
int row_index; /* cur row's vertical index in dither matrix */
ODITHER_MATRIX *odither; /* one dither array per component */
/* Variables for Floyd-Steinberg dithering */
FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
boolean on_odd_row; /* flag to remember which row we are on */
} my_cquantizer;
typedef my_cquantizer * my_cquantize_ptr;
/*
* Policy-making subroutines for color_quant_init: these routines determine
* Policy-making subroutines for create_colormap: these routines determine
* the colormap to be used. The rest of the module only assumes that the
* colormap is orthogonal.
*
@@ -131,16 +151,16 @@ static boolean on_odd_row; /* flag to remember which row we are on */
LOCAL int
select_ncolors (decompress_info_ptr cinfo, int Ncolors[])
select_ncolors (j_decompress_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 nc = cinfo->out_color_components; /* number of color components */
int max_colors = cinfo->desired_number_of_colors;
int total_colors, iroot, i;
int total_colors, iroot, i, j;
long temp;
boolean changed;
static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
/* We can allocate at least the nc'th root of max_colors per component. */
/* Compute floor(nc'th root of max_colors). */
@@ -155,82 +175,27 @@ select_ncolors (decompress_info_ptr cinfo, int Ncolors[])
/* Must have at least 2 color values per component */
if (iroot < 2)
ERREXIT1(cinfo->emethods, "Cannot quantize to fewer than %d colors",
(int) temp);
ERREXIT1(cinfo, JERR_QUANT_FEW_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;
}
/* 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.
* In RGB colorspace, try to increment G first, then R, then B.
*/
for (i = 0; i < nc; i++) {
j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
/* calculate new total_colors if Ncolors[j] is incremented */
temp = total_colors / Ncolors[j];
temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
if (temp > (long) max_colors)
break; /* won't fit, done */
Ncolors[j]++; /* OK, apply the increment */
total_colors = (int) temp;
}
return total_colors;
@@ -238,7 +203,7 @@ select_ncolors (decompress_info_ptr cinfo, int Ncolors[])
LOCAL int
output_value (decompress_info_ptr cinfo, int ci, int j, int maxj)
output_value (j_decompress_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 */
{
@@ -247,65 +212,69 @@ output_value (decompress_info_ptr cinfo, int ci, int j, int maxj)
* (Forcing the upper and lower values to the limits ensures that
* dithering can't produce a color outside the selected gamut.)
*/
return (j * MAXJSAMPLE + maxj/2) / maxj;
return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
}
LOCAL int
largest_input_value (decompress_info_ptr cinfo, int ci, int j, int maxj)
largest_input_value (j_decompress_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 ((2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj);
return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
}
/*
* Initialize for one-pass color quantization.
* Create the colormap and color index table.
* Also creates the ordered-dither tables, if required.
*/
METHODDEF void
color_quant_init (decompress_info_ptr cinfo)
LOCAL void
create_colormap (j_decompress_ptr cinfo)
{
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
JSAMPARRAY colormap; /* Created colormap */
JSAMPROW indexptr;
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;
/* 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);
/* 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);
int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
ODITHER_MATRIX *odither;
int i,j,k, nci, blksize, blkdist, ptr, val, pad;
/* Select number of colors for each component */
total_colors = select_ncolors(cinfo, Ncolors);
/* Report selected color counts */
if (cinfo->color_out_comps == 3)
TRACEMS4(cinfo->emethods, 1, "Quantizing to %d = %d*%d*%d colors",
if (cinfo->out_color_components == 3)
TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
total_colors, Ncolors[0], Ncolors[1], Ncolors[2]);
else
TRACEMS1(cinfo->emethods, 1, "Quantizing to %d colors", total_colors);
TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
/* For ordered dither, we pad the color index tables by MAXJSAMPLE in
* each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
* This is not necessary in the other dithering modes.
*/
pad = (cinfo->dither_mode == JDITHER_ORDERED) ? MAXJSAMPLE*2 : 0;
/* Allocate and fill in the colormap and color index. */
/* The colors are ordered in the map in standard row-major order, */
/* i.e. rightmost (highest-indexed) color changes most rapidly. */
colormap = (*cinfo->emethods->alloc_small_sarray)
((long) total_colors, (long) cinfo->color_out_comps);
colorindex = (*cinfo->emethods->alloc_small_sarray)
((long) (MAXJSAMPLE+1), (long) cinfo->color_out_comps);
colormap = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
cquantize->colorindex = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (MAXJSAMPLE+1 + pad),
(JDIMENSION) cinfo->out_color_components);
/* blksize is number of adjacent repeated entries for a component */
/* blkdist is distance between groups of identical entries for a component */
blkdist = total_colors;
for (i = 0; i < cinfo->color_out_comps; i++) {
for (i = 0; i < cinfo->out_color_components; i++) {
/* fill in colormap entries for i'th color component */
nci = Ncolors[i]; /* # of distinct values for this color */
blksize = blkdist / nci;
@@ -321,95 +290,100 @@ color_quant_init (decompress_info_ptr cinfo)
}
blkdist = blksize; /* blksize of this color is blkdist of next */
/* adjust colorindex pointers to provide padding at negative indexes. */
if (pad)
cquantize->colorindex[i] += MAXJSAMPLE;
/* 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 */
indexptr = cquantize->colorindex[i];
val = 0;
k = largest_input_value(cinfo, i, 0, nci-1);
for (j = 0; j <= MAXJSAMPLE; j++) {
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);
indexptr[j] = (JSAMPLE) (val * blksize);
}
/* Pad at both ends if necessary */
if (pad)
for (j = 1; j <= MAXJSAMPLE; j++) {
indexptr[-j] = indexptr[0];
indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
}
}
/* Pass the colormap to the output module. */
/* NB: the output module may continue to use the colormap until shutdown. */
/* Make the colormap available to the application. */
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 = (size_t) ((cinfo->image_width + 2L) * SIZEOF(FSERROR));
for (i = 0; i < cinfo->color_out_comps; i++) {
evenrowerrs[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
oddrowerrs[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
/* we only need to zero the forward contribution for current row. */
jzero_far((void FAR *) evenrowerrs[i], arraysize);
if (cinfo->dither_mode == JDITHER_ORDERED) {
/* Allocate and fill in the ordered-dither tables. */
odither = (ODITHER_MATRIX *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->out_color_components * SIZEOF(ODITHER_MATRIX));
cquantize->odither = odither;
for (i = 0; i < cinfo->out_color_components; i++) {
nci = Ncolors[i]; /* # of distinct values for this color */
/* The inter-value distance for this color is MAXJSAMPLE/(nci-1).
* Hence the dither value for the matrix cell with fill order j
* (j=1..N) should be (N+1-2*j)/(2*(N+1)) * MAXJSAMPLE/(nci-1).
*/
val = 2 * (ODITHER_CELLS + 1) * (nci - 1); /* denominator */
/* Macro is coded to ensure round towards zero despite C's
* lack of consistency in integer division...
*/
#define ODITHER_DIV(num,den) ((num)<0 ? -((-(num))/(den)) : (num)/(den))
#define ODITHER_VAL(j) ODITHER_DIV((ODITHER_CELLS+1-2*j)*MAXJSAMPLE, val)
/* Traditional fill order for 4x4 dither; see Schumacher's figure 4. */
odither[0][0][0] = ODITHER_VAL(1);
odither[0][0][1] = ODITHER_VAL(9);
odither[0][0][2] = ODITHER_VAL(3);
odither[0][0][3] = ODITHER_VAL(11);
odither[0][1][0] = ODITHER_VAL(13);
odither[0][1][1] = ODITHER_VAL(5);
odither[0][1][2] = ODITHER_VAL(15);
odither[0][1][3] = ODITHER_VAL(7);
odither[0][2][0] = ODITHER_VAL(4);
odither[0][2][1] = ODITHER_VAL(12);
odither[0][2][2] = ODITHER_VAL(2);
odither[0][2][3] = ODITHER_VAL(10);
odither[0][3][0] = ODITHER_VAL(16);
odither[0][3][1] = ODITHER_VAL(8);
odither[0][3][2] = ODITHER_VAL(14);
odither[0][3][3] = ODITHER_VAL(6);
odither++; /* advance to next matrix */
}
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);
}
/*
* Map some rows of pixels to the output colormapped representation.
*/
METHODDEF void
color_quantize (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE input_data, JSAMPARRAY output_data)
color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
/* General case, no dithering */
{
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
JSAMPARRAY colorindex = cquantize->colorindex;
register int pixcode, ci;
register JSAMPROW ptrout;
register long col;
register JSAMPROW ptrin, ptrout;
int row;
long width = cinfo->image_width;
register int nc = cinfo->color_out_comps;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
register int nc = cinfo->out_color_components;
for (row = 0; row < num_rows; row++) {
do_color_conversion(cinfo, input_data, row);
ptrout = output_data[row];
for (col = 0; col < width; col++) {
ptrin = input_buf[row];
ptrout = output_buf[row];
for (col = width; col > 0; col--) {
pixcode = 0;
for (ci = 0; ci < nc; ci++) {
pixcode += GETJSAMPLE(colorindex[ci]
[GETJSAMPLE(input_buffer[ci][col])]);
pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
}
*ptrout++ = (JSAMPLE) pixcode;
}
@@ -418,26 +392,27 @@ color_quantize (decompress_info_ptr cinfo, int num_rows,
METHODDEF void
color_quantize3 (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE input_data, JSAMPARRAY output_data)
/* Fast path for color_out_comps==3, no dithering */
color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, no dithering */
{
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
register int pixcode;
register JSAMPROW ptr0, ptr1, ptr2, ptrout;
register long col;
register JSAMPROW ptrin, ptrout;
JSAMPROW colorindex0 = cquantize->colorindex[0];
JSAMPROW colorindex1 = cquantize->colorindex[1];
JSAMPROW colorindex2 = cquantize->colorindex[2];
int row;
long width = cinfo->image_width;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
for (row = 0; row < num_rows; row++) {
do_color_conversion(cinfo, input_data, row);
ptr0 = input_buffer[0];
ptr1 = input_buffer[1];
ptr2 = input_buffer[2];
ptrout = output_data[row];
ptrin = input_buf[row];
ptrout = output_buf[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(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
*ptrout++ = (JSAMPLE) pixcode;
}
}
@@ -445,146 +420,291 @@ color_quantize3 (decompress_info_ptr cinfo, int num_rows,
METHODDEF void
color_quantize_dither (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE input_data, JSAMPARRAY output_data)
quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
/* General case, with ordered dithering */
{
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
JSAMPROW colorindex_ci;
int * dither; /* points to active row of dither matrix */
int row_index, col_index; /* current indexes into dither matrix */
int nc = cinfo->out_color_components;
int ci;
int row;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
for (row = 0; row < num_rows; row++) {
/* Initialize output values to 0 so can process components separately */
jzero_far((void FAR *) output_buf[row],
(size_t) (width * SIZEOF(JSAMPLE)));
row_index = cquantize->row_index;
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buf[row] + ci;
output_ptr = output_buf[row];
colorindex_ci = cquantize->colorindex[ci];
dither = cquantize->odither[ci][row_index];
col_index = 0;
for (col = width; col > 0; col--) {
/* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
* select output value, accumulate into output code for this pixel.
* Range-limiting need not be done explicitly, as we have extended
* the colorindex table to produce the right answers for out-of-range
* inputs. The maximum dither is +- MAXJSAMPLE; this sets the
* required amount of padding.
*/
*output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
input_ptr += nc;
output_ptr++;
col_index = (col_index + 1) & ODITHER_MASK;
}
}
/* Advance row index for next row */
row_index = (row_index + 1) & ODITHER_MASK;
cquantize->row_index = row_index;
}
}
METHODDEF void
quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, with ordered dithering */
{
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
register int pixcode;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
JSAMPROW colorindex0 = cquantize->colorindex[0];
JSAMPROW colorindex1 = cquantize->colorindex[1];
JSAMPROW colorindex2 = cquantize->colorindex[2];
int * dither0; /* points to active row of dither matrix */
int * dither1;
int * dither2;
int row_index, col_index; /* current indexes into dither matrix */
int row;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
for (row = 0; row < num_rows; row++) {
row_index = cquantize->row_index;
input_ptr = input_buf[row];
output_ptr = output_buf[row];
dither0 = cquantize->odither[0][row_index];
dither1 = cquantize->odither[1][row_index];
dither2 = cquantize->odither[2][row_index];
col_index = 0;
for (col = width; col > 0; col--) {
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
dither0[col_index]]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
dither1[col_index]]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
dither2[col_index]]);
*output_ptr++ = (JSAMPLE) pixcode;
col_index = (col_index + 1) & ODITHER_MASK;
}
row_index = (row_index + 1) & ODITHER_MASK;
cquantize->row_index = row_index;
}
}
METHODDEF void
quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows)
/* General case, with Floyd-Steinberg dithering */
{
register FSERROR val;
FSERROR two_val;
register FSERRPTR thisrowerr, nextrowerr;
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
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;
register int pixcode;
int pixcode;
int nc = cinfo->out_color_components;
int dir; /* 1 for left-to-right, -1 for right-to-left */
int dirnc; /* dir * nc */
int ci;
int nc = cinfo->color_out_comps;
int row;
long col_counter;
long width = cinfo->image_width;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
JSAMPLE *range_limit = cinfo->sample_range_limit;
SHIFT_TEMPS
for (row = 0; row < num_rows; row++) {
do_color_conversion(cinfo, input_data, row);
/* Initialize output values to 0 so can process components separately */
jzero_far((void FAR *) output_data[row],
jzero_far((void FAR *) output_buf[row],
(size_t) (width * SIZEOF(JSAMPLE)));
for (ci = 0; ci < nc; ci++) {
if (on_odd_row) {
input_ptr = input_buf[row] + ci;
output_ptr = output_buf[row];
if (cquantize->on_odd_row) {
/* work right to left in this row */
input_ptr += (width-1) * nc; /* so point to rightmost pixel */
output_ptr += width-1;
dir = -1;
input_ptr = input_buffer[ci] + (width-1);
output_ptr = output_data[row] + (width-1);
thisrowerr = oddrowerrs[ci] + 1;
nextrowerr = evenrowerrs[ci] + width;
dirnc = -nc;
errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
} else {
/* work left to right in this row */
dir = 1;
input_ptr = input_buffer[ci];
output_ptr = output_data[row];
thisrowerr = evenrowerrs[ci] + 1;
nextrowerr = oddrowerrs[ci] + width;
dirnc = nc;
errorptr = cquantize->fserrors[ci]; /* => entry before first column */
}
colorindex_ci = colorindex[ci];
colormap_ci = colormap[ci];
*nextrowerr = 0; /* need only initialize this one entry */
for (col_counter = width; col_counter > 0; col_counter--) {
/* Compute pixel value + accumulated error for this component */
val = (((FSERROR) GETJSAMPLE(*input_ptr)) << 4) + *thisrowerr;
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;
}
colorindex_ci = cquantize->colorindex[ci];
colormap_ci = cinfo->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 = width; col > 0; col--) {
/* 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(*output_ptr);
pixcode += GETJSAMPLE(colorindex_ci[val]);
*output_ptr = (JSAMPLE) pixcode;
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 yet have the final */
/* value of pixcode, because the colormap is orthogonal. */
val -= (FSERROR) GETJSAMPLE(colormap_ci[pixcode]);
/* Propagate error to (same component of) adjacent pixels */
/* Remember that nextrowerr entries are in reverse order! */
two_val = val * 2;
nextrowerr[-1] = val; /* not +=, since not initialized yet */
val += two_val; /* form error * 3 */
nextrowerr[ 1] += val;
val += two_val; /* form error * 5 */
nextrowerr[ 0] += val;
val += two_val; /* form error * 7 */
thisrowerr[ 1] += val;
input_ptr += dir; /* advance input ptr to next column */
/* 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 += dirnc; /* advance input ptr to next column */
output_ptr += dir; /* advance output ptr to next column */
thisrowerr++; /* cur-row error ptr advances to right */
nextrowerr--; /* next-row error ptr advances to left */
errorptr += dir; /* advance errorptr to current column */
}
/* 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);
cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
}
}
/*
* Finish up at the end of the file.
* Initialize for one-pass color quantization.
*/
METHODDEF void
color_quant_term (decompress_info_ptr cinfo)
start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
{
/* 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! */
/* no work in 1-pass case */
}
/*
* Prescan some rows of pixels.
* Not used in one-pass case.
* Finish up at the end of the pass.
*/
METHODDEF void
color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
JSAMPIMAGE image_data, JSAMPARRAY workspace)
finish_pass_1_quant (j_decompress_ptr cinfo)
{
ERREXIT(cinfo->emethods, "Should not get here!");
/* no work in 1-pass case */
}
/*
* Do two-pass quantization.
* Not used in one-pass case.
*/
METHODDEF void
color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method)
{
ERREXIT(cinfo->emethods, "Should not get here!");
}
/*
* The method selection routine for 1-pass color quantization.
* Module initialization routine for 1-pass color quantization.
*/
GLOBAL void
jsel1quantize (decompress_info_ptr cinfo)
jinit_1pass_quantizer (j_decompress_ptr cinfo)
{
if (! cinfo->two_pass_quantize) {
cinfo->methods->color_quant_init = color_quant_init;
if (cinfo->use_dithering) {
cinfo->methods->color_quantize = color_quantize_dither;
} else {
if (cinfo->color_out_comps == 3)
cinfo->methods->color_quantize = color_quantize3;
else
cinfo->methods->color_quantize = color_quantize;
my_cquantize_ptr cquantize;
size_t arraysize;
int i;
cquantize = (my_cquantize_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(my_cquantizer));
cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
cquantize->pub.start_pass = start_pass_1_quant;
cquantize->pub.finish_pass = finish_pass_1_quant;
/* Make sure my internal arrays won't overflow */
if (cinfo->out_color_components > MAX_Q_COMPS)
ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
/* Make sure colormap indexes can be represented by JSAMPLEs */
if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
/* Initialize for desired dithering mode. */
switch (cinfo->dither_mode) {
case JDITHER_NONE:
if (cinfo->out_color_components == 3)
cquantize->pub.color_quantize = color_quantize3;
else
cquantize->pub.color_quantize = color_quantize;
break;
case JDITHER_ORDERED:
if (cinfo->out_color_components == 3)
cquantize->pub.color_quantize = quantize3_ord_dither;
else
cquantize->pub.color_quantize = quantize_ord_dither;
cquantize->row_index = 0; /* initialize state for ordered dither */
break;
case JDITHER_FS:
cquantize->pub.color_quantize = quantize_fs_dither;
cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
/* Allocate Floyd-Steinberg workspace if necessary. */
/* We do this now since it is FAR storage and may affect the memory */
/* manager's space calculations. */
arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
for (i = 0; i < cinfo->out_color_components; i++) {
cquantize->fserrors[i] = (FSERRPTR) (*cinfo->mem->alloc_large)
((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
/* Initialize the propagated errors to zero. */
jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
}
cinfo->methods->color_quant_prescan = color_quant_prescan;
cinfo->methods->color_quant_doit = color_quant_doit;
cinfo->methods->color_quant_term = color_quant_term;
break;
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
/* Create the colormap. */
create_colormap(cinfo);
}
#endif /* QUANT_1PASS_SUPPORTED */

1076
jquant2.c

File diff suppressed because it is too large Load Diff

616
jrdgif.c
View File

@@ -1,616 +0,0 @@
/*
* jrdgif.c
*
* 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 routines to read input images in GIF format.
*
* These routines may need modification for non-Unix environments or
* specialized applications. As they stand, they assume input from
* an ordinary stdio stream. They further assume that reading begins
* at the start of the file; input_init may need work if the
* user interface has already read some data (e.g., to determine that
* the file is indeed GIF format).
*
* These routines are invoked via the methods get_input_row
* and input_init/term.
*/
/*
* This code is loosely based on giftoppm from the PBMPLUS distribution
* of Feb. 1991. That file contains the following copyright notice:
* +-------------------------------------------------------------------+
* | Copyright 1990, David Koblas. |
* | Permission to use, copy, modify, and distribute this software |
* | and its documentation for any purpose and without fee is hereby |
* | granted, provided that the above copyright notice appear in all |
* | copies and that both that copyright notice and this permission |
* | notice appear in supporting documentation. This software is |
* | provided "as is" without express or implied warranty. |
* +-------------------------------------------------------------------+
*
* We are also required to state that
* "The Graphics Interchange Format(c) is the Copyright property of
* CompuServe Incorporated. GIF(sm) is a Service Mark property of
* CompuServe Incorporated."
*/
#include "jinclude.h"
#ifdef GIF_SUPPORTED
#define MAXCOLORMAPSIZE 256 /* max # of colors in a GIF colormap */
#define NUMCOLORS 3 /* # of colors */
#define CM_RED 0 /* color component numbers */
#define CM_GREEN 1
#define CM_BLUE 2
static JSAMPARRAY colormap; /* the colormap to use */
/* colormap[i][j] = value of i'th color component for pixel value j */
#define MAX_LZW_BITS 12 /* maximum LZW code size */
#define LZW_TABLE_SIZE (1<<MAX_LZW_BITS) /* # of possible LZW symbols */
/* Macros for extracting header data --- note we assume chars may be signed */
#define LM_to_uint(a,b) ((((b)&0xFF) << 8) | ((a)&0xFF))
#define BitSet(byte, bit) ((byte) & (bit))
#define INTERLACE 0x40 /* mask for bit signifying interlaced image */
#define COLORMAPFLAG 0x80 /* mask for bit signifying colormap presence */
#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
/* Static vars for GetCode and LZWReadByte */
static char code_buf[256+4]; /* current input data block */
static int last_byte; /* # of bytes in code_buf */
static int last_bit; /* # of bits in code_buf */
static int cur_bit; /* next bit index to read */
static boolean out_of_blocks; /* TRUE if hit terminator data block */
static int input_code_size; /* codesize given in GIF file */
static int clear_code,end_code; /* values for Clear and End codes */
static int code_size; /* current actual code size */
static int limit_code; /* 2^code_size */
static int max_code; /* first unused code value */
static boolean first_time; /* flags first call to LZWReadByte */
/* LZW decompression tables:
* symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1)
* symbol_tail[K] = suffix byte of any LZW symbol K (0..LZW_TABLE_SIZE-1)
* Note that entries 0..end_code of the above tables are not used,
* since those symbols represent raw bytes or special codes.
*
* The stack represents the not-yet-used expansion of the last LZW symbol.
* In the worst case, a symbol could expand to as many bytes as there are
* LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack.
* (This is conservative since that number includes the raw-byte symbols.)
*
* The tables are allocated from FAR heap space since they would use up
* rather a lot of the near data space in a PC.
*/
static UINT16 FAR *symbol_head; /* => table of prefix symbols */
static UINT8 FAR *symbol_tail; /* => table of suffix bytes */
static UINT8 FAR *symbol_stack; /* stack for symbol expansions */
static UINT8 FAR *sp; /* stack pointer */
/* Static state for interlaced image processing */
static boolean is_interlaced; /* TRUE if have interlaced image */
static big_sarray_ptr interlaced_image; /* full image in interlaced order */
static long cur_row_number; /* need to know actual row number */
static long pass2_offset; /* # of pixel rows in pass 1 */
static long pass3_offset; /* # of pixel rows in passes 1&2 */
static long pass4_offset; /* # of pixel rows in passes 1,2,3 */
/* Forward declarations */
METHODDEF void load_interlaced_image PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
METHODDEF void get_interlaced_row PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
LOCAL int
ReadByte (compress_info_ptr cinfo)
/* Read next byte from GIF file */
{
register FILE * infile = cinfo->input_file;
int c;
if ((c = getc(infile)) == EOF)
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
return c;
}
LOCAL int
GetDataBlock (compress_info_ptr cinfo, char *buf)
/* Read a GIF data block, which has a leading count byte */
/* A zero-length block marks the end of a data block sequence */
{
int count;
count = ReadByte(cinfo);
if (count > 0) {
if (! ReadOK(cinfo->input_file, buf, count))
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
}
return count;
}
LOCAL void
SkipDataBlocks (compress_info_ptr cinfo)
/* Skip a series of data blocks, until a block terminator is found */
{
char buf[256];
while (GetDataBlock(cinfo, buf) > 0)
/* skip */;
}
LOCAL void
ReInitLZW (void)
/* (Re)initialize LZW state; shared code for startup and Clear processing */
{
code_size = input_code_size+1;
limit_code = clear_code << 1; /* 2^code_size */
max_code = clear_code + 2; /* first unused code value */
sp = symbol_stack; /* init stack to empty */
}
LOCAL void
InitLZWCode (void)
/* Initialize for a series of LZWReadByte (and hence GetCode) calls */
{
/* GetCode initialization */
last_byte = 2; /* make safe to "recopy last two bytes" */
last_bit = 0; /* nothing in the buffer */
cur_bit = 0; /* force buffer load on first call */
out_of_blocks = FALSE;
/* LZWReadByte initialization */
clear_code = 1 << input_code_size; /* compute special code values */
end_code = clear_code + 1; /* note that these do not change */
first_time = TRUE;
ReInitLZW();
}
LOCAL int
GetCode (compress_info_ptr cinfo)
/* Fetch the next code_size bits from the GIF data */
/* We assume code_size is less than 16 */
{
register INT32 accum;
int offs, ret, count;
if ( (cur_bit+code_size) > last_bit) {
/* Time to reload the buffer */
if (out_of_blocks) {
TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
return end_code; /* fake something useful */
}
/* preserve last two bytes of what we have -- assume code_size <= 16 */
code_buf[0] = code_buf[last_byte-2];
code_buf[1] = code_buf[last_byte-1];
/* Load more bytes; set flag if we reach the terminator block */
if ((count = GetDataBlock(cinfo, &code_buf[2])) == 0) {
out_of_blocks = TRUE;
TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
return end_code; /* fake something useful */
}
/* Reset counters */
cur_bit = (cur_bit - last_bit) + 16;
last_byte = 2 + count;
last_bit = last_byte * 8;
}
/* Form up next 24 bits in accum */
offs = cur_bit >> 3; /* byte containing cur_bit */
#ifdef CHAR_IS_UNSIGNED
accum = code_buf[offs+2];
accum <<= 8;
accum |= code_buf[offs+1];
accum <<= 8;
accum |= code_buf[offs];
#else
accum = code_buf[offs+2] & 0xFF;
accum <<= 8;
accum |= code_buf[offs+1] & 0xFF;
accum <<= 8;
accum |= code_buf[offs] & 0xFF;
#endif
/* Right-align cur_bit in accum, then mask off desired number of bits */
accum >>= (cur_bit & 7);
ret = ((int) accum) & ((1 << code_size) - 1);
cur_bit += code_size;
return ret;
}
LOCAL int
LZWReadByte (compress_info_ptr cinfo)
/* Read an LZW-compressed byte */
{
static int oldcode; /* previous LZW symbol */
static int firstcode; /* first byte of oldcode's expansion */
register int code; /* current working code */
int incode; /* saves actual input code */
/* First time, just eat the expected Clear code(s) and return next code, */
/* which is assumed to be a raw byte. */
if (first_time) {
first_time = FALSE;
do {
code = GetCode(cinfo);
} while (code == clear_code);
firstcode = oldcode = code; /* make firstcode, oldcode valid! */
return code;
}
/* If any codes are stacked from a previously read symbol, return them */
if (sp > symbol_stack)
return (int) *(--sp);
code = GetCode(cinfo);
if (code == clear_code) {
/* Reinit static state, swallow any extra Clear codes, and return */
ReInitLZW();
do {
code = GetCode(cinfo);
} while (code == clear_code);
firstcode = oldcode = code; /* gotta reinit these too */
return code;
}
if (code == end_code) {
/* Skip the rest of the image, unless GetCode already read terminator */
if (! out_of_blocks)
SkipDataBlocks(cinfo);
return -1;
}
/* Normal raw byte or LZW symbol */
incode = code; /* save for a moment */
if (code >= max_code) { /* special case for not-yet-defined symbol */
*sp++ = (UINT8) firstcode; /* it will be defined as oldcode/firstcode */
code = oldcode;
}
/* If it's a symbol, expand it into the stack */
while (code >= clear_code) {
*sp++ = symbol_tail[code]; /* tail of symbol: a simple byte value */
code = symbol_head[code]; /* head of symbol: another LZW symbol */
}
/* At this point code just represents a raw byte */
firstcode = code; /* save for possible future use */
/* If there's room in table, */
if ((code = max_code) < LZW_TABLE_SIZE) {
/* Define a new symbol = prev sym + head of this sym's expansion */
symbol_head[code] = oldcode;
symbol_tail[code] = (UINT8) firstcode;
max_code++;
/* Is it time to increase code_size? */
if ((max_code >= limit_code) && (code_size < MAX_LZW_BITS)) {
code_size++;
limit_code <<= 1; /* keep equal to 2^code_size */
}
}
oldcode = incode; /* save last input symbol for future use */
return firstcode; /* return first byte of symbol's expansion */
}
LOCAL void
ReadColorMap (compress_info_ptr cinfo, int cmaplen, JSAMPARRAY cmap)
/* Read a GIF colormap */
{
int i;
for (i = 0; i < cmaplen; i++) {
cmap[CM_RED][i] = (JSAMPLE) ReadByte(cinfo);
cmap[CM_GREEN][i] = (JSAMPLE) ReadByte(cinfo);
cmap[CM_BLUE][i] = (JSAMPLE) ReadByte(cinfo);
}
}
LOCAL void
DoExtension (compress_info_ptr cinfo)
/* Process an extension block */
/* Currently we ignore 'em all */
{
int extlabel;
/* Read extension label byte */
extlabel = ReadByte(cinfo);
TRACEMS1(cinfo->emethods, 1, "Ignoring GIF extension block of type 0x%02x",
extlabel);
/* Skip the data block(s) associated with the extension */
SkipDataBlocks(cinfo);
}
/*
* Read the file header; return image size and component count.
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
{
char hdrbuf[10]; /* workspace for reading control blocks */
UINT16 width, height; /* image dimensions */
int colormaplen, aspectRatio;
int c;
/* Allocate space to store the colormap */
colormap = (*cinfo->emethods->alloc_small_sarray)
((long) MAXCOLORMAPSIZE, (long) NUMCOLORS);
/* Read and verify GIF Header */
if (! ReadOK(cinfo->input_file, hdrbuf, 6))
ERREXIT(cinfo->emethods, "Not a GIF file");
if (strncmp(hdrbuf, "GIF", 3) != 0)
ERREXIT(cinfo->emethods, "Not a GIF file");
/* Check for expected version numbers.
* If unknown version, give warning and try to process anyway;
* this is per recommendation in GIF89a standard.
*/
if ((strncmp(hdrbuf+3, "87a", 3) != 0) &&
(strncmp(hdrbuf+3, "89a", 3) != 0))
TRACEMS3(cinfo->emethods, 1,
"Warning: unexpected GIF version number '%c%c%c'",
hdrbuf[3], hdrbuf[4], hdrbuf[5]);
/* Read and decipher Logical Screen Descriptor */
if (! ReadOK(cinfo->input_file, hdrbuf, 7))
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
width = LM_to_uint(hdrbuf[0],hdrbuf[1]);
height = LM_to_uint(hdrbuf[2],hdrbuf[3]);
colormaplen = 2 << (hdrbuf[4] & 0x07);
/* we ignore the color resolution, sort flag, and background color index */
aspectRatio = hdrbuf[6] & 0xFF;
if (aspectRatio != 0 && aspectRatio != 49)
TRACEMS(cinfo->emethods, 1, "Warning: nonsquare pixels in input");
/* Read global colormap if header indicates it is present */
if (BitSet(hdrbuf[4], COLORMAPFLAG))
ReadColorMap(cinfo, colormaplen, colormap);
/* Scan until we reach start of desired image.
* We don't currently support skipping images, but could add it easily.
*/
for (;;) {
c = ReadByte(cinfo);
if (c == ';') /* GIF terminator?? */
ERREXIT(cinfo->emethods, "Too few images in GIF file");
if (c == '!') { /* Extension */
DoExtension(cinfo);
continue;
}
if (c != ',') { /* Not an image separator? */
TRACEMS1(cinfo->emethods, 1, "Bogus input char 0x%02x, ignoring", c);
continue;
}
/* Read and decipher Local Image Descriptor */
if (! ReadOK(cinfo->input_file, hdrbuf, 9))
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
/* we ignore top/left position info, also sort flag */
width = LM_to_uint(hdrbuf[4],hdrbuf[5]);
height = LM_to_uint(hdrbuf[6],hdrbuf[7]);
is_interlaced = BitSet(hdrbuf[8], INTERLACE);
colormaplen = 2 << (hdrbuf[8] & 0x07);
/* Read local colormap if header indicates it is present */
/* Note: if we wanted to support skipping images, */
/* we'd need to skip rather than read colormap for ignored images */
if (BitSet(hdrbuf[8], COLORMAPFLAG))
ReadColorMap(cinfo, colormaplen, colormap);
input_code_size = ReadByte(cinfo); /* get minimum-code-size byte */
if (input_code_size < 2 || input_code_size >= MAX_LZW_BITS)
ERREXIT1(cinfo->emethods, "Bogus codesize %d", input_code_size);
/* Reached desired image, so break out of loop */
/* If we wanted to skip this image, */
/* we'd call SkipDataBlocks and then continue the loop */
break;
}
/* Prepare to read selected image: first initialize LZW decompressor */
symbol_head = (UINT16 FAR *) (*cinfo->emethods->alloc_medium)
(LZW_TABLE_SIZE * SIZEOF(UINT16));
symbol_tail = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
(LZW_TABLE_SIZE * SIZEOF(UINT8));
symbol_stack = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
(LZW_TABLE_SIZE * SIZEOF(UINT8));
InitLZWCode();
/*
* If image is interlaced, we read it into a full-size sample array,
* decompressing as we go; then get_input_row selects rows from the
* sample array in the proper order.
*/
if (is_interlaced) {
/* We request the big array now, but can't access it until the pipeline
* controller causes all the big arrays to be allocated. Hence, the
* actual work of reading the image is postponed until the first call
* of get_input_row.
*/
interlaced_image = (*cinfo->emethods->request_big_sarray)
((long) width, (long) height, 1L);
cinfo->methods->get_input_row = load_interlaced_image;
cinfo->total_passes++; /* count file reading as separate pass */
}
/* Return info about the image. */
cinfo->input_components = NUMCOLORS;
cinfo->in_color_space = CS_RGB;
cinfo->image_width = width;
cinfo->image_height = height;
cinfo->data_precision = 8; /* always, even if 12-bit JSAMPLEs */
}
/*
* Read one row of pixels.
* This version is used for noninterlaced GIF images:
* we read directly from the GIF file.
*/
METHODDEF void
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
register int c;
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
if ((c = LZWReadByte(cinfo)) < 0)
ERREXIT(cinfo->emethods, "Premature end of GIF image");
*ptr0++ = colormap[CM_RED][c];
*ptr1++ = colormap[CM_GREEN][c];
*ptr2++ = colormap[CM_BLUE][c];
}
}
/*
* Read one row of pixels.
* This version is used for the first call on get_input_row when
* reading an interlaced GIF file: we read the whole image into memory.
*/
METHODDEF void
load_interlaced_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
JSAMPARRAY image_ptr;
register JSAMPROW sptr;
register long col;
register int c;
long row;
/* Read the interlaced image into the big array we've created. */
for (row = 0; row < cinfo->image_height; row++) {
(*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;
}
}
cinfo->completed_passes++;
/* Replace method pointer so subsequent calls don't come here. */
cinfo->methods->get_input_row = get_interlaced_row;
/* Initialize for get_interlaced_row, and perform first call on it. */
cur_row_number = 0;
pass2_offset = (cinfo->image_height + 7L) / 8L;
pass3_offset = pass2_offset + (cinfo->image_height + 3L) / 8L;
pass4_offset = pass3_offset + (cinfo->image_height + 1L) / 4L;
get_interlaced_row(cinfo, pixel_row);
}
/*
* Read one row of pixels.
* This version is used for interlaced GIF images:
* we read from the big in-memory image.
*/
METHODDEF void
get_interlaced_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
JSAMPARRAY image_ptr;
register JSAMPROW sptr, ptr0, ptr1, ptr2;
register long col;
register int c;
long irow;
/* Figure out which row of interlaced image is needed, and access it. */
switch ((int) (cur_row_number & 7L)) {
case 0: /* first-pass row */
irow = cur_row_number >> 3;
break;
case 4: /* second-pass row */
irow = (cur_row_number >> 3) + pass2_offset;
break;
case 2: /* third-pass row */
case 6:
irow = (cur_row_number >> 2) + pass3_offset;
break;
default: /* fourth-pass row */
irow = (cur_row_number >> 1) + pass4_offset;
break;
}
image_ptr = (*cinfo->emethods->access_big_sarray)
(interlaced_image, irow, FALSE);
/* Scan the row, expand colormap, and output */
sptr = image_ptr[0];
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
c = GETJSAMPLE(*sptr++);
*ptr0++ = colormap[CM_RED][c];
*ptr1++ = colormap[CM_GREEN][c];
*ptr2++ = colormap[CM_BLUE][c];
}
cur_row_number++; /* for next time */
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
input_term (compress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/*
* The method selection routine for GIF format input.
* Note that this must be called by the user interface before calling
* jpeg_compress. If multiple input formats are supported, the
* user interface is responsible for discovering the file format and
* calling the appropriate method selection routine.
*/
GLOBAL void
jselrgif (compress_info_ptr cinfo)
{
cinfo->methods->input_init = input_init;
cinfo->methods->get_input_row = get_input_row; /* assume uninterlaced */
cinfo->methods->input_term = input_term;
}
#endif /* GIF_SUPPORTED */

740
jrdjfif.c
View File

@@ -1,740 +0,0 @@
/*
* jrdjfif.c
*
* 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 routines to decode standard JPEG file headers/markers.
* 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; 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.
*/
#include "jinclude.h"
#ifdef JFIF_SUPPORTED
typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0,
M_SOF1 = 0xc1,
M_SOF2 = 0xc2,
M_SOF3 = 0xc3,
M_SOF5 = 0xc5,
M_SOF6 = 0xc6,
M_SOF7 = 0xc7,
M_JPG = 0xc8,
M_SOF9 = 0xc9,
M_SOF10 = 0xca,
M_SOF11 = 0xcb,
M_SOF13 = 0xcd,
M_SOF14 = 0xce,
M_SOF15 = 0xcf,
M_DHT = 0xc4,
M_DAC = 0xcc,
M_RST0 = 0xd0,
M_RST1 = 0xd1,
M_RST2 = 0xd2,
M_RST3 = 0xd3,
M_RST4 = 0xd4,
M_RST5 = 0xd5,
M_RST6 = 0xd6,
M_RST7 = 0xd7,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
M_DQT = 0xdb,
M_DNL = 0xdc,
M_DRI = 0xdd,
M_DHP = 0xde,
M_EXP = 0xdf,
M_APP0 = 0xe0,
M_APP15 = 0xef,
M_JPG0 = 0xf0,
M_JPG13 = 0xfd,
M_COM = 0xfe,
M_TEM = 0x01,
M_ERROR = 0x100
} JPEG_MARKER;
/*
* Reload the input buffer after it's been emptied, and return the next byte.
* This is exported for direct use by the entropy decoder.
* See the JGETC macro for calling conditions.
*
* For this header control module, read_jpeg_data is supplied by the
* user interface. However, header formats that require random access
* to the input file would need to supply their own code. This code is
* left here to indicate what is required.
*/
#if 0 /* not needed in this module */
METHODDEF int
read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
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");
return JGETC(cinfo);
}
#endif
/*
* Routines to parse JPEG markers & save away the useful info.
*/
LOCAL INT32
get_2bytes (decompress_info_ptr cinfo)
/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
{
INT32 a;
a = JGETC(cinfo);
return (a << 8) + JGETC(cinfo);
}
LOCAL void
skip_variable (decompress_info_ptr cinfo, int code)
/* Skip over an unknown or uninteresting variable-length marker */
{
INT32 length;
length = get_2bytes(cinfo);
TRACEMS2(cinfo->emethods, 1,
"Skipping marker 0x%02x, length %u", code, (int) length);
for (length -= 2; length > 0; length--)
(void) JGETC(cinfo);
}
LOCAL void
get_dht (decompress_info_ptr cinfo)
/* Process a DHT marker */
{
INT32 length;
UINT8 bits[17];
UINT8 huffval[256];
int i, index, count;
HUFF_TBL **htblptr;
length = get_2bytes(cinfo)-2;
while (length > 0) {
index = JGETC(cinfo);
TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
bits[0] = 0;
count = 0;
for (i = 1; i <= 16; i++) {
bits[i] = (UINT8) JGETC(cinfo);
count += bits[i];
}
TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
bits[1], bits[2], bits[3], bits[4],
bits[5], bits[6], bits[7], bits[8]);
TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
bits[9], bits[10], bits[11], bits[12],
bits[13], bits[14], bits[15], bits[16]);
if (count > 256)
ERREXIT(cinfo->emethods, "Bogus DHT counts");
for (i = 0; i < count; i++)
huffval[i] = (UINT8) JGETC(cinfo);
length -= 1 + 16 + count;
if (index & 0x10) { /* AC table definition */
index -= 0x10;
htblptr = &cinfo->ac_huff_tbl_ptrs[index];
} else { /* DC table definition */
htblptr = &cinfo->dc_huff_tbl_ptrs[index];
}
if (index < 0 || index >= NUM_HUFF_TBLS)
ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index);
if (*htblptr == NULL)
*htblptr = (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));
}
}
LOCAL void
get_dac (decompress_info_ptr cinfo)
/* Process a DAC marker */
{
INT32 length;
int index, val;
length = get_2bytes(cinfo)-2;
while (length > 0) {
index = JGETC(cinfo);
val = JGETC(cinfo);
TRACEMS2(cinfo->emethods, 1,
"Define Arithmetic Table 0x%02x: 0x%02x", index, val);
if (index < 0 || index >= (2*NUM_ARITH_TBLS))
ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index);
if (index >= NUM_ARITH_TBLS) { /* define AC table */
cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
} else { /* define DC table */
cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
}
length -= 2;
}
}
LOCAL void
get_dqt (decompress_info_ptr cinfo)
/* Process a DQT marker */
{
INT32 length;
int n, i, prec;
UINT16 tmp;
QUANT_TBL_PTR quant_ptr;
length = get_2bytes(cinfo) - 2;
while (length > 0) {
n = JGETC(cinfo);
prec = n >> 4;
n &= 0x0F;
TRACEMS2(cinfo->emethods, 1,
"Define Quantization Table %d precision %d", n, prec);
if (n >= NUM_QUANT_TBLS)
ERREXIT1(cinfo->emethods, "Bogus table number %d", n);
if (cinfo->quant_tbl_ptrs[n] == NULL)
cinfo->quant_tbl_ptrs[n] = (QUANT_TBL_PTR)
(*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
quant_ptr = cinfo->quant_tbl_ptrs[n];
for (i = 0; i < DCTSIZE2; i++) {
tmp = JGETC(cinfo);
if (prec)
tmp = (tmp<<8) + JGETC(cinfo);
quant_ptr[i] = tmp;
}
for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo->emethods, 2, " %4d %4d %4d %4d %4d %4d %4d %4d",
quant_ptr[i ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
}
length -= DCTSIZE2+1;
if (prec) length -= DCTSIZE2;
}
}
LOCAL void
get_dri (decompress_info_ptr cinfo)
/* Process a DRI marker */
{
if (get_2bytes(cinfo) != 4)
ERREXIT(cinfo->emethods, "Bogus length in DRI");
cinfo->restart_interval = (UINT16) get_2bytes(cinfo);
TRACEMS1(cinfo->emethods, 1,
"Define Restart Interval %d", cinfo->restart_interval);
}
LOCAL void
get_app0 (decompress_info_ptr cinfo)
/* Process an APP0 marker */
{
#define JFIF_LEN 14
INT32 length;
UINT8 b[JFIF_LEN];
int buffp;
length = get_2bytes(cinfo) - 2;
/* See if a JFIF APP0 marker is present */
if (length >= JFIF_LEN) {
for (buffp = 0; buffp < JFIF_LEN; buffp++)
b[buffp] = (UINT8) JGETC(cinfo);
length -= JFIF_LEN;
if (b[0]=='J' && b[1]=='F' && b[2]=='I' && b[3]=='F' && b[4]==0) {
/* Found JFIF APP0 marker: check version */
/* Major version must be 1 */
if (b[5] != 1)
ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
b[5], b[6]);
/* Minor version should be 0 or 1, but try to process anyway if newer */
if (b[6] != 0 && b[6] != 1)
TRACEMS2(cinfo->emethods, 0, "Warning: unknown JFIF revision number %d.%02d",
b[5], b[6]);
/* Save info */
cinfo->density_unit = b[7];
cinfo->X_density = (b[8] << 8) + b[9];
cinfo->Y_density = (b[10] << 8) + b[11];
/* Assume colorspace is YCbCr, unless UI has overridden me */
if (cinfo->jpeg_color_space == CS_UNKNOWN)
cinfo->jpeg_color_space = CS_YCbCr;
TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d %d",
cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
} else {
TRACEMS(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF)");
}
} else {
TRACEMS1(cinfo->emethods, 1,
"Short APP0 marker, length %d", (int) length);
}
while (length-- > 0) /* skip any remaining data */
(void) JGETC(cinfo);
}
LOCAL void
get_sof (decompress_info_ptr cinfo, int code)
/* Process a SOFn marker */
{
INT32 length;
short ci;
int c;
jpeg_component_info * compptr;
length = get_2bytes(cinfo);
cinfo->data_precision = JGETC(cinfo);
cinfo->image_height = get_2bytes(cinfo);
cinfo->image_width = get_2bytes(cinfo);
cinfo->num_components = JGETC(cinfo);
TRACEMS4(cinfo->emethods, 1,
"Start Of Frame 0x%02x: width=%u, height=%u, components=%d",
code, (int) cinfo->image_width, (int) cinfo->image_height,
cinfo->num_components);
/* We don't support files in which the image height is initially specified */
/* as 0 and is later redefined by DNL. As long as we have to check that, */
/* might as well have a general sanity check. */
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|| cinfo->num_components <= 0)
ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)");
#ifdef EIGHT_BIT_SAMPLES
if (cinfo->data_precision != 8)
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
#endif
#ifdef TWELVE_BIT_SAMPLES
if (cinfo->data_precision != 12) /* this needs more thought?? */
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
#endif
#ifdef SIXTEEN_BIT_SAMPLES
if (cinfo->data_precision != 16) /* this needs more thought?? */
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
#endif
if (length != (cinfo->num_components * 3 + 8))
ERREXIT(cinfo->emethods, "Bogus SOF length");
cinfo->comp_info = (jpeg_component_info *) (*cinfo->emethods->alloc_small)
(cinfo->num_components * SIZEOF(jpeg_component_info));
for (ci = 0; ci < cinfo->num_components; ci++) {
compptr = &cinfo->comp_info[ci];
compptr->component_index = ci;
compptr->component_id = JGETC(cinfo);
c = JGETC(cinfo);
compptr->h_samp_factor = (c >> 4) & 15;
compptr->v_samp_factor = (c ) & 15;
compptr->quant_tbl_no = JGETC(cinfo);
TRACEMS4(cinfo->emethods, 1, " Component %d: %dhx%dv q=%d",
compptr->component_id, compptr->h_samp_factor,
compptr->v_samp_factor, compptr->quant_tbl_no);
}
}
LOCAL void
get_sos (decompress_info_ptr cinfo)
/* Process a SOS marker */
{
INT32 length;
int i, ci, n, c, cc;
jpeg_component_info * compptr;
length = get_2bytes(cinfo);
n = JGETC(cinfo); /* Number of components */
cinfo->comps_in_scan = n;
length -= 3;
if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo->emethods, "Bogus SOS length");
TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n);
for (i = 0; i < n; i++) {
cc = JGETC(cinfo);
c = JGETC(cinfo);
length -= 2;
for (ci = 0; ci < cinfo->num_components; ci++)
if (cc == cinfo->comp_info[ci].component_id)
break;
if (ci >= cinfo->num_components)
ERREXIT(cinfo->emethods, "Invalid component number in SOS");
compptr = &cinfo->comp_info[ci];
cinfo->cur_comp_info[i] = compptr;
compptr->dc_tbl_no = (c >> 4) & 15;
compptr->ac_tbl_no = (c ) & 15;
TRACEMS3(cinfo->emethods, 1, " c%d: [dc=%d ac=%d]", cc,
compptr->dc_tbl_no, compptr->ac_tbl_no);
}
while (length > 0) {
(void) JGETC(cinfo);
length--;
}
}
LOCAL void
get_soi (decompress_info_ptr cinfo)
/* Process an SOI marker */
{
int i;
TRACEMS(cinfo->emethods, 1, "Start of Image");
/* Reset all parameters that are defined to be reset by SOI */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo->arith_dc_L[i] = 0;
cinfo->arith_dc_U[i] = 1;
cinfo->arith_ac_K[i] = 5;
}
cinfo->restart_interval = 0;
cinfo->density_unit = 0; /* set default JFIF APP0 values */
cinfo->X_density = 1;
cinfo->Y_density = 1;
cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */
}
LOCAL int
next_marker (decompress_info_ptr cinfo)
/* Find the next JPEG marker */
/* Note that the output might not be a valid marker code, */
/* but it will never be 0 or FF */
{
int c, nbytes;
nbytes = 0;
do {
do { /* skip any non-FF bytes */
nbytes++;
c = JGETC(cinfo);
} while (c != 0xFF);
do { /* skip any duplicate FFs */
nbytes++;
c = JGETC(cinfo);
} while (c == 0xFF);
} while (c == 0); /* repeat if it was a stuffed FF/00 */
if (nbytes != 2)
TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before marker 0x%02x",
nbytes-2, c);
return c;
}
LOCAL JPEG_MARKER
process_tables (decompress_info_ptr cinfo)
/* Scan and process JPEG markers that can appear in any order */
/* Return when an SOI, EOI, SOFn, or SOS is found */
{
int c;
while (TRUE) {
c = next_marker(cinfo);
switch (c) {
case M_SOF0:
case M_SOF1:
case M_SOF2:
case M_SOF3:
case M_SOF5:
case M_SOF6:
case M_SOF7:
case M_JPG:
case M_SOF9:
case M_SOF10:
case M_SOF11:
case M_SOF13:
case M_SOF14:
case M_SOF15:
case M_SOI:
case M_EOI:
case M_SOS:
return ((JPEG_MARKER) c);
case M_DHT:
get_dht(cinfo);
break;
case M_DAC:
get_dac(cinfo);
break;
case M_DQT:
get_dqt(cinfo);
break;
case M_DRI:
get_dri(cinfo);
break;
case M_APP0:
get_app0(cinfo);
break;
case M_RST0: /* these are all parameterless */
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
case M_TEM:
TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
break;
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
skip_variable(cinfo, c);
break;
}
}
}
/*
* Initialize and read the file header (everything through the SOF marker).
*/
METHODDEF void
read_file_header (decompress_info_ptr cinfo)
{
int c;
/* 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) != M_SOI)
ERREXIT(cinfo->emethods, "Not a JPEG file");
get_soi(cinfo); /* OK, process SOI */
/* Process markers until SOF */
c = process_tables(cinfo);
switch (c) {
case M_SOF0:
case M_SOF1:
get_sof(cinfo, c);
cinfo->arith_code = FALSE;
break;
case M_SOF9:
get_sof(cinfo, c);
cinfo->arith_code = TRUE;
break;
default:
ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c);
break;
}
/* Figure out what colorspace we have */
/* (too bad the JPEG committee didn't provide a real way to specify this) */
switch (cinfo->num_components) {
case 1:
cinfo->jpeg_color_space = CS_GRAYSCALE;
break;
case 3:
/* if we saw a JFIF marker, leave it set to YCbCr; */
/* also leave it alone if UI has provided a value */
if (cinfo->jpeg_color_space == CS_UNKNOWN) {
short cid0 = cinfo->comp_info[0].component_id;
short cid1 = cinfo->comp_info[1].component_id;
short cid2 = cinfo->comp_info[2].component_id;
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */
else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
else {
TRACEMS3(cinfo->emethods, 0,
"Unrecognized component IDs %d %d %d, assuming YCbCr",
cid0, cid1, cid2);
cinfo->jpeg_color_space = CS_YCbCr;
}
}
break;
case 4:
cinfo->jpeg_color_space = CS_CMYK;
break;
default:
cinfo->jpeg_color_space = CS_UNKNOWN;
break;
}
}
/*
* Read the start of a scan (everything through the SOS marker).
* Return TRUE if find SOS, FALSE if find EOI.
*/
METHODDEF boolean
read_scan_header (decompress_info_ptr cinfo)
{
int c;
/* Process markers until SOS or EOI */
c = process_tables(cinfo);
switch (c) {
case M_SOS:
get_sos(cinfo);
return TRUE;
case M_EOI:
TRACEMS(cinfo->emethods, 1, "End Of Image");
return FALSE;
default:
ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c);
break;
}
return FALSE; /* keeps lint happy */
}
/*
* Finish up after a compressed scan (series of read_jpeg_data calls);
* prepare for another read_scan_header call.
*/
METHODDEF void
read_scan_trailer (decompress_info_ptr cinfo)
{
/* no work needed */
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
read_file_trailer (decompress_info_ptr cinfo)
{
/* no work needed */
}
/*
* The method selection routine for standard JPEG header reading.
* Note that this must be called by the user interface before calling
* jpeg_decompress. When a non-JFIF file is to be decompressed (TIFF,
* perhaps), the user interface must discover the file type and call
* the appropriate method selection routine.
*/
GLOBAL void
jselrjfif (decompress_info_ptr cinfo)
{
cinfo->methods->read_file_header = read_file_header;
cinfo->methods->read_scan_header = read_scan_header;
/* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */
#if 0
cinfo->methods->read_jpeg_data = read_jpeg_data;
#endif
cinfo->methods->read_scan_trailer = read_scan_trailer;
cinfo->methods->read_file_trailer = read_file_trailer;
}
#endif /* JFIF_SUPPORTED */

324
jrdppm.c
View File

@@ -1,324 +0,0 @@
/*
* jrdppm.c
*
* 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 routines to read input images in PPM format.
* The PBMPLUS library is NOT required to compile this software,
* but it is highly useful as a set of PPM image manipulation programs.
*
* These routines may need modification for non-Unix environments or
* specialized applications. As they stand, they assume input from
* an ordinary stdio stream. They further assume that reading begins
* at the start of the file; input_init may need work if the
* user interface has already read some data (e.g., to determine that
* the file is indeed PPM format).
*
* These routines are invoked via the methods get_input_row
* and input_init/term.
*/
#include "jinclude.h"
#ifdef PPM_SUPPORTED
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.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
LOCAL int
pbm_getc (FILE * file)
/* Read next char, skipping over any comments */
/* 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 unsigned int
read_pbm_integer (compress_info_ptr cinfo)
/* Read an unsigned decimal integer from the PPM file */
/* Swallows one trailing character after the integer */
/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
/* This should not be a problem in practice. */
{
register int ch;
register unsigned int val;
/* Skip any leading whitespace */
do {
ch = pbm_getc(cinfo->input_file);
if (ch == EOF)
ERREXIT(cinfo->emethods, "Premature EOF in PPM file");
} while (ch == ' ' || ch == '\t' || ch == '\n');
if (ch < '0' || ch > '9')
ERREXIT(cinfo->emethods, "Bogus data in PPM file");
val = ch - '0';
while ((ch = pbm_getc(cinfo->input_file)) >= '0' && ch <= '9') {
val *= 10;
val += ch - '0';
}
return val;
}
/*
* Read one row of pixels.
*
* We provide several different versions depending on input file format.
* In all cases, input is scaled to the size of JSAMPLE; it's possible that
* when JSAMPLE is 12 bits, this would not really be desirable.
*
* Note that a really fast path is provided for reading raw files with
* maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs).
*/
METHODDEF void
get_text_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading text-format PGM files with any maxval */
{
register JSAMPROW ptr0;
register unsigned int val;
register long col;
ptr0 = pixel_row[0];
for (col = cinfo->image_width; col > 0; col--) {
val = read_pbm_integer(cinfo);
if (rescale != NULL)
val = rescale[val];
*ptr0++ = (JSAMPLE) val;
}
}
METHODDEF void
get_text_rgb_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading text-format PPM files with any maxval */
{
register JSAMPROW ptr0, ptr1, ptr2;
register unsigned int val;
register long col;
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
val = read_pbm_integer(cinfo);
if (rescale != NULL)
val = rescale[val];
*ptr0++ = (JSAMPLE) val;
val = read_pbm_integer(cinfo);
if (rescale != NULL)
val = rescale[val];
*ptr1++ = (JSAMPLE) val;
val = read_pbm_integer(cinfo);
if (rescale != NULL)
val = rescale[val];
*ptr2++ = (JSAMPLE) val;
}
}
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 FILE * infile = cinfo->input_file;
register JSAMPROW ptr0;
register long col;
ptr0 = pixel_row[0];
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = rescale[getc(infile)];
}
}
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 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 = cinfo->image_width; col > 0; col--) {
*ptr0++ = rescale[getc(infile)];
*ptr1++ = rescale[getc(infile)];
*ptr2++ = rescale[getc(infile)];
}
}
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 FILE * infile = cinfo->input_file;
register JSAMPROW ptr0;
register long col;
ptr0 = pixel_row[0];
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = (JSAMPLE) getc(infile);
}
}
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 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 = cinfo->image_width; col > 0; col--) {
*ptr0++ = (JSAMPLE) getc(infile);
*ptr1++ = (JSAMPLE) getc(infile);
*ptr2++ = (JSAMPLE) getc(infile);
}
}
/*
* Read the file header; return image size and component count.
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
{
int c;
unsigned int w, h, maxval;
if (getc(cinfo->input_file) != 'P')
ERREXIT(cinfo->emethods, "Not a PPM file");
c = getc(cinfo->input_file); /* save format discriminator for a sec */
w = read_pbm_integer(cinfo); /* while we fetch the header info */
h = read_pbm_integer(cinfo);
maxval = read_pbm_integer(cinfo);
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;
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;
break;
case '5': /* it's a raw-format PGM file */
if (maxval == MAXJSAMPLE)
cinfo->methods->get_input_row = get_raw_gray_row;
else
cinfo->methods->get_input_row = get_scaled_gray_row;
cinfo->input_components = 1;
cinfo->in_color_space = CS_GRAYSCALE;
break;
case '6': /* it's a raw-format PPM file */
if (maxval == MAXJSAMPLE)
cinfo->methods->get_input_row = get_raw_rgb_row;
else
cinfo->methods->get_input_row = get_scaled_rgb_row;
cinfo->input_components = 3;
cinfo->in_color_space = CS_RGB;
break;
default:
ERREXIT(cinfo->emethods, "Not a PPM file");
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)
rescale = NULL; /* no rescaling required */
else {
INT32 val, half_maxval;
/* On 16-bit-int machines we have to be careful of maxval = 65535 */
rescale = (JSAMPLE *) (*cinfo->emethods->alloc_small)
((size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
half_maxval = maxval / 2;
for (val = 0; val <= (INT32) maxval; val++) {
/* The multiplication here must be done in 32 bits to avoid overflow */
rescale[val] = (JSAMPLE) ((val * MAXJSAMPLE + half_maxval) / maxval);
}
}
cinfo->image_width = w;
cinfo->image_height = h;
cinfo->data_precision = BITS_IN_JSAMPLE;
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
input_term (compress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/*
* The method selection routine for PPM format input.
* Note that this must be called by the user interface before calling
* jpeg_compress. If multiple input formats are supported, the
* user interface is responsible for discovering the file format and
* calling the appropriate method selection routine.
*/
GLOBAL void
jselrppm (compress_info_ptr cinfo)
{
cinfo->methods->input_init = input_init;
/* cinfo->methods->get_input_row is set by input_init */
cinfo->methods->input_term = input_term;
}
#endif /* PPM_SUPPORTED */

366
jrdrle.c
View File

@@ -1,366 +0,0 @@
/*
* jrdrle.c
*
* 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 routines to read input images in Utah RLE format.
* The Utah Raster Toolkit library is required (version 3.0).
*
* These routines may need modification for non-Unix environments or
* specialized applications. As they stand, they assume input from
* an ordinary stdio stream. They further assume that reading begins
* at the start of the file; input_init may need work if the
* user interface has already read some data (e.g., to determine that
* the file is indeed RLE format).
*
* These routines are invoked via the methods get_input_row
* and input_init/term.
*
* Based on code contributed by Mike Lijewski.
*/
#include "jinclude.h"
#ifdef RLE_SUPPORTED
/* rle.h is provided by the Utah Raster Toolkit. */
#include <rle.h>
/*
* load_image assumes that JSAMPLE has the same representation as rle_pixel,
* to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
*/
#ifndef EIGHT_BIT_SAMPLES
Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
#endif
/*
* We support the following types of RLE files:
*
* GRAYSCALE - 8 bits, no colormap
* PSEUDOCOLOR - 8 bits, colormap
* TRUECOLOR - 24 bits, colormap
* DIRECTCOLOR - 24 bits, no colormap
*
* For now, we ignore any alpha channel in the image.
*/
typedef enum { GRAYSCALE, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
static rle_kind visual; /* actual type of input file */
/*
* Since RLE stores scanlines bottom-to-top, we have to invert the image
* to conform to JPEG's top-to-bottom order. To do this, we read the
* incoming image into a virtual array on the first get_input_row call,
* then fetch the required row from the virtual array on subsequent calls.
*/
static big_sarray_ptr image; /* single array for GRAYSCALE/PSEUDOCOLOR */
static big_sarray_ptr red_channel; /* three arrays for TRUECOLOR/DIRECTCOLOR */
static big_sarray_ptr green_channel;
static big_sarray_ptr blue_channel;
static long cur_row_number; /* last row# read from virtual array */
static rle_hdr header; /* Input file information */
static rle_map *colormap; /* RLE colormap, if any */
/*
* Read the file header; return image size and component count.
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
{
long width, height;
/* Use RLE library routine to get the header info */
header.rle_file = cinfo->input_file;
switch (rle_get_setup(&header)) {
case RLE_SUCCESS:
/* A-OK */
break;
case RLE_NOT_RLE:
ERREXIT(cinfo->emethods, "Not an RLE file");
break;
case RLE_NO_SPACE:
ERREXIT(cinfo->emethods, "Insufficient memory for RLE header");
break;
case RLE_EMPTY:
ERREXIT(cinfo->emethods, "Empty RLE file");
break;
case RLE_EOF:
ERREXIT(cinfo->emethods, "Premature EOF in RLE header");
break;
default:
ERREXIT(cinfo->emethods, "Bogus RLE error code");
break;
}
/* Figure out what we have, set private vars and return values accordingly */
width = header.xmax - header.xmin + 1;
height = header.ymax - header.ymin + 1;
header.xmin = 0; /* realign horizontally */
header.xmax = width-1;
cinfo->image_width = width;
cinfo->image_height = height;
cinfo->data_precision = 8; /* we can only handle 8 bit data */
if (header.ncolors == 1 && header.ncmap == 0) {
visual = GRAYSCALE;
TRACEMS(cinfo->emethods, 1, "Gray-scale RLE file");
} else if (header.ncolors == 1 && header.ncmap == 3) {
visual = PSEUDOCOLOR;
colormap = header.cmap;
TRACEMS1(cinfo->emethods, 1, "Colormapped RLE file with map of length %d",
1 << header.cmaplen);
} else if (header.ncolors == 3 && header.ncmap == 3) {
visual = TRUECOLOR;
colormap = header.cmap;
TRACEMS1(cinfo->emethods, 1, "Full-color RLE file with map of length %d",
1 << header.cmaplen);
} else if (header.ncolors == 3 && header.ncmap == 0) {
visual = DIRECTCOLOR;
TRACEMS(cinfo->emethods, 1, "Full-color RLE file");
} else
ERREXIT(cinfo->emethods, "Can't handle this RLE setup");
switch (visual) {
case GRAYSCALE:
/* request one big array to hold the grayscale image */
image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
cinfo->in_color_space = CS_GRAYSCALE;
cinfo->input_components = 1;
break;
case PSEUDOCOLOR:
/* request one big array to hold the pseudocolor image */
image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
cinfo->in_color_space = CS_RGB;
cinfo->input_components = 3;
break;
case TRUECOLOR:
case DIRECTCOLOR:
/* request three big arrays to hold the RGB channels */
red_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
green_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
blue_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
cinfo->in_color_space = CS_RGB;
cinfo->input_components = 3;
break;
}
cinfo->total_passes++; /* count file reading as separate pass */
}
/*
* Read one row of pixels.
* These are called only after load_image has read the image into
* the virtual array(s).
*/
METHODDEF void
get_grayscale_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This is used for GRAYSCALE images */
{
JSAMPROW inputrows[1]; /* a pseudo JSAMPARRAY structure */
cur_row_number--; /* work down in array */
inputrows[0] = *((*cinfo->emethods->access_big_sarray)
(image, cur_row_number, FALSE));
jcopy_sample_rows(inputrows, 0, pixel_row, 0, 1, cinfo->image_width);
}
METHODDEF void
get_pseudocolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This is used for PSEUDOCOLOR images */
{
long col;
JSAMPROW image_ptr, ptr0, ptr1, ptr2;
int val;
cur_row_number--; /* work down in array */
image_ptr = *((*cinfo->emethods->access_big_sarray)
(image, cur_row_number, FALSE));
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
val = GETJSAMPLE(*image_ptr++);
*ptr0++ = colormap[val ] >> 8;
*ptr1++ = colormap[val + 256] >> 8;
*ptr2++ = colormap[val + 512] >> 8;
}
}
METHODDEF void
get_truecolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This is used for TRUECOLOR images */
/* The colormap consists of 3 independent lookup tables */
{
long col;
JSAMPROW red_ptr, green_ptr, blue_ptr, ptr0, ptr1, ptr2;
cur_row_number--; /* work down in array */
red_ptr = *((*cinfo->emethods->access_big_sarray)
(red_channel, cur_row_number, FALSE));
green_ptr = *((*cinfo->emethods->access_big_sarray)
(green_channel, cur_row_number, FALSE));
blue_ptr = *((*cinfo->emethods->access_big_sarray)
(blue_channel, cur_row_number, FALSE));
ptr0 = pixel_row[0];
ptr1 = pixel_row[1];
ptr2 = pixel_row[2];
for (col = cinfo->image_width; col > 0; col--) {
*ptr0++ = colormap[GETJSAMPLE(*red_ptr++) ] >> 8;
*ptr1++ = colormap[GETJSAMPLE(*green_ptr++) + 256] >> 8;
*ptr2++ = colormap[GETJSAMPLE(*blue_ptr++) + 512] >> 8;
}
}
METHODDEF void
get_directcolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This is used for DIRECTCOLOR images */
{
JSAMPROW inputrows[3]; /* a pseudo JSAMPARRAY structure */
cur_row_number--; /* work down in array */
inputrows[0] = *((*cinfo->emethods->access_big_sarray)
(red_channel, cur_row_number, FALSE));
inputrows[1] = *((*cinfo->emethods->access_big_sarray)
(green_channel, cur_row_number, FALSE));
inputrows[2] = *((*cinfo->emethods->access_big_sarray)
(blue_channel, cur_row_number, FALSE));
jcopy_sample_rows(inputrows, 0, pixel_row, 0, 3, cinfo->image_width);
}
/*
* Load the color channels into separate arrays. We have to do
* this because RLE files start at the lower left while the JPEG standard
* has them starting in the upper left. This is called the first time
* we want to get a row of input. What we do is load the RLE data into
* big arrays and then call the appropriate routine to read one row from
* the big arrays. We also change cinfo->methods->get_input_row so that
* subsequent calls go straight to the row-reading routine.
*/
METHODDEF void
load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
long row;
rle_pixel *rle_row[3];
/* Read the RLE data into our virtual array(s).
* We assume here that (a) rle_pixel is represented the same as JSAMPLE,
* and (b) we are not on a machine where FAR pointers differ from regular.
*/
RLE_CLR_BIT(header, RLE_ALPHA); /* don't read the alpha channel */
switch (visual) {
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 :-(.
*/
rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
(image, row, TRUE));
rle_getrow(&header, rle_row);
}
break;
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 :-(.
*/
rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
(red_channel, row, TRUE));
rle_row[1] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
(green_channel, row, TRUE));
rle_row[2] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
(blue_channel, row, TRUE));
rle_getrow(&header, rle_row);
}
break;
}
cinfo->completed_passes++;
/* Set up to call proper row-extraction routine in future */
switch (visual) {
case GRAYSCALE:
cinfo->methods->get_input_row = get_grayscale_row;
break;
case PSEUDOCOLOR:
cinfo->methods->get_input_row = get_pseudocolor_row;
break;
case TRUECOLOR:
cinfo->methods->get_input_row = get_truecolor_row;
break;
case DIRECTCOLOR:
cinfo->methods->get_input_row = get_directcolor_row;
break;
}
/* And fetch the topmost (bottommost) row */
cur_row_number = cinfo->image_height;
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
input_term (compress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/*
* The method selection routine for RLE format input.
* Note that this must be called by the user interface before calling
* jpeg_compress. If multiple input formats are supported, the
* user interface is responsible for discovering the file format and
* calling the appropriate method selection routine.
*/
GLOBAL void
jselrrle (compress_info_ptr cinfo)
{
cinfo->methods->input_init = input_init;
cinfo->methods->get_input_row = load_image; /* until first call */
cinfo->methods->input_term = input_term;
}
#endif /* RLE_SUPPORTED */

View File

@@ -1,464 +0,0 @@
/*
* jrdtarga.c
*
* 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 routines to read input images in Targa format.
*
* These routines may need modification for non-Unix environments or
* specialized applications. As they stand, they assume input from
* an ordinary stdio stream. They further assume that reading begins
* at the start of the file; input_init may need work if the
* user interface has already read some data (e.g., to determine that
* the file is indeed Targa format).
*
* These routines are invoked via the methods get_input_row
* and input_init/term.
*
* Based on code contributed by Lee Daniel Crocker.
*/
#include "jinclude.h"
#ifdef TARGA_SUPPORTED
/* 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)))
static JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
static big_sarray_ptr whole_image; /* Needed if funny input row order */
static long current_row; /* Current logical row number to read */
/* Pointer to routine to extract next Targa pixel from input file */
static void (*read_pixel) PP((compress_info_ptr cinfo));
/* Result of read_pixel is delivered here: */
static U_CHAR tga_pixel[4];
static int pixel_size; /* Bytes per Targa pixel (1 to 4) */
/* State info for reading RLE-coded pixels; both counts must be init to 0 */
static int block_count; /* # of pixels remaining in RLE block */
static int dup_pixel_count; /* # of times to duplicate previous pixel */
/* This saves the correct pixel-row-expansion method for preload_image */
static void (*get_pixel_row) PP((compress_info_ptr cinfo,
JSAMPARRAY pixel_row));
/* For expanding 5-bit pixel values to 8-bit with best rounding */
static const UINT8 c5to8bits[32] = {
0, 8, 16, 24, 32, 41, 49, 57,
65, 74, 82, 90, 98, 106, 115, 123,
131, 139, 148, 156, 164, 172, 180, 189,
197, 205, 213, 222, 230, 238, 246, 255
};
LOCAL int
read_byte (compress_info_ptr cinfo)
/* Read next byte from Targa file */
{
register FILE *infile = cinfo->input_file;
register int c;
if ((c = getc(infile)) == EOF)
ERREXIT(cinfo->emethods, "Premature EOF in Targa file");
return c;
}
LOCAL void
read_colormap (compress_info_ptr cinfo, int cmaplen, int mapentrysize)
/* Read the colormap from a Targa file */
{
int i;
/* Presently only handles 24-bit BGR format */
if (mapentrysize != 24)
ERREXIT(cinfo->emethods, "Unsupported Targa colormap format");
for (i = 0; i < cmaplen; i++) {
colormap[2][i] = (JSAMPLE) read_byte(cinfo);
colormap[1][i] = (JSAMPLE) read_byte(cinfo);
colormap[0][i] = (JSAMPLE) read_byte(cinfo);
}
}
/*
* read_pixel methods: get a single pixel from Targa file into tga_pixel[]
*/
LOCAL void
read_non_rle_pixel (compress_info_ptr cinfo)
/* Read one Targa pixel from the input file; no RLE expansion */
{
register FILE * infile = cinfo->input_file;
register int i;
for (i = 0; i < pixel_size; i++) {
tga_pixel[i] = (U_CHAR) getc(infile);
}
}
LOCAL void
read_rle_pixel (compress_info_ptr cinfo)
/* Read one Targa pixel from the input file, expanding RLE data as needed */
{
register FILE * infile = cinfo->input_file;
register int i;
/* Duplicate previously read pixel? */
if (dup_pixel_count > 0) {
dup_pixel_count--;
return;
}
/* Time to read RLE block header? */
if (--block_count < 0) { /* decrement pixels remaining in block */
i = read_byte(cinfo);
if (i & 0x80) { /* Start of duplicate-pixel block? */
dup_pixel_count = i & 0x7F; /* number of duplications after this one */
block_count = 0; /* then read new block header */
} else {
block_count = i & 0x7F; /* number of pixels after this one */
}
}
/* Read next pixel */
for (i = 0; i < pixel_size; i++) {
tga_pixel[i] = (U_CHAR) getc(infile);
}
}
/*
* Read one row of pixels.
*
* We provide several different versions depending on input file format.
*/
METHODDEF void
get_8bit_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading 8-bit grayscale pixels */
{
register JSAMPROW ptr0;
register long col;
ptr0 = pixel_row[0];
for (col = cinfo->image_width; col > 0; col--) {
(*read_pixel) (cinfo); /* Load next pixel into tga_pixel */
*ptr0++ = (JSAMPLE) UCH(tga_pixel[0]);
}
}
METHODDEF void
get_8bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading 8-bit colormap indexes */
{
register int t;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
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 */
t = UCH(tga_pixel[0]);
*ptr0++ = colormap[0][t];
*ptr1++ = colormap[1][t];
*ptr2++ = colormap[2][t];
}
}
METHODDEF void
get_16bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading 16-bit pixels */
{
register int t;
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
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 */
t = UCH(tga_pixel[0]);
t += UCH(tga_pixel[1]) << 8;
/* We expand 5 bit data to 8 bit sample width.
* The format of the 16-bit (LSB first) input word is
* xRRRRRGGGGGBBBBB
*/
*ptr2++ = (JSAMPLE) c5to8bits[t & 0x1F];
t >>= 5;
*ptr1++ = (JSAMPLE) c5to8bits[t & 0x1F];
t >>= 5;
*ptr0++ = (JSAMPLE) c5to8bits[t & 0x1F];
}
}
METHODDEF void
get_24bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* This version is for reading 24-bit pixels */
{
register JSAMPROW ptr0, ptr1, ptr2;
register long col;
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 */
*ptr0++ = (JSAMPLE) UCH(tga_pixel[2]); /* convert BGR to RGB order */
*ptr1++ = (JSAMPLE) UCH(tga_pixel[1]);
*ptr2++ = (JSAMPLE) UCH(tga_pixel[0]);
}
}
/*
* 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.
*/
#define get_32bit_row get_24bit_row
/*
* This method is for re-reading the input data in standard top-down
* row order. The entire image has already been read into whole_image
* with proper conversion of pixel format, but it's in a funny row order.
*/
METHODDEF void
get_memory_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
JSAMPARRAY image_ptr;
long source_row;
/* Compute row of source that maps to current_row of normal order */
/* For now, assume image is bottom-up and not interlaced. */
/* NEEDS WORK to support interlaced images! */
source_row = cinfo->image_height - current_row - 1;
/* Fetch that row from virtual array */
image_ptr = (*cinfo->emethods->access_big_sarray)
(whole_image, source_row * cinfo->input_components, FALSE);
jcopy_sample_rows(image_ptr, 0, pixel_row, 0,
cinfo->input_components, cinfo->image_width);
current_row++;
}
/*
* This method loads the image into whole_image during the first call on
* get_input_row. The get_input_row pointer is then adjusted to call
* get_memory_row on subsequent calls.
*/
METHODDEF void
preload_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
{
JSAMPARRAY image_ptr;
long 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;
/* And read the first row */
get_memory_row(cinfo, pixel_row);
}
/*
* Read the file header; return image size and component count.
*/
METHODDEF void
input_init (compress_info_ptr cinfo)
{
U_CHAR targaheader[18];
int idlen, cmaptype, subtype, flags, interlace_type, components;
UINT16 width, height, maplen;
boolean is_bottom_up;
#define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \
(((unsigned int) UCH(targaheader[offset+1])) << 8))
if (! ReadOK(cinfo->input_file, targaheader, 18))
ERREXIT(cinfo->emethods, "Unexpected end of file");
/* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
if (targaheader[16] == 15)
targaheader[16] = 16;
idlen = UCH(targaheader[0]);
cmaptype = UCH(targaheader[1]);
subtype = UCH(targaheader[2]);
maplen = GET_2B(5);
width = GET_2B(12);
height = GET_2B(14);
pixel_size = UCH(targaheader[16]) >> 3;
flags = UCH(targaheader[17]); /* Image Descriptor byte */
is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
interlace_type = flags >> 6; /* bits 6/7 are interlace code */
if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
pixel_size < 1 || pixel_size > 4 ||
(UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
interlace_type != 0) /* currently don't allow interlaced image */
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
if (subtype > 8) {
/* It's an RLE-coded file */
read_pixel = read_rle_pixel;
block_count = dup_pixel_count = 0;
subtype -= 8;
} else {
/* Non-RLE file */
read_pixel = read_non_rle_pixel;
}
/* Now should have subtype 1, 2, or 3 */
components = 3; /* until proven different */
cinfo->in_color_space = CS_RGB;
switch (subtype) {
case 1: /* colormapped image */
if (pixel_size == 1 && cmaptype == 1)
get_pixel_row = get_8bit_row;
else
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
break;
case 2: /* RGB image */
switch (pixel_size) {
case 2:
get_pixel_row = get_16bit_row;
break;
case 3:
get_pixel_row = get_24bit_row;
break;
case 4:
get_pixel_row = get_32bit_row;
break;
default:
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
break;
}
break;
case 3: /* Grayscale image */
components = 1;
cinfo->in_color_space = CS_GRAYSCALE;
if (pixel_size == 1)
get_pixel_row = get_8bit_gray_row;
else
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
break;
default:
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
break;
}
if (is_bottom_up) {
whole_image = (*cinfo->emethods->request_big_sarray)
((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;
}
while (idlen--) /* Throw away ID field */
(void) read_byte(cinfo);
if (maplen > 0) {
if (maplen > 256 || GET_2B(3) != 0)
ERREXIT(cinfo->emethods, "Colormap too large");
/* Allocate space to store the colormap */
colormap = (*cinfo->emethods->alloc_small_sarray)
((long) maplen, 3L);
/* and read it from the file */
read_colormap(cinfo, (int) maplen, UCH(targaheader[7]));
} else {
if (cmaptype) /* but you promised a cmap! */
ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
colormap = NULL;
}
cinfo->input_components = components;
cinfo->image_width = width;
cinfo->image_height = height;
cinfo->data_precision = 8; /* always, even if 12-bit JSAMPLEs */
}
/*
* Finish up at the end of the file.
*/
METHODDEF void
input_term (compress_info_ptr cinfo)
{
/* no work (we let free_all release the workspace) */
}
/*
* The method selection routine for Targa format input.
* Note that this must be called by the user interface before calling
* jpeg_compress. If multiple input formats are supported, the
* user interface is responsible for discovering the file format and
* calling the appropriate method selection routine.
*/
GLOBAL void
jselrtarga (compress_info_ptr cinfo)
{
cinfo->methods->input_init = input_init;
/* cinfo->methods->get_input_row is set by input_init */
cinfo->methods->input_term = input_term;
}
#endif /* TARGA_SUPPORTED */

221
jrevdct.c
View File

@@ -1,221 +0,0 @@
/*
* jrevdct.c
*
* 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.
*/
#include "jinclude.h"
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/* The poop on this scaling stuff is as follows:
*
* 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).
*
* 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.
*/
#ifdef EIGHT_BIT_SAMPLES
#define LG2_DCT_SCALE 16
#else
#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
/* 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)
/* Scale a fractional constant by DCT_SCALE */
#define FIX(x) ((INT32) ((x) * DCT_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 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 pass, rowctr;
register DCTELEM *inptr, *outptr;
DCTBLOCK workspace;
/* Each iteration of the inner loop performs one 8-point 1-D IDCT.
* It reads from a *row* of the input matrix and stores into a *column*
* of the output matrix. In the first pass, we read from the data[] array
* and store into the local workspace[]. In the second pass, we read from
* the workspace[] array and store into data[], thus performing the
* equivalent of a columnar IDCT pass with no variable array indexing.
*/
inptr = data; /* initialize pointers for first pass */
outptr = workspace;
for (pass = 1; pass >= 0; pass--) {
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* 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
in0 = inptr[0];
in1 = inptr[1];
in2 = inptr[2];
in3 = inptr[3];
in4 = inptr[4];
in5 = inptr[5];
in6 = inptr[6];
in7 = inptr[7];
/* These values are scaled by DCT_SCALE */
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;
/* These values are scaled by OVERSCALE */
tmp30 = UNFIXO((in3 + in5) * COS_1_4);
tmp31 = UNFIXO((in3 - in5) * COS_1_4);
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;
outptr[ 0] = (DCTELEM) UNFIXH(tmp20 + tmp50);
outptr[DCTSIZE ] = (DCTELEM) UNFIXH(tmp21 + tmp53);
outptr[DCTSIZE*2] = (DCTELEM) UNFIXH(tmp22 + tmp52);
outptr[DCTSIZE*3] = (DCTELEM) UNFIXH(tmp23 + tmp51);
outptr[DCTSIZE*4] = (DCTELEM) UNFIXH(tmp23 - tmp51);
outptr[DCTSIZE*5] = (DCTELEM) UNFIXH(tmp22 - tmp52);
outptr[DCTSIZE*6] = (DCTELEM) UNFIXH(tmp21 - tmp53);
outptr[DCTSIZE*7] = (DCTELEM) UNFIXH(tmp20 - tmp50);
inptr += DCTSIZE; /* advance inptr to next row */
outptr++; /* advance outptr to next column */
}
/* end of pass; in case it was pass 1, set up for pass 2 */
inptr = workspace;
outptr = data;
}
}

Some files were not shown because too many files have changed in this diff Show More