The Independent JPEG Group's JPEG software v1
This commit is contained in:
commit
2cbeb8abd9
391
README
Normal file
391
README
Normal file
@ -0,0 +1,391 @@
|
||||
The Independent JPEG Group's JPEG software
|
||||
==========================================
|
||||
|
||||
README for release of 7-Oct-91
|
||||
===============================
|
||||
|
||||
This distribution contains the first public release of the Independent JPEG
|
||||
Group's free JPEG software. You are welcome to redistribute this software and
|
||||
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
|
||||
|
||||
This software is still undergoing revision. Updated versions may be obtained
|
||||
by anonymous FTP to uunet.uu.net; look under directory /graphics/jpeg. This
|
||||
particular version will be archived as jpegsrc.v1.tar.Z. If you don't have
|
||||
access to Internet FTP, UUNET's archives are also available via UUCP; contact
|
||||
postmaster@uunet.uu.net for information on retrieving files that way.
|
||||
|
||||
Please report any problems with this software to jpeg-info@uunet.uu.net.
|
||||
|
||||
If you intend to become a serious user of this software, please contact
|
||||
jpeg-info@uunet to be added to our electronic mailing list. Then you'll be
|
||||
notified of updates and have a chance to participate in discussions, etc.
|
||||
|
||||
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, and other
|
||||
members of the independent JPEG group.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED. It is not guaranteed to be
|
||||
useful for anything, nor to be compatible with subsequent releases, nor to be
|
||||
an accurate implementation of the JPEG standard. (See LEGAL ISSUES for even
|
||||
more disclaimers.)
|
||||
|
||||
|
||||
WHAT'S HERE
|
||||
===========
|
||||
|
||||
This distribution contains software to implement JPEG image compression and
|
||||
decompression. JPEG is a standardized compression method for full-color and
|
||||
gray-scale images. JPEG is intended for "real-world" scenes; cartoons and
|
||||
other non-realistic images are not its strong suit. JPEG is lossy, meaning
|
||||
that the output image is not necessarily identical to the input image. Hence
|
||||
you should not use JPEG if you have to have identical output bits. However,
|
||||
on typical images of real-world scenes, very good compression levels can be
|
||||
obtained with hardly any visible change, and amazingly high compression levels
|
||||
can be obtained if you can tolerate a low-quality image. For more details,
|
||||
see the references, or just experiment with various compression settings.
|
||||
|
||||
The software implements JPEG baseline and extended-sequential compression
|
||||
processes. Provision is made for supporting all variants of these processes,
|
||||
although some uncommon parameter settings aren't implemented yet. For legal
|
||||
reasons, we are not distributing code for the arithmetic-coding process; see
|
||||
LEGAL ISSUES. At present we have made no provision for supporting the
|
||||
progressive or lossless processes defined in the standard.
|
||||
|
||||
The present software is still largely in the prototype stage. It does not
|
||||
support all possible variants of the JPEG standard, and some functions have
|
||||
rather slow and/or crude implementations. However, it is useful already.
|
||||
|
||||
The emphasis in designing this software has been on achieving portability and
|
||||
flexibility, while also making it fast enough to be useful. We have not yet
|
||||
undertaken serious performance measurement or tuning; we intend to do so in
|
||||
the future.
|
||||
|
||||
|
||||
This software can be used on several levels:
|
||||
|
||||
* As canned software for JPEG compression and decompression. Just edit the
|
||||
Makefile and configuration files as needed (see SETUP), compile and go.
|
||||
Members of the independent JPEG group will improve the out-of-the-box
|
||||
functionality as time goes on.
|
||||
|
||||
* As the basis for other JPEG programs. For example, you could incorporate
|
||||
the decompressor into a general image viewing package by replacing the
|
||||
output module with write-to-screen functions. For an implementation on
|
||||
specific hardware, you might want to replace some of the inner loops with
|
||||
assembly code. For a non-command-line-driven system, you might want a
|
||||
different user interface. (Members of the group will be producing Macintosh
|
||||
and Amiga versions with appropriate user interfaces, for example.)
|
||||
|
||||
* As a toolkit for experimentation with JPEG and JPEG-like algorithms. Most
|
||||
of the individual decisions you might want to mess with are packaged up into
|
||||
separate modules. For example, the details of color-space conversion and
|
||||
subsampling techniques are each localized in one compressor and one
|
||||
decompressor module. You'd probably also want to extend the user interface
|
||||
to give you more detailed control over the JPEG compression parameters.
|
||||
|
||||
In particular, we welcome the use of this software as the basis for commercial
|
||||
products; no royalty is required.
|
||||
|
||||
|
||||
SETUP
|
||||
=====
|
||||
|
||||
The installation process is not very automatic; you will need at least some
|
||||
familiarity with C programming and program build procedures for your system.
|
||||
(Volunteers to work on improving this situation are welcome. Also, we will
|
||||
probably start distributing pre-built binaries for popular systems at some
|
||||
point.)
|
||||
|
||||
First, select a makefile and copy it to "Makefile". "makefile.unix"
|
||||
is appropriate for most Unix and Unix-like systems. Special makefiles are
|
||||
included for various PC compilers. If you don't see a makefile for your
|
||||
system, we recommend starting from makefile.unix.
|
||||
|
||||
Look over the Makefile and adjust options as needed. In particular, you'll
|
||||
need to change the CC= and CFLAGS= definitions if you don't have gcc
|
||||
(makefile.unix only). If you have a function-prototype-less compiler, be sure
|
||||
to uncomment the .c.o rule and say "make ansi2knr". This will cause the
|
||||
source files to be preprocessed to change our ANSI-style function definitions
|
||||
to old-style definitions. (Thanks to Peter Deutsch of Aladdin Enterprises for
|
||||
ansi2knr.)
|
||||
|
||||
Also look over jconfig.h and adjust #defines as necessary. If you have an
|
||||
ANSI-compliant C compiler (gcc for instance), no changes should be necessary
|
||||
except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE. For
|
||||
older compilers other mods may be needed, depending on what ANSI features are
|
||||
supported. If you prefer, you can usually leave jconfig.h unmodified and add
|
||||
-D switches to the Makefile's CFLAGS= definition.
|
||||
|
||||
Then say "make".
|
||||
|
||||
If you have trouble with missing system include files or inclusion of the
|
||||
wrong ones, you can fix it in jinclude.h. In particular, if you are using
|
||||
gcc on a machine with non-ANSI system include files, you are likely to find
|
||||
that jinclude.h tries to include the wrong files (because gcc defines
|
||||
__STDC__). There's no good automatic solution to this, so you'll just have
|
||||
to hand-edit jinclude.h.
|
||||
|
||||
As a quick test of functionality we've included three sample files:
|
||||
testorig.jpg same as blkint.jpg from JPEG validation floppy.
|
||||
testimg.ppm output of djpeg testorig.jpg
|
||||
testimg.jpg output of cjpeg testimg.ppm
|
||||
The two .jpg files aren't identical due to different parameter choices (and
|
||||
wouldn't be anyway, since JPEG is lossy). However, if you can generate
|
||||
duplicates of testimg.ppm and testimg.jpg then you probably have a working
|
||||
port. "make test" will perform the necessary comparisons (by generating
|
||||
testout.ppm and testout.jpg and comparing these to testimg.*). NOTE: this
|
||||
is far from an exhaustive test of the JPEG software; some modules, such as
|
||||
color quantization and GIF I/O, are not exercised at all. It's just a quick
|
||||
test to give you some confidence that you haven't missed something major.
|
||||
|
||||
If you need to make a smaller version of the JPEG software, some optional
|
||||
functions can be removed at compile time. See the xxx_SUPPORTED #defines
|
||||
in jconfig.h. (Not a lot is actually removed right now, but as more optional
|
||||
stuff gets added, this mechanism will start to make a difference.)
|
||||
|
||||
If you want to incorporate the JPEG code as subroutines in a larger program,
|
||||
we recommend that you make libjpeg.a. Then use the .h files and libjpeg.a as
|
||||
your interface to the JPEG functions. Your surrounding program will have to
|
||||
provide functionality similar to what's in jcmain.c or jdmain.c, and you may
|
||||
want to replace jerror.c and possibly other modules depending on your needs.
|
||||
See the "architecture" file for more info. If it seems to you that the system
|
||||
structure doesn't accommodate what you want to do, please contact the authors.
|
||||
|
||||
Special notes for Macintosh Think C users: If you have version 5.0 you should
|
||||
be able to just turn on __STDC__ through the compiler switch that enables
|
||||
that. With version 4.0 you must manually edit jconfig.h to define PROTO,
|
||||
HAVE_UNSIGNED_CHAR, HAVE_UNSIGNED_SHORT, and const. (It seems to be safe to
|
||||
just define __STDC__ to take care of the first three.) When setting up
|
||||
project files, use the COBJECTS and DOBJECTS lists in makefile.unix as a guide
|
||||
to which files need to be included, and add the ANSI and Unix C libraries in a
|
||||
separate segment. You may need to divide the JPEG files into more than one
|
||||
segment; you can do this pretty much as you please.
|
||||
|
||||
|
||||
USAGE
|
||||
=====
|
||||
|
||||
The user interface is pretty minimal at this point. We haven't bothered to
|
||||
generate manual-page files since the switches badly need redesign. At the
|
||||
moment, things work like this:
|
||||
|
||||
There are two programs, cjpeg to compress an image file into JPEG format,
|
||||
and djpeg to decompress.
|
||||
|
||||
On Unix systems, you say:
|
||||
cjpeg [switches] [imagefile] >jpegfile
|
||||
djpeg [switches] [jpegfile] >imagefile
|
||||
The programs read the specified input file, or standard input if none is
|
||||
named. They always write to standard output (with trace/error messages to
|
||||
standard error). These conventions are handy for piping images between
|
||||
programs.
|
||||
|
||||
On PC, Macintosh, and Amiga systems, you say:
|
||||
cjpeg [switches] imagefile jpegfile
|
||||
djpeg [switches] jpegfile imagefile
|
||||
i.e., both input and output files are named on the command line. This style
|
||||
is a little more foolproof, and it loses no functionality if you don't have
|
||||
pipes. You can get this style on Unix too, if you prefer, by defining
|
||||
TWO_FILE_COMMANDLINE in jconfig.h or in the Makefile. You MUST use this style
|
||||
on any system that doesn't cope well with binary data fed through
|
||||
stdin/stdout.
|
||||
|
||||
Currently supported image file formats include raw-format PPM, raw-format PGM
|
||||
(for monochrome images), and GIF. cjpeg recognizes the input image format
|
||||
automatically, but you have to tell djpeg which format to generate.
|
||||
|
||||
The only JPEG file format currently supported is a raw JPEG data stream.
|
||||
Unless modified, the programs use the JFIF conventions for variables left
|
||||
unspecified by the JPEG standard. (In particular, cjpeg generates a JFIF APP0
|
||||
marker.) Support for the JPEG-in-TIFF format will probably be added at some
|
||||
future date.
|
||||
|
||||
The command line switches for cjpeg are:
|
||||
|
||||
-I Generate noninterleaved JPEG file (not yet supported).
|
||||
|
||||
-Q quality Scale quantization tables to adjust quality.
|
||||
Quality is 0 (worst) to 100 (best); default is 75.
|
||||
(See below for more info.)
|
||||
|
||||
-a Use arithmetic coding rather than Huffman coding.
|
||||
(Not currently supported, see LEGAL ISSUES.)
|
||||
|
||||
-o Perform optimization of entropy encoding parameters.
|
||||
Without this, default Huffman or arithmetic
|
||||
parameters are used. -o makes the JPEG file a tad
|
||||
smaller, but compression uses much more memory.
|
||||
Image quality is unaffected by -o.
|
||||
|
||||
-d Enable debug printout. More -d's give more printout.
|
||||
|
||||
Typically you'd use -Q settings of 50 or 75 or so. -Q 100 will generate a
|
||||
quantization table of all 1's, meaning no quantization loss; then any
|
||||
differences between input and output images are due to subsampling or to
|
||||
roundoff error in the DCT or colorspace-conversion steps. -Q values below 50
|
||||
may be useful for making real small, low-quality images. Try -Q 2 (or so) for
|
||||
some amusing Cubist effects. (Note that -Q values below about 25 generate
|
||||
2-byte quantization tables, which are not decodable by pure baseline JPEG
|
||||
decoders. cjpeg emits a warning message when you give such a -Q value.)
|
||||
|
||||
The command line switches for djpeg are:
|
||||
|
||||
-G Select GIF output format (implies -q, with default
|
||||
of 256 colors).
|
||||
|
||||
-b Perform cross-block smoothing. This is quite
|
||||
memory-intensive and only seems to improve the image
|
||||
at very low quality settings (-Q 10 to 20 or so).
|
||||
|
||||
-g Force gray-scale output even if input is color.
|
||||
|
||||
-q N Quantize to N colors.
|
||||
|
||||
-D Use Floyd-Steinberg dithering in color quantization.
|
||||
|
||||
-2 Use two-pass color quantization (not yet supported).
|
||||
|
||||
-d Enable debug printout. More -d's give more printout.
|
||||
|
||||
Color quantization currently uses a rather shoddy algorithm (although it's not
|
||||
so horrible when dithered). Because of this, the GIF output mode is not
|
||||
recommended in the current release, except for gray-scale output. You can get
|
||||
better results by applying ppmquant to the unquantized (PPM) output of djpeg,
|
||||
then converting to GIF with ppmtogif. We expect to provide a considerably
|
||||
better quantization algorithm in a future release.
|
||||
|
||||
Note that djpeg *can* read noninterleaved JPEG files even though cjpeg can't
|
||||
yet generate them. For most applications this is a nonissue, since hardly
|
||||
anybody seems to be using noninterleaved format.
|
||||
|
||||
On a non-virtual-memory machine, you may run out of memory if you use -I or -o
|
||||
in cjpeg, or -q ... -2 in djpeg, or try to read an interlaced GIF file. This
|
||||
will be addressed eventually by replacing jvirtmem.c with something that uses
|
||||
temporary files for large images (see TO DO).
|
||||
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
|
||||
The best and most readily available introduction to the JPEG compression
|
||||
algorithm is Wallace's article in the April '91 CACM:
|
||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||
applications of JPEG, and related topics.) We highly recommend reading that
|
||||
article before looking at any of the JPEG software.
|
||||
|
||||
For more detail about the JPEG standard you pretty much have to go to the
|
||||
draft standard, which is not nearly as intelligible as Wallace's article.
|
||||
The current version is ISO/IEC Committee Draft CD 10918-1 dated 1991-03-15.
|
||||
The standard is not presently available electronically; you must order a paper
|
||||
copy through ISO.
|
||||
|
||||
The JPEG standard does not specify all details of an interchangeable file
|
||||
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||
1.01. A copy of the JFIF spec is available from:
|
||||
Literature Department
|
||||
C-Cube Microsystems, Inc.
|
||||
399A West Trimble Road
|
||||
San Jose, CA 95131
|
||||
(408) 944-6300
|
||||
Requests can also be e-mailed to info@c3.pla.ca.us (this address good after
|
||||
10/10/91). The same source can supply copies of the draft JPEG-in-TIFF specs.
|
||||
|
||||
If you want to understand this implementation, start by reading the
|
||||
"architecture" documentation file. Please read "codingrules" if you want to
|
||||
contribute any code.
|
||||
|
||||
|
||||
SUPPORTING SOFTWARE
|
||||
===================
|
||||
|
||||
You will probably want Jef Poskanzer's PBMPLUS image software; this provides
|
||||
many useful operations on PPM-format image files. In particular, it can
|
||||
convert PPM images to and from a wide range of other formats. You can FTP
|
||||
this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or
|
||||
ftp.ee.lbl.gov (pbmplus*.tar.Z).
|
||||
|
||||
If you are using X Windows you might want to use the xv or xloadimage viewers
|
||||
to save yourself the trouble of converting PPM to some other format.
|
||||
Both of these can be found in the contrib directory at export.lcs.mit.edu.
|
||||
|
||||
|
||||
LEGAL ISSUES
|
||||
============
|
||||
|
||||
The authors make NO WARRANTY or representation, either express or implied,
|
||||
with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991, Thomas G. Lane.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
software (or portions thereof) for any purpose, without fee, subject to these
|
||||
conditions:
|
||||
(1) If any part of the source code for this software is distributed, then this
|
||||
README file must be included, with this copyright and no-warranty notice
|
||||
unaltered; and any additions, deletions, or changes to the original files
|
||||
must be clearly indicated in accompanying documentation.
|
||||
(2) If only executable code is distributed, then the accompanying
|
||||
documentation must state that "this software is based in part on the work of
|
||||
the Independent JPEG Group".
|
||||
(3) Permission for use of this software is granted only if the user accepts
|
||||
full responsibility for any undesirable consequences; the authors accept
|
||||
NO LIABILITY for damages of any kind.
|
||||
|
||||
Permission is NOT granted for the use of any author's name or author's company
|
||||
name in advertising or publicity relating to this software or products derived
|
||||
from it. This software may be referred to only as "the Independent JPEG
|
||||
Group's software".
|
||||
|
||||
We specifically permit and encourage the use of this software as the basis of
|
||||
commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
||||
|
||||
|
||||
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
|
||||
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
|
||||
ansi2knr.c is NOT covered by the above copyright and conditions, but instead
|
||||
by the usual distribution terms of the Free Software Foundation; principally,
|
||||
that you must include source code if you redistribute it. (See the file
|
||||
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
|
||||
of any product generated from the JPEG code, this does not limit you more than
|
||||
the foregoing paragraphs do.
|
||||
|
||||
|
||||
It appears that the arithmetic coding option of the JPEG spec is covered by
|
||||
patents held by IBM, and possibly also patents of AT&T and Mitsubishi. Hence
|
||||
arithmetic coding cannot legally be used without obtaining one or more
|
||||
licenses. For this reason, support for arithmetic coding has been removed
|
||||
from the free JPEG software. (Since arithmetic coding provides only a
|
||||
marginal gain over the unpatented Huffman mode, it is unlikely that very many
|
||||
people will choose to use it. If you do obtain such a license, contact
|
||||
jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.) So far
|
||||
as we are aware, there are no patent restrictions on the remaining code.
|
||||
|
||||
|
||||
TO DO
|
||||
=====
|
||||
|
||||
Many of the modules need fleshing out to provide more complete
|
||||
implementations, or to provide faster paths for common cases. The greatest
|
||||
needs are for (a) decent color quantization, and (b) a memory manager
|
||||
implementation that can work in limited memory by swapping "big" images to
|
||||
temporary files. I (Tom Lane) am going to work on color quantization next.
|
||||
Volunteers to write a PC memory manager, or to work on any other modules, are
|
||||
welcome.
|
||||
|
||||
We'd appreciate it if people would compile and check out the code on as wide a
|
||||
variety of systems as possible, and report any portability problems
|
||||
encountered (with solutions, if possible). Checks of file compatibility with
|
||||
other JPEG implementations would also be of interest. Finally, we would
|
||||
appreciate code profiles showing where the most time is spent, especially on
|
||||
unusual systems.
|
||||
|
||||
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
|
477
ansi2knr.c
Normal file
477
ansi2knr.c
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Received from Peter Deutsch (ghost@aladdin.com)
|
||||
* Fri, 26 Apr 91 10:10:10 PDT
|
||||
*/
|
||||
|
||||
/* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved.
|
||||
Distributed by Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Ghostscript.
|
||||
|
||||
Ghostscript is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
|
||||
to anyone for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing. Refer
|
||||
to the Ghostscript General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute
|
||||
Ghostscript, but only under the conditions described in the Ghostscript
|
||||
General Public License. A copy of this license is supposed to have been
|
||||
given to you along with Ghostscript so you can know your rights and
|
||||
responsibilities. It should be in a file named COPYING. Among other
|
||||
things, the copyright notice and this notice must be preserved on all
|
||||
copies. */
|
||||
|
||||
/*
|
||||
---------- Here is the GhostScript file COPYING, referred to above ----------
|
||||
----- These terms do NOT apply to the JPEG software itself; see README ------
|
||||
|
||||
GHOSTSCRIPT GENERAL PUBLIC LICENSE
|
||||
(Clarified 11 Feb 1988)
|
||||
|
||||
Copyright (C) 1988 Richard M. Stallman
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license, but changing it is not allowed. You can also use this wording
|
||||
to make the terms for other programs.
|
||||
|
||||
The license agreements of most software companies keep you at the
|
||||
mercy of those companies. By contrast, our general public license is
|
||||
intended to give everyone the right to share Ghostscript. To make sure
|
||||
that you get the rights we want you to have, we need to make
|
||||
restrictions that forbid anyone to deny you these rights or to ask you
|
||||
to surrender the rights. Hence this license agreement.
|
||||
|
||||
Specifically, we want to make sure that you have the right to give
|
||||
away copies of Ghostscript, that you receive source code or else can get
|
||||
it if you want it, that you can change Ghostscript or use pieces of it
|
||||
in new free programs, and that you know you can do these things.
|
||||
|
||||
To make sure that everyone has such rights, we have to forbid you to
|
||||
deprive anyone else of these rights. For example, if you distribute
|
||||
copies of Ghostscript, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must tell them their rights.
|
||||
|
||||
Also, for our own protection, we must make certain that everyone finds
|
||||
out that there is no warranty for Ghostscript. If Ghostscript is
|
||||
modified by someone else and passed on, we want its recipients to know
|
||||
that what they have is not what we distributed, so that any problems
|
||||
introduced by others will not reflect on our reputation.
|
||||
|
||||
Therefore we (Richard M. Stallman and the Free Software Foundation,
|
||||
Inc.) make the following terms which say what you must do to be allowed
|
||||
to distribute or change Ghostscript.
|
||||
|
||||
|
||||
COPYING POLICIES
|
||||
|
||||
1. You may copy and distribute verbatim copies of Ghostscript source
|
||||
code as you receive it, in any medium, provided that you conspicuously
|
||||
and appropriately publish on each copy a valid copyright and license
|
||||
notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved.
|
||||
Distributed by Free Software Foundation, Inc." (or with whatever year is
|
||||
appropriate); keep intact the notices on all files that refer to this
|
||||
License Agreement and to the absence of any warranty; and give any other
|
||||
recipients of the Ghostscript program a copy of this License Agreement
|
||||
along with the program. You may charge a distribution fee for the
|
||||
physical act of transferring a copy.
|
||||
|
||||
2. You may modify your copy or copies of Ghostscript or any portion of
|
||||
it, and copy and distribute such modifications under the terms of
|
||||
Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of Ghostscript
|
||||
or any part thereof, to be licensed at no charge to all third
|
||||
parties on terms identical to those contained in this License
|
||||
Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute Ghostscript (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the
|
||||
terms of Paragraphs 1 and 2 above provided that you also do one of the
|
||||
following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer Ghostscript
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer Ghostscript is
|
||||
void and your rights to use the program under this License agreement
|
||||
shall be automatically terminated. However, parties who have received
|
||||
computer software programs from you with this License Agreement will not
|
||||
have their licenses terminated so long as such parties remain in full
|
||||
compliance.
|
||||
|
||||
5. If you wish to incorporate parts of Ghostscript into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not
|
||||
yet worked out a simple rule that can be stated here, but we will often
|
||||
permit this. We will be guided by the two goals of preserving the free
|
||||
status of all derivatives of our free software and of promoting the
|
||||
sharing and reuse of software.
|
||||
|
||||
Your comments and suggestions about our licensing policies and our
|
||||
software are welcome! Please contact the Free Software Foundation,
|
||||
Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
|
||||
M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
|
||||
PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
|
||||
YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
|
||||
ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
|
||||
GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
|
||||
ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
|
||||
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
|
||||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
|
||||
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
|
||||
BY ANY OTHER PARTY.
|
||||
-------------------- End of file COPYING ------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* ansi2knr.c */
|
||||
/* Convert ANSI function declarations to K&R syntax */
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef BSD
|
||||
# include <strings.h>
|
||||
# define strchr index
|
||||
#else
|
||||
# ifdef VMS
|
||||
extern char *strcat(), *strchr(), *strcpy(), *strupr();
|
||||
extern int strcmp(), strlen(), strncmp();
|
||||
# else
|
||||
# include <string.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef MSDOS
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# ifdef VMS
|
||||
extern char *malloc();
|
||||
extern void free();
|
||||
# else
|
||||
# ifdef BSD
|
||||
extern char *malloc();
|
||||
# else
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Usage:
|
||||
ansi2knr input_file output_file
|
||||
* If no output_file is supplied, output goes to stdout.
|
||||
* There are no error messages.
|
||||
*
|
||||
* ansi2knr recognizes functions by seeing a non-keyword identifier
|
||||
* at the left margin, followed by a left parenthesis,
|
||||
* with a right parenthesis as the last character on the line.
|
||||
* It will recognize a multi-line header if the last character
|
||||
* on each line but the last is a left parenthesis or comma.
|
||||
* These algorithms ignore whitespace and comments, except that
|
||||
* the function name must be the first thing on the line.
|
||||
* The following constructs will confuse it:
|
||||
- Any other construct that starts at the left margin and
|
||||
follows the above syntax (such as a macro or function call).
|
||||
- Macros that tinker with the syntax of the function header.
|
||||
*/
|
||||
|
||||
/* Scanning macros */
|
||||
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
|
||||
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ FILE *in, *out;
|
||||
#define bufsize 500 /* arbitrary size */
|
||||
char buf[bufsize];
|
||||
char *line;
|
||||
switch ( argc )
|
||||
{
|
||||
default:
|
||||
printf("Usage: ansi2knr input_file [output_file]\n");
|
||||
exit(0);
|
||||
case 2:
|
||||
out = stdout; break;
|
||||
case 3:
|
||||
out = fopen(argv[2], "w");
|
||||
if ( out == NULL )
|
||||
{ fprintf(stderr, "Cannot open %s\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
in = fopen(argv[1], "r");
|
||||
if ( in == NULL )
|
||||
{ fprintf(stderr, "Cannot open %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
|
||||
line = buf;
|
||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||
{ switch ( test1(buf) )
|
||||
{
|
||||
case 1: /* a function */
|
||||
convert1(buf, out);
|
||||
break;
|
||||
case -1: /* maybe the start of a function */
|
||||
line = buf + strlen(buf);
|
||||
continue;
|
||||
default: /* not a function */
|
||||
fputs(buf, out);
|
||||
break;
|
||||
}
|
||||
line = buf;
|
||||
}
|
||||
if ( line != buf ) fputs(buf, out);
|
||||
fclose(out);
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip over space and comments, in either direction. */
|
||||
char *
|
||||
skipspace(p, dir)
|
||||
register char *p;
|
||||
register int dir; /* 1 for forward, -1 for backward */
|
||||
{ for ( ; ; )
|
||||
{ while ( isspace(*p) ) p += dir;
|
||||
if ( !(*p == '/' && p[dir] == '*') ) break;
|
||||
p += dir; p += dir;
|
||||
while ( !(*p == '*' && p[dir] == '/') )
|
||||
{ if ( *p == 0 ) return p; /* multi-line comment?? */
|
||||
p += dir;
|
||||
}
|
||||
p += dir; p += dir;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blanks over part of a string.
|
||||
*/
|
||||
void
|
||||
writeblanks(start, end)
|
||||
char *start;
|
||||
char *end;
|
||||
{ char *p;
|
||||
for ( p = start; p < end; p++ ) *p = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the string in buf is a function definition.
|
||||
* The string may contain and/or end with a newline.
|
||||
* Return as follows:
|
||||
* 0 - definitely not a function definition;
|
||||
* 1 - definitely a function definition;
|
||||
* -1 - may be the beginning of a function definition,
|
||||
* append another line and look again.
|
||||
*/
|
||||
test1(buf)
|
||||
char *buf;
|
||||
{ register char *p = buf;
|
||||
char *bend;
|
||||
char *endfn;
|
||||
int contin;
|
||||
if ( !isidfirstchar(*p) )
|
||||
return 0; /* no name at left margin */
|
||||
bend = skipspace(buf + strlen(buf) - 1, -1);
|
||||
switch ( *bend )
|
||||
{
|
||||
case ')': contin = 1; break;
|
||||
case '(':
|
||||
case ',': contin = -1; break;
|
||||
default: return 0; /* not a function */
|
||||
}
|
||||
while ( isidchar(*p) ) p++;
|
||||
endfn = p;
|
||||
p = skipspace(p, 1);
|
||||
if ( *p++ != '(' )
|
||||
return 0; /* not a function */
|
||||
p = skipspace(p, 1);
|
||||
if ( *p == ')' )
|
||||
return 0; /* no parameters */
|
||||
/* Check that the apparent function name isn't a keyword. */
|
||||
/* We only need to check for keywords that could be followed */
|
||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||
{ static char *words[] =
|
||||
{ "asm", "auto", "case", "char", "const", "double",
|
||||
"extern", "float", "for", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof",
|
||||
"static", "switch", "typedef", "unsigned",
|
||||
"void", "volatile", "while", 0
|
||||
};
|
||||
char **key = words;
|
||||
char *kp;
|
||||
int len = endfn - buf;
|
||||
while ( (kp = *key) != 0 )
|
||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||
return 0; /* name is a keyword */
|
||||
key++;
|
||||
}
|
||||
}
|
||||
return contin;
|
||||
}
|
||||
|
||||
convert1(buf, out)
|
||||
char *buf;
|
||||
FILE *out;
|
||||
{ char *endfn = strchr(buf, '(') + 1;
|
||||
register char *p;
|
||||
char **breaks;
|
||||
unsigned num_breaks = 2; /* for testing */
|
||||
char **btop;
|
||||
char **bp;
|
||||
char **ap;
|
||||
top: p = endfn;
|
||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||
if ( breaks == 0 )
|
||||
{ /* Couldn't allocate break table, give up */
|
||||
fprintf(stderr, "Unable to allocate break table!\n");
|
||||
fputs(buf, out);
|
||||
return -1;
|
||||
}
|
||||
btop = breaks + num_breaks * 2 - 2;
|
||||
bp = breaks;
|
||||
/* Parse the argument list */
|
||||
do
|
||||
{ int level = 0;
|
||||
char *end = NULL;
|
||||
if ( bp >= btop )
|
||||
{ /* Filled up break table. */
|
||||
/* Allocate a bigger one and start over. */
|
||||
free((char *)breaks);
|
||||
num_breaks <<= 1;
|
||||
goto top;
|
||||
}
|
||||
*bp++ = p;
|
||||
/* Find the end of the argument */
|
||||
for ( ; end == NULL; p++ )
|
||||
{ switch(*p)
|
||||
{
|
||||
case ',': if ( !level ) end = p; break;
|
||||
case '(': level++; break;
|
||||
case ')': if ( --level < 0 ) end = p; break;
|
||||
case '/': p = skipspace(p, 1) - 1; break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
p--; /* back up over terminator */
|
||||
/* Find the name being declared. */
|
||||
/* This is complicated because of procedure and */
|
||||
/* array modifiers. */
|
||||
for ( ; ; )
|
||||
{ p = skipspace(p - 1, -1);
|
||||
switch ( *p )
|
||||
{
|
||||
case ']': /* skip array dimension(s) */
|
||||
case ')': /* skip procedure args OR name */
|
||||
{ int level = 1;
|
||||
while ( level )
|
||||
switch ( *--p )
|
||||
{
|
||||
case ']': case ')': level++; break;
|
||||
case '[': case '(': level--; break;
|
||||
case '/': p = skipspace(p, -1) + 1; break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||
{ /* We found the name being declared */
|
||||
while ( !isidfirstchar(*p) )
|
||||
p = skipspace(p, 1) + 1;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default: goto found;
|
||||
}
|
||||
}
|
||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||
{ p++;
|
||||
if ( bp == breaks + 1 ) /* sole argument */
|
||||
writeblanks(breaks[0], p);
|
||||
else
|
||||
writeblanks(bp[-1] - 1, p);
|
||||
bp--;
|
||||
}
|
||||
else
|
||||
{ while ( isidchar(*p) ) p--;
|
||||
*bp++ = p+1;
|
||||
}
|
||||
p = end;
|
||||
}
|
||||
while ( *p++ == ',' );
|
||||
*bp = p;
|
||||
/* Make a special check for 'void' arglist */
|
||||
if ( bp == breaks+2 )
|
||||
{ p = skipspace(breaks[0], 1);
|
||||
if ( !strncmp(p, "void", 4) )
|
||||
{ p = skipspace(p+4, 1);
|
||||
if ( p == breaks[2] - 1 )
|
||||
{ bp = breaks; /* yup, pretend arglist is empty */
|
||||
writeblanks(breaks[0], p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put out the function name */
|
||||
p = buf;
|
||||
while ( p != endfn ) putc(*p, out), p++;
|
||||
/* Put out the declaration */
|
||||
for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||
{ p = *ap;
|
||||
while ( isidchar(*p) ) putc(*p, out), p++;
|
||||
if ( ap < bp - 1 ) fputs(", ", out);
|
||||
}
|
||||
fputs(") ", out);
|
||||
/* Put out the argument declarations */
|
||||
for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
|
||||
fputs(breaks[0], out);
|
||||
free((char *)breaks);
|
||||
return 0;
|
||||
}
|
1106
architecture
Normal file
1106
architecture
Normal file
File diff suppressed because it is too large
Load Diff
99
codingrules
Normal file
99
codingrules
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
JPEG SYSTEM CODING RULES 27-SEP-91
|
||||
|
||||
Since numerous people will be contributing code and bug fixes, it's important
|
||||
to establish a common coding style. The goal of using similar coding styles
|
||||
is much more important than the details of just what that style is.
|
||||
|
||||
I suggest we follow the recommendations of "Recommended C Style and Coding
|
||||
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
|
||||
Brader). I have placed a copy of this document in the jpeg FTP archive (see
|
||||
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
|
||||
|
||||
Unless someone has a real strong objection, let's do block comments thusly:
|
||||
|
||||
/*
|
||||
* Block comments in this style.
|
||||
*/
|
||||
|
||||
and indent statements in K&R style, e.g.,
|
||||
|
||||
if (test) {
|
||||
then-part;
|
||||
} else {
|
||||
else-part;
|
||||
}
|
||||
|
||||
I suggest that multi-word names be written in the style multi_word_name
|
||||
rather than multiWordName, but I am open to argument on this.
|
||||
|
||||
|
||||
I would like to use function prototypes everywhere, and rely on automatic
|
||||
source code transformation to feed non-ANSI C compilers. The best tool
|
||||
I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
|
||||
ansi2knr is not very bright, so it imposes a format requirement on function
|
||||
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
|
||||
should be written in the following style:
|
||||
|
||||
static int *
|
||||
function_name (int a, char *b)
|
||||
{
|
||||
code...
|
||||
}
|
||||
|
||||
ansi2knr won't help with method declarations (function pointers in structs).
|
||||
I suggest we use a macro to declare method pointers, something like this:
|
||||
|
||||
#ifdef PROTO
|
||||
#define METHOD(type,methodname,arglist) type (*methodname) arglist
|
||||
#else
|
||||
#define METHOD(type,methodname,arglist) type (*methodname) ()
|
||||
#endif
|
||||
|
||||
which is used like this:
|
||||
|
||||
struct function_pointers {
|
||||
METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
|
||||
METHOD(void, term_entropy_encoder, (void));
|
||||
};
|
||||
|
||||
Note the set of parentheses surrounding the parameter list.
|
||||
|
||||
A similar solution is used for external function declarations (see the PP
|
||||
macro in jpegdata.h).
|
||||
|
||||
If the code is to work on non-ANSI compilers, you cannot rely on a prototype
|
||||
declaration to coerce actual parameters into the right types. Therefore, use
|
||||
explicit casts on actual parameters whenever the actual parameter type is not
|
||||
identical to the formal parameter. Beware of implicit conversions to "int".
|
||||
|
||||
It seems there are some non-ANSI compilers in which the sizeof() operator
|
||||
is defined to return int, while size_t is defined as long. Needless to say,
|
||||
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
|
||||
so that the result is guaranteed to be of type size_t.
|
||||
|
||||
|
||||
We can expect that the JPEG compressor and decompressor will be incorporated
|
||||
into larger programs. Therefore, the following rules are important:
|
||||
|
||||
1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
|
||||
pass these through the common routines provided.
|
||||
|
||||
2. Assume that the JPEG code may be invoked more than once per program run;
|
||||
therefore, do not rely on static initialization of variables, and be careful
|
||||
to release all allocated storage at the end of processing.
|
||||
|
||||
3. Minimize global namespace pollution. Functions should be declared static
|
||||
wherever possible. (Note that our method-based calling conventions help this
|
||||
a lot: in many modules only the method-selector function will ever need to be
|
||||
called directly, so only that function need be externally visible.) All
|
||||
global function names should begin with "j", and should be unique in the first
|
||||
six characters for portability reasons.
|
||||
Don't use global variables at all; anything that must be used in another
|
||||
module should be put into parameters (there'll be some large structs passed
|
||||
around for this purpose).
|
||||
|
||||
4. Source file names should also begin with "j"; remember to keep them to
|
||||
eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
|
||||
Do not put code for both compression and decompression into the same source
|
||||
file.
|
276
egetopt.c
Normal file
276
egetopt.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* egetopt.c -- Extended 'getopt'.
|
||||
*
|
||||
* A while back, a public-domain version of getopt() was posted to the
|
||||
* net. A bit later, a gentleman by the name of Keith Bostic made some
|
||||
* enhancements and reposted it.
|
||||
*
|
||||
* In recent weeks (i.e., early-to-mid 1988) there's been some
|
||||
* heated discussion in comp.lang.c about the merits and drawbacks
|
||||
* of getopt(), especially with regard to its handling of '?'.
|
||||
*
|
||||
* In light of this, I have taken Mr. Bostic's public-domain getopt()
|
||||
* and have made some changes that I hope will be considered to be
|
||||
* improvements. I call this routine 'egetopt' ("Extended getopt").
|
||||
* The default behavior of this routine is the same as that of getopt(),
|
||||
* but it has some optional features that make it more useful. These
|
||||
* options are controlled by the settings of some global variables.
|
||||
* By not setting any of these extra global variables, you will have
|
||||
* the same functionality as getopt(), which should satisfy those
|
||||
* purists who believe getopt() is perfect and can never be improved.
|
||||
* If, on the other hand, you are someone who isn't satisfied with the
|
||||
* status quo, egetopt() may very well give you the added capabilities
|
||||
* you want.
|
||||
*
|
||||
* Look at the enclosed README file for a description of egetopt()'s
|
||||
* new features.
|
||||
*
|
||||
* The code was originally posted to the net as getopt.c by ...
|
||||
*
|
||||
* Keith Bostic
|
||||
* ARPA: keith@seismo
|
||||
* UUCP: seismo!keith
|
||||
*
|
||||
* Current version: added enhancements and comments, reformatted code.
|
||||
*
|
||||
* Lloyd Zusman
|
||||
* Master Byte Software
|
||||
* Los Gatos, California
|
||||
* Internet: ljz@fx.com
|
||||
* UUCP: ...!ames!fxgrp!ljz
|
||||
*
|
||||
* May, 1988
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you want, include stdio.h or something where EOF and NULL are defined.
|
||||
* However, egetopt() is written so as not to need stdio.h, which should
|
||||
* make it significantly smaller on some systems.
|
||||
*/
|
||||
|
||||
#ifndef EOF
|
||||
# define EOF (-1)
|
||||
#endif /* ! EOF */
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL (char *)0
|
||||
#endif /* ! NULL */
|
||||
|
||||
/*
|
||||
* None of these constants are referenced in the executable portion of
|
||||
* the code ... their sole purpose is to initialize global variables.
|
||||
*/
|
||||
#define BADCH (int)'?'
|
||||
#define NEEDSEP (int)':'
|
||||
#define MAYBESEP (int)'\0'
|
||||
#define ERRFD 2
|
||||
#define EMSG ""
|
||||
#define START "-"
|
||||
|
||||
/*
|
||||
* Here are all the pertinent global variables.
|
||||
*/
|
||||
int opterr = 1; /* if true, output error message */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt; /* character checked for validity */
|
||||
int optbad = BADCH; /* character returned on error */
|
||||
int optchar = 0; /* character that begins returned option */
|
||||
int optneed = NEEDSEP; /* flag for mandatory argument */
|
||||
int optmaybe = MAYBESEP;/* flag for optional argument */
|
||||
int opterrfd = ERRFD; /* file descriptor for error text */
|
||||
char *optarg; /* argument associated with option */
|
||||
char *optstart = START; /* list of characters that start options */
|
||||
|
||||
|
||||
/*
|
||||
* Macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Conditionally print out an error message and return (depends on the
|
||||
* setting of 'opterr' and 'opterrfd'). Note that this version of
|
||||
* TELL() doesn't require the existence of stdio.h.
|
||||
*/
|
||||
#define TELL(S) { \
|
||||
if (opterr && opterrfd >= 0) { \
|
||||
char option = optopt; \
|
||||
write(opterrfd, *nargv, strlen(*nargv)); \
|
||||
write(opterrfd, (S), strlen(S)); \
|
||||
write(opterrfd, &option, 1); \
|
||||
write(opterrfd, "\n", 1); \
|
||||
} \
|
||||
return (optbad); \
|
||||
}
|
||||
|
||||
/*
|
||||
* This works similarly to index() and strchr(). I include it so that you
|
||||
* don't need to be concerned as to which one your system has.
|
||||
*/
|
||||
static char *
|
||||
_sindex(string, ch)
|
||||
char *string;
|
||||
int ch;
|
||||
{
|
||||
if (string != NULL) {
|
||||
for (; *string != '\0'; ++string) {
|
||||
if (*string == (char)ch) {
|
||||
return (string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here it is:
|
||||
*/
|
||||
int
|
||||
egetopt(nargc, nargv, ostr)
|
||||
int nargc;
|
||||
char **nargv;
|
||||
char *ostr;
|
||||
{
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
register char *oli; /* option letter list index */
|
||||
register char *osi = NULL; /* option start list index */
|
||||
|
||||
if (nargv == (char **)NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
if (nargc <= optind || nargv[optind] == NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
if (place == NULL) {
|
||||
place = EMSG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update scanning pointer.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
place = nargv[optind];
|
||||
if (place == NULL) {
|
||||
return (EOF);
|
||||
}
|
||||
osi = _sindex(optstart, *place);
|
||||
if (osi != NULL) {
|
||||
optchar = (int)*osi;
|
||||
}
|
||||
if (optind >= nargc || osi == NULL || *++place == '\0') {
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Two adjacent, identical flag characters were found.
|
||||
* This takes care of "--", for example.
|
||||
*/
|
||||
if (*place == place[-1]) {
|
||||
++optind;
|
||||
return (EOF);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the option is a separator or the option isn't in the list,
|
||||
* we've got an error.
|
||||
*/
|
||||
optopt = (int)*place++;
|
||||
oli = _sindex(ostr, optopt);
|
||||
if (optopt == optneed || optopt == optmaybe || oli == NULL) {
|
||||
/*
|
||||
* If we're at the end of the current argument, bump the
|
||||
* argument index.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
++optind;
|
||||
}
|
||||
TELL(": illegal option -- "); /* byebye */
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no argument indicator, then we don't even try to
|
||||
* return an argument.
|
||||
*/
|
||||
++oli;
|
||||
if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
|
||||
/*
|
||||
* If we're at the end of the current argument, bump the
|
||||
* argument index.
|
||||
*/
|
||||
if (*place == '\0') {
|
||||
++optind;
|
||||
}
|
||||
optarg = NULL;
|
||||
}
|
||||
/*
|
||||
* If we're here, there's an argument indicator. It's handled
|
||||
* differently depending on whether it's a mandatory or an
|
||||
* optional argument.
|
||||
*/
|
||||
else {
|
||||
/*
|
||||
* If there's no white space, use the rest of the
|
||||
* string as the argument. In this case, it doesn't
|
||||
* matter if the argument is mandatory or optional.
|
||||
*/
|
||||
if (*place != '\0') {
|
||||
optarg = place;
|
||||
}
|
||||
/*
|
||||
* If we're here, there's whitespace after the option.
|
||||
*
|
||||
* Is it a mandatory argument? If so, return the
|
||||
* next command-line argument if there is one.
|
||||
*/
|
||||
else if (*oli == optneed) {
|
||||
/*
|
||||
* If we're at the end of the argument list, there
|
||||
* isn't an argument and hence we have an error.
|
||||
* Otherwise, make 'optarg' point to the argument.
|
||||
*/
|
||||
if (nargc <= ++optind) {
|
||||
place = EMSG;
|
||||
TELL(": option requires an argument -- ");
|
||||
}
|
||||
else {
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we're here it must have been an optional argument.
|
||||
*/
|
||||
else {
|
||||
if (nargc <= ++optind) {
|
||||
place = EMSG;
|
||||
optarg = NULL;
|
||||
}
|
||||
else {
|
||||
optarg = nargv[optind];
|
||||
if (optarg == NULL) {
|
||||
place = EMSG;
|
||||
}
|
||||
/*
|
||||
* If the next item begins with a flag
|
||||
* character, we treat it like a new
|
||||
* argument. This is accomplished by
|
||||
* decrementing 'optind' and returning
|
||||
* a null argument.
|
||||
*/
|
||||
else if (_sindex(optstart, *optarg) != NULL) {
|
||||
--optind;
|
||||
optarg = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return option letter.
|
||||
*/
|
||||
return (optopt);
|
||||
}
|
120
jbsmooth.c
Normal file
120
jbsmooth.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* jbsmooth.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains cross-block smoothing routines.
|
||||
* These routines are invoked via the smooth_coefficients method.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* Cross-block coefficient smoothing.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
smooth_coefficients (decompress_info_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
JBLOCKROW above,
|
||||
JBLOCKROW currow,
|
||||
JBLOCKROW below,
|
||||
JBLOCKROW output)
|
||||
{
|
||||
QUANT_TBL_PTR Qptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
|
||||
long blocks_in_row = compptr->subsampled_width / DCTSIZE;
|
||||
long col;
|
||||
|
||||
/* First, copy the block row as-is.
|
||||
* This takes care of the first & last blocks in the row, the top/bottom
|
||||
* special cases, and the higher-order coefficients in each block.
|
||||
*/
|
||||
jcopy_block_row(currow, output, blocks_in_row);
|
||||
|
||||
/* Now apply the smoothing calculation, but not to any blocks on the
|
||||
* edges of the image.
|
||||
*/
|
||||
|
||||
if (above != NULL && below != NULL) {
|
||||
for (col = 1; col < blocks_in_row-1; col++) {
|
||||
|
||||
/* See section 13.10 of JPEG-8-R8, or K.8 of JPEG-9-R6.
|
||||
*
|
||||
* As I understand it, this produces approximations
|
||||
* for the low frequency AC components, based on the
|
||||
* DC values of the block and its eight neighboring blocks.
|
||||
* (Thus it can't be used for blocks on the image edges.)
|
||||
*/
|
||||
|
||||
/* The layout of these variables corresponds to
|
||||
* the text in 13.10
|
||||
*/
|
||||
|
||||
JCOEF DC1, DC2, DC3;
|
||||
JCOEF DC4, DC5, DC6;
|
||||
JCOEF DC7, DC8, DC9;
|
||||
|
||||
long AC01, AC02;
|
||||
long AC10, AC11;
|
||||
long AC20;
|
||||
|
||||
DC1 = above [col-1][0];
|
||||
DC2 = above [col ][0];
|
||||
DC3 = above [col+1][0];
|
||||
DC4 = currow[col-1][0];
|
||||
DC5 = currow[col ][0];
|
||||
DC6 = currow[col+1][0];
|
||||
DC7 = below [col-1][0];
|
||||
DC8 = below [col ][0];
|
||||
DC9 = below [col+1][0];
|
||||
|
||||
#define DIVIDE_256(x) x = ( (x) < 0 ? -((128-(x))/256) : ((x)+128)/256 )
|
||||
|
||||
AC01 = (36 * (DC4 - DC6));
|
||||
DIVIDE_256(AC01);
|
||||
AC10 = (36 * (DC2 - DC8));
|
||||
DIVIDE_256(AC10);
|
||||
AC20 = (9 * (DC2 + DC8 - 2*DC5));
|
||||
DIVIDE_256(AC20);
|
||||
AC11 = (5 * ((DC1 - DC3) - (DC7 - DC9)));
|
||||
DIVIDE_256(AC11);
|
||||
AC02 = (9 * (DC4 + DC6 - 2*DC5));
|
||||
DIVIDE_256(AC02);
|
||||
|
||||
/* I think that this checks to see if the quantisation
|
||||
* on the transmitting side would have produced this
|
||||
* answer. If so, then we use our (hopefully better)
|
||||
* estimate.
|
||||
*/
|
||||
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
#define COND_ASSIGN(_ac,_n,_z) if ((ABS(output[col][_n] - (_ac))<<1) <= Qptr[_z]) output[col][_n] = (_ac)
|
||||
|
||||
COND_ASSIGN(AC01, 1, 1);
|
||||
COND_ASSIGN(AC02, 2, 5);
|
||||
COND_ASSIGN(AC10, 8, 2);
|
||||
COND_ASSIGN(AC11, 9, 4);
|
||||
COND_ASSIGN(AC20, 16, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for cross-block smoothing.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselbsmooth (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* just one implementation for now */
|
||||
cinfo->methods->smooth_coefficients = smooth_coefficients;
|
||||
}
|
||||
|
||||
#endif /* BLOCK_SMOOTHING_SUPPORTED */
|
42
jcarith.c
Normal file
42
jcarith.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* jcarith.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains arithmetic entropy encoding routines.
|
||||
* These routines are invoked via the methods entropy_encode,
|
||||
* entropy_encoder_init/term, and entropy_optimize.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef ARITH_CODING_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* The arithmetic coding option of the JPEG standard specifies Q-coding,
|
||||
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
|
||||
* At this time it does not appear to be legal for the Independent JPEG
|
||||
* Group to distribute software that implements arithmetic coding.
|
||||
* We have therefore removed arithmetic coding support from the
|
||||
* distributed source code.
|
||||
*
|
||||
* We're not happy about it either.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for arithmetic entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselcarithmetic (compress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ARITH_CODING_SUPPORTED */
|
203
jccolor.c
Normal file
203
jccolor.c
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* jccolor.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains input colorspace conversion routines.
|
||||
* These routines are invoked via the methods get_sample_rows
|
||||
* and colorin_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for colorspace conversion.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
colorin_init (compress_info_ptr cinfo)
|
||||
{
|
||||
/* Allocate a workspace for the result of get_input_row. */
|
||||
pixel_row = (*cinfo->emethods->alloc_small_sarray)
|
||||
(cinfo->image_width, (long) cinfo->input_components);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fetch some rows of pixels from get_input_row and convert to the
|
||||
* JPEG colorspace.
|
||||
* This version handles RGB -> YCbCr conversion.
|
||||
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
||||
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_rgb_ycc_rows (compress_info_ptr cinfo,
|
||||
int rows_to_read, JSAMPIMAGE image_data)
|
||||
{
|
||||
register INT32 r, g, b;
|
||||
register JSAMPROW inptr0, inptr1, inptr2;
|
||||
register JSAMPROW outptr0, outptr1, outptr2;
|
||||
register long col;
|
||||
long width = cinfo->image_width;
|
||||
int row;
|
||||
|
||||
for (row = 0; row < rows_to_read; row++) {
|
||||
/* Read one row from the source file */
|
||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
||||
/* Convert colorspace */
|
||||
inptr0 = pixel_row[0];
|
||||
inptr1 = pixel_row[1];
|
||||
inptr2 = pixel_row[2];
|
||||
outptr0 = image_data[0][row];
|
||||
outptr1 = image_data[1][row];
|
||||
outptr2 = image_data[2][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
r = GETJSAMPLE(*inptr0++);
|
||||
g = GETJSAMPLE(*inptr1++);
|
||||
b = GETJSAMPLE(*inptr2++);
|
||||
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||
* must be too; do not need an explicit range-limiting operation.
|
||||
*/
|
||||
/* Y */
|
||||
*outptr0++ = ( 306*r + 601*g + 117*b + (INT32) 512) >> 10;
|
||||
/* Cb */
|
||||
*outptr1++ = ((-173)*r - 339*g + 512*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10;
|
||||
/* Cr */
|
||||
*outptr2++ = ( 512*r - 429*g - 83*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fetch some rows of pixels from get_input_row and convert to the
|
||||
* JPEG colorspace.
|
||||
* This version handles grayscale (no conversion).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_grayscale_rows (compress_info_ptr cinfo,
|
||||
int rows_to_read, JSAMPIMAGE image_data)
|
||||
{
|
||||
int row;
|
||||
|
||||
for (row = 0; row < rows_to_read; row++) {
|
||||
/* Read one row from the source file */
|
||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
||||
/* Convert colorspace (gamma mapping needed here) */
|
||||
jcopy_sample_rows(pixel_row, 0, image_data[0], row,
|
||||
1, cinfo->image_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fetch some rows of pixels from get_input_row and convert to the
|
||||
* JPEG colorspace.
|
||||
* This version handles multi-component colorspaces without conversion.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_noconvert_rows (compress_info_ptr cinfo,
|
||||
int rows_to_read, JSAMPIMAGE image_data)
|
||||
{
|
||||
int row, ci;
|
||||
|
||||
for (row = 0; row < rows_to_read; row++) {
|
||||
/* Read one row from the source file */
|
||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
||||
/* Convert colorspace (gamma mapping needed here) */
|
||||
for (ci = 0; ci < cinfo->input_components; ci++) {
|
||||
jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
|
||||
1, cinfo->image_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
colorin_term (compress_info_ptr cinfo)
|
||||
{
|
||||
/* Release the workspace. */
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(pixel_row, (long) cinfo->input_components);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for input colorspace conversion.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselccolor (compress_info_ptr cinfo)
|
||||
{
|
||||
/* Make sure input_components agrees with in_color_space */
|
||||
switch (cinfo->in_color_space) {
|
||||
case CS_GRAYSCALE:
|
||||
if (cinfo->input_components != 1)
|
||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
||||
break;
|
||||
|
||||
case CS_RGB:
|
||||
if (cinfo->input_components != 3)
|
||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
||||
break;
|
||||
|
||||
case CS_CMYK:
|
||||
if (cinfo->input_components != 4)
|
||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported input colorspace");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check num_components, set conversion method based on requested space */
|
||||
switch (cinfo->jpeg_color_space) {
|
||||
case CS_GRAYSCALE:
|
||||
if (cinfo->num_components != 1)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
if (cinfo->in_color_space == CS_GRAYSCALE)
|
||||
cinfo->methods->get_sample_rows = get_grayscale_rows;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
case CS_YCbCr:
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
if (cinfo->in_color_space == CS_RGB)
|
||||
cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
case CS_CMYK:
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
if (cinfo->in_color_space == CS_CMYK)
|
||||
cinfo->methods->get_sample_rows = get_noconvert_rows;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
|
||||
break;
|
||||
}
|
||||
|
||||
cinfo->methods->colorin_init = colorin_init;
|
||||
cinfo->methods->colorin_term = colorin_term;
|
||||
}
|
364
jcdeflts.c
Normal file
364
jcdeflts.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* jcdeflts.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains optional default-setting code for the JPEG compressor.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
LOCAL void
|
||||
add_huff_table (compress_info_ptr cinfo,
|
||||
HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
|
||||
/* Define a Huffman table */
|
||||
{
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
|
||||
|
||||
memcpy((void *) (*htblptr)->bits, (void *) bits,
|
||||
SIZEOF((*htblptr)->bits));
|
||||
memcpy((void *) (*htblptr)->huffval, (void *) val,
|
||||
SIZEOF((*htblptr)->huffval));
|
||||
|
||||
/* Initialize sent_table FALSE so table will be written to JPEG file.
|
||||
* In an application where we are writing non-interchange JPEG files,
|
||||
* it might be desirable to save space by leaving default Huffman tables
|
||||
* out of the file. To do that, just initialize sent_table = TRUE...
|
||||
*/
|
||||
|
||||
(*htblptr)->sent_table = FALSE;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
std_huff_tables (compress_info_ptr cinfo)
|
||||
/* Set up the standard Huffman tables (cf. JPEG-8-R8 section 13.3) */
|
||||
{
|
||||
static const UINT8 dc_luminance_bits[17] =
|
||||
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static const UINT8 dc_luminance_val[] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
|
||||
static const UINT8 dc_chrominance_bits[17] =
|
||||
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const UINT8 dc_chrominance_val[] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
|
||||
static const UINT8 ac_luminance_bits[17] =
|
||||
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
|
||||
static const UINT8 ac_luminance_val[] =
|
||||
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
|
||||
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
|
||||
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
|
||||
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
|
||||
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
|
||||
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
||||
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
||||
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
||||
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
|
||||
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
|
||||
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
|
||||
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
|
||||
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
|
||||
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa };
|
||||
|
||||
static const UINT8 ac_chrominance_bits[17] =
|
||||
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
|
||||
static const UINT8 ac_chrominance_val[] =
|
||||
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
|
||||
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
|
||||
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
|
||||
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
|
||||
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
|
||||
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
|
||||
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
|
||||
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
|
||||
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
|
||||
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
|
||||
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
|
||||
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
|
||||
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa };
|
||||
|
||||
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
|
||||
dc_luminance_bits, dc_luminance_val);
|
||||
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
|
||||
ac_luminance_bits, ac_luminance_val);
|
||||
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
|
||||
dc_chrominance_bits, dc_chrominance_val);
|
||||
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
|
||||
ac_chrominance_bits, ac_chrominance_val);
|
||||
}
|
||||
|
||||
|
||||
/* This is the sample quantization table given in JPEG-8-R8 sec 13.1,
|
||||
* but expressed in zigzag order (as are all of our quant. tables).
|
||||
* The spec says that the values given produce "good" quality, and
|
||||
* when divided by 2, "very good" quality. (These two settings are
|
||||
* selected by quality=50 and quality=75 in j_set_quality, below.)
|
||||
*/
|
||||
|
||||
|
||||
static const QUANT_VAL std_luminance_quant_tbl[DCTSIZE2] = {
|
||||
16, 11, 12, 14, 12, 10, 16, 14,
|
||||
13, 14, 18, 17, 16, 19, 24, 40,
|
||||
26, 24, 22, 22, 24, 49, 35, 37,
|
||||
29, 40, 58, 51, 61, 60, 57, 51,
|
||||
56, 55, 64, 72, 92, 78, 64, 68,
|
||||
87, 69, 55, 56, 80, 109, 81, 87,
|
||||
95, 98, 103, 104, 103, 62, 77, 113,
|
||||
121, 112, 100, 120, 92, 101, 103, 99
|
||||
};
|
||||
|
||||
static const QUANT_VAL std_chrominance_quant_tbl[DCTSIZE2] = {
|
||||
17, 18, 18, 24, 21, 24, 47, 26,
|
||||
26, 47, 99, 66, 56, 66, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
};
|
||||
|
||||
|
||||
LOCAL void
|
||||
add_quant_table (compress_info_ptr cinfo, int which_tbl,
|
||||
const QUANT_VAL *basic_table, int scale_factor,
|
||||
boolean force_baseline)
|
||||
/* Define a quantization table equal to the basic_table times */
|
||||
/* a scale factor (given as a percentage) */
|
||||
{
|
||||
QUANT_TBL_PTR * qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
|
||||
int i;
|
||||
long temp;
|
||||
|
||||
if (*qtblptr == NULL)
|
||||
*qtblptr = (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
|
||||
/* limit the values to the valid range */
|
||||
if (temp <= 0L) temp = 1L;
|
||||
#ifdef EIGHT_BIT_SAMPLES
|
||||
if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */
|
||||
#else
|
||||
if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */
|
||||
#endif
|
||||
if (force_baseline && temp > 255L)
|
||||
temp = 255L; /* limit to baseline range if requested */
|
||||
(*qtblptr)[i] = (QUANT_VAL) temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
|
||||
/* Set or change the 'quality' (quantization) setting. */
|
||||
/* The 'quality' factor should be 0 (terrible) to 100 (very good). */
|
||||
/* Quality 50 corresponds to the JPEG basic tables given above; */
|
||||
/* quality 100 results in no quantization scaling at all. */
|
||||
/* If force_baseline is TRUE, quantization table entries are limited */
|
||||
/* to 0..255 for JPEG baseline compatibility; this is only an issue */
|
||||
/* for quality settings below 24. */
|
||||
{
|
||||
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
|
||||
if (quality <= 0) quality = 1;
|
||||
if (quality > 100) quality = 100;
|
||||
|
||||
/* Convert quality rating to a percentage scaling of the basic tables.
|
||||
* The basic table is used as-is (scaling 100) for a quality of 50.
|
||||
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
|
||||
* note that at Q=100 the scaling is 0, which will cause add_quant_table
|
||||
* to make all the table entries 1 (hence, no quantization loss).
|
||||
* Qualities 1..50 are converted to scaling percentage 5000/Q.
|
||||
*/
|
||||
if (quality < 50)
|
||||
quality = 5000 / quality;
|
||||
else
|
||||
quality = 200 - quality*2;
|
||||
|
||||
/* Set up two quantization tables using the specified quality scaling */
|
||||
add_quant_table(cinfo, 0, std_luminance_quant_tbl, quality, force_baseline);
|
||||
add_quant_table(cinfo, 1, std_chrominance_quant_tbl, quality, force_baseline);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Default parameter setup for compression.
|
||||
*
|
||||
* User interfaces that don't choose to use this routine must do their
|
||||
* own setup of all these parameters. Alternately, you can call this
|
||||
* to establish defaults and then alter parameters selectively.
|
||||
*
|
||||
* See above for the meaning of the 'quality' parameter. Typically,
|
||||
* the application's default quality setting will be passed to this
|
||||
* routine. A later call on j_set_quality() can be used to change to
|
||||
* a user-specified quality setting.
|
||||
*
|
||||
* This sets up for a color image; to output a grayscale image,
|
||||
* do this first and call j_monochrome_default() afterwards.
|
||||
* (The latter can be called within c_ui_method_selection, so the
|
||||
* choice can depend on the input file header.)
|
||||
* Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr,
|
||||
* you should also change the component ID codes, and you should NOT emit
|
||||
* a JFIF header (set write_JFIF_header = FALSE).
|
||||
*
|
||||
* CAUTION: if you want to compress multiple images per run, it's safest
|
||||
* to call j_default_compression before *each* call to jpeg_compress (and
|
||||
* j_free_defaults afterwards). If this isn't practical, you'll have to
|
||||
* be careful to reset any individual parameters that may change during
|
||||
* the compression run. The main thing you need to worry about as this
|
||||
* is written is that the sent_table boolean in each Huffman table must
|
||||
* be reset to FALSE before each compression; otherwise, Huffman tables
|
||||
* won't get emitted for the second and subsequent images.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
j_default_compression (compress_info_ptr cinfo, int quality)
|
||||
/* NB: the external methods must already be set up. */
|
||||
{
|
||||
short i;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Initialize pointers as needed to mark stuff unallocated. */
|
||||
cinfo->comp_info = NULL;
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||
}
|
||||
|
||||
cinfo->data_precision = 8; /* default; can be overridden by input_init */
|
||||
cinfo->density_unit = 0; /* Pixel size is unknown by default */
|
||||
cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
|
||||
cinfo->Y_density = 1;
|
||||
|
||||
cinfo->input_gamma = 1.0; /* no gamma correction by default */
|
||||
|
||||
/* Prepare three color components; first is luminance which is also usable */
|
||||
/* for grayscale. The others are assumed to be UV or similar chrominance. */
|
||||
cinfo->write_JFIF_header = TRUE;
|
||||
cinfo->jpeg_color_space = CS_YCbCr;
|
||||
cinfo->num_components = 3;
|
||||
cinfo->comp_info = (*cinfo->emethods->alloc_small)
|
||||
(4 * SIZEOF(jpeg_component_info));
|
||||
/* Note: we allocate a 4-entry comp_info array so that user interface can
|
||||
* easily change over to CMYK color space if desired.
|
||||
*/
|
||||
|
||||
compptr = &cinfo->comp_info[0];
|
||||
compptr->component_index = 0;
|
||||
compptr->component_id = 1; /* JFIF specifies IDs 1,2,3 */
|
||||
compptr->h_samp_factor = 2; /* default to 2x2 subsamples of chrominance */
|
||||
compptr->v_samp_factor = 2;
|
||||
compptr->quant_tbl_no = 0; /* use tables 0 for luminance */
|
||||
compptr->dc_tbl_no = 0;
|
||||
compptr->ac_tbl_no = 0;
|
||||
|
||||
compptr = &cinfo->comp_info[1];
|
||||
compptr->component_index = 1;
|
||||
compptr->component_id = 2;
|
||||
compptr->h_samp_factor = 1;
|
||||
compptr->v_samp_factor = 1;
|
||||
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
|
||||
compptr->dc_tbl_no = 1;
|
||||
compptr->ac_tbl_no = 1;
|
||||
|
||||
compptr = &cinfo->comp_info[2];
|
||||
compptr->component_index = 2;
|
||||
compptr->component_id = 3;
|
||||
compptr->h_samp_factor = 1;
|
||||
compptr->v_samp_factor = 1;
|
||||
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
|
||||
compptr->dc_tbl_no = 1;
|
||||
compptr->ac_tbl_no = 1;
|
||||
|
||||
/* Set up two quantization tables using the specified quality scaling */
|
||||
/* Baseline compatibility is forced (a nonissue for reasonable defaults) */
|
||||
j_set_quality(cinfo, quality, TRUE);
|
||||
|
||||
/* Set up two Huffman tables in case user interface wants Huffman coding */
|
||||
std_huff_tables(cinfo);
|
||||
|
||||
/* Initialize default arithmetic coding conditioning */
|
||||
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
||||
cinfo->arith_dc_L[i] = 0;
|
||||
cinfo->arith_dc_U[i] = 1;
|
||||
cinfo->arith_ac_K[i] = 5;
|
||||
}
|
||||
|
||||
/* Use Huffman coding, not arithmetic coding, by default */
|
||||
cinfo->arith_code = FALSE;
|
||||
|
||||
/* Color images are interleaved by default */
|
||||
cinfo->interleave = TRUE;
|
||||
|
||||
/* By default, don't do extra passes to optimize entropy coding */
|
||||
cinfo->optimize_coding = FALSE;
|
||||
|
||||
/* By default, use the simpler non-cosited sampling alignment */
|
||||
cinfo->CCIR601_sampling = FALSE;
|
||||
|
||||
/* No restart markers */
|
||||
cinfo->restart_interval = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLOBAL void
|
||||
j_monochrome_default (compress_info_ptr cinfo)
|
||||
/* Change the j_default_compression() values to emit a monochrome JPEG file. */
|
||||
{
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
cinfo->jpeg_color_space = CS_GRAYSCALE;
|
||||
cinfo->num_components = 1;
|
||||
/* Set single component to 1x1 subsampling */
|
||||
compptr = &cinfo->comp_info[0];
|
||||
compptr->h_samp_factor = 1;
|
||||
compptr->v_samp_factor = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This routine releases storage allocated by j_default_compression.
|
||||
* Note that freeing the method pointer structs and the compress_info_struct
|
||||
* itself are the responsibility of the user interface.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
j_free_defaults (compress_info_ptr cinfo)
|
||||
{
|
||||
short i;
|
||||
|
||||
#define FREE(ptr) if ((ptr) != NULL) \
|
||||
(*cinfo->emethods->free_small) ((void *) ptr)
|
||||
|
||||
FREE(cinfo->comp_info);
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
FREE(cinfo->quant_tbl_ptrs[i]);
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
FREE(cinfo->dc_huff_tbl_ptrs[i]);
|
||||
FREE(cinfo->ac_huff_tbl_ptrs[i]);
|
||||
}
|
||||
}
|
75
jcexpand.c
Normal file
75
jcexpand.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* jcexpand.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains image edge-expansion routines.
|
||||
* These routines are invoked via the edge_expand method.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* Expand an image so that it is a multiple of the MCU dimensions.
|
||||
* This is to be accomplished by duplicating the rightmost column
|
||||
* and/or bottommost row of pixels. The image has not yet been
|
||||
* subsampled, so all components have the same dimensions.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
edge_expand (compress_info_ptr cinfo,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPIMAGE image_data)
|
||||
{
|
||||
/* Expand horizontally */
|
||||
if (input_cols < output_cols) {
|
||||
register JSAMPROW ptr;
|
||||
register JSAMPLE pixval;
|
||||
register long count;
|
||||
register int row;
|
||||
short ci;
|
||||
long numcols = output_cols - input_cols;
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
for (row = 0; row < input_rows; row++) {
|
||||
ptr = image_data[ci][row] + (input_cols-1);
|
||||
pixval = GETJSAMPLE(*ptr++);
|
||||
for (count = numcols; count > 0; count--)
|
||||
*ptr++ = pixval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand vertically */
|
||||
/* This happens only once at the bottom of the image, */
|
||||
/* so it needn't be super-efficient */
|
||||
if (input_rows < output_rows) {
|
||||
register int row;
|
||||
short ci;
|
||||
JSAMPARRAY this_component;
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
this_component = image_data[ci];
|
||||
for (row = input_rows; row < output_rows; row++) {
|
||||
jcopy_sample_rows(this_component, input_rows-1, this_component, row,
|
||||
1, output_cols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for edge expansion.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselexpand (compress_info_ptr cinfo)
|
||||
{
|
||||
/* just one implementation for now */
|
||||
cinfo->methods->edge_expand = edge_expand;
|
||||
}
|
689
jchuff.c
Normal file
689
jchuff.c
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
* jchuff.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy encoding routines.
|
||||
* These routines are invoked via the methods entropy_encode,
|
||||
* entropy_encoder_init/term, and entropy_optimize.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/* Static variables to avoid passing 'round extra parameters */
|
||||
|
||||
static compress_info_ptr cinfo;
|
||||
|
||||
static INT32 huff_put_buffer; /* current bit-accumulation buffer */
|
||||
static int huff_put_bits; /* # of bits now in it */
|
||||
|
||||
static char * output_buffer; /* output buffer */
|
||||
static int bytes_in_buffer;
|
||||
|
||||
|
||||
|
||||
LOCAL void
|
||||
fix_huff_tbl (HUFF_TBL * htbl)
|
||||
/* Compute derived values for a Huffman table */
|
||||
{
|
||||
int p, i, l, lastp, si;
|
||||
char huffsize[257];
|
||||
UINT16 huffcode[257];
|
||||
UINT16 code;
|
||||
|
||||
/* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
for (i = 1; i <= htbl->bits[l]; i++)
|
||||
huffsize[p++] = l;
|
||||
}
|
||||
huffsize[p] = 0;
|
||||
lastp = p;
|
||||
|
||||
/* Figure 7.3.5.4.2.2: generate the codes themselves */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
code = 0;
|
||||
si = huffsize[0];
|
||||
p = 0;
|
||||
while (huffsize[p]) {
|
||||
while (huffsize[p] == si) {
|
||||
huffcode[p++] = code;
|
||||
code++;
|
||||
}
|
||||
code <<= 1;
|
||||
si++;
|
||||
}
|
||||
|
||||
/* Figure 7.3.5.4.2.3: generate encoding tables */
|
||||
/* These are code and size indexed by symbol value */
|
||||
|
||||
for (p = 0; p < lastp; p++) {
|
||||
htbl->ehufco[htbl->huffval[p]] = huffcode[p];
|
||||
htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
|
||||
}
|
||||
|
||||
/* Figure 13.4.2.3.1: generate decoding tables */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
if (htbl->bits[l]) {
|
||||
htbl->valptr[l] = p; /* huffval[] index of 1st sym of code len l */
|
||||
htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
|
||||
p += htbl->bits[l];
|
||||
htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
|
||||
} else {
|
||||
htbl->maxcode[l] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Outputting bytes to the file */
|
||||
|
||||
LOCAL void
|
||||
flush_bytes (void)
|
||||
{
|
||||
if (bytes_in_buffer)
|
||||
(*cinfo->methods->entropy_output) (cinfo, output_buffer, bytes_in_buffer);
|
||||
bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
|
||||
#define emit_byte(val) ((bytes_in_buffer >= JPEG_BUF_SIZE ? \
|
||||
(flush_bytes(), 0) : 0), \
|
||||
output_buffer[bytes_in_buffer] = (val), \
|
||||
bytes_in_buffer++)
|
||||
|
||||
|
||||
|
||||
/* Outputting bits to the file */
|
||||
|
||||
/* Only the right 24 bits of huff_put_buffer are used; the valid bits are
|
||||
* left-justified in this part. At most 16 bits can be passed to emit_bits
|
||||
* in one call, and we never retain more than 7 bits in huff_put_buffer
|
||||
* between calls, so 24 bits are sufficient.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
emit_bits (UINT16 code, int size)
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding tightly. */
|
||||
register INT32 put_buffer = code;
|
||||
register int put_bits = huff_put_bits;
|
||||
|
||||
put_buffer &= (((INT32) 1) << size) - 1; /* Mask off any excess bits in code */
|
||||
|
||||
put_bits += size; /* new number of bits in buffer */
|
||||
|
||||
put_buffer <<= 24 - put_bits; /* align incoming bits */
|
||||
|
||||
put_buffer |= huff_put_buffer; /* and merge with old buffer contents */
|
||||
|
||||
while (put_bits >= 8) {
|
||||
int c = (int) ((put_buffer >> 16) & 0xFF);
|
||||
|
||||
emit_byte(c);
|
||||
if (c == 0xFF) { /* need to stuff a zero byte? */
|
||||
emit_byte(0);
|
||||
}
|
||||
put_buffer <<= 8;
|
||||
put_bits -= 8;
|
||||
}
|
||||
|
||||
huff_put_buffer = put_buffer; /* Update global variables */
|
||||
huff_put_bits = put_bits;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
flush_bits (void)
|
||||
{
|
||||
emit_bits((UINT16) 0x7F, 7); /* fill any partial byte with ones */
|
||||
huff_put_buffer = 0; /* and reset bit-buffer to empty */
|
||||
huff_put_bits = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Encode a single block's worth of coefficients */
|
||||
/* Note that the DC coefficient has already been converted to a difference */
|
||||
|
||||
LOCAL void
|
||||
encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
|
||||
{
|
||||
register INT32 temp;
|
||||
register int nbits;
|
||||
register int k, r, i;
|
||||
|
||||
/* Encode the DC coefficient difference per section 7.3.5.1 */
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
temp = block[0];
|
||||
if (temp < 0) temp = -temp;
|
||||
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
emit_bits(dctbl->ehufco[nbits], dctbl->ehufsi[nbits]);
|
||||
|
||||
/* If positive, emit nbits low order bits; */
|
||||
/* if negative, emit nbits low order bits of value-1 */
|
||||
if ((temp = block[0]) < 0)
|
||||
temp--;
|
||||
|
||||
emit_bits((UINT16) temp, nbits);
|
||||
|
||||
/* Encode the AC coefficients per section 7.3.5.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[k]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
emit_bits(actbl->ehufco[0xF0], actbl->ehufsi[0xF0]);
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
if (temp < 0) temp = -temp;
|
||||
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while (temp >>= 1)
|
||||
nbits++;
|
||||
|
||||
/* Emit Huffman symbol for run length / number of bits */
|
||||
i = (r << 4) + nbits;
|
||||
emit_bits(actbl->ehufco[i], actbl->ehufsi[i]);
|
||||
|
||||
/* If positive, emit nbits low order bits; */
|
||||
/* if negative, emit nbits low order bits of value-1 */
|
||||
if ((temp = block[k]) < 0)
|
||||
temp--;
|
||||
|
||||
emit_bits((UINT16) temp, nbits);
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
emit_bits(actbl->ehufco[0], actbl->ehufsi[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
* This is invoked after writing the SOS marker.
|
||||
* The pipeline controller must establish the entropy_output method pointer
|
||||
* before calling this routine.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_init (compress_info_ptr xinfo)
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Initialize static variables */
|
||||
cinfo = xinfo;
|
||||
huff_put_buffer = 0;
|
||||
huff_put_bits = 0;
|
||||
|
||||
/* Initialize the output buffer */
|
||||
output_buffer = (char *) (*cinfo->emethods->alloc_small)
|
||||
((size_t) JPEG_BUF_SIZE);
|
||||
bytes_in_buffer = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Make sure requested tables are present */
|
||||
if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
|
||||
cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
|
||||
ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for same table, but it's not a big deal */
|
||||
fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
|
||||
fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
|
||||
/* Initialize DC predictions to 0 */
|
||||
cinfo->last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Initialize restart stuff */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
cinfo->next_restart_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emit a restart marker & resynchronize predictions.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
emit_restart (compress_info_ptr cinfo)
|
||||
{
|
||||
short ci;
|
||||
|
||||
flush_bits();
|
||||
|
||||
emit_byte(0xFF);
|
||||
emit_byte(RST0 + cinfo->next_restart_num);
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
cinfo->last_dc_val[ci] = 0;
|
||||
|
||||
/* Update restart state */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
cinfo->next_restart_num++;
|
||||
cinfo->next_restart_num &= 7;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode and output one MCU's worth of Huffman-compressed coefficients.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_encode (compress_info_ptr cinfo, JBLOCK *MCU_data)
|
||||
{
|
||||
short blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
JCOEF temp;
|
||||
|
||||
/* Account for restart interval, emit restart marker if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (cinfo->restarts_to_go == 0)
|
||||
emit_restart(cinfo);
|
||||
cinfo->restarts_to_go--;
|
||||
}
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Convert DC value to difference, update last_dc_val */
|
||||
temp = MCU_data[blkn][0];
|
||||
MCU_data[blkn][0] -= cinfo->last_dc_val[ci];
|
||||
cinfo->last_dc_val[ci] = temp;
|
||||
encode_one_block(MCU_data[blkn],
|
||||
cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no],
|
||||
cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_term (compress_info_ptr cinfo)
|
||||
{
|
||||
/* Flush out the last data */
|
||||
flush_bits();
|
||||
flush_bytes();
|
||||
/* Release the I/O buffer */
|
||||
(*cinfo->emethods->free_small) ((void *) output_buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Huffman coding optimization.
|
||||
*
|
||||
* This actually is optimization, in the sense that we find the best possible
|
||||
* Huffman table(s) for the given data. We first scan the supplied data and
|
||||
* count the number of uses of each symbol that is to be Huffman-coded.
|
||||
* (This process must agree with the code above.) Then we build an
|
||||
* optimal Huffman coding tree for the observed counts.
|
||||
*/
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
|
||||
/* These are static so htest_one_block can find 'em */
|
||||
static long * dc_count_ptrs[NUM_HUFF_TBLS];
|
||||
static long * ac_count_ptrs[NUM_HUFF_TBLS];
|
||||
|
||||
|
||||
LOCAL void
|
||||
gen_huff_coding (compress_info_ptr cinfo, HUFF_TBL *htbl, long freq[])
|
||||
/* Generate the optimal coding for the given counts */
|
||||
{
|
||||
#define MAX_CLEN 32 /* assumed maximum initial code length */
|
||||
UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
|
||||
short codesize[257]; /* codesize[k] = code length of symbol k */
|
||||
short others[257]; /* next symbol in current branch of tree */
|
||||
int c1, c2;
|
||||
int p, i, j;
|
||||
long v;
|
||||
|
||||
/* This algorithm is explained in section 13.2 of JPEG-8-R8 */
|
||||
|
||||
MEMZERO((void *) bits, SIZEOF(bits));
|
||||
MEMZERO((void *) codesize, SIZEOF(codesize));
|
||||
for (i = 0; i < 257; i++)
|
||||
others[i] = -1; /* init links to empty */
|
||||
|
||||
freq[256] = 1; /* make sure there is a nonzero count */
|
||||
/* including the pseudo-symbol 256 in the Huffman procedure guarantees
|
||||
* that no real symbol is given code-value of all ones, because 256
|
||||
* will be placed in the largest codeword category.
|
||||
*/
|
||||
|
||||
/* Huffman's basic algorithm to assign optimal code lengths to symbols */
|
||||
|
||||
for (;;) {
|
||||
/* Find the smallest nonzero frequency, set c1 = its symbol */
|
||||
/* In case of ties, take the larger symbol number */
|
||||
c1 = -1;
|
||||
v = 1000000000L;
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (freq[i] && freq[i] <= v) {
|
||||
v = freq[i];
|
||||
c1 = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next smallest nonzero frequency, set c2 = its symbol */
|
||||
/* In case of ties, take the larger symbol number */
|
||||
c2 = -1;
|
||||
v = 1000000000L;
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (freq[i] && freq[i] <= v && i != c1) {
|
||||
v = freq[i];
|
||||
c2 = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Done if we've merged everything into one frequency */
|
||||
if (c2 < 0)
|
||||
break;
|
||||
|
||||
/* Else merge the two counts/trees */
|
||||
freq[c1] += freq[c2];
|
||||
freq[c2] = 0;
|
||||
|
||||
/* Increment the codesize of everything in c1's tree branch */
|
||||
codesize[c1]++;
|
||||
while (others[c1] >= 0) {
|
||||
c1 = others[c1];
|
||||
codesize[c1]++;
|
||||
}
|
||||
|
||||
others[c1] = c2; /* chain c2 onto c1's tree branch */
|
||||
|
||||
/* Increment the codesize of everything in c2's tree branch */
|
||||
codesize[c2]++;
|
||||
while (others[c2] >= 0) {
|
||||
c2 = others[c2];
|
||||
codesize[c2]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now count the number of symbols of each code length */
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (codesize[i]) {
|
||||
/* The JPEG standard seems to think that this can't happen, */
|
||||
/* but I'm paranoid... */
|
||||
if (codesize[i] > MAX_CLEN)
|
||||
ERREXIT(cinfo->emethods, "Huffman code size table overflow");
|
||||
|
||||
bits[codesize[i]]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
|
||||
* Huffman procedure assigned any such lengths, we must adjust the coding.
|
||||
* Here is what the JPEG spec says about how this next bit works:
|
||||
* Since symbols are paired for the longest Huffman code, the symbols are
|
||||
* removed from this length category two at a time. The prefix for the pair
|
||||
* (which is one bit shorter) is allocated to one of the pair; then,
|
||||
* skipping the BITS entry for that prefix length, a code word from the next
|
||||
* shortest nonzero BITS entry is converted into a prefix for two code words
|
||||
* one bit longer.
|
||||
*/
|
||||
|
||||
for (i = MAX_CLEN; i > 16; i--) {
|
||||
while (bits[i] > 0) {
|
||||
j = i - 2; /* find length of new prefix to be used */
|
||||
while (bits[j] == 0)
|
||||
j--;
|
||||
|
||||
bits[i] -= 2; /* remove two symbols */
|
||||
bits[i-1]++; /* one goes in this length */
|
||||
bits[j+1] += 2; /* two new symbols in this length */
|
||||
bits[j]--; /* symbol of this length is now a prefix */
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the count for the pseudo-symbol 256 from the largest codelength */
|
||||
while (bits[i] == 0) /* find largest codelength still in use */
|
||||
i--;
|
||||
bits[i]--;
|
||||
|
||||
/* Return final symbol counts (only for lengths 0..16) */
|
||||
memcpy((void *) htbl->bits, (void *) bits, SIZEOF(htbl->bits));
|
||||
|
||||
/* Return a list of the symbols sorted by code length */
|
||||
/* It's not real clear to me why we don't need to consider the codelength
|
||||
* changes made above, but the JPEG spec seems to think this works.
|
||||
*/
|
||||
p = 0;
|
||||
for (i = 1; i <= MAX_CLEN; i++) {
|
||||
for (j = 0; j <= 255; j++) {
|
||||
if (codesize[j] == i) {
|
||||
htbl->huffval[p] = j;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Process a single block's worth of coefficients */
|
||||
/* Note that the DC coefficient has already been converted to a difference */
|
||||
|
||||
LOCAL void
|
||||
htest_one_block (JBLOCK block, JCOEF block0,
|
||||
long dc_counts[], long ac_counts[])
|
||||
{
|
||||
register INT32 temp;
|
||||
register int nbits;
|
||||
register int k, r;
|
||||
|
||||
/* Encode the DC coefficient difference per section 7.3.5.1 */
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
temp = block0;
|
||||
if (temp < 0) temp = -temp;
|
||||
|
||||
for (nbits = 0; temp; nbits++)
|
||||
temp >>= 1;
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[nbits]++;
|
||||
|
||||
/* Encode the AC coefficients per section 7.3.5.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[k]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
ac_counts[0xF0]++;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
if (temp < 0) temp = -temp;
|
||||
|
||||
for (nbits = 0; temp; nbits++)
|
||||
temp >>= 1;
|
||||
|
||||
/* Count Huffman symbol for run length / number of bits */
|
||||
ac_counts[(r << 4) + nbits]++;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
ac_counts[0]++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Trial-encode one MCU's worth of Huffman-compressed coefficients.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
htest_encode (compress_info_ptr cinfo, JBLOCK *MCU_data)
|
||||
{
|
||||
short blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Take care of restart intervals if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (cinfo->restarts_to_go == 0) {
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
cinfo->last_dc_val[ci] = 0;
|
||||
/* Update restart state */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
cinfo->restarts_to_go--;
|
||||
}
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* NB: unlike the real entropy encoder, we may not change the input data */
|
||||
htest_one_block(MCU_data[blkn],
|
||||
(JCOEF) (MCU_data[blkn][0] - cinfo->last_dc_val[ci]),
|
||||
dc_count_ptrs[compptr->dc_tbl_no],
|
||||
ac_count_ptrs[compptr->ac_tbl_no]);
|
||||
cinfo->last_dc_val[ci] = MCU_data[blkn][0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Find the best coding parameters for a Huffman-coded scan.
|
||||
* When called, the scan data has already been converted to a sequence of
|
||||
* MCU groups of quantized coefficients, which are stored in a "big" array.
|
||||
* The source_method knows how to iterate through that array.
|
||||
* On return, the MCU data is unmodified, but the Huffman tables referenced
|
||||
* by the scan components may have been altered.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_optimize (compress_info_ptr cinfo, MCU_output_caller_ptr source_method)
|
||||
/* Optimize Huffman-coding parameters (Huffman symbol table) */
|
||||
{
|
||||
int i, tbl;
|
||||
HUFF_TBL **htblptr;
|
||||
|
||||
/* Allocate and zero the count tables */
|
||||
/* Note that gen_huff_coding expects 257 entries in each table! */
|
||||
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
dc_count_ptrs[i] = NULL;
|
||||
ac_count_ptrs[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
/* Create DC table */
|
||||
tbl = cinfo->cur_comp_info[i]->dc_tbl_no;
|
||||
if (dc_count_ptrs[tbl] == NULL) {
|
||||
dc_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small)
|
||||
(257 * SIZEOF(long));
|
||||
MEMZERO((void *) dc_count_ptrs[tbl], 257 * SIZEOF(long));
|
||||
}
|
||||
/* Create AC table */
|
||||
tbl = cinfo->cur_comp_info[i]->ac_tbl_no;
|
||||
if (ac_count_ptrs[tbl] == NULL) {
|
||||
ac_count_ptrs[tbl] = (long *) (*cinfo->emethods->alloc_small)
|
||||
(257 * SIZEOF(long));
|
||||
MEMZERO((void *) ac_count_ptrs[tbl], 257 * SIZEOF(long));
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize DC predictions to 0 */
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
cinfo->last_dc_val[i] = 0;
|
||||
}
|
||||
/* Initialize restart stuff */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
|
||||
/* Scan the MCU data, count symbol uses */
|
||||
(*source_method) (cinfo, htest_encode);
|
||||
|
||||
/* Now generate optimal Huffman tables */
|
||||
for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) {
|
||||
if (dc_count_ptrs[tbl] != NULL) {
|
||||
htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
|
||||
/* Set sent_table FALSE so updated table will be written to JPEG file. */
|
||||
(*htblptr)->sent_table = FALSE;
|
||||
/* Compute the optimal Huffman encoding */
|
||||
gen_huff_coding(cinfo, *htblptr, dc_count_ptrs[tbl]);
|
||||
/* Release the count table */
|
||||
(*cinfo->emethods->free_small) ((void *) dc_count_ptrs[tbl]);
|
||||
}
|
||||
if (ac_count_ptrs[tbl] != NULL) {
|
||||
htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
|
||||
/* Set sent_table FALSE so updated table will be written to JPEG file. */
|
||||
(*htblptr)->sent_table = FALSE;
|
||||
/* Compute the optimal Huffman encoding */
|
||||
gen_huff_coding(cinfo, *htblptr, ac_count_ptrs[tbl]);
|
||||
/* Release the count table */
|
||||
(*cinfo->emethods->free_small) ((void *) ac_count_ptrs[tbl]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for Huffman entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselchuffman (compress_info_ptr cinfo)
|
||||
{
|
||||
if (! cinfo->arith_code) {
|
||||
cinfo->methods->entropy_encoder_init = huff_init;
|
||||
cinfo->methods->entropy_encode = huff_encode;
|
||||
cinfo->methods->entropy_encoder_term = huff_term;
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
cinfo->methods->entropy_optimize = huff_optimize;
|
||||
#endif
|
||||
}
|
||||
}
|
272
jcmain.c
Normal file
272
jcmain.c
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* jcmain.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a trivial test user interface for the JPEG compressor.
|
||||
* It should work on any system with Unix- or MS-DOS-style command lines.
|
||||
*
|
||||
* Two different command line styles are permitted, depending on the
|
||||
* compile-time switch TWO_FILE_COMMANDLINE:
|
||||
* cjpeg [options] inputfile outputfile
|
||||
* cjpeg [options] [inputfile]
|
||||
* In the second style, output is always to standard output, which you'd
|
||||
* normally redirect to a file or pipe to some other program. Input is
|
||||
* either from a named file or from standard input (typically redirected).
|
||||
* The second style is convenient on Unix but is unhelpful on systems that
|
||||
* don't support pipes. Also, you MUST use the first style if your system
|
||||
* doesn't do binary I/O to stdin/stdout.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h> /* to declare exit() */
|
||||
#endif
|
||||
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* command-line reader for Macintosh */
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#define WRITE_BINARY "w"
|
||||
#else
|
||||
#define READ_BINARY "rb"
|
||||
#define WRITE_BINARY "wb"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* If your system has getopt(3), you can use your library version by
|
||||
* defining HAVE_GETOPT. By default, we use the PD 'egetopt'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_GETOPT
|
||||
extern int getopt PP((int argc, char **argv, char *optstring));
|
||||
extern char * optarg;
|
||||
extern int optind;
|
||||
#else
|
||||
#include "egetopt.c"
|
||||
#define getopt(argc,argv,opt) egetopt(argc,argv,opt)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This routine determines what format the input file is,
|
||||
* and selects the appropriate input-reading module.
|
||||
*
|
||||
* To determine which family of input formats the file belongs to,
|
||||
* we look only at the first byte of the file, since C does not
|
||||
* guarantee that more than one character can be pushed back with ungetc.
|
||||
* This is sufficient for the currently envisioned set of input formats.
|
||||
*
|
||||
* If you need to look at more than one character to select an input module,
|
||||
* you can either
|
||||
* 1) assume you can fseek() the input file (may fail for piped input);
|
||||
* 2) assume you can push back more than one character (works in
|
||||
* some C implementations, but unportable);
|
||||
* or 3) don't put back the data, and modify the various input_init
|
||||
* methods to assume they start reading after the start of file.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
select_file_type (compress_info_ptr cinfo)
|
||||
{
|
||||
int c;
|
||||
|
||||
if ((c = getc(cinfo->input_file)) == EOF)
|
||||
ERREXIT(cinfo->emethods, "Empty input file");
|
||||
|
||||
switch (c) {
|
||||
#ifdef GIF_SUPPORTED
|
||||
case 'G':
|
||||
jselrgif(cinfo);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PPM_SUPPORTED
|
||||
case 'P':
|
||||
jselrppm(cinfo);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported input file format");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ungetc(c, cinfo->input_file) == EOF)
|
||||
ERREXIT(cinfo->emethods, "ungetc failed");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine gets control after the input file header has been read.
|
||||
* It must determine what output JPEG file format is to be written,
|
||||
* and make any other compression parameter changes that are desirable.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
c_ui_method_selection (compress_info_ptr cinfo)
|
||||
{
|
||||
/* If the input is gray scale, generate a monochrome JPEG file. */
|
||||
if (cinfo->in_color_space == CS_GRAYSCALE)
|
||||
j_monochrome_default(cinfo);
|
||||
/* For now, always select JFIF output format. */
|
||||
#ifdef JFIF_SUPPORTED
|
||||
jselwjfif(cinfo);
|
||||
#else
|
||||
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
usage (char * progname)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "usage: %s ", progname);
|
||||
fprintf(stderr, "[-I] [-Q quality 0..100] [-a] [-o] [-d]");
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, " inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, " [inputfile]\n");
|
||||
#endif
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct compress_info_struct cinfo;
|
||||
struct compress_methods_struct c_methods;
|
||||
struct external_methods_struct e_methods;
|
||||
int c;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef THINK_C
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
/* Initialize the system-dependent method pointers. */
|
||||
cinfo.methods = &c_methods;
|
||||
cinfo.emethods = &e_methods;
|
||||
jselerror(&e_methods); /* error/trace message routines */
|
||||
jselvirtmem(&e_methods); /* memory allocation routines */
|
||||
c_methods.c_ui_method_selection = c_ui_method_selection;
|
||||
|
||||
/* Set up default input and output file references. */
|
||||
/* (These may be overridden below.) */
|
||||
cinfo.input_file = stdin;
|
||||
cinfo.output_file = stdout;
|
||||
|
||||
/* Set up default parameters. */
|
||||
e_methods.trace_level = 0;
|
||||
j_default_compression(&cinfo, 75); /* default quality level */
|
||||
|
||||
/* Scan parameters */
|
||||
|
||||
while ((c = getopt(argc, argv, "IQ:aod")) != EOF)
|
||||
switch (c) {
|
||||
case 'I': /* Create noninterleaved file. */
|
||||
#ifdef MULTISCAN_FILES_SUPPORTED
|
||||
cinfo.interleave = FALSE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
|
||||
argv[0]);
|
||||
exit(2);
|
||||
#endif
|
||||
break;
|
||||
case 'Q': /* Quality factor. */
|
||||
{ int val;
|
||||
if (optarg == NULL)
|
||||
usage(argv[0]);
|
||||
if (sscanf(optarg, "%d", &val) != 1)
|
||||
usage(argv[0]);
|
||||
/* Note: for now, we leave force_baseline FALSE.
|
||||
* In a production user interface, probably should make it TRUE
|
||||
* unless overridden by a separate switch.
|
||||
*/
|
||||
j_set_quality(&cinfo, val, FALSE);
|
||||
}
|
||||
break;
|
||||
case 'a': /* Use arithmetic coding. */
|
||||
#ifdef ARITH_CODING_SUPPORTED
|
||||
cinfo.arith_code = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
||||
argv[0]);
|
||||
exit(2);
|
||||
#endif
|
||||
break;
|
||||
case 'o': /* Enable entropy parm optimization. */
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
cinfo.optimize_coding = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
||||
argv[0]);
|
||||
exit(2);
|
||||
#endif
|
||||
break;
|
||||
case 'd': /* Debugging. */
|
||||
e_methods.trace_level++;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Select the input and output files */
|
||||
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
|
||||
if (optind != argc-2) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
|
||||
usage(argv[0]);
|
||||
}
|
||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
||||
exit(2);
|
||||
}
|
||||
if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#else /* not TWO_FILE_COMMANDLINE -- use Unix style */
|
||||
|
||||
if (optind < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", argv[0]);
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (optind < argc) {
|
||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TWO_FILE_COMMANDLINE */
|
||||
|
||||
/* Figure out the input file format, and set up to read it. */
|
||||
select_file_type(&cinfo);
|
||||
|
||||
/* Do it to it! */
|
||||
jpeg_compress(&cinfo);
|
||||
|
||||
/* Release memory. */
|
||||
j_free_defaults(&cinfo);
|
||||
#ifdef MEM_STATS
|
||||
if (e_methods.trace_level > 0)
|
||||
j_mem_stats();
|
||||
#endif
|
||||
|
||||
/* All done. */
|
||||
exit(0);
|
||||
}
|
127
jcmaster.c
Normal file
127
jcmaster.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* jcmaster.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the main control for the JPEG compressor.
|
||||
* The system-dependent (user interface) code should call jpeg_compress()
|
||||
* after doing appropriate setup of the compress_info_struct parameter.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
METHODDEF void
|
||||
c_per_scan_method_selection (compress_info_ptr cinfo)
|
||||
/* Central point for per-scan method selection */
|
||||
{
|
||||
/* Edge expansion */
|
||||
jselexpand(cinfo);
|
||||
/* Subsampling of pixels */
|
||||
jselsubsample(cinfo);
|
||||
/* MCU extraction */
|
||||
jselcmcu(cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
c_initial_method_selection (compress_info_ptr cinfo)
|
||||
/* Central point for initial method selection */
|
||||
{
|
||||
/* Input image reading method selection is already done. */
|
||||
/* So is output file header formatting (both are done by user interface). */
|
||||
|
||||
/* Gamma and color space conversion */
|
||||
jselccolor(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
#ifdef ARITH_CODING_SUPPORTED
|
||||
jselcarithmetic(cinfo);
|
||||
#else
|
||||
cinfo->arith_code = FALSE; /* force Huffman mode */
|
||||
#endif
|
||||
jselchuffman(cinfo);
|
||||
/* Pipeline control */
|
||||
jselcpipeline(cinfo);
|
||||
/* Overall control (that's me!) */
|
||||
cinfo->methods->c_per_scan_method_selection = c_per_scan_method_selection;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
initial_setup (compress_info_ptr cinfo)
|
||||
/* Do computations that are needed before initial method selection */
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Compute maximum sampling factors; check factor validity */
|
||||
cinfo->max_h_samp_factor = 1;
|
||||
cinfo->max_v_samp_factor = 1;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
||||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||
ERREXIT(cinfo->emethods, "Bogus sampling factors");
|
||||
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||
compptr->h_samp_factor);
|
||||
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||
compptr->v_samp_factor);
|
||||
|
||||
}
|
||||
|
||||
/* Compute logical subsampled dimensions of components */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
|
||||
+ cinfo->max_h_samp_factor - 1)
|
||||
/ cinfo->max_h_samp_factor;
|
||||
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
|
||||
+ cinfo->max_v_samp_factor - 1)
|
||||
/ cinfo->max_v_samp_factor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the main entry point to the JPEG compressor.
|
||||
*/
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jpeg_compress (compress_info_ptr cinfo)
|
||||
{
|
||||
/* Read the input file header: determine image size & component count.
|
||||
* NOTE: the user interface must have initialized the input_init method
|
||||
* pointer (eg, by calling jselrppm) before calling me.
|
||||
* The other file reading methods (get_input_row etc.) were probably
|
||||
* set at the same time, but could be set up by input_init itself,
|
||||
* or by c_ui_method_selection.
|
||||
*/
|
||||
(*cinfo->methods->input_init) (cinfo);
|
||||
|
||||
/* Give UI a chance to adjust compression parameters and select */
|
||||
/* output file format based on results of input_init. */
|
||||
(*cinfo->methods->c_ui_method_selection) (cinfo);
|
||||
|
||||
/* Now select methods for compression steps. */
|
||||
initial_setup(cinfo);
|
||||
c_initial_method_selection(cinfo);
|
||||
|
||||
/* Initialize the output file & other modules as needed */
|
||||
/* (entropy_encoder is inited by pipeline controller) */
|
||||
|
||||
(*cinfo->methods->colorin_init) (cinfo);
|
||||
(*cinfo->methods->write_file_header) (cinfo);
|
||||
|
||||
/* And let the pipeline controller do the rest. */
|
||||
(*cinfo->methods->c_pipeline_controller) (cinfo);
|
||||
|
||||
/* Finish output file, release working storage, etc */
|
||||
(*cinfo->methods->write_file_trailer) (cinfo);
|
||||
(*cinfo->methods->colorin_term) (cinfo);
|
||||
(*cinfo->methods->input_term) (cinfo);
|
||||
|
||||
/* My, that was easy, wasn't it? */
|
||||
}
|
212
jcmcu.c
Normal file
212
jcmcu.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* jcmcu.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains MCU extraction routines and quantization scaling.
|
||||
* These routines are invoked via the extract_MCUs and
|
||||
* extract_init/term methods.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* If this file is compiled with -DDCT_ERR_STATS, it will reverse-DCT each
|
||||
* block and sum the total errors across the whole picture. This provides
|
||||
* a convenient method of using real picture data to test the roundoff error
|
||||
* of a DCT algorithm. DCT_ERR_STATS should *not* be defined for a production
|
||||
* compression program, since compression is much slower with it defined.
|
||||
* Also note that jrevdct.o must be linked into the compressor when this
|
||||
* switch is defined.
|
||||
*/
|
||||
|
||||
#ifdef DCT_ERR_STATS
|
||||
static int dcterrorsum; /* these hold the error statistics */
|
||||
static int dcterrormax;
|
||||
static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine */
|
||||
#endif
|
||||
|
||||
|
||||
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
|
||||
|
||||
static const short ZAG[DCTSIZE2] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
||||
|
||||
|
||||
LOCAL void
|
||||
extract_block (JSAMPARRAY input_data, int start_row, long start_col,
|
||||
JBLOCK output_data, QUANT_TBL_PTR quanttbl)
|
||||
/* Extract one 8x8 block from the specified location in the sample array; */
|
||||
/* perform forward DCT, quantization scaling, and zigzag reordering on it. */
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding it tightly. */
|
||||
DCTBLOCK block;
|
||||
#ifdef DCT_ERR_STATS
|
||||
DCTBLOCK svblock; /* saves input data for comparison */
|
||||
#endif
|
||||
|
||||
{ register JSAMPROW elemptr;
|
||||
register DCTELEM *localblkptr = block;
|
||||
#if DCTSIZE != 8
|
||||
register short elemc;
|
||||
#endif
|
||||
register short elemr;
|
||||
|
||||
for (elemr = DCTSIZE; elemr > 0; elemr--) {
|
||||
elemptr = input_data[start_row++] + start_col;
|
||||
#if DCTSIZE == 8 /* unroll the inner loop */
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
#else
|
||||
for (elemc = DCTSIZE; elemc > 0; elemc--) {
|
||||
*localblkptr++ = (DCTELEM) GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DCT_ERR_STATS
|
||||
memcpy((void *) svblock, (void *) block, SIZEOF(DCTBLOCK));
|
||||
#endif
|
||||
|
||||
j_fwd_dct(block);
|
||||
|
||||
{ register JCOEF temp;
|
||||
register short i;
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
temp = (JCOEF) block[ZAG[i]];
|
||||
/* divide by *quanttbl, ensuring proper rounding */
|
||||
if (temp < 0) {
|
||||
temp = -temp;
|
||||
temp += *quanttbl>>1;
|
||||
temp /= *quanttbl;
|
||||
temp = -temp;
|
||||
} else {
|
||||
temp += *quanttbl>>1;
|
||||
temp /= *quanttbl;
|
||||
}
|
||||
*output_data++ = temp;
|
||||
quanttbl++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DCT_ERR_STATS
|
||||
j_rev_dct(block);
|
||||
|
||||
{ register int diff;
|
||||
register short i;
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
diff = block[i] - svblock[i];
|
||||
if (diff < 0) diff = -diff;
|
||||
dcterrorsum += diff;
|
||||
if (dcterrormax < diff) dcterrormax = diff;
|
||||
}
|
||||
dctcoefcount += DCTSIZE2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extract samples in MCU order, process & hand off to output_method.
|
||||
* The input is always exactly N MCU rows worth of data.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
extract_MCUs (compress_info_ptr cinfo,
|
||||
JSAMPIMAGE image_data,
|
||||
int num_mcu_rows,
|
||||
MCU_output_method_ptr output_method)
|
||||
{
|
||||
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
|
||||
int mcurow;
|
||||
long mcuindex;
|
||||
short blkn, ci, xpos, ypos;
|
||||
jpeg_component_info * compptr;
|
||||
QUANT_TBL_PTR quant_ptr;
|
||||
|
||||
for (mcurow = 0; mcurow < num_mcu_rows; mcurow++) {
|
||||
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
|
||||
/* Extract data from the image array, DCT it, and quantize it */
|
||||
blkn = 0;
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
|
||||
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
|
||||
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
|
||||
extract_block(image_data[ci],
|
||||
(mcurow * compptr->MCU_height + ypos)*DCTSIZE,
|
||||
(mcuindex * compptr->MCU_width + xpos)*DCTSIZE,
|
||||
MCU_data[blkn], quant_ptr);
|
||||
blkn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Send the MCU whereever the pipeline controller wants it to go */
|
||||
(*output_method) (cinfo, MCU_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for processing a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
extract_init (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
#ifdef DCT_ERR_STATS
|
||||
dcterrorsum = dcterrormax = dctcoefcount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clean up after a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
extract_term (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
#ifdef DCT_ERR_STATS
|
||||
TRACEMS3(cinfo->emethods, 0, "DCT roundoff errors = %d/%d, max = %d",
|
||||
dcterrorsum, dctcoefcount, dcterrormax);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for MCU extraction.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselcmcu (compress_info_ptr cinfo)
|
||||
{
|
||||
/* just one implementation for now */
|
||||
cinfo->methods->extract_init = extract_init;
|
||||
cinfo->methods->extract_MCUs = extract_MCUs;
|
||||
cinfo->methods->extract_term = extract_term;
|
||||
}
|
320
jconfig.h
Normal file
320
jconfig.h
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* jconfig.h
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains preprocessor declarations that help customize
|
||||
* the JPEG software for a particular application, machine, or compiler.
|
||||
* Edit these declarations as needed (or add -D flags to the Makefile).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* These symbols indicate the properties of your machine or compiler.
|
||||
* The conditional definitions given may do the right thing already,
|
||||
* but you'd best look them over closely, especially if your compiler
|
||||
* does not handle full ANSI C. An ANSI-compliant C compiler should
|
||||
* provide all the necessary features; __STDC__ is supposed to be
|
||||
* predefined by such compilers.
|
||||
*/
|
||||
|
||||
/* Does your compiler support function prototypes? */
|
||||
/* (If not, you also need to use ansi2knr, see README) */
|
||||
|
||||
#ifdef __STDC__ /* ANSI C compilers always have prototypes */
|
||||
#define PROTO
|
||||
#else
|
||||
#ifdef __cplusplus /* So do C++ compilers */
|
||||
#define PROTO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Does your compiler support the declaration "unsigned char" ? */
|
||||
/* How about "unsigned short" ? */
|
||||
|
||||
#ifdef __STDC__ /* ANSI C compilers must support both */
|
||||
#define HAVE_UNSIGNED_CHAR
|
||||
#define HAVE_UNSIGNED_SHORT
|
||||
#endif
|
||||
|
||||
/* Define this if an ordinary "char" type is unsigned.
|
||||
* If you're not sure, leaving it undefined will work at some cost in speed.
|
||||
* If you defined HAVE_UNSIGNED_CHAR then it doesn't matter very much.
|
||||
*/
|
||||
|
||||
/* #define CHAR_IS_UNSIGNED */
|
||||
|
||||
/* Define this if your compiler implements ">>" on signed values as a logical
|
||||
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
|
||||
* which is the normal and rational definition.
|
||||
* The DCT and IDCT routines will compute wrong values if you get this wrong!
|
||||
*/
|
||||
|
||||
/* #define RIGHT_SHIFT_IS_UNSIGNED */
|
||||
|
||||
/* Define "void" as "char" if your compiler doesn't know about type void.
|
||||
* NOTE: be sure to define void such that "void *" represents the most general
|
||||
* pointer type, e.g., that returned by malloc().
|
||||
*/
|
||||
|
||||
/* #define void char */
|
||||
|
||||
/* Define const as empty if your compiler doesn't know the "const" keyword. */
|
||||
/* (Even if it does, defining const as empty won't break anything.) */
|
||||
|
||||
#ifndef __STDC__ /* ANSI C and C++ compilers should know it. */
|
||||
#ifndef __cplusplus
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
|
||||
* unless you are using a large-data memory model or 80386 flat-memory mode.
|
||||
* On less brain-damaged CPUs this symbol must not be defined.
|
||||
* (Defining this symbol causes large data structures to be referenced through
|
||||
* "far" pointers and to be allocated with a special version of malloc.)
|
||||
*/
|
||||
|
||||
#ifdef MSDOS /* Microsoft C and compatibles */
|
||||
#define NEED_FAR_POINTERS
|
||||
#else
|
||||
#ifdef __TURBOC__ /* Turbo C doesn't define MSDOS */
|
||||
#define NEED_FAR_POINTERS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* The next couple of symbols only affect the system-dependent user interface
|
||||
* modules (jcmain.c, jdmain.c). You can ignore these if you are supplying
|
||||
* your own user interface code.
|
||||
*/
|
||||
|
||||
/* Define this if you want to name both input and output files on the command
|
||||
* line, rather than using stdout and optionally stdin. You MUST do this if
|
||||
* your system can't cope with binary I/O to stdin/stdout. See comments at
|
||||
* head of jcmain.c or jdmain.c.
|
||||
*/
|
||||
|
||||
#ifdef MSDOS /* two-file style is needed for PCs */
|
||||
#define TWO_FILE_COMMANDLINE
|
||||
#else
|
||||
#ifdef __TURBOC__ /* Turbo C doesn't define MSDOS */
|
||||
#define TWO_FILE_COMMANDLINE
|
||||
#endif
|
||||
#endif
|
||||
#ifdef THINK_C /* needed for Macintosh too */
|
||||
#define TWO_FILE_COMMANDLINE
|
||||
#endif
|
||||
|
||||
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
|
||||
* This is necessary on systems that distinguish text files from binary files,
|
||||
* and is harmless on most systems that don't. If you have one of the rare
|
||||
* systems that complains about the "b" spec, define this symbol.
|
||||
*/
|
||||
|
||||
/* #define DONT_USE_B_MODE */
|
||||
|
||||
|
||||
/* If you're getting bored, that's the end of the symbols you HAVE to
|
||||
* worry about. Go fix the makefile and compile.
|
||||
*/
|
||||
|
||||
|
||||
/* If your compiler supports inline functions, define INLINE as
|
||||
* the inline keyword; otherwise define it as empty.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__ /* GNU C has inline... */
|
||||
#define INLINE inline
|
||||
#else /* ...but I don't think anyone else does. */
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
/* On a few systems, type boolean and/or macros FALSE, TRUE may appear
|
||||
* in standard header files. Or you may have conflicts with application-
|
||||
* specific header files that you want to include together with these files.
|
||||
* In that case you need only comment out these definitions.
|
||||
*/
|
||||
|
||||
typedef int boolean;
|
||||
#define FALSE 0 /* values of boolean */
|
||||
#define TRUE 1
|
||||
|
||||
/* This defines the size of the I/O buffers for entropy compression
|
||||
* and decompression; you could reduce it if memory is tight.
|
||||
*/
|
||||
|
||||
#define JPEG_BUF_SIZE 4096 /* bytes */
|
||||
|
||||
|
||||
|
||||
/* These symbols determine the JPEG functionality supported. */
|
||||
|
||||
/*
|
||||
* These defines indicate whether to include various optional functions.
|
||||
* Undefining some of these symbols will produce a smaller but less capable
|
||||
* program file. Note that you can leave certain source files out of the
|
||||
* compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
||||
*/
|
||||
|
||||
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
|
||||
#undef ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
||||
#define MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */
|
||||
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
|
||||
#undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? (not yet impl.) */
|
||||
/* these defines indicate which JPEG file formats are allowed */
|
||||
#define JFIF_SUPPORTED /* JFIF or "raw JPEG" files */
|
||||
#undef JTIFF_SUPPORTED /* JPEG-in-TIFF (not yet implemented) */
|
||||
/* these defines indicate which image (non-JPEG) file formats are allowed */
|
||||
#define PPM_SUPPORTED /* PPM/PGM image file format */
|
||||
#define GIF_SUPPORTED /* GIF image file format */
|
||||
#undef TIFF_SUPPORTED /* TIFF image file format (not yet impl.) */
|
||||
|
||||
/* more capability options later, no doubt */
|
||||
|
||||
|
||||
/*
|
||||
* Define exactly one of these three symbols to indicate whether you want
|
||||
* 8-bit, 12-bit, or 16-bit sample (pixel component) values. 8-bit is the
|
||||
* default and is nearly always the right thing to use. You can use 12-bit if
|
||||
* you need to support image formats with more than 8 bits of resolution in a
|
||||
* color value. 16-bit should only be used for the lossless JPEG mode (not
|
||||
* currently supported). Note that 12- and 16-bit values take up twice as
|
||||
* much memory as 8-bit!
|
||||
*/
|
||||
|
||||
#define EIGHT_BIT_SAMPLES
|
||||
#undef TWELVE_BIT_SAMPLES
|
||||
#undef SIXTEEN_BIT_SAMPLES
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The remaining definitions don't need to be hand-edited in most cases.
|
||||
* You may need to change these if you have a machine with unusual data
|
||||
* types; for example, "char" not 8 bits, "short" not 16 bits,
|
||||
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
|
||||
* but it had better be at least 16.
|
||||
*/
|
||||
|
||||
/* First define the representation of a single pixel element value. */
|
||||
|
||||
#ifdef EIGHT_BIT_SAMPLES
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
||||
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
||||
* If you have only signed chars, and you are more worried about speed than
|
||||
* memory usage, it might be a win to make JSAMPLE be short.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JSAMPLE;
|
||||
#define GETJSAMPLE(value) (value)
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
|
||||
typedef char JSAMPLE;
|
||||
#define GETJSAMPLE(value) (value)
|
||||
|
||||
#else /* not CHAR_IS_UNSIGNED */
|
||||
|
||||
typedef char JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((value) & 0xFF)
|
||||
|
||||
#endif /* CHAR_IS_UNSIGNED */
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
#define MAXJSAMPLE 255
|
||||
#define CENTERJSAMPLE 128
|
||||
|
||||
#endif /* EIGHT_BIT_SAMPLES */
|
||||
|
||||
|
||||
#ifdef TWELVE_BIT_SAMPLES
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..4095. */
|
||||
/* On nearly all machines "short" will do nicely. */
|
||||
|
||||
typedef short JSAMPLE;
|
||||
#define GETJSAMPLE(value) (value)
|
||||
|
||||
#define MAXJSAMPLE 4095
|
||||
#define CENTERJSAMPLE 2048
|
||||
|
||||
#endif /* TWELVE_BIT_SAMPLES */
|
||||
|
||||
|
||||
#ifdef SIXTEEN_BIT_SAMPLES
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
|
||||
typedef unsigned short JSAMPLE;
|
||||
#define GETJSAMPLE(value) (value)
|
||||
|
||||
#else /* not HAVE_UNSIGNED_SHORT */
|
||||
|
||||
/* If int is 32 bits this'll be horrendously inefficient storage-wise.
|
||||
* But since we don't actually support 16-bit samples (ie lossless coding) yet,
|
||||
* I'm not going to worry about making a smarter definition ...
|
||||
*/
|
||||
typedef unsigned int JSAMPLE;
|
||||
#define GETJSAMPLE(value) (value)
|
||||
|
||||
#endif /* HAVE_UNSIGNED_SHORT */
|
||||
|
||||
#define MAXJSAMPLE 65535
|
||||
#define CENTERJSAMPLE 32768
|
||||
|
||||
#endif /* SIXTEEN_BIT_SAMPLES */
|
||||
|
||||
|
||||
/* Here we define the representation of a DCT frequency coefficient.
|
||||
* This should be a signed 16-bit value; "short" is usually right.
|
||||
* It's important that this be exactly 16 bits, no more and no less;
|
||||
* more will cost you a BIG hit of memory, less will give wrong answers.
|
||||
*/
|
||||
|
||||
typedef short JCOEF;
|
||||
|
||||
|
||||
/* The remaining typedefs are used for various table entries and so forth.
|
||||
* They must be at least as wide as specified; but making them too big
|
||||
* won't cost a huge amount of memory, so we don't provide special
|
||||
* extraction code like we did for JSAMPLE. (In other words, these
|
||||
* typedefs live at a different point on the speed/space tradeoff curve.)
|
||||
*/
|
||||
|
||||
/* UINT8 must hold at least the values 0..255. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
typedef unsigned char UINT8;
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
typedef char UINT8;
|
||||
#else /* not CHAR_IS_UNSIGNED */
|
||||
typedef short UINT8;
|
||||
#endif /* CHAR_IS_UNSIGNED */
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
/* UINT16 must hold at least the values 0..65535. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
typedef unsigned short UINT16;
|
||||
#else /* not HAVE_UNSIGNED_SHORT */
|
||||
typedef unsigned int UINT16;
|
||||
#endif /* HAVE_UNSIGNED_SHORT */
|
||||
|
||||
/* INT16 must hold at least the values -32768..32767. */
|
||||
|
||||
typedef short INT16;
|
||||
|
||||
/* INT32 must hold signed 32-bit values; if your machine happens */
|
||||
/* to have 64-bit longs, you might want to change this. */
|
||||
|
||||
typedef long INT32;
|
715
jcpipe.c
Normal file
715
jcpipe.c
Normal file
@ -0,0 +1,715 @@
|
||||
/*
|
||||
* jcpipe.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains compression pipeline controllers.
|
||||
* These routines are invoked via the c_pipeline_controller method.
|
||||
*
|
||||
* There are four basic pipeline controllers, one for each combination of:
|
||||
* single-scan JPEG file (single component or fully interleaved)
|
||||
* vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
|
||||
*
|
||||
* optimization of entropy encoding parameters
|
||||
* vs. usage of default encoding parameters.
|
||||
*
|
||||
* Note that these conditions determine the needs for "big" arrays:
|
||||
* multiple scans imply a big array for splitting the color components;
|
||||
* entropy encoding optimization needs a big array for the MCU data.
|
||||
*
|
||||
* All but the simplest controller (single-scan, no optimization) can be
|
||||
* compiled out through configuration options, if you need to make a minimal
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* About the data structures:
|
||||
*
|
||||
* The processing chunk size for subsampling is referred to in this file as
|
||||
* a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
|
||||
* any component after subsampling, or Vmax (max_v_samp_factor) unsubsampled
|
||||
* rows. In an interleaved scan each MCU row contains exactly DCTSIZE row
|
||||
* groups of each component in the scan. In a noninterleaved scan an MCU row
|
||||
* is one row of blocks, which might not be an integral number of row groups;
|
||||
* for convenience we use a buffer of the same size as in interleaved scans,
|
||||
* and process Vk MCU rows in each burst of subsampling.
|
||||
* To provide context for the subsampling step, we have to retain the last
|
||||
* two row groups of the previous MCU row while reading in the next MCU row
|
||||
* (or set of Vk MCU rows). To do this without copying data about, we create
|
||||
* a rather strange data structure. Exactly DCTSIZE+2 row groups of samples
|
||||
* are allocated, but we create two different sets of pointers to this array.
|
||||
* The second set swaps the last two pairs of row groups. By working
|
||||
* alternately with the two sets of pointers, we can access the data in the
|
||||
* desired order.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Utility routines: common code for pipeline controllers
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
interleaved_scan_setup (compress_info_ptr cinfo)
|
||||
/* Compute all derived info for an interleaved (multi-component) scan */
|
||||
/* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
|
||||
{
|
||||
short ci, mcublks;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
|
||||
|
||||
cinfo->MCUs_per_row = (cinfo->image_width
|
||||
+ cinfo->max_h_samp_factor*DCTSIZE - 1)
|
||||
/ (cinfo->max_h_samp_factor*DCTSIZE);
|
||||
|
||||
cinfo->MCU_rows_in_scan = (cinfo->image_height
|
||||
+ cinfo->max_v_samp_factor*DCTSIZE - 1)
|
||||
/ (cinfo->max_v_samp_factor*DCTSIZE);
|
||||
|
||||
cinfo->blocks_in_MCU = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* for interleaved scan, sampling factors give # of blocks per component */
|
||||
compptr->MCU_width = compptr->h_samp_factor;
|
||||
compptr->MCU_height = compptr->v_samp_factor;
|
||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
/* compute physical dimensions of component */
|
||||
compptr->subsampled_width = jround_up(compptr->true_comp_width,
|
||||
(long) (compptr->MCU_width*DCTSIZE));
|
||||
compptr->subsampled_height = jround_up(compptr->true_comp_height,
|
||||
(long) (compptr->MCU_height*DCTSIZE));
|
||||
/* Sanity check */
|
||||
if (compptr->subsampled_width !=
|
||||
(cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
|
||||
ERREXIT(cinfo->emethods, "I'm confused about the image width");
|
||||
/* Prepare array describing MCU composition */
|
||||
mcublks = compptr->MCU_blocks;
|
||||
if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
|
||||
ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
|
||||
while (mcublks-- > 0) {
|
||||
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
noninterleaved_scan_setup (compress_info_ptr cinfo)
|
||||
/* Compute all derived info for a noninterleaved (single-component) scan */
|
||||
/* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
|
||||
{
|
||||
jpeg_component_info *compptr = cinfo->cur_comp_info[0];
|
||||
|
||||
/* for noninterleaved scan, always one block per MCU */
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_blocks = 1;
|
||||
/* compute physical dimensions of component */
|
||||
compptr->subsampled_width = jround_up(compptr->true_comp_width,
|
||||
(long) DCTSIZE);
|
||||
compptr->subsampled_height = jround_up(compptr->true_comp_height,
|
||||
(long) DCTSIZE);
|
||||
|
||||
cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
|
||||
cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
|
||||
|
||||
/* Prepare array describing MCU composition */
|
||||
cinfo->blocks_in_MCU = 1;
|
||||
cinfo->MCU_membership[0] = 0;
|
||||
|
||||
(*cinfo->methods->c_per_scan_method_selection) (cinfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOCAL void
|
||||
alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
|
||||
long fullsize_width)
|
||||
/* Create a pre-subsampling data buffer having the desired structure */
|
||||
/* (see comments at head of file) */
|
||||
{
|
||||
short ci, vs, i;
|
||||
|
||||
vs = cinfo->max_v_samp_factor; /* row group height */
|
||||
|
||||
/* Get top-level space for array pointers */
|
||||
fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
|
||||
(cinfo->num_components * SIZEOF(JSAMPARRAY));
|
||||
fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
|
||||
(cinfo->num_components * SIZEOF(JSAMPARRAY));
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
/* Allocate the real storage */
|
||||
fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
|
||||
(fullsize_width,
|
||||
(long) (vs * (DCTSIZE+2)));
|
||||
/* Create space for the scrambled-order pointers */
|
||||
fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
|
||||
(vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
|
||||
/* Duplicate the first DCTSIZE-2 row groups */
|
||||
for (i = 0; i < vs * (DCTSIZE-2); i++) {
|
||||
fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
|
||||
}
|
||||
/* Copy the last four row groups in swapped order */
|
||||
for (i = 0; i < vs * 2; i++) {
|
||||
fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
|
||||
fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
|
||||
/* Release a sampling buffer created by alloc_sampling_buffer */
|
||||
{
|
||||
short ci, vs;
|
||||
|
||||
vs = cinfo->max_v_samp_factor; /* row group height */
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
/* Free the real storage */
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(fullsize_data[0][ci], (long) (vs * (DCTSIZE+2)));
|
||||
/* Free the scrambled-order pointers */
|
||||
(*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
|
||||
}
|
||||
|
||||
/* Free the top-level space */
|
||||
(*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
|
||||
(*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
subsample (compress_info_ptr cinfo,
|
||||
JSAMPIMAGE fullsize_data, JSAMPIMAGE subsampled_data,
|
||||
long fullsize_width,
|
||||
short above, short current, short below, short out)
|
||||
/* Do subsampling of a single row group (of each component). */
|
||||
/* above, current, below are indexes of row groups in fullsize_data; */
|
||||
/* out is the index of the target row group in subsampled_data. */
|
||||
/* Special case: above, below can be -1 to indicate top, bottom of image. */
|
||||
{
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY above_ptr, below_ptr;
|
||||
JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
|
||||
short ci, vs, i;
|
||||
|
||||
vs = cinfo->max_v_samp_factor; /* row group height */
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = & cinfo->comp_info[ci];
|
||||
|
||||
if (above >= 0)
|
||||
above_ptr = fullsize_data[ci] + above * vs;
|
||||
else {
|
||||
/* Top of image: make a dummy above-context with copies of 1st row */
|
||||
/* We assume current=0 in this case */
|
||||
for (i = 0; i < vs; i++)
|
||||
dummy[i] = fullsize_data[ci][0];
|
||||
above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
|
||||
}
|
||||
|
||||
if (below >= 0)
|
||||
below_ptr = fullsize_data[ci] + below * vs;
|
||||
else {
|
||||
/* Bot of image: make a dummy below-context with copies of last row */
|
||||
for (i = 0; i < vs; i++)
|
||||
dummy[i] = fullsize_data[ci][(current+1)*vs-1];
|
||||
below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
|
||||
}
|
||||
|
||||
(*cinfo->methods->subsample[ci])
|
||||
(cinfo, (int) ci,
|
||||
fullsize_width, (int) vs,
|
||||
compptr->subsampled_width, (int) compptr->v_samp_factor,
|
||||
above_ptr,
|
||||
fullsize_data[ci] + current * vs,
|
||||
below_ptr,
|
||||
subsampled_data[ci] + out * compptr->v_samp_factor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* These vars are initialized by the pipeline controller for use by
|
||||
* MCU_output_catcher.
|
||||
* To avoid a lot of row-pointer overhead, we cram as many MCUs into each
|
||||
* row of whole_scan_MCUs as we can get without exceeding 64KB per row.
|
||||
*/
|
||||
|
||||
#define MAX_WHOLE_ROW_BLOCKS (65500 / SIZEOF(JBLOCK)) /* max blocks/row */
|
||||
|
||||
static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
|
||||
static int MCUs_in_big_row; /* # of MCUs in each row of whole_scan_MCUs */
|
||||
static long next_whole_row; /* next row to access in whole_scan_MCUs */
|
||||
static int next_MCU_index; /* next MCU in current row */
|
||||
|
||||
|
||||
METHODDEF void
|
||||
MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
|
||||
/* Output method for siphoning off extract_MCUs output into a big array */
|
||||
{
|
||||
static JBLOCKARRAY rowptr;
|
||||
|
||||
if (next_MCU_index >= MCUs_in_big_row) {
|
||||
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
|
||||
next_whole_row, TRUE);
|
||||
next_whole_row++;
|
||||
next_MCU_index = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* note that on 80x86, the cast applied to MCU_data implies
|
||||
* near to far pointer conversion.
|
||||
*/
|
||||
jcopy_block_row((JBLOCKROW) MCU_data,
|
||||
rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
|
||||
(long) cinfo->blocks_in_MCU);
|
||||
next_MCU_index++;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
|
||||
/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
|
||||
/* The method may be either the entropy encoder or some routine supplied */
|
||||
/* by the entropy optimizer. */
|
||||
{
|
||||
/* On an 80x86 machine, the entropy encoder expects the passed data block
|
||||
* to be in NEAR memory (for performance reasons), so we have to copy it
|
||||
* back from the big array to a local array. On less brain-damaged CPUs
|
||||
* we needn't do that.
|
||||
*/
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
|
||||
#endif
|
||||
long mcurow, mcuindex, next_row;
|
||||
int next_index;
|
||||
JBLOCKARRAY rowptr = NULL; /* init only to suppress compiler complaint */
|
||||
|
||||
next_row = 0;
|
||||
next_index = MCUs_in_big_row;
|
||||
|
||||
for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
|
||||
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
|
||||
if (next_index >= MCUs_in_big_row) {
|
||||
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
|
||||
next_row, FALSE);
|
||||
next_row++;
|
||||
next_index = 0;
|
||||
}
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
|
||||
(JBLOCKROW) MCU_data, /* note cast */
|
||||
(long) cinfo->blocks_in_MCU);
|
||||
(*output_method) (cinfo, MCU_data);
|
||||
#else
|
||||
(*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
|
||||
#endif
|
||||
next_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compression pipeline controller used for single-scan files
|
||||
* with no optimization of entropy parameters.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
single_ccontroller (compress_info_ptr cinfo)
|
||||
{
|
||||
int rows_in_mem; /* # of sample rows in full-size buffers */
|
||||
long fullsize_width; /* # of samples per row in full-size buffers */
|
||||
long cur_pixel_row; /* counts # of pixel rows processed */
|
||||
long mcu_rows_output; /* # of MCU rows actually emitted */
|
||||
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
|
||||
/* Work buffer for pre-subsampling data (see comments at head of file) */
|
||||
JSAMPIMAGE fullsize_data[2];
|
||||
/* Work buffer for subsampled data */
|
||||
JSAMPIMAGE subsampled_data;
|
||||
int rows_this_time;
|
||||
short ci, whichss, i;
|
||||
|
||||
/* Prepare for single scan containing all components */
|
||||
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
|
||||
cinfo->comps_in_scan = cinfo->num_components;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||
}
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
noninterleaved_scan_setup(cinfo);
|
||||
/* Vk block rows constitute the same number of MCU rows */
|
||||
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||
} else {
|
||||
interleaved_scan_setup(cinfo);
|
||||
/* in an interleaved scan, one MCU row contains Vk block rows */
|
||||
mcu_rows_per_loop = 1;
|
||||
}
|
||||
|
||||
/* Compute dimensions of full-size pixel buffers */
|
||||
/* Note these are the same whether interleaved or not. */
|
||||
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
|
||||
fullsize_width = jround_up(cinfo->image_width,
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
|
||||
/* Allocate working memory: */
|
||||
/* fullsize_data is sample data before subsampling */
|
||||
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
|
||||
/* subsampled_data is sample data after subsampling */
|
||||
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
|
||||
(cinfo->num_components * SIZEOF(JSAMPARRAY));
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
|
||||
(cinfo->comp_info[ci].subsampled_width,
|
||||
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
|
||||
}
|
||||
|
||||
/* Tell the memory manager to instantiate big arrays.
|
||||
* We don't need any big arrays in this controller,
|
||||
* but some other module (like the input file reader) may need one.
|
||||
*/
|
||||
(*cinfo->emethods->alloc_big_arrays)
|
||||
((long) 0, /* no more small sarrays */
|
||||
(long) 0, /* no more small barrays */
|
||||
(long) 0); /* no more "medium" objects */
|
||||
|
||||
/* Initialize output file & do per-scan object init */
|
||||
|
||||
(*cinfo->methods->write_scan_header) (cinfo);
|
||||
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
|
||||
(*cinfo->methods->entropy_encoder_init) (cinfo);
|
||||
(*cinfo->methods->subsample_init) (cinfo);
|
||||
(*cinfo->methods->extract_init) (cinfo);
|
||||
|
||||
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
|
||||
|
||||
mcu_rows_output = 0;
|
||||
whichss = 1; /* arrange to start with fullsize_data[0] */
|
||||
|
||||
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
|
||||
cur_pixel_row += rows_in_mem) {
|
||||
whichss ^= 1; /* switch to other fullsize_data buffer */
|
||||
|
||||
/* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
|
||||
/* Then we have exactly DCTSIZE row groups for subsampling. */
|
||||
rows_this_time = MIN(rows_in_mem, cinfo->image_height - cur_pixel_row);
|
||||
|
||||
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
|
||||
fullsize_data[whichss]);
|
||||
(*cinfo->methods->edge_expand) (cinfo,
|
||||
cinfo->image_width, rows_this_time,
|
||||
fullsize_width, rows_in_mem,
|
||||
fullsize_data[whichss]);
|
||||
|
||||
/* Subsample the data (all components) */
|
||||
/* First time through is a special case */
|
||||
|
||||
if (cur_pixel_row) {
|
||||
/* Subsample last row group of previous set */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
|
||||
(short) (DCTSIZE-1));
|
||||
/* and dump the previous set's subsampled data */
|
||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
||||
mcu_rows_per_loop,
|
||||
cinfo->methods->entropy_encode);
|
||||
mcu_rows_output += mcu_rows_per_loop;
|
||||
/* Subsample first row group of this set */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (DCTSIZE+1), (short) 0, (short) 1,
|
||||
(short) 0);
|
||||
} else {
|
||||
/* Subsample first row group with dummy above-context */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (-1), (short) 0, (short) 1,
|
||||
(short) 0);
|
||||
}
|
||||
/* Subsample second through next-to-last row groups of this set */
|
||||
for (i = 1; i <= DCTSIZE-2; i++) {
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (i-1), (short) i, (short) (i+1),
|
||||
(short) i);
|
||||
}
|
||||
} /* end of outer loop */
|
||||
|
||||
/* Subsample the last row group with dummy below-context */
|
||||
/* Note whichss points to last buffer side used */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
|
||||
(short) (DCTSIZE-1));
|
||||
/* Dump the remaining data (may be less than full height if uninterleaved) */
|
||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
||||
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
|
||||
cinfo->methods->entropy_encode);
|
||||
|
||||
/* Finish output file */
|
||||
(*cinfo->methods->extract_term) (cinfo);
|
||||
(*cinfo->methods->subsample_term) (cinfo);
|
||||
(*cinfo->methods->entropy_encoder_term) (cinfo);
|
||||
(*cinfo->methods->write_scan_trailer) (cinfo);
|
||||
|
||||
/* Release working memory */
|
||||
free_sampling_buffer(cinfo, fullsize_data);
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(subsampled_data[ci],
|
||||
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
|
||||
}
|
||||
(*cinfo->emethods->free_small) ((void *) subsampled_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compression pipeline controller used for single-scan files
|
||||
* with optimization of entropy parameters.
|
||||
*/
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
METHODDEF void
|
||||
single_eopt_ccontroller (compress_info_ptr cinfo)
|
||||
{
|
||||
int rows_in_mem; /* # of sample rows in full-size buffers */
|
||||
long fullsize_width; /* # of samples per row in full-size buffers */
|
||||
long cur_pixel_row; /* counts # of pixel rows processed */
|
||||
long mcu_rows_output; /* # of MCU rows actually emitted */
|
||||
int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */
|
||||
/* Work buffer for pre-subsampling data (see comments at head of file) */
|
||||
JSAMPIMAGE fullsize_data[2];
|
||||
/* Work buffer for subsampled data */
|
||||
JSAMPIMAGE subsampled_data;
|
||||
int rows_this_time;
|
||||
int blocks_in_big_row;
|
||||
short ci, whichss, i;
|
||||
|
||||
/* Prepare for single scan containing all components */
|
||||
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
|
||||
cinfo->comps_in_scan = cinfo->num_components;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||
}
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
noninterleaved_scan_setup(cinfo);
|
||||
/* Vk block rows constitute the same number of MCU rows */
|
||||
mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||
} else {
|
||||
interleaved_scan_setup(cinfo);
|
||||
/* in an interleaved scan, one MCU row contains Vk block rows */
|
||||
mcu_rows_per_loop = 1;
|
||||
}
|
||||
|
||||
/* Compute dimensions of full-size pixel buffers */
|
||||
/* Note these are the same whether interleaved or not. */
|
||||
rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
|
||||
fullsize_width = jround_up(cinfo->image_width,
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
|
||||
/* Allocate working memory: */
|
||||
/* fullsize_data is sample data before subsampling */
|
||||
alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
|
||||
/* subsampled_data is sample data after subsampling */
|
||||
subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
|
||||
(cinfo->num_components * SIZEOF(JSAMPARRAY));
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
|
||||
(cinfo->comp_info[ci].subsampled_width,
|
||||
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
|
||||
}
|
||||
|
||||
/* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
|
||||
MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
|
||||
blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
|
||||
|
||||
/* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
|
||||
whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
|
||||
((long) blocks_in_big_row,
|
||||
(long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
|
||||
+ MCUs_in_big_row-1) / MCUs_in_big_row,
|
||||
1L); /* unit height is 1 row */
|
||||
|
||||
next_whole_row = 0; /* init output ptr for MCU_output_catcher */
|
||||
next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
|
||||
|
||||
/* Tell the memory manager to instantiate big arrays */
|
||||
(*cinfo->emethods->alloc_big_arrays)
|
||||
((long) 0, /* no more small sarrays */
|
||||
(long) 0, /* no more small barrays */
|
||||
(long) 0); /* no more "medium" objects */
|
||||
|
||||
/* Do per-scan object init */
|
||||
|
||||
(*cinfo->methods->subsample_init) (cinfo);
|
||||
(*cinfo->methods->extract_init) (cinfo);
|
||||
|
||||
/* Loop over input image: rows_in_mem pixel rows are processed per loop */
|
||||
/* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
|
||||
|
||||
mcu_rows_output = 0;
|
||||
whichss = 1; /* arrange to start with fullsize_data[0] */
|
||||
|
||||
for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
|
||||
cur_pixel_row += rows_in_mem) {
|
||||
whichss ^= 1; /* switch to other fullsize_data buffer */
|
||||
|
||||
/* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
|
||||
/* Then we have exactly DCTSIZE row groups for subsampling. */
|
||||
rows_this_time = MIN(rows_in_mem, cinfo->image_height - cur_pixel_row);
|
||||
|
||||
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
|
||||
fullsize_data[whichss]);
|
||||
(*cinfo->methods->edge_expand) (cinfo,
|
||||
cinfo->image_width, rows_this_time,
|
||||
fullsize_width, rows_in_mem,
|
||||
fullsize_data[whichss]);
|
||||
|
||||
/* Subsample the data (all components) */
|
||||
/* First time through is a special case */
|
||||
|
||||
if (cur_pixel_row) {
|
||||
/* Subsample last row group of previous set */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
|
||||
(short) (DCTSIZE-1));
|
||||
/* and dump the previous set's subsampled data */
|
||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
||||
mcu_rows_per_loop,
|
||||
MCU_output_catcher);
|
||||
mcu_rows_output += mcu_rows_per_loop;
|
||||
/* Subsample first row group of this set */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (DCTSIZE+1), (short) 0, (short) 1,
|
||||
(short) 0);
|
||||
} else {
|
||||
/* Subsample first row group with dummy above-context */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (-1), (short) 0, (short) 1,
|
||||
(short) 0);
|
||||
}
|
||||
/* Subsample second through next-to-last row groups of this set */
|
||||
for (i = 1; i <= DCTSIZE-2; i++) {
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (i-1), (short) i, (short) (i+1),
|
||||
(short) i);
|
||||
}
|
||||
} /* end of outer loop */
|
||||
|
||||
/* Subsample the last row group with dummy below-context */
|
||||
/* Note whichss points to last buffer side used */
|
||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
||||
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
|
||||
(short) (DCTSIZE-1));
|
||||
/* Dump the remaining data (may be less than full height if uninterleaved) */
|
||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
||||
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
|
||||
MCU_output_catcher);
|
||||
|
||||
/* Clean up after that stuff, then find the optimal entropy parameters */
|
||||
|
||||
(*cinfo->methods->extract_term) (cinfo);
|
||||
(*cinfo->methods->subsample_term) (cinfo);
|
||||
|
||||
(*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
|
||||
|
||||
/* Emit scan to output file */
|
||||
/* Note: we can't do write_scan_header until entropy parameters are set! */
|
||||
|
||||
(*cinfo->methods->write_scan_header) (cinfo);
|
||||
cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
|
||||
(*cinfo->methods->entropy_encoder_init) (cinfo);
|
||||
dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
|
||||
(*cinfo->methods->entropy_encoder_term) (cinfo);
|
||||
(*cinfo->methods->write_scan_trailer) (cinfo);
|
||||
|
||||
/* Release working memory */
|
||||
free_sampling_buffer(cinfo, fullsize_data);
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(subsampled_data[ci],
|
||||
(long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
|
||||
}
|
||||
(*cinfo->emethods->free_small) ((void *) subsampled_data);
|
||||
(*cinfo->emethods->free_big_barray) (whole_scan_MCUs);
|
||||
}
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Compression pipeline controller used for multiple-scan files
|
||||
* with no optimization of entropy parameters.
|
||||
*/
|
||||
|
||||
#ifdef MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
METHODDEF void
|
||||
multi_ccontroller (compress_info_ptr cinfo)
|
||||
{
|
||||
ERREXIT(cinfo->emethods, "Not implemented yet");
|
||||
}
|
||||
|
||||
#endif /* MULTISCAN_FILES_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Compression pipeline controller used for multiple-scan files
|
||||
* with optimization of entropy parameters.
|
||||
*/
|
||||
|
||||
#ifdef MULTISCAN_FILES_SUPPORTED
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
METHODDEF void
|
||||
multi_eopt_ccontroller (compress_info_ptr cinfo)
|
||||
{
|
||||
ERREXIT(cinfo->emethods, "Not implemented yet");
|
||||
}
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
#endif /* MULTISCAN_FILES_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for compression pipeline controllers.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselcpipeline (compress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->interleave || cinfo->num_components == 1) {
|
||||
/* single scan needed */
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
if (cinfo->optimize_coding)
|
||||
cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
|
||||
else
|
||||
#endif
|
||||
cinfo->methods->c_pipeline_controller = single_ccontroller;
|
||||
} else {
|
||||
/* multiple scans needed */
|
||||
#ifdef MULTISCAN_FILES_SUPPORTED
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
if (cinfo->optimize_coding)
|
||||
cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
|
||||
else
|
||||
#endif
|
||||
cinfo->methods->c_pipeline_controller = multi_ccontroller;
|
||||
#else
|
||||
ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
|
||||
#endif
|
||||
}
|
||||
}
|
135
jcsample.c
Normal file
135
jcsample.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* jcsample.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains subsampling routines.
|
||||
* These routines are invoked via the subsample and
|
||||
* subsample_init/term methods.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for subsampling a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
subsample_init (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subsample pixel values of a single component.
|
||||
* This version only handles integral sampling ratios.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
subsample (compress_info_ptr cinfo, int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
|
||||
JSAMPARRAY output_data)
|
||||
{
|
||||
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
|
||||
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
|
||||
long outcol;
|
||||
JSAMPROW inptr, outptr;
|
||||
INT32 outvalue;
|
||||
|
||||
/* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
|
||||
if (output_rows != compptr->v_samp_factor ||
|
||||
input_rows != cinfo->max_v_samp_factor ||
|
||||
(output_cols % compptr->h_samp_factor) != 0 ||
|
||||
(input_cols % cinfo->max_h_samp_factor) != 0 ||
|
||||
input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
|
||||
ERREXIT(cinfo->emethods, "Bogus subsample parameters");
|
||||
|
||||
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
|
||||
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
|
||||
numpix = h_expand * v_expand;
|
||||
numpix2 = numpix/2;
|
||||
|
||||
inrow = 0;
|
||||
for (outrow = 0; outrow < output_rows; outrow++) {
|
||||
outptr = output_data[outrow];
|
||||
for (outcol = 0; outcol < output_cols; outcol++) {
|
||||
outvalue = 0;
|
||||
for (v = 0; v < v_expand; v++) {
|
||||
inptr = input_data[inrow+v] + (outcol*h_expand);
|
||||
for (h = 0; h < h_expand; h++) {
|
||||
outvalue += GETJSAMPLE(*inptr++);
|
||||
}
|
||||
}
|
||||
*outptr++ = (outvalue + numpix2) / numpix;
|
||||
}
|
||||
inrow += v_expand;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subsample pixel values of a single component.
|
||||
* This version handles the special case of a full-size component.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
fullsize_subsample (compress_info_ptr cinfo, int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
|
||||
JSAMPARRAY output_data)
|
||||
{
|
||||
if (input_cols != output_cols || input_rows != output_rows) /* DEBUG */
|
||||
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
|
||||
|
||||
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clean up after a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
subsample_term (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for subsampling.
|
||||
* Note that we must select a routine for each component.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselsubsample (compress_info_ptr cinfo)
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
if (cinfo->CCIR601_sampling)
|
||||
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
|
||||
compptr->v_samp_factor == cinfo->max_v_samp_factor)
|
||||
cinfo->methods->subsample[ci] = fullsize_subsample;
|
||||
else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
|
||||
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
|
||||
cinfo->methods->subsample[ci] = subsample;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
|
||||
}
|
||||
|
||||
cinfo->methods->subsample_init = subsample_init;
|
||||
cinfo->methods->subsample_term = subsample_term;
|
||||
}
|
42
jdarith.c
Normal file
42
jdarith.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* jdarith.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains arithmetic entropy decoding routines.
|
||||
* These routines are invoked via the methods entropy_decode
|
||||
* and entropy_decoder_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef ARITH_CODING_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* The arithmetic coding option of the JPEG standard specifies Q-coding,
|
||||
* which is covered by patents held by IBM (and possibly AT&T and Mitsubishi).
|
||||
* At this time it does not appear to be legal for the Independent JPEG
|
||||
* Group to distribute software that implements arithmetic coding.
|
||||
* We have therefore removed arithmetic coding support from the
|
||||
* distributed source code.
|
||||
*
|
||||
* We're not happy about it either.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for arithmetic entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jseldarithmetic (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo->emethods, "Sorry, there are legal restrictions on arithmetic coding");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ARITH_CODING_SUPPORTED */
|
194
jdcolor.c
Normal file
194
jdcolor.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* jdcolor.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains output colorspace conversion routines.
|
||||
* These routines are invoked via the methods color_convert
|
||||
* and colorout_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for colorspace conversion.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
colorout_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert some rows of samples to the output colorspace.
|
||||
* This version handles YCbCr -> RGB conversion.
|
||||
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
||||
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
||||
{
|
||||
register INT32 y, u, v, x;
|
||||
register JSAMPROW inptr0, inptr1, inptr2;
|
||||
register JSAMPROW outptr0, outptr1, outptr2;
|
||||
register long col;
|
||||
register long width = cinfo->image_width;
|
||||
register int row;
|
||||
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
inptr0 = input_data[0][row];
|
||||
inptr1 = input_data[1][row];
|
||||
inptr2 = input_data[2][row];
|
||||
outptr0 = output_data[0][row];
|
||||
outptr1 = output_data[1][row];
|
||||
outptr2 = output_data[2][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
u = (int) GETJSAMPLE(*inptr1++) - CENTERJSAMPLE;
|
||||
v = (int) GETJSAMPLE(*inptr2++) - CENTERJSAMPLE;
|
||||
/* Note: if the inputs were computed directly from RGB values,
|
||||
* range-limiting would be unnecessary here; but due to possible
|
||||
* noise in the DCT/IDCT phase, we do need to apply range limits.
|
||||
*/
|
||||
y *= 1024; /* in case compiler can't spot common subexpression */
|
||||
x = y + 1436*v + 512; /* red */
|
||||
if (x < 0) x = 0;
|
||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
||||
*outptr0++ = x >> 10;
|
||||
x = y - 352*u - 731*v + 512; /* green */
|
||||
if (x < 0) x = 0;
|
||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
||||
*outptr1++ = x >> 10;
|
||||
x = y + 1815*u + 512; /* blue */
|
||||
if (x < 0) x = 0;
|
||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
||||
*outptr2++ = x >> 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Color conversion for no colorspace change: just copy the data.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
null_convert (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
||||
{
|
||||
short ci;
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
|
||||
num_rows, cinfo->image_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Color conversion for grayscale: just copy the data.
|
||||
* This also works for YCbCr/YIQ -> grayscale conversion, in which
|
||||
* we just copy the Y (luminance) component and ignore chrominance.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
grayscale_convert (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
||||
{
|
||||
jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
|
||||
num_rows, cinfo->image_width);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
colorout_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for output colorspace conversion.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jseldcolor (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* Make sure num_components agrees with jpeg_color_space */
|
||||
switch (cinfo->jpeg_color_space) {
|
||||
case CS_GRAYSCALE:
|
||||
if (cinfo->num_components != 1)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
break;
|
||||
|
||||
case CS_RGB:
|
||||
case CS_YIQ:
|
||||
case CS_YCbCr:
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
break;
|
||||
|
||||
case CS_CMYK:
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set color_out_comps and conversion method based on requested space */
|
||||
switch (cinfo->out_color_space) {
|
||||
case CS_GRAYSCALE:
|
||||
cinfo->color_out_comps = 1;
|
||||
if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
|
||||
cinfo->jpeg_color_space == CS_YCbCr ||
|
||||
cinfo->jpeg_color_space == CS_YIQ)
|
||||
cinfo->methods->color_convert = grayscale_convert;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
case CS_RGB:
|
||||
cinfo->color_out_comps = 3;
|
||||
if (cinfo->jpeg_color_space == CS_YCbCr)
|
||||
cinfo->methods->color_convert = ycc_rgb_convert;
|
||||
else if (cinfo->jpeg_color_space == CS_RGB)
|
||||
cinfo->methods->color_convert = null_convert;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
case CS_CMYK:
|
||||
cinfo->color_out_comps = 4;
|
||||
if (cinfo->jpeg_color_space == CS_CMYK)
|
||||
cinfo->methods->color_convert = null_convert;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported output colorspace");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cinfo->quantize_colors)
|
||||
cinfo->final_out_comps = 1; /* single colormapped output component */
|
||||
else
|
||||
cinfo->final_out_comps = cinfo->color_out_comps;
|
||||
|
||||
cinfo->methods->colorout_init = colorout_init;
|
||||
cinfo->methods->colorout_term = colorout_term;
|
||||
}
|
318
jdhuff.c
Normal file
318
jdhuff.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* jdhuff.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines.
|
||||
* These routines are invoked via the methods entropy_decode
|
||||
* and entropy_decoder_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/* Static variables to avoid passing 'round extra parameters */
|
||||
|
||||
static decompress_info_ptr dcinfo;
|
||||
|
||||
static unsigned int get_buffer; /* current bit-extraction buffer */
|
||||
static int bits_left; /* # of unused bits in it */
|
||||
|
||||
|
||||
LOCAL void
|
||||
fix_huff_tbl (HUFF_TBL * htbl)
|
||||
/* Compute derived values for a Huffman table */
|
||||
{
|
||||
int p, i, l, lastp, si;
|
||||
char huffsize[257];
|
||||
UINT16 huffcode[257];
|
||||
UINT16 code;
|
||||
|
||||
/* Figure 7.3.5.4.2.1: make table of Huffman code length for each symbol */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
for (i = 1; i <= htbl->bits[l]; i++)
|
||||
huffsize[p++] = l;
|
||||
}
|
||||
huffsize[p] = 0;
|
||||
lastp = p;
|
||||
|
||||
/* Figure 7.3.5.4.2.2: generate the codes themselves */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
code = 0;
|
||||
si = huffsize[0];
|
||||
p = 0;
|
||||
while (huffsize[p]) {
|
||||
while (huffsize[p] == si) {
|
||||
huffcode[p++] = code;
|
||||
code++;
|
||||
}
|
||||
code <<= 1;
|
||||
si++;
|
||||
}
|
||||
|
||||
/* Figure 7.3.5.4.2.3: generate encoding tables */
|
||||
/* These are code and size indexed by symbol value */
|
||||
|
||||
for (p = 0; p < lastp; p++) {
|
||||
htbl->ehufco[htbl->huffval[p]] = huffcode[p];
|
||||
htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
|
||||
}
|
||||
|
||||
/* Figure 13.4.2.3.1: generate decoding tables */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
if (htbl->bits[l]) {
|
||||
htbl->valptr[l] = p; /* huffval[] index of 1st sym of code len l */
|
||||
htbl->mincode[l] = huffcode[p]; /* minimum code of length l */
|
||||
p += htbl->bits[l];
|
||||
htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
|
||||
} else {
|
||||
htbl->maxcode[l] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Extract the next N bits from the input stream (N <= 8) */
|
||||
|
||||
LOCAL int
|
||||
get_bits (int nbits)
|
||||
{
|
||||
int result;
|
||||
|
||||
while (nbits > bits_left) {
|
||||
int c = JGETC(dcinfo);
|
||||
|
||||
get_buffer = (get_buffer << 8) + c;
|
||||
bits_left += 8;
|
||||
/* If it's 0xFF, check and discard stuffed zero byte */
|
||||
if (c == 0xff) {
|
||||
c = JGETC(dcinfo); /* Byte stuffing */
|
||||
if (c != 0)
|
||||
ERREXIT1(dcinfo->emethods,
|
||||
"Unexpected marker 0x%02x in compressed data", c);
|
||||
}
|
||||
}
|
||||
|
||||
bits_left -= nbits;
|
||||
result = (get_buffer >> bits_left) & ((1 << nbits) - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Macro to make things go at some speed! */
|
||||
|
||||
#define get_bit() (bits_left ? \
|
||||
((get_buffer >> (--bits_left)) & 1) : \
|
||||
get_bits(1))
|
||||
|
||||
|
||||
/* Figure 13.4.2.3.2: extract next coded symbol from input stream */
|
||||
|
||||
LOCAL int
|
||||
huff_DECODE (HUFF_TBL * htbl)
|
||||
{
|
||||
int l, p;
|
||||
INT32 code;
|
||||
|
||||
code = get_bit();
|
||||
l = 1;
|
||||
while (code > htbl->maxcode[l]) {
|
||||
code = (code << 1) + get_bit();
|
||||
l++;
|
||||
}
|
||||
|
||||
p = htbl->valptr[l] + (code - htbl->mincode[l]);
|
||||
|
||||
return htbl->huffval[p];
|
||||
}
|
||||
|
||||
|
||||
/* Figure 13.4.2.1.1: extend sign bit */
|
||||
|
||||
#define huff_EXTEND(x, s) ((x) < (1 << ((s)-1)) ? \
|
||||
(x) + (-1 << (s)) + 1 : \
|
||||
(x))
|
||||
|
||||
|
||||
/* Decode a single block's worth of coefficients */
|
||||
/* Note that only the difference is returned for the DC coefficient */
|
||||
|
||||
LOCAL void
|
||||
decode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl)
|
||||
{
|
||||
int s, k, r, n;
|
||||
|
||||
/* zero out the coefficient block */
|
||||
|
||||
MEMZERO((void *) block, SIZEOF(JBLOCK));
|
||||
|
||||
/* Section 13.4.2.1: decode the DC coefficient difference */
|
||||
|
||||
s = huff_DECODE(dctbl);
|
||||
r = get_bits(s);
|
||||
block[0] = huff_EXTEND(r, s);
|
||||
|
||||
/* Section 13.4.2.2: decode the AC coefficients */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
r = huff_DECODE(actbl);
|
||||
|
||||
s = r & 15;
|
||||
n = r >> 4;
|
||||
|
||||
if (s) {
|
||||
k = k + n;
|
||||
r = get_bits(s);
|
||||
block[k] = huff_EXTEND(r, s);
|
||||
} else {
|
||||
if (n != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
* This is invoked after reading the SOS marker.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_decoder_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Initialize static variables */
|
||||
dcinfo = cinfo;
|
||||
bits_left = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Make sure requested tables are present */
|
||||
if (cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no] == NULL ||
|
||||
cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no] == NULL)
|
||||
ERREXIT(cinfo->emethods, "Use of undefined Huffman table");
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for same table, but it's not a big deal */
|
||||
fix_huff_tbl(cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]);
|
||||
fix_huff_tbl(cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
|
||||
/* Initialize DC predictions to 0 */
|
||||
cinfo->last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Initialize restart stuff */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
cinfo->next_restart_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for a restart marker & resynchronize decoder.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
process_restart (decompress_info_ptr cinfo)
|
||||
{
|
||||
int c, nbytes;
|
||||
short ci;
|
||||
|
||||
/* Throw away any partial unread byte */
|
||||
bits_left = 0;
|
||||
|
||||
/* Scan for next JPEG marker */
|
||||
nbytes = 0;
|
||||
do {
|
||||
do { /* skip any non-FF bytes */
|
||||
nbytes++;
|
||||
c = JGETC(cinfo);
|
||||
} while (c != 0xFF);
|
||||
do { /* skip any duplicate FFs */
|
||||
nbytes++;
|
||||
c = JGETC(cinfo);
|
||||
} while (c == 0xFF);
|
||||
} while (c == 0); /* repeat if it was a stuffed FF/00 */
|
||||
|
||||
if (c != (RST0 + cinfo->next_restart_num))
|
||||
ERREXIT2(cinfo->emethods, "Found 0x%02x marker instead of RST%d",
|
||||
c, cinfo->next_restart_num);
|
||||
|
||||
if (nbytes != 2)
|
||||
TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before RST%d",
|
||||
nbytes-2, cinfo->next_restart_num);
|
||||
else
|
||||
TRACEMS1(cinfo->emethods, 2, "RST%d", cinfo->next_restart_num);
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
cinfo->last_dc_val[ci] = 0;
|
||||
|
||||
/* Update restart state */
|
||||
cinfo->restarts_to_go = cinfo->restart_interval;
|
||||
cinfo->next_restart_num++;
|
||||
cinfo->next_restart_num &= 7;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode and return one MCU's worth of Huffman-compressed coefficients.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_decode (decompress_info_ptr cinfo, JBLOCK *MCU_data)
|
||||
{
|
||||
short blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Account for restart interval, process restart marker if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (cinfo->restarts_to_go == 0)
|
||||
process_restart(cinfo);
|
||||
cinfo->restarts_to_go--;
|
||||
}
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
decode_one_block(MCU_data[blkn],
|
||||
cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no],
|
||||
cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]);
|
||||
/* Convert DC difference to actual value, update last_dc_val */
|
||||
MCU_data[blkn][0] += cinfo->last_dc_val[ci];
|
||||
cinfo->last_dc_val[ci] = MCU_data[blkn][0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
huff_decoder_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* No work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jseldhuffman (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (! cinfo->arith_code) {
|
||||
cinfo->methods->entropy_decoder_init = huff_decoder_init;
|
||||
cinfo->methods->entropy_decode = huff_decode;
|
||||
cinfo->methods->entropy_decoder_term = huff_decoder_term;
|
||||
}
|
||||
}
|
289
jdmain.c
Normal file
289
jdmain.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* jdmain.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a trivial test user interface for the JPEG decompressor.
|
||||
* It should work on any system with Unix- or MS-DOS-style command lines.
|
||||
*
|
||||
* Two different command line styles are permitted, depending on the
|
||||
* compile-time switch TWO_FILE_COMMANDLINE:
|
||||
* djpeg [options] inputfile outputfile
|
||||
* djpeg [options] [inputfile]
|
||||
* In the second style, output is always to standard output, which you'd
|
||||
* normally redirect to a file or pipe to some other program. Input is
|
||||
* either from a named file or from standard input (typically redirected).
|
||||
* The second style is convenient on Unix but is unhelpful on systems that
|
||||
* don't support pipes. Also, you MUST use the first style if your system
|
||||
* doesn't do binary I/O to stdin/stdout.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h> /* to declare exit() */
|
||||
#endif
|
||||
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* command-line reader for Macintosh */
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#define WRITE_BINARY "w"
|
||||
#else
|
||||
#define READ_BINARY "rb"
|
||||
#define WRITE_BINARY "wb"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* If your system has getopt(3), you can use your library version by
|
||||
* defining HAVE_GETOPT. By default, we use the PD 'egetopt'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_GETOPT
|
||||
extern int getopt PP((int argc, char **argv, char *optstring));
|
||||
extern char * optarg;
|
||||
extern int optind;
|
||||
#else
|
||||
#include "egetopt.c"
|
||||
#define getopt(argc,argv,opt) egetopt(argc,argv,opt)
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum { /* defines known output image formats */
|
||||
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
|
||||
FMT_GIF, /* GIF format */
|
||||
FMT_TIFF /* TIFF format */
|
||||
} IMAGE_FORMATS;
|
||||
|
||||
static IMAGE_FORMATS requested_fmt;
|
||||
|
||||
|
||||
/*
|
||||
* This routine gets control after the input file header has been read.
|
||||
* It must determine what output file format is to be written,
|
||||
* and make any other decompression parameter changes that are desirable.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
d_ui_method_selection (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* if grayscale or CMYK input, force similar output; */
|
||||
/* else leave the output colorspace as set by options. */
|
||||
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
|
||||
cinfo->out_color_space = CS_GRAYSCALE;
|
||||
else if (cinfo->jpeg_color_space == CS_CMYK)
|
||||
cinfo->out_color_space = CS_CMYK;
|
||||
|
||||
/* select output file format */
|
||||
/* Note: jselwxxx routine may make additional parameter changes,
|
||||
* such as forcing color quantization if it's a colormapped format.
|
||||
*/
|
||||
switch (requested_fmt) {
|
||||
#ifdef GIF_SUPPORTED
|
||||
case FMT_GIF:
|
||||
jselwgif(cinfo);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PPM_SUPPORTED
|
||||
case FMT_PPM:
|
||||
jselwppm(cinfo);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Unsupported output file format");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reload the input buffer after it's been emptied, and return the next byte.
|
||||
* See the JGETC macro for calling conditions.
|
||||
*
|
||||
* This routine would need to be replaced if reading JPEG data from something
|
||||
* other than a stdio stream.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
read_jpeg_data (decompress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->bytes_in_buffer = fread(cinfo->input_buffer + MIN_UNGET,
|
||||
1, JPEG_BUF_SIZE,
|
||||
cinfo->input_file);
|
||||
|
||||
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
|
||||
|
||||
if (cinfo->bytes_in_buffer <= 0)
|
||||
ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
|
||||
|
||||
return JGETC(cinfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOCAL void
|
||||
usage (char * progname)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "usage: %s ", progname);
|
||||
fprintf(stderr, "[-b] [-q colors] [-2] [-d] [-g] [-G]");
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, " inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, " [inputfile]\n");
|
||||
#endif
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct decompress_info_struct cinfo;
|
||||
struct decompress_methods_struct dc_methods;
|
||||
struct external_methods_struct e_methods;
|
||||
int c;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef THINK_C
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
/* Initialize the system-dependent method pointers. */
|
||||
cinfo.methods = &dc_methods;
|
||||
cinfo.emethods = &e_methods;
|
||||
jselerror(&e_methods); /* error/trace message routines */
|
||||
jselvirtmem(&e_methods); /* memory allocation routines */
|
||||
dc_methods.d_ui_method_selection = d_ui_method_selection;
|
||||
dc_methods.read_jpeg_data = read_jpeg_data;
|
||||
|
||||
/* Allocate memory for input buffer. */
|
||||
cinfo.input_buffer = (char *) (*cinfo.emethods->alloc_small)
|
||||
((size_t) (JPEG_BUF_SIZE + MIN_UNGET));
|
||||
cinfo.bytes_in_buffer = 0; /* initialize buffer to empty */
|
||||
|
||||
/* Set up default input and output file references. */
|
||||
/* (These may be overridden below.) */
|
||||
cinfo.input_file = stdin;
|
||||
cinfo.output_file = stdout;
|
||||
|
||||
/* Set up default parameters. */
|
||||
e_methods.trace_level = 0;
|
||||
cinfo.output_gamma = 1.0;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
cinfo.two_pass_quantize = FALSE;
|
||||
cinfo.use_dithering = FALSE;
|
||||
cinfo.desired_number_of_colors = 256;
|
||||
cinfo.do_block_smoothing = FALSE;
|
||||
cinfo.do_pixel_smoothing = FALSE;
|
||||
cinfo.out_color_space = CS_RGB;
|
||||
cinfo.jpeg_color_space = CS_UNKNOWN;
|
||||
/* setting any other value in jpeg_color_space overrides heuristics */
|
||||
/* in jrdjfif.c ... */
|
||||
/* You may wanta change the default output format; here's the place: */
|
||||
#ifdef PPM_SUPPORTED
|
||||
requested_fmt = FMT_PPM;
|
||||
#else
|
||||
requested_fmt = FMT_GIF;
|
||||
#endif
|
||||
|
||||
/* Scan parameters */
|
||||
|
||||
while ((c = getopt(argc, argv, "bq:2DdgG")) != EOF)
|
||||
switch (c) {
|
||||
case 'b': /* Enable cross-block smoothing. */
|
||||
cinfo.do_block_smoothing = TRUE;
|
||||
break;
|
||||
case 'q': /* Do color quantization. */
|
||||
{ int val;
|
||||
if (optarg == NULL)
|
||||
usage(argv[0]);
|
||||
if (sscanf(optarg, "%d", &val) != 1)
|
||||
usage(argv[0]);
|
||||
cinfo.desired_number_of_colors = val;
|
||||
}
|
||||
cinfo.quantize_colors = TRUE;
|
||||
break;
|
||||
case '2': /* Use two-pass quantization. */
|
||||
cinfo.two_pass_quantize = TRUE;
|
||||
break;
|
||||
case 'D': /* Use dithering in color quantization. */
|
||||
cinfo.use_dithering = TRUE;
|
||||
break;
|
||||
case 'd': /* Debugging. */
|
||||
e_methods.trace_level++;
|
||||
break;
|
||||
case 'g': /* Force grayscale output. */
|
||||
cinfo.out_color_space = CS_GRAYSCALE;
|
||||
break;
|
||||
case 'G': /* GIF output format. */
|
||||
requested_fmt = FMT_GIF;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Select the input and output files */
|
||||
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
|
||||
if (optind != argc-2) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
|
||||
usage(argv[0]);
|
||||
}
|
||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
||||
exit(2);
|
||||
}
|
||||
if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#else /* not TWO_FILE_COMMANDLINE -- use Unix style */
|
||||
|
||||
if (optind < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", argv[0]);
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (optind < argc) {
|
||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TWO_FILE_COMMANDLINE */
|
||||
|
||||
/* Set up to read a JFIF or baseline-JPEG file. */
|
||||
/* A smarter UI would inspect the first few bytes of the input file */
|
||||
/* to determine its type. */
|
||||
#ifdef JFIF_SUPPORTED
|
||||
jselrjfif(&cinfo);
|
||||
#else
|
||||
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
|
||||
#endif
|
||||
|
||||
/* Do it to it! */
|
||||
jpeg_decompress(&cinfo);
|
||||
|
||||
/* Release memory. */
|
||||
(*cinfo.emethods->free_small) ((void *) cinfo.input_buffer);
|
||||
#ifdef MEM_STATS
|
||||
if (e_methods.trace_level > 0)
|
||||
j_mem_stats();
|
||||
#endif
|
||||
|
||||
/* All done. */
|
||||
exit(0);
|
||||
}
|
180
jdmaster.c
Normal file
180
jdmaster.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* jdmaster.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the main control for the JPEG decompressor.
|
||||
* The system-dependent (user interface) code should call jpeg_decompress()
|
||||
* after doing appropriate setup of the decompress_info_struct parameter.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
METHODDEF void
|
||||
d_per_scan_method_selection (decompress_info_ptr cinfo)
|
||||
/* Central point for per-scan method selection */
|
||||
{
|
||||
/* MCU disassembly */
|
||||
jseldmcu(cinfo);
|
||||
/* Un-subsampling of pixels */
|
||||
jselunsubsample(cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
d_initial_method_selection (decompress_info_ptr cinfo)
|
||||
/* Central point for initial method selection (after reading file header) */
|
||||
{
|
||||
/* JPEG file scanning method selection is already done. */
|
||||
/* So is output file format selection (both are done by user interface). */
|
||||
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
#ifdef ARITH_CODING_SUPPORTED
|
||||
jseldarithmetic(cinfo);
|
||||
#else
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo->emethods, "Arithmetic coding not supported");
|
||||
}
|
||||
#endif
|
||||
jseldhuffman(cinfo);
|
||||
/* Cross-block smoothing */
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
jselbsmooth(cinfo);
|
||||
#else
|
||||
cinfo->do_block_smoothing = FALSE;
|
||||
#endif
|
||||
/* Gamma and color space conversion */
|
||||
jseldcolor(cinfo);
|
||||
|
||||
/* Color quantization */
|
||||
#ifdef QUANT_1PASS_SUPPORTED
|
||||
#ifndef QUANT_2PASS_SUPPORTED
|
||||
cinfo->two_pass_quantize = FALSE; /* only have 1-pass */
|
||||
#endif
|
||||
#else /* not QUANT_1PASS_SUPPORTED */
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
cinfo->two_pass_quantize = TRUE; /* only have 2-pass */
|
||||
#else /* not QUANT_2PASS_SUPPORTED */
|
||||
if (cinfo->quantize_colors) {
|
||||
ERREXIT(cinfo->emethods, "Color quantization was not compiled");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef QUANT_1PASS_SUPPORTED
|
||||
jsel1quantize(cinfo);
|
||||
#endif
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
jsel2quantize(cinfo);
|
||||
#endif
|
||||
|
||||
/* Pipeline control */
|
||||
jseldpipeline(cinfo);
|
||||
/* Overall control (that's me!) */
|
||||
cinfo->methods->d_per_scan_method_selection = d_per_scan_method_selection;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
initial_setup (decompress_info_ptr cinfo)
|
||||
/* Do computations that are needed before initial method selection */
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Compute maximum sampling factors; check factor validity */
|
||||
cinfo->max_h_samp_factor = 1;
|
||||
cinfo->max_v_samp_factor = 1;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
||||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||
ERREXIT(cinfo->emethods, "Bogus sampling factors");
|
||||
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||
compptr->h_samp_factor);
|
||||
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||
compptr->v_samp_factor);
|
||||
|
||||
}
|
||||
|
||||
/* Compute logical subsampled dimensions of components */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
|
||||
+ cinfo->max_h_samp_factor - 1)
|
||||
/ cinfo->max_h_samp_factor;
|
||||
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
|
||||
+ cinfo->max_v_samp_factor - 1)
|
||||
/ cinfo->max_v_samp_factor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the main entry point to the JPEG decompressor.
|
||||
*/
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jpeg_decompress (decompress_info_ptr cinfo)
|
||||
{
|
||||
short i;
|
||||
|
||||
/* Initialize pointers as needed to mark stuff unallocated. */
|
||||
cinfo->comp_info = NULL;
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||
}
|
||||
|
||||
/* Read the JPEG file header markers; everything up through the first SOS
|
||||
* marker is read now. NOTE: the user interface must have initialized the
|
||||
* read_file_header method pointer (eg, by calling jselrjfif or jselrtiff).
|
||||
* The other file reading methods (read_scan_header etc.) were probably
|
||||
* set at the same time, but could be set up by read_file_header itself.
|
||||
*/
|
||||
(*cinfo->methods->read_file_header) (cinfo);
|
||||
if (! ((*cinfo->methods->read_scan_header) (cinfo)))
|
||||
ERREXIT(cinfo->emethods, "Empty JPEG file");
|
||||
|
||||
/* Give UI a chance to adjust decompression parameters and select */
|
||||
/* output file format based on info from file header. */
|
||||
(*cinfo->methods->d_ui_method_selection) (cinfo);
|
||||
|
||||
/* Now select methods for decompression steps. */
|
||||
initial_setup(cinfo);
|
||||
d_initial_method_selection(cinfo);
|
||||
|
||||
/* Initialize the output file & other modules as needed */
|
||||
/* (color_quant and entropy_decoder are inited by pipeline controller) */
|
||||
|
||||
(*cinfo->methods->output_init) (cinfo);
|
||||
(*cinfo->methods->colorout_init) (cinfo);
|
||||
|
||||
/* And let the pipeline controller do the rest. */
|
||||
(*cinfo->methods->d_pipeline_controller) (cinfo);
|
||||
|
||||
/* Finish output file, release working storage, etc */
|
||||
(*cinfo->methods->colorout_term) (cinfo);
|
||||
(*cinfo->methods->output_term) (cinfo);
|
||||
(*cinfo->methods->read_file_trailer) (cinfo);
|
||||
|
||||
/* Release allocated storage for tables */
|
||||
#define FREE(ptr) if ((ptr) != NULL) \
|
||||
(*cinfo->emethods->free_small) ((void *) ptr)
|
||||
|
||||
FREE(cinfo->comp_info);
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
FREE(cinfo->quant_tbl_ptrs[i]);
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
FREE(cinfo->dc_huff_tbl_ptrs[i]);
|
||||
FREE(cinfo->ac_huff_tbl_ptrs[i]);
|
||||
}
|
||||
|
||||
/* My, that was easy, wasn't it? */
|
||||
}
|
146
jdmcu.c
Normal file
146
jdmcu.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* jdmcu.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains MCU disassembly routines and quantization descaling.
|
||||
* These routines are invoked via the disassemble_MCU and
|
||||
* disassemble_init/term methods.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* Quantization descaling and zigzag reordering
|
||||
*/
|
||||
|
||||
|
||||
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
|
||||
|
||||
static const short ZAG[DCTSIZE2] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
||||
|
||||
|
||||
LOCAL void
|
||||
qdescale_zig (JBLOCK input, JBLOCKROW outputptr, QUANT_TBL_PTR quanttbl)
|
||||
{
|
||||
short i;
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
(*outputptr)[ZAG[i]] = (*input++) * (*quanttbl++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Fetch one MCU row from entropy_decode, build coefficient array.
|
||||
* This version is used for noninterleaved (single-component) scans.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
disassemble_noninterleaved_MCU (decompress_info_ptr cinfo,
|
||||
JBLOCKIMAGE image_data)
|
||||
{
|
||||
JBLOCK MCU_data[1];
|
||||
long mcuindex;
|
||||
jpeg_component_info * compptr;
|
||||
QUANT_TBL_PTR quant_ptr;
|
||||
|
||||
/* this is pretty easy since there is one component and one block per MCU */
|
||||
compptr = cinfo->cur_comp_info[0];
|
||||
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
|
||||
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
|
||||
/* Fetch the coefficient data */
|
||||
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
|
||||
/* Descale, reorder, and distribute it into the image array */
|
||||
qdescale_zig(MCU_data[0], image_data[0][0] + mcuindex, quant_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fetch one MCU row from entropy_decode, build coefficient array.
|
||||
* This version is used for interleaved (multi-component) scans.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
disassemble_interleaved_MCU (decompress_info_ptr cinfo,
|
||||
JBLOCKIMAGE image_data)
|
||||
{
|
||||
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
|
||||
long mcuindex;
|
||||
short blkn, ci, xpos, ypos;
|
||||
jpeg_component_info * compptr;
|
||||
QUANT_TBL_PTR quant_ptr;
|
||||
JBLOCKROW image_ptr;
|
||||
|
||||
for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
|
||||
/* Fetch the coefficient data */
|
||||
(*cinfo->methods->entropy_decode) (cinfo, MCU_data);
|
||||
/* Descale, reorder, and distribute it into the image array */
|
||||
blkn = 0;
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
quant_ptr = cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
|
||||
for (ypos = 0; ypos < compptr->MCU_height; ypos++) {
|
||||
image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width);
|
||||
for (xpos = 0; xpos < compptr->MCU_width; xpos++) {
|
||||
qdescale_zig(MCU_data[blkn], image_ptr, quant_ptr);
|
||||
image_ptr++;
|
||||
blkn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for processing a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
disassemble_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clean up after a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
disassemble_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for MCU disassembly.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jseldmcu (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->comps_in_scan == 1)
|
||||
cinfo->methods->disassemble_MCU = disassemble_noninterleaved_MCU;
|
||||
else
|
||||
cinfo->methods->disassemble_MCU = disassemble_interleaved_MCU;
|
||||
cinfo->methods->disassemble_init = disassemble_init;
|
||||
cinfo->methods->disassemble_term = disassemble_term;
|
||||
}
|
133
jdsample.c
Normal file
133
jdsample.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* jdsample.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains un-subsampling routines.
|
||||
* These routines are invoked via the unsubsample and
|
||||
* unsubsample_init/term methods.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for un-subsampling a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
unsubsample_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Un-subsample pixel values of a single component.
|
||||
* This version only handles integral sampling ratios.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
unsubsample (decompress_info_ptr cinfo, int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
|
||||
JSAMPARRAY output_data)
|
||||
{
|
||||
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
|
||||
short h_expand, v_expand, h, v;
|
||||
int inrow, outrow;
|
||||
long incol;
|
||||
JSAMPROW inptr, outptr;
|
||||
JSAMPLE invalue;
|
||||
|
||||
/* TEMP FOR DEBUGGING PIPELINE CONTROLLER */
|
||||
if (input_rows != compptr->v_samp_factor ||
|
||||
output_rows != cinfo->max_v_samp_factor ||
|
||||
(input_cols % compptr->h_samp_factor) != 0 ||
|
||||
(output_cols % cinfo->max_h_samp_factor) != 0 ||
|
||||
output_cols*compptr->h_samp_factor != input_cols*cinfo->max_h_samp_factor)
|
||||
ERREXIT(cinfo->emethods, "Bogus unsubsample parameters");
|
||||
|
||||
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
|
||||
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
|
||||
|
||||
outrow = 0;
|
||||
for (inrow = 0; inrow < input_rows; inrow++) {
|
||||
for (v = 0; v < v_expand; v++) {
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[outrow++];
|
||||
for (incol = 0; incol < input_cols; incol++) {
|
||||
invalue = GETJSAMPLE(*inptr++);
|
||||
for (h = 0; h < h_expand; h++) {
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Un-subsample pixel values of a single component.
|
||||
* This version handles the special case of a full-size component.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
fullsize_unsubsample (decompress_info_ptr cinfo, int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
|
||||
JSAMPARRAY output_data)
|
||||
{
|
||||
if (input_cols != output_cols || input_rows != output_rows) /* DEBUG */
|
||||
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
|
||||
|
||||
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clean up after a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
unsubsample_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work for now */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for unsubsampling.
|
||||
* Note that we must select a routine for each component.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselunsubsample (decompress_info_ptr cinfo)
|
||||
{
|
||||
short ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
if (cinfo->CCIR601_sampling)
|
||||
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
|
||||
compptr->v_samp_factor == cinfo->max_v_samp_factor)
|
||||
cinfo->methods->unsubsample[ci] = fullsize_unsubsample;
|
||||
else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
|
||||
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
|
||||
cinfo->methods->unsubsample[ci] = unsubsample;
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
|
||||
}
|
||||
|
||||
cinfo->methods->unsubsample_init = unsubsample_init;
|
||||
cinfo->methods->unsubsample_term = unsubsample_term;
|
||||
}
|
67
jerror.c
Normal file
67
jerror.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* jerror.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains simple error-reporting and trace-message routines.
|
||||
* These are suitable for Unix-like systems and others where writing to
|
||||
* stderr is the right thing to do. If the JPEG software is integrated
|
||||
* into a larger application, you may well need to replace these.
|
||||
*
|
||||
* The error_exit() routine should not return to its caller. Within a
|
||||
* larger application, you might want to have it do a longjmp() to return
|
||||
* control to the outer user interface routine. This should work since
|
||||
* the portable JPEG code doesn't use setjmp/longjmp. However, this won't
|
||||
* release allocated memory or close temp files --- some bookkeeping would
|
||||
* need to be added to the memory manager module to make that work.
|
||||
*
|
||||
* These routines are used by both the compression and decompression code.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h> /* to declare exit() */
|
||||
#endif
|
||||
|
||||
|
||||
static external_methods_ptr methods; /* saved for access to message_parm */
|
||||
|
||||
|
||||
METHODDEF void
|
||||
trace_message (char *msgtext)
|
||||
{
|
||||
fprintf(stderr, msgtext,
|
||||
methods->message_parm[0], methods->message_parm[1],
|
||||
methods->message_parm[2], methods->message_parm[3],
|
||||
methods->message_parm[4], methods->message_parm[5],
|
||||
methods->message_parm[6], methods->message_parm[7]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
error_exit (char *msgtext)
|
||||
{
|
||||
trace_message(msgtext);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for simple error handling.
|
||||
* The system-dependent setup routine should call this routine
|
||||
* to install the necessary method pointers in the supplied struct.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselerror (external_methods_ptr emethods)
|
||||
{
|
||||
methods = emethods; /* save struct addr for msg parm access */
|
||||
|
||||
emethods->error_exit = error_exit;
|
||||
emethods->trace_message = trace_message;
|
||||
|
||||
emethods->trace_level = 0; /* default = no tracing */
|
||||
}
|
179
jfwddct.c
Normal file
179
jfwddct.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* jfwddct.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the basic DCT (Discrete Cosine Transform)
|
||||
* transformation subroutine.
|
||||
*
|
||||
* This implementation is based on Appendix A.2 of the book
|
||||
* "Discrete Cosine Transform---Algorithms, Advantages, Applications"
|
||||
* by K.R. Rao and P. Yip (Academic Press, Inc, London, 1990).
|
||||
* It uses scaled fixed-point arithmetic instead of floating point.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/* The poop on this scaling stuff is as follows:
|
||||
*
|
||||
* Most of the numbers (after multiplication by the constants) are
|
||||
* (logically) shifted left by LG2_DCT_SCALE. This is undone by UNFIXH
|
||||
* before assignment to the output array. Note that we want an additional
|
||||
* division by 2 on the output (required by the equations).
|
||||
*
|
||||
* If right shifts are unsigned, then there is a potential problem.
|
||||
* However, shifting right by 16 and then assigning to a short
|
||||
* (assuming short = 16 bits) will keep the sign right!!
|
||||
*
|
||||
* For other shifts,
|
||||
*
|
||||
* ((x + (1 << 30)) >> shft) - (1 << (30 - shft))
|
||||
*
|
||||
* gives a nice right shift with sign (assuming no overflow). However, all the
|
||||
* scaling is such that this isn't a problem. (Is this true?)
|
||||
*/
|
||||
|
||||
|
||||
#define ONE 1L /* remove L if long > 32 bits */
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define LG2_DCT_SCALE 15
|
||||
#define RIGHT_SHIFT(_x,_shft) ((((_x) + (ONE << 30)) >> (_shft)) - (ONE << (30 - (_shft))))
|
||||
#else
|
||||
#define LG2_DCT_SCALE 16
|
||||
#define RIGHT_SHIFT(_x,_shft) ((_x) >> (_shft))
|
||||
#endif
|
||||
|
||||
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
|
||||
|
||||
#define LG2_OVERSCALE 2
|
||||
#define OVERSCALE (ONE << LG2_OVERSCALE)
|
||||
|
||||
#define FIX(x) ((INT32) ((x) * DCT_SCALE + 0.5))
|
||||
#define FIXO(x) ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
|
||||
#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
|
||||
#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
|
||||
#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)), LG2_DCT_SCALE-LG2_OVERSCALE)
|
||||
#define OVERSH(x) ((x) << LG2_OVERSCALE)
|
||||
|
||||
#define SIN_1_4 FIX(0.7071067811856476)
|
||||
#define COS_1_4 SIN_1_4
|
||||
|
||||
#define SIN_1_8 FIX(0.3826834323650898)
|
||||
#define COS_1_8 FIX(0.9238795325112870)
|
||||
#define SIN_3_8 COS_1_8
|
||||
#define COS_3_8 SIN_1_8
|
||||
|
||||
#define SIN_1_16 FIX(0.1950903220161282)
|
||||
#define COS_1_16 FIX(0.9807852804032300)
|
||||
#define SIN_7_16 COS_1_16
|
||||
#define COS_7_16 SIN_1_16
|
||||
|
||||
#define SIN_3_16 FIX(0.5555702330196022)
|
||||
#define COS_3_16 FIX(0.8314696123025450)
|
||||
#define SIN_5_16 COS_3_16
|
||||
#define COS_5_16 SIN_3_16
|
||||
|
||||
#define OSIN_1_4 FIXO(0.707106781185647)
|
||||
#define OCOS_1_4 OSIN_1_4
|
||||
|
||||
#define OSIN_1_8 FIXO(0.3826834323650898)
|
||||
#define OCOS_1_8 FIXO(0.9238795325112870)
|
||||
#define OSIN_3_8 OCOS_1_8
|
||||
#define OCOS_3_8 OSIN_1_8
|
||||
|
||||
#define OSIN_1_16 FIXO(0.1950903220161282)
|
||||
#define OCOS_1_16 FIXO(0.9807852804032300)
|
||||
#define OSIN_7_16 OCOS_1_16
|
||||
#define OCOS_7_16 OSIN_1_16
|
||||
|
||||
#define OSIN_3_16 FIXO(0.5555702330196022)
|
||||
#define OCOS_3_16 FIXO(0.8314696123025450)
|
||||
#define OSIN_5_16 OCOS_3_16
|
||||
#define OCOS_5_16 OSIN_3_16
|
||||
|
||||
|
||||
INLINE
|
||||
LOCAL void
|
||||
fast_dct_8 (DCTELEM *in, int stride)
|
||||
{
|
||||
/* tmp1x are new values of tmpx -- flashy register colourers
|
||||
* should be able to do this lot very well
|
||||
*/
|
||||
INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17;
|
||||
INT32 tmp25, tmp26;
|
||||
INT32 in0, in1, in2, in3, in4, in5, in6, in7;
|
||||
|
||||
in0 = in[ 0];
|
||||
in1 = in[stride ];
|
||||
in2 = in[stride*2];
|
||||
in3 = in[stride*3];
|
||||
in4 = in[stride*4];
|
||||
in5 = in[stride*5];
|
||||
in6 = in[stride*6];
|
||||
in7 = in[stride*7];
|
||||
|
||||
tmp0 = in7 + in0;
|
||||
tmp1 = in6 + in1;
|
||||
tmp2 = in5 + in2;
|
||||
tmp3 = in4 + in3;
|
||||
tmp4 = in3 - in4;
|
||||
tmp5 = in2 - in5;
|
||||
tmp6 = in1 - in6;
|
||||
tmp7 = in0 - in7;
|
||||
|
||||
tmp10 = tmp3 + tmp0 ;
|
||||
tmp11 = tmp2 + tmp1 ;
|
||||
tmp12 = tmp1 - tmp2 ;
|
||||
tmp13 = tmp0 - tmp3 ;
|
||||
|
||||
/* Now using tmp10, tmp11, tmp12, tmp13 */
|
||||
|
||||
in[ 0] = UNFIXH((tmp10 + tmp11) * SIN_1_4);
|
||||
in[stride*4] = UNFIXH((tmp10 - tmp11) * COS_1_4);
|
||||
|
||||
in[stride*2] = UNFIXH(tmp13*COS_1_8 + tmp12*SIN_1_8);
|
||||
in[stride*6] = UNFIXH(tmp13*SIN_1_8 - tmp12*COS_1_8);
|
||||
|
||||
tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4);
|
||||
tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4);
|
||||
|
||||
/* Now using tmp10, tmp11, tmp13, tmp14, tmp15, tmp16 */
|
||||
|
||||
tmp14 = OVERSH(tmp4) + tmp15;
|
||||
tmp25 = OVERSH(tmp4) - tmp15;
|
||||
tmp26 = OVERSH(tmp7) - tmp16;
|
||||
tmp17 = OVERSH(tmp7) + tmp16;
|
||||
|
||||
/* These are now overscaled by OVERSCALE */
|
||||
|
||||
/* tmp10, tmp11, tmp12, tmp13, tmp14, tmp25, tmp26, tmp17 */
|
||||
|
||||
in[stride ] = UNFIXH(tmp17*OCOS_1_16 + tmp14*OSIN_1_16);
|
||||
in[stride*7] = UNFIXH(tmp17*OCOS_7_16 - tmp14*OSIN_7_16);
|
||||
in[stride*5] = UNFIXH(tmp26*OCOS_5_16 + tmp25*OSIN_5_16);
|
||||
in[stride*3] = UNFIXH(tmp26*OCOS_3_16 - tmp25*OSIN_3_16);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform the forward DCT on one block of samples.
|
||||
*
|
||||
* Note that this code is specialized to the case DCTSIZE = 8.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
j_fwd_dct (DCTBLOCK data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
fast_dct_8(data+i*DCTSIZE, 1);
|
||||
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
fast_dct_8(data+i, DCTSIZE);
|
||||
}
|
73
jinclude.h
Normal file
73
jinclude.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This is the central file that's #include'd by all the JPEG .c files.
|
||||
* Its purpose is to provide a single place to fix any problems with
|
||||
* including the wrong system include files.
|
||||
* You can edit these declarations if you use a system with nonstandard
|
||||
* system include files.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* <stdio.h> is included to get the FILE typedef and NULL macro.
|
||||
* Note that the core portable-JPEG files do not actually do any I/O
|
||||
* using the stdio library; only the user interface, error handler,
|
||||
* and file reading/writing modules invoke any stdio functions.
|
||||
* (Well, we did cheat a bit in jvirtmem.c, but only if MEM_STATS is defined.)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* We need the size_t typedef, which defines the parameter type of malloc().
|
||||
* In an ANSI-conforming implementation this is provided by <stdio.h>,
|
||||
* but on non-ANSI systems it's more likely to be in <sys/types.h>.
|
||||
*/
|
||||
|
||||
#ifndef __STDC__ /* shouldn't need this if __STDC__ */
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||
* type returned by sizeof(). However, it seems there are some irrational
|
||||
* implementations out there, in which sizeof() returns an int even though
|
||||
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||
*/
|
||||
|
||||
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||
|
||||
/*
|
||||
* We need the memcpy() and strcmp() functions, plus memory zeroing.
|
||||
* ANSI and System V implementations declare these in <string.h>.
|
||||
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||
* Insert casts in these macros if not!
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <string.h>
|
||||
#define MEMZERO(voidptr,size) memset((voidptr), 0, (size))
|
||||
#else /* not STDC */
|
||||
#ifdef BSD
|
||||
#include <strings.h>
|
||||
#define MEMZERO(voidptr,size) bzero((voidptr), (size))
|
||||
#define memcpy(dest,src,size) bcopy((src), (dest), (size))
|
||||
#else /* not BSD, assume Sys V or compatible */
|
||||
#include <string.h>
|
||||
#define MEMZERO(voidptr,size) memset((voidptr), 0, (size))
|
||||
#endif /* BSD */
|
||||
#endif /* STDC */
|
||||
|
||||
|
||||
/* Now include the portable JPEG definition files. */
|
||||
|
||||
#include "jconfig.h"
|
||||
|
||||
#include "jpegdata.h"
|
812
jpegdata.h
Normal file
812
jpegdata.h
Normal file
@ -0,0 +1,812 @@
|
||||
/*
|
||||
* jpegdata.h
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file defines shared data structures for the various JPEG modules.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* You might need to change some of the following declarations if you are
|
||||
* using the JPEG software within a surrounding application program
|
||||
* or porting it to an unusual system.
|
||||
*/
|
||||
|
||||
|
||||
/* If the source or destination of image data is not to be stdio streams,
|
||||
* these types may need work. You can replace them with some kind of
|
||||
* pointer or indicator that is useful to you, or just ignore 'em.
|
||||
* Note that the user interface and the various jrdxxx/jwrxxx modules
|
||||
* will also need work for non-stdio input/output.
|
||||
*/
|
||||
|
||||
typedef FILE * JFILEREF; /* source or dest of JPEG-compressed data */
|
||||
|
||||
typedef FILE * IFILEREF; /* source or dest of non-JPEG image data */
|
||||
|
||||
|
||||
/* These defines are used in all function definitions and extern declarations.
|
||||
* You could modify them if you need to change function linkage conventions,
|
||||
* as is shown below for use with C++. Another application would be to make
|
||||
* all functions global for use with code profilers that require it.
|
||||
* NOTE: the C++ test does the right thing if you are reading this include
|
||||
* file in a C++ application to link to JPEG code that's been compiled with a
|
||||
* regular C compiler. I'm not sure it works if you try to compile the JPEG
|
||||
* code with C++.
|
||||
*/
|
||||
|
||||
#define METHODDEF static /* a function called through method pointers */
|
||||
#define LOCAL static /* a function used only in its module */
|
||||
#define GLOBAL /* a function referenced thru EXTERNs */
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C" /* a reference to a GLOBAL function */
|
||||
#else
|
||||
#define EXTERN extern /* a reference to a GLOBAL function */
|
||||
#endif
|
||||
|
||||
|
||||
/* Here is the pseudo-keyword for declaring pointers that must be "far"
|
||||
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
|
||||
* by just saying "FAR *" where such a pointer is needed. In a few places
|
||||
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
|
||||
*/
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
#define FAR far
|
||||
#else
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* The remaining declarations are not system-dependent, we hope. */
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: if you have an ancient, strict-K&R C compiler, it may choke on the
|
||||
* similarly-named fields in compress_info_struct and decompress_info_struct.
|
||||
* If this happens, you can get around it by rearranging the two structs so
|
||||
* that the similarly-named fields appear first and in the same order in
|
||||
* each struct. Since such compilers are now pretty rare, we haven't done
|
||||
* this in the portable code, preferring to maintain a logical ordering.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* This macro is used to declare a "method", that is, a function pointer. */
|
||||
/* We want to supply prototype parameters if the compiler can cope. */
|
||||
/* Note that the arglist parameter must be parenthesized! */
|
||||
|
||||
#ifdef PROTO
|
||||
#define METHOD(type,methodname,arglist) type (*methodname) arglist
|
||||
#else
|
||||
#define METHOD(type,methodname,arglist) type (*methodname) ()
|
||||
#endif
|
||||
|
||||
/* Forward references to lists of method pointers */
|
||||
typedef struct external_methods_struct * external_methods_ptr;
|
||||
typedef struct compress_methods_struct * compress_methods_ptr;
|
||||
typedef struct decompress_methods_struct * decompress_methods_ptr;
|
||||
|
||||
|
||||
/* Data structures for images containing either samples or coefficients. */
|
||||
/* Note that the topmost (leftmost) index is always color component. */
|
||||
/* On 80x86 machines, the image arrays are too big for near pointers, */
|
||||
/* but the pointer arrays can fit in near memory. */
|
||||
|
||||
typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
|
||||
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
|
||||
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
|
||||
|
||||
|
||||
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
|
||||
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
|
||||
|
||||
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
|
||||
typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
|
||||
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
|
||||
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
|
||||
|
||||
typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
|
||||
|
||||
|
||||
/* The input and output data of the DCT transform subroutines are of
|
||||
* the following type, which need not be the same as JCOEF.
|
||||
* For example, on a machine with fast floating point, it might make sense
|
||||
* to recode the DCT routines to use floating point; then DCTELEM would be
|
||||
* 'float' or 'double'.
|
||||
*/
|
||||
|
||||
typedef JCOEF DCTELEM;
|
||||
typedef DCTELEM DCTBLOCK[DCTSIZE2];
|
||||
|
||||
|
||||
/* Types for JPEG compression parameters and working tables. */
|
||||
|
||||
|
||||
typedef enum { /* defines known color spaces */
|
||||
CS_UNKNOWN, /* error/unspecified */
|
||||
CS_GRAYSCALE, /* monochrome (only 1 component) */
|
||||
CS_RGB, /* red/green/blue */
|
||||
CS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
|
||||
CS_YIQ, /* Y/I/Q */
|
||||
CS_CMYK /* C/M/Y/K */
|
||||
} COLOR_SPACE;
|
||||
|
||||
|
||||
typedef struct { /* Basic info about one component */
|
||||
/* These values are fixed over the whole image */
|
||||
/* For compression, they must be supplied by the user interface; */
|
||||
/* for decompression, they are read from the SOF marker. */
|
||||
short component_id; /* identifier for this component (0..255) */
|
||||
short component_index; /* its index in SOF or cinfo->comp_info[] */
|
||||
short h_samp_factor; /* horizontal sampling factor (1..4) */
|
||||
short v_samp_factor; /* vertical sampling factor (1..4) */
|
||||
short quant_tbl_no; /* quantization table selector (0..3) */
|
||||
/* These values may vary between scans */
|
||||
/* For compression, they must be supplied by the user interface; */
|
||||
/* for decompression, they are read from the SOS marker. */
|
||||
short dc_tbl_no; /* DC entropy table selector (0..3) */
|
||||
short ac_tbl_no; /* AC entropy table selector (0..3) */
|
||||
/* These values are computed during compression or decompression startup */
|
||||
long true_comp_width; /* component's image width in samples */
|
||||
long true_comp_height; /* component's image height in samples */
|
||||
/* the above are the logical dimensions of the subsampled image */
|
||||
/* These values are computed before starting a scan of the component */
|
||||
short MCU_width; /* number of blocks per MCU, horizontally */
|
||||
short MCU_height; /* number of blocks per MCU, vertically */
|
||||
short MCU_blocks; /* MCU_width * MCU_height */
|
||||
long subsampled_width; /* image width in samples, after expansion */
|
||||
long subsampled_height; /* image height in samples, after expansion */
|
||||
/* the above are the true_comp_xxx values rounded up to multiples of */
|
||||
/* the MCU dimensions; these are the working dimensions of the array */
|
||||
/* as it is passed through the DCT or IDCT step. NOTE: these values */
|
||||
/* differ depending on whether the component is interleaved or not!! */
|
||||
} jpeg_component_info;
|
||||
|
||||
|
||||
/* DCT coefficient quantization tables.
|
||||
* For 8-bit precision, 'INT16' should be good enough for quantization values;
|
||||
* for more precision, we go for the full 16 bits. 'INT16' provides a useful
|
||||
* speedup on many machines (multiplication & division of JCOEFs by
|
||||
* quantization values is a significant chunk of the runtime).
|
||||
* Note: the values in a QUANT_TBL are always given in zigzag order.
|
||||
*/
|
||||
#ifdef EIGHT_BIT_SAMPLES
|
||||
typedef INT16 QUANT_VAL; /* element of a quantization table */
|
||||
#else
|
||||
typedef UINT16 QUANT_VAL; /* element of a quantization table */
|
||||
#endif
|
||||
typedef QUANT_VAL QUANT_TBL[DCTSIZE2]; /* A quantization table */
|
||||
typedef QUANT_VAL * QUANT_TBL_PTR; /* pointer to same */
|
||||
|
||||
|
||||
typedef struct { /* A Huffman coding table */
|
||||
/* These two fields directly represent the contents of a JPEG DHT marker */
|
||||
UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
|
||||
/* length k bits; bits[0] is unused */
|
||||
UINT8 huffval[256]; /* The symbols, in order of incr code length */
|
||||
/* This field is used only during compression. It's initialized FALSE when
|
||||
* the table is created, and set TRUE when it's been output to the file.
|
||||
*/
|
||||
boolean sent_table; /* TRUE when table has been output */
|
||||
/* The remaining fields are computed from the above to allow more efficient
|
||||
* coding and decoding. These fields should be considered private to the
|
||||
* Huffman compression & decompression modules.
|
||||
*/
|
||||
UINT16 ehufco[256]; /* code for each symbol */
|
||||
char ehufsi[256]; /* length of code for each symbol */
|
||||
UINT16 mincode[17]; /* smallest code of length k */
|
||||
INT32 maxcode[17]; /* largest code of length k (-1 if none) */
|
||||
short valptr[17]; /* huffval[] index of 1st symbol of length k */
|
||||
} HUFF_TBL;
|
||||
|
||||
|
||||
#define NUM_QUANT_TBLS 4 /* quantization tables are numbered 0..3 */
|
||||
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
|
||||
#define NUM_ARITH_TBLS 16 /* arith-coding tables are numbered 0..15 */
|
||||
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
|
||||
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
|
||||
#define MAX_BLOCKS_IN_MCU 10 /* JPEG limit on # of blocks in an MCU */
|
||||
|
||||
|
||||
/* Working data for compression */
|
||||
|
||||
struct compress_info_struct {
|
||||
/*
|
||||
* All of these fields shall be established by the user interface before
|
||||
* calling jpeg_compress, or by the input_init or c_ui_method_selection
|
||||
* methods.
|
||||
* Most parameters can be set to reasonable defaults by j_default_compression.
|
||||
* Note that the UI must supply the storage for the main methods struct,
|
||||
* though it sets only a few of the methods there.
|
||||
*/
|
||||
compress_methods_ptr methods; /* Points to list of methods to use */
|
||||
|
||||
external_methods_ptr emethods; /* Points to list of methods to use */
|
||||
|
||||
IFILEREF input_file; /* tells input routines where to read image */
|
||||
JFILEREF output_file; /* tells output routines where to write JPEG */
|
||||
|
||||
long image_width; /* input image width */
|
||||
long image_height; /* input image height */
|
||||
short input_components; /* # of color components in input image */
|
||||
|
||||
short data_precision; /* bits of precision in image data */
|
||||
|
||||
COLOR_SPACE in_color_space; /* colorspace of input file */
|
||||
COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
|
||||
|
||||
double input_gamma; /* image gamma of input file */
|
||||
|
||||
boolean write_JFIF_header; /* should a JFIF marker be written? */
|
||||
/* These three values are not used by the JPEG code, only copied */
|
||||
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
|
||||
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
|
||||
/* ratio is defined by X_density/Y_density even when density_unit=0. */
|
||||
UINT8 density_unit; /* JFIF code for pixel size units */
|
||||
UINT16 X_density; /* Horizontal pixel density */
|
||||
UINT16 Y_density; /* Vertical pixel density */
|
||||
|
||||
short num_components; /* # of color components in JPEG image */
|
||||
jpeg_component_info * comp_info;
|
||||
/* comp_info[i] describes component that appears i'th in SOF */
|
||||
|
||||
QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
|
||||
/* ptrs to coefficient quantization tables, or NULL if not defined */
|
||||
|
||||
HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||
HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||
/* ptrs to Huffman coding tables, or NULL if not defined */
|
||||
|
||||
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arithmetic-coding tables */
|
||||
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arithmetic-coding tables */
|
||||
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arithmetic-coding tables */
|
||||
|
||||
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
|
||||
boolean interleave; /* TRUE=interleaved output, FALSE=not */
|
||||
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
|
||||
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
|
||||
|
||||
UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
|
||||
|
||||
/*
|
||||
* These fields are computed during jpeg_compress startup
|
||||
*/
|
||||
short max_h_samp_factor; /* largest h_samp_factor */
|
||||
short max_v_samp_factor; /* largest v_samp_factor */
|
||||
|
||||
/*
|
||||
* These fields are valid during any one scan
|
||||
*/
|
||||
short comps_in_scan; /* # of JPEG components output this time */
|
||||
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
|
||||
/* *cur_comp_info[i] describes component that appears i'th in SOS */
|
||||
|
||||
long MCUs_per_row; /* # of MCUs across the image */
|
||||
long MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||
|
||||
short blocks_in_MCU; /* # of DCT blocks per MCU */
|
||||
short MCU_membership[MAX_BLOCKS_IN_MCU];
|
||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||
/* i'th block in an MCU */
|
||||
|
||||
/* these fields are private data for the entropy encoder */
|
||||
JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
|
||||
JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
|
||||
UINT16 restarts_to_go; /* MDUs left in this restart interval */
|
||||
short next_restart_num; /* # of next RSTn marker (0..7) */
|
||||
};
|
||||
|
||||
typedef struct compress_info_struct * compress_info_ptr;
|
||||
|
||||
|
||||
/* Working data for decompression */
|
||||
|
||||
struct decompress_info_struct {
|
||||
/*
|
||||
* These fields shall be established by the user interface before
|
||||
* calling jpeg_decompress. Note that the UI must supply the storage for
|
||||
* the main methods struct, though it sets only a few of the methods there.
|
||||
*/
|
||||
decompress_methods_ptr methods; /* Points to list of methods to use */
|
||||
|
||||
external_methods_ptr emethods; /* Points to list of methods to use */
|
||||
|
||||
JFILEREF input_file; /* tells input routines where to read JPEG */
|
||||
IFILEREF output_file; /* tells output routines where to write image */
|
||||
|
||||
/* these can be set at d_ui_method_selection time: */
|
||||
|
||||
COLOR_SPACE out_color_space; /* colorspace of output */
|
||||
|
||||
double output_gamma; /* image gamma wanted in output */
|
||||
|
||||
boolean quantize_colors; /* T if output is a colormapped format */
|
||||
/* the following are ignored if not quantize_colors: */
|
||||
boolean two_pass_quantize; /* use two-pass color quantization? */
|
||||
boolean use_dithering; /* want color dithering? */
|
||||
int desired_number_of_colors; /* number of colors to use */
|
||||
|
||||
boolean do_block_smoothing; /* T = apply cross-block smoothing */
|
||||
boolean do_pixel_smoothing; /* T = apply post-subsampling smoothing */
|
||||
|
||||
/*
|
||||
* These fields are used for efficient buffering of data between read_jpeg_data
|
||||
* and the entropy decoding object. By using a shared buffer, we avoid copying
|
||||
* data and eliminate the need for an "unget" operation at the end of a scan.
|
||||
* The actual source of the data is known only to read_jpeg_data; see the
|
||||
* JGETC macro, below.
|
||||
* Note: the user interface is expected to allocate the input_buffer and
|
||||
* initialize bytes_in_buffer to 0. Also, for JFIF/raw-JPEG input, the UI
|
||||
* actually supplies the read_jpeg_data method.
|
||||
*/
|
||||
char * input_buffer; /* start of buffer (private to input code) */
|
||||
char * next_input_byte; /* => next byte to read from buffer */
|
||||
int bytes_in_buffer; /* # of bytes remaining in buffer */
|
||||
|
||||
/*
|
||||
* These fields are set by read_file_header or read_scan_header
|
||||
*/
|
||||
long image_width; /* overall image width */
|
||||
long image_height; /* overall image height */
|
||||
|
||||
short data_precision; /* bits of precision in image data */
|
||||
|
||||
COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
|
||||
|
||||
/* These three values are not used by the JPEG code, merely copied */
|
||||
/* from the JFIF APP0 marker (if any). */
|
||||
UINT8 density_unit; /* JFIF code for pixel size units */
|
||||
UINT16 X_density; /* Horizontal pixel density */
|
||||
UINT16 Y_density; /* Vertical pixel density */
|
||||
|
||||
short num_components; /* # of color components in JPEG image */
|
||||
jpeg_component_info * comp_info;
|
||||
/* comp_info[i] describes component that appears i'th in SOF */
|
||||
|
||||
QUANT_TBL_PTR quant_tbl_ptrs[NUM_QUANT_TBLS];
|
||||
/* ptrs to coefficient quantization tables, or NULL if not defined */
|
||||
|
||||
HUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||
HUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||
/* ptrs to Huffman coding tables, or NULL if not defined */
|
||||
|
||||
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
|
||||
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
|
||||
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
|
||||
|
||||
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
|
||||
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
|
||||
|
||||
UINT16 restart_interval;/* MDUs per restart interval, or 0 for no restart */
|
||||
|
||||
/*
|
||||
* These fields are computed during jpeg_decompress startup
|
||||
*/
|
||||
short max_h_samp_factor; /* largest h_samp_factor */
|
||||
short max_v_samp_factor; /* largest v_samp_factor */
|
||||
|
||||
short color_out_comps; /* # of color components output by color_convert */
|
||||
/* (need not match num_components) */
|
||||
short final_out_comps; /* # of color components in output image */
|
||||
/* (1 when quantizing colors, else same as color_out_comps) */
|
||||
|
||||
/*
|
||||
* These fields are valid during any one scan
|
||||
*/
|
||||
short comps_in_scan; /* # of JPEG components input this time */
|
||||
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
|
||||
/* *cur_comp_info[i] describes component that appears i'th in SOS */
|
||||
|
||||
long MCUs_per_row; /* # of MCUs across the image */
|
||||
long MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||
|
||||
short blocks_in_MCU; /* # of DCT blocks per MCU */
|
||||
short MCU_membership[MAX_BLOCKS_IN_MCU];
|
||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||
/* i'th block in an MCU */
|
||||
|
||||
/* these fields are private data for the entropy encoder */
|
||||
JCOEF last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each comp */
|
||||
JCOEF last_dc_diff[MAX_COMPS_IN_SCAN]; /* last DC diff for each comp */
|
||||
UINT16 restarts_to_go; /* MDUs left in this restart interval */
|
||||
short next_restart_num; /* # of next RSTn marker (0..7) */
|
||||
};
|
||||
|
||||
typedef struct decompress_info_struct * decompress_info_ptr;
|
||||
|
||||
|
||||
/* Macros for reading data from the decompression input buffer */
|
||||
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
#define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \
|
||||
(*(cinfo)->methods->read_jpeg_data) (cinfo) : \
|
||||
(int) *(cinfo)->next_input_byte++ )
|
||||
#else
|
||||
#define JGETC(cinfo) ( --(cinfo)->bytes_in_buffer < 0 ? \
|
||||
(*(cinfo)->methods->read_jpeg_data) (cinfo) : \
|
||||
(int) (*(cinfo)->next_input_byte++) & 0xFF )
|
||||
#endif
|
||||
|
||||
#define JUNGETC(ch,cinfo) ((cinfo)->bytes_in_buffer++, \
|
||||
*(--((cinfo)->next_input_byte)) = (ch))
|
||||
|
||||
#define MIN_UNGET 2 /* may always do at least 2 JUNGETCs */
|
||||
|
||||
|
||||
/* A virtual image has a control block whose contents are private to the
|
||||
* memory manager module (and may differ between managers). The rest of the
|
||||
* code only refers to virtual images by these pointer types.
|
||||
*/
|
||||
|
||||
typedef struct big_sarray_control * big_sarray_ptr;
|
||||
typedef struct big_barray_control * big_barray_ptr;
|
||||
|
||||
|
||||
/* Method types that need typedefs */
|
||||
|
||||
typedef METHOD(void, MCU_output_method_ptr, (compress_info_ptr cinfo,
|
||||
JBLOCK *MCU_data));
|
||||
typedef METHOD(void, MCU_output_caller_ptr, (compress_info_ptr cinfo,
|
||||
MCU_output_method_ptr output_method));
|
||||
typedef METHOD(void, subsample_ptr, (compress_info_ptr cinfo,
|
||||
int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above,
|
||||
JSAMPARRAY input_data,
|
||||
JSAMPARRAY below,
|
||||
JSAMPARRAY output_data));
|
||||
typedef METHOD(void, unsubsample_ptr, (decompress_info_ptr cinfo,
|
||||
int which_component,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPARRAY above,
|
||||
JSAMPARRAY input_data,
|
||||
JSAMPARRAY below,
|
||||
JSAMPARRAY output_data));
|
||||
typedef METHOD(void, quantize_method_ptr, (decompress_info_ptr cinfo,
|
||||
int num_rows,
|
||||
JSAMPIMAGE input_data,
|
||||
JSAMPARRAY output_workspace));
|
||||
typedef METHOD(void, quantize_caller_ptr, (decompress_info_ptr cinfo,
|
||||
quantize_method_ptr quantize_method));
|
||||
|
||||
|
||||
/* These structs contain function pointers for the various JPEG methods. */
|
||||
|
||||
/* Routines to be provided by the surrounding application, rather than the
|
||||
* portable JPEG code proper. These are the same for compression and
|
||||
* decompression.
|
||||
*/
|
||||
|
||||
struct external_methods_struct {
|
||||
/* User interface: error exit and trace message routines */
|
||||
/* NOTE: the string msgtext parameters will eventually be replaced */
|
||||
/* by an enumerated-type code so that non-English error messages */
|
||||
/* can be substituted easily. This will not be done until all the */
|
||||
/* code is in place, so that we know what messages are needed. */
|
||||
METHOD(void, error_exit, (char *msgtext));
|
||||
METHOD(void, trace_message, (char *msgtext));
|
||||
|
||||
/* Working data for error/trace facility */
|
||||
/* See macros below for the usage of these variables */
|
||||
int trace_level; /* level of detail of tracing messages */
|
||||
/* Use level 0 for unsuppressable messages (nonfatal errors) */
|
||||
/* Use levels 1, 2, 3 for successively more detailed trace options */
|
||||
|
||||
int message_parm[8]; /* store numeric parms for messages here */
|
||||
|
||||
/* Memory management */
|
||||
/* NB: alloc routines never return NULL. They exit to */
|
||||
/* error_exit if not successful. */
|
||||
METHOD(void *, alloc_small, (size_t sizeofobject));
|
||||
METHOD(void, free_small, (void *ptr));
|
||||
#ifdef NEED_FAR_POINTERS /* routines for getting far-heap space */
|
||||
METHOD(void FAR *, alloc_medium, (size_t sizeofobject));
|
||||
METHOD(void, free_medium, (void FAR *ptr));
|
||||
#else
|
||||
#define alloc_medium alloc_small
|
||||
#define free_medium free_small
|
||||
#endif
|
||||
METHOD(JSAMPARRAY, alloc_small_sarray, (long samplesperrow,
|
||||
long numrows));
|
||||
METHOD(void, free_small_sarray, (JSAMPARRAY ptr,
|
||||
long numrows));
|
||||
METHOD(JBLOCKARRAY, alloc_small_barray, (long blocksperrow,
|
||||
long numrows));
|
||||
METHOD(void, free_small_barray, (JBLOCKARRAY ptr,
|
||||
long numrows));
|
||||
METHOD(big_sarray_ptr, request_big_sarray, (long samplesperrow,
|
||||
long numrows,
|
||||
long unitheight));
|
||||
METHOD(big_barray_ptr, request_big_barray, (long blocksperrow,
|
||||
long numrows,
|
||||
long unitheight));
|
||||
METHOD(void, alloc_big_arrays, (long extra_small_samples,
|
||||
long extra_small_blocks,
|
||||
long extra_medium_space));
|
||||
METHOD(JSAMPARRAY, access_big_sarray, (big_sarray_ptr ptr,
|
||||
long start_row,
|
||||
boolean writable));
|
||||
METHOD(JBLOCKARRAY, access_big_barray, (big_barray_ptr ptr,
|
||||
long start_row,
|
||||
boolean writable));
|
||||
METHOD(void, free_big_sarray, (big_sarray_ptr ptr));
|
||||
METHOD(void, free_big_barray, (big_barray_ptr ptr));
|
||||
};
|
||||
|
||||
/* Macros to simplify using the error and trace message stuff */
|
||||
/* The first parameter is generally cinfo->emethods */
|
||||
|
||||
#define ERREXIT(emeth,msg) ((*(emeth)->error_exit) (msg))
|
||||
#define ERREXIT1(emeth,msg,p1) ((emeth)->message_parm[0] = (p1), \
|
||||
(*(emeth)->error_exit) (msg))
|
||||
#define ERREXIT2(emeth,msg,p1,p2) ((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(*(emeth)->error_exit) (msg))
|
||||
#define ERREXIT3(emeth,msg,p1,p2,p3) ((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(emeth)->message_parm[2] = (p3), \
|
||||
(*(emeth)->error_exit) (msg))
|
||||
#define ERREXIT4(emeth,msg,p1,p2,p3,p4) ((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(emeth)->message_parm[2] = (p3), \
|
||||
(emeth)->message_parm[3] = (p4), \
|
||||
(*(emeth)->error_exit) (msg))
|
||||
|
||||
#define TRACEMS(emeth,lvl,msg) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((*(emeth)->trace_message) (msg), 0) : 0)
|
||||
#define TRACEMS1(emeth,lvl,msg,p1) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((emeth)->message_parm[0] = (p1), \
|
||||
(*(emeth)->trace_message) (msg), 0) : 0)
|
||||
#define TRACEMS2(emeth,lvl,msg,p1,p2) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(*(emeth)->trace_message) (msg), 0) : 0)
|
||||
#define TRACEMS3(emeth,lvl,msg,p1,p2,p3) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(emeth)->message_parm[2] = (p3), \
|
||||
(*(emeth)->trace_message) (msg), 0) : 0)
|
||||
#define TRACEMS4(emeth,lvl,msg,p1,p2,p3,p4) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(emeth)->message_parm[2] = (p3), \
|
||||
(emeth)->message_parm[3] = (p4), \
|
||||
(*(emeth)->trace_message) (msg), 0) : 0)
|
||||
#define TRACEMS8(emeth,lvl,msg,p1,p2,p3,p4,p5,p6,p7,p8) \
|
||||
( (emeth)->trace_level >= (lvl) ? \
|
||||
((emeth)->message_parm[0] = (p1), \
|
||||
(emeth)->message_parm[1] = (p2), \
|
||||
(emeth)->message_parm[2] = (p3), \
|
||||
(emeth)->message_parm[3] = (p4), \
|
||||
(emeth)->message_parm[4] = (p5), \
|
||||
(emeth)->message_parm[5] = (p6), \
|
||||
(emeth)->message_parm[6] = (p7), \
|
||||
(emeth)->message_parm[7] = (p8), \
|
||||
(*(emeth)->trace_message) (msg), 0) : 0)
|
||||
|
||||
|
||||
/* Methods used during JPEG compression. */
|
||||
|
||||
struct compress_methods_struct {
|
||||
/* Hook for user interface to get control after input_init */
|
||||
METHOD(void, c_ui_method_selection, (compress_info_ptr cinfo));
|
||||
/* Input image reading & conversion to standard form */
|
||||
METHOD(void, input_init, (compress_info_ptr cinfo));
|
||||
METHOD(void, get_input_row, (compress_info_ptr cinfo,
|
||||
JSAMPARRAY pixel_row));
|
||||
METHOD(void, input_term, (compress_info_ptr cinfo));
|
||||
/* Gamma and color space conversion */
|
||||
METHOD(void, colorin_init, (compress_info_ptr cinfo));
|
||||
METHOD(void, get_sample_rows, (compress_info_ptr cinfo,
|
||||
int rows_to_read,
|
||||
JSAMPIMAGE image_data));
|
||||
METHOD(void, colorin_term, (compress_info_ptr cinfo));
|
||||
/* Expand picture data at edges */
|
||||
METHOD(void, edge_expand, (compress_info_ptr cinfo,
|
||||
long input_cols, int input_rows,
|
||||
long output_cols, int output_rows,
|
||||
JSAMPIMAGE image_data));
|
||||
/* Subsample pixel values of a single component */
|
||||
/* There can be a different subsample method for each component */
|
||||
METHOD(void, subsample_init, (compress_info_ptr cinfo));
|
||||
subsample_ptr subsample[MAX_COMPS_IN_SCAN];
|
||||
METHOD(void, subsample_term, (compress_info_ptr cinfo));
|
||||
/* Extract samples in MCU order, process & hand off to output_method */
|
||||
/* The input is always exactly N MCU rows worth of data */
|
||||
METHOD(void, extract_init, (compress_info_ptr cinfo));
|
||||
METHOD(void, extract_MCUs, (compress_info_ptr cinfo,
|
||||
JSAMPIMAGE image_data,
|
||||
int num_mcu_rows,
|
||||
MCU_output_method_ptr output_method));
|
||||
METHOD(void, extract_term, (compress_info_ptr cinfo));
|
||||
/* Entropy encoding parameter optimization */
|
||||
METHOD(void, entropy_optimize, (compress_info_ptr cinfo,
|
||||
MCU_output_caller_ptr source_method));
|
||||
/* Entropy encoding */
|
||||
METHOD(void, entropy_encoder_init, (compress_info_ptr cinfo));
|
||||
METHOD(void, entropy_encode, (compress_info_ptr cinfo,
|
||||
JBLOCK *MCU_data));
|
||||
METHOD(void, entropy_encoder_term, (compress_info_ptr cinfo));
|
||||
/* JPEG file header construction */
|
||||
METHOD(void, write_file_header, (compress_info_ptr cinfo));
|
||||
METHOD(void, write_scan_header, (compress_info_ptr cinfo));
|
||||
METHOD(void, write_jpeg_data, (compress_info_ptr cinfo,
|
||||
char *dataptr,
|
||||
int datacount));
|
||||
METHOD(void, write_scan_trailer, (compress_info_ptr cinfo));
|
||||
METHOD(void, write_file_trailer, (compress_info_ptr cinfo));
|
||||
/* Pipeline control */
|
||||
METHOD(void, c_pipeline_controller, (compress_info_ptr cinfo));
|
||||
METHOD(void, entropy_output, (compress_info_ptr cinfo,
|
||||
char *dataptr,
|
||||
int datacount));
|
||||
/* Overall control */
|
||||
METHOD(void, c_per_scan_method_selection, (compress_info_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Methods used during JPEG decompression. */
|
||||
|
||||
struct decompress_methods_struct {
|
||||
/* Hook for user interface to get control after reading file header */
|
||||
METHOD(void, d_ui_method_selection, (decompress_info_ptr cinfo));
|
||||
/* JPEG file scanning */
|
||||
/* Note: user interface supplies read_jpeg_data for JFIF/raw-JPEG
|
||||
* reading. For file formats that require random access (eg, TIFF)
|
||||
* the JPEG file header module will override the UI read_jpeg_data.
|
||||
*/
|
||||
METHOD(void, read_file_header, (decompress_info_ptr cinfo));
|
||||
METHOD(boolean, read_scan_header, (decompress_info_ptr cinfo));
|
||||
METHOD(int, read_jpeg_data, (decompress_info_ptr cinfo));
|
||||
METHOD(void, read_scan_trailer, (decompress_info_ptr cinfo));
|
||||
METHOD(void, read_file_trailer, (decompress_info_ptr cinfo));
|
||||
/* Entropy decoding */
|
||||
METHOD(void, entropy_decoder_init, (decompress_info_ptr cinfo));
|
||||
METHOD(void, entropy_decode, (decompress_info_ptr cinfo,
|
||||
JBLOCK *MCU_data));
|
||||
METHOD(void, entropy_decoder_term, (decompress_info_ptr cinfo));
|
||||
/* MCU disassembly: fetch MCUs from entropy_decode, build coef array */
|
||||
METHOD(void, disassemble_init, (decompress_info_ptr cinfo));
|
||||
METHOD(void, disassemble_MCU, (decompress_info_ptr cinfo,
|
||||
JBLOCKIMAGE image_data));
|
||||
METHOD(void, disassemble_term, (decompress_info_ptr cinfo));
|
||||
/* Cross-block smoothing */
|
||||
METHOD(void, smooth_coefficients, (decompress_info_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
JBLOCKROW above,
|
||||
JBLOCKROW currow,
|
||||
JBLOCKROW below,
|
||||
JBLOCKROW output));
|
||||
/* Un-subsample pixel values of a single component */
|
||||
/* There can be a different unsubsample method for each component */
|
||||
METHOD(void, unsubsample_init, (decompress_info_ptr cinfo));
|
||||
unsubsample_ptr unsubsample[MAX_COMPS_IN_SCAN];
|
||||
METHOD(void, unsubsample_term, (decompress_info_ptr cinfo));
|
||||
/* Gamma and color space conversion */
|
||||
METHOD(void, colorout_init, (decompress_info_ptr cinfo));
|
||||
METHOD(void, color_convert, (decompress_info_ptr cinfo,
|
||||
int num_rows,
|
||||
JSAMPIMAGE input_data,
|
||||
JSAMPIMAGE output_data));
|
||||
METHOD(void, colorout_term, (decompress_info_ptr cinfo));
|
||||
/* Color quantization */
|
||||
METHOD(void, color_quant_init, (decompress_info_ptr cinfo));
|
||||
METHOD(void, color_quantize, (decompress_info_ptr cinfo,
|
||||
int num_rows,
|
||||
JSAMPIMAGE input_data,
|
||||
JSAMPARRAY output_data));
|
||||
METHOD(void, color_quant_prescan, (decompress_info_ptr cinfo,
|
||||
int num_rows,
|
||||
JSAMPIMAGE image_data));
|
||||
METHOD(void, color_quant_doit, (decompress_info_ptr cinfo,
|
||||
quantize_caller_ptr source_method));
|
||||
METHOD(void, color_quant_term, (decompress_info_ptr cinfo));
|
||||
/* Output image writing */
|
||||
METHOD(void, output_init, (decompress_info_ptr cinfo));
|
||||
METHOD(void, put_color_map, (decompress_info_ptr cinfo,
|
||||
int num_colors, JSAMPARRAY colormap));
|
||||
METHOD(void, put_pixel_rows, (decompress_info_ptr cinfo,
|
||||
int num_rows,
|
||||
JSAMPIMAGE pixel_data));
|
||||
METHOD(void, output_term, (decompress_info_ptr cinfo));
|
||||
/* Pipeline control */
|
||||
METHOD(void, d_pipeline_controller, (decompress_info_ptr cinfo));
|
||||
/* Overall control */
|
||||
METHOD(void, d_per_scan_method_selection, (decompress_info_ptr cinfo));
|
||||
};
|
||||
|
||||
|
||||
/* External declarations for routines that aren't called via method ptrs. */
|
||||
/* Note: use "j" as first char of names to minimize namespace pollution. */
|
||||
/* The PP macro hides prototype parameters from compilers that can't cope. */
|
||||
|
||||
#ifdef PROTO
|
||||
#define PP(arglist) arglist
|
||||
#else
|
||||
#define PP(arglist) ()
|
||||
#endif
|
||||
|
||||
|
||||
/* main entry for compression */
|
||||
EXTERN void jpeg_compress PP((compress_info_ptr cinfo));
|
||||
/* default parameter setup for compression */
|
||||
EXTERN void j_default_compression PP((compress_info_ptr cinfo, int quality));
|
||||
EXTERN void j_monochrome_default PP((compress_info_ptr cinfo));
|
||||
EXTERN void j_set_quality PP((compress_info_ptr cinfo, int quality,
|
||||
boolean force_baseline));
|
||||
EXTERN void j_free_defaults PP((compress_info_ptr cinfo));
|
||||
|
||||
/* main entry for decompression */
|
||||
EXTERN void jpeg_decompress PP((decompress_info_ptr cinfo));
|
||||
|
||||
/* forward DCT */
|
||||
EXTERN void j_fwd_dct PP((DCTBLOCK data));
|
||||
/* inverse DCT */
|
||||
EXTERN void j_rev_dct PP((DCTBLOCK data));
|
||||
|
||||
/* utility routines in jutils.c */
|
||||
EXTERN long jround_up PP((long a, long b));
|
||||
EXTERN void jcopy_sample_rows PP((JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, long num_cols));
|
||||
EXTERN void jcopy_block_row PP((JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
long num_blocks));
|
||||
EXTERN void jzero_far PP((void FAR * target, size_t bytestozero));
|
||||
|
||||
/* method selection routines for compression modules */
|
||||
EXTERN void jselcpipeline PP((compress_info_ptr cinfo)); /* jcpipe.c */
|
||||
EXTERN void jselchuffman PP((compress_info_ptr cinfo)); /* jchuff.c */
|
||||
EXTERN void jselcarithmetic PP((compress_info_ptr cinfo)); /* jcarith.c */
|
||||
EXTERN void jselexpand PP((compress_info_ptr cinfo)); /* jcexpand.c */
|
||||
EXTERN void jselsubsample PP((compress_info_ptr cinfo)); /* jcsample.c */
|
||||
EXTERN void jselcmcu PP((compress_info_ptr cinfo)); /* jcmcu.c */
|
||||
EXTERN void jselccolor PP((compress_info_ptr cinfo)); /* jccolor.c */
|
||||
/* The user interface should call one of these to select input format: */
|
||||
EXTERN void jselrgif PP((compress_info_ptr cinfo)); /* jrdgif.c */
|
||||
EXTERN void jselrppm PP((compress_info_ptr cinfo)); /* jrdppm.c */
|
||||
/* and one of these to select output header format: */
|
||||
EXTERN void jselwjfif PP((compress_info_ptr cinfo)); /* jwrjfif.c */
|
||||
|
||||
/* method selection routines for decompression modules */
|
||||
EXTERN void jseldpipeline PP((decompress_info_ptr cinfo)); /* jdpipe.c */
|
||||
EXTERN void jseldhuffman PP((decompress_info_ptr cinfo)); /* jdhuff.c */
|
||||
EXTERN void jseldarithmetic PP((decompress_info_ptr cinfo)); /* jdarith.c */
|
||||
EXTERN void jseldmcu PP((decompress_info_ptr cinfo)); /* jdmcu.c */
|
||||
EXTERN void jselbsmooth PP((decompress_info_ptr cinfo)); /* jbsmooth.c */
|
||||
EXTERN void jselunsubsample PP((decompress_info_ptr cinfo)); /* jdsample.c */
|
||||
EXTERN void jseldcolor PP((decompress_info_ptr cinfo)); /* jdcolor.c */
|
||||
EXTERN void jsel1quantize PP((decompress_info_ptr cinfo)); /* jquant1.c */
|
||||
EXTERN void jsel2quantize PP((decompress_info_ptr cinfo)); /* jquant2.c */
|
||||
/* The user interface should call one of these to select input format: */
|
||||
EXTERN void jselrjfif PP((decompress_info_ptr cinfo)); /* jrdjfif.c */
|
||||
/* and one of these to select output image format: */
|
||||
EXTERN void jselwgif PP((decompress_info_ptr cinfo)); /* jwrgif.c */
|
||||
EXTERN void jselwppm PP((decompress_info_ptr cinfo)); /* jwrppm.c */
|
||||
|
||||
/* method selection routines for system-dependent modules */
|
||||
EXTERN void jselerror PP((external_methods_ptr emethods)); /* jerror.c */
|
||||
EXTERN void jselvirtmem PP((external_methods_ptr emethods)); /* jvirtmem.c */
|
||||
|
||||
/* debugging hook in jvirtmem.c */
|
||||
#ifdef MEM_STATS
|
||||
EXTERN void j_mem_stats PP((void));
|
||||
#endif
|
||||
|
||||
/* Miscellaneous useful macros */
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
#define RST0 0xD0 /* RST0 marker code */
|
387
jquant1.c
Normal file
387
jquant1.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* jquant1.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains 1-pass color quantization (color mapping) routines.
|
||||
* These routines are invoked via the methods color_quantize
|
||||
* and color_quant_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef QUANT_1PASS_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* This implementation is a fairly dumb, quick-and-dirty quantizer;
|
||||
* it's here mostly so that we can start working on colormapped output formats.
|
||||
*
|
||||
* We quantize to a color map that is selected in advance of seeing the image;
|
||||
* the map depends only on the requested number of colors (at least 8).
|
||||
* The map consists of all combinations of Ncolors[j] color values for each
|
||||
* component j; we choose Ncolors[] based on the requested # of colors.
|
||||
* We always use 0 and MAXJSAMPLE in each color (hence the minimum 8 colors).
|
||||
* Any additional color values are equally spaced between these limits.
|
||||
*
|
||||
* The result almost always needs dithering to look decent.
|
||||
*/
|
||||
|
||||
#define MAX_COMPONENTS 4 /* max components I can handle */
|
||||
|
||||
static int total_colors; /* Number of distinct output colors */
|
||||
static int Ncolors[MAX_COMPONENTS]; /* # of values alloced to each component */
|
||||
/* total_colors is the product of the Ncolors[] values */
|
||||
|
||||
static JSAMPARRAY colormap; /* The actual color map */
|
||||
/* colormap[i][j] = value of i'th color component for output pixel value j */
|
||||
|
||||
static JSAMPARRAY colorindex; /* Precomputed mapping for speed */
|
||||
/* colorindex[i][j] = index of color closest to pixel value j in component i,
|
||||
* premultiplied so that the correct mapped value for a pixel (r,g,b) is:
|
||||
* colorindex[0][r] + colorindex[1][g] + colorindex[2][b]
|
||||
*/
|
||||
|
||||
|
||||
/* Declarations for Floyd-Steinberg dithering.
|
||||
* Errors are accumulated into the arrays evenrowerrs[] and oddrowerrs[],
|
||||
* each of which have #colors * (#columns + 2) entries (so that first/last
|
||||
* pixels need not be special cases). These have resolutions of 1/16th of
|
||||
* a pixel count. The error at a given pixel is propagated to its unprocessed
|
||||
* neighbors using the standard F-S fractions,
|
||||
* ... (here) 7/16
|
||||
* 3/16 5/16 1/16
|
||||
* We work left-to-right on even rows, right-to-left on odd rows.
|
||||
*
|
||||
* Note: on a wide image, we might not have enough room in a PC's near data
|
||||
* segment to hold the error arrays; so they are allocated with alloc_medium.
|
||||
*/
|
||||
|
||||
#ifdef EIGHT_BIT_SAMPLES
|
||||
typedef short FSERROR; /* 16 bits should be enough */
|
||||
#else
|
||||
typedef INT32 FSERROR; /* may need more than 16 bits? */
|
||||
#endif
|
||||
|
||||
typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
|
||||
|
||||
static FSERRPTR evenrowerrs, oddrowerrs; /* current-row and next-row errors */
|
||||
static boolean on_odd_row; /* flag to remember which row we are on */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for one-pass color quantization.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
int max_colors = cinfo->desired_number_of_colors;
|
||||
int i,j,k, ntc, nci, blksize, blkdist, ptr, val;
|
||||
|
||||
if (cinfo->color_out_comps > MAX_COMPONENTS)
|
||||
ERREXIT1(cinfo->emethods, "Cannot quantize more than %d color components",
|
||||
MAX_COMPONENTS);
|
||||
if (max_colors > (MAXJSAMPLE+1))
|
||||
ERREXIT1(cinfo->emethods, "Cannot request more than %d quantized colors",
|
||||
MAXJSAMPLE+1);
|
||||
|
||||
/* Initialize to 2 color values for each component */
|
||||
total_colors = 1;
|
||||
for (i = 0; i < cinfo->color_out_comps; i++) {
|
||||
Ncolors[i] = 2;
|
||||
total_colors *= 2;
|
||||
}
|
||||
if (total_colors > max_colors)
|
||||
ERREXIT1(cinfo->emethods, "Cannot quantize to fewer than %d colors",
|
||||
total_colors);
|
||||
|
||||
/* Increase the number of color values until requested limit is reached. */
|
||||
/* Note that for standard RGB color space, we will have at least as many */
|
||||
/* red values as green, and at least as many green values as blue. */
|
||||
i = 0; /* component index to increase next */
|
||||
/* test calculates ntc = new total_colors if Ncolors[i] is incremented */
|
||||
while ((ntc = (total_colors / Ncolors[i]) * (Ncolors[i]+1)) <= max_colors) {
|
||||
Ncolors[i]++; /* OK, apply the increment */
|
||||
total_colors = ntc;
|
||||
i++; /* advance to next component */
|
||||
if (i >= cinfo->color_out_comps) i = 0;
|
||||
}
|
||||
|
||||
/* Report selected color counts */
|
||||
if (cinfo->color_out_comps == 3)
|
||||
TRACEMS4(cinfo->emethods, 1, "Quantizing to %d = %d*%d*%d colors",
|
||||
total_colors, Ncolors[0], Ncolors[1], Ncolors[2]);
|
||||
else
|
||||
TRACEMS1(cinfo->emethods, 1, "Quantizing to %d colors", total_colors);
|
||||
|
||||
/* Allocate and fill in the colormap and color index. */
|
||||
/* The colors are ordered in the map in standard row-major order, */
|
||||
/* i.e. rightmost (highest-indexed) color changes most rapidly. */
|
||||
|
||||
colormap = (*cinfo->emethods->alloc_small_sarray)
|
||||
((long) total_colors, (long) cinfo->color_out_comps);
|
||||
colorindex = (*cinfo->emethods->alloc_small_sarray)
|
||||
((long) (MAXJSAMPLE+1), (long) cinfo->color_out_comps);
|
||||
|
||||
/* blksize is number of adjacent repeated entries for a component */
|
||||
/* blkdist is distance between groups of identical entries for a component */
|
||||
blkdist = total_colors;
|
||||
|
||||
for (i = 0; i < cinfo->color_out_comps; i++) {
|
||||
/* fill in colormap entries for i'th color component */
|
||||
nci = Ncolors[i]; /* # of distinct values for this color */
|
||||
blksize = blkdist / nci;
|
||||
for (j = 0; j < nci; j++) {
|
||||
val = (j * MAXJSAMPLE + (nci-1)/2) / (nci-1); /* j'th value of color */
|
||||
for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
|
||||
/* fill in blksize entries beginning at ptr */
|
||||
for (k = 0; k < blksize; k++)
|
||||
colormap[i][ptr+k] = val;
|
||||
}
|
||||
}
|
||||
blkdist = blksize; /* blksize of this color is blkdist of next */
|
||||
|
||||
/* fill in colorindex entries for i'th color component */
|
||||
for (j = 0; j <= MAXJSAMPLE; j++) {
|
||||
/* compute index of color closest to pixel value j */
|
||||
val = (j * (nci-1) + CENTERJSAMPLE) / MAXJSAMPLE;
|
||||
/* premultiply so that no multiplication needed in main processing */
|
||||
val *= blksize;
|
||||
colorindex[i][j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass the colormap to the output module. Note that the output */
|
||||
/* module is allowed to save this pointer and use the map during */
|
||||
/* any put_pixel_rows call! */
|
||||
(*cinfo->methods->put_color_map) (cinfo, total_colors, colormap);
|
||||
|
||||
/* Allocate Floyd-Steinberg workspace if necessary */
|
||||
if (cinfo->use_dithering) {
|
||||
size_t arraysize = (cinfo->image_width + 2L) * cinfo->color_out_comps
|
||||
* SIZEOF(FSERROR);
|
||||
|
||||
evenrowerrs = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
|
||||
oddrowerrs = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize);
|
||||
/* we only need to zero the forward contribution for current row. */
|
||||
jzero_far((void FAR *) evenrowerrs, arraysize);
|
||||
on_odd_row = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Map some rows of pixels to the output colormapped representation.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quantize (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPARRAY output_data)
|
||||
/* General case, no dithering */
|
||||
{
|
||||
register int pixcode, ci;
|
||||
register long col;
|
||||
register int row;
|
||||
register long widthm1 = cinfo->image_width - 1;
|
||||
register int nc = cinfo->color_out_comps;
|
||||
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
for (col = widthm1; col >= 0; col--) {
|
||||
pixcode = 0;
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
pixcode += GETJSAMPLE(colorindex[ci]
|
||||
[GETJSAMPLE(input_data[ci][row][col])]);
|
||||
}
|
||||
output_data[row][col] = pixcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
color_quantize3 (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPARRAY output_data)
|
||||
/* Fast path for color_out_comps==3, no dithering */
|
||||
{
|
||||
register int pixcode;
|
||||
register JSAMPROW ptr0, ptr1, ptr2, ptrout;
|
||||
register long col;
|
||||
register int row;
|
||||
register long width = cinfo->image_width;
|
||||
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr0 = input_data[0][row];
|
||||
ptr1 = input_data[1][row];
|
||||
ptr2 = input_data[2][row];
|
||||
ptrout = output_data[row];
|
||||
for (col = width; col > 0; col--) {
|
||||
pixcode = GETJSAMPLE(colorindex[0][GETJSAMPLE(*ptr0++)]);
|
||||
pixcode += GETJSAMPLE(colorindex[1][GETJSAMPLE(*ptr1++)]);
|
||||
pixcode += GETJSAMPLE(colorindex[2][GETJSAMPLE(*ptr2++)]);
|
||||
*ptrout++ = pixcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
color_quantize_dither (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPARRAY output_data)
|
||||
/* General case, with Floyd-Steinberg dithering */
|
||||
{
|
||||
register int pixcode, ci;
|
||||
register FSERROR val;
|
||||
register FSERRPTR thisrowerr, nextrowerr;
|
||||
register long col;
|
||||
register int row;
|
||||
register long width = cinfo->image_width;
|
||||
register int nc = cinfo->color_out_comps;
|
||||
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
if (on_odd_row) {
|
||||
/* work right to left in this row */
|
||||
thisrowerr = oddrowerrs + width*nc;
|
||||
nextrowerr = evenrowerrs + width*nc;
|
||||
for (ci = 0; ci < nc; ci++) /* need only initialize this one entry */
|
||||
nextrowerr[ci] = 0;
|
||||
for (col = width - 1; col >= 0; col--) {
|
||||
/* select the output pixel value */
|
||||
pixcode = 0;
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
/* compute pixel value + accumulated error */
|
||||
val = (((FSERROR) GETJSAMPLE(input_data[ci][row][col])) << 4)
|
||||
+ thisrowerr[ci];
|
||||
if (val < 0) val = 0; /* must watch for range overflow! */
|
||||
else {
|
||||
val += 8; /* divide by 16 with proper rounding */
|
||||
val >>= 4;
|
||||
if (val > MAXJSAMPLE) val = MAXJSAMPLE;
|
||||
}
|
||||
thisrowerr[ci] = val; /* save for error propagation */
|
||||
pixcode += GETJSAMPLE(colorindex[ci][val]);
|
||||
}
|
||||
output_data[row][col] = pixcode;
|
||||
/* propagate error to adjacent pixels */
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
val = thisrowerr[ci] - GETJSAMPLE(colormap[ci][pixcode]);
|
||||
thisrowerr[ci-nc] += val * 7;
|
||||
nextrowerr[ci+nc] += val * 3;
|
||||
nextrowerr[ci ] += val * 5;
|
||||
nextrowerr[ci-nc] = val; /* not +=, since not initialized yet */
|
||||
}
|
||||
thisrowerr -= nc; /* advance error ptrs to next pixel entry */
|
||||
nextrowerr -= nc;
|
||||
}
|
||||
on_odd_row = FALSE;
|
||||
} else {
|
||||
/* work left to right in this row */
|
||||
thisrowerr = evenrowerrs + nc;
|
||||
nextrowerr = oddrowerrs + nc;
|
||||
for (ci = 0; ci < nc; ci++) /* need only initialize this one entry */
|
||||
nextrowerr[ci] = 0;
|
||||
for (col = 0; col < width; col++) {
|
||||
/* select the output pixel value */
|
||||
pixcode = 0;
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
/* compute pixel value + accumulated error */
|
||||
val = (((FSERROR) GETJSAMPLE(input_data[ci][row][col])) << 4)
|
||||
+ thisrowerr[ci];
|
||||
if (val < 0) val = 0; /* must watch for range overflow! */
|
||||
else {
|
||||
val += 8; /* divide by 16 with proper rounding */
|
||||
val >>= 4;
|
||||
if (val > MAXJSAMPLE) val = MAXJSAMPLE;
|
||||
}
|
||||
thisrowerr[ci] = val; /* save for error propagation */
|
||||
pixcode += GETJSAMPLE(colorindex[ci][val]);
|
||||
}
|
||||
output_data[row][col] = pixcode;
|
||||
/* propagate error to adjacent pixels */
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
val = thisrowerr[ci] - GETJSAMPLE(colormap[ci][pixcode]);
|
||||
thisrowerr[ci+nc] += val * 7;
|
||||
nextrowerr[ci-nc] += val * 3;
|
||||
nextrowerr[ci ] += val * 5;
|
||||
nextrowerr[ci+nc] = val; /* not +=, since not initialized yet */
|
||||
}
|
||||
thisrowerr += nc; /* advance error ptrs to next pixel entry */
|
||||
nextrowerr += nc;
|
||||
}
|
||||
on_odd_row = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* We can't free the colormap until now, since output module may use it! */
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(colormap, (long) cinfo->color_out_comps);
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(colorindex, (long) cinfo->color_out_comps);
|
||||
if (cinfo->use_dithering) {
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) evenrowerrs);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) oddrowerrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prescan some rows of pixels.
|
||||
* Not used in one-pass case.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE image_data)
|
||||
{
|
||||
ERREXIT(cinfo->emethods, "Should not get here!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do two-pass quantization.
|
||||
* Not used in one-pass case.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method)
|
||||
{
|
||||
ERREXIT(cinfo->emethods, "Should not get here!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for 1-pass color quantization.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jsel1quantize (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (! cinfo->two_pass_quantize) {
|
||||
cinfo->methods->color_quant_init = color_quant_init;
|
||||
if (cinfo->use_dithering) {
|
||||
cinfo->methods->color_quantize = color_quantize_dither;
|
||||
} else {
|
||||
if (cinfo->color_out_comps == 3)
|
||||
cinfo->methods->color_quantize = color_quantize3;
|
||||
else
|
||||
cinfo->methods->color_quantize = color_quantize;
|
||||
}
|
||||
cinfo->methods->color_quant_prescan = color_quant_prescan;
|
||||
cinfo->methods->color_quant_doit = color_quant_doit;
|
||||
cinfo->methods->color_quant_term = color_quant_term;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QUANT_1PASS_SUPPORTED */
|
122
jquant2.c
Normal file
122
jquant2.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* jquant2.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains 2-pass color quantization (color mapping) routines.
|
||||
* These routines are invoked via the methods color_quant_prescan,
|
||||
* color_quant_doit, and color_quant_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for two-pass color quantization.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
TRACEMS(cinfo->emethods, 1, "color_quant_init 2 pass");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prescan some rows of pixels.
|
||||
* Note: this could change the data being written into the big image array,
|
||||
* if there were any benefit to doing so. The doit routine is not allowed
|
||||
* to modify the big image array, because the memory manager is not required
|
||||
* to support multiple write passes on a big image.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_prescan (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE image_data)
|
||||
{
|
||||
TRACEMS1(cinfo->emethods, 2, "color_quant_prescan %d rows", num_rows);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine makes the final pass over the image data.
|
||||
* output_workspace is a one-component array of pixel dimensions at least
|
||||
* as large as the input image strip; it can be used to hold the converted
|
||||
* pixels' colormap indexes.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
final_pass (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE image_data, JSAMPARRAY output_workspace)
|
||||
{
|
||||
TRACEMS1(cinfo->emethods, 2, "final_pass %d rows", num_rows);
|
||||
/* for debug purposes, just emit input data */
|
||||
/* NB: this only works for PPM output */
|
||||
(*cinfo->methods->put_pixel_rows) (cinfo, num_rows, image_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform two-pass quantization: rescan the image data and output the
|
||||
* converted data via put_color_map and put_pixel_rows.
|
||||
* The source_method is a routine that can scan the image data; it can
|
||||
* be called as many times as desired. The processing routine called by
|
||||
* source_method has the same interface as color_quantize does in the
|
||||
* one-pass case, except it must call put_pixel_rows itself. (This allows
|
||||
* me to use multiple passes in which earlier passes don't output anything.)
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_doit (decompress_info_ptr cinfo, quantize_caller_ptr source_method)
|
||||
{
|
||||
TRACEMS(cinfo->emethods, 1, "color_quant_doit 2 pass");
|
||||
(*source_method) (cinfo, final_pass);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quant_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
TRACEMS(cinfo->emethods, 1, "color_quant_term 2 pass");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Map some rows of pixels to the output colormapped representation.
|
||||
* Not used in two-pass case.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
color_quantize (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE input_data, JSAMPARRAY output_data)
|
||||
{
|
||||
ERREXIT(cinfo->emethods, "Should not get here!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for 2-pass color quantization.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jsel2quantize (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->two_pass_quantize) {
|
||||
/* just one alternative for the moment */
|
||||
cinfo->methods->color_quant_init = color_quant_init;
|
||||
cinfo->methods->color_quant_prescan = color_quant_prescan;
|
||||
cinfo->methods->color_quant_doit = color_quant_doit;
|
||||
cinfo->methods->color_quant_term = color_quant_term;
|
||||
cinfo->methods->color_quantize = color_quantize;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
620
jrdgif.c
Normal file
620
jrdgif.c
Normal file
@ -0,0 +1,620 @@
|
||||
/*
|
||||
* jrdgif.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to read input images in GIF format.
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume input from
|
||||
* an ordinary stdio stream. They further assume that reading begins
|
||||
* at the start of the file; input_init may need work if the
|
||||
* user interface has already read some data (e.g., to determine that
|
||||
* the file is indeed GIF format).
|
||||
*
|
||||
* These routines are invoked via the methods get_input_row
|
||||
* and input_init/term.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is loosely based on giftoppm from the PBMPLUS distribution
|
||||
* of Feb. 1991. That file contains the following copyright notice:
|
||||
* +-------------------------------------------------------------------+
|
||||
* | Copyright 1990, David Koblas. |
|
||||
* | Permission to use, copy, modify, and distribute this software |
|
||||
* | and its documentation for any purpose and without fee is hereby |
|
||||
* | granted, provided that the above copyright notice appear in all |
|
||||
* | copies and that both that copyright notice and this permission |
|
||||
* | notice appear in supporting documentation. This software is |
|
||||
* | provided "as is" without express or implied warranty. |
|
||||
* +-------------------------------------------------------------------+
|
||||
*
|
||||
* We are also required to state that
|
||||
* "The Graphics Interchange Format(c) is the Copyright property of
|
||||
* CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
* CompuServe Incorporated."
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef GIF_SUPPORTED
|
||||
|
||||
|
||||
#define MAXCOLORMAPSIZE 256 /* max # of colors in a GIF colormap */
|
||||
#define NUMCOLORS 3 /* # of colors */
|
||||
#define CM_RED 0 /* color component numbers */
|
||||
#define CM_GREEN 1
|
||||
#define CM_BLUE 2
|
||||
|
||||
static JSAMPARRAY colormap; /* the colormap to use */
|
||||
/* colormap[i][j] = value of i'th color component for pixel value j */
|
||||
|
||||
#define MAX_LZW_BITS 12 /* maximum LZW code size */
|
||||
#define LZW_TABLE_SIZE (1<<MAX_LZW_BITS) /* # of possible LZW symbols */
|
||||
|
||||
/* Macros for extracting header data --- note we assume chars may be signed */
|
||||
|
||||
#define LM_to_uint(a,b) ((((b)&0xFF) << 8) | ((a)&0xFF))
|
||||
|
||||
#define BitSet(byte, bit) ((byte) & (bit))
|
||||
#define INTERLACE 0x40 /* mask for bit signifying interlaced image */
|
||||
#define COLORMAPFLAG 0x80 /* mask for bit signifying colormap presence */
|
||||
|
||||
#define ReadOK(file,buffer,len) (fread(buffer, 1, len, file) == (len))
|
||||
|
||||
/* Static vars for GetCode and LZWReadByte */
|
||||
|
||||
static char code_buf[256+4]; /* current input data block */
|
||||
static int last_byte; /* # of bytes in code_buf */
|
||||
static int last_bit; /* # of bits in code_buf */
|
||||
static int cur_bit; /* next bit index to read */
|
||||
static boolean out_of_blocks; /* TRUE if hit terminator data block */
|
||||
|
||||
static int input_code_size; /* codesize given in GIF file */
|
||||
static int clear_code,end_code; /* values for Clear and End codes */
|
||||
|
||||
static int code_size; /* current actual code size */
|
||||
static int limit_code; /* 2^code_size */
|
||||
static int max_code; /* first unused code value */
|
||||
static boolean first_time; /* flags first call to LZWReadByte */
|
||||
|
||||
/* LZW decompression tables:
|
||||
* symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1)
|
||||
* symbol_tail[K] = suffix byte of any LZW symbol K (0..LZW_TABLE_SIZE-1)
|
||||
* Note that entries 0..end_code of the above tables are not used,
|
||||
* since those symbols represent raw bytes or special codes.
|
||||
*
|
||||
* The stack represents the not-yet-used expansion of the last LZW symbol.
|
||||
* In the worst case, a symbol could expand to as many bytes as there are
|
||||
* LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack.
|
||||
* (This is conservative since that number includes the raw-byte symbols.)
|
||||
*
|
||||
* The tables are allocated from FAR heap space since they would use up
|
||||
* rather a lot of the near data space in a PC.
|
||||
*/
|
||||
|
||||
static UINT16 FAR *symbol_head; /* => table of prefix symbols */
|
||||
static UINT8 FAR *symbol_tail; /* => table of suffix bytes */
|
||||
static UINT8 FAR *symbol_stack; /* stack for symbol expansions */
|
||||
static UINT8 FAR *sp; /* stack pointer */
|
||||
|
||||
/* Static state for interlaced image processing */
|
||||
|
||||
static boolean is_interlaced; /* TRUE if have interlaced image */
|
||||
static big_sarray_ptr interlaced_image; /* full image in interlaced order */
|
||||
static long cur_row_number; /* need to know actual row number */
|
||||
static long pass2_offset; /* # of pixel rows in pass 1 */
|
||||
static long pass3_offset; /* # of pixel rows in passes 1&2 */
|
||||
static long pass4_offset; /* # of pixel rows in passes 1,2,3 */
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF void load_interlaced_image PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
|
||||
METHODDEF void get_interlaced_row PP((compress_info_ptr cinfo, JSAMPARRAY pixel_row));
|
||||
|
||||
|
||||
|
||||
LOCAL int
|
||||
ReadByte (compress_info_ptr cinfo)
|
||||
/* Read next byte from GIF file */
|
||||
{
|
||||
register FILE * infile = cinfo->input_file;
|
||||
int c;
|
||||
|
||||
if ((c = getc(infile)) == EOF)
|
||||
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
LOCAL int
|
||||
GetDataBlock (compress_info_ptr cinfo, char *buf)
|
||||
/* Read a GIF data block, which has a leading count byte */
|
||||
/* A zero-length block marks the end of a data block sequence */
|
||||
{
|
||||
int count;
|
||||
|
||||
count = ReadByte(cinfo);
|
||||
if (count > 0) {
|
||||
if (! ReadOK(cinfo->input_file, buf, count))
|
||||
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
SkipDataBlocks (compress_info_ptr cinfo)
|
||||
/* Skip a series of data blocks, until a block terminator is found */
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
while (GetDataBlock(cinfo, buf) > 0)
|
||||
/* skip */;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
ReInitLZW (void)
|
||||
/* (Re)initialize LZW state; shared code for startup and Clear processing */
|
||||
{
|
||||
code_size = input_code_size+1;
|
||||
limit_code = clear_code << 1; /* 2^code_size */
|
||||
max_code = clear_code + 2; /* first unused code value */
|
||||
sp = symbol_stack; /* init stack to empty */
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
InitLZWCode (void)
|
||||
/* Initialize for a series of LZWReadByte (and hence GetCode) calls */
|
||||
{
|
||||
/* GetCode initialization */
|
||||
last_byte = 2; /* make safe to "recopy last two bytes" */
|
||||
last_bit = 0; /* nothing in the buffer */
|
||||
cur_bit = 0; /* force buffer load on first call */
|
||||
out_of_blocks = FALSE;
|
||||
|
||||
/* LZWReadByte initialization */
|
||||
clear_code = 1 << input_code_size; /* compute special code values */
|
||||
end_code = clear_code + 1; /* note that these do not change */
|
||||
first_time = TRUE;
|
||||
ReInitLZW();
|
||||
}
|
||||
|
||||
|
||||
LOCAL int
|
||||
GetCode (compress_info_ptr cinfo)
|
||||
/* Fetch the next code_size bits from the GIF data */
|
||||
/* We assume code_size is less than 16 */
|
||||
{
|
||||
register INT32 accum;
|
||||
int offs, ret, count;
|
||||
|
||||
if ( (cur_bit+code_size) > last_bit) {
|
||||
/* Time to reload the buffer */
|
||||
if (out_of_blocks) {
|
||||
TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
|
||||
return end_code; /* fake something useful */
|
||||
}
|
||||
/* preserve last two bytes of what we have -- assume code_size <= 16 */
|
||||
code_buf[0] = code_buf[last_byte-2];
|
||||
code_buf[1] = code_buf[last_byte-1];
|
||||
/* Load more bytes; set flag if we reach the terminator block */
|
||||
if ((count = GetDataBlock(cinfo, &code_buf[2])) == 0) {
|
||||
out_of_blocks = TRUE;
|
||||
TRACEMS(cinfo->emethods, 1, "Ran out of GIF bits");
|
||||
return end_code; /* fake something useful */
|
||||
}
|
||||
/* Reset counters */
|
||||
cur_bit = (cur_bit - last_bit) + 16;
|
||||
last_byte = 2 + count;
|
||||
last_bit = last_byte * 8;
|
||||
}
|
||||
|
||||
/* Form up next 24 bits in accum */
|
||||
offs = cur_bit >> 3; /* byte containing cur_bit */
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
accum = code_buf[offs+2];
|
||||
accum <<= 8;
|
||||
accum |= code_buf[offs+1];
|
||||
accum <<= 8;
|
||||
accum |= code_buf[offs];
|
||||
#else
|
||||
accum = code_buf[offs+2] & 0xFF;
|
||||
accum <<= 8;
|
||||
accum |= code_buf[offs+1] & 0xFF;
|
||||
accum <<= 8;
|
||||
accum |= code_buf[offs] & 0xFF;
|
||||
#endif
|
||||
|
||||
/* Right-align cur_bit in accum, then mask off desired number of bits */
|
||||
accum >>= (cur_bit & 7);
|
||||
ret = ((int) accum) & ((1 << code_size) - 1);
|
||||
|
||||
cur_bit += code_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LOCAL int
|
||||
LZWReadByte (compress_info_ptr cinfo)
|
||||
/* Read an LZW-compressed byte */
|
||||
{
|
||||
static int oldcode; /* previous LZW symbol */
|
||||
static int firstcode; /* first byte of oldcode's expansion */
|
||||
register int code; /* current working code */
|
||||
int incode; /* saves actual input code */
|
||||
|
||||
/* First time, just eat the expected Clear code(s) and return next code, */
|
||||
/* which is assumed to be a raw byte. */
|
||||
if (first_time) {
|
||||
first_time = FALSE;
|
||||
do {
|
||||
code = GetCode(cinfo);
|
||||
} while (code == clear_code);
|
||||
firstcode = oldcode = code; /* make firstcode, oldcode valid! */
|
||||
return code;
|
||||
}
|
||||
|
||||
/* If any codes are stacked from a previously read symbol, return them */
|
||||
if (sp > symbol_stack)
|
||||
return *(--sp);
|
||||
|
||||
code = GetCode(cinfo);
|
||||
|
||||
if (code == clear_code) {
|
||||
/* Reinit static state, swallow any extra Clear codes, and return */
|
||||
ReInitLZW();
|
||||
do {
|
||||
code = GetCode(cinfo);
|
||||
} while (code == clear_code);
|
||||
firstcode = oldcode = code; /* gotta reinit these too */
|
||||
return code;
|
||||
}
|
||||
|
||||
if (code == end_code) {
|
||||
/* Skip the rest of the image, unless GetCode already read terminator */
|
||||
if (! out_of_blocks)
|
||||
SkipDataBlocks(cinfo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Normal raw byte or LZW symbol */
|
||||
incode = code; /* save for a moment */
|
||||
|
||||
if (code >= max_code) { /* special case for not-yet-defined symbol */
|
||||
*sp++ = firstcode; /* it will be defined as oldcode/firstcode */
|
||||
code = oldcode;
|
||||
}
|
||||
|
||||
/* If it's a symbol, expand it into the stack */
|
||||
while (code >= clear_code) {
|
||||
*sp++ = symbol_tail[code]; /* tail of symbol: a simple byte value */
|
||||
code = symbol_head[code]; /* head of symbol: another LZW symbol */
|
||||
}
|
||||
/* At this point code just represents a raw byte */
|
||||
firstcode = code; /* save for possible future use */
|
||||
|
||||
/* If there's room in table, */
|
||||
if ((code = max_code) < LZW_TABLE_SIZE) {
|
||||
/* Define a new symbol = prev sym + head of this sym's expansion */
|
||||
symbol_head[code] = oldcode;
|
||||
symbol_tail[code] = firstcode;
|
||||
max_code++;
|
||||
/* Is it time to increase code_size? */
|
||||
if ((max_code >= limit_code) && (code_size < MAX_LZW_BITS)) {
|
||||
code_size++;
|
||||
limit_code <<= 1; /* keep equal to 2^code_size */
|
||||
}
|
||||
}
|
||||
|
||||
oldcode = incode; /* save last input symbol for future use */
|
||||
return firstcode; /* return first byte of symbol's expansion */
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
ReadColorMap (compress_info_ptr cinfo, int cmaplen, JSAMPARRAY cmap)
|
||||
/* Read a GIF colormap */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cmaplen; i++) {
|
||||
cmap[CM_RED][i] = ReadByte(cinfo);
|
||||
cmap[CM_GREEN][i] = ReadByte(cinfo);
|
||||
cmap[CM_BLUE][i] = ReadByte(cinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
DoExtension (compress_info_ptr cinfo)
|
||||
/* Process an extension block */
|
||||
/* Currently we ignore 'em all */
|
||||
{
|
||||
int extlabel;
|
||||
|
||||
/* Read extension label byte */
|
||||
extlabel = ReadByte(cinfo);
|
||||
TRACEMS1(cinfo->emethods, 1, "Ignoring GIF extension block of type 0x%02x",
|
||||
extlabel);
|
||||
/* Skip the data block(s) associated with the extension */
|
||||
SkipDataBlocks(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the file header; return image size and component count.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
input_init (compress_info_ptr cinfo)
|
||||
{
|
||||
char hdrbuf[10]; /* workspace for reading control blocks */
|
||||
UINT16 width, height; /* image dimensions */
|
||||
int colormaplen, aspectRatio;
|
||||
int c;
|
||||
|
||||
/* Allocate space to store the colormap */
|
||||
colormap = (*cinfo->emethods->alloc_small_sarray)
|
||||
((long) MAXCOLORMAPSIZE, (long) NUMCOLORS);
|
||||
|
||||
/* Read and verify GIF Header */
|
||||
if (! ReadOK(cinfo->input_file, hdrbuf, 6))
|
||||
ERREXIT(cinfo->emethods, "Not a GIF file");
|
||||
if (strncmp(hdrbuf, "GIF", 3) != 0)
|
||||
ERREXIT(cinfo->emethods, "Not a GIF file");
|
||||
/* Check for expected version numbers.
|
||||
* If unknown version, give warning and try to process anyway;
|
||||
* this is per recommendation in GIF89a standard.
|
||||
*/
|
||||
if ((strncmp(hdrbuf+3, "87a", 3) != 0) &&
|
||||
(strncmp(hdrbuf+3, "89a", 3) != 0))
|
||||
TRACEMS3(cinfo->emethods, 1,
|
||||
"Warning: unexpected GIF version number '%c%c%c'",
|
||||
hdrbuf[3], hdrbuf[4], hdrbuf[5]);
|
||||
|
||||
/* Read and decipher Logical Screen Descriptor */
|
||||
if (! ReadOK(cinfo->input_file, hdrbuf, 7))
|
||||
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
|
||||
width = LM_to_uint(hdrbuf[0],hdrbuf[1]);
|
||||
height = LM_to_uint(hdrbuf[2],hdrbuf[3]);
|
||||
colormaplen = 2 << (hdrbuf[4] & 0x07);
|
||||
/* we ignore the color resolution, sort flag, and background color index */
|
||||
aspectRatio = hdrbuf[6] & 0xFF;
|
||||
if (aspectRatio != 0 && aspectRatio != 49)
|
||||
TRACEMS(cinfo->emethods, 1, "Warning: nonsquare pixels in input");
|
||||
|
||||
/* Read global colormap if header indicates it is present */
|
||||
if (BitSet(hdrbuf[4], COLORMAPFLAG))
|
||||
ReadColorMap(cinfo, colormaplen, colormap);
|
||||
|
||||
/* Scan until we reach start of desired image.
|
||||
* We don't currently support skipping images, but could add it easily.
|
||||
*/
|
||||
for (;;) {
|
||||
c = ReadByte(cinfo);
|
||||
|
||||
if (c == ';') /* GIF terminator?? */
|
||||
ERREXIT(cinfo->emethods, "Too few images in GIF file");
|
||||
|
||||
if (c == '!') { /* Extension */
|
||||
DoExtension(cinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c != ',') { /* Not an image separator? */
|
||||
TRACEMS1(cinfo->emethods, 1, "Bogus input char 0x%02x, ignoring", c);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read and decipher Local Image Descriptor */
|
||||
if (! ReadOK(cinfo->input_file, hdrbuf, 9))
|
||||
ERREXIT(cinfo->emethods, "Premature EOF in GIF file");
|
||||
/* we ignore top/left position info, also sort flag */
|
||||
width = LM_to_uint(hdrbuf[4],hdrbuf[5]);
|
||||
height = LM_to_uint(hdrbuf[6],hdrbuf[7]);
|
||||
is_interlaced = BitSet(hdrbuf[8], INTERLACE);
|
||||
colormaplen = 2 << (hdrbuf[8] & 0x07);
|
||||
|
||||
/* Read local colormap if header indicates it is present */
|
||||
/* Note: if we wanted to support skipping images, */
|
||||
/* we'd need to skip rather than read colormap for ignored images */
|
||||
if (BitSet(hdrbuf[8], COLORMAPFLAG))
|
||||
ReadColorMap(cinfo, colormaplen, colormap);
|
||||
|
||||
input_code_size = ReadByte(cinfo); /* get minimum-code-size byte */
|
||||
if (input_code_size < 2 || input_code_size >= MAX_LZW_BITS)
|
||||
ERREXIT1(cinfo->emethods, "Bogus codesize %d", input_code_size);
|
||||
|
||||
/* Reached desired image, so break out of loop */
|
||||
/* If we wanted to skip this image, */
|
||||
/* we'd call SkipDataBlocks and then continue the loop */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prepare to read selected image: first initialize LZW decompressor */
|
||||
symbol_head = (UINT16 FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(LZW_TABLE_SIZE * SIZEOF(UINT16));
|
||||
symbol_tail = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(LZW_TABLE_SIZE * SIZEOF(UINT8));
|
||||
symbol_stack = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(LZW_TABLE_SIZE * SIZEOF(UINT8));
|
||||
InitLZWCode();
|
||||
|
||||
/*
|
||||
* If image is interlaced, we read it into a full-size sample array,
|
||||
* decompressing as we go; then get_input_row selects rows from the
|
||||
* sample array in the proper order.
|
||||
*/
|
||||
if (is_interlaced) {
|
||||
/* We request the big array now, but can't access it until the pipeline
|
||||
* controller causes all the big arrays to be allocated. Hence, the
|
||||
* actual work of reading the image is postponed until the first call
|
||||
* of get_input_row.
|
||||
*/
|
||||
interlaced_image = (*cinfo->emethods->request_big_sarray)
|
||||
((long) width, (long) height, (long) 1);
|
||||
cinfo->methods->get_input_row = load_interlaced_image;
|
||||
}
|
||||
|
||||
/* Return info about the image. */
|
||||
cinfo->input_components = NUMCOLORS;
|
||||
cinfo->in_color_space = CS_RGB;
|
||||
cinfo->image_width = width;
|
||||
cinfo->image_height = height;
|
||||
cinfo->data_precision = 8;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
* This version is used for noninterlaced GIF images:
|
||||
* we read directly from the GIF file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
|
||||
{
|
||||
register JSAMPROW ptr0, ptr1, ptr2;
|
||||
register long col;
|
||||
register int c;
|
||||
|
||||
ptr0 = pixel_row[0];
|
||||
ptr1 = pixel_row[1];
|
||||
ptr2 = pixel_row[2];
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
if ((c = LZWReadByte(cinfo)) < 0)
|
||||
ERREXIT(cinfo->emethods, "Premature end of GIF image");
|
||||
*ptr0++ = colormap[CM_RED][c];
|
||||
*ptr1++ = colormap[CM_GREEN][c];
|
||||
*ptr2++ = colormap[CM_BLUE][c];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
* This version is used for the first call on get_input_row when
|
||||
* reading an interlaced GIF file: we read the whole image into memory.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
load_interlaced_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
|
||||
{
|
||||
JSAMPARRAY image_ptr;
|
||||
register JSAMPROW sptr;
|
||||
register long col;
|
||||
register int c;
|
||||
long row;
|
||||
|
||||
/* Read the interlaced image into the big array we've created. */
|
||||
for (row = 0; row < cinfo->image_height; row++) {
|
||||
image_ptr = (*cinfo->emethods->access_big_sarray)
|
||||
(interlaced_image, row, TRUE);
|
||||
sptr = image_ptr[0];
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
if ((c = LZWReadByte(cinfo)) < 0)
|
||||
ERREXIT(cinfo->emethods, "Premature end of GIF image");
|
||||
*sptr++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace method pointer so subsequent calls don't come here. */
|
||||
cinfo->methods->get_input_row = get_interlaced_row;
|
||||
/* Initialize for get_interlaced_row, and perform first call on it. */
|
||||
cur_row_number = 0;
|
||||
pass2_offset = (cinfo->image_height + 7L) / 8L;
|
||||
pass3_offset = pass2_offset + (cinfo->image_height + 3L) / 8L;
|
||||
pass4_offset = pass3_offset + (cinfo->image_height + 1L) / 4L;
|
||||
|
||||
get_interlaced_row(cinfo, pixel_row);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
* This version is used for interlaced GIF images:
|
||||
* we read from the big in-memory image.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_interlaced_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
|
||||
{
|
||||
JSAMPARRAY image_ptr;
|
||||
register JSAMPROW sptr, ptr0, ptr1, ptr2;
|
||||
register long col;
|
||||
register int c;
|
||||
long irow;
|
||||
|
||||
/* Figure out which row of interlaced image is needed, and access it. */
|
||||
switch ((int) (cur_row_number & 7L)) {
|
||||
case 0: /* first-pass row */
|
||||
irow = cur_row_number >> 3;
|
||||
break;
|
||||
case 4: /* second-pass row */
|
||||
irow = (cur_row_number >> 3) + pass2_offset;
|
||||
break;
|
||||
case 2: /* third-pass row */
|
||||
case 6:
|
||||
irow = (cur_row_number >> 2) + pass3_offset;
|
||||
break;
|
||||
default: /* fourth-pass row */
|
||||
irow = (cur_row_number >> 1) + pass4_offset;
|
||||
break;
|
||||
}
|
||||
image_ptr = (*cinfo->emethods->access_big_sarray)
|
||||
(interlaced_image, irow, FALSE);
|
||||
/* Scan the row, expand colormap, and output */
|
||||
sptr = image_ptr[0];
|
||||
ptr0 = pixel_row[0];
|
||||
ptr1 = pixel_row[1];
|
||||
ptr2 = pixel_row[2];
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
c = GETJSAMPLE(*sptr++);
|
||||
*ptr0++ = colormap[CM_RED][c];
|
||||
*ptr1++ = colormap[CM_GREEN][c];
|
||||
*ptr2++ = colormap[CM_BLUE][c];
|
||||
}
|
||||
cur_row_number++; /* for next time */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
input_term (compress_info_ptr cinfo)
|
||||
{
|
||||
if (is_interlaced) {
|
||||
(*cinfo->emethods->free_big_sarray) (interlaced_image);
|
||||
}
|
||||
(*cinfo->emethods->free_small_sarray)
|
||||
(colormap, (long) NUMCOLORS);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) symbol_head);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) symbol_tail);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) symbol_stack);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for GIF format input.
|
||||
* Note that this must be called by the user interface before calling
|
||||
* jpeg_compress. If multiple input formats are supported, the
|
||||
* user interface is responsible for discovering the file format and
|
||||
* calling the appropriate method selection routine.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselrgif (compress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->input_init = input_init;
|
||||
cinfo->methods->get_input_row = get_input_row; /* assume uninterlaced */
|
||||
cinfo->methods->input_term = input_term;
|
||||
}
|
||||
|
||||
#endif /* GIF_SUPPORTED */
|
733
jrdjfif.c
Normal file
733
jrdjfif.c
Normal file
@ -0,0 +1,733 @@
|
||||
/*
|
||||
* jrdjfif.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to decode standard JPEG file headers/markers.
|
||||
* This will handle baseline and JFIF-convention JPEG files.
|
||||
*
|
||||
* This module relies on the JGETC macro and the read_jpeg_data method (which
|
||||
* is provided by the user interface) to read from the JPEG data stream.
|
||||
* Therefore, this module is NOT dependent on any particular assumption about
|
||||
* the data source. This fact does not carry over to more complex JPEG file
|
||||
* formats such as JPEG-in-TIFF; those format control modules may well need to
|
||||
* assume stdio input.
|
||||
*
|
||||
* read_file_header assumes that reading begins at the JPEG SOI marker
|
||||
* (although it will skip non-FF bytes looking for a JPEG marker).
|
||||
* The user interface must position the data stream appropriately.
|
||||
*
|
||||
* These routines are invoked via the methods read_file_header,
|
||||
* read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef JFIF_SUPPORTED
|
||||
|
||||
|
||||
typedef enum { /* JPEG marker codes */
|
||||
M_SOF0 = 0xc0,
|
||||
M_SOF1 = 0xc1,
|
||||
M_SOF2 = 0xc2,
|
||||
M_SOF3 = 0xc3,
|
||||
|
||||
M_SOF5 = 0xc5,
|
||||
M_SOF6 = 0xc6,
|
||||
M_SOF7 = 0xc7,
|
||||
|
||||
M_JPG = 0xc8,
|
||||
M_SOF9 = 0xc9,
|
||||
M_SOF10 = 0xca,
|
||||
M_SOF11 = 0xcb,
|
||||
|
||||
M_SOF13 = 0xcd,
|
||||
M_SOF14 = 0xce,
|
||||
M_SOF15 = 0xcf,
|
||||
|
||||
M_DHT = 0xc4,
|
||||
|
||||
M_DAC = 0xcc,
|
||||
|
||||
M_RST0 = 0xd0,
|
||||
M_RST1 = 0xd1,
|
||||
M_RST2 = 0xd2,
|
||||
M_RST3 = 0xd3,
|
||||
M_RST4 = 0xd4,
|
||||
M_RST5 = 0xd5,
|
||||
M_RST6 = 0xd6,
|
||||
M_RST7 = 0xd7,
|
||||
|
||||
M_SOI = 0xd8,
|
||||
M_EOI = 0xd9,
|
||||
M_SOS = 0xda,
|
||||
M_DQT = 0xdb,
|
||||
M_DNL = 0xdc,
|
||||
M_DRI = 0xdd,
|
||||
M_DHP = 0xde,
|
||||
M_EXP = 0xdf,
|
||||
|
||||
M_APP0 = 0xe0,
|
||||
M_APP15 = 0xef,
|
||||
|
||||
M_JPG0 = 0xf0,
|
||||
M_JPG13 = 0xfd,
|
||||
M_COM = 0xfe,
|
||||
|
||||
M_TEM = 0x01,
|
||||
|
||||
M_ERROR = 0x100
|
||||
} JPEG_MARKER;
|
||||
|
||||
|
||||
/*
|
||||
* Reload the input buffer after it's been emptied, and return the next byte.
|
||||
* This is exported for direct use by the entropy decoder.
|
||||
* See the JGETC macro for calling conditions.
|
||||
*
|
||||
* For this header control module, read_jpeg_data is supplied by the
|
||||
* user interface. However, header formats that require random access
|
||||
* to the input file would need to supply their own code. This code is
|
||||
* left here to indicate what is required.
|
||||
*/
|
||||
|
||||
#if 0 /* not needed in this module */
|
||||
|
||||
METHODDEF int
|
||||
read_jpeg_data (decompress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->bytes_in_buffer = fread(cinfo->input_buffer + MIN_UNGET,
|
||||
1, JPEG_BUF_SIZE,
|
||||
cinfo->input_file);
|
||||
|
||||
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
|
||||
|
||||
if (cinfo->bytes_in_buffer <= 0)
|
||||
ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
|
||||
|
||||
return JGETC(cinfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Routines to parse JPEG markers & save away the useful info.
|
||||
*/
|
||||
|
||||
|
||||
LOCAL INT32
|
||||
get_2bytes (decompress_info_ptr cinfo)
|
||||
/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
|
||||
{
|
||||
INT32 a;
|
||||
|
||||
a = JGETC(cinfo);
|
||||
return (a << 8) + JGETC(cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
skip_variable (decompress_info_ptr cinfo, int code)
|
||||
/* Skip over an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
INT32 length;
|
||||
|
||||
length = get_2bytes(cinfo);
|
||||
|
||||
TRACEMS2(cinfo->emethods, 1,
|
||||
"Skipping marker 0x%02x, length %d", code, length);
|
||||
|
||||
for (length -= 2; length > 0; length--)
|
||||
(void) JGETC(cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_dht (decompress_info_ptr cinfo)
|
||||
/* Process a DHT marker */
|
||||
{
|
||||
INT32 length;
|
||||
UINT8 bits[17];
|
||||
UINT8 huffval[256];
|
||||
int i, index, count;
|
||||
HUFF_TBL **htblptr;
|
||||
|
||||
length = get_2bytes(cinfo)-2;
|
||||
|
||||
while (length > 0) {
|
||||
index = JGETC(cinfo);
|
||||
|
||||
TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
|
||||
|
||||
bits[0] = 0;
|
||||
count = 0;
|
||||
for (i = 1; i <= 16; i++) {
|
||||
bits[i] = JGETC(cinfo);
|
||||
count += bits[i];
|
||||
}
|
||||
|
||||
TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
|
||||
bits[1], bits[2], bits[3], bits[4],
|
||||
bits[5], bits[6], bits[7], bits[8]);
|
||||
TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
|
||||
bits[9], bits[10], bits[11], bits[12],
|
||||
bits[13], bits[14], bits[15], bits[16]);
|
||||
|
||||
if (count > 256)
|
||||
ERREXIT(cinfo->emethods, "Bogus DHT counts");
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
huffval[i] = JGETC(cinfo);
|
||||
|
||||
length -= 1 + 16 + count;
|
||||
|
||||
if (index & 0x10) { /* AC table definition */
|
||||
index -= 0x10;
|
||||
htblptr = &cinfo->ac_huff_tbl_ptrs[index];
|
||||
} else { /* DC table definition */
|
||||
htblptr = &cinfo->dc_huff_tbl_ptrs[index];
|
||||
}
|
||||
|
||||
if (index < 0 || index >= NUM_HUFF_TBLS)
|
||||
ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index);
|
||||
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
|
||||
|
||||
memcpy((void *) (*htblptr)->bits, (void *) bits,
|
||||
SIZEOF((*htblptr)->bits));
|
||||
memcpy((void *) (*htblptr)->huffval, (void *) huffval,
|
||||
SIZEOF((*htblptr)->huffval));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_dac (decompress_info_ptr cinfo)
|
||||
/* Process a DAC marker */
|
||||
{
|
||||
INT32 length;
|
||||
int index, val;
|
||||
|
||||
length = get_2bytes(cinfo)-2;
|
||||
|
||||
while (length > 0) {
|
||||
index = JGETC(cinfo);
|
||||
val = JGETC(cinfo);
|
||||
|
||||
TRACEMS2(cinfo->emethods, 1,
|
||||
"Define Arithmetic Table 0x%02x: 0x%02x", index, val);
|
||||
|
||||
if (index < 0 || index >= (2*NUM_ARITH_TBLS))
|
||||
ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index);
|
||||
|
||||
if (index >= NUM_ARITH_TBLS) { /* define AC table */
|
||||
cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = val;
|
||||
} else { /* define DC table */
|
||||
cinfo->arith_dc_L[index] = val & 0x0F;
|
||||
cinfo->arith_dc_U[index] = val >> 4;
|
||||
if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
|
||||
ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
|
||||
}
|
||||
|
||||
length -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_dqt (decompress_info_ptr cinfo)
|
||||
/* Process a DQT marker */
|
||||
{
|
||||
INT32 length;
|
||||
int n, i, prec;
|
||||
UINT16 tmp;
|
||||
QUANT_TBL_PTR quant_ptr;
|
||||
|
||||
length = get_2bytes(cinfo) - 2;
|
||||
|
||||
while (length > 0) {
|
||||
n = JGETC(cinfo);
|
||||
prec = n >> 4;
|
||||
n &= 0x0F;
|
||||
|
||||
TRACEMS2(cinfo->emethods, 1,
|
||||
"Define Quantization Table %d precision %d", n, prec);
|
||||
|
||||
if (n >= NUM_QUANT_TBLS)
|
||||
ERREXIT1(cinfo->emethods, "Bogus table number %d", n);
|
||||
|
||||
if (cinfo->quant_tbl_ptrs[n] == NULL)
|
||||
cinfo->quant_tbl_ptrs[n] = (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
|
||||
quant_ptr = cinfo->quant_tbl_ptrs[n];
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
tmp = JGETC(cinfo);
|
||||
if (prec)
|
||||
tmp = (tmp<<8) + JGETC(cinfo);
|
||||
quant_ptr[i] = tmp;
|
||||
}
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i += 8) {
|
||||
TRACEMS8(cinfo->emethods, 2, " %4d %4d %4d %4d %4d %4d %4d %4d",
|
||||
quant_ptr[i ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
|
||||
quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
|
||||
}
|
||||
|
||||
length -= DCTSIZE2+1;
|
||||
if (prec) length -= DCTSIZE2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_dri (decompress_info_ptr cinfo)
|
||||
/* Process a DRI marker */
|
||||
{
|
||||
if (get_2bytes(cinfo) != 4)
|
||||
ERREXIT(cinfo->emethods, "Bogus length in DRI");
|
||||
|
||||
cinfo->restart_interval = get_2bytes(cinfo);
|
||||
|
||||
TRACEMS1(cinfo->emethods, 1,
|
||||
"Define Restart Interval %d", cinfo->restart_interval);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_app0 (decompress_info_ptr cinfo)
|
||||
/* Process an APP0 marker */
|
||||
{
|
||||
#define JFIF_LEN 14
|
||||
INT32 length;
|
||||
UINT8 b[JFIF_LEN];
|
||||
int buffp;
|
||||
|
||||
length = get_2bytes(cinfo) - 2;
|
||||
|
||||
/* See if a JFIF APP0 marker is present */
|
||||
|
||||
if (length >= JFIF_LEN) {
|
||||
for (buffp = 0; buffp < JFIF_LEN; buffp++)
|
||||
b[buffp] = JGETC(cinfo);
|
||||
length -= JFIF_LEN;
|
||||
|
||||
if (b[0]=='J' && b[1]=='F' && b[2]=='I' && b[3]=='F' && b[4]==0) {
|
||||
/* Found JFIF APP0 marker: check version */
|
||||
/* Major version must be 1 */
|
||||
if (b[5] != 1)
|
||||
ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
|
||||
b[5], b[6]);
|
||||
/* Minor version should be 0 or 1, but try to process anyway if newer */
|
||||
if (b[6] != 0 && b[6] != 1)
|
||||
TRACEMS2(cinfo->emethods, 0, "Warning: unknown JFIF revision number %d.%02d",
|
||||
b[5], b[6]);
|
||||
/* Save info */
|
||||
cinfo->density_unit = b[7];
|
||||
cinfo->X_density = (b[8] << 8) + b[9];
|
||||
cinfo->Y_density = (b[10] << 8) + b[11];
|
||||
/* Assume colorspace is YCbCr, unless UI has overridden me */
|
||||
if (cinfo->jpeg_color_space == CS_UNKNOWN)
|
||||
cinfo->jpeg_color_space = CS_YCbCr;
|
||||
TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d %d",
|
||||
cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
|
||||
} else {
|
||||
TRACEMS(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF)");
|
||||
}
|
||||
} else {
|
||||
TRACEMS1(cinfo->emethods, 1,
|
||||
"Short APP0 marker, length %d", (int) length);
|
||||
}
|
||||
|
||||
while (length-- > 0) /* skip any remaining data */
|
||||
(void) JGETC(cinfo);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_sof (decompress_info_ptr cinfo, int code)
|
||||
/* Process a SOFn marker */
|
||||
{
|
||||
INT32 length;
|
||||
short ci;
|
||||
int c;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
length = get_2bytes(cinfo);
|
||||
|
||||
cinfo->data_precision = JGETC(cinfo);
|
||||
cinfo->image_height = get_2bytes(cinfo);
|
||||
cinfo->image_width = get_2bytes(cinfo);
|
||||
cinfo->num_components = JGETC(cinfo);
|
||||
|
||||
TRACEMS4(cinfo->emethods, 1,
|
||||
"Start Of Frame 0x%02x: width=%d, height=%d, components=%d",
|
||||
code, cinfo->image_width, cinfo->image_height,
|
||||
cinfo->num_components);
|
||||
|
||||
/* We don't support files in which the image height is initially specified */
|
||||
/* as 0 and is later redefined by DNL. As long as we have to check that, */
|
||||
/* might as well have a general sanity check. */
|
||||
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|
||||
|| cinfo->num_components <= 0)
|
||||
ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)");
|
||||
|
||||
#ifdef EIGHT_BIT_SAMPLES
|
||||
if (cinfo->data_precision != 8)
|
||||
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
|
||||
#endif
|
||||
#ifdef TWELVE_BIT_SAMPLES
|
||||
if (cinfo->data_precision != 12) /* this needs more thought?? */
|
||||
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
|
||||
#endif
|
||||
#ifdef SIXTEEN_BIT_SAMPLES
|
||||
if (cinfo->data_precision != 16) /* this needs more thought?? */
|
||||
ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
|
||||
#endif
|
||||
|
||||
if (length != (cinfo->num_components * 3 + 8))
|
||||
ERREXIT(cinfo->emethods, "Bogus SOF length");
|
||||
|
||||
cinfo->comp_info = (*cinfo->emethods->alloc_small)
|
||||
(cinfo->num_components * SIZEOF(jpeg_component_info));
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
compptr->component_index = ci;
|
||||
compptr->component_id = JGETC(cinfo);
|
||||
c = JGETC(cinfo);
|
||||
compptr->h_samp_factor = (c >> 4) & 15;
|
||||
compptr->v_samp_factor = (c ) & 15;
|
||||
compptr->quant_tbl_no = JGETC(cinfo);
|
||||
|
||||
TRACEMS4(cinfo->emethods, 1, " Component %d: %dhx%dv q=%d",
|
||||
compptr->component_id, compptr->h_samp_factor,
|
||||
compptr->v_samp_factor, compptr->quant_tbl_no);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_sos (decompress_info_ptr cinfo)
|
||||
/* Process a SOS marker */
|
||||
{
|
||||
INT32 length;
|
||||
int i, ci, n, c, cc;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
length = get_2bytes(cinfo);
|
||||
|
||||
n = JGETC(cinfo); /* Number of components */
|
||||
cinfo->comps_in_scan = n;
|
||||
length -= 3;
|
||||
|
||||
if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT(cinfo->emethods, "Bogus SOS length");
|
||||
|
||||
TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
cc = JGETC(cinfo);
|
||||
c = JGETC(cinfo);
|
||||
length -= 2;
|
||||
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
if (cc == cinfo->comp_info[ci].component_id)
|
||||
break;
|
||||
|
||||
if (ci >= cinfo->num_components)
|
||||
ERREXIT(cinfo->emethods, "Invalid component number in SOS");
|
||||
|
||||
compptr = &cinfo->comp_info[ci];
|
||||
cinfo->cur_comp_info[i] = compptr;
|
||||
compptr->dc_tbl_no = (c >> 4) & 15;
|
||||
compptr->ac_tbl_no = (c ) & 15;
|
||||
|
||||
TRACEMS3(cinfo->emethods, 1, " c%d: [dc=%d ac=%d]", cc,
|
||||
compptr->dc_tbl_no, compptr->ac_tbl_no);
|
||||
}
|
||||
|
||||
while (length > 0) {
|
||||
(void) JGETC(cinfo);
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
get_soi (decompress_info_ptr cinfo)
|
||||
/* Process an SOI marker */
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACEMS(cinfo->emethods, 1, "Start of Image");
|
||||
|
||||
/* Reset all parameters that are defined to be reset by SOI */
|
||||
|
||||
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
||||
cinfo->arith_dc_L[i] = 0;
|
||||
cinfo->arith_dc_U[i] = 1;
|
||||
cinfo->arith_ac_K[i] = 5;
|
||||
}
|
||||
cinfo->restart_interval = 0;
|
||||
|
||||
cinfo->density_unit = 0; /* set default JFIF APP0 values */
|
||||
cinfo->X_density = 1;
|
||||
cinfo->Y_density = 1;
|
||||
|
||||
cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */
|
||||
}
|
||||
|
||||
|
||||
LOCAL int
|
||||
next_marker (decompress_info_ptr cinfo)
|
||||
/* Find the next JPEG marker */
|
||||
/* Note that the output might not be a valid marker code, */
|
||||
/* but it will never be 0 or FF */
|
||||
{
|
||||
int c, nbytes;
|
||||
|
||||
nbytes = 0;
|
||||
do {
|
||||
do { /* skip any non-FF bytes */
|
||||
nbytes++;
|
||||
c = JGETC(cinfo);
|
||||
} while (c != 0xFF);
|
||||
do { /* skip any duplicate FFs */
|
||||
nbytes++;
|
||||
c = JGETC(cinfo);
|
||||
} while (c == 0xFF);
|
||||
} while (c == 0); /* repeat if it was a stuffed FF/00 */
|
||||
|
||||
if (nbytes != 2)
|
||||
TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before marker 0x%02x",
|
||||
nbytes-2, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
LOCAL JPEG_MARKER
|
||||
process_tables (decompress_info_ptr cinfo)
|
||||
/* Scan and process JPEG markers that can appear in any order */
|
||||
/* Return when an SOI, EOI, SOFn, or SOS is found */
|
||||
{
|
||||
int c;
|
||||
|
||||
while (TRUE) {
|
||||
c = next_marker(cinfo);
|
||||
|
||||
switch (c) {
|
||||
case M_SOF0:
|
||||
case M_SOF1:
|
||||
case M_SOF2:
|
||||
case M_SOF3:
|
||||
case M_SOF5:
|
||||
case M_SOF6:
|
||||
case M_SOF7:
|
||||
case M_JPG:
|
||||
case M_SOF9:
|
||||
case M_SOF10:
|
||||
case M_SOF11:
|
||||
case M_SOF13:
|
||||
case M_SOF14:
|
||||
case M_SOF15:
|
||||
case M_SOI:
|
||||
case M_EOI:
|
||||
case M_SOS:
|
||||
return c;
|
||||
|
||||
case M_DHT:
|
||||
get_dht(cinfo);
|
||||
break;
|
||||
|
||||
case M_DAC:
|
||||
get_dac(cinfo);
|
||||
break;
|
||||
|
||||
case M_DQT:
|
||||
get_dqt(cinfo);
|
||||
break;
|
||||
|
||||
case M_DRI:
|
||||
get_dri(cinfo);
|
||||
break;
|
||||
|
||||
case M_APP0:
|
||||
get_app0(cinfo);
|
||||
break;
|
||||
|
||||
case M_RST0: /* these are all parameterless */
|
||||
case M_RST1:
|
||||
case M_RST2:
|
||||
case M_RST3:
|
||||
case M_RST4:
|
||||
case M_RST5:
|
||||
case M_RST6:
|
||||
case M_RST7:
|
||||
case M_TEM:
|
||||
TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
|
||||
break;
|
||||
|
||||
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
|
||||
skip_variable(cinfo, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Initialize and read the file header (everything through the SOF marker).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
read_file_header (decompress_info_ptr cinfo)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Expect an SOI marker first */
|
||||
if (next_marker(cinfo) == M_SOI)
|
||||
get_soi(cinfo);
|
||||
else
|
||||
ERREXIT(cinfo->emethods, "File does not start with JPEG SOI marker");
|
||||
|
||||
/* Process markers until SOF */
|
||||
c = process_tables(cinfo);
|
||||
|
||||
switch (c) {
|
||||
case M_SOF0:
|
||||
case M_SOF1:
|
||||
get_sof(cinfo, c);
|
||||
cinfo->arith_code = FALSE;
|
||||
break;
|
||||
|
||||
case M_SOF9:
|
||||
get_sof(cinfo, c);
|
||||
cinfo->arith_code = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Figure out what colorspace we have */
|
||||
/* (too bad the JPEG committee didn't provide a real way to specify this) */
|
||||
|
||||
switch (cinfo->num_components) {
|
||||
case 1:
|
||||
cinfo->jpeg_color_space = CS_GRAYSCALE;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* if we saw a JFIF marker, leave it set to YCbCr; */
|
||||
/* also leave it alone if UI has provided a value */
|
||||
if (cinfo->jpeg_color_space == CS_UNKNOWN) {
|
||||
short cid0 = cinfo->comp_info[0].component_id;
|
||||
short cid1 = cinfo->comp_info[1].component_id;
|
||||
short cid2 = cinfo->comp_info[2].component_id;
|
||||
|
||||
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
|
||||
cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */
|
||||
else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
|
||||
cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
|
||||
else {
|
||||
TRACEMS3(cinfo->emethods, 0,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr",
|
||||
cid0, cid1, cid2);
|
||||
cinfo->jpeg_color_space = CS_YCbCr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cinfo->jpeg_color_space = CS_CMYK;
|
||||
break;
|
||||
|
||||
default:
|
||||
cinfo->jpeg_color_space = CS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the start of a scan (everything through the SOS marker).
|
||||
* Return TRUE if find SOS, FALSE if find EOI.
|
||||
*/
|
||||
|
||||
METHODDEF boolean
|
||||
read_scan_header (decompress_info_ptr cinfo)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Process markers until SOS or EOI */
|
||||
c = process_tables(cinfo);
|
||||
|
||||
switch (c) {
|
||||
case M_SOS:
|
||||
get_sos(cinfo);
|
||||
return TRUE;
|
||||
|
||||
case M_EOI:
|
||||
TRACEMS(cinfo->emethods, 1, "End Of Image");
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c);
|
||||
break;
|
||||
}
|
||||
return FALSE; /* keeps lint happy */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up after a compressed scan (series of read_jpeg_data calls);
|
||||
* prepare for another read_scan_header call.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
read_scan_trailer (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
read_file_trailer (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* no work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for standard JPEG header reading.
|
||||
* Note that this must be called by the user interface before calling
|
||||
* jpeg_decompress. When a non-JFIF file is to be decompressed (TIFF,
|
||||
* perhaps), the user interface must discover the file type and call
|
||||
* the appropriate method selection routine.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselrjfif (decompress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->read_file_header = read_file_header;
|
||||
cinfo->methods->read_scan_header = read_scan_header;
|
||||
/* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */
|
||||
#if 0
|
||||
cinfo->methods->read_jpeg_data = read_jpeg_data;
|
||||
#endif
|
||||
cinfo->methods->read_scan_trailer = read_scan_trailer;
|
||||
cinfo->methods->read_file_trailer = read_file_trailer;
|
||||
}
|
||||
|
||||
#endif /* JFIF_SUPPORTED */
|
124
jrdppm.c
Normal file
124
jrdppm.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* jrdppm.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to read input images in PPM format.
|
||||
* The PBMPLUS library is required (well, it will be in the real version).
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume input from
|
||||
* an ordinary stdio stream. They further assume that reading begins
|
||||
* at the start of the file; input_init may need work if the
|
||||
* user interface has already read some data (e.g., to determine that
|
||||
* the file is indeed PPM format).
|
||||
*
|
||||
* These routines are invoked via the methods get_input_row
|
||||
* and input_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef PPM_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* Read the file header; return image size and component count.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
input_init (compress_info_ptr cinfo)
|
||||
{
|
||||
int c, w, h, prec;
|
||||
|
||||
if (getc(cinfo->input_file) != 'P')
|
||||
ERREXIT(cinfo->emethods, "Not a PPM file");
|
||||
|
||||
c = getc(cinfo->input_file);
|
||||
switch (c) {
|
||||
case '5': /* it's a PGM file */
|
||||
cinfo->input_components = 1;
|
||||
cinfo->in_color_space = CS_GRAYSCALE;
|
||||
break;
|
||||
|
||||
case '6': /* it's a PPM file */
|
||||
cinfo->input_components = 3;
|
||||
cinfo->in_color_space = CS_RGB;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERREXIT(cinfo->emethods, "Not a PPM file");
|
||||
break;
|
||||
}
|
||||
|
||||
if (fscanf(cinfo->input_file, " %d %d %d", &w, &h, &prec) != 3)
|
||||
ERREXIT(cinfo->emethods, "Not a PPM file");
|
||||
|
||||
if (getc(cinfo->input_file) != '\n' || w <= 0 || h <= 0 || prec != 255)
|
||||
ERREXIT(cinfo->emethods, "Not a PPM file");
|
||||
|
||||
cinfo->image_width = w;
|
||||
cinfo->image_height = h;
|
||||
cinfo->data_precision = 8;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
|
||||
{
|
||||
register FILE * infile = cinfo->input_file;
|
||||
register JSAMPROW ptr0, ptr1, ptr2;
|
||||
register long col;
|
||||
|
||||
if (cinfo->input_components == 1) {
|
||||
ptr0 = pixel_row[0];
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
*ptr0++ = getc(infile);
|
||||
}
|
||||
} else {
|
||||
ptr0 = pixel_row[0];
|
||||
ptr1 = pixel_row[1];
|
||||
ptr2 = pixel_row[2];
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
*ptr0++ = getc(infile);
|
||||
*ptr1++ = getc(infile);
|
||||
*ptr2++ = getc(infile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
input_term (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work required */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for PPM format input.
|
||||
* Note that this must be called by the user interface before calling
|
||||
* jpeg_compress. If multiple input formats are supported, the
|
||||
* user interface is responsible for discovering the file format and
|
||||
* calling the appropriate method selection routine.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselrppm (compress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->input_init = input_init;
|
||||
cinfo->methods->get_input_row = get_input_row;
|
||||
cinfo->methods->input_term = input_term;
|
||||
}
|
||||
|
||||
#endif /* PPM_SUPPORTED */
|
171
jrevdct.c
Normal file
171
jrevdct.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* jrevdct.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the basic inverse-DCT transformation subroutine.
|
||||
*
|
||||
* This implementation is based on Appendix A.2 of the book
|
||||
* "Discrete Cosine Transform---Algorithms, Advantages, Applications"
|
||||
* by K.R. Rao and P. Yip (Academic Press, Inc, London, 1990).
|
||||
* It uses scaled fixed-point arithmetic instead of floating point.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
/* The poop on this scaling stuff is as follows:
|
||||
*
|
||||
* Most of the numbers (after multiplication by the constants) are
|
||||
* (logically) shifted left by LG2_DCT_SCALE. This is undone by UNFIXH
|
||||
* before assignment to the output array. Note that we want an additional
|
||||
* division by 2 on the output (required by the equations).
|
||||
*
|
||||
* If right shifts are unsigned, then there is a potential problem.
|
||||
* However, shifting right by 16 and then assigning to a short
|
||||
* (assuming short = 16 bits) will keep the sign right!!
|
||||
*
|
||||
* For other shifts,
|
||||
*
|
||||
* ((x + (1 << 30)) >> shft) - (1 << (30 - shft))
|
||||
*
|
||||
* gives a nice right shift with sign (assuming no overflow). However, all the
|
||||
* scaling is such that this isn't a problem. (Is this true?)
|
||||
*/
|
||||
|
||||
|
||||
#define ONE 1L /* remove L if long > 32 bits */
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define LG2_DCT_SCALE 15
|
||||
#define RIGHT_SHIFT(_x,_shft) ((((_x) + (ONE << 30)) >> (_shft)) - (ONE << (30 - (_shft))))
|
||||
#else
|
||||
#define LG2_DCT_SCALE 16
|
||||
#define RIGHT_SHIFT(_x,_shft) ((_x) >> (_shft))
|
||||
#endif
|
||||
|
||||
#define DCT_SCALE (ONE << LG2_DCT_SCALE)
|
||||
|
||||
#define LG2_OVERSCALE 2
|
||||
#define OVERSCALE (ONE << LG2_OVERSCALE)
|
||||
|
||||
#define FIX(x) ((INT32) ((x) * DCT_SCALE + 0.5))
|
||||
#define FIXO(x) ((INT32) ((x) * DCT_SCALE / OVERSCALE + 0.5))
|
||||
#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE)
|
||||
#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1)
|
||||
#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)), LG2_DCT_SCALE-LG2_OVERSCALE)
|
||||
#define OVERSH(x) ((x) << LG2_OVERSCALE)
|
||||
|
||||
#define SIN_1_4 FIX(0.7071067811856476)
|
||||
#define COS_1_4 SIN_1_4
|
||||
|
||||
#define SIN_1_8 FIX(0.3826834323650898)
|
||||
#define COS_1_8 FIX(0.9238795325112870)
|
||||
#define SIN_3_8 COS_1_8
|
||||
#define COS_3_8 SIN_1_8
|
||||
|
||||
#define SIN_1_16 FIX(0.1950903220161282)
|
||||
#define COS_1_16 FIX(0.9807852804032300)
|
||||
#define SIN_7_16 COS_1_16
|
||||
#define COS_7_16 SIN_1_16
|
||||
|
||||
#define SIN_3_16 FIX(0.5555702330196022)
|
||||
#define COS_3_16 FIX(0.8314696123025450)
|
||||
#define SIN_5_16 COS_3_16
|
||||
#define COS_5_16 SIN_3_16
|
||||
|
||||
#define OSIN_1_4 FIXO(0.707106781185647)
|
||||
#define OCOS_1_4 OSIN_1_4
|
||||
|
||||
#define OSIN_1_8 FIXO(0.3826834323650898)
|
||||
#define OCOS_1_8 FIXO(0.9238795325112870)
|
||||
#define OSIN_3_8 OCOS_1_8
|
||||
#define OCOS_3_8 OSIN_1_8
|
||||
|
||||
#define OSIN_1_16 FIXO(0.1950903220161282)
|
||||
#define OCOS_1_16 FIXO(0.9807852804032300)
|
||||
#define OSIN_7_16 OCOS_1_16
|
||||
#define OCOS_7_16 OSIN_1_16
|
||||
|
||||
#define OSIN_3_16 FIXO(0.5555702330196022)
|
||||
#define OCOS_3_16 FIXO(0.8314696123025450)
|
||||
#define OSIN_5_16 OCOS_3_16
|
||||
#define OCOS_5_16 OSIN_3_16
|
||||
|
||||
|
||||
INLINE
|
||||
LOCAL void
|
||||
fast_idct_8 (DCTELEM *in, int stride)
|
||||
{
|
||||
/* tmp1x are new values of tmpx -- flashy register colourers
|
||||
* should be able to do this lot very well
|
||||
*/
|
||||
INT32 tmp10, tmp11, tmp12, tmp13;
|
||||
INT32 tmp20, tmp21, tmp22, tmp23;
|
||||
INT32 tmp30, tmp31;
|
||||
INT32 tmp40, tmp41, tmp42, tmp43;
|
||||
INT32 tmp50, tmp51, tmp52, tmp53;
|
||||
INT32 in0, in1, in2, in3, in4, in5, in6, in7;
|
||||
|
||||
in0 = in[ 0];
|
||||
in1 = in[stride ];
|
||||
in2 = in[stride*2];
|
||||
in3 = in[stride*3];
|
||||
in4 = in[stride*4];
|
||||
in5 = in[stride*5];
|
||||
in6 = in[stride*6];
|
||||
in7 = in[stride*7];
|
||||
|
||||
tmp10 = (in0 + in4) * COS_1_4;
|
||||
tmp11 = (in0 - in4) * COS_1_4;
|
||||
tmp12 = in2 * SIN_1_8 - in6 * COS_1_8;
|
||||
tmp13 = in6 * SIN_1_8 + in2 * COS_1_8;
|
||||
|
||||
tmp20 = tmp10 + tmp13;
|
||||
tmp21 = tmp11 + tmp12;
|
||||
tmp22 = tmp11 - tmp12;
|
||||
tmp23 = tmp10 - tmp13;
|
||||
|
||||
tmp30 = UNFIXO((in3 + in5) * COS_1_4);
|
||||
tmp31 = UNFIXO((in3 - in5) * COS_1_4);
|
||||
|
||||
tmp40 = OVERSH(in1) + tmp30;
|
||||
tmp41 = OVERSH(in7) + tmp31;
|
||||
tmp42 = OVERSH(in1) - tmp30;
|
||||
tmp43 = OVERSH(in7) - tmp31;
|
||||
|
||||
tmp50 = tmp40 * OCOS_1_16 + tmp41 * OSIN_1_16;
|
||||
tmp51 = tmp40 * OSIN_1_16 - tmp41 * OCOS_1_16;
|
||||
tmp52 = tmp42 * OCOS_5_16 + tmp43 * OSIN_5_16;
|
||||
tmp53 = tmp42 * OSIN_5_16 - tmp43 * OCOS_5_16;
|
||||
|
||||
in[ 0] = UNFIXH(tmp20 + tmp50);
|
||||
in[stride ] = UNFIXH(tmp21 + tmp53);
|
||||
in[stride*2] = UNFIXH(tmp22 + tmp52);
|
||||
in[stride*3] = UNFIXH(tmp23 + tmp51);
|
||||
in[stride*4] = UNFIXH(tmp23 - tmp51);
|
||||
in[stride*5] = UNFIXH(tmp22 - tmp52);
|
||||
in[stride*6] = UNFIXH(tmp21 - tmp53);
|
||||
in[stride*7] = UNFIXH(tmp20 - tmp50);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform the inverse DCT on one block of coefficients.
|
||||
*
|
||||
* Note that this code is specialized to the case DCTSIZE = 8.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
j_rev_dct (DCTBLOCK data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
fast_idct_8(data+i*DCTSIZE, 1);
|
||||
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
fast_idct_8(data+i, DCTSIZE);
|
||||
}
|
106
jutils.c
Normal file
106
jutils.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* jutils.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains miscellaneous utility routines needed for both
|
||||
* compression and decompression.
|
||||
* Note we prefix all global names with "j" to minimize conflicts with
|
||||
* a surrounding application.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
|
||||
GLOBAL long
|
||||
jround_up (long a, long b)
|
||||
/* Compute a rounded up to next multiple of b; a >= 0, b > 0 */
|
||||
{
|
||||
a += b-1;
|
||||
return a - (a % b);
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, long num_cols)
|
||||
/* Copy some rows of samples from one place to another.
|
||||
* num_rows rows are copied from input_array[source_row++]
|
||||
* to output_array[dest_row++]; these areas should not overlap.
|
||||
* The source and destination arrays must be at least as wide as num_cols.
|
||||
*/
|
||||
{
|
||||
/* On normal machines we can use memcpy(). This won't work on 80x86 because
|
||||
* the sample arrays are FAR and we're assuming a small-pointer memory model.
|
||||
*/
|
||||
register JSAMPROW inptr, outptr;
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
register long count;
|
||||
#else
|
||||
register size_t count = num_cols * SIZEOF(JSAMPLE);
|
||||
#endif
|
||||
register int row;
|
||||
|
||||
input_array += source_row;
|
||||
output_array += dest_row;
|
||||
|
||||
for (row = num_rows; row > 0; row--) {
|
||||
inptr = *input_array++;
|
||||
outptr = *output_array++;
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
for (count = num_cols; count > 0; count--)
|
||||
*outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
|
||||
#else
|
||||
memcpy((void *) outptr, (void *) inptr, count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, long num_blocks)
|
||||
/* Copy a row of coefficient blocks from one place to another. */
|
||||
{
|
||||
/* On normal machines we can use memcpy(). This won't work on 80x86 because
|
||||
* the block arrays are FAR and we're assuming a small-pointer memory model.
|
||||
*/
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
register JCOEFPTR inptr, outptr;
|
||||
register int i;
|
||||
register long count;
|
||||
|
||||
for (count = num_blocks; count > 0; count--) {
|
||||
inptr = *input_row++;
|
||||
outptr = *output_row++;
|
||||
for (i = DCTSIZE2; i > 0; i--)
|
||||
*outptr++ = *inptr++;
|
||||
}
|
||||
#else
|
||||
memcpy((void *) output_row, (void *) input_row,
|
||||
(size_t) (num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jzero_far (void FAR * target, size_t bytestozero)
|
||||
/* Zero out a chunk of FAR memory. */
|
||||
/* This might be sample-array data, block-array data, or alloc_medium data. */
|
||||
{
|
||||
/* On normal machines we can use MEMZERO(). This won't work on 80x86
|
||||
* because we're assuming a small-pointer memory model.
|
||||
*/
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
register char FAR * ptr = (char FAR *) target;
|
||||
register size_t count;
|
||||
|
||||
for (count = bytestozero; count > 0; count--) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
#else
|
||||
MEMZERO((void *) target, bytestozero);
|
||||
#endif
|
||||
}
|
548
jvirtmem.c
Normal file
548
jvirtmem.c
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* jvirtmem.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides the system-dependent memory allocation routines
|
||||
* for the case where we can rely on virtual memory to handle large arrays.
|
||||
*
|
||||
* This includes some MS-DOS code just for trial purposes; "big" arrays will
|
||||
* have to be handled with temp files on MS-DOS, so a real implementation of
|
||||
* a DOS memory manager will probably be a separate file. (See additional
|
||||
* comments about big arrays, below.)
|
||||
*
|
||||
* NB: allocation routines never return NULL.
|
||||
* They should exit to error_exit if unsuccessful.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h> /* to declare malloc(), free() */
|
||||
#else
|
||||
extern void * malloc PP((size_t size));
|
||||
extern void free PP((void *ptr));
|
||||
#endif
|
||||
|
||||
|
||||
/* Insert system-specific definitions of far_malloc, far_free here. */
|
||||
|
||||
#ifndef NEED_FAR_POINTERS /* Generic for non-braindamaged CPUs */
|
||||
|
||||
#define far_malloc(x) malloc(x)
|
||||
#define far_free(x) free(x)
|
||||
|
||||
#else /* NEED_FAR_POINTERS */
|
||||
|
||||
#ifdef __TURBOC__
|
||||
/* These definitions work for Turbo C */
|
||||
#include <alloc.h> /* need farmalloc(), farfree() */
|
||||
#define far_malloc(x) farmalloc(x)
|
||||
#define far_free(x) farfree(x)
|
||||
#else
|
||||
#ifdef MSDOS
|
||||
/* These definitions work for Microsoft C and compatible compilers */
|
||||
#include <malloc.h> /* need _fmalloc(), _ffree() */
|
||||
#define far_malloc(x) _fmalloc(x)
|
||||
#define far_free(x) _ffree(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* NEED_FAR_POINTERS */
|
||||
|
||||
|
||||
/*
|
||||
* Some important notes:
|
||||
* The array alloc/dealloc routines are not merely a convenience;
|
||||
* on 80x86 machines the bottom-level pointers in an array are FAR
|
||||
* and thus may not be allocatable by alloc_small.
|
||||
*
|
||||
* Also, it's not a good idea to try to merge the sarray and barray
|
||||
* routines, even though they are textually almost the same, because
|
||||
* samples are usually stored as bytes while coefficients are shorts.
|
||||
* Thus, in machines where byte pointers have a different representation
|
||||
* from word pointers, the resulting machine code could not be the same.
|
||||
*/
|
||||
|
||||
|
||||
static external_methods_ptr methods; /* saved for access to error_exit */
|
||||
|
||||
|
||||
#ifdef MEM_STATS /* optional extra stuff for statistics */
|
||||
|
||||
#define MALLOC_OVERHEAD (SIZEOF(char *)) /* assumed overhead per request */
|
||||
#define MALLOC_FAR_OVERHEAD (SIZEOF(char FAR *)) /* for "far" storage */
|
||||
|
||||
static long total_num_small = 0; /* total # of small objects alloced */
|
||||
static long total_bytes_small = 0; /* total bytes requested */
|
||||
static long cur_num_small = 0; /* # currently alloced */
|
||||
static long max_num_small = 0; /* max simultaneously alloced */
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
static long total_num_medium = 0; /* total # of medium objects alloced */
|
||||
static long total_bytes_medium = 0; /* total bytes requested */
|
||||
static long cur_num_medium = 0; /* # currently alloced */
|
||||
static long max_num_medium = 0; /* max simultaneously alloced */
|
||||
#endif
|
||||
|
||||
static long total_num_sarray = 0; /* total # of sarray objects alloced */
|
||||
static long total_bytes_sarray = 0; /* total bytes requested */
|
||||
static long cur_num_sarray = 0; /* # currently alloced */
|
||||
static long max_num_sarray = 0; /* max simultaneously alloced */
|
||||
|
||||
static long total_num_barray = 0; /* total # of barray objects alloced */
|
||||
static long total_bytes_barray = 0; /* total bytes requested */
|
||||
static long cur_num_barray = 0; /* # currently alloced */
|
||||
static long max_num_barray = 0; /* max simultaneously alloced */
|
||||
|
||||
|
||||
GLOBAL void
|
||||
j_mem_stats (void)
|
||||
{
|
||||
/* since this is only a debugging stub, we can cheat a little on the
|
||||
* trace message mechanism... helps 'cuz trace can't handle longs.
|
||||
*/
|
||||
fprintf(stderr, "total_num_small = %ld\n", total_num_small);
|
||||
fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small);
|
||||
if (cur_num_small)
|
||||
fprintf(stderr, "CUR_NUM_SMALL = %ld\n", cur_num_small);
|
||||
fprintf(stderr, "max_num_small = %ld\n", max_num_small);
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
fprintf(stderr, "total_num_medium = %ld\n", total_num_medium);
|
||||
fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium);
|
||||
if (cur_num_medium)
|
||||
fprintf(stderr, "CUR_NUM_MEDIUM = %ld\n", cur_num_medium);
|
||||
fprintf(stderr, "max_num_medium = %ld\n", max_num_medium);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray);
|
||||
fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray);
|
||||
if (cur_num_sarray)
|
||||
fprintf(stderr, "CUR_NUM_SARRAY = %ld\n", cur_num_sarray);
|
||||
fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray);
|
||||
|
||||
fprintf(stderr, "total_num_barray = %ld\n", total_num_barray);
|
||||
fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray);
|
||||
if (cur_num_barray)
|
||||
fprintf(stderr, "CUR_NUM_BARRAY = %ld\n", cur_num_barray);
|
||||
fprintf(stderr, "max_num_barray = %ld\n", max_num_barray);
|
||||
}
|
||||
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
|
||||
LOCAL void
|
||||
out_of_memory (int which)
|
||||
/* Report an out-of-memory error and stop execution */
|
||||
/* If we compiled MEM_STATS support, report alloc requests before dying */
|
||||
{
|
||||
#ifdef MEM_STATS
|
||||
j_mem_stats();
|
||||
#endif
|
||||
ERREXIT1(methods, "Insufficient memory (case %d)", which);
|
||||
}
|
||||
|
||||
|
||||
|
||||
METHODDEF void *
|
||||
alloc_small (size_t sizeofobject)
|
||||
/* Allocate a "small" (all-in-memory) object */
|
||||
{
|
||||
void * result;
|
||||
|
||||
#ifdef MEM_STATS
|
||||
total_num_small++;
|
||||
total_bytes_small += sizeofobject + MALLOC_OVERHEAD;
|
||||
cur_num_small++;
|
||||
if (cur_num_small > max_num_small) max_num_small = cur_num_small;
|
||||
#endif
|
||||
|
||||
result = malloc(sizeofobject);
|
||||
if (result == NULL)
|
||||
out_of_memory(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_small (void *ptr)
|
||||
/* Free a "small" (all-in-memory) object */
|
||||
{
|
||||
free(ptr);
|
||||
|
||||
#ifdef MEM_STATS
|
||||
cur_num_small--;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
|
||||
METHODDEF void FAR *
|
||||
alloc_medium (size_t sizeofobject)
|
||||
/* Allocate a "medium" (all in memory, but in far heap) object */
|
||||
{
|
||||
void FAR * result;
|
||||
|
||||
#ifdef MEM_STATS
|
||||
total_num_medium++;
|
||||
total_bytes_medium += sizeofobject + MALLOC_FAR_OVERHEAD;
|
||||
cur_num_medium++;
|
||||
if (cur_num_medium > max_num_medium) max_num_medium = cur_num_medium;
|
||||
#endif
|
||||
|
||||
result = far_malloc(sizeofobject);
|
||||
if (result == NULL)
|
||||
out_of_memory(2);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_medium (void FAR *ptr)
|
||||
/* Free a "medium" (all in memory, but in far heap) object */
|
||||
{
|
||||
far_free(ptr);
|
||||
|
||||
#ifdef MEM_STATS
|
||||
cur_num_medium--;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* NEED_FAR_POINTERS */
|
||||
|
||||
|
||||
METHODDEF JSAMPARRAY
|
||||
alloc_small_sarray (long samplesperrow, long numrows)
|
||||
/* Allocate a "small" (all-in-memory) 2-D sample array */
|
||||
{
|
||||
JSAMPARRAY result;
|
||||
long i;
|
||||
|
||||
#ifdef MEM_STATS
|
||||
total_num_sarray++;
|
||||
total_bytes_sarray += (samplesperrow * SIZEOF(JSAMPLE) + MALLOC_FAR_OVERHEAD)
|
||||
* numrows;
|
||||
cur_num_sarray++;
|
||||
if (cur_num_sarray > max_num_sarray) max_num_sarray = cur_num_sarray;
|
||||
#endif
|
||||
|
||||
/* Get space for row pointers; this is always "near" on 80x86 */
|
||||
result = (JSAMPARRAY) alloc_small((size_t) (numrows * SIZEOF(JSAMPROW)));
|
||||
|
||||
/* Get the rows themselves; on 80x86 these are "far" */
|
||||
for (i = 0; i < numrows; i++) {
|
||||
result[i] = (JSAMPROW) far_malloc((size_t) (samplesperrow * SIZEOF(JSAMPLE)));
|
||||
if (result[i] == NULL)
|
||||
out_of_memory(3);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_small_sarray (JSAMPARRAY ptr, long numrows)
|
||||
/* Free a "small" (all-in-memory) 2-D sample array */
|
||||
{
|
||||
long i;
|
||||
|
||||
/* Free the rows themselves; on 80x86 these are "far" */
|
||||
for (i = 0; i < numrows; i++) {
|
||||
far_free((void FAR *) ptr[i]);
|
||||
}
|
||||
|
||||
/* Free space for row pointers; this is always "near" on 80x86 */
|
||||
free_small((void *) ptr);
|
||||
|
||||
#ifdef MEM_STATS
|
||||
cur_num_sarray--;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
METHODDEF JBLOCKARRAY
|
||||
alloc_small_barray (long blocksperrow, long numrows)
|
||||
/* Allocate a "small" (all-in-memory) 2-D coefficient-block array */
|
||||
{
|
||||
JBLOCKARRAY result;
|
||||
long i;
|
||||
|
||||
#ifdef MEM_STATS
|
||||
total_num_barray++;
|
||||
total_bytes_barray += (blocksperrow * SIZEOF(JBLOCK) + MALLOC_FAR_OVERHEAD)
|
||||
* numrows;
|
||||
cur_num_barray++;
|
||||
if (cur_num_barray > max_num_barray) max_num_barray = cur_num_barray;
|
||||
#endif
|
||||
|
||||
/* Get space for row pointers; this is always "near" on 80x86 */
|
||||
result = (JBLOCKARRAY) alloc_small((size_t) (numrows * SIZEOF(JBLOCKROW)));
|
||||
|
||||
/* Get the rows themselves; on 80x86 these are "far" */
|
||||
for (i = 0; i < numrows; i++) {
|
||||
result[i] = (JBLOCKROW) far_malloc((size_t) (blocksperrow * SIZEOF(JBLOCK)));
|
||||
if (result[i] == NULL)
|
||||
out_of_memory(4);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_small_barray (JBLOCKARRAY ptr, long numrows)
|
||||
/* Free a "small" (all-in-memory) 2-D coefficient-block array */
|
||||
{
|
||||
long i;
|
||||
|
||||
/* Free the rows themselves; on 80x86 these are "far" */
|
||||
for (i = 0; i < numrows; i++) {
|
||||
far_free((void FAR *) ptr[i]);
|
||||
}
|
||||
|
||||
/* Free space for row pointers; this is always "near" on 80x86 */
|
||||
free_small((void *) ptr);
|
||||
|
||||
#ifdef MEM_STATS
|
||||
cur_num_barray--;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* About "big" array management:
|
||||
*
|
||||
* To allow machines with limited memory to handle large images,
|
||||
* all processing in the JPEG system is done a few pixel or block rows
|
||||
* at a time. The above "small" array routines are only used to allocate
|
||||
* strip buffers (as wide as the image, but just a few rows high).
|
||||
* In some cases multiple passes must be made over the data. In these
|
||||
* cases the "big" array routines are used. The array is still accessed
|
||||
* a strip at a time, but the memory manager must save the whole array
|
||||
* for repeated accesses. The intended implementation is that there is
|
||||
* a strip buffer in memory (as high as is possible given the desired memory
|
||||
* limit), plus a backing file that holds the rest of the array.
|
||||
*
|
||||
* The request_big_array routines are told the total size of the image (in case
|
||||
* it is useful to know the total file size that will be needed). They are
|
||||
* also given the unit height, which is the number of rows that will be
|
||||
* accessed at once; the in-memory buffer should usually be made a multiple of
|
||||
* this height for best efficiency.
|
||||
*
|
||||
* The request routines create control blocks (and may open backing files),
|
||||
* but they don't create the in-memory buffers. This is postponed until
|
||||
* alloc_big_arrays is called. At that time the total amount of space needed
|
||||
* is known (approximately, anyway), so free memory can be divided up fairly.
|
||||
*
|
||||
* The access_big_array routines are responsible for making a specific strip
|
||||
* area accessible (after reading or writing the backing file, if necessary).
|
||||
* Note that the access routines are told whether the caller intends to modify
|
||||
* the accessed strip; during a read-only pass this saves having to rewrite
|
||||
* data to disk.
|
||||
*
|
||||
* The typical access pattern is one top-to-bottom pass to write the data,
|
||||
* followed by one or more read-only top-to-bottom passes. However, other
|
||||
* access patterns may occur while reading. For example, translation of image
|
||||
* formats that use bottom-to-top scan order will require bottom-to-top read
|
||||
* passes. The memory manager need not support multiple write passes nor
|
||||
* funny write orders (meaning that rearranging rows must be handled while
|
||||
* reading data out of the big array, not while putting it in).
|
||||
*
|
||||
* In current usage, the access requests are always for nonoverlapping strips;
|
||||
* that is, successive access start_row numbers always differ by exactly the
|
||||
* unitheight. This allows fairly simple buffer dump/reload logic if the
|
||||
* in-memory buffer is made a multiple of the unitheight. It would be
|
||||
* possible to keep subsampled rather than fullsize data in the "big" arrays,
|
||||
* thus reducing temp file size, if we supported overlapping strip access
|
||||
* (access requests differing by less than the unitheight). At the moment
|
||||
* I don't believe this is worth the extra complexity.
|
||||
*
|
||||
* This particular implementation doesn't use temp files; the whole of a big
|
||||
* array is allocated in (virtual) memory, and any swapping is done behind the
|
||||
* scenes by the operating system.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* The control blocks for virtual arrays.
|
||||
* These are pretty minimal in this implementation.
|
||||
* Note: in this implementation we could realize big arrays
|
||||
* at request time and make alloc_big_arrays a no-op;
|
||||
* however, doing it separately keeps callers honest.
|
||||
*/
|
||||
|
||||
struct big_sarray_control {
|
||||
JSAMPARRAY mem_buffer; /* memory buffer (the whole thing, here) */
|
||||
long rows_in_mem; /* Height of memory buffer */
|
||||
long samplesperrow; /* Width of memory buffer */
|
||||
long unitheight; /* # of rows accessed by access_big_sarray() */
|
||||
big_sarray_ptr next; /* list link for unrealized arrays */
|
||||
};
|
||||
|
||||
struct big_barray_control {
|
||||
JBLOCKARRAY mem_buffer; /* memory buffer (the whole thing, here) */
|
||||
long rows_in_mem; /* Height of memory buffer */
|
||||
long blocksperrow; /* Width of memory buffer */
|
||||
long unitheight; /* # of rows accessed by access_big_barray() */
|
||||
big_barray_ptr next; /* list link for unrealized arrays */
|
||||
};
|
||||
|
||||
|
||||
/* Headers of lists of control blocks for unrealized big arrays */
|
||||
static big_sarray_ptr unalloced_sarrays;
|
||||
static big_barray_ptr unalloced_barrays;
|
||||
|
||||
|
||||
METHODDEF big_sarray_ptr
|
||||
request_big_sarray (long samplesperrow, long numrows, long unitheight)
|
||||
/* Request a "big" (virtual-memory) 2-D sample array */
|
||||
{
|
||||
big_sarray_ptr result;
|
||||
|
||||
/* get control block */
|
||||
result = (big_sarray_ptr) alloc_small(SIZEOF(struct big_sarray_control));
|
||||
|
||||
result->mem_buffer = NULL; /* lets access routine spot premature access */
|
||||
result->rows_in_mem = numrows;
|
||||
result->samplesperrow = samplesperrow;
|
||||
result->unitheight = unitheight;
|
||||
result->next = unalloced_sarrays; /* add to list of unallocated arrays */
|
||||
unalloced_sarrays = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF big_barray_ptr
|
||||
request_big_barray (long blocksperrow, long numrows, long unitheight)
|
||||
/* Request a "big" (virtual-memory) 2-D coefficient-block array */
|
||||
{
|
||||
big_barray_ptr result;
|
||||
|
||||
/* get control block */
|
||||
result = (big_barray_ptr) alloc_small(SIZEOF(struct big_barray_control));
|
||||
|
||||
result->mem_buffer = NULL; /* lets access routine spot premature access */
|
||||
result->rows_in_mem = numrows;
|
||||
result->blocksperrow = blocksperrow;
|
||||
result->unitheight = unitheight;
|
||||
result->next = unalloced_barrays; /* add to list of unallocated arrays */
|
||||
unalloced_barrays = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
alloc_big_arrays (long extra_small_samples, long extra_small_blocks,
|
||||
long extra_medium_space)
|
||||
/* Allocate the in-memory buffers for any unrealized "big" arrays */
|
||||
/* 'extra' values are upper bounds for total future small-array requests */
|
||||
/* and far-heap requests */
|
||||
{
|
||||
/* In this implementation we just malloc the whole arrays */
|
||||
/* and expect the system's virtual memory to worry about swapping them */
|
||||
big_sarray_ptr sptr;
|
||||
big_barray_ptr bptr;
|
||||
|
||||
for (sptr = unalloced_sarrays; sptr != NULL; sptr = sptr->next) {
|
||||
sptr->mem_buffer = alloc_small_sarray(sptr->samplesperrow,
|
||||
sptr->rows_in_mem);
|
||||
}
|
||||
|
||||
for (bptr = unalloced_barrays; bptr != NULL; bptr = bptr->next) {
|
||||
bptr->mem_buffer = alloc_small_barray(bptr->blocksperrow,
|
||||
bptr->rows_in_mem);
|
||||
}
|
||||
|
||||
unalloced_sarrays = NULL; /* reset for possible future cycles */
|
||||
unalloced_barrays = NULL;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF JSAMPARRAY
|
||||
access_big_sarray (big_sarray_ptr ptr, long start_row, boolean writable)
|
||||
/* Access the part of a "big" sample array starting at start_row */
|
||||
/* and extending for ptr->unitheight rows. writable is true if */
|
||||
/* caller intends to modify the accessed area. */
|
||||
{
|
||||
/* debugging check */
|
||||
if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
|
||||
ptr->mem_buffer == NULL)
|
||||
ERREXIT(methods, "Bogus access_big_sarray request");
|
||||
|
||||
return ptr->mem_buffer + start_row;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF JBLOCKARRAY
|
||||
access_big_barray (big_barray_ptr ptr, long start_row, boolean writable)
|
||||
/* Access the part of a "big" coefficient-block array starting at start_row */
|
||||
/* and extending for ptr->unitheight rows. writable is true if */
|
||||
/* caller intends to modify the accessed area. */
|
||||
{
|
||||
/* debugging check */
|
||||
if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
|
||||
ptr->mem_buffer == NULL)
|
||||
ERREXIT(methods, "Bogus access_big_barray request");
|
||||
|
||||
return ptr->mem_buffer + start_row;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_big_sarray (big_sarray_ptr ptr)
|
||||
/* Free a "big" (virtual-memory) 2-D sample array */
|
||||
{
|
||||
free_small_sarray(ptr->mem_buffer, ptr->rows_in_mem);
|
||||
free_small((void *) ptr); /* free the control block too */
|
||||
}
|
||||
|
||||
|
||||
METHODDEF void
|
||||
free_big_barray (big_barray_ptr ptr)
|
||||
/* Free a "big" (virtual-memory) 2-D coefficient-block array */
|
||||
{
|
||||
free_small_barray(ptr->mem_buffer, ptr->rows_in_mem);
|
||||
free_small((void *) ptr); /* free the control block too */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for virtual memory systems.
|
||||
* The system-dependent setup routine should call this routine
|
||||
* to install the necessary method pointers in the supplied struct.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselvirtmem (external_methods_ptr emethods)
|
||||
{
|
||||
methods = emethods; /* save struct addr for error exit access */
|
||||
|
||||
emethods->alloc_small = alloc_small;
|
||||
emethods->free_small = free_small;
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
emethods->alloc_medium = alloc_medium;
|
||||
emethods->free_medium = free_medium;
|
||||
#endif
|
||||
emethods->alloc_small_sarray = alloc_small_sarray;
|
||||
emethods->free_small_sarray = free_small_sarray;
|
||||
emethods->alloc_small_barray = alloc_small_barray;
|
||||
emethods->free_small_barray = free_small_barray;
|
||||
emethods->request_big_sarray = request_big_sarray;
|
||||
emethods->request_big_barray = request_big_barray;
|
||||
emethods->alloc_big_arrays = alloc_big_arrays;
|
||||
emethods->access_big_sarray = access_big_sarray;
|
||||
emethods->access_big_barray = access_big_barray;
|
||||
emethods->free_big_sarray = free_big_sarray;
|
||||
emethods->free_big_barray = free_big_barray;
|
||||
|
||||
unalloced_sarrays = NULL; /* make sure list headers are empty */
|
||||
unalloced_barrays = NULL;
|
||||
}
|
497
jwrgif.c
Normal file
497
jwrgif.c
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* jwrgif.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to write output images in GIF format.
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume output to
|
||||
* an ordinary stdio stream.
|
||||
*
|
||||
* These routines are invoked via the methods put_pixel_rows, put_color_map,
|
||||
* and output_init/term.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is loosely based on ppmtogif from the PBMPLUS distribution
|
||||
* of Feb. 1991. That file contains the following copyright notice:
|
||||
* Based on GIFENCODE by David Rowley <mgardi@watdscu.waterloo.edu>.
|
||||
* Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
|
||||
* Copyright (C) 1989 by Jef Poskanzer.
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. This software is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*
|
||||
* We are also required to state that
|
||||
* "The Graphics Interchange Format(c) is the Copyright property of
|
||||
* CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
* CompuServe Incorporated."
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef GIF_SUPPORTED
|
||||
|
||||
|
||||
static decompress_info_ptr dcinfo; /* to avoid passing to all functions */
|
||||
|
||||
#define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */
|
||||
|
||||
typedef INT16 code_int; /* must hold -1 .. 2**MAX_LZW_BITS */
|
||||
|
||||
#define LZW_TABLE_SIZE ((code_int) 1 << MAX_LZW_BITS)
|
||||
|
||||
#define HSIZE 5003 /* hash table size for 80% occupancy */
|
||||
|
||||
typedef int hash_int; /* must hold -2*HSIZE..2*HSIZE */
|
||||
|
||||
static int n_bits; /* current number of bits/code */
|
||||
static code_int maxcode; /* maximum code, given n_bits */
|
||||
#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
|
||||
|
||||
static int init_bits; /* initial n_bits ... restored after clear */
|
||||
|
||||
static code_int ClearCode; /* clear code (doesn't change) */
|
||||
static code_int EOFCode; /* EOF code (ditto) */
|
||||
|
||||
static code_int free_code; /* first not-yet-used symbol code */
|
||||
|
||||
/*
|
||||
* The LZW hash table consists of three parallel arrays:
|
||||
* hash_code[i] code of symbol in slot i, or 0 if empty slot
|
||||
* hash_prefix[i] symbol's prefix code; undefined if empty slot
|
||||
* hash_suffix[i] symbol's suffix character; undefined if empty slot
|
||||
* where slot values (i) range from 0 to HSIZE-1.
|
||||
*
|
||||
* Algorithm: use open addressing double hashing (no chaining) on the
|
||||
* prefix code / suffix character combination. We do a variant of Knuth's
|
||||
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
|
||||
* secondary probe.
|
||||
*
|
||||
* The hash tables are allocated from FAR heap space since they would use up
|
||||
* rather a lot of the near data space in a PC.
|
||||
*/
|
||||
|
||||
static code_int FAR *hash_code; /* => hash table of symbol codes */
|
||||
static code_int FAR *hash_prefix; /* => hash table of prefix symbols */
|
||||
static UINT8 FAR *hash_suffix; /* => hash table of suffix bytes */
|
||||
|
||||
|
||||
/*
|
||||
* Routines to package compressed data bytes into GIF data blocks.
|
||||
* A data block consists of a count byte (1..255) and that many data bytes.
|
||||
*/
|
||||
|
||||
static int bytesinpkt; /* # of bytes in current packet */
|
||||
static char packetbuf[256]; /* workspace for accumulating packet */
|
||||
|
||||
|
||||
LOCAL void
|
||||
flush_packet (void)
|
||||
/* flush any accumulated data */
|
||||
{
|
||||
if (bytesinpkt > 0) { /* never write zero-length packet */
|
||||
packetbuf[0] = bytesinpkt++;
|
||||
if (fwrite(packetbuf, 1, bytesinpkt, dcinfo->output_file) != bytesinpkt)
|
||||
ERREXIT(dcinfo->emethods, "Output file write error");
|
||||
bytesinpkt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
char_out (int c)
|
||||
/* Add a character to current packet; flush to disk if necessary */
|
||||
{
|
||||
packetbuf[++bytesinpkt] = c;
|
||||
if (bytesinpkt >= 255)
|
||||
flush_packet();
|
||||
}
|
||||
|
||||
|
||||
/* Routine to convert variable-width codes into a byte stream */
|
||||
|
||||
static INT32 cur_accum; /* holds bits not yet output */
|
||||
static int cur_bits; /* # of bits in cur_accum */
|
||||
|
||||
|
||||
LOCAL void
|
||||
output (code_int code)
|
||||
/* Emit a code of n_bits bits */
|
||||
/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
|
||||
{
|
||||
if (cur_bits > 0)
|
||||
cur_accum |= ((INT32) code << cur_bits);
|
||||
else
|
||||
cur_accum = code;
|
||||
cur_bits += n_bits;
|
||||
|
||||
while (cur_bits >= 8) {
|
||||
char_out((int) (cur_accum & 0xFF));
|
||||
cur_accum >>= 8;
|
||||
cur_bits -= 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the next entry is going to be too big for the code size,
|
||||
* then increase it, if possible. We do this here to ensure
|
||||
* that it's done in sync with the decoder's codesize increases.
|
||||
*/
|
||||
if (free_code > maxcode) {
|
||||
n_bits++;
|
||||
if (n_bits == MAX_LZW_BITS)
|
||||
maxcode = LZW_TABLE_SIZE; /* free_code will never exceed this */
|
||||
else
|
||||
maxcode = MAXCODE(n_bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The LZW algorithm proper */
|
||||
|
||||
static code_int waiting_code; /* symbol not yet output; may be extendable */
|
||||
static boolean first_byte; /* if TRUE, waiting_code is not valid */
|
||||
|
||||
|
||||
LOCAL void
|
||||
clear_hash (void)
|
||||
/* Fill the hash table with empty entries */
|
||||
{
|
||||
/* It's sufficient to zero hash_code[] */
|
||||
jzero_far((void FAR *) hash_code, HSIZE * SIZEOF(code_int));
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
clear_block (void)
|
||||
/* Reset compressor and issue a Clear code */
|
||||
{
|
||||
clear_hash(); /* delete all the symbols */
|
||||
free_code = ClearCode + 2;
|
||||
output(ClearCode); /* inform decoder */
|
||||
n_bits = init_bits; /* reset code size */
|
||||
maxcode = MAXCODE(n_bits);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
compress_init (int i_bits)
|
||||
/* Initialize LZW compressor */
|
||||
{
|
||||
/* init all the static variables */
|
||||
n_bits = init_bits = i_bits;
|
||||
maxcode = MAXCODE(n_bits);
|
||||
ClearCode = ((code_int) 1 << (init_bits - 1));
|
||||
EOFCode = ClearCode + 1;
|
||||
free_code = ClearCode + 2;
|
||||
first_byte = TRUE; /* no waiting symbol yet */
|
||||
/* init output buffering vars */
|
||||
bytesinpkt = 0;
|
||||
cur_accum = 0;
|
||||
cur_bits = 0;
|
||||
/* clear hash table */
|
||||
clear_hash();
|
||||
/* GIF specifies an initial Clear code */
|
||||
output(ClearCode);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
compress_byte (int c)
|
||||
/* Accept and compress one 8-bit byte */
|
||||
{
|
||||
register hash_int i;
|
||||
register hash_int disp;
|
||||
|
||||
if (first_byte) { /* need to initialize waiting_code */
|
||||
waiting_code = c;
|
||||
first_byte = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Probe hash table to see if a symbol exists for
|
||||
* waiting_code followed by c.
|
||||
* If so, replace waiting_code by that symbol and return.
|
||||
*/
|
||||
i = ((hash_int) c << (MAX_LZW_BITS-8)) + waiting_code;
|
||||
/* i is less than twice 2**MAX_LZW_BITS, therefore less than twice HSIZE */
|
||||
if (i >= HSIZE)
|
||||
i -= HSIZE;
|
||||
|
||||
if (hash_code[i] != 0) { /* is first probed slot empty? */
|
||||
if (hash_prefix[i] == waiting_code && hash_suffix[i] == c) {
|
||||
waiting_code = hash_code[i];
|
||||
return;
|
||||
}
|
||||
if (i == 0) /* secondary hash (after G. Knott) */
|
||||
disp = 1;
|
||||
else
|
||||
disp = HSIZE - i;
|
||||
while (1) {
|
||||
i -= disp;
|
||||
if (i < 0)
|
||||
i += HSIZE;
|
||||
if (hash_code[i] == 0)
|
||||
break; /* hit empty slot */
|
||||
if (hash_prefix[i] == waiting_code && hash_suffix[i] == c) {
|
||||
waiting_code = hash_code[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* here when hashtable[i] is an empty slot; desired symbol not in table */
|
||||
output(waiting_code);
|
||||
if (free_code < LZW_TABLE_SIZE) {
|
||||
hash_code[i] = free_code++; /* add symbol to hashtable */
|
||||
hash_prefix[i] = waiting_code;
|
||||
hash_suffix[i] = c;
|
||||
} else
|
||||
clear_block();
|
||||
waiting_code = c;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
compress_term (void)
|
||||
/* Clean up at end */
|
||||
{
|
||||
/* Flush out the buffered code */
|
||||
if (! first_byte)
|
||||
output(waiting_code);
|
||||
/* Send an EOF code */
|
||||
output(EOFCode);
|
||||
/* Flush the bit-packing buffer */
|
||||
if (cur_bits > 0) {
|
||||
char_out((int) (cur_accum & 0xFF));
|
||||
}
|
||||
/* Flush the packet buffer */
|
||||
flush_packet();
|
||||
}
|
||||
|
||||
|
||||
/* GIF header construction */
|
||||
|
||||
|
||||
LOCAL void
|
||||
put_word (UINT16 w)
|
||||
/* Emit a 16-bit word, LSB first */
|
||||
{
|
||||
putc(w & 0xFF, dcinfo->output_file);
|
||||
putc((w >> 8) & 0xFF, dcinfo->output_file);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
put_3bytes (int val)
|
||||
/* Emit 3 copies of same byte value --- handy subr for colormap construction */
|
||||
{
|
||||
putc(val, dcinfo->output_file);
|
||||
putc(val, dcinfo->output_file);
|
||||
putc(val, dcinfo->output_file);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_header (int num_colors, JSAMPARRAY colormap)
|
||||
/* Output the GIF file header, including color map */
|
||||
/* If colormap==NULL, synthesize a gray-scale colormap */
|
||||
{
|
||||
int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
|
||||
int i;
|
||||
|
||||
if (num_colors > 256)
|
||||
ERREXIT(dcinfo->emethods, "GIF can only handle 256 colors");
|
||||
/* Compute bits/pixel and related values */
|
||||
if (num_colors <= 2)
|
||||
BitsPerPixel = 1;
|
||||
else if (num_colors <= 4)
|
||||
BitsPerPixel = 2;
|
||||
else if (num_colors <= 8)
|
||||
BitsPerPixel = 3;
|
||||
else if (num_colors <= 16)
|
||||
BitsPerPixel = 4;
|
||||
else if (num_colors <= 32)
|
||||
BitsPerPixel = 5;
|
||||
else if (num_colors <= 64)
|
||||
BitsPerPixel = 6;
|
||||
else if (num_colors <= 128)
|
||||
BitsPerPixel = 7;
|
||||
else
|
||||
BitsPerPixel = 8;
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
if (BitsPerPixel <= 1)
|
||||
InitCodeSize = 2;
|
||||
else
|
||||
InitCodeSize = BitsPerPixel;
|
||||
/*
|
||||
* Write the GIF header.
|
||||
* Note that we generate a plain GIF87 header for maximum compatibility.
|
||||
*/
|
||||
fwrite("GIF87a", 1, 6, dcinfo->output_file);
|
||||
/* Write the Logical Screen Descriptor */
|
||||
put_word((UINT16) dcinfo->image_width);
|
||||
put_word((UINT16) dcinfo->image_height);
|
||||
FlagByte = 0x80; /* Yes, there is a global color table */
|
||||
FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
|
||||
FlagByte |= (BitsPerPixel-1); /* size of global color table */
|
||||
putc(FlagByte, dcinfo->output_file);
|
||||
putc(0, dcinfo->output_file); /* Background color index */
|
||||
putc(0, dcinfo->output_file); /* Reserved in GIF87 (aspect ratio in GIF89) */
|
||||
/* Write the Global Color Map */
|
||||
for (i=0; i < ColorMapSize; i++) {
|
||||
if (i < num_colors) {
|
||||
if (colormap != NULL) {
|
||||
if (dcinfo->out_color_space == CS_RGB) {
|
||||
/* Normal case: RGB color map */
|
||||
putc(GETJSAMPLE(colormap[0][i]), dcinfo->output_file);
|
||||
putc(GETJSAMPLE(colormap[1][i]), dcinfo->output_file);
|
||||
putc(GETJSAMPLE(colormap[2][i]), dcinfo->output_file);
|
||||
} else {
|
||||
/* Grayscale "color map": possible if quantizing grayscale image */
|
||||
put_3bytes(GETJSAMPLE(colormap[0][i]));
|
||||
}
|
||||
} else {
|
||||
/* Create a gray-scale map of num_colors values, range 0..255 */
|
||||
put_3bytes((i * 255 + (num_colors-1)/2) / (num_colors-1));
|
||||
}
|
||||
} else {
|
||||
/* fill out the map to a power of 2 */
|
||||
put_3bytes(0);
|
||||
}
|
||||
}
|
||||
/* Write image separator and Image Descriptor */
|
||||
putc(',', dcinfo->output_file); /* separator */
|
||||
put_word((UINT16) 0); /* left/top offset */
|
||||
put_word((UINT16) 0);
|
||||
put_word((UINT16) dcinfo->image_width); /* image size */
|
||||
put_word((UINT16) dcinfo->image_height);
|
||||
/* flag byte: not interlaced, no local color map */
|
||||
putc(0x00, dcinfo->output_file);
|
||||
/* Write Initial Code Size byte */
|
||||
putc(InitCodeSize, dcinfo->output_file);
|
||||
|
||||
/* Initialize for LZW compression of image data */
|
||||
compress_init(InitCodeSize+1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for GIF output.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
output_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
dcinfo = cinfo; /* save for use by local routines */
|
||||
if (cinfo->final_out_comps != 1) /* safety check */
|
||||
ERREXIT(cinfo->emethods, "GIF output got confused");
|
||||
/* Allocate space for hash table */
|
||||
hash_code = (code_int FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(HSIZE * SIZEOF(code_int));
|
||||
hash_prefix = (code_int FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(HSIZE * SIZEOF(code_int));
|
||||
hash_suffix = (UINT8 FAR *) (*cinfo->emethods->alloc_medium)
|
||||
(HSIZE * SIZEOF(UINT8));
|
||||
/*
|
||||
* If we aren't quantizing, put_color_map won't be called,
|
||||
* so emit the header now. This only happens with gray scale output.
|
||||
* (If we are quantizing, wait for the color map to be provided.)
|
||||
*/
|
||||
if (! cinfo->quantize_colors)
|
||||
emit_header(256, (JSAMPARRAY) NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the color map.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
|
||||
{
|
||||
emit_header(num_colors, colormap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write some pixel data.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE pixel_data)
|
||||
{
|
||||
register JSAMPROW ptr;
|
||||
register long col;
|
||||
register long width = cinfo->image_width;
|
||||
register int row;
|
||||
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr = pixel_data[0][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
compress_byte(GETJSAMPLE(*ptr));
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
output_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* Flush LZW mechanism */
|
||||
compress_term();
|
||||
/* Write a zero-length data block to end the series */
|
||||
putc(0, cinfo->output_file);
|
||||
/* Write the GIF terminator mark */
|
||||
putc(';', cinfo->output_file);
|
||||
/* Make sure we wrote the output file OK */
|
||||
fflush(cinfo->output_file);
|
||||
if (ferror(cinfo->output_file))
|
||||
ERREXIT(cinfo->emethods, "Output file write error");
|
||||
/* Free space */
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) hash_code);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) hash_prefix);
|
||||
(*cinfo->emethods->free_medium) ((void FAR *) hash_suffix);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for GIF format output.
|
||||
* This should be called from d_ui_method_selection if GIF output is wanted.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselwgif (decompress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->output_init = output_init;
|
||||
cinfo->methods->put_color_map = put_color_map;
|
||||
cinfo->methods->put_pixel_rows = put_pixel_rows;
|
||||
cinfo->methods->output_term = output_term;
|
||||
|
||||
if (cinfo->out_color_space != CS_GRAYSCALE &&
|
||||
cinfo->out_color_space != CS_RGB)
|
||||
ERREXIT(cinfo->emethods, "GIF output must be grayscale or RGB");
|
||||
|
||||
/* Force quantization if color or if > 8 bits input */
|
||||
if (cinfo->out_color_space == CS_RGB || cinfo->data_precision > 8) {
|
||||
/* Force quantization to at most 256 colors */
|
||||
cinfo->quantize_colors = TRUE;
|
||||
if (cinfo->desired_number_of_colors > 256)
|
||||
cinfo->desired_number_of_colors = 256;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GIF_SUPPORTED */
|
468
jwrjfif.c
Normal file
468
jwrjfif.c
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* jwrjfif.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to write standard JPEG file headers/markers.
|
||||
* The file format created is a raw JPEG data stream with (optionally) an
|
||||
* APP0 marker per the JFIF spec. This will handle baseline and
|
||||
* JFIF-convention JPEG files, although there is currently no provision
|
||||
* for inserting a thumbnail image in the JFIF header.
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume output to
|
||||
* an ordinary stdio stream. However, the changes to write to something
|
||||
* else are localized in the macros appearing just below.
|
||||
*
|
||||
* These routines are invoked via the methods write_file_header,
|
||||
* write_scan_header, write_jpeg_data, write_scan_trailer, and
|
||||
* write_file_trailer.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef JFIF_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* To output to something other than a stdio stream, you'd need to redefine
|
||||
* these macros.
|
||||
*/
|
||||
|
||||
/* Write a single byte */
|
||||
#define emit_byte(cinfo,x) putc((x), cinfo->output_file)
|
||||
|
||||
/* Write some bytes from a (char *) buffer */
|
||||
#define WRITE_BYTES(cinfo,dataptr,datacount) \
|
||||
{ if (fwrite((dataptr), 1, (datacount), cinfo->output_file) != (datacount)) \
|
||||
ERREXIT(cinfo->emethods, "Output file write error"); }
|
||||
|
||||
/* Clean up and verify successful output */
|
||||
#define CHECK_OUTPUT(cinfo) \
|
||||
{ fflush(cinfo->output_file); \
|
||||
if (ferror(cinfo->output_file)) \
|
||||
ERREXIT(cinfo->emethods, "Output file write error"); }
|
||||
|
||||
|
||||
/* End of stdio-specific code. */
|
||||
|
||||
|
||||
typedef enum { /* JPEG marker codes */
|
||||
M_SOF0 = 0xc0,
|
||||
M_SOF1 = 0xc1,
|
||||
M_SOF2 = 0xc2,
|
||||
M_SOF3 = 0xc3,
|
||||
|
||||
M_SOF5 = 0xc5,
|
||||
M_SOF6 = 0xc6,
|
||||
M_SOF7 = 0xc7,
|
||||
|
||||
M_JPG = 0xc8,
|
||||
M_SOF9 = 0xc9,
|
||||
M_SOF10 = 0xca,
|
||||
M_SOF11 = 0xcb,
|
||||
|
||||
M_SOF13 = 0xcd,
|
||||
M_SOF14 = 0xce,
|
||||
M_SOF15 = 0xcf,
|
||||
|
||||
M_DHT = 0xc4,
|
||||
|
||||
M_DAC = 0xcc,
|
||||
|
||||
M_RST0 = 0xd0,
|
||||
M_RST1 = 0xd1,
|
||||
M_RST2 = 0xd2,
|
||||
M_RST3 = 0xd3,
|
||||
M_RST4 = 0xd4,
|
||||
M_RST5 = 0xd5,
|
||||
M_RST6 = 0xd6,
|
||||
M_RST7 = 0xd7,
|
||||
|
||||
M_SOI = 0xd8,
|
||||
M_EOI = 0xd9,
|
||||
M_SOS = 0xda,
|
||||
M_DQT = 0xdb,
|
||||
M_DNL = 0xdc,
|
||||
M_DRI = 0xdd,
|
||||
M_DHP = 0xde,
|
||||
M_EXP = 0xdf,
|
||||
|
||||
M_APP0 = 0xe0,
|
||||
M_APP15 = 0xef,
|
||||
|
||||
M_JPG0 = 0xf0,
|
||||
M_JPG13 = 0xfd,
|
||||
M_COM = 0xfe,
|
||||
|
||||
M_TEM = 0x01,
|
||||
|
||||
M_ERROR = 0x100
|
||||
} JPEG_MARKER;
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_marker (compress_info_ptr cinfo, JPEG_MARKER mark)
|
||||
/* Emit a marker code */
|
||||
{
|
||||
emit_byte(cinfo, 0xFF);
|
||||
emit_byte(cinfo, mark);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_2bytes (compress_info_ptr cinfo, int value)
|
||||
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
|
||||
{
|
||||
emit_byte(cinfo, (value >> 8) & 0xFF);
|
||||
emit_byte(cinfo, value & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
LOCAL int
|
||||
emit_dqt (compress_info_ptr cinfo, int index)
|
||||
/* Emit a DQT marker */
|
||||
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
|
||||
{
|
||||
QUANT_TBL_PTR data = cinfo->quant_tbl_ptrs[index];
|
||||
int prec = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
if (data[i] > 255)
|
||||
prec = 1;
|
||||
}
|
||||
|
||||
emit_marker(cinfo, M_DQT);
|
||||
|
||||
emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
|
||||
|
||||
emit_byte(cinfo, index + (prec<<4));
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
if (prec)
|
||||
emit_byte(cinfo, data[i] >> 8);
|
||||
emit_byte(cinfo, data[i] & 0xFF);
|
||||
}
|
||||
|
||||
return prec;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_dht (compress_info_ptr cinfo, int index, boolean is_ac)
|
||||
/* Emit a DHT marker */
|
||||
{
|
||||
HUFF_TBL * htbl;
|
||||
int length, i;
|
||||
|
||||
if (is_ac) {
|
||||
htbl = cinfo->ac_huff_tbl_ptrs[index];
|
||||
index += 0x10; /* output index has AC bit set */
|
||||
} else {
|
||||
htbl = cinfo->dc_huff_tbl_ptrs[index];
|
||||
}
|
||||
|
||||
if (! htbl->sent_table) {
|
||||
emit_marker(cinfo, M_DHT);
|
||||
|
||||
length = 0;
|
||||
for (i = 1; i <= 16; i++)
|
||||
length += htbl->bits[i];
|
||||
|
||||
emit_2bytes(cinfo, length + 2 + 1 + 16);
|
||||
emit_byte(cinfo, index);
|
||||
|
||||
for (i = 1; i <= 16; i++)
|
||||
emit_byte(cinfo, htbl->bits[i]);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
emit_byte(cinfo, htbl->huffval[i]);
|
||||
|
||||
htbl->sent_table = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_dac (compress_info_ptr cinfo)
|
||||
/* Emit a DAC marker */
|
||||
/* Since the useful info is so small, we want to emit all the tables in */
|
||||
/* one DAC marker. Therefore this routine does its own scan of the table. */
|
||||
{
|
||||
char dc_in_use[NUM_ARITH_TBLS];
|
||||
char ac_in_use[NUM_ARITH_TBLS];
|
||||
int length, i;
|
||||
|
||||
for (i = 0; i < NUM_ARITH_TBLS; i++)
|
||||
dc_in_use[i] = ac_in_use[i] = 0;
|
||||
|
||||
for (i = 0; i < cinfo->num_components; i++) {
|
||||
dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1;
|
||||
ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1;
|
||||
}
|
||||
|
||||
length = 0;
|
||||
for (i = 0; i < NUM_ARITH_TBLS; i++)
|
||||
length += dc_in_use[i] + ac_in_use[i];
|
||||
|
||||
emit_marker(cinfo, M_DAC);
|
||||
|
||||
emit_2bytes(cinfo, length*2 + 2);
|
||||
|
||||
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
||||
if (dc_in_use[i]) {
|
||||
emit_byte(cinfo, i);
|
||||
emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
|
||||
}
|
||||
if (ac_in_use[i]) {
|
||||
emit_byte(cinfo, i + 0x10);
|
||||
emit_byte(cinfo, cinfo->arith_ac_K[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_dri (compress_info_ptr cinfo)
|
||||
/* Emit a DRI marker */
|
||||
{
|
||||
emit_marker(cinfo, M_DRI);
|
||||
|
||||
emit_2bytes(cinfo, 4); /* fixed length */
|
||||
|
||||
emit_2bytes(cinfo, (int) cinfo->restart_interval);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_sof (compress_info_ptr cinfo, JPEG_MARKER code)
|
||||
/* Emit a SOF marker */
|
||||
{
|
||||
int i;
|
||||
|
||||
emit_marker(cinfo, code);
|
||||
|
||||
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
|
||||
|
||||
emit_byte(cinfo, cinfo->data_precision);
|
||||
emit_2bytes(cinfo, (int) cinfo->image_height);
|
||||
emit_2bytes(cinfo, (int) cinfo->image_width);
|
||||
|
||||
emit_byte(cinfo, cinfo->num_components);
|
||||
|
||||
for (i = 0; i < cinfo->num_components; i++) {
|
||||
emit_byte(cinfo, cinfo->comp_info[i].component_id);
|
||||
emit_byte(cinfo, (cinfo->comp_info[i].h_samp_factor << 4)
|
||||
+ cinfo->comp_info[i].v_samp_factor);
|
||||
emit_byte(cinfo, cinfo->comp_info[i].quant_tbl_no);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_sos (compress_info_ptr cinfo)
|
||||
/* Emit a SOS marker */
|
||||
{
|
||||
int i;
|
||||
|
||||
emit_marker(cinfo, M_SOS);
|
||||
|
||||
emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
|
||||
|
||||
emit_byte(cinfo, cinfo->comps_in_scan);
|
||||
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id);
|
||||
emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4)
|
||||
+ cinfo->cur_comp_info[i]->ac_tbl_no);
|
||||
}
|
||||
|
||||
emit_byte(cinfo, 0); /* Spectral selection start */
|
||||
emit_byte(cinfo, DCTSIZE2-1); /* Spectral selection end */
|
||||
emit_byte(cinfo, 0); /* Successive approximation */
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
emit_jfif_app0 (compress_info_ptr cinfo)
|
||||
/* Emit a JFIF-compliant APP0 marker */
|
||||
{
|
||||
/*
|
||||
* Length of APP0 block (2 bytes)
|
||||
* Block ID (4 bytes - ASCII "JFIF")
|
||||
* Zero byte (1 byte to terminate the ID string)
|
||||
* Version Major, Minor (2 bytes - 0x01, 0x01)
|
||||
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
|
||||
* Xdpu (2 bytes - dots per unit horizontal)
|
||||
* Ydpu (2 bytes - dots per unit vertical)
|
||||
* Thumbnail X size (1 byte)
|
||||
* Thumbnail Y size (1 byte)
|
||||
*/
|
||||
|
||||
emit_marker(cinfo, M_APP0);
|
||||
|
||||
emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
|
||||
|
||||
emit_byte(cinfo, 'J'); /* Identifier */
|
||||
emit_byte(cinfo, 'F');
|
||||
emit_byte(cinfo, 'I');
|
||||
emit_byte(cinfo, 'F');
|
||||
emit_byte(cinfo, 0);
|
||||
emit_byte(cinfo, 1); /* Major version */
|
||||
emit_byte(cinfo, 1); /* Minor version */
|
||||
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
|
||||
emit_2bytes(cinfo, (int) cinfo->X_density);
|
||||
emit_2bytes(cinfo, (int) cinfo->Y_density);
|
||||
emit_byte(cinfo, 0); /* No thumbnail image */
|
||||
emit_byte(cinfo, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the file header.
|
||||
*/
|
||||
|
||||
|
||||
METHODDEF void
|
||||
write_file_header (compress_info_ptr cinfo)
|
||||
{
|
||||
char qt_in_use[NUM_QUANT_TBLS];
|
||||
int i, prec;
|
||||
boolean is_baseline;
|
||||
|
||||
emit_marker(cinfo, M_SOI); /* first the SOI */
|
||||
|
||||
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
|
||||
emit_jfif_app0(cinfo);
|
||||
|
||||
/* Emit DQT for each quantization table. */
|
||||
/* Note that doing it here means we can't adjust the QTs on-the-fly. */
|
||||
/* If we did want to do that, we'd have a problem with checking precision */
|
||||
/* for the is_baseline determination. */
|
||||
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
qt_in_use[i] = 0;
|
||||
|
||||
for (i = 0; i < cinfo->num_components; i++)
|
||||
qt_in_use[cinfo->comp_info[i].quant_tbl_no] = 1;
|
||||
|
||||
prec = 0;
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||
if (qt_in_use[i])
|
||||
prec += emit_dqt(cinfo, i);
|
||||
}
|
||||
/* now prec is nonzero iff there are any 16-bit quant tables. */
|
||||
|
||||
if (cinfo->restart_interval)
|
||||
emit_dri(cinfo);
|
||||
|
||||
/* Check for a non-baseline specification. */
|
||||
/* Note we assume that Huffman table numbers won't be changed later. */
|
||||
is_baseline = TRUE;
|
||||
if (cinfo->arith_code || (cinfo->data_precision != 8))
|
||||
is_baseline = FALSE;
|
||||
for (i = 0; i < cinfo->num_components; i++) {
|
||||
if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1)
|
||||
is_baseline = FALSE;
|
||||
}
|
||||
if (prec && is_baseline) {
|
||||
is_baseline = FALSE;
|
||||
/* If it's baseline except for quantizer size, warn the user */
|
||||
TRACEMS(cinfo->emethods, 0,
|
||||
"Caution: quantization tables are too coarse for baseline JPEG");
|
||||
}
|
||||
|
||||
|
||||
/* Emit the proper SOF marker */
|
||||
if (cinfo->arith_code)
|
||||
emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
|
||||
else if (is_baseline)
|
||||
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
|
||||
else
|
||||
emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the start of a scan (everything through the SOS marker).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
write_scan_header (compress_info_ptr cinfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cinfo->arith_code) {
|
||||
/* Emit arith conditioning info. We will have some duplication
|
||||
* if the file has multiple scans, but it's so small it's hardly
|
||||
* worth worrying about.
|
||||
*/
|
||||
emit_dac(cinfo);
|
||||
} else {
|
||||
/* Emit Huffman tables. Note that emit_dht takes care of
|
||||
* suppressing duplicate tables.
|
||||
*/
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE);
|
||||
emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
emit_sos(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write some bytes of compressed data within a scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
write_jpeg_data (compress_info_ptr cinfo, char *dataptr, int datacount)
|
||||
{
|
||||
WRITE_BYTES(cinfo, dataptr, datacount);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up after a compressed scan (series of write_jpeg_data calls).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
write_scan_trailer (compress_info_ptr cinfo)
|
||||
{
|
||||
/* no work needed in this format */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
write_file_trailer (compress_info_ptr cinfo)
|
||||
{
|
||||
emit_marker(cinfo, M_EOI);
|
||||
/* Make sure we wrote the output file OK */
|
||||
CHECK_OUTPUT(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for standard JPEG header writing.
|
||||
* This should be called from c_ui_method_selection if appropriate.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselwjfif (compress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->write_file_header = write_file_header;
|
||||
cinfo->methods->write_scan_header = write_scan_header;
|
||||
cinfo->methods->write_jpeg_data = write_jpeg_data;
|
||||
cinfo->methods->write_scan_trailer = write_scan_trailer;
|
||||
cinfo->methods->write_file_trailer = write_file_trailer;
|
||||
}
|
||||
|
||||
#endif /* JFIF_SUPPORTED */
|
167
jwrppm.c
Normal file
167
jwrppm.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* jwrppm.c
|
||||
*
|
||||
* Copyright (C) 1991, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to write output images in PPM format.
|
||||
* The PBMPLUS library is required (well, it will be in the real version).
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume output to
|
||||
* an ordinary stdio stream.
|
||||
*
|
||||
* These routines are invoked via the methods put_pixel_rows, put_color_map,
|
||||
* and output_init/term.
|
||||
*/
|
||||
|
||||
#include "jinclude.h"
|
||||
|
||||
#ifdef PPM_SUPPORTED
|
||||
|
||||
|
||||
static JSAMPARRAY color_map; /* saves color map passed by quantizer */
|
||||
|
||||
|
||||
/*
|
||||
* Write the file header.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
output_init (decompress_info_ptr cinfo)
|
||||
{
|
||||
if (cinfo->out_color_space == CS_GRAYSCALE) {
|
||||
/* emit header for raw PGM format */
|
||||
fprintf(cinfo->output_file, "P5\n%ld %ld\n%d\n",
|
||||
cinfo->image_width, cinfo->image_height, 255);
|
||||
} else if (cinfo->out_color_space == CS_RGB) {
|
||||
/* emit header for raw PPM format */
|
||||
fprintf(cinfo->output_file, "P6\n%ld %ld\n%d\n",
|
||||
cinfo->image_width, cinfo->image_height, 255);
|
||||
} else {
|
||||
ERREXIT(cinfo->emethods, "PPM output must be grayscale or RGB");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write some pixel data.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE pixel_data)
|
||||
{
|
||||
register FILE * outfile = cinfo->output_file;
|
||||
register JSAMPROW ptr0, ptr1, ptr2;
|
||||
register long col;
|
||||
register long width = cinfo->image_width;
|
||||
register int row;
|
||||
|
||||
if (cinfo->out_color_space == CS_GRAYSCALE) {
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr0 = pixel_data[0][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
putc(GETJSAMPLE(*ptr0), outfile);
|
||||
ptr0++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr0 = pixel_data[0][row];
|
||||
ptr1 = pixel_data[1][row];
|
||||
ptr2 = pixel_data[2][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
putc(GETJSAMPLE(*ptr0), outfile);
|
||||
ptr0++;
|
||||
putc(GETJSAMPLE(*ptr1), outfile);
|
||||
ptr1++;
|
||||
putc(GETJSAMPLE(*ptr2), outfile);
|
||||
ptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write some pixel data when color quantization is in effect.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
put_demapped_rows (decompress_info_ptr cinfo, int num_rows,
|
||||
JSAMPIMAGE pixel_data)
|
||||
{
|
||||
register FILE * outfile = cinfo->output_file;
|
||||
register JSAMPROW ptr;
|
||||
register long col;
|
||||
register long width = cinfo->image_width;
|
||||
register int row;
|
||||
|
||||
if (cinfo->out_color_space == CS_GRAYSCALE) {
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr = pixel_data[0][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
putc(GETJSAMPLE(color_map[0][GETJSAMPLE(*ptr)]), outfile);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr = pixel_data[0][row];
|
||||
for (col = width; col > 0; col--) {
|
||||
register int pixval = GETJSAMPLE(*ptr);
|
||||
|
||||
putc(GETJSAMPLE(color_map[0][pixval]), outfile);
|
||||
putc(GETJSAMPLE(color_map[1][pixval]), outfile);
|
||||
putc(GETJSAMPLE(color_map[2][pixval]), outfile);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the color map.
|
||||
* For PPM output, we just demap the output data!
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
|
||||
{
|
||||
color_map = colormap; /* save for use in output */
|
||||
cinfo->methods->put_pixel_rows = put_demapped_rows;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
output_term (decompress_info_ptr cinfo)
|
||||
{
|
||||
/* No work except to make sure we wrote the output file OK */
|
||||
fflush(cinfo->output_file);
|
||||
if (ferror(cinfo->output_file))
|
||||
ERREXIT(cinfo->emethods, "Output file write error");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The method selection routine for PPM format output.
|
||||
* This should be called from d_ui_method_selection if PPM output is wanted.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jselwppm (decompress_info_ptr cinfo)
|
||||
{
|
||||
cinfo->methods->output_init = output_init;
|
||||
cinfo->methods->put_color_map = put_color_map;
|
||||
cinfo->methods->put_pixel_rows = put_pixel_rows;
|
||||
cinfo->methods->output_term = output_term;
|
||||
}
|
||||
|
||||
#endif /* PPM_SUPPORTED */
|
5
makcjpeg.cf
Normal file
5
makcjpeg.cf
Normal file
@ -0,0 +1,5 @@
|
||||
L jcmain.mix jerror.mix jcdeflts.mix jrdgif.mix jrdppm.mix jwrjfif.mix
|
||||
L jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmaster.mix jcmcu.mix
|
||||
L jcpipe.mix jcsample.mix jfwddct.mix jutils.mix jvirtmem.mix
|
||||
fa;
|
||||
b cjpeg,8K,48K,
|
21
makcjpeg.lnk
Normal file
21
makcjpeg.lnk
Normal file
@ -0,0 +1,21 @@
|
||||
jcmain.obj +
|
||||
jerror.obj +
|
||||
jcdeflts.obj +
|
||||
jrdgif.obj +
|
||||
jrdppm.obj +
|
||||
jwrjfif.obj +
|
||||
jcarith.obj +
|
||||
jccolor.obj +
|
||||
jcexpand.obj +
|
||||
jchuff.obj +
|
||||
jcmaster.obj +
|
||||
jcmcu.obj +
|
||||
jcpipe.obj +
|
||||
jcsample.obj +
|
||||
jfwddct.obj +
|
||||
jutils.obj +
|
||||
jvirtmem.obj
|
||||
cjpeg.exe /NOI
|
||||
nul.map
|
||||
|
||||
nul.def
|
6
makdjpeg.cf
Normal file
6
makdjpeg.cf
Normal file
@ -0,0 +1,6 @@
|
||||
L jdmain.mix jerror.mix jrdjfif.mix jwrgif.mix jwrppm.mix
|
||||
L jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmaster.mix jdmcu.mix
|
||||
L jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jutils.mix
|
||||
L jvirtmem.mix
|
||||
fa;
|
||||
b djpeg,8K,48K,
|
22
makdjpeg.lnk
Normal file
22
makdjpeg.lnk
Normal file
@ -0,0 +1,22 @@
|
||||
jdmain.obj +
|
||||
jerror.obj +
|
||||
jrdjfif.obj +
|
||||
jwrgif.obj +
|
||||
jwrppm.obj +
|
||||
jbsmooth.obj +
|
||||
jdarith.obj +
|
||||
jdcolor.obj +
|
||||
jdhuff.obj +
|
||||
jdmaster.obj +
|
||||
jdmcu.obj +
|
||||
jdpipe.obj +
|
||||
jdsample.obj +
|
||||
jquant1.obj +
|
||||
jquant2.obj +
|
||||
jrevdct.obj +
|
||||
jutils.obj +
|
||||
jvirtmem.obj /NOI
|
||||
djpeg.exe
|
||||
nul.map
|
||||
|
||||
nul.def
|
143
makefile.amiga
Normal file
143
makefile.amiga
Normal file
@ -0,0 +1,143 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# This makefile is suitable for Amiga systems using Manx Aztec C ver 5.x.
|
||||
# Thanks to D.J. James for this version.
|
||||
|
||||
# See README and edit jconfig.h before saying "make" !!
|
||||
|
||||
CC= cc
|
||||
|
||||
# You may need to adjust these cc options:
|
||||
CFLAGS= -MC -MD -DTWO_FILE_COMMANDLINE
|
||||
LDFLAGS=
|
||||
LDLIBS= -lml -lcl
|
||||
|
||||
# miscellaneous OS-dependent stuff
|
||||
LN= ln # linker
|
||||
RM= delete quiet # file deletion command
|
||||
AR= lb # library (.lib) file creation command
|
||||
|
||||
|
||||
# source files
|
||||
INCLUDES= jinclude.h jconfig.h jpegdata.h
|
||||
SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c \
|
||||
jchuff.c jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c \
|
||||
jdarith.c jdcolor.c jdhuff.c jdmain.c jdmaster.c jdmcu.c \
|
||||
jdpipe.c jdsample.c jerror.c jfwddct.c jquant1.c jquant2.c \
|
||||
jrdjfif.c jrdgif.c jrdppm.c jrevdct.c jutils.c jvirtmem.c \
|
||||
jwrjfif.c jwrgif.c jwrppm.c egetopt.c
|
||||
DOCS= README architecture codingrules
|
||||
MAKEFILES= makefile.unix makefile.amiga \
|
||||
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk \
|
||||
makefile.pwc makcjpeg.cf makdjpeg.cf makljpeg.cf
|
||||
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
|
||||
DISTFILES= $(DOCS) $(MAKEFILES) ansi2knr.c $(SOURCES) $(INCLUDES) $(TESTFILES)
|
||||
|
||||
# compression objectfiles
|
||||
COBJECTS = jcmain.o jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
|
||||
jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
|
||||
jrdgif.o jrdppm.o jwrjfif.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
# decompression objectfiles
|
||||
DOBJECTS = jdmain.o jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
|
||||
jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
|
||||
jrdjfif.o jwrgif.o jwrppm.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
# These objectfiles are included in libjpeg.lib (all but jcmain.o, jdmain.o)
|
||||
LIBOBJECTS = jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
|
||||
jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
|
||||
jrdgif.o jrdppm.o jwrjfif.o \
|
||||
jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
|
||||
jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
|
||||
jrdjfif.o jwrgif.o jwrppm.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
|
||||
|
||||
all: cjpeg djpeg
|
||||
# By default, libjpeg.lib is not built unless you explicitly request it.
|
||||
|
||||
|
||||
# If you have a C compiler that doesn't understand function prototypes,
|
||||
# uncomment the 5 lines below and make sure PROTO is not defined by jconfig.h.
|
||||
# Then say "make ansi2knr" before "make".
|
||||
|
||||
#.c.o:
|
||||
# ./ansi2knr $*.c tmpansi.c
|
||||
# $(CC) $(CFLAGS) -c tmpansi.c
|
||||
# mv tmpansi.o $*.o
|
||||
# $(RM) tmpansi.c
|
||||
|
||||
ansi2knr: ansi2knr.c
|
||||
$(CC) -o ansi2knr ansi2knr.c
|
||||
# You may need to add one of -DBSD, -DVMS, or -DMSDOS to the line above.
|
||||
|
||||
|
||||
cjpeg: $(COBJECTS)
|
||||
$(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS)
|
||||
|
||||
djpeg: $(DOBJECTS)
|
||||
$(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS)
|
||||
|
||||
# libjpeg.lib is useful if you are including the JPEG software in a larger
|
||||
# program; you'd include it in your link, rather than the individual modules.
|
||||
libjpeg.lib: $(LIBOBJECTS)
|
||||
-$(RM) libjpeg.lib
|
||||
$(AR) libjpeg.lib $(LIBOBJECTS)
|
||||
|
||||
# Use the following to test the built library
|
||||
#cjpeg: jcmain.o libjpeg.lib
|
||||
# $(LN) $(LDFLAGS) -o cjpeg jcmain.o -llibjpeg $(LDLIBS)
|
||||
#
|
||||
#djpeg: jdmain.o libjpeg.lib
|
||||
# $(LN) $(LDFLAGS) -o djpeg jdmain.o -llibjpeg $(LDLIBS)
|
||||
|
||||
clean:
|
||||
-$(RM) *.o cjpeg djpeg libjpeg.lib ansi2knr core tmpansi.* testout.ppm testout.jpg
|
||||
|
||||
distribute:
|
||||
-$(RM) jpegsrc.tar*
|
||||
tar cvf jpegsrc.tar $(DISTFILES)
|
||||
list jpegsrc.tar
|
||||
compress -v jpegsrc.tar
|
||||
list jpegsrc.tar*
|
||||
|
||||
test: cjpeg djpeg
|
||||
-$(RM) testout.ppm testout.jpg
|
||||
./djpeg testorig.jpg testout.ppm
|
||||
./cjpeg testimg.ppm testout.jpg
|
||||
cmp testimg.ppm testout.ppm
|
||||
cmp testimg.jpg testout.jpg
|
||||
|
||||
|
||||
jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h
|
||||
jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h
|
||||
jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h
|
||||
jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h
|
||||
jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h
|
||||
jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h
|
||||
jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h
|
||||
jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
|
115
makefile.mc5
Normal file
115
makefile.mc5
Normal file
@ -0,0 +1,115 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# This makefile is for Microsoft C for MS-DOS, version 5.x.
|
||||
|
||||
# See README and edit jconfig.h before saying "make" !!
|
||||
|
||||
# Microsoft's brain-damaged version of make uses nonstandard syntax (a blank
|
||||
# line is needed to terminate a command list) and it simply scans the rules
|
||||
# in order, rather than doing a true dependency-tree walk. Furthermore,
|
||||
# expanded command lines can't exceed 128 chars (this is a DOS bug, not
|
||||
# make's fault); so we can't just name all the objectfiles in the link steps.
|
||||
# Instead we shove each objectfile into a library as it is made, and link
|
||||
# from the library. The objectfiles are also kept separately as timestamps.
|
||||
|
||||
# You may need to adjust these cc options:
|
||||
CFLAGS= /AS /I. /W3 /Oail /Gs /DMEM_STATS # NB: /Gs turns off stack oflo checks
|
||||
LDFLAGS= /Fm /F 2000 # /F hhhh sets stack size (in hex)
|
||||
# In particular:
|
||||
# Add /DMSDOS if your compiler doesn't automatically #define MSDOS.
|
||||
# Add /DHAVE_GETOPT if your library includes getopt(3) (see jcmain.c, jdmain.c).
|
||||
# /DMEM_STATS is optional -- it enables gathering of memory usage statistics.
|
||||
|
||||
# compression objectfiles
|
||||
COBJECTS = jcmain.obj jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
|
||||
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
|
||||
jrdgif.obj jrdppm.obj jwrjfif.obj \
|
||||
jutils.obj jvirtmem.obj jerror.obj
|
||||
# decompression objectfiles
|
||||
DOBJECTS = jdmain.obj jdmaster.obj jbsmooth.obj jdarith.obj jdcolor.obj jdhuff.obj \
|
||||
jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj jquant2.obj jrevdct.obj \
|
||||
jrdjfif.obj jwrgif.obj jwrppm.obj \
|
||||
jutils.obj jvirtmem.obj jerror.obj
|
||||
|
||||
|
||||
# inference rule used for all compilations except jcmain.c, jdmain.c
|
||||
# notice that objectfile is also inserted into libjpeg.lib
|
||||
.c.obj:
|
||||
cl $(CFLAGS) /c $*.c
|
||||
lib libjpeg -+$*.obj;
|
||||
|
||||
# these two objectfiles are not inserted into libjpeg
|
||||
# because they have duplicate global symbol names (notably main()).
|
||||
jcmain.obj: jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
cl $(CFLAGS) /c $*.c
|
||||
|
||||
jdmain.obj: jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
cl $(CFLAGS) /c $*.c
|
||||
|
||||
|
||||
jbsmooth.obj: jbsmooth.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcarith.obj: jcarith.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jccolor.obj: jccolor.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcdeflts.obj: jcdeflts.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcexpand.obj: jcexpand.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jchuff.obj: jchuff.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcmaster.obj: jcmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcmcu.obj: jcmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcpipe.obj: jcpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jcsample.obj: jcsample.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdarith.obj: jdarith.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdcolor.obj: jdcolor.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdhuff.obj: jdhuff.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdmaster.obj: jdmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdmcu.obj: jdmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdpipe.obj: jdpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jdsample.obj: jdsample.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jerror.obj: jerror.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jfwddct.obj: jfwddct.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jquant1.obj: jquant1.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jquant2.obj: jquant2.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jrdjfif.obj: jrdjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jrdgif.obj: jrdgif.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jrdppm.obj: jrdppm.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jrevdct.obj: jrevdct.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jutils.obj: jutils.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jvirtmem.obj: jvirtmem.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jwrjfif.obj: jwrjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jwrgif.obj: jwrgif.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
jwrppm.obj: jwrppm.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
|
||||
cjpeg.exe: $(COBJECTS)
|
||||
cl /Fecjpeg.exe jcmain.obj libjpeg.lib $(LDFLAGS)
|
||||
|
||||
djpeg.exe: $(DOBJECTS)
|
||||
cl /Fedjpeg.exe jdmain.obj libjpeg.lib $(LDFLAGS)
|
79
makefile.mc6
Normal file
79
makefile.mc6
Normal file
@ -0,0 +1,79 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# This makefile is for Microsoft C for MS-DOS, version 6.x (use NMAKE).
|
||||
# Thanks to Alan Wright and Chris Turner of Olivetti Research Ltd.
|
||||
|
||||
# See README and edit jconfig.h before saying "make" !!
|
||||
|
||||
all: cjpeg.exe djpeg.exe
|
||||
|
||||
# compiler flags. -D gives a #define to the sources:
|
||||
# -O default optimisation
|
||||
# -W3 warning level 3
|
||||
# -Za ANSI conformance, defines__STDC__ but undefines far
|
||||
# and near!
|
||||
# -D__STDC__ pretend we have full ANSI compliance. MSC is near
|
||||
# enough anyway
|
||||
# -DMSDOS we are on an MSDOS machine
|
||||
# -DMEM_STATS enable memory usage statistics (optional)
|
||||
# -DHAVE_GETOPT library has getopt routine to parse cmnd line options
|
||||
# -c compile, don't link (implicit in inference rules)
|
||||
|
||||
CFLAGS = -c -O -W3 -DMSDOS -D__STDC__ -DMEM_STATS
|
||||
|
||||
|
||||
# compression objectfiles
|
||||
COBJECTS = jcmain.obj jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \
|
||||
jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \
|
||||
jrdgif.obj jrdppm.obj jwrjfif.obj \
|
||||
jutils.obj jvirtmem.obj jerror.obj
|
||||
# decompression objectfiles
|
||||
DOBJECTS = jdmain.obj jdmaster.obj jbsmooth.obj jdarith.obj jdcolor.obj jdhuff.obj \
|
||||
jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj jquant2.obj jrevdct.obj \
|
||||
jrdjfif.obj jwrgif.obj jwrppm.obj \
|
||||
jutils.obj jvirtmem.obj jerror.obj
|
||||
|
||||
|
||||
# default rules in nmake will use cflags and compile the list below
|
||||
|
||||
jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h
|
||||
jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h
|
||||
jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h
|
||||
jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h
|
||||
jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h
|
||||
jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h
|
||||
jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h
|
||||
jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
|
||||
|
||||
|
||||
# use linker response files because file list > 128 chars
|
||||
|
||||
cjpeg.exe: $(COBJECTS)
|
||||
link /STACK:8192 @makcjpeg.lnk
|
||||
|
||||
djpeg.exe: $(DOBJECTS)
|
||||
link /STACK:8192 @makdjpeg.lnk
|
100
makefile.pwc
Normal file
100
makefile.pwc
Normal file
@ -0,0 +1,100 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# This makefile is for Mix Software's Power C, v2.1.1
|
||||
# and Dan Grayson's pd make 2.14 under MS-DOS.
|
||||
# Thanks to Bob Hardy for this version.
|
||||
|
||||
# See README and edit jconfig.h before saying "make" !!
|
||||
|
||||
# NOTE: make sure you have converted end-of-line markers to CR/LF in this file
|
||||
# and in the three mak*.cf files; otherwise pd make and the Mix linker will
|
||||
# choke. Power C doesn't seem to care whether end-of-lines are CR/LF or just
|
||||
# LF in the *.h and *.c files. If you blindly converted LF to CR/LF in ALL
|
||||
# the files, then you broke the test*.* files, which contain binary data.
|
||||
|
||||
CC=pc
|
||||
|
||||
# You may need to adjust these cc options:
|
||||
MODEL=m
|
||||
CFLAGS=-dMEM_STATS -dMSDOS -m$(MODEL)
|
||||
LDFLAGS=
|
||||
# In particular:
|
||||
# -dMEM_STATS is optional -- it enables gathering of memory usage statistics.
|
||||
LDLIBS=
|
||||
|
||||
# miscellaneous OS-dependent stuff
|
||||
# linker
|
||||
LN=pcl
|
||||
# file deletion command
|
||||
RM=del
|
||||
# library (.mix) file creation command
|
||||
AR=merge
|
||||
|
||||
|
||||
# compression objectfiles
|
||||
COBJECTS = jcmain.mix jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jrdgif.mix jrdppm.mix jwrjfif.mix jutils.mix jvirtmem.mix jerror.mix
|
||||
# decompression objectfiles
|
||||
DOBJECTS = jdmain.mix jdmaster.mix jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmcu.mix jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jrdjfif.mix jwrgif.mix jwrppm.mix jutils.mix jvirtmem.mix jerror.mix
|
||||
# These objectfiles are included in libjpeg.mix (all but jcmain, jdmain)
|
||||
LIBOBJECTS = jcmaster.mix jcdeflts.mix jcarith.mix jccolor.mix jcexpand.mix jchuff.mix jcmcu.mix jcpipe.mix jcsample.mix jfwddct.mix jrdgif.mix jrdppm.mix jwrjfif.mix jdmaster.mix jbsmooth.mix jdarith.mix jdcolor.mix jdhuff.mix jdmcu.mix jdpipe.mix jdsample.mix jquant1.mix jquant2.mix jrevdct.mix jrdjfif.mix jwrgif.mix jwrppm.mix jutils.mix jvirtmem.mix jerror.mix
|
||||
|
||||
|
||||
all: cjpeg.exe djpeg.exe test
|
||||
# By default, libjpeg.mix is not built unless you explicitly request it.
|
||||
|
||||
|
||||
cjpeg.exe: $(COBJECTS)
|
||||
$(LN) $(LDFLAGS) @makcjpeg.cf
|
||||
|
||||
djpeg.exe: $(DOBJECTS)
|
||||
$(LN) $(LDFLAGS) @makdjpeg.cf
|
||||
|
||||
# libjpeg.mix is useful if you are including the JPEG software in a larger
|
||||
# program; you'd include it in your link, rather than the individual modules.
|
||||
libjpeg.mix: $(LIBOBJECTS)
|
||||
@$(RM) libjpeg.mix
|
||||
$(AR) libjpeg.mix @makljpeg.cf
|
||||
|
||||
clean:
|
||||
$(RM) *.mix cjpeg.exe djpeg.exe testout.*
|
||||
|
||||
test:
|
||||
@$(RM) testout.*
|
||||
+djpeg testorig.jpg testout.ppm
|
||||
+cjpeg testimg.ppm testout.jpg
|
||||
fc testimg.ppm testout.ppm
|
||||
fc testimg.jpg testout.jpg
|
||||
|
||||
|
||||
jbsmooth.mix : jbsmooth.c jinclude.h jconfig.h jpegdata.h
|
||||
jcarith.mix : jcarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jccolor.mix : jccolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jcdeflts.mix : jcdeflts.c jinclude.h jconfig.h jpegdata.h
|
||||
jcexpand.mix : jcexpand.c jinclude.h jconfig.h jpegdata.h
|
||||
jchuff.mix : jchuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmain.mix : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jcmaster.mix : jcmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmcu.mix : jcmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jcpipe.mix : jcpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jcsample.mix : jcsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jdarith.mix : jdarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jdcolor.mix : jdcolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jdhuff.mix : jdhuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmain.mix : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jdmaster.mix : jdmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmcu.mix : jdmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jdpipe.mix : jdpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jdsample.mix : jdsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jerror.mix : jerror.c jinclude.h jconfig.h jpegdata.h
|
||||
jfwddct.mix : jfwddct.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant1.mix : jquant1.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant2.mix : jquant2.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdjfif.mix : jrdjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdgif.mix : jrdgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdppm.mix : jrdppm.c jinclude.h jconfig.h jpegdata.h
|
||||
jrevdct.mix : jrevdct.c jinclude.h jconfig.h jpegdata.h
|
||||
jutils.mix : jutils.c jinclude.h jconfig.h jpegdata.h
|
||||
jvirtmem.mix : jvirtmem.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrjfif.mix : jwrjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrgif.mix : jwrgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrppm.mix : jwrppm.c jinclude.h jconfig.h jpegdata.h
|
152
makefile.unix
Normal file
152
makefile.unix
Normal file
@ -0,0 +1,152 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# This makefile is suitable for Unix-like systems.
|
||||
|
||||
# See README and edit jconfig.h before saying "make" !!
|
||||
|
||||
# Comment out this line if you don't have gcc:
|
||||
CC=gcc
|
||||
|
||||
# You may need to adjust these cc options:
|
||||
CFLAGS= -O -g -Wall -DHAVE_GETOPT -DMEM_STATS
|
||||
LDFLAGS= -g
|
||||
# In particular:
|
||||
# Remove -g and -Wall if not using gcc.
|
||||
# Add -DBSD if on a pure BSD system (see jinclude.h).
|
||||
# Remove -DHAVE_GETOPT if you don't have getopt(3) (see jcmain.c, jdmain.c).
|
||||
# -DMEM_STATS is optional -- it enables gathering of memory usage statistics.
|
||||
# You may also want to add -DTWO_FILE_COMMANDLINE or -D switches for other
|
||||
# symbols listed in jconfig.h, if you prefer not to change jconfig.h.
|
||||
# If your compiler is non-ANSI, also see the .c.o rule below.
|
||||
|
||||
# On HP-UX (and probably other SysV systems) the alternate malloc(3X) is a lot
|
||||
# faster than the standard malloc; this makes a noticeable difference in the
|
||||
# startup time when handling big noninterleaved images. I say "-lmalloc" to
|
||||
# get the alternate allocator. On most non-SysV systems you can just
|
||||
# define LDLIBS as empty.
|
||||
LDLIBS= -lmalloc
|
||||
|
||||
# miscellaneous OS-dependent stuff
|
||||
LN= $(CC) # linker
|
||||
RM= rm -f # file deletion command
|
||||
AR= ar rc # library (.a) file creation command
|
||||
AR2= ranlib # second step in .a creation (use "touch" if not needed)
|
||||
|
||||
|
||||
# source files
|
||||
INCLUDES= jinclude.h jconfig.h jpegdata.h
|
||||
SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c \
|
||||
jchuff.c jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c \
|
||||
jdarith.c jdcolor.c jdhuff.c jdmain.c jdmaster.c jdmcu.c \
|
||||
jdpipe.c jdsample.c jerror.c jfwddct.c jquant1.c jquant2.c \
|
||||
jrdjfif.c jrdgif.c jrdppm.c jrevdct.c jutils.c jvirtmem.c \
|
||||
jwrjfif.c jwrgif.c jwrppm.c egetopt.c
|
||||
DOCS= README architecture codingrules
|
||||
MAKEFILES= makefile.unix makefile.amiga \
|
||||
makefile.mc5 makefile.mc6 makcjpeg.lnk makdjpeg.lnk \
|
||||
makefile.pwc makcjpeg.cf makdjpeg.cf makljpeg.cf
|
||||
TESTFILES= testorig.jpg testimg.ppm testimg.jpg
|
||||
DISTFILES= $(DOCS) $(MAKEFILES) ansi2knr.c $(SOURCES) $(INCLUDES) $(TESTFILES)
|
||||
|
||||
# compression objectfiles
|
||||
COBJECTS = jcmain.o jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
|
||||
jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
|
||||
jrdgif.o jrdppm.o jwrjfif.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
# decompression objectfiles
|
||||
DOBJECTS = jdmain.o jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
|
||||
jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
|
||||
jrdjfif.o jwrgif.o jwrppm.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
# These objectfiles are included in libjpeg.a (all but jcmain.o, jdmain.o)
|
||||
LIBOBJECTS = jcmaster.o jcdeflts.o jcarith.o jccolor.o jcexpand.o \
|
||||
jchuff.o jcmcu.o jcpipe.o jcsample.o jfwddct.o \
|
||||
jrdgif.o jrdppm.o jwrjfif.o \
|
||||
jdmaster.o jbsmooth.o jdarith.o jdcolor.o jdhuff.o \
|
||||
jdmcu.o jdpipe.o jdsample.o jquant1.o jquant2.o jrevdct.o \
|
||||
jrdjfif.o jwrgif.o jwrppm.o \
|
||||
jutils.o jvirtmem.o jerror.o
|
||||
|
||||
|
||||
all: cjpeg djpeg
|
||||
# By default, libjpeg.a is not built unless you explicitly request it.
|
||||
|
||||
|
||||
# If you have a C compiler that doesn't understand function prototypes,
|
||||
# uncomment the 5 lines below and make sure PROTO is not defined by jconfig.h.
|
||||
# Then say "make ansi2knr" before "make".
|
||||
|
||||
#.c.o:
|
||||
# ./ansi2knr $*.c tmpansi.c
|
||||
# $(CC) $(CFLAGS) -c tmpansi.c
|
||||
# mv tmpansi.o $*.o
|
||||
# $(RM) tmpansi.c
|
||||
|
||||
ansi2knr: ansi2knr.c
|
||||
$(CC) -o ansi2knr ansi2knr.c
|
||||
# You may need to add one of -DBSD, -DVMS, or -DMSDOS to the line above.
|
||||
|
||||
|
||||
cjpeg: $(COBJECTS)
|
||||
$(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) $(LDLIBS)
|
||||
|
||||
djpeg: $(DOBJECTS)
|
||||
$(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) $(LDLIBS)
|
||||
|
||||
# libjpeg.a is useful if you are including the JPEG software in a larger
|
||||
# program; you'd include it in your link, rather than the individual modules.
|
||||
libjpeg.a: $(LIBOBJECTS)
|
||||
$(RM) libjpeg.a
|
||||
$(AR) libjpeg.a $(LIBOBJECTS)
|
||||
$(AR2) libjpeg.a
|
||||
|
||||
clean:
|
||||
$(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core tmpansi.* testout.ppm testout.jpg
|
||||
|
||||
distribute:
|
||||
$(RM) jpegsrc.tar*
|
||||
tar cvf jpegsrc.tar $(DISTFILES)
|
||||
ls -l jpegsrc.tar
|
||||
compress -v jpegsrc.tar
|
||||
ls -l jpegsrc.tar*
|
||||
|
||||
test: cjpeg djpeg
|
||||
$(RM) testout.ppm testout.jpg
|
||||
./djpeg testorig.jpg >testout.ppm
|
||||
./cjpeg testimg.ppm >testout.jpg
|
||||
cmp testimg.ppm testout.ppm
|
||||
cmp testimg.jpg testout.jpg
|
||||
|
||||
|
||||
jbsmooth.o : jbsmooth.c jinclude.h jconfig.h jpegdata.h
|
||||
jcarith.o : jcarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jccolor.o : jccolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jcdeflts.o : jcdeflts.c jinclude.h jconfig.h jpegdata.h
|
||||
jcexpand.o : jcexpand.c jinclude.h jconfig.h jpegdata.h
|
||||
jchuff.o : jchuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmain.o : jcmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jcmaster.o : jcmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jcmcu.o : jcmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jcpipe.o : jcpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jcsample.o : jcsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jdarith.o : jdarith.c jinclude.h jconfig.h jpegdata.h
|
||||
jdcolor.o : jdcolor.c jinclude.h jconfig.h jpegdata.h
|
||||
jdhuff.o : jdhuff.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmain.o : jdmain.c jinclude.h jconfig.h jpegdata.h egetopt.c
|
||||
jdmaster.o : jdmaster.c jinclude.h jconfig.h jpegdata.h
|
||||
jdmcu.o : jdmcu.c jinclude.h jconfig.h jpegdata.h
|
||||
jdpipe.o : jdpipe.c jinclude.h jconfig.h jpegdata.h
|
||||
jdsample.o : jdsample.c jinclude.h jconfig.h jpegdata.h
|
||||
jerror.o : jerror.c jinclude.h jconfig.h jpegdata.h
|
||||
jfwddct.o : jfwddct.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant1.o : jquant1.c jinclude.h jconfig.h jpegdata.h
|
||||
jquant2.o : jquant2.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdjfif.o : jrdjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdgif.o : jrdgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jrdppm.o : jrdppm.c jinclude.h jconfig.h jpegdata.h
|
||||
jrevdct.o : jrevdct.c jinclude.h jconfig.h jpegdata.h
|
||||
jutils.o : jutils.c jinclude.h jconfig.h jpegdata.h
|
||||
jvirtmem.o : jvirtmem.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrjfif.o : jwrjfif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrgif.o : jwrgif.c jinclude.h jconfig.h jpegdata.h
|
||||
jwrppm.o : jwrppm.c jinclude.h jconfig.h jpegdata.h
|
5
makljpeg.cf
Normal file
5
makljpeg.cf
Normal file
@ -0,0 +1,5 @@
|
||||
jbsmooth.mix,jcarith.mix,jccolor.mix,jcdeflts.mix,jcexpand.mix,jchuff.mix
|
||||
jcmaster.mix,jcmcu.mix,jcpipe.mix,jcsample.mix,jdarith.mix,jdcolor.mix
|
||||
jdhuff.mix,jdmaster.mix,jdmcu.mix,jdpipe.mix,jdsample.mix,jerror.mix
|
||||
jfwddct.mix,jquant1.mix,jquant2.mix,jrdgif.mix,jrdjfif.mix,jrdppm.mix
|
||||
jrevdct.mix,jutils.mix,jvirtmem.mix,jwrgif.mix,jwrjfif.mix,jwrppm.mix
|
BIN
testimg.jpg
Normal file
BIN
testimg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
9
testimg.ppm
Normal file
9
testimg.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
testorig.jpg
Normal file
BIN
testorig.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Loading…
Reference in New Issue
Block a user