Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2e6a9dd47 | ||
|
|
5ead57a34a | ||
|
|
489583f516 | ||
|
|
bc79e0680a | ||
|
|
a8b67c4fbb | ||
|
|
9ba2f5ed36 | ||
|
|
36a4ccccd3 | ||
|
|
cc7150e281 | ||
|
|
88aeed428f | ||
|
|
4a6b730364 |
37
CHANGELOG
37
CHANGELOG
@@ -1,37 +0,0 @@
|
|||||||
CHANGELOG for Independent JPEG Group's JPEG software
|
|
||||||
|
|
||||||
Version 2 13-Dec-91
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Documentation improved a little --- there are man pages now.
|
|
||||||
Installation instructions moved from README to a separate file SETUP.
|
|
||||||
|
|
||||||
New program config.c is provided to help you get the configuration options
|
|
||||||
right. This should make installation a lot more foolproof.
|
|
||||||
|
|
||||||
Sense of djpeg -D switch reversed: dithering is now ON by default.
|
|
||||||
|
|
||||||
RLE image file support added (thanks to Mike Lijewski).
|
|
||||||
|
|
||||||
Targa image file support added (thanks to Lee Crocker).
|
|
||||||
|
|
||||||
PPM input now accepts all PPM and PGM files.
|
|
||||||
|
|
||||||
Bug fix: on machines where 'int' is 16 bits, high-Q-setting JPEG files
|
|
||||||
were not decoded correctly.
|
|
||||||
|
|
||||||
Numerous changes to improve portability. There should be few or no compiler
|
|
||||||
warnings now.
|
|
||||||
|
|
||||||
Makefiles cleaned up; defaults now appropriate for production use rather than
|
|
||||||
debugging.
|
|
||||||
|
|
||||||
Subroutine interface cleaned up. If you wrote code based on version 1's
|
|
||||||
jcmain/jdmain, you'll need to change it, but it should get a little shorter
|
|
||||||
and simpler.
|
|
||||||
|
|
||||||
|
|
||||||
Version 1 7-Oct-91
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Initial public release.
|
|
||||||
522
README
522
README
@@ -1,233 +1,133 @@
|
|||||||
The Independent JPEG Group's JPEG software
|
The Independent JPEG Group's JPEG software
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
README for release 2 of 13-Dec-91
|
README for release 6b of 27-Mar-1998
|
||||||
=================================
|
====================================
|
||||||
|
|
||||||
This distribution contains the second public release of the Independent JPEG
|
This distribution contains the sixth public release of the Independent JPEG
|
||||||
Group's free JPEG software. You are welcome to redistribute this software and
|
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.
|
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
|
||||||
|
|
||||||
For installation instructions, see file SETUP; for usage instructions, see
|
Serious users of this software (particularly those incorporating it into
|
||||||
file USAGE (or the cjpeg.1 and djpeg.1 manual pages).
|
larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
|
||||||
|
our electronic mailing list. Mailing list members are notified of updates
|
||||||
|
and have a chance to participate in technical discussions, etc.
|
||||||
|
|
||||||
This software is still undergoing revision. Updated versions may be obtained
|
This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
|
||||||
by FTP or UUCP to uunet.uu.net and other archive sites; see ARCHIVE LOCATIONS
|
Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
|
||||||
below for details.
|
Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
|
||||||
|
Group.
|
||||||
|
|
||||||
If you intend to become a serious user of this software, please contact
|
IJG is not affiliated with the official ISO JPEG standards committee.
|
||||||
jpeg-info@uunet.uu.net to be added to our electronic mailing list. Then
|
|
||||||
you'll be notified of updates and have a chance to participate in discussions,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz,
|
|
||||||
Lee Crocker, and other members of the Independent JPEG Group.
|
|
||||||
|
|
||||||
|
|
||||||
DISCLAIMER
|
DOCUMENTATION ROADMAP
|
||||||
==========
|
=====================
|
||||||
|
|
||||||
THIS SOFTWARE IS NOT COMPLETE NOR FULLY DEBUGGED. It is not guaranteed to be
|
This file contains the following sections:
|
||||||
useful for anything, nor to be compatible with subsequent releases, nor to be
|
|
||||||
an accurate implementation of the JPEG standard. (See LEGAL ISSUES for even
|
|
||||||
more disclaimers.)
|
|
||||||
|
|
||||||
Please report any problems with this software to jpeg-info@uunet.uu.net.
|
OVERVIEW General description of JPEG and the IJG software.
|
||||||
|
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
|
||||||
|
REFERENCES Where to learn more about JPEG.
|
||||||
|
ARCHIVE LOCATIONS Where to find newer versions of this software.
|
||||||
|
RELATED SOFTWARE Other stuff you should get.
|
||||||
|
FILE FORMAT WARS Software *not* to get.
|
||||||
|
TO DO Plans for future IJG releases.
|
||||||
|
|
||||||
|
Other documentation files in the distribution are:
|
||||||
|
|
||||||
|
User documentation:
|
||||||
|
install.doc How to configure and install the IJG software.
|
||||||
|
usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
|
||||||
|
rdjpgcom, and wrjpgcom.
|
||||||
|
*.1 Unix-style man pages for programs (same info as usage.doc).
|
||||||
|
wizard.doc Advanced usage instructions for JPEG wizards only.
|
||||||
|
change.log Version-to-version change highlights.
|
||||||
|
Programmer and internal documentation:
|
||||||
|
libjpeg.doc How to use the JPEG library in your own programs.
|
||||||
|
example.c Sample code for calling the JPEG library.
|
||||||
|
structure.doc Overview of the JPEG library's internal structure.
|
||||||
|
filelist.doc Road map of IJG files.
|
||||||
|
coderules.doc Coding style rules --- please read if you contribute code.
|
||||||
|
|
||||||
|
Please read at least the files install.doc and usage.doc. Useful information
|
||||||
|
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
|
||||||
|
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
|
||||||
|
|
||||||
|
If you want to understand how the JPEG code works, we suggest reading one or
|
||||||
|
more of the REFERENCES, then looking at the documentation files (in roughly
|
||||||
|
the order listed) before diving into the code.
|
||||||
|
|
||||||
|
|
||||||
WHAT'S HERE
|
OVERVIEW
|
||||||
===========
|
========
|
||||||
|
|
||||||
This distribution contains software to implement JPEG image compression and
|
This package contains C software to implement JPEG image compression and
|
||||||
decompression. JPEG (pronounced "jay-peg") is a standardized compression
|
decompression. JPEG (pronounced "jay-peg") is a standardized compression
|
||||||
method for full-color and gray-scale images. JPEG is intended for
|
method for full-color and gray-scale images. JPEG is intended for compressing
|
||||||
"real-world" scenes; cartoons and other non-realistic images are not its
|
"real-world" scenes; line drawings, cartoons and other non-realistic images
|
||||||
strong suit. JPEG is lossy, meaning that the output image is not necessarily
|
are not its strong suit. JPEG is lossy, meaning that the output image is not
|
||||||
identical to the input image. Hence you should not use JPEG if you have to
|
exactly identical to the input image. Hence you must not use JPEG if you
|
||||||
have identical output bits. However, on typical images of real-world scenes,
|
have to have identical output bits. However, on typical photographic images,
|
||||||
very good compression levels can be obtained with no visible change, and
|
very good compression levels can be obtained with no visible change, and
|
||||||
amazingly high compression levels can be obtained if you can tolerate a
|
remarkably high compression levels are possible if you can tolerate a
|
||||||
low-quality image. For more details, see the references, or just experiment
|
low-quality image. For more details, see the references, or just experiment
|
||||||
with various compression settings.
|
with various compression settings.
|
||||||
|
|
||||||
The software implements JPEG baseline and extended-sequential compression
|
This software implements JPEG baseline, extended-sequential, and progressive
|
||||||
processes. Provision is made for supporting all variants of these processes,
|
compression processes. Provision is made for supporting all variants of these
|
||||||
although some uncommon parameter settings aren't implemented yet. For legal
|
processes, although some uncommon parameter settings aren't implemented yet.
|
||||||
reasons, we are not distributing code for the arithmetic-coding process; see
|
For legal reasons, we are not distributing code for the arithmetic-coding
|
||||||
LEGAL ISSUES. At present we have made no provision for supporting the
|
variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
|
||||||
progressive or lossless processes defined in the standard.
|
the hierarchical or lossless processes defined in the standard.
|
||||||
|
|
||||||
The present software is still largely in the prototype stage. It does not
|
We provide a set of library routines for reading and writing JPEG image files,
|
||||||
support all possible variants of the JPEG standard, and some functions have
|
plus two sample applications "cjpeg" and "djpeg", which use the library to
|
||||||
rather slow and/or crude implementations. However, it is useful already.
|
perform conversion between JPEG and some other popular image file formats.
|
||||||
|
The library is intended to be reused in other applications.
|
||||||
|
|
||||||
|
In order to support file conversion and viewing software, we have included
|
||||||
|
considerable functionality beyond the bare JPEG coding/decoding capability;
|
||||||
|
for example, the color quantization modules are not strictly part of JPEG
|
||||||
|
decoding, but they are essential for output to colormapped file formats or
|
||||||
|
colormapped displays. These extra functions can be compiled out of the
|
||||||
|
library if not required for a particular application. We have also included
|
||||||
|
"jpegtran", a utility for lossless transcoding between different JPEG
|
||||||
|
processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
|
||||||
|
inserting and extracting textual comments in JFIF files.
|
||||||
|
|
||||||
The emphasis in designing this software has been on achieving portability and
|
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
|
flexibility, while also making it fast enough to be useful. In particular,
|
||||||
undertaken serious performance measurement or tuning; we intend to do so in
|
the software is not intended to be read as a tutorial on JPEG. (See the
|
||||||
the future.
|
REFERENCES section for introductory material.) Rather, it is intended to
|
||||||
|
be reliable, portable, industrial-strength code. We do not claim to have
|
||||||
|
achieved that goal in every aspect of the software, but we strive for it.
|
||||||
|
|
||||||
|
We welcome the use of this software as a component of commercial products.
|
||||||
This software can be used on several levels:
|
No royalty is required, but we do ask for an acknowledgement in product
|
||||||
|
documentation, as described under LEGAL ISSUES.
|
||||||
* As canned software for JPEG compression and decompression. Just edit the
|
|
||||||
Makefile and configuration files as needed (see file SETUP), compile and go.
|
|
||||||
Members of the independent JPEG group will improve the out-of-the-box
|
|
||||||
functionality and speed as time goes on.
|
|
||||||
|
|
||||||
* As the basis for other JPEG programs. For example, you could incorporate
|
|
||||||
the decompressor into a general image viewing package by replacing the
|
|
||||||
output module with write-to-screen functions. For an implementation on
|
|
||||||
specific hardware, you might want to replace some of the inner loops with
|
|
||||||
assembly code. For a non-command-line-driven system, you might want a
|
|
||||||
different user interface. (Members of the group will be producing Macintosh
|
|
||||||
and Amiga versions with more appropriate user interfaces, for example.)
|
|
||||||
|
|
||||||
* As a toolkit for experimentation with JPEG and JPEG-like algorithms. Most
|
|
||||||
of the individual decisions you might want to mess with are packaged up into
|
|
||||||
separate modules. For example, the details of color-space conversion and
|
|
||||||
subsampling techniques are each localized in one compressor and one
|
|
||||||
decompressor module. You'd probably also want to extend the user interface
|
|
||||||
to give you more detailed control over the JPEG compression parameters.
|
|
||||||
|
|
||||||
In particular, we welcome the use of this software as the basis for commercial
|
|
||||||
products; no royalty is required.
|
|
||||||
|
|
||||||
|
|
||||||
ARCHIVE LOCATIONS
|
|
||||||
=================
|
|
||||||
|
|
||||||
The "official" archive site for this software is uunet.uu.net (Internet
|
|
||||||
address 137.39.1.2 or 192.48.96.2). The most recent released version can
|
|
||||||
always be found there in directory graphics/jpeg. This particular version
|
|
||||||
will be archived as jpegsrc.v2.tar.Z. If you are on the Internet, you can
|
|
||||||
retrieve files from UUNET by anonymous FTP. If you don't have FTP access,
|
|
||||||
UUNET's archives are also available via UUCP; contact postmaster@uunet.uu.net
|
|
||||||
for information on retrieving files that way.
|
|
||||||
|
|
||||||
Various other Internet sites maintain copies of the UUNET file, which may or
|
|
||||||
may not be up-to-date. In Europe, try nic.funet.fi (128.214.6.100; look in
|
|
||||||
directory pub/graphics/programs/jpeg).
|
|
||||||
|
|
||||||
You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum
|
|
||||||
(GO PICS), library 10; this version will be file jpsrc2.zip.
|
|
||||||
|
|
||||||
If you are not reasonably handy at configuring and installing portable C
|
|
||||||
programs, you may have some difficulty installing this package. You may
|
|
||||||
prefer to obtain a pre-built executable version. A collection of pre-built
|
|
||||||
executables for various machines is currently available for anonymous FTP at
|
|
||||||
procyon.cis.ksu.edu (129.130.10.80 --- this number is due to change soon);
|
|
||||||
look under /pub/JPEG. The administrators of this system ask that FTP traffic
|
|
||||||
be limited to non-prime hours. For more information on this archive, please
|
|
||||||
contact Steve Davis (strat@cis.ksu.edu). This collection is not maintained by
|
|
||||||
the Independent JPEG Group, and programs in it may not be the latest version.
|
|
||||||
|
|
||||||
|
|
||||||
SUPPORTING SOFTWARE
|
|
||||||
===================
|
|
||||||
|
|
||||||
You will probably want Jef Poskanzer's PBMPLUS image software, which provides
|
|
||||||
many useful operations on PPM-format image files. In particular, it can
|
|
||||||
convert PPM images to and from a wide range of other formats. You can FTP
|
|
||||||
this free software from export.lcs.mit.edu (contrib/pbmplus*.tar.Z) or
|
|
||||||
ftp.ee.lbl.gov (pbmplus*.tar.Z). Unfortunately PBMPLUS is not nearly as
|
|
||||||
portable as the JPEG software is; you are likely to have difficulty making it
|
|
||||||
work on any non-Unix machine.
|
|
||||||
|
|
||||||
If you are using X Windows you might want to use the xv or xloadimage viewers
|
|
||||||
to save yourself the trouble of converting PPM to some other format. Both of
|
|
||||||
these can be found in the contrib directory at export.lcs.mit.edu.
|
|
||||||
There will soon be a new release of xv that incorporates our software and thus
|
|
||||||
can read and write JPEG files directly. (NOTE: since xv internally reduces
|
|
||||||
all images to 8 bits/pixel, a JPEG file written by xv will not be very high
|
|
||||||
quality. Caveat user.)
|
|
||||||
|
|
||||||
|
|
||||||
SOFTWARE THAT'S NO HELP AT ALL
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Handmade Software's shareware PC program GIF2JPG produces files that are
|
|
||||||
totally incompatible with our programs. They use a proprietary format that is
|
|
||||||
an amalgam of GIF and JPEG representations. However, you can force GIF2JPG
|
|
||||||
to produce compatible files with its -j switch, and their decompression
|
|
||||||
program JPG2GIF can read our files (at least ones produced with our default
|
|
||||||
option settings).
|
|
||||||
|
|
||||||
Unfortunately, most commercial JPEG implementations are also incompatible as
|
|
||||||
of this writing, especially programs released before summer 1991. The root of
|
|
||||||
the problem is that the ISO JPEG committee failed to specify a concrete file
|
|
||||||
format. Many vendors "filled in the blanks" on their own, creating
|
|
||||||
proprietary formats that no one else could read. (For example, none of the
|
|
||||||
early commercial JPEG implementations for the Macintosh were able to exchange
|
|
||||||
compressed files.)
|
|
||||||
|
|
||||||
The file format we have adopted is called JFIF (see REFERENCES). This format
|
|
||||||
has been agreed to by a number of major commercial JPEG vendors, and we expect
|
|
||||||
that it will become the de facto standard. JFIF is a minimal representation;
|
|
||||||
work is also going forward to incorporate JPEG compression into the TIFF
|
|
||||||
standard, for use in "high end" applications that need to record a lot of
|
|
||||||
additional data about an image. We intend to support JPEG-in-TIFF in the
|
|
||||||
future. We hope that these two formats will be sufficient and that other,
|
|
||||||
incompatible JPEG file formats will not proliferate.
|
|
||||||
|
|
||||||
Indeed, part of the reason for developing and releasing this free software is
|
|
||||||
to help force rapid convergence to de facto standards for JPEG file formats.
|
|
||||||
SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or JPEG-in-TIFF!
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCES
|
|
||||||
==========
|
|
||||||
|
|
||||||
The best and most readily available introduction to the JPEG compression
|
|
||||||
algorithm is Wallace's article in the April '91 CACM:
|
|
||||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
|
||||||
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
|
||||||
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
|
||||||
applications of JPEG, and related topics.) We highly recommend reading that
|
|
||||||
article before trying to understand the innards of any JPEG software.
|
|
||||||
|
|
||||||
For more detail about the JPEG standard you pretty much have to go to the
|
|
||||||
draft standard (which is not nearly as intelligible as Wallace's article).
|
|
||||||
The standard is not now available electronically; you must order a paper copy
|
|
||||||
through ISO. In the US, copies may be ordered from ANSI Sales at (212)
|
|
||||||
642-4900. The standard is divided into two parts: Part 1 is the actual
|
|
||||||
specification, and Part 2 covers compliance testing methods. The current
|
|
||||||
"committee draft" version of Part 1 is titled "Digital Compression and Coding
|
|
||||||
of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has
|
|
||||||
document number ISO/IEC CD 10918-1. (The alternate number SC2 N2215 should
|
|
||||||
also be mentioned when ordering.) This draft is expected to be superseded by
|
|
||||||
the Draft International Standard version around the end of November 1991.
|
|
||||||
Ordering info will be the same as above, but replace "CD" with "DIS" in the
|
|
||||||
document number (alternate number not yet known). The committee draft of
|
|
||||||
Part 2 is expected to be available around the end of December 1991. It will
|
|
||||||
be titled "Digital Compression and Coding of Continuous-tone Still Images,
|
|
||||||
Part 2: Compliance testing" and will have document number ISO/IEC CD 10918-2
|
|
||||||
(alternate number not yet known).
|
|
||||||
|
|
||||||
The JPEG standard does not specify all details of an interchangeable file
|
|
||||||
format. For the omitted details we follow the "JFIF" conventions, revision
|
|
||||||
1.01. A copy of the JFIF spec is available from:
|
|
||||||
Literature Department
|
|
||||||
C-Cube Microsystems, Inc.
|
|
||||||
399A West Trimble Road
|
|
||||||
San Jose, CA 95131
|
|
||||||
(408) 944-6300
|
|
||||||
Requests can also be e-mailed to info@c3.pla.ca.us. The same source can
|
|
||||||
supply copies of the draft JPEG-in-TIFF specs.
|
|
||||||
|
|
||||||
If you want to understand this implementation, start by reading the
|
|
||||||
"architecture" documentation file. Please read "codingrules" if you want to
|
|
||||||
contribute any code.
|
|
||||||
|
|
||||||
|
|
||||||
LEGAL ISSUES
|
LEGAL ISSUES
|
||||||
============
|
============
|
||||||
|
|
||||||
|
In plain English:
|
||||||
|
|
||||||
|
1. We don't promise that this software works. (But if you find any bugs,
|
||||||
|
please let us know!)
|
||||||
|
2. You can use this software for whatever you want. You don't have to pay us.
|
||||||
|
3. You may not pretend that you wrote this software. If you use it in a
|
||||||
|
program, you must acknowledge somewhere in your documentation that
|
||||||
|
you've used the IJG code.
|
||||||
|
|
||||||
|
In legalese:
|
||||||
|
|
||||||
The authors make NO WARRANTY or representation, either express or implied,
|
The authors make NO WARRANTY or representation, either express or implied,
|
||||||
with respect to this software, its quality, accuracy, merchantability, or
|
with respect to this software, its quality, accuracy, merchantability, or
|
||||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
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.
|
its user, assume the entire risk as to its quality and accuracy.
|
||||||
|
|
||||||
This software is copyright (C) 1991, Thomas G. Lane.
|
This software is copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
All Rights Reserved except as specified below.
|
All Rights Reserved except as specified below.
|
||||||
|
|
||||||
Permission is hereby granted to use, copy, modify, and distribute this
|
Permission is hereby granted to use, copy, modify, and distribute this
|
||||||
@@ -244,10 +144,14 @@ the Independent JPEG Group".
|
|||||||
full responsibility for any undesirable consequences; the authors accept
|
full responsibility for any undesirable consequences; the authors accept
|
||||||
NO LIABILITY for damages of any kind.
|
NO LIABILITY for damages of any kind.
|
||||||
|
|
||||||
Permission is NOT granted for the use of any author's name or author's company
|
These conditions apply to any software derived from or based on the IJG code,
|
||||||
name in advertising or publicity relating to this software or products derived
|
not just to the unmodified library. If you use our work, you ought to
|
||||||
from it. This software may be referred to only as "the Independent JPEG
|
acknowledge us.
|
||||||
Group's software".
|
|
||||||
|
Permission is NOT granted for the use of any IJG author's name or company name
|
||||||
|
in advertising or publicity relating to this software or products derived from
|
||||||
|
it. This software may be referred to only as "the Independent JPEG Group's
|
||||||
|
software".
|
||||||
|
|
||||||
We specifically permit and encourage the use of this software as the basis of
|
We specifically permit and encourage the use of this software as the basis of
|
||||||
commercial products, provided that all warranty or liability claims are
|
commercial products, provided that all warranty or liability claims are
|
||||||
@@ -260,21 +164,30 @@ ansi2knr.c is NOT covered by the above copyright and conditions, but instead
|
|||||||
by the usual distribution terms of the Free Software Foundation; principally,
|
by the usual distribution terms of the Free Software Foundation; principally,
|
||||||
that you must include source code if you redistribute it. (See the file
|
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
|
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
|
||||||
of any product generated from the JPEG code, this does not limit you more than
|
of any program generated from the IJG code, this does not limit you more than
|
||||||
the foregoing paragraphs do.
|
the foregoing paragraphs do.
|
||||||
|
|
||||||
|
The Unix configuration script "configure" was produced with GNU Autoconf.
|
||||||
|
It is copyright by the Free Software Foundation but is freely distributable.
|
||||||
|
The same holds for its supporting scripts (config.guess, config.sub,
|
||||||
|
ltconfig, ltmain.sh). Another support script, install-sh, is copyright
|
||||||
|
by M.I.T. but is also freely distributable.
|
||||||
|
|
||||||
It appears that the arithmetic coding option of the JPEG spec is covered by
|
It appears that the arithmetic coding option of the JPEG spec is covered by
|
||||||
patents owned by IBM and AT&T, as well as a pending Japanese patent of
|
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
|
||||||
Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining
|
legally be used without obtaining one or more licenses. For this reason,
|
||||||
one or more licenses. For this reason, support for arithmetic coding has been
|
support for arithmetic coding has been removed from the free JPEG software.
|
||||||
removed from the free JPEG software. (Since arithmetic coding provides only a
|
(Since arithmetic coding provides only a marginal gain over the unpatented
|
||||||
marginal gain over the unpatented Huffman mode, it is unlikely that very many
|
Huffman mode, it is unlikely that very many implementations will support it.)
|
||||||
people will choose to use it. If you do obtain the necessary licenses,
|
|
||||||
contact jpeg-info@uunet.uu.net for a copy of our arithmetic coding modules.)
|
|
||||||
So far as we are aware, there are no patent restrictions on the remaining
|
So far as we are aware, there are no patent restrictions on the remaining
|
||||||
code.
|
code.
|
||||||
|
|
||||||
|
The IJG distribution formerly included code to read and write GIF files.
|
||||||
|
To avoid entanglement with the Unisys LZW patent, GIF reading support has
|
||||||
|
been removed altogether, and the GIF writer has been simplified to produce
|
||||||
|
"uncompressed GIFs". This technique does not use the LZW algorithm; the
|
||||||
|
resulting GIF files are larger than usual, but are readable by all standard
|
||||||
|
GIF decoders.
|
||||||
|
|
||||||
We are required to state that
|
We are required to state that
|
||||||
"The Graphics Interchange Format(c) is the Copyright property of
|
"The Graphics Interchange Format(c) is the Copyright property of
|
||||||
@@ -282,22 +195,191 @@ We are required to state that
|
|||||||
CompuServe Incorporated."
|
CompuServe Incorporated."
|
||||||
|
|
||||||
|
|
||||||
|
REFERENCES
|
||||||
|
==========
|
||||||
|
|
||||||
|
We highly recommend reading one or more of these references before trying to
|
||||||
|
understand the innards of the JPEG software.
|
||||||
|
|
||||||
|
The best short technical introduction to the JPEG compression algorithm is
|
||||||
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||||
|
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||||
|
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||||
|
applications of JPEG, and related topics.) If you don't have the CACM issue
|
||||||
|
handy, a PostScript file containing a revised version of Wallace's article is
|
||||||
|
available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
|
||||||
|
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
|
||||||
|
omits the sample images that appeared in CACM, but it includes corrections
|
||||||
|
and some added material. Note: the Wallace article is copyright ACM and IEEE,
|
||||||
|
and it may not be used for commercial purposes.
|
||||||
|
|
||||||
|
A somewhat less technical, more leisurely introduction to JPEG can be found in
|
||||||
|
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
|
||||||
|
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
|
||||||
|
good explanations and example C code for a multitude of compression methods
|
||||||
|
including JPEG. It is an excellent source if you are comfortable reading C
|
||||||
|
code but don't know much about data compression in general. The book's JPEG
|
||||||
|
sample code is far from industrial-strength, but when you are ready to look
|
||||||
|
at a full implementation, you've got one here...
|
||||||
|
|
||||||
|
The best full description of JPEG is the textbook "JPEG Still Image Data
|
||||||
|
Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
|
||||||
|
by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
|
||||||
|
The book includes the complete text of the ISO JPEG standards (DIS 10918-1
|
||||||
|
and draft DIS 10918-2). This is by far the most complete exposition of JPEG
|
||||||
|
in existence, and we highly recommend it.
|
||||||
|
|
||||||
|
The JPEG standard itself is not available electronically; you must order a
|
||||||
|
paper copy through ISO or ITU. (Unless you feel a need to own a certified
|
||||||
|
official copy, we recommend buying the Pennebaker and Mitchell book instead;
|
||||||
|
it's much cheaper and includes a great deal of useful explanatory material.)
|
||||||
|
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
|
||||||
|
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
|
||||||
|
doesn't take credit card orders, but Global does.) It's not cheap: as of
|
||||||
|
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
|
||||||
|
shipping/handling. The standard is divided into two parts, Part 1 being the
|
||||||
|
actual specification, while Part 2 covers compliance testing methods. Part 1
|
||||||
|
is titled "Digital Compression and Coding of Continuous-tone Still Images,
|
||||||
|
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
|
||||||
|
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
|
||||||
|
Continuous-tone Still Images, Part 2: Compliance testing" and has document
|
||||||
|
numbers ISO/IEC IS 10918-2, ITU-T T.83.
|
||||||
|
|
||||||
|
Some extensions to the original JPEG standard are defined in JPEG Part 3,
|
||||||
|
a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
|
||||||
|
currently does not support any Part 3 extensions.
|
||||||
|
|
||||||
|
The JPEG standard does not specify all details of an interchangeable file
|
||||||
|
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||||
|
1.02. A copy of the JFIF spec is available from:
|
||||||
|
Literature Department
|
||||||
|
C-Cube Microsystems, Inc.
|
||||||
|
1778 McCarthy Blvd.
|
||||||
|
Milpitas, CA 95035
|
||||||
|
phone (408) 944-6300, fax (408) 944-6314
|
||||||
|
A PostScript version of this document is available by FTP at
|
||||||
|
ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
|
||||||
|
version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
|
||||||
|
the figures.
|
||||||
|
|
||||||
|
The TIFF 6.0 file format specification can be obtained by FTP from
|
||||||
|
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
|
||||||
|
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
|
||||||
|
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
|
||||||
|
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
|
||||||
|
(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
|
||||||
|
from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
|
||||||
|
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
|
||||||
|
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
|
||||||
|
uses our library to implement TIFF/JPEG per the Note. libtiff is available
|
||||||
|
from ftp://ftp.sgi.com/graphics/tiff/.
|
||||||
|
|
||||||
|
|
||||||
|
ARCHIVE LOCATIONS
|
||||||
|
=================
|
||||||
|
|
||||||
|
The "official" archive site for this software is ftp.uu.net (Internet
|
||||||
|
address 192.48.96.9). The most recent released version can always be found
|
||||||
|
there in directory graphics/jpeg. This particular version will be archived
|
||||||
|
as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
|
||||||
|
direct Internet access, UUNET's archives are also available via UUCP; contact
|
||||||
|
help@uunet.uu.net for information on retrieving files that way.
|
||||||
|
|
||||||
|
Numerous Internet sites maintain copies of the UUNET files. However, only
|
||||||
|
ftp.uu.net is guaranteed to have the latest official version.
|
||||||
|
|
||||||
|
You can also obtain this software in DOS-compatible "zip" archive format from
|
||||||
|
the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
|
||||||
|
on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
|
||||||
|
"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
|
||||||
|
release.
|
||||||
|
|
||||||
|
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
|
||||||
|
general information about JPEG. It is updated constantly and therefore is
|
||||||
|
not included in this distribution. The FAQ is posted every two weeks to
|
||||||
|
Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
|
||||||
|
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
|
||||||
|
and other news.answers archive sites, including the official news.answers
|
||||||
|
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
|
||||||
|
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
|
||||||
|
with body
|
||||||
|
send usenet/news.answers/jpeg-faq/part1
|
||||||
|
send usenet/news.answers/jpeg-faq/part2
|
||||||
|
|
||||||
|
|
||||||
|
RELATED SOFTWARE
|
||||||
|
================
|
||||||
|
|
||||||
|
Numerous viewing and image manipulation programs now support JPEG. (Quite a
|
||||||
|
few of them use this library to do so.) The JPEG FAQ described above lists
|
||||||
|
some of the more popular free and shareware viewers, and tells where to
|
||||||
|
obtain them on Internet.
|
||||||
|
|
||||||
|
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
|
||||||
|
PBMPLUS software, which provides many useful operations on PPM-format image
|
||||||
|
files. In particular, it can convert PPM images to and from a wide range of
|
||||||
|
other formats, thus making cjpeg/djpeg considerably more useful. The latest
|
||||||
|
version is distributed by the NetPBM group, and is available from numerous
|
||||||
|
sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
|
||||||
|
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
|
||||||
|
you are likely to have difficulty making it work on any non-Unix machine.
|
||||||
|
|
||||||
|
A different free JPEG implementation, written by the PVRG group at Stanford,
|
||||||
|
is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
|
||||||
|
is designed for research and experimentation rather than production use;
|
||||||
|
it is slower, harder to use, and less portable than the IJG code, but it
|
||||||
|
is easier to read and modify. Also, the PVRG code supports lossless JPEG,
|
||||||
|
which we do not. (On the other hand, it doesn't do progressive JPEG.)
|
||||||
|
|
||||||
|
|
||||||
|
FILE FORMAT WARS
|
||||||
|
================
|
||||||
|
|
||||||
|
Some JPEG programs produce files that are not compatible with our library.
|
||||||
|
The root of the problem is that the ISO JPEG committee failed to specify a
|
||||||
|
concrete file format. Some vendors "filled in the blanks" on their own,
|
||||||
|
creating proprietary formats that no one else could read. (For example, none
|
||||||
|
of the early commercial JPEG implementations for the Macintosh were able to
|
||||||
|
exchange compressed files.)
|
||||||
|
|
||||||
|
The file format we have adopted is called JFIF (see REFERENCES). This format
|
||||||
|
has been agreed to by a number of major commercial JPEG vendors, and it has
|
||||||
|
become the de facto standard. JFIF is a minimal or "low end" representation.
|
||||||
|
We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
|
||||||
|
Technical Note #2) for "high end" applications that need to record a lot of
|
||||||
|
additional data about an image. TIFF/JPEG is fairly new and not yet widely
|
||||||
|
supported, unfortunately.
|
||||||
|
|
||||||
|
The upcoming JPEG Part 3 standard defines a file format called SPIFF.
|
||||||
|
SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
|
||||||
|
be able to read the most common variant of SPIFF. SPIFF has some technical
|
||||||
|
advantages over JFIF, but its major claim to fame is simply that it is an
|
||||||
|
official standard rather than an informal one. At this point it is unclear
|
||||||
|
whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
|
||||||
|
standard. IJG intends to support SPIFF once the standard is frozen, but we
|
||||||
|
have not decided whether it should become our default output format or not.
|
||||||
|
(In any case, our decoder will remain capable of reading JFIF indefinitely.)
|
||||||
|
|
||||||
|
Various proprietary file formats incorporating JPEG compression also exist.
|
||||||
|
We have little or no sympathy for the existence of these formats. Indeed,
|
||||||
|
one of the original reasons for developing this free software was to help
|
||||||
|
force convergence on common, open format standards for JPEG files. Don't
|
||||||
|
use a proprietary file format!
|
||||||
|
|
||||||
|
|
||||||
TO DO
|
TO DO
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Many of the modules need fleshing out to provide more complete
|
The major thrust for v7 will probably be improvement of visual quality.
|
||||||
implementations, or to provide faster paths for common cases. The greatest
|
The current method for scaling the quantization tables is known not to be
|
||||||
needs are for (a) decent color quantization, and (b) a memory manager
|
very good at low Q values. We also intend to investigate block boundary
|
||||||
implementation that can work in limited memory by swapping "big" images to
|
smoothing, "poor man's variable quantization", and other means of improving
|
||||||
temporary files. I (Tom Lane) am going to work on color quantization next.
|
quality-vs-file-size performance without sacrificing compatibility.
|
||||||
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
|
In future versions, we are considering supporting some of the upcoming JPEG
|
||||||
variety of systems as possible, and report any portability problems
|
Part 3 extensions --- principally, variable quantization and the SPIFF file
|
||||||
encountered (with solutions, if possible). Checks of file compatibility with
|
format.
|
||||||
other JPEG implementations would also be of interest. Finally, we would
|
|
||||||
appreciate code profiles showing where the most time is spent, especially on
|
As always, speeding things up is of great interest.
|
||||||
unusual systems.
|
|
||||||
|
|
||||||
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
|
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
|
||||||
|
|||||||
235
SETUP
235
SETUP
@@ -1,235 +0,0 @@
|
|||||||
SETUP instructions for the Independent JPEG Group's JPEG software
|
|
||||||
=================================================================
|
|
||||||
|
|
||||||
This file explains how to configure and compile the JPEG software. We have
|
|
||||||
tried to make this software extremely portable and flexible, so that it can be
|
|
||||||
adapted to almost any environment. The downside of this decision is that the
|
|
||||||
installation process is not very automatic; you will need at least a little
|
|
||||||
familiarity with C programming and program build procedures for your system.
|
|
||||||
|
|
||||||
This file contains general instructions, then sections of specific hints for
|
|
||||||
certain systems. You may save yourself considerable time if you scan the
|
|
||||||
whole file before starting to do anything.
|
|
||||||
|
|
||||||
Before installing the software you must unpack the distributed source code.
|
|
||||||
Since you are reading this file, you have probably already succeeded in this
|
|
||||||
task. However, there is one potential trap if you are on a non-Unix system:
|
|
||||||
you may need to convert these files to the local standard text file format
|
|
||||||
(for example, if you are on MS-DOS you probably have to convert LF end-of-line
|
|
||||||
to CR/LF). If so, apply the conversion to all the files EXCEPT those whose
|
|
||||||
names begin with "test". The test files contain binary data; if you change
|
|
||||||
them in any way then the self-test will give bad results.
|
|
||||||
|
|
||||||
|
|
||||||
STEP 1: PREPARE A MAKEFILE
|
|
||||||
==========================
|
|
||||||
|
|
||||||
First, select a makefile and copy it to "Makefile" (or whatever your version
|
|
||||||
of make uses as the default makefile name; for example, "makefile.mak" for
|
|
||||||
Borland C). We include several standard makefiles in the distribution:
|
|
||||||
|
|
||||||
makefile.ansi: for Unix systems with ANSI-compatible C compilers.
|
|
||||||
makefile.unix: for Unix systems with non-ANSI C compilers.
|
|
||||||
makefile.mc5: for Microsoft C 5.x under MS-DOS.
|
|
||||||
makefile.mc6: for Microsoft C 6.x under MS-DOS.
|
|
||||||
makefile.tc: for Borland's Turbo C under MS-DOS.
|
|
||||||
makefile.pwc: for Mix Software's Power C under MS-DOS.
|
|
||||||
makefile.manx: for Manx Aztec C on Amigas.
|
|
||||||
makefile.sas: for SAS C on Amigas.
|
|
||||||
|
|
||||||
If you don't see a makefile for your system, we recommend starting from either
|
|
||||||
makefile.ansi or makefile.unix, depending on whether your compiler accepts
|
|
||||||
ANSI C or not. Actually you should start with makefile.ansi whenever your
|
|
||||||
compiler supports ANSI-style function definitions; you don't need full ANSI
|
|
||||||
compatibility. The difference between the two makefiles is that makefile.unix
|
|
||||||
preprocesses the source code to convert function definitions to old-style C.
|
|
||||||
(Our thanks to Peter Deutsch of Aladdin Enterprises for the ansi2knr program.)
|
|
||||||
|
|
||||||
If you don't know whether your compiler supports ANSI-style function
|
|
||||||
definitions, then take a look at config.c. It is a test program that will
|
|
||||||
help you figure out this fact, as well as some other facts you'll need in
|
|
||||||
later steps. You must compile and execute config.c by hand; the makefiles
|
|
||||||
don't provide any support for this. config.c may not compile the first try
|
|
||||||
(in fact, the whole idea is for it to fail if anything is going to). If you
|
|
||||||
get compile errors, fix them by editing config.c according to the directions
|
|
||||||
given in config.c. Once you get it to run, select a makefile according to the
|
|
||||||
advice it prints out, and make any other changes it recommends.
|
|
||||||
|
|
||||||
Look over the selected Makefile and adjust options as needed. In particular
|
|
||||||
you may want to change the CC and CFLAGS definitions. For instance, if you
|
|
||||||
are using GCC, set CC=gcc.
|
|
||||||
|
|
||||||
If you are on a system that doesn't use makefiles, you'll need to set up
|
|
||||||
project files (or whatever you do use) to compile all the source files and
|
|
||||||
link them into executable files cjpeg and djpeg. See the file lists in any of
|
|
||||||
the makefiles to find out which files go into each program (makcjpeg.lst and
|
|
||||||
makdjpeg.lst are handy summaries).
|
|
||||||
|
|
||||||
|
|
||||||
STEP 2: EDIT JCONFIG.H
|
|
||||||
======================
|
|
||||||
|
|
||||||
Look over jconfig.h and adjust #defines to reflect the properties of your
|
|
||||||
system and C compiler. (If you prefer, you can usually leave jconfig.h
|
|
||||||
unmodified and add -Dsymbol switches to the Makefile's CFLAGS definition.)
|
|
||||||
|
|
||||||
If you have an ANSI-compliant C compiler, no changes should be necessary
|
|
||||||
except perhaps for RIGHT_SHIFT_IS_UNSIGNED and TWO_FILE_COMMANDLINE. For
|
|
||||||
older compilers other changes may be needed, depending on what ANSI features
|
|
||||||
are supported.
|
|
||||||
|
|
||||||
If you don't know enough about C programming to understand the questions in
|
|
||||||
jconfig.h, then use config.c to figure out what to change. (See description
|
|
||||||
of config.c in step 1.)
|
|
||||||
|
|
||||||
A note about TWO_FILE_COMMANDLINE: defining this selects the command line
|
|
||||||
syntax in which the input and output files are both named on the command line.
|
|
||||||
If it's not defined, the output image goes to standard output, and the input
|
|
||||||
can optionally come from standard input. You MUST use two-file style on any
|
|
||||||
system that doesn't cope well with binary data fed through stdin/stdout; this
|
|
||||||
is true for most MS-DOS compilers, for example. If you're not on a Unix
|
|
||||||
system, it's probably safest to assume you need two-file style.
|
|
||||||
|
|
||||||
|
|
||||||
STEP 3: MAKE
|
|
||||||
============
|
|
||||||
|
|
||||||
Now you should be able to "make" the software.
|
|
||||||
|
|
||||||
If you have trouble with missing system include files or inclusion of the
|
|
||||||
wrong ones, look at jinclude.h (or use config.c, if you are not a C expert).
|
|
||||||
|
|
||||||
If your compiler complains about big_sarray_control and big_barray_control
|
|
||||||
being undefined structures, you should be able to shut it up by adding
|
|
||||||
-DINCOMPLETE_TYPES_BROKEN to CFLAGS (or add #define INCOMPLETE_TYPES_BROKEN
|
|
||||||
to jconfig.h).
|
|
||||||
|
|
||||||
There are a fair number of routines that do not use all of their parameters;
|
|
||||||
some compilers will issue warnings about this, which you can ignore. Any
|
|
||||||
other warning deserves investigation.
|
|
||||||
|
|
||||||
|
|
||||||
STEP 4: TEST
|
|
||||||
============
|
|
||||||
|
|
||||||
As a quick test of functionality we've included three small sample files:
|
|
||||||
testorig.jpg A reduced section of the well-known Lenna picture.
|
|
||||||
testimg.ppm The output of djpeg testorig.jpg
|
|
||||||
testimg.jpg The output of cjpeg testimg.ppm
|
|
||||||
(The two .jpg files aren't identical since JPEG is lossy.) If you can
|
|
||||||
generate duplicates of testimg.ppm and testimg.jpg then you probably have a
|
|
||||||
working port.
|
|
||||||
|
|
||||||
With most of the makefiles, "make test" will perform the necessary
|
|
||||||
comparisons. If you're using a makefile that doesn't provide this option, run
|
|
||||||
djpeg and cjpeg to generate testout.ppm and testout.jpg, then compare these to
|
|
||||||
testimg.* with whatever file comparison tool you have. The files should be
|
|
||||||
bit-for-bit identical.
|
|
||||||
|
|
||||||
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 the test passes, you can copy the executable files cjpeg and djpeg to
|
|
||||||
wherever you normally install programs. Read the file USAGE to learn more
|
|
||||||
about using the programs.
|
|
||||||
|
|
||||||
|
|
||||||
OPTIONAL STUFF
|
|
||||||
==============
|
|
||||||
|
|
||||||
We distribute the software with support for RLE image files (Utah Raster
|
|
||||||
Toolkit format) disabled, because the RLE support won't compile without the
|
|
||||||
Utah library. If you have URT version 3.0, you can enable RLE support as
|
|
||||||
follows:
|
|
||||||
1. #define RLE_SUPPORTED in jconfig.h or in the Makefile.
|
|
||||||
2. Add a -I option to CFLAGS in the Makefile for the directory
|
|
||||||
containing the URT .h files (typically the "include"
|
|
||||||
subdirectory of the URT distribution).
|
|
||||||
3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
|
|
||||||
the directory containing the URT "librle.a" file (typically the
|
|
||||||
"lib" subdirectory of the URT distribution).
|
|
||||||
|
|
||||||
If you want to incorporate the JPEG code as subroutines in a larger program,
|
|
||||||
we recommend that you make libjpeg.a. Then use the jconfig.h and jpegdata.h
|
|
||||||
files as your interface to the JPEG functions, and link libjpeg.a with your
|
|
||||||
program. Your surrounding program will have to provide functionality similar
|
|
||||||
to what's in jcmain.c or jdmain.c, and you may want to replace jerror.c and
|
|
||||||
possibly other modules depending on your needs. See the "architecture" file
|
|
||||||
for more info. If it seems to you that the system structure doesn't
|
|
||||||
accommodate what you want to do, please contact the authors.
|
|
||||||
|
|
||||||
CAUTION: When you use the JPEG code as subroutines, we recommend that you make
|
|
||||||
any required configuration changes by modifying jconfig.h, not by adding -D
|
|
||||||
switches to the Makefile. Otherwise you must be sure to provide the same -D
|
|
||||||
switches when compiling any program that includes the JPEG .h files.
|
|
||||||
|
|
||||||
If you need to make a smaller version of the JPEG software, some optional
|
|
||||||
functions can be removed at compile time. See the xxx_SUPPORTED #defines in
|
|
||||||
jconfig.h. If at all possible, we recommend that you leave in decoder support
|
|
||||||
for all valid JPEG files, to ensure that you can read anyone's output.
|
|
||||||
Restricting your encoder, or removing optional functions like block smoothing,
|
|
||||||
won't hurt compatibility. Taking out support for image file formats that you
|
|
||||||
don't use is the most painless way to make the programs smaller.
|
|
||||||
|
|
||||||
|
|
||||||
NOTES FOR SPECIFIC SYSTEMS
|
|
||||||
==========================
|
|
||||||
|
|
||||||
We welcome reports on changes needed for systems not mentioned here.
|
|
||||||
Submit 'em to jpeg-info@uunet.uu.net. Also, config.c is fairly new and not
|
|
||||||
yet thoroughly tested; if it's wrong about how to configure the JPEG software
|
|
||||||
for your system, please let us know.
|
|
||||||
|
|
||||||
|
|
||||||
HP/Apollo DOMAIN:
|
|
||||||
|
|
||||||
At least in version 10.3.5, the C compiler is ANSI but the system include
|
|
||||||
files are not. Use makefile.ansi and add -DNONANSI_INCLUDES to CFLAGS.
|
|
||||||
|
|
||||||
HP-UX:
|
|
||||||
|
|
||||||
If you have HP-UX 7.05 or later with the "software development" C compiler,
|
|
||||||
then you can use makefile.ansi. Add "-Aa" to the CFLAGS line in the
|
|
||||||
makefile. If you have a pre-7.05 system, or if you are using the non-ANSI C
|
|
||||||
compiler delivered with a minimum HP-UX 8.0 system, then you must use
|
|
||||||
makefile.unix (and do NOT add -Aa). Also, adding "-lmalloc" to LDLIBS is
|
|
||||||
recommended if you have libmalloc.a (it seems not to be present in minimum
|
|
||||||
8.0).
|
|
||||||
|
|
||||||
On HP series 800 machines, the HP C compiler is buggy in revisions prior to
|
|
||||||
A.08.07. If you get complaints about "not a typedef name", you'll have to
|
|
||||||
convert the code to K&R style (i.e., use makefile.unix).
|
|
||||||
|
|
||||||
IBM RS/6000 AIX:
|
|
||||||
|
|
||||||
The CFLAGS switch to make the compiler define __STDC__ is "-qlanglvl=ansi".
|
|
||||||
|
|
||||||
Macintosh Think C:
|
|
||||||
|
|
||||||
You'll have to prepare project files for cjpeg and djpeg; we don't include
|
|
||||||
those in the distribution since they are not text files. The COBJECTS and
|
|
||||||
DOBJECTS lists in makefile.unix show which files should be included in each
|
|
||||||
project. Also add the ANSI and Unix C libraries in a separate segment. You
|
|
||||||
may need to divide the JPEG files into more than one segment; you can do this
|
|
||||||
pretty much as you please.
|
|
||||||
|
|
||||||
If you have Think C version 5.0 you should be able to just turn on __STDC__
|
|
||||||
through the compiler switch that enables that. With version 4.0 you must
|
|
||||||
manually edit jconfig.h. (You can #define __STDC__, but also #define const.)
|
|
||||||
|
|
||||||
Microsoft C for MS-DOS:
|
|
||||||
|
|
||||||
Some versions of MS C fail with an "out of macro expansion space" error
|
|
||||||
because they can't cope with the macro TRACEMS8 (defined in jpegdata.h).
|
|
||||||
If this happens to you, the easiest solution is to change TRACEMS8 to
|
|
||||||
expand to nothing. You'll lose the ability to dump out JPEG coefficient
|
|
||||||
tables with djpeg -d -d, but at least you can compile.
|
|
||||||
|
|
||||||
Sun:
|
|
||||||
|
|
||||||
Don't forget to add -DBSD to CFLAGS. If you are using GCC on SunOS 4.0.1 or
|
|
||||||
earlier, you will need to add -DNONANSI_INCLUDES to CFLAGS (your compiler may
|
|
||||||
be ANSI, but your system include files aren't). I've gotten conflicting
|
|
||||||
reports on whether this is still necessary on SunOS 4.1 or later.
|
|
||||||
162
USAGE
162
USAGE
@@ -1,162 +0,0 @@
|
|||||||
USAGE instructions for the Independent JPEG Group's JPEG software
|
|
||||||
=================================================================
|
|
||||||
|
|
||||||
This distribution contains software to implement JPEG image compression and
|
|
||||||
decompression. JPEG (pronounced "jay-peg") is a standardized compression
|
|
||||||
method for full-color and gray-scale images. JPEG is intended for
|
|
||||||
"real-world" scenes; cartoons and other non-realistic images are not its
|
|
||||||
strong suit. JPEG is lossy, meaning that the output image is not necessarily
|
|
||||||
identical to the input image. Hence you should not use JPEG if you have to
|
|
||||||
have identical output bits. However, on typical images of real-world scenes,
|
|
||||||
very good compression levels can be obtained with no visible change, and
|
|
||||||
amazingly high compression levels can be obtained if you can tolerate a
|
|
||||||
low-quality image.
|
|
||||||
|
|
||||||
This file describes usage of the standard programs "cjpeg" and "djpeg" that
|
|
||||||
can be built directly from the distributed software. See the README file for
|
|
||||||
hints on incorporating the JPEG software into other programs.
|
|
||||||
|
|
||||||
If you are on a Unix machine you may prefer to read the Unix-style manual
|
|
||||||
pages in files cjpeg.1 and djpeg.1.
|
|
||||||
|
|
||||||
NOTE: at some point we will probably redesign the user interface, so the
|
|
||||||
command line switches described here will change.
|
|
||||||
|
|
||||||
|
|
||||||
We provide two programs, cjpeg to compress an image file into JPEG format,
|
|
||||||
and djpeg to decompress a JPEG file back into a conventional image format.
|
|
||||||
|
|
||||||
On Unix-like systems, you say:
|
|
||||||
cjpeg [switches] [imagefile] >jpegfile
|
|
||||||
or
|
|
||||||
djpeg [switches] [jpegfile] >imagefile
|
|
||||||
The programs read the specified input file, or standard input if none is
|
|
||||||
named. They always write to standard output (with trace/error messages to
|
|
||||||
standard error). These conventions are handy for piping images between
|
|
||||||
programs.
|
|
||||||
|
|
||||||
On PC, Macintosh, and Amiga systems, you say:
|
|
||||||
cjpeg [switches] imagefile jpegfile
|
|
||||||
or
|
|
||||||
djpeg [switches] jpegfile imagefile
|
|
||||||
i.e., both input and output files are named on the command line. This style
|
|
||||||
is a little more foolproof, and it loses no functionality if you don't have
|
|
||||||
pipes. (You can get this style on Unix too, if you prefer, by defining
|
|
||||||
TWO_FILE_COMMANDLINE; see SETUP.)
|
|
||||||
|
|
||||||
The currently supported image file formats are: PPM (PBMPLUS color format),
|
|
||||||
PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit
|
|
||||||
format). (RLE is supported only if the URT library is available.)
|
|
||||||
cjpeg recognizes the input image format automatically, with the exception
|
|
||||||
of some Targa-format files.
|
|
||||||
|
|
||||||
The only JPEG file format currently supported is the JFIF format. Support for
|
|
||||||
the TIFF/JPEG format will probably be added at some future date.
|
|
||||||
|
|
||||||
|
|
||||||
The command line switches for cjpeg are:
|
|
||||||
|
|
||||||
-Q quality Scale quantization tables to adjust image quality.
|
|
||||||
Quality is 0 (worst) to 100 (best); default is 75.
|
|
||||||
(See below for more info.)
|
|
||||||
|
|
||||||
-o Perform optimization of entropy encoding parameters.
|
|
||||||
Without this, default encoding parameters are used.
|
|
||||||
-o usually makes the JPEG file a little smaller, but
|
|
||||||
cjpeg runs much slower. Image quality and speed of
|
|
||||||
decompression are unaffected by -o.
|
|
||||||
|
|
||||||
-T Input file is Targa format. Targa files that contain
|
|
||||||
an "identification" field will not be automatically
|
|
||||||
recognized by cjpeg; for such files you must specify
|
|
||||||
-T to force cjpeg to treat the input as Targa format.
|
|
||||||
|
|
||||||
-I Generate noninterleaved JPEG file (not yet supported).
|
|
||||||
|
|
||||||
-a Use arithmetic coding rather than Huffman coding.
|
|
||||||
(Not currently supported for legal reasons.)
|
|
||||||
|
|
||||||
-d Enable debug printout. More -d's give more printout.
|
|
||||||
Also, version information is printed at startup.
|
|
||||||
|
|
||||||
The -Q switch lets you trade off compressed file size against quality of the
|
|
||||||
reconstructed image: the higher the -Q setting, the larger the JPEG file, and
|
|
||||||
the closer the output image will be to the original input. Normally you want
|
|
||||||
to use the lowest -Q setting (smallest file) that decompresses into something
|
|
||||||
visually indistinguishable from the original image. For this purpose the -Q
|
|
||||||
setting should be between 50 and 95; the default of 75 is often about right.
|
|
||||||
If you see defects at -Q 75, then go up 5 or 10 counts at a time until you are
|
|
||||||
happy with the output image. (The optimal setting will vary from one image to
|
|
||||||
another.)
|
|
||||||
|
|
||||||
-Q 100 will generate a quantization table of all 1's, eliminating loss in the
|
|
||||||
quantization step (but there is still information loss in subsampling, as well
|
|
||||||
as roundoff error). This setting is mainly of interest for experimental
|
|
||||||
purposes. -Q values above about 95 are NOT recommended for normal use; the
|
|
||||||
compressed file size goes up dramatically for hardly any gain in output image
|
|
||||||
quality.
|
|
||||||
|
|
||||||
In the other direction, -Q values below 50 will produce very small files of
|
|
||||||
low image quality. Settings around 5 to 10 might be useful in preparing an
|
|
||||||
index of a large image library, for example. Try -Q 2 (or so) for some
|
|
||||||
amusing Cubist effects. (Note: -Q values below about 25 generate 2-byte
|
|
||||||
quantization tables, which are considered optional in the JPEG standard.
|
|
||||||
cjpeg emits a warning message when you give such a -Q value, because some
|
|
||||||
commercial JPEG programs may be unable to decode the resulting file.)
|
|
||||||
|
|
||||||
|
|
||||||
The command line switches for djpeg are:
|
|
||||||
|
|
||||||
-G Select GIF output format (implies -q, with default
|
|
||||||
of 256 colors).
|
|
||||||
|
|
||||||
-P Select PPM or PGM output format (this is the default).
|
|
||||||
PGM is emitted if the JPEG file is gray-scale or if -g
|
|
||||||
is specified.
|
|
||||||
|
|
||||||
-R Select RLE output format. Requires URT library.
|
|
||||||
|
|
||||||
-T Select Targa output format. Gray-scale format is
|
|
||||||
emitted if the JPEG file is gray-scale or if -g is
|
|
||||||
specified; otherwise, colormapped format is emitted
|
|
||||||
if -q is specified; otherwise, 24-bit full-color
|
|
||||||
format is emitted.
|
|
||||||
|
|
||||||
-b Perform cross-block smoothing. This is quite
|
|
||||||
memory-intensive and only seems to improve the image
|
|
||||||
at very low quality settings (-Q 10 to 20 or so).
|
|
||||||
At normal -Q settings it may make the image worse.
|
|
||||||
|
|
||||||
-g Force gray-scale output even if input is color.
|
|
||||||
|
|
||||||
-q N Quantize to N colors.
|
|
||||||
|
|
||||||
-D Do NOT use dithering in color quantization.
|
|
||||||
By default, Floyd-Steinberg dithering is applied when
|
|
||||||
quantizing colors, but on some images dithering may
|
|
||||||
result in objectionable "graininess". If that
|
|
||||||
happens, you can turn off dithering with -D.
|
|
||||||
|
|
||||||
-2 Use two-pass color quantization (not yet supported).
|
|
||||||
|
|
||||||
-d Enable debug printout. More -d's give more printout.
|
|
||||||
Also, version information is printed at startup.
|
|
||||||
|
|
||||||
Color quantization currently uses a rather shoddy algorithm (although it's not
|
|
||||||
as horrible when dithered). Because of this, the GIF output mode is NOT
|
|
||||||
RECOMMENDED in the current release, except for gray-scale output. You can get
|
|
||||||
better results by applying ppmquant to the unquantized (PPM) output of djpeg,
|
|
||||||
then converting to GIF with ppmtogif. (See SUPPORTING SOFTWARE in the README
|
|
||||||
file.) We expect to provide a considerably better quantization algorithm in a
|
|
||||||
future release. (The same applies to colormapped RLE or Targa output, of
|
|
||||||
course.)
|
|
||||||
|
|
||||||
Note that djpeg *can* read noninterleaved JPEG files even though cjpeg can't
|
|
||||||
yet generate them. For most applications this is a nonissue, since hardly
|
|
||||||
anybody seems to be using noninterleaved format.
|
|
||||||
|
|
||||||
On a non-virtual-memory machine, you may run out of memory if you use -I or -o
|
|
||||||
in cjpeg, or -q ... -2 in djpeg, or try to read an interlaced GIF file, or try
|
|
||||||
to read or write an RLE file, or try to read an interlaced or bottom-up Targa
|
|
||||||
file. This will be addressed soon by replacing jvirtmem.c with something that
|
|
||||||
uses temporary files for large images.
|
|
||||||
3655
aclocal.m4
vendored
Normal file
3655
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
71
altui/README.alt
Normal file
71
altui/README.alt
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
Here is an alternate command-line user interface for the IJG JPEG software.
|
||||||
|
It is designed for use under MS-DOS, and may also be useful on other non-Unix
|
||||||
|
operating systems. (For that matter, this code works fine on Unix, but the
|
||||||
|
standard command-line syntax is better on Unix because it is pipe-friendly.)
|
||||||
|
|
||||||
|
With this user interface, cjpeg and djpeg accept multiple input file names
|
||||||
|
on the command line; output file names are generated by substituting
|
||||||
|
appropriate extensions. The user is prompted before any already-existing
|
||||||
|
file will be overwritten. See usage.alt for details.
|
||||||
|
|
||||||
|
Expansion of wild-card file specifications is useful but is not directly
|
||||||
|
provided by this code. Most DOS C compilers have the ability to do wild-card
|
||||||
|
expansion "behind the scenes", and we rely on that feature. On other systems,
|
||||||
|
the shell may do it for you, as is done on Unix.
|
||||||
|
|
||||||
|
Also, a DOS-specific routine is provided to determine available memory;
|
||||||
|
this makes the -maxmemory switch unnecessary except in unusual cases.
|
||||||
|
If you know how to determine available memory on a different system,
|
||||||
|
you can easily add the necessary code. (And please send it along to
|
||||||
|
jpeg-info@uunet.uu.net so we can include it in future releases!)
|
||||||
|
|
||||||
|
|
||||||
|
INSTALLATION
|
||||||
|
============
|
||||||
|
|
||||||
|
You need to have the main IJG JPEG distribution, release 6 or later.
|
||||||
|
Replace the standard cjpeg.c and djpeg.c files with the ones provided here.
|
||||||
|
Then build the software as described in the main distribution's install.doc
|
||||||
|
file, with these exceptions:
|
||||||
|
|
||||||
|
* Define PROGRESS_REPORT in jconfig.h if you want the percent-done display.
|
||||||
|
* Define NO_OVERWRITE_CHECK if you *don't* want overwrite confirmation.
|
||||||
|
* You may ignore the USE_SETMODE and TWO_FILE_COMMANDLINE symbols discussed
|
||||||
|
in install.doc; these files do not use them.
|
||||||
|
* As given, djpeg.c defaults to GIF output (not PPM output as in the standard
|
||||||
|
djpeg.c). If you want something different, modify DEFAULT_FMT.
|
||||||
|
|
||||||
|
You may also need to do something special to enable filename wild-card
|
||||||
|
expansion, assuming your compiler has that capability at all.
|
||||||
|
|
||||||
|
Modify the standard usage.doc file as described in usage.alt. (If you want
|
||||||
|
to use the Unix-style manual pages cjpeg.1 and djpeg.1, better fix them too.)
|
||||||
|
|
||||||
|
|
||||||
|
Here are some specific notes for popular MS-DOS compilers:
|
||||||
|
|
||||||
|
Borland C:
|
||||||
|
Add "-DMSDOS" to CFLAGS to enable use of the DOS memory determination code.
|
||||||
|
Link with the standard library file WILDARGS.OBJ to get wild-card expansion.
|
||||||
|
|
||||||
|
Microsoft C:
|
||||||
|
Add "-DMSDOS" to CFLAGS to enable use of the DOS memory determination code.
|
||||||
|
Link with the standard library file SETARGV.OBJ to get wild-card expansion.
|
||||||
|
In the versions I've used, you must also add /NOE to the linker switches to
|
||||||
|
avoid a duplicate-symbol error from including SETARGV.
|
||||||
|
|
||||||
|
DJGPP (we recommend version 2.0 or later):
|
||||||
|
Add "-DFREE_MEM_ESTIMATE=0" to CFLAGS. Wild-card expansion is automatic.
|
||||||
|
|
||||||
|
|
||||||
|
LEGAL ISSUES
|
||||||
|
============
|
||||||
|
|
||||||
|
This software is copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
Terms of distribution and use are the same as for the free IJG JPEG software;
|
||||||
|
see its README file for details.
|
||||||
|
|
||||||
|
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.
|
||||||
813
altui/cjpeg.c
Normal file
813
altui/cjpeg.c
Normal file
@@ -0,0 +1,813 @@
|
|||||||
|
/*
|
||||||
|
* alternate cjpeg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 6, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains an alternate user interface for the JPEG compressor.
|
||||||
|
* One or more input files are named on the command line, and output file
|
||||||
|
* names are created by substituting ".jpg" for the input file's extension.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||||
|
#include "jversion.h" /* for version message */
|
||||||
|
|
||||||
|
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||||
|
#ifdef __MWERKS__
|
||||||
|
#include <SIOUX.h> /* Metrowerks needs this */
|
||||||
|
#include <console.h> /* ... and this */
|
||||||
|
#endif
|
||||||
|
#ifdef THINK_C
|
||||||
|
#include <console.h> /* Think declares it here */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX /* ANSI maximum-pathname-length constant */
|
||||||
|
#define PATH_MAX 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the add-on message string table. */
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) string ,
|
||||||
|
|
||||||
|
static const char * const cdjpeg_message_table[] = {
|
||||||
|
#include "cderror.h"
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: compiler-specific hacks to enable filename wild-card expansion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER /* Microsoft Visual C++ */
|
||||||
|
/* from setargv.c (setargv.obj) */
|
||||||
|
/* Tested under Visual C++ V6.0, Toolkit 2003, and 2005 Express Edition */
|
||||||
|
int __cdecl _setargv(void) { int __cdecl __setargv(void); return __setargv(); }
|
||||||
|
#endif
|
||||||
|
#ifdef __BORLANDC__ /* Borland C++ */
|
||||||
|
/* from wildargs.c (wildargs.obj) */
|
||||||
|
/* Tested under Borland C++ Compiler 5.5 (win32) */
|
||||||
|
#include <wildargs.h>
|
||||||
|
typedef void _RTLENTRY (* _RTLENTRY _argv_expand_fnc)(char *, _PFN_ADDARG);
|
||||||
|
_argv_expand_fnc _argv_expand_ptr = _expand_wild;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatic determination of available memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long default_maxmem; /* saves value determined at startup, or 0 */
|
||||||
|
|
||||||
|
#ifndef FREE_MEM_ESTIMATE /* may be defined from command line */
|
||||||
|
|
||||||
|
#ifdef MSDOS /* For MS-DOS (unless flat-memory model) */
|
||||||
|
|
||||||
|
#include <dos.h> /* for access to intdos() call */
|
||||||
|
|
||||||
|
LOCAL(long)
|
||||||
|
unused_dos_memory (void)
|
||||||
|
/* Obtain total amount of unallocated DOS memory */
|
||||||
|
{
|
||||||
|
union REGS regs;
|
||||||
|
long nparas;
|
||||||
|
|
||||||
|
regs.h.ah = 0x48; /* DOS function Allocate Memory Block */
|
||||||
|
regs.x.bx = 0xFFFF; /* Ask for more memory than DOS can have */
|
||||||
|
(void) intdos(®s, ®s);
|
||||||
|
/* DOS will fail and return # of paragraphs actually available in BX. */
|
||||||
|
nparas = (unsigned int) regs.x.bx;
|
||||||
|
/* Times 16 to convert to bytes. */
|
||||||
|
return nparas << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The default memory setting is 95% of the available space. */
|
||||||
|
#define FREE_MEM_ESTIMATE ((unused_dos_memory() * 95L) / 100L)
|
||||||
|
|
||||||
|
#endif /* MSDOS */
|
||||||
|
|
||||||
|
#ifdef ATARI /* For Atari ST/STE/TT, Pure C or Turbo C */
|
||||||
|
|
||||||
|
#include <ext.h>
|
||||||
|
|
||||||
|
/* The default memory setting is 90% of the available space. */
|
||||||
|
#define FREE_MEM_ESTIMATE (((long) coreleft() * 90L) / 100L)
|
||||||
|
|
||||||
|
#endif /* ATARI */
|
||||||
|
|
||||||
|
/* Add memory-estimation procedures for other operating systems here,
|
||||||
|
* with appropriate #ifdef's around them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !FREE_MEM_ESTIMATE */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine determines what format the input file is,
|
||||||
|
* and selects the appropriate input-reading module.
|
||||||
|
*
|
||||||
|
* To determine which family of input formats the file belongs to,
|
||||||
|
* we may look only at the first byte of the file, since C does not
|
||||||
|
* guarantee that more than one character can be pushed back with ungetc.
|
||||||
|
* Looking at additional bytes would require one of these approaches:
|
||||||
|
* 1) assume we can fseek() the input file (fails for piped input);
|
||||||
|
* 2) assume we can push back more than one character (works in
|
||||||
|
* some C implementations, but unportable);
|
||||||
|
* 3) provide our own buffering (breaks input readers that want to use
|
||||||
|
* stdio directly, such as the RLE library);
|
||||||
|
* or 4) don't put back the data, and modify the input_init methods to assume
|
||||||
|
* they start reading after the start of file (also breaks RLE library).
|
||||||
|
* #1 is attractive for MS-DOS but is untenable on Unix.
|
||||||
|
*
|
||||||
|
* The most portable solution for file types that can't be identified by their
|
||||||
|
* first byte is to make the user tell us what they are. This is also the
|
||||||
|
* only approach for "raw" file types that contain only arbitrary values.
|
||||||
|
* We presently apply this method for Targa files. Most of the time Targa
|
||||||
|
* files start with 0x00, so we recognize that case. Potentially, however,
|
||||||
|
* a Targa file could start with any byte value (byte 0 is the length of the
|
||||||
|
* seldom-used ID field), so we provide a switch to force Targa input mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static boolean is_targa; /* records user -targa switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(cjpeg_source_ptr)
|
||||||
|
select_file_type (j_compress_ptr cinfo, FILE * infile)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (is_targa) {
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
return jinit_read_targa(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_TGA_NOTCOMP);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c = getc(infile)) == EOF)
|
||||||
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||||
|
if (ungetc(c, infile) == EOF)
|
||||||
|
ERREXIT(cinfo, JERR_UNGETC_FAILED);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
case 'B':
|
||||||
|
return jinit_read_bmp(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
case 'G':
|
||||||
|
return jinit_read_gif(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
case 'P':
|
||||||
|
return jinit_read_ppm(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
case 'R':
|
||||||
|
return jinit_read_rle(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
case 0x00:
|
||||||
|
return jinit_read_targa(cinfo);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; /* suppress compiler warnings */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argument-parsing code.
|
||||||
|
* The switch parser is designed to be useful with DOS-style command line
|
||||||
|
* syntax, ie, intermixed switches and file names, where only the switches
|
||||||
|
* to the left of a given file name affect processing of that file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static const char * progname; /* program name for error messages */
|
||||||
|
static char * outfilename; /* for -outfile switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
usage (void)
|
||||||
|
/* complain about bad command line */
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
|
||||||
|
fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
|
||||||
|
fprintf(stderr, "Output filename is same as input filename, but extension .jpg\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||||
|
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
|
||||||
|
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
|
||||||
|
#endif
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
fprintf(stderr, " -progressive Create progressive JPEG file\n");
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Switches for advanced users:\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
|
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
|
||||||
|
#endif
|
||||||
|
#ifndef FREE_MEM_ESTIMATE
|
||||||
|
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||||
|
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||||
|
fprintf(stderr, "Switches for wizards:\n");
|
||||||
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
|
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -baseline Force baseline quantization tables\n");
|
||||||
|
fprintf(stderr, " -qtables file Use quantization tables given in file\n");
|
||||||
|
fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
|
||||||
|
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
|
||||||
|
#endif
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
print_simd_info (FILE * file, char * labelstr, unsigned int simd)
|
||||||
|
{
|
||||||
|
fprintf(file, "%s%s%s%s%s%s\n", labelstr,
|
||||||
|
simd & JSIMD_MMX ? " MMX" : "",
|
||||||
|
simd & JSIMD_3DNOW ? " 3DNow!" : "",
|
||||||
|
simd & JSIMD_SSE ? " SSE" : "",
|
||||||
|
simd & JSIMD_SSE2 ? " SSE2" : "",
|
||||||
|
simd == JSIMD_NONE ? " NONE" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||||
|
int last_file_arg_seen, boolean for_real)
|
||||||
|
/* Parse optional switches.
|
||||||
|
* Returns argv[] index of first file-name argument (== argc if none).
|
||||||
|
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||||
|
* they have presumably been processed in a previous iteration.
|
||||||
|
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||||
|
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int argn;
|
||||||
|
char * arg;
|
||||||
|
int quality; /* -quality parameter */
|
||||||
|
int q_scale_factor; /* scaling percentage for -qtables */
|
||||||
|
boolean force_baseline;
|
||||||
|
boolean simple_progressive;
|
||||||
|
char * qtablefile = NULL; /* saves -qtables filename if any */
|
||||||
|
char * qslotsarg = NULL; /* saves -qslots parm if any */
|
||||||
|
char * samplearg = NULL; /* saves -sample parm if any */
|
||||||
|
char * scansarg = NULL; /* saves -scans parm if any */
|
||||||
|
|
||||||
|
/* Set up default JPEG parameters. */
|
||||||
|
/* Note that default -quality level need not, and does not,
|
||||||
|
* match the default scaling for an explicit -qtables argument.
|
||||||
|
*/
|
||||||
|
quality = 75; /* default -quality value */
|
||||||
|
q_scale_factor = 100; /* default to no scaling for -qtables */
|
||||||
|
force_baseline = FALSE; /* by default, allow 16-bit quantizers */
|
||||||
|
simple_progressive = FALSE;
|
||||||
|
is_targa = FALSE;
|
||||||
|
outfilename = NULL;
|
||||||
|
cinfo->err->trace_level = 0;
|
||||||
|
if (default_maxmem > 0) /* override library's default value */
|
||||||
|
cinfo->mem->max_memory_to_use = default_maxmem;
|
||||||
|
|
||||||
|
/* Scan command line options, adjust parameters */
|
||||||
|
|
||||||
|
for (argn = 1; argn < argc; argn++) {
|
||||||
|
arg = argv[argn];
|
||||||
|
if (*arg != '-') {
|
||||||
|
/* Not a switch, must be a file name argument */
|
||||||
|
if (argn <= last_file_arg_seen) {
|
||||||
|
outfilename = NULL; /* -outfile applies to just one input file */
|
||||||
|
continue; /* ignore this name if previously processed */
|
||||||
|
}
|
||||||
|
break; /* else done parsing switches */
|
||||||
|
}
|
||||||
|
arg++; /* advance past switch marker character */
|
||||||
|
|
||||||
|
if (keymatch(arg, "arithmetic", 1)) {
|
||||||
|
/* Use arithmetic coding. */
|
||||||
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
|
cinfo->arith_code = TRUE;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "baseline", 1)) {
|
||||||
|
/* Force baseline-compatible output (8-bit quantizer values). */
|
||||||
|
force_baseline = TRUE;
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
} else if (keymatch(arg, "nosimd" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_ALL);
|
||||||
|
} else if (keymatch(arg, "nommx" , 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_MMX);
|
||||||
|
} else if (keymatch(arg, "no3dnow", 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_3DNOW);
|
||||||
|
} else if (keymatch(arg, "nosse" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE);
|
||||||
|
} else if (keymatch(arg, "nosse2" , 6)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE2);
|
||||||
|
#endif /* !JSIMD_MASKFUNC_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) {
|
||||||
|
/* Select DCT algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "int", 1)) {
|
||||||
|
cinfo->dct_method = JDCT_ISLOW;
|
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_IFAST;
|
||||||
|
} else if (keymatch(argv[argn], "float", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_FLOAT;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||||
|
/* Enable debug printouts. */
|
||||||
|
/* On first -d, print version identification */
|
||||||
|
static boolean printed_version = FALSE;
|
||||||
|
|
||||||
|
if (! printed_version) {
|
||||||
|
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
|
||||||
|
JVERSION, JCOPYRIGHT);
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nx86 SIMD extension for IJG JPEG library, version %s\n\n",
|
||||||
|
JPEG_SIMDEXT_VER_STR);
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "SIMD instructions supported by the system :",
|
||||||
|
jpeg_simd_support(NULL));
|
||||||
|
|
||||||
|
fprintf(stderr, "\n === SIMD Operation Modes ===\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Accurate integer DCT (-dct int) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_ISLOW));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Fast integer DCT (-dct fast) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_IFAST));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Floating-point DCT (-dct float) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_FLOAT));
|
||||||
|
#endif
|
||||||
|
print_simd_info(stderr, "Downsampling (-sample 2x2 or 2x1) :",
|
||||||
|
jpeg_simd_downsampler(cinfo));
|
||||||
|
print_simd_info(stderr, "Colorspace conversion (RGB->YCbCr) :",
|
||||||
|
jpeg_simd_color_converter(cinfo));
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
printed_version = TRUE;
|
||||||
|
}
|
||||||
|
cinfo->err->trace_level++;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
|
||||||
|
/* Force a monochrome JPEG file to be generated. */
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (ch == 'm' || ch == 'M')
|
||||||
|
lval *= 1000L;
|
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
|
||||||
|
/* Enable entropy parm optimization. */
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
cinfo->optimize_coding = TRUE;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "outfile", 4)) {
|
||||||
|
/* Set output file name. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
outfilename = argv[argn]; /* save it away for later use */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "progressive", 1)) {
|
||||||
|
/* Select simple progressive mode. */
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
simple_progressive = TRUE;
|
||||||
|
/* We must postpone execution until num_components is known. */
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "quality", 1)) {
|
||||||
|
/* Quality factor (quantization table scaling factor). */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &quality) != 1)
|
||||||
|
usage();
|
||||||
|
/* Change scale factor in case -qtables is present. */
|
||||||
|
q_scale_factor = jpeg_quality_scaling(quality);
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "qslots", 2)) {
|
||||||
|
/* Quantization table slot numbers. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
qslotsarg = argv[argn];
|
||||||
|
/* Must delay setting qslots until after we have processed any
|
||||||
|
* colorspace-determining switches, since jpeg_set_colorspace sets
|
||||||
|
* default quant table numbers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "qtables", 2)) {
|
||||||
|
/* Quantization tables fetched from file. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
qtablefile = argv[argn];
|
||||||
|
/* We postpone actually reading the file in case -quality comes later. */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "restart", 1)) {
|
||||||
|
/* Restart interval in MCU rows (or in MCUs with 'b'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (lval < 0 || lval > 65535L)
|
||||||
|
usage();
|
||||||
|
if (ch == 'b' || ch == 'B') {
|
||||||
|
cinfo->restart_interval = (unsigned int) lval;
|
||||||
|
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
|
||||||
|
} else {
|
||||||
|
cinfo->restart_in_rows = (int) lval;
|
||||||
|
/* restart_interval will be computed during startup */
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "sample", 2)) {
|
||||||
|
/* Set sampling factors. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
samplearg = argv[argn];
|
||||||
|
/* Must delay setting sample factors until after we have processed any
|
||||||
|
* colorspace-determining switches, since jpeg_set_colorspace sets
|
||||||
|
* default sampling factors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "scans", 2)) {
|
||||||
|
/* Set scan script. */
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
scansarg = argv[argn];
|
||||||
|
/* We must postpone reading the file in case -progressive appears. */
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "smooth", 2)) {
|
||||||
|
/* Set input smoothing factor. */
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1)
|
||||||
|
usage();
|
||||||
|
if (val < 0 || val > 100)
|
||||||
|
usage();
|
||||||
|
cinfo->smoothing_factor = val;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "targa", 1)) {
|
||||||
|
/* Input file is Targa format. */
|
||||||
|
is_targa = TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
usage(); /* bogus switch */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Post-switch-scanning cleanup */
|
||||||
|
|
||||||
|
if (for_real) {
|
||||||
|
|
||||||
|
/* Set quantization tables for selected quality. */
|
||||||
|
/* Some or all may be overridden if -qtables is present. */
|
||||||
|
jpeg_set_quality(cinfo, quality, force_baseline);
|
||||||
|
|
||||||
|
if (qtablefile != NULL) /* process -qtables if it was present */
|
||||||
|
if (! read_quant_tables(cinfo, qtablefile,
|
||||||
|
q_scale_factor, force_baseline))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (qslotsarg != NULL) /* process -qslots if it was present */
|
||||||
|
if (! set_quant_slots(cinfo, qslotsarg))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (samplearg != NULL) /* process -sample if it was present */
|
||||||
|
if (! set_sample_factors(cinfo, samplearg))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
if (simple_progressive) /* process -progressive; -scans can override */
|
||||||
|
jpeg_simple_progression(cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
if (scansarg != NULL) /* process -scans if it was present */
|
||||||
|
if (! read_scan_script(cinfo, scansarg))
|
||||||
|
usage();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return argn; /* return index of next arg (file name) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for overwrite of an existing file; clear it with user
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_OVERWRITE_CHECK
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
is_write_ok (char * outfname)
|
||||||
|
{
|
||||||
|
FILE * ofile;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
ofile = fopen(outfname, READ_BINARY);
|
||||||
|
if (ofile == NULL)
|
||||||
|
return TRUE; /* not present */
|
||||||
|
fclose(ofile); /* oops, it is present */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
|
||||||
|
outfname);
|
||||||
|
fflush(stderr);
|
||||||
|
ch = getc(stdin);
|
||||||
|
if (ch != '\n') /* flush rest of line */
|
||||||
|
while (getc(stdin) != '\n')
|
||||||
|
/* nothing */;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 'Y':
|
||||||
|
case 'y':
|
||||||
|
return TRUE;
|
||||||
|
case 'N':
|
||||||
|
case 'n':
|
||||||
|
return FALSE;
|
||||||
|
/* otherwise, ask again */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process a single input file name, and return its index in argv[].
|
||||||
|
* File names at or to left of old_file_index have been processed already.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
process_one_file (int argc, char **argv, int old_file_index)
|
||||||
|
{
|
||||||
|
struct jpeg_compress_struct cinfo;
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
char *infilename;
|
||||||
|
char workfilename[PATH_MAX];
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
struct cdjpeg_progress_mgr progress;
|
||||||
|
#endif
|
||||||
|
int file_index;
|
||||||
|
cjpeg_source_ptr src_mgr;
|
||||||
|
FILE * input_file = NULL;
|
||||||
|
FILE * output_file = NULL;
|
||||||
|
JDIMENSION num_scanlines;
|
||||||
|
|
||||||
|
/* Initialize the JPEG compression object with default error handling. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
jpeg_create_compress(&cinfo);
|
||||||
|
/* Add some application-specific error messages (from cderror.h) */
|
||||||
|
jerr.addon_message_table = cdjpeg_message_table;
|
||||||
|
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
||||||
|
jerr.last_addon_message = JMSG_LASTADDONCODE;
|
||||||
|
|
||||||
|
/* Now safe to enable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialize JPEG parameters.
|
||||||
|
* Much of this may be overridden later.
|
||||||
|
* In particular, we don't yet know the input file's color space,
|
||||||
|
* but we need to provide some value for jpeg_set_defaults() to work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
|
||||||
|
jpeg_set_defaults(&cinfo);
|
||||||
|
|
||||||
|
/* Scan command line to find next file name.
|
||||||
|
* It is convenient to use just one switch-parsing routine, but the switch
|
||||||
|
* values read here are ignored; we will rescan the switches after opening
|
||||||
|
* the input file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
|
||||||
|
if (file_index >= argc) {
|
||||||
|
fprintf(stderr, "%s: missing input file name\n", progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the input file. */
|
||||||
|
infilename = argv[file_index];
|
||||||
|
if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, infilename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
start_progress_monitor((j_common_ptr) &cinfo, &progress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Figure out the input file format, and set up to read it. */
|
||||||
|
src_mgr = select_file_type(&cinfo, input_file);
|
||||||
|
src_mgr->input_file = input_file;
|
||||||
|
|
||||||
|
/* Read the input file header to obtain file size & colorspace. */
|
||||||
|
(*src_mgr->start_input) (&cinfo, src_mgr);
|
||||||
|
|
||||||
|
/* Now that we know input colorspace, fix colorspace-dependent defaults */
|
||||||
|
jpeg_default_colorspace(&cinfo);
|
||||||
|
|
||||||
|
/* Adjust default compression parameters by re-parsing the options */
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
|
||||||
|
|
||||||
|
/* If user didn't supply -outfile switch, select output file name. */
|
||||||
|
if (outfilename == NULL) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
outfilename = workfilename;
|
||||||
|
/* Make outfilename be infilename with .jpg substituted for extension */
|
||||||
|
strcpy(outfilename, infilename);
|
||||||
|
for (i = strlen(outfilename)-1; i >= 0; i--) {
|
||||||
|
switch (outfilename[i]) {
|
||||||
|
case ':':
|
||||||
|
case '/':
|
||||||
|
case '\\':
|
||||||
|
i = 0; /* stop scanning */
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
outfilename[i] = '\0'; /* lop off existing extension */
|
||||||
|
i = 0; /* stop scanning */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; /* keep scanning */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcat(outfilename, ".jpg");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Compressing %s => %s\n", infilename, outfilename);
|
||||||
|
#ifndef NO_OVERWRITE_CHECK
|
||||||
|
if (! is_write_ok(outfilename))
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Open the output file. */
|
||||||
|
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specify data destination for compression */
|
||||||
|
jpeg_stdio_dest(&cinfo, output_file);
|
||||||
|
|
||||||
|
/* Start compressor */
|
||||||
|
jpeg_start_compress(&cinfo, TRUE);
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
while (cinfo.next_scanline < cinfo.image_height) {
|
||||||
|
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
|
||||||
|
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish compression and release memory */
|
||||||
|
(*src_mgr->finish_input) (&cinfo, src_mgr);
|
||||||
|
jpeg_finish_compress(&cinfo);
|
||||||
|
|
||||||
|
/* Clean up and exit */
|
||||||
|
fail:
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
if (input_file != NULL) fclose(input_file);
|
||||||
|
if (output_file != NULL) fclose(output_file);
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
end_progress_monitor((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Disable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return file_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int file_index;
|
||||||
|
|
||||||
|
/* On Mac, fetch a command line. */
|
||||||
|
#ifdef USE_CCOMMAND
|
||||||
|
argc = ccommand(&argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MSDOS
|
||||||
|
progname = "cjpeg"; /* DOS tends to be too verbose about argv[0] */
|
||||||
|
#else
|
||||||
|
progname = argv[0];
|
||||||
|
if (progname == NULL || progname[0] == 0)
|
||||||
|
progname = "cjpeg"; /* in case C library doesn't provide it */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The default maxmem must be computed only once at program startup,
|
||||||
|
* since releasing memory with free() won't give it back to the OS.
|
||||||
|
*/
|
||||||
|
#ifdef FREE_MEM_ESTIMATE
|
||||||
|
default_maxmem = FREE_MEM_ESTIMATE;
|
||||||
|
#else
|
||||||
|
default_maxmem = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Scan command line, parse switches and locate input file names */
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(); /* nothing on the command line?? */
|
||||||
|
|
||||||
|
file_index = 0;
|
||||||
|
|
||||||
|
while (file_index < argc-1)
|
||||||
|
file_index = process_one_file(argc, argv, file_index);
|
||||||
|
|
||||||
|
/* All done. */
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
return 0; /* suppress no-return-value warnings */
|
||||||
|
}
|
||||||
836
altui/djpeg.c
Normal file
836
altui/djpeg.c
Normal file
@@ -0,0 +1,836 @@
|
|||||||
|
/*
|
||||||
|
* alternate djpeg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 6, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains an alternate user interface for the JPEG decompressor.
|
||||||
|
* One or more input files are named on the command line, and output file
|
||||||
|
* names are created by substituting an appropriate extension.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||||
|
#include "jversion.h" /* for version message */
|
||||||
|
|
||||||
|
#include <ctype.h> /* to declare isprint() */
|
||||||
|
|
||||||
|
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||||
|
#ifdef __MWERKS__
|
||||||
|
#include <SIOUX.h> /* Metrowerks needs this */
|
||||||
|
#include <console.h> /* ... and this */
|
||||||
|
#endif
|
||||||
|
#ifdef THINK_C
|
||||||
|
#include <console.h> /* Think declares it here */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX /* ANSI maximum-pathname-length constant */
|
||||||
|
#define PATH_MAX 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the add-on message string table. */
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) string ,
|
||||||
|
|
||||||
|
static const char * const cdjpeg_message_table[] = {
|
||||||
|
#include "cderror.h"
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: compiler-specific hacks to enable filename wild-card expansion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER /* Microsoft Visual C++ */
|
||||||
|
/* from setargv.c (setargv.obj) */
|
||||||
|
/* Tested under Visual C++ V6.0, Toolkit 2003, and 2005 Express Edition */
|
||||||
|
int __cdecl _setargv(void) { int __cdecl __setargv(void); return __setargv(); }
|
||||||
|
#endif
|
||||||
|
#ifdef __BORLANDC__ /* Borland C++ */
|
||||||
|
/* from wildargs.c (wildargs.obj) */
|
||||||
|
/* Tested under Borland C++ Compiler 5.5 (win32) */
|
||||||
|
#include <wildargs.h>
|
||||||
|
typedef void _RTLENTRY (* _RTLENTRY _argv_expand_fnc)(char *, _PFN_ADDARG);
|
||||||
|
_argv_expand_fnc _argv_expand_ptr = _expand_wild;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatic determination of available memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long default_maxmem; /* saves value determined at startup, or 0 */
|
||||||
|
|
||||||
|
#ifndef FREE_MEM_ESTIMATE /* may be defined from command line */
|
||||||
|
|
||||||
|
#ifdef MSDOS /* For MS-DOS (unless flat-memory model) */
|
||||||
|
|
||||||
|
#include <dos.h> /* for access to intdos() call */
|
||||||
|
|
||||||
|
LOCAL(long)
|
||||||
|
unused_dos_memory (void)
|
||||||
|
/* Obtain total amount of unallocated DOS memory */
|
||||||
|
{
|
||||||
|
union REGS regs;
|
||||||
|
long nparas;
|
||||||
|
|
||||||
|
regs.h.ah = 0x48; /* DOS function Allocate Memory Block */
|
||||||
|
regs.x.bx = 0xFFFF; /* Ask for more memory than DOS can have */
|
||||||
|
(void) intdos(®s, ®s);
|
||||||
|
/* DOS will fail and return # of paragraphs actually available in BX. */
|
||||||
|
nparas = (unsigned int) regs.x.bx;
|
||||||
|
/* Times 16 to convert to bytes. */
|
||||||
|
return nparas << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The default memory setting is 95% of the available space. */
|
||||||
|
#define FREE_MEM_ESTIMATE ((unused_dos_memory() * 95L) / 100L)
|
||||||
|
|
||||||
|
#endif /* MSDOS */
|
||||||
|
|
||||||
|
#ifdef ATARI /* For Atari ST/STE/TT, Pure C or Turbo C */
|
||||||
|
|
||||||
|
#include <ext.h>
|
||||||
|
|
||||||
|
/* The default memory setting is 90% of the available space. */
|
||||||
|
#define FREE_MEM_ESTIMATE (((long) coreleft() * 90L) / 100L)
|
||||||
|
|
||||||
|
#endif /* ATARI */
|
||||||
|
|
||||||
|
/* Add memory-estimation procedures for other operating systems here,
|
||||||
|
* with appropriate #ifdef's around them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !FREE_MEM_ESTIMATE */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This list defines the known output image formats
|
||||||
|
* (not all of which need be supported by a given version).
|
||||||
|
* You can change the default output format by defining DEFAULT_FMT;
|
||||||
|
* indeed, you had better do so if you undefine PPM_SUPPORTED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FMT_BMP, /* BMP format (Windows flavor) */
|
||||||
|
FMT_GIF, /* GIF format */
|
||||||
|
FMT_OS2, /* BMP format (OS/2 flavor) */
|
||||||
|
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
|
||||||
|
FMT_RLE, /* RLE format */
|
||||||
|
FMT_TARGA, /* Targa format */
|
||||||
|
FMT_TIFF /* TIFF format */
|
||||||
|
} IMAGE_FORMATS;
|
||||||
|
|
||||||
|
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
|
||||||
|
#define DEFAULT_FMT FMT_GIF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static IMAGE_FORMATS requested_fmt;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argument-parsing code.
|
||||||
|
* The switch parser is designed to be useful with DOS-style command line
|
||||||
|
* syntax, ie, intermixed switches and file names, where only the switches
|
||||||
|
* to the left of a given file name affect processing of that file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static const char * progname; /* program name for error messages */
|
||||||
|
static char * outfilename; /* for -outfile switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
usage (void)
|
||||||
|
/* complain about bad command line */
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
|
||||||
|
fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
|
||||||
|
fprintf(stderr, "Output filename is same as input filename except for extension\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||||
|
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
|
||||||
|
fprintf(stderr, " -fast Fast, low-quality processing\n");
|
||||||
|
fprintf(stderr, " -grayscale Force grayscale output\n");
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
|
||||||
|
#endif
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
fprintf(stderr, " -gif Select GIF output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
fprintf(stderr, " -targa Select Targa output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Switches for advanced users:\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
|
||||||
|
fprintf(stderr, " -dither none Don't use dithering in quantization\n");
|
||||||
|
fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
fprintf(stderr, " -map FILE Map to colors used in named image file\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
|
||||||
|
#ifdef QUANT_1PASS_SUPPORTED
|
||||||
|
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
|
||||||
|
#endif
|
||||||
|
#ifndef FREE_MEM_ESTIMATE
|
||||||
|
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||||
|
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
print_simd_info (FILE * file, char * labelstr, unsigned int simd)
|
||||||
|
{
|
||||||
|
fprintf(file, "%s%s%s%s%s%s\n", labelstr,
|
||||||
|
simd & JSIMD_MMX ? " MMX" : "",
|
||||||
|
simd & JSIMD_3DNOW ? " 3DNow!" : "",
|
||||||
|
simd & JSIMD_SSE ? " SSE" : "",
|
||||||
|
simd & JSIMD_SSE2 ? " SSE2" : "",
|
||||||
|
simd == JSIMD_NONE ? " NONE" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
||||||
|
int last_file_arg_seen, boolean for_real)
|
||||||
|
/* Parse optional switches.
|
||||||
|
* Returns argv[] index of first file-name argument (== argc if none).
|
||||||
|
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||||
|
* they have presumably been processed in a previous iteration.
|
||||||
|
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||||
|
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int argn;
|
||||||
|
char * arg;
|
||||||
|
|
||||||
|
/* Set up default JPEG parameters. */
|
||||||
|
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
||||||
|
outfilename = NULL;
|
||||||
|
cinfo->err->trace_level = 0;
|
||||||
|
if (default_maxmem > 0) /* override library's default value */
|
||||||
|
cinfo->mem->max_memory_to_use = default_maxmem;
|
||||||
|
|
||||||
|
/* Scan command line options, adjust parameters */
|
||||||
|
|
||||||
|
for (argn = 1; argn < argc; argn++) {
|
||||||
|
arg = argv[argn];
|
||||||
|
if (*arg != '-') {
|
||||||
|
/* Not a switch, must be a file name argument */
|
||||||
|
if (argn <= last_file_arg_seen) {
|
||||||
|
outfilename = NULL; /* -outfile applies to just one input file */
|
||||||
|
continue; /* ignore this name if previously processed */
|
||||||
|
}
|
||||||
|
break; /* else done parsing switches */
|
||||||
|
}
|
||||||
|
arg++; /* advance past switch marker character */
|
||||||
|
|
||||||
|
if (keymatch(arg, "bmp", 1)) {
|
||||||
|
/* BMP output format. */
|
||||||
|
requested_fmt = FMT_BMP;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
|
||||||
|
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
|
||||||
|
/* Do color quantization. */
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1)
|
||||||
|
usage();
|
||||||
|
cinfo->desired_number_of_colors = val;
|
||||||
|
cinfo->quantize_colors = TRUE;
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
} else if (keymatch(arg, "nosimd" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_ALL);
|
||||||
|
} else if (keymatch(arg, "nommx" , 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_MMX);
|
||||||
|
} else if (keymatch(arg, "no3dnow", 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_3DNOW);
|
||||||
|
} else if (keymatch(arg, "nosse" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE);
|
||||||
|
} else if (keymatch(arg, "nosse2" , 6)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE2);
|
||||||
|
#endif /* !JSIMD_MASKFUNC_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) {
|
||||||
|
/* Select IDCT algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "int", 1)) {
|
||||||
|
cinfo->dct_method = JDCT_ISLOW;
|
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_IFAST;
|
||||||
|
} else if (keymatch(argv[argn], "float", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_FLOAT;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dither", 2)) {
|
||||||
|
/* Select dithering algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "fs", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_FS;
|
||||||
|
} else if (keymatch(argv[argn], "none", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_NONE;
|
||||||
|
} else if (keymatch(argv[argn], "ordered", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_ORDERED;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||||
|
/* Enable debug printouts. */
|
||||||
|
/* On first -d, print version identification */
|
||||||
|
static boolean printed_version = FALSE;
|
||||||
|
|
||||||
|
if (! printed_version) {
|
||||||
|
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
|
||||||
|
JVERSION, JCOPYRIGHT);
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nx86 SIMD extension for IJG JPEG library, version %s\n\n",
|
||||||
|
JPEG_SIMDEXT_VER_STR);
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "SIMD instructions supported by the system :",
|
||||||
|
jpeg_simd_support(NULL));
|
||||||
|
|
||||||
|
fprintf(stderr, "\n === SIMD Operation Modes ===\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Accurate integer DCT (-dct int) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_ISLOW));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Fast integer DCT (-dct fast) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_IFAST));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Floating-point DCT (-dct float) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_FLOAT));
|
||||||
|
#endif
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Reduced-size DCT (-scale M/N) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_FLOAT+1));
|
||||||
|
#endif
|
||||||
|
print_simd_info(stderr, "High-quality upsampling (default) :",
|
||||||
|
jpeg_simd_upsampler(cinfo, TRUE));
|
||||||
|
print_simd_info(stderr, "Low-quality upsampling (-nosmooth) :",
|
||||||
|
jpeg_simd_upsampler(cinfo, FALSE));
|
||||||
|
print_simd_info(stderr, "Colorspace conversion (YCbCr->RGB) :",
|
||||||
|
jpeg_simd_color_deconverter(cinfo));
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
printed_version = TRUE;
|
||||||
|
}
|
||||||
|
cinfo->err->trace_level++;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "fast", 1)) {
|
||||||
|
/* Select recommended processing options for quick-and-dirty output. */
|
||||||
|
cinfo->two_pass_quantize = FALSE;
|
||||||
|
cinfo->dither_mode = JDITHER_ORDERED;
|
||||||
|
if (! cinfo->quantize_colors) /* don't override an earlier -colors */
|
||||||
|
cinfo->desired_number_of_colors = 216;
|
||||||
|
cinfo->dct_method = JDCT_FASTEST;
|
||||||
|
cinfo->do_fancy_upsampling = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "gif", 1)) {
|
||||||
|
/* GIF output format. */
|
||||||
|
requested_fmt = FMT_GIF;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
|
||||||
|
/* Force monochrome output. */
|
||||||
|
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "map", 3)) {
|
||||||
|
/* Quantize to a color map taken from an input file. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (for_real) { /* too expensive to do twice! */
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
|
||||||
|
FILE * mapfile;
|
||||||
|
|
||||||
|
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
read_color_map(cinfo, mapfile);
|
||||||
|
fclose(mapfile);
|
||||||
|
cinfo->quantize_colors = TRUE;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (ch == 'm' || ch == 'M')
|
||||||
|
lval *= 1000L;
|
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "nosmooth", 3)) {
|
||||||
|
/* Suppress fancy upsampling */
|
||||||
|
cinfo->do_fancy_upsampling = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "onepass", 3)) {
|
||||||
|
/* Use fast one-pass quantization. */
|
||||||
|
cinfo->two_pass_quantize = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "os2", 3)) {
|
||||||
|
/* BMP output format (OS/2 flavor). */
|
||||||
|
requested_fmt = FMT_OS2;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "outfile", 4)) {
|
||||||
|
/* Set output file name. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
outfilename = argv[argn]; /* save it away for later use */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
|
||||||
|
/* PPM/PGM output format. */
|
||||||
|
requested_fmt = FMT_PPM;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "rle", 1)) {
|
||||||
|
/* RLE output format. */
|
||||||
|
requested_fmt = FMT_RLE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "scale", 1)) {
|
||||||
|
/* Scale the output image by a fraction M/N. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d/%d",
|
||||||
|
&cinfo->scale_num, &cinfo->scale_denom) != 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "targa", 1)) {
|
||||||
|
/* Targa output format. */
|
||||||
|
requested_fmt = FMT_TARGA;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
usage(); /* bogus switch */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argn; /* return index of next arg (file name) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marker processor for COM and interesting APPn markers.
|
||||||
|
* This replaces the library's built-in processor, which just skips the marker.
|
||||||
|
* We want to print out the marker as text, to the extent possible.
|
||||||
|
* Note this code relies on a non-suspending data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(unsigned int)
|
||||||
|
jpeg_getc (j_decompress_ptr cinfo)
|
||||||
|
/* Read next byte */
|
||||||
|
{
|
||||||
|
struct jpeg_source_mgr * datasrc = cinfo->src;
|
||||||
|
|
||||||
|
if (datasrc->bytes_in_buffer == 0) {
|
||||||
|
if (! (*datasrc->fill_input_buffer) (cinfo))
|
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||||
|
}
|
||||||
|
datasrc->bytes_in_buffer--;
|
||||||
|
return GETJOCTET(*datasrc->next_input_byte++);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
print_text_marker (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
boolean traceit = (cinfo->err->trace_level >= 1);
|
||||||
|
INT32 length;
|
||||||
|
unsigned int ch;
|
||||||
|
unsigned int lastch = 0;
|
||||||
|
|
||||||
|
length = jpeg_getc(cinfo) << 8;
|
||||||
|
length += jpeg_getc(cinfo);
|
||||||
|
length -= 2; /* discount the length word itself */
|
||||||
|
|
||||||
|
if (traceit) {
|
||||||
|
if (cinfo->unread_marker == JPEG_COM)
|
||||||
|
fprintf(stderr, "Comment, length %ld:\n", (long) length);
|
||||||
|
else /* assume it is an APPn otherwise */
|
||||||
|
fprintf(stderr, "APP%d, length %ld:\n",
|
||||||
|
cinfo->unread_marker - JPEG_APP0, (long) length);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--length >= 0) {
|
||||||
|
ch = jpeg_getc(cinfo);
|
||||||
|
if (traceit) {
|
||||||
|
/* Emit the character in a readable form.
|
||||||
|
* Nonprintables are converted to \nnn form,
|
||||||
|
* while \ is converted to \\.
|
||||||
|
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
|
||||||
|
*/
|
||||||
|
if (ch == '\r') {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
} else if (ch == '\n') {
|
||||||
|
if (lastch != '\r')
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
fprintf(stderr, "\\\\");
|
||||||
|
} else if (isprint(ch)) {
|
||||||
|
putc(ch, stderr);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\\%03o", ch);
|
||||||
|
}
|
||||||
|
lastch = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traceit)
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for overwrite of an existing file; clear it with user
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_OVERWRITE_CHECK
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
is_write_ok (char * outfname)
|
||||||
|
{
|
||||||
|
FILE * ofile;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
ofile = fopen(outfname, READ_BINARY);
|
||||||
|
if (ofile == NULL)
|
||||||
|
return TRUE; /* not present */
|
||||||
|
fclose(ofile); /* oops, it is present */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
|
||||||
|
outfname);
|
||||||
|
fflush(stderr);
|
||||||
|
ch = getc(stdin);
|
||||||
|
if (ch != '\n') /* flush rest of line */
|
||||||
|
while (getc(stdin) != '\n')
|
||||||
|
/* nothing */;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 'Y':
|
||||||
|
case 'y':
|
||||||
|
return TRUE;
|
||||||
|
case 'N':
|
||||||
|
case 'n':
|
||||||
|
return FALSE;
|
||||||
|
/* otherwise, ask again */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process a single input file name, and return its index in argv[].
|
||||||
|
* File names at or to left of old_file_index have been processed already.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
process_one_file (int argc, char **argv, int old_file_index)
|
||||||
|
{
|
||||||
|
struct jpeg_decompress_struct cinfo;
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
char *infilename;
|
||||||
|
char workfilename[PATH_MAX];
|
||||||
|
const char *default_extension = NULL;
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
struct cdjpeg_progress_mgr progress;
|
||||||
|
#endif
|
||||||
|
int file_index;
|
||||||
|
djpeg_dest_ptr dest_mgr = NULL;
|
||||||
|
FILE * input_file = NULL;
|
||||||
|
FILE * output_file = NULL;
|
||||||
|
JDIMENSION num_scanlines;
|
||||||
|
|
||||||
|
/* Initialize the JPEG decompression object with default error handling. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
/* Add some application-specific error messages (from cderror.h) */
|
||||||
|
jerr.addon_message_table = cdjpeg_message_table;
|
||||||
|
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
||||||
|
jerr.last_addon_message = JMSG_LASTADDONCODE;
|
||||||
|
|
||||||
|
/* Insert custom marker processor for COM and APP12.
|
||||||
|
* APP12 is used by some digital camera makers for textual info,
|
||||||
|
* so we provide the ability to display it as text.
|
||||||
|
* If you like, additional APPn marker types can be selected for display,
|
||||||
|
* but don't try to override APP0 or APP14 this way (see libjpeg.doc).
|
||||||
|
*/
|
||||||
|
jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
|
||||||
|
jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
|
||||||
|
|
||||||
|
/* Now safe to enable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Scan command line to find next file name.
|
||||||
|
* It is convenient to use just one switch-parsing routine, but the switch
|
||||||
|
* values read here are ignored; we will rescan the switches after opening
|
||||||
|
* the input file.
|
||||||
|
* (Exception: tracing level set here controls verbosity for COM markers
|
||||||
|
* found during jpeg_read_header...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
|
||||||
|
if (file_index >= argc) {
|
||||||
|
fprintf(stderr, "%s: missing input file name\n", progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the input file. */
|
||||||
|
infilename = argv[file_index];
|
||||||
|
if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, infilename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
start_progress_monitor((j_common_ptr) &cinfo, &progress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specify data source for decompression */
|
||||||
|
jpeg_stdio_src(&cinfo, input_file);
|
||||||
|
|
||||||
|
/* Read file header, set default decompression parameters */
|
||||||
|
(void) jpeg_read_header(&cinfo, TRUE);
|
||||||
|
|
||||||
|
/* Adjust default decompression parameters by re-parsing the options */
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
|
||||||
|
|
||||||
|
/* Initialize the output module now to let it override any crucial
|
||||||
|
* option settings (for instance, GIF wants to force color quantization).
|
||||||
|
*/
|
||||||
|
switch (requested_fmt) {
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
case FMT_BMP:
|
||||||
|
dest_mgr = jinit_write_bmp(&cinfo, FALSE);
|
||||||
|
default_extension = ".bmp";
|
||||||
|
break;
|
||||||
|
case FMT_OS2:
|
||||||
|
dest_mgr = jinit_write_bmp(&cinfo, TRUE);
|
||||||
|
default_extension = ".bmp";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
case FMT_GIF:
|
||||||
|
dest_mgr = jinit_write_gif(&cinfo);
|
||||||
|
default_extension = ".gif";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
case FMT_PPM:
|
||||||
|
dest_mgr = jinit_write_ppm(&cinfo);
|
||||||
|
default_extension = ".ppm";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
case FMT_RLE:
|
||||||
|
dest_mgr = jinit_write_rle(&cinfo);
|
||||||
|
default_extension = ".rle";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
case FMT_TARGA:
|
||||||
|
dest_mgr = jinit_write_targa(&cinfo);
|
||||||
|
default_extension = ".tga";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If user didn't supply -outfile switch, select output file name. */
|
||||||
|
if (outfilename == NULL) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
outfilename = workfilename;
|
||||||
|
/* Make outfilename be infilename with appropriate extension */
|
||||||
|
strcpy(outfilename, infilename);
|
||||||
|
for (i = strlen(outfilename)-1; i >= 0; i--) {
|
||||||
|
switch (outfilename[i]) {
|
||||||
|
case ':':
|
||||||
|
case '/':
|
||||||
|
case '\\':
|
||||||
|
i = 0; /* stop scanning */
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
outfilename[i] = '\0'; /* lop off existing extension */
|
||||||
|
i = 0; /* stop scanning */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; /* keep scanning */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcat(outfilename, default_extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Decompressing %s => %s\n", infilename, outfilename);
|
||||||
|
#ifndef NO_OVERWRITE_CHECK
|
||||||
|
if (! is_write_ok(outfilename))
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Open the output file. */
|
||||||
|
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
dest_mgr->output_file = output_file;
|
||||||
|
|
||||||
|
/* Start decompressor */
|
||||||
|
(void) jpeg_start_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Write output file header */
|
||||||
|
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
|
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||||
|
dest_mgr->buffer_height);
|
||||||
|
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
/* Hack: count final pass as done in case finish_output does an extra pass.
|
||||||
|
* The library won't have updated completed_passes.
|
||||||
|
*/
|
||||||
|
progress.pub.completed_passes = progress.pub.total_passes;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Finish decompression and release memory.
|
||||||
|
* I must do it in this order because output module has allocated memory
|
||||||
|
* of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
||||||
|
*/
|
||||||
|
(*dest_mgr->finish_output) (&cinfo, dest_mgr);
|
||||||
|
(void) jpeg_finish_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Clean up and exit */
|
||||||
|
fail:
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
|
||||||
|
if (input_file != NULL) fclose(input_file);
|
||||||
|
if (output_file != NULL) fclose(output_file);
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
end_progress_monitor((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Disable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return file_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int file_index;
|
||||||
|
|
||||||
|
/* On Mac, fetch a command line. */
|
||||||
|
#ifdef USE_CCOMMAND
|
||||||
|
argc = ccommand(&argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MSDOS
|
||||||
|
progname = "djpeg"; /* DOS tends to be too verbose about argv[0] */
|
||||||
|
#else
|
||||||
|
progname = argv[0];
|
||||||
|
if (progname == NULL || progname[0] == 0)
|
||||||
|
progname = "djpeg"; /* in case C library doesn't provide it */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The default maxmem must be computed only once at program startup,
|
||||||
|
* since releasing memory with free() won't give it back to the OS.
|
||||||
|
*/
|
||||||
|
#ifdef FREE_MEM_ESTIMATE
|
||||||
|
default_maxmem = FREE_MEM_ESTIMATE;
|
||||||
|
#else
|
||||||
|
default_maxmem = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Scan command line, parse switches and locate input file names */
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(); /* nothing on the command line?? */
|
||||||
|
|
||||||
|
file_index = 0;
|
||||||
|
|
||||||
|
while (file_index < argc-1)
|
||||||
|
file_index = process_one_file(argc, argv, file_index);
|
||||||
|
|
||||||
|
/* All done. */
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
return 0; /* suppress no-return-value warnings */
|
||||||
|
}
|
||||||
62
altui/usage.alt
Normal file
62
altui/usage.alt
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
(Most of the standard usage.doc file also applies to this alternate version,
|
||||||
|
but replace its "GENERAL USAGE" section with the text below. Edit the text
|
||||||
|
as necessary if you don't support wildcards or overwrite checking. Be sure
|
||||||
|
to fix the djpeg switch descriptions if you are not defaulting to PPM output.
|
||||||
|
Also, if you've provided an accurate memory-estimation procedure, you can
|
||||||
|
probably eliminate the HINTS related to the -maxmemory switch.)
|
||||||
|
|
||||||
|
|
||||||
|
GENERAL USAGE
|
||||||
|
|
||||||
|
We provide two programs, cjpeg to compress an image file into JPEG format,
|
||||||
|
and djpeg to decompress a JPEG file back into a conventional image format.
|
||||||
|
|
||||||
|
The basic command line is:
|
||||||
|
cjpeg [switches] list of image files
|
||||||
|
or
|
||||||
|
djpeg [switches] list of jpeg files
|
||||||
|
|
||||||
|
Each file named is compressed or decompressed. The input file(s) are not
|
||||||
|
modified; the output data is written to files which have the same names
|
||||||
|
except for extension. cjpeg always uses ".jpg" for the output file name's
|
||||||
|
extension; djpeg uses one of ".bmp", ".gif", ".ppm", ".rle", or ".tga",
|
||||||
|
depending on what output format is selected by the switches.
|
||||||
|
|
||||||
|
For example, to convert xxx.bmp to xxx.jpg and yyy.ppm to yyy.jpg, say:
|
||||||
|
cjpeg xxx.bmp yyy.ppm
|
||||||
|
|
||||||
|
On most systems you can use standard wildcards to specify the list of input
|
||||||
|
files; for example, on DOS "djpeg *.jpg" decompresses all the JPEG files in
|
||||||
|
the current directory.
|
||||||
|
|
||||||
|
If an intended output file already exists, you'll be asked whether or not to
|
||||||
|
overwrite it. If you say no, the program skips that input file and goes on
|
||||||
|
to the next one.
|
||||||
|
|
||||||
|
You can intermix switches and file names; for example
|
||||||
|
djpeg -gif file1.jpg -targa file2.jpg
|
||||||
|
decompresses file1.jpg into GIF format (file1.gif) and file2.jpg into Targa
|
||||||
|
format (file2.tga). Only switches to the left of a given file name affect
|
||||||
|
processing of that file; when there are conflicting switches, the rightmost
|
||||||
|
one takes precedence.
|
||||||
|
|
||||||
|
You can override the program's choice of output file name by using the
|
||||||
|
-outfile switch, as in
|
||||||
|
cjpeg -outfile output.jpg input.ppm
|
||||||
|
-outfile only affects the first input file name to its right.
|
||||||
|
|
||||||
|
The currently supported image file formats are: PPM (PBMPLUS color format),
|
||||||
|
PGM (PBMPLUS gray-scale format), BMP, GIF, Targa, and RLE (Utah Raster
|
||||||
|
Toolkit format). (RLE is supported only if the URT library is available,
|
||||||
|
which it isn't on most non-Unix systems.) cjpeg recognizes the input image
|
||||||
|
format automatically, with the exception of some Targa-format files. You
|
||||||
|
have to tell djpeg which format to generate.
|
||||||
|
|
||||||
|
JPEG files are in the defacto standard JFIF file format. There are other,
|
||||||
|
less widely used JPEG-based file formats, but we don't support them.
|
||||||
|
|
||||||
|
All switch names may be abbreviated; for example, -grayscale may be written
|
||||||
|
-gray or -gr. Most of the "basic" switches can be abbreviated to as little as
|
||||||
|
one letter. Upper and lower case are equivalent (-BMP is the same as -bmp).
|
||||||
|
British spellings are also accepted (e.g., -greyscale), though for brevity
|
||||||
|
these are not mentioned below.
|
||||||
36
ansi2knr.1
Normal file
36
ansi2knr.1
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
.TH ANSI2KNR 1 "19 Jan 1996"
|
||||||
|
.SH NAME
|
||||||
|
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.I ansi2knr
|
||||||
|
[--varargs] input_file [output_file]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
If no output_file is supplied, output goes to stdout.
|
||||||
|
.br
|
||||||
|
There are no error messages.
|
||||||
|
.sp
|
||||||
|
.I ansi2knr
|
||||||
|
recognizes function definitions 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, and with a left brace as the first token on the
|
||||||
|
following line (ignoring possible intervening comments). It will recognize a
|
||||||
|
multi-line header provided that no intervening line ends with a left or right
|
||||||
|
brace or a semicolon. These algorithms ignore whitespace and comments, except
|
||||||
|
that the function name must be the first thing on the line.
|
||||||
|
.sp
|
||||||
|
The following constructs will confuse it:
|
||||||
|
.br
|
||||||
|
- Any other construct that starts at the left margin and follows the
|
||||||
|
above syntax (such as a macro or function call).
|
||||||
|
.br
|
||||||
|
- Some macros that tinker with the syntax of the function header.
|
||||||
|
.sp
|
||||||
|
The --varargs switch is obsolete, and is recognized only for
|
||||||
|
backwards compatibility. The present version of
|
||||||
|
.I ansi2knr
|
||||||
|
will always attempt to convert a ... argument to va_alist and va_dcl.
|
||||||
|
.SH AUTHOR
|
||||||
|
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
|
||||||
|
continues to maintain the current version; most of the code in the current
|
||||||
|
version is his work. ansi2knr also includes contributions by Francois
|
||||||
|
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.
|
||||||
463
ansi2knr.c
463
ansi2knr.c
@@ -1,30 +1,32 @@
|
|||||||
/*
|
/* ansi2knr.c */
|
||||||
* Received from Peter Deutsch (ghost@aladdin.com)
|
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
|
||||||
* Fri, 26 Apr 91 10:10:10 PDT
|
|
||||||
* Small portability improvements by Tom Lane
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved.
|
|
||||||
Distributed by Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of Ghostscript.
|
|
||||||
|
|
||||||
Ghostscript is distributed in the hope that it will be useful, but
|
|
||||||
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 ----------
|
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY. No author or distributor accepts responsibility to anyone for the
|
||||||
|
consequences of using it or for whether it serves any particular purpose or
|
||||||
|
works at all, unless he says so in writing. Refer to the GNU General Public
|
||||||
|
License (the "GPL") for full details.
|
||||||
|
|
||||||
|
Everyone is granted permission to copy, modify and redistribute ansi2knr,
|
||||||
|
but only under the conditions described in the GPL. A copy of this license
|
||||||
|
is supposed to have been given to you along with ansi2knr so you can know
|
||||||
|
your rights and responsibilities. It should be in a file named COPYLEFT.
|
||||||
|
[In the IJG distribution, the GPL appears below, not in a separate file.]
|
||||||
|
Among other things, the copyright notice and this notice must be preserved
|
||||||
|
on all copies.
|
||||||
|
|
||||||
|
We explicitly state here what we believe is already implied by the GPL: if
|
||||||
|
the ansi2knr program is distributed as a separate set of sources and a
|
||||||
|
separate executable file which are aggregated on a storage medium together
|
||||||
|
with another program, this in itself does not bring the other program under
|
||||||
|
the GPL, nor does the mere fact that such a program or the procedures for
|
||||||
|
constructing it invoke the ansi2knr executable bring any other part of the
|
||||||
|
program under the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
---------- Here is the GNU GPL file COPYLEFT, referred to above ----------
|
||||||
----- These terms do NOT apply to the JPEG software itself; see README ------
|
----- These terms do NOT apply to the JPEG software itself; see README ------
|
||||||
|
|
||||||
GHOSTSCRIPT GENERAL PUBLIC LICENSE
|
GHOSTSCRIPT GENERAL PUBLIC LICENSE
|
||||||
@@ -169,107 +171,253 @@ INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
|
|||||||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
|
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
|
||||||
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
|
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
|
||||||
BY ANY OTHER PARTY.
|
BY ANY OTHER PARTY.
|
||||||
-------------------- End of file COPYING ------------------------------
|
|
||||||
|
-------------------- End of file COPYLEFT ------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Usage:
|
||||||
|
ansi2knr input_file [output_file]
|
||||||
|
* If no output_file is supplied, output goes to stdout.
|
||||||
|
* There are no error messages.
|
||||||
|
*
|
||||||
|
* ansi2knr recognizes function definitions 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,
|
||||||
|
* and with a left brace as the first token on the following line
|
||||||
|
* (ignoring possible intervening comments).
|
||||||
|
* It will recognize a multi-line header provided that no intervening
|
||||||
|
* line ends with a left or right brace or a semicolon.
|
||||||
|
* These algorithms ignore whitespace and comments, except that
|
||||||
|
* the function name must be the first thing on the line.
|
||||||
|
* The following constructs will confuse it:
|
||||||
|
* - Any other construct that starts at the left margin and
|
||||||
|
* follows the above syntax (such as a macro or function call).
|
||||||
|
* - Some macros that tinker with the syntax of the function header.
|
||||||
|
*/
|
||||||
|
|
||||||
/* ansi2knr.c */
|
/*
|
||||||
/* Convert ANSI function declarations to K&R syntax */
|
* The original and principal author of ansi2knr is L. Peter Deutsch
|
||||||
|
* <ghost@aladdin.com>. Other authors are noted in the change history
|
||||||
|
* that follows (in reverse chronological order):
|
||||||
|
lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
|
||||||
|
compilers that don't understand void, as suggested by
|
||||||
|
Tom Lane
|
||||||
|
lpd 96-01-15 changed to require that the first non-comment token
|
||||||
|
on the line following a function header be a left brace,
|
||||||
|
to reduce sensitivity to macros, as suggested by Tom Lane
|
||||||
|
<tgl@sss.pgh.pa.us>
|
||||||
|
lpd 95-06-22 removed #ifndefs whose sole purpose was to define
|
||||||
|
undefined preprocessor symbols as 0; changed all #ifdefs
|
||||||
|
for configuration symbols to #ifs
|
||||||
|
lpd 95-04-05 changed copyright notice to make it clear that
|
||||||
|
including ansi2knr in a program does not bring the entire
|
||||||
|
program under the GPL
|
||||||
|
lpd 94-12-18 added conditionals for systems where ctype macros
|
||||||
|
don't handle 8-bit characters properly, suggested by
|
||||||
|
Francois Pinard <pinard@iro.umontreal.ca>;
|
||||||
|
removed --varargs switch (this is now the default)
|
||||||
|
lpd 94-10-10 removed CONFIG_BROKETS conditional
|
||||||
|
lpd 94-07-16 added some conditionals to help GNU `configure',
|
||||||
|
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
|
||||||
|
properly erase prototype args in function parameters,
|
||||||
|
contributed by Jim Avera <jima@netcom.com>;
|
||||||
|
correct error in writeblanks (it shouldn't erase EOLs)
|
||||||
|
lpd 89-xx-xx original version
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Most of the conditionals here are to make ansi2knr work with */
|
||||||
|
/* or without the GNU configure machinery. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef BSD
|
#if HAVE_CONFIG_H
|
||||||
#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>
|
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
|
||||||
#else
|
This will define HAVE_CONFIG_H and so, activate the following lines.
|
||||||
#ifdef VMS
|
|
||||||
extern char *malloc();
|
|
||||||
extern void free();
|
|
||||||
#else
|
|
||||||
extern char *malloc();
|
|
||||||
extern int free();
|
|
||||||
#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 */
|
# if STDC_HEADERS || HAVE_STRING_H
|
||||||
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
|
# include <string.h>
|
||||||
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
|
# else
|
||||||
|
# include <strings.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* not HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
/* Otherwise do it the hard way */
|
||||||
|
|
||||||
|
# ifdef BSD
|
||||||
|
# include <strings.h>
|
||||||
|
# else
|
||||||
|
# ifdef VMS
|
||||||
|
extern int strlen(), strncmp();
|
||||||
|
# else
|
||||||
|
# include <string.h>
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif /* not HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#if STDC_HEADERS
|
||||||
|
# include <stdlib.h>
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
malloc and free should be declared in stdlib.h,
|
||||||
|
but if you've got a K&R compiler, they probably aren't.
|
||||||
|
*/
|
||||||
|
# ifdef MSDOS
|
||||||
|
# include <malloc.h>
|
||||||
|
# else
|
||||||
|
# ifdef VMS
|
||||||
|
extern char *malloc();
|
||||||
|
extern void free();
|
||||||
|
# else
|
||||||
|
extern char *malloc();
|
||||||
|
extern int free();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ctype macros don't always handle 8-bit characters correctly.
|
||||||
|
* Compensate for this here.
|
||||||
|
*/
|
||||||
|
#ifdef isascii
|
||||||
|
# undef HAVE_ISASCII /* just in case */
|
||||||
|
# define HAVE_ISASCII 1
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
#if STDC_HEADERS || !HAVE_ISASCII
|
||||||
|
# define is_ascii(c) 1
|
||||||
|
#else
|
||||||
|
# define is_ascii(c) isascii(c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define is_space(c) (is_ascii(c) && isspace(c))
|
||||||
|
#define is_alpha(c) (is_ascii(c) && isalpha(c))
|
||||||
|
#define is_alnum(c) (is_ascii(c) && isalnum(c))
|
||||||
|
|
||||||
|
/* Scanning macros */
|
||||||
|
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
|
||||||
|
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
|
||||||
|
|
||||||
|
/* Forward references */
|
||||||
|
char *skipspace();
|
||||||
|
int writeblanks();
|
||||||
|
int test1();
|
||||||
|
int convert1();
|
||||||
|
|
||||||
|
/* The main program */
|
||||||
int
|
int
|
||||||
main(argc, argv)
|
main(argc, argv)
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{ FILE *in, *out;
|
{ FILE *in, *out;
|
||||||
#define bufsize 500 /* arbitrary size */
|
#define bufsize 5000 /* arbitrary size */
|
||||||
char buf[bufsize+1];
|
char *buf;
|
||||||
char *line;
|
char *line;
|
||||||
|
char *more;
|
||||||
|
/*
|
||||||
|
* In previous versions, ansi2knr recognized a --varargs switch.
|
||||||
|
* If this switch was supplied, ansi2knr would attempt to convert
|
||||||
|
* a ... argument to va_alist and va_dcl; if this switch was not
|
||||||
|
* supplied, ansi2knr would simply drop any such arguments.
|
||||||
|
* Now, ansi2knr always does this conversion, and we only
|
||||||
|
* check for this switch for backward compatibility.
|
||||||
|
*/
|
||||||
|
int convert_varargs = 1;
|
||||||
|
|
||||||
|
if ( argc > 1 && argv[1][0] == '-' )
|
||||||
|
{ if ( !strcmp(argv[1], "--varargs") )
|
||||||
|
{ convert_varargs = 1;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
switch ( argc )
|
switch ( argc )
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
printf("Usage: ansi2knr input_file [output_file]\n");
|
printf("Usage: ansi2knr input_file [output_file]\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
case 2:
|
case 2:
|
||||||
out = stdout; break;
|
out = stdout;
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
out = fopen(argv[2], "w");
|
out = fopen(argv[2], "w");
|
||||||
if ( out == NULL )
|
if ( out == NULL )
|
||||||
{ fprintf(stderr, "Cannot open %s\n", argv[2]);
|
{ fprintf(stderr, "Cannot open output file %s\n", argv[2]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in = fopen(argv[1], "r");
|
in = fopen(argv[1], "r");
|
||||||
if ( in == NULL )
|
if ( in == NULL )
|
||||||
{ fprintf(stderr, "Cannot open %s\n", argv[1]);
|
{ fprintf(stderr, "Cannot open input file %s\n", argv[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
|
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
|
||||||
|
buf = malloc(bufsize);
|
||||||
line = buf;
|
line = buf;
|
||||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||||
{ switch ( test1(buf) )
|
{
|
||||||
|
test: line += strlen(line);
|
||||||
|
switch ( test1(buf) )
|
||||||
{
|
{
|
||||||
|
case 2: /* a function header */
|
||||||
|
convert1(buf, out, 1, convert_varargs);
|
||||||
|
break;
|
||||||
case 1: /* a function */
|
case 1: /* a function */
|
||||||
convert1(buf, out);
|
/* Check for a { at the start of the next line. */
|
||||||
|
more = ++line;
|
||||||
|
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
|
||||||
|
goto wl;
|
||||||
|
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
|
||||||
|
goto wl;
|
||||||
|
switch ( *skipspace(more, 1) )
|
||||||
|
{
|
||||||
|
case '{':
|
||||||
|
/* Definitely a function header. */
|
||||||
|
convert1(buf, out, 0, convert_varargs);
|
||||||
|
fputs(more, out);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* The next line was blank or a comment: */
|
||||||
|
/* keep scanning for a non-comment. */
|
||||||
|
line += strlen(line);
|
||||||
|
goto f;
|
||||||
|
default:
|
||||||
|
/* buf isn't a function header, but */
|
||||||
|
/* more might be. */
|
||||||
|
fputs(buf, out);
|
||||||
|
strcpy(buf, more);
|
||||||
|
line = buf;
|
||||||
|
goto test;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case -1: /* maybe the start of a function */
|
case -1: /* maybe the start of a function */
|
||||||
line = buf + strlen(buf);
|
if ( line != buf + (bufsize - 1) ) /* overflow check */
|
||||||
continue;
|
continue;
|
||||||
|
/* falls through */
|
||||||
default: /* not a function */
|
default: /* not a function */
|
||||||
fputs(buf, out);
|
wl: fputs(buf, out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
line = buf;
|
line = buf;
|
||||||
}
|
}
|
||||||
if ( line != buf ) fputs(buf, out);
|
if ( line != buf )
|
||||||
|
fputs(buf, out);
|
||||||
|
free(buf);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -281,11 +429,14 @@ skipspace(p, dir)
|
|||||||
register char *p;
|
register char *p;
|
||||||
register int dir; /* 1 for forward, -1 for backward */
|
register int dir; /* 1 for forward, -1 for backward */
|
||||||
{ for ( ; ; )
|
{ for ( ; ; )
|
||||||
{ while ( isspace(*p) ) p += dir;
|
{ while ( is_space(*p) )
|
||||||
if ( !(*p == '/' && p[dir] == '*') ) break;
|
p += dir;
|
||||||
|
if ( !(*p == '/' && p[dir] == '*') )
|
||||||
|
break;
|
||||||
p += dir; p += dir;
|
p += dir; p += dir;
|
||||||
while ( !(*p == '*' && p[dir] == '/') )
|
while ( !(*p == '*' && p[dir] == '/') )
|
||||||
{ if ( *p == 0 ) return p; /* multi-line comment?? */
|
{ if ( *p == 0 )
|
||||||
|
return p; /* multi-line comment?? */
|
||||||
p += dir;
|
p += dir;
|
||||||
}
|
}
|
||||||
p += dir; p += dir;
|
p += dir; p += dir;
|
||||||
@@ -295,13 +446,16 @@ skipspace(p, dir)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Write blanks over part of a string.
|
* Write blanks over part of a string.
|
||||||
|
* Don't overwrite end-of-line characters.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
writeblanks(start, end)
|
writeblanks(start, end)
|
||||||
char *start;
|
char *start;
|
||||||
char *end;
|
char *end;
|
||||||
{ char *p;
|
{ char *p;
|
||||||
for ( p = start; p < end; p++ ) *p = ' ';
|
for ( p = start; p < end; p++ )
|
||||||
|
if ( *p != '\r' && *p != '\n' )
|
||||||
|
*p = ' ';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,8 +465,12 @@ writeblanks(start, end)
|
|||||||
* Return as follows:
|
* Return as follows:
|
||||||
* 0 - definitely not a function definition;
|
* 0 - definitely not a function definition;
|
||||||
* 1 - definitely a function definition;
|
* 1 - definitely a function definition;
|
||||||
|
* 2 - definitely a function prototype (NOT USED);
|
||||||
* -1 - may be the beginning of a function definition,
|
* -1 - may be the beginning of a function definition,
|
||||||
* append another line and look again.
|
* append another line and look again.
|
||||||
|
* The reason we don't attempt to convert function prototypes is that
|
||||||
|
* Ghostscript's declaration-generating macros look too much like
|
||||||
|
* prototypes, and confuse the algorithms.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
test1(buf)
|
test1(buf)
|
||||||
@@ -321,24 +479,27 @@ test1(buf)
|
|||||||
char *bend;
|
char *bend;
|
||||||
char *endfn;
|
char *endfn;
|
||||||
int contin;
|
int contin;
|
||||||
|
|
||||||
if ( !isidfirstchar(*p) )
|
if ( !isidfirstchar(*p) )
|
||||||
return 0; /* no name at left margin */
|
return 0; /* no name at left margin */
|
||||||
bend = skipspace(buf + strlen(buf) - 1, -1);
|
bend = skipspace(buf + strlen(buf) - 1, -1);
|
||||||
switch ( *bend )
|
switch ( *bend )
|
||||||
{
|
{
|
||||||
case ')': contin = 1; break;
|
case ';': contin = 0 /*2*/; break;
|
||||||
case '(':
|
case ')': contin = 1; break;
|
||||||
case ',': contin = -1; break;
|
case '{': return 0; /* not a function */
|
||||||
default: return 0; /* not a function */
|
case '}': return 0; /* not a function */
|
||||||
|
default: contin = -1;
|
||||||
}
|
}
|
||||||
while ( isidchar(*p) ) p++;
|
while ( isidchar(*p) )
|
||||||
|
p++;
|
||||||
endfn = p;
|
endfn = p;
|
||||||
p = skipspace(p, 1);
|
p = skipspace(p, 1);
|
||||||
if ( *p++ != '(' )
|
if ( *p++ != '(' )
|
||||||
return 0; /* not a function */
|
return 0; /* not a function */
|
||||||
p = skipspace(p, 1);
|
p = skipspace(p, 1);
|
||||||
if ( *p == ')' )
|
if ( *p == ')' )
|
||||||
return 0; /* no parameters */
|
return 0; /* no parameters */
|
||||||
/* Check that the apparent function name isn't a keyword. */
|
/* Check that the apparent function name isn't a keyword. */
|
||||||
/* We only need to check for keywords that could be followed */
|
/* We only need to check for keywords that could be followed */
|
||||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||||
@@ -352,26 +513,36 @@ test1(buf)
|
|||||||
char **key = words;
|
char **key = words;
|
||||||
char *kp;
|
char *kp;
|
||||||
int len = endfn - buf;
|
int len = endfn - buf;
|
||||||
|
|
||||||
while ( (kp = *key) != 0 )
|
while ( (kp = *key) != 0 )
|
||||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||||
return 0; /* name is a keyword */
|
return 0; /* name is a keyword */
|
||||||
key++;
|
key++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return contin;
|
return contin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert a recognized function definition or header to K&R syntax. */
|
||||||
int
|
int
|
||||||
convert1(buf, out)
|
convert1(buf, out, header, convert_varargs)
|
||||||
char *buf;
|
char *buf;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
{ char *endfn = strchr(buf, '(') + 1;
|
int header; /* Boolean */
|
||||||
|
int convert_varargs; /* Boolean */
|
||||||
|
{ char *endfn;
|
||||||
register char *p;
|
register char *p;
|
||||||
char **breaks;
|
char **breaks;
|
||||||
unsigned num_breaks = 2; /* for testing */
|
unsigned num_breaks = 2; /* for testing */
|
||||||
char **btop;
|
char **btop;
|
||||||
char **bp;
|
char **bp;
|
||||||
char **ap;
|
char **ap;
|
||||||
|
char *vararg = 0;
|
||||||
|
|
||||||
|
/* Pre-ANSI implementations don't agree on whether strchr */
|
||||||
|
/* is called strchr or index, so we open-code it here. */
|
||||||
|
for ( endfn = buf; *(endfn++) != '('; )
|
||||||
|
;
|
||||||
top: p = endfn;
|
top: p = endfn;
|
||||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||||
if ( breaks == 0 )
|
if ( breaks == 0 )
|
||||||
@@ -385,7 +556,10 @@ top: p = endfn;
|
|||||||
/* Parse the argument list */
|
/* Parse the argument list */
|
||||||
do
|
do
|
||||||
{ int level = 0;
|
{ int level = 0;
|
||||||
|
char *lp = NULL;
|
||||||
|
char *rp;
|
||||||
char *end = NULL;
|
char *end = NULL;
|
||||||
|
|
||||||
if ( bp >= btop )
|
if ( bp >= btop )
|
||||||
{ /* Filled up break table. */
|
{ /* Filled up break table. */
|
||||||
/* Allocate a bigger one and start over. */
|
/* Allocate a bigger one and start over. */
|
||||||
@@ -398,13 +572,27 @@ top: p = endfn;
|
|||||||
for ( ; end == NULL; p++ )
|
for ( ; end == NULL; p++ )
|
||||||
{ switch(*p)
|
{ switch(*p)
|
||||||
{
|
{
|
||||||
case ',': if ( !level ) end = p; break;
|
case ',':
|
||||||
case '(': level++; break;
|
if ( !level ) end = p;
|
||||||
case ')': if ( --level < 0 ) end = p; break;
|
break;
|
||||||
case '/': p = skipspace(p, 1) - 1; break;
|
case '(':
|
||||||
default: ;
|
if ( !level ) lp = p;
|
||||||
|
level++;
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
if ( --level < 0 ) end = p;
|
||||||
|
else rp = p;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
p = skipspace(p, 1) - 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Erase any embedded prototype parameters. */
|
||||||
|
if ( lp )
|
||||||
|
writeblanks(lp + 1, rp);
|
||||||
p--; /* back up over terminator */
|
p--; /* back up over terminator */
|
||||||
/* Find the name being declared. */
|
/* Find the name being declared. */
|
||||||
/* This is complicated because of procedure and */
|
/* This is complicated because of procedure and */
|
||||||
@@ -413,35 +601,42 @@ top: p = endfn;
|
|||||||
{ p = skipspace(p - 1, -1);
|
{ p = skipspace(p - 1, -1);
|
||||||
switch ( *p )
|
switch ( *p )
|
||||||
{
|
{
|
||||||
case ']': /* skip array dimension(s) */
|
case ']': /* skip array dimension(s) */
|
||||||
case ')': /* skip procedure args OR name */
|
case ')': /* skip procedure args OR name */
|
||||||
{ int level = 1;
|
{ int level = 1;
|
||||||
while ( level )
|
while ( level )
|
||||||
switch ( *--p )
|
switch ( *--p )
|
||||||
{
|
{
|
||||||
case ']': case ')': level++; break;
|
case ']': case ')': level++; break;
|
||||||
case '[': case '(': level--; break;
|
case '[': case '(': level--; break;
|
||||||
case '/': p = skipspace(p, -1) + 1; break;
|
case '/': p = skipspace(p, -1) + 1; break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||||
{ /* We found the name being declared */
|
{ /* We found the name being declared */
|
||||||
while ( !isidfirstchar(*p) )
|
while ( !isidfirstchar(*p) )
|
||||||
p = skipspace(p, 1) + 1;
|
p = skipspace(p, 1) + 1;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: goto found;
|
default:
|
||||||
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||||
{ p++;
|
{ if ( convert_varargs )
|
||||||
if ( bp == breaks + 1 ) /* sole argument */
|
{ *bp++ = "va_alist";
|
||||||
writeblanks(breaks[0], p);
|
vararg = p-2;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
writeblanks(bp[-1] - 1, p);
|
{ p++;
|
||||||
bp--;
|
if ( bp == breaks + 1 ) /* sole argument */
|
||||||
|
writeblanks(breaks[0], p);
|
||||||
|
else
|
||||||
|
writeblanks(bp[-1] - 1, p);
|
||||||
|
bp--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ while ( isidchar(*p) ) p--;
|
{ while ( isidchar(*p) ) p--;
|
||||||
@@ -462,19 +657,37 @@ found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Put out the function name */
|
/* Put out the function name and left parenthesis. */
|
||||||
p = buf;
|
p = buf;
|
||||||
while ( p != endfn ) putc(*p, out), p++;
|
while ( p != endfn ) putc(*p, out), p++;
|
||||||
/* Put out the declaration */
|
/* Put out the declaration. */
|
||||||
for ( ap = breaks+1; ap < bp; ap += 2 )
|
if ( header )
|
||||||
{ p = *ap;
|
{ fputs(");", out);
|
||||||
while ( isidchar(*p) ) putc(*p, out), p++;
|
for ( p = breaks[0]; *p; p++ )
|
||||||
if ( ap < bp - 1 ) fputs(", ", out);
|
if ( *p == '\r' || *p == '\n' )
|
||||||
}
|
putc(*p, out);
|
||||||
fputs(") ", out);
|
}
|
||||||
/* Put out the argument declarations */
|
else
|
||||||
for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
|
{ for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||||
fputs(breaks[0], out);
|
{ 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] = ';';
|
||||||
|
if ( vararg != 0 )
|
||||||
|
{ *vararg = 0;
|
||||||
|
fputs(breaks[0], out); /* any prior args */
|
||||||
|
fputs("va_dcl", out); /* the final arg */
|
||||||
|
fputs(bp[0], out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputs(breaks[0], out);
|
||||||
|
}
|
||||||
free((char *)breaks);
|
free((char *)breaks);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
1106
architecture
1106
architecture
File diff suppressed because it is too large
Load Diff
132
cderror.h
Normal file
132
cderror.h
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* cderror.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file defines the error and message codes for the cjpeg/djpeg
|
||||||
|
* applications. These strings are not needed as part of the JPEG library
|
||||||
|
* proper.
|
||||||
|
* Edit this file to add new codes, or to translate the message strings to
|
||||||
|
* some other language.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To define the enum list of message codes, include this file without
|
||||||
|
* defining macro JMESSAGE. To create a message string table, include it
|
||||||
|
* again with a suitable JMESSAGE definition (see jerror.c for an example).
|
||||||
|
*/
|
||||||
|
#ifndef JMESSAGE
|
||||||
|
#ifndef CDERROR_H
|
||||||
|
#define CDERROR_H
|
||||||
|
/* First time through, define the enum list */
|
||||||
|
#define JMAKE_ENUM_LIST
|
||||||
|
#else
|
||||||
|
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
|
||||||
|
#define JMESSAGE(code,string)
|
||||||
|
#endif /* CDERROR_H */
|
||||||
|
#endif /* JMESSAGE */
|
||||||
|
|
||||||
|
#ifdef JMAKE_ENUM_LIST
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) code ,
|
||||||
|
|
||||||
|
#endif /* JMAKE_ENUM_LIST */
|
||||||
|
|
||||||
|
JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
|
||||||
|
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
|
||||||
|
JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
|
||||||
|
JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
|
||||||
|
JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
|
||||||
|
JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
|
||||||
|
JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
|
||||||
|
JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
|
||||||
|
JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
|
||||||
|
JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
|
||||||
|
JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
|
||||||
|
JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
|
||||||
|
#endif /* BMP_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
|
||||||
|
JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
|
||||||
|
JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
|
||||||
|
JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
|
||||||
|
JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
|
||||||
|
JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
|
||||||
|
JMESSAGE(JTRC_GIF_BADVERSION,
|
||||||
|
"Warning: unexpected GIF version number '%c%c%c'")
|
||||||
|
JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
|
||||||
|
JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
|
||||||
|
JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
|
||||||
|
JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
|
||||||
|
JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
|
||||||
|
JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
|
||||||
|
#endif /* GIF_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
|
||||||
|
JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
|
||||||
|
JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
|
||||||
|
JMESSAGE(JTRC_PGM, "%ux%u PGM image")
|
||||||
|
JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
|
||||||
|
JMESSAGE(JTRC_PPM, "%ux%u PPM image")
|
||||||
|
JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
|
||||||
|
#endif /* PPM_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
|
||||||
|
JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
|
||||||
|
JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
|
||||||
|
JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
|
||||||
|
JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
|
||||||
|
JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
|
||||||
|
JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
|
||||||
|
JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
|
||||||
|
JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
|
||||||
|
JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
|
||||||
|
JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
|
||||||
|
JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
|
||||||
|
JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
|
||||||
|
JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
|
||||||
|
#endif /* RLE_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
|
||||||
|
JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
|
||||||
|
JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
|
||||||
|
JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
|
||||||
|
JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
|
||||||
|
JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
|
||||||
|
#else
|
||||||
|
JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
|
||||||
|
#endif /* TARGA_SUPPORTED */
|
||||||
|
|
||||||
|
JMESSAGE(JERR_BAD_CMAP_FILE,
|
||||||
|
"Color map file is invalid or of unsupported format")
|
||||||
|
JMESSAGE(JERR_TOO_MANY_COLORS,
|
||||||
|
"Output file format cannot handle %d colormap entries")
|
||||||
|
JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
JMESSAGE(JERR_UNKNOWN_FORMAT,
|
||||||
|
"Unrecognized input file format --- perhaps you need -targa")
|
||||||
|
#else
|
||||||
|
JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
|
||||||
|
#endif
|
||||||
|
JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
|
||||||
|
|
||||||
|
#ifdef JMAKE_ENUM_LIST
|
||||||
|
|
||||||
|
JMSG_LASTADDONCODE
|
||||||
|
} ADDON_MESSAGE_CODE;
|
||||||
|
|
||||||
|
#undef JMAKE_ENUM_LIST
|
||||||
|
#endif /* JMAKE_ENUM_LIST */
|
||||||
|
|
||||||
|
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
|
||||||
|
#undef JMESSAGE
|
||||||
181
cdjpeg.c
Normal file
181
cdjpeg.c
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* cdjpeg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains common support routines used by the IJG application
|
||||||
|
* programs (cjpeg, djpeg, jpegtran).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||||
|
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
#include <signal.h> /* to declare signal() */
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SETMODE
|
||||||
|
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||||
|
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||||
|
#include <io.h> /* to declare setmode() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal catcher to ensure that temporary files are removed before aborting.
|
||||||
|
* NB: for Amiga Manx C this is actually a global routine named _abort();
|
||||||
|
* we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
|
||||||
|
static j_common_ptr sig_cinfo;
|
||||||
|
|
||||||
|
void /* must be global for Manx C */
|
||||||
|
signal_catcher (int signum)
|
||||||
|
{
|
||||||
|
if (sig_cinfo != NULL) {
|
||||||
|
if (sig_cinfo->err != NULL) /* turn off trace output */
|
||||||
|
sig_cinfo->err->trace_level = 0;
|
||||||
|
jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
enable_signal_catcher (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
sig_cinfo = cinfo;
|
||||||
|
#ifdef SIGINT /* not all systems have SIGINT */
|
||||||
|
signal(SIGINT, signal_catcher);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM /* not all systems have SIGTERM */
|
||||||
|
signal(SIGTERM, signal_catcher);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optional progress monitor: display a percent-done figure on stderr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
progress_monitor (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
|
||||||
|
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
|
||||||
|
int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
|
||||||
|
|
||||||
|
if (percent_done != prog->percent_done) {
|
||||||
|
prog->percent_done = percent_done;
|
||||||
|
if (total_passes > 1) {
|
||||||
|
fprintf(stderr, "\rPass %d/%d: %3d%% ",
|
||||||
|
prog->pub.completed_passes + prog->completed_extra_passes + 1,
|
||||||
|
total_passes, percent_done);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\r %3d%% ", percent_done);
|
||||||
|
}
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
|
||||||
|
{
|
||||||
|
/* Enable progress display, unless trace output is on */
|
||||||
|
if (cinfo->err->trace_level == 0) {
|
||||||
|
progress->pub.progress_monitor = progress_monitor;
|
||||||
|
progress->completed_extra_passes = 0;
|
||||||
|
progress->total_extra_passes = 0;
|
||||||
|
progress->percent_done = -1;
|
||||||
|
cinfo->progress = &progress->pub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
end_progress_monitor (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Clear away progress display */
|
||||||
|
if (cinfo->err->trace_level == 0) {
|
||||||
|
fprintf(stderr, "\r \r");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Case-insensitive matching of possibly-abbreviated keyword switches.
|
||||||
|
* keyword is the constant keyword (must be lower case already),
|
||||||
|
* minchars is length of minimum legal abbreviation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
keymatch (char * arg, const char * keyword, int minchars)
|
||||||
|
{
|
||||||
|
register int ca, ck;
|
||||||
|
register int nmatched = 0;
|
||||||
|
|
||||||
|
while ((ca = *arg++) != '\0') {
|
||||||
|
if ((ck = *keyword++) == '\0')
|
||||||
|
return FALSE; /* arg longer than keyword, no good */
|
||||||
|
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||||
|
ca = tolower(ca);
|
||||||
|
if (ca != ck)
|
||||||
|
return FALSE; /* no good */
|
||||||
|
nmatched++; /* count matched characters */
|
||||||
|
}
|
||||||
|
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||||
|
if (nmatched < minchars)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE; /* A-OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines to establish binary I/O mode for stdin and stdout.
|
||||||
|
* Non-Unix systems often require some hacking to get out of text mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(FILE *)
|
||||||
|
read_stdin (void)
|
||||||
|
{
|
||||||
|
FILE * input_file = stdin;
|
||||||
|
|
||||||
|
#ifdef USE_SETMODE /* need to hack file mode? */
|
||||||
|
setmode(fileno(stdin), O_BINARY);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
|
||||||
|
if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "Cannot reopen stdin\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return input_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(FILE *)
|
||||||
|
write_stdout (void)
|
||||||
|
{
|
||||||
|
FILE * output_file = stdout;
|
||||||
|
|
||||||
|
#ifdef USE_SETMODE /* need to hack file mode? */
|
||||||
|
setmode(fileno(stdout), O_BINARY);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
|
||||||
|
if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "Cannot reopen stdout\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return output_file;
|
||||||
|
}
|
||||||
184
cdjpeg.h
Normal file
184
cdjpeg.h
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* cdjpeg.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains common declarations for the sample applications
|
||||||
|
* cjpeg and djpeg. It is NOT used by the core JPEG library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
|
||||||
|
#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jerror.h" /* get library error codes too */
|
||||||
|
#include "cderror.h" /* get application-specific error codes */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Object interface for cjpeg's source file decoding modules
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct cjpeg_source_struct * cjpeg_source_ptr;
|
||||||
|
|
||||||
|
struct cjpeg_source_struct {
|
||||||
|
JMETHOD(void, start_input, (j_compress_ptr cinfo,
|
||||||
|
cjpeg_source_ptr sinfo));
|
||||||
|
JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
|
||||||
|
cjpeg_source_ptr sinfo));
|
||||||
|
JMETHOD(void, finish_input, (j_compress_ptr cinfo,
|
||||||
|
cjpeg_source_ptr sinfo));
|
||||||
|
|
||||||
|
FILE *input_file;
|
||||||
|
|
||||||
|
JSAMPARRAY buffer;
|
||||||
|
JDIMENSION buffer_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Object interface for djpeg's output file encoding modules
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct djpeg_dest_struct * djpeg_dest_ptr;
|
||||||
|
|
||||||
|
struct djpeg_dest_struct {
|
||||||
|
/* start_output is called after jpeg_start_decompress finishes.
|
||||||
|
* The color map will be ready at this time, if one is needed.
|
||||||
|
*/
|
||||||
|
JMETHOD(void, start_output, (j_decompress_ptr cinfo,
|
||||||
|
djpeg_dest_ptr dinfo));
|
||||||
|
/* Emit the specified number of pixel rows from the buffer. */
|
||||||
|
JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo,
|
||||||
|
djpeg_dest_ptr dinfo,
|
||||||
|
JDIMENSION rows_supplied));
|
||||||
|
/* Finish up at the end of the image. */
|
||||||
|
JMETHOD(void, finish_output, (j_decompress_ptr cinfo,
|
||||||
|
djpeg_dest_ptr dinfo));
|
||||||
|
|
||||||
|
/* Target file spec; filled in by djpeg.c after object is created. */
|
||||||
|
FILE * output_file;
|
||||||
|
|
||||||
|
/* Output pixel-row buffer. Created by module init or start_output.
|
||||||
|
* Width is cinfo->output_width * cinfo->output_components;
|
||||||
|
* height is buffer_height.
|
||||||
|
*/
|
||||||
|
JSAMPARRAY buffer;
|
||||||
|
JDIMENSION buffer_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cjpeg/djpeg may need to perform extra passes to convert to or from
|
||||||
|
* the source/destination file format. The JPEG library does not know
|
||||||
|
* about these passes, but we'd like them to be counted by the progress
|
||||||
|
* monitor. We use an expanded progress monitor object to hold the
|
||||||
|
* additional pass count.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct cdjpeg_progress_mgr {
|
||||||
|
struct jpeg_progress_mgr pub; /* fields known to JPEG library */
|
||||||
|
int completed_extra_passes; /* extra passes completed */
|
||||||
|
int total_extra_passes; /* total extra */
|
||||||
|
/* last printed percentage stored here to avoid multiple printouts */
|
||||||
|
int percent_done;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#define jinit_read_bmp jIRdBMP
|
||||||
|
#define jinit_write_bmp jIWrBMP
|
||||||
|
#define jinit_read_gif jIRdGIF
|
||||||
|
#define jinit_write_gif jIWrGIF
|
||||||
|
#define jinit_read_ppm jIRdPPM
|
||||||
|
#define jinit_write_ppm jIWrPPM
|
||||||
|
#define jinit_read_rle jIRdRLE
|
||||||
|
#define jinit_write_rle jIWrRLE
|
||||||
|
#define jinit_read_targa jIRdTarga
|
||||||
|
#define jinit_write_targa jIWrTarga
|
||||||
|
#define read_quant_tables RdQTables
|
||||||
|
#define read_scan_script RdScnScript
|
||||||
|
#define set_quant_slots SetQSlots
|
||||||
|
#define set_sample_factors SetSFacts
|
||||||
|
#define read_color_map RdCMap
|
||||||
|
#define enable_signal_catcher EnSigCatcher
|
||||||
|
#define start_progress_monitor StProgMon
|
||||||
|
#define end_progress_monitor EnProgMon
|
||||||
|
#define read_stdin RdStdin
|
||||||
|
#define write_stdout WrStdout
|
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||||
|
|
||||||
|
/* Module selection routines for I/O modules. */
|
||||||
|
|
||||||
|
EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo,
|
||||||
|
boolean is_os2));
|
||||||
|
EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* cjpeg support routines (in rdswitch.c) */
|
||||||
|
|
||||||
|
EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
|
||||||
|
int scale_factor, boolean force_baseline));
|
||||||
|
EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
|
||||||
|
EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
|
||||||
|
EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));
|
||||||
|
|
||||||
|
/* djpeg support routines (in rdcolmap.c) */
|
||||||
|
|
||||||
|
EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile));
|
||||||
|
|
||||||
|
/* common support routines (in cdjpeg.c) */
|
||||||
|
|
||||||
|
EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo));
|
||||||
|
EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo,
|
||||||
|
cd_progress_ptr progress));
|
||||||
|
EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo));
|
||||||
|
EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars));
|
||||||
|
EXTERN(FILE *) read_stdin JPP((void));
|
||||||
|
EXTERN(FILE *) write_stdout JPP((void));
|
||||||
|
|
||||||
|
/* miscellaneous useful macros */
|
||||||
|
|
||||||
|
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||||
|
#define READ_BINARY "r"
|
||||||
|
#define WRITE_BINARY "w"
|
||||||
|
#else
|
||||||
|
#ifdef VMS /* VMS is very nonstandard */
|
||||||
|
#define READ_BINARY "rb", "ctx=stm"
|
||||||
|
#define WRITE_BINARY "wb", "ctx=stm"
|
||||||
|
#else /* standard ANSI-compliant case */
|
||||||
|
#define READ_BINARY "rb"
|
||||||
|
#define WRITE_BINARY "wb"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||||
|
#define EXIT_FAILURE 1
|
||||||
|
#endif
|
||||||
|
#ifndef EXIT_SUCCESS
|
||||||
|
#ifdef VMS
|
||||||
|
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
|
||||||
|
#else
|
||||||
|
#define EXIT_SUCCESS 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef EXIT_WARNING
|
||||||
|
#ifdef VMS
|
||||||
|
#define EXIT_WARNING 1 /* VMS is very nonstandard */
|
||||||
|
#else
|
||||||
|
#define EXIT_WARNING 2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
217
change.log
Normal file
217
change.log
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
CHANGE LOG for Independent JPEG Group's JPEG software
|
||||||
|
|
||||||
|
|
||||||
|
Version 6b 27-Mar-1998
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
jpegtran has new features for lossless image transformations (rotation
|
||||||
|
and flipping) as well as "lossless" reduction to grayscale.
|
||||||
|
|
||||||
|
jpegtran now copies comments by default; it has a -copy switch to enable
|
||||||
|
copying all APPn blocks as well, or to suppress comments. (Formerly it
|
||||||
|
always suppressed comments and APPn blocks.) jpegtran now also preserves
|
||||||
|
JFIF version and resolution information.
|
||||||
|
|
||||||
|
New decompressor library feature: COM and APPn markers found in the input
|
||||||
|
file can be saved in memory for later use by the application. (Before,
|
||||||
|
you had to code this up yourself with a custom marker processor.)
|
||||||
|
|
||||||
|
There is an unused field "void * client_data" now in compress and decompress
|
||||||
|
parameter structs; this may be useful in some applications.
|
||||||
|
|
||||||
|
JFIF version number information is now saved by the decoder and accepted by
|
||||||
|
the encoder. jpegtran uses this to copy the source file's version number,
|
||||||
|
to ensure "jpegtran -copy all" won't create bogus files that contain JFXX
|
||||||
|
extensions but claim to be version 1.01. Applications that generate their
|
||||||
|
own JFXX extension markers also (finally) have a supported way to cause the
|
||||||
|
encoder to emit JFIF version number 1.02.
|
||||||
|
|
||||||
|
djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather
|
||||||
|
than as unknown APP0 markers.
|
||||||
|
|
||||||
|
In -verbose mode, djpeg and rdjpgcom will try to print the contents of
|
||||||
|
APP12 markers as text. Some digital cameras store useful text information
|
||||||
|
in APP12 markers.
|
||||||
|
|
||||||
|
Handling of truncated data streams is more robust: blocks beyond the one in
|
||||||
|
which the error occurs will be output as uniform gray, or left unchanged
|
||||||
|
if decoding a progressive JPEG. The appearance no longer depends on the
|
||||||
|
Huffman tables being used.
|
||||||
|
|
||||||
|
Huffman tables are checked for validity much more carefully than before.
|
||||||
|
|
||||||
|
To avoid the Unisys LZW patent, djpeg's GIF output capability has been
|
||||||
|
changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
|
||||||
|
has been removed altogether. We're not happy about it either, but there
|
||||||
|
seems to be no good alternative.
|
||||||
|
|
||||||
|
The configure script now supports building libjpeg as a shared library
|
||||||
|
on many flavors of Unix (all the ones that GNU libtool knows how to
|
||||||
|
build shared libraries for). Use "./configure --enable-shared" to
|
||||||
|
try this out.
|
||||||
|
|
||||||
|
New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio.
|
||||||
|
Also, a jconfig file and a build script for Metrowerks CodeWarrior
|
||||||
|
on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there
|
||||||
|
are miscellaneous other minor improvements in the makefiles.
|
||||||
|
|
||||||
|
jmemmac.c now knows how to create temporary files following Mac System 7
|
||||||
|
conventions.
|
||||||
|
|
||||||
|
djpeg's -map switch is now able to read raw-format PPM files reliably.
|
||||||
|
|
||||||
|
cjpeg -progressive -restart no longer generates any unnecessary DRI markers.
|
||||||
|
|
||||||
|
Multiple calls to jpeg_simple_progression for a single JPEG object
|
||||||
|
no longer leak memory.
|
||||||
|
|
||||||
|
|
||||||
|
Version 6a 7-Feb-96
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Library initialization sequence modified to detect version mismatches
|
||||||
|
and struct field packing mismatches between library and calling application.
|
||||||
|
This change requires applications to be recompiled, but does not require
|
||||||
|
any application source code change.
|
||||||
|
|
||||||
|
All routine declarations changed to the style "GLOBAL(type) name ...",
|
||||||
|
that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the
|
||||||
|
routine's return type as an argument. This makes it possible to add
|
||||||
|
Microsoft-style linkage keywords to all the routines by changing just
|
||||||
|
these macros. Note that any application code that was using these macros
|
||||||
|
will have to be changed.
|
||||||
|
|
||||||
|
DCT coefficient quantization tables are now stored in normal array order
|
||||||
|
rather than zigzag order. Application code that calls jpeg_add_quant_table,
|
||||||
|
or otherwise manipulates quantization tables directly, will need to be
|
||||||
|
changed. If you need to make such code work with either older or newer
|
||||||
|
versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is
|
||||||
|
recommended.
|
||||||
|
|
||||||
|
djpeg's trace capability now dumps DQT tables in natural order, not zigzag
|
||||||
|
order. This allows the trace output to be made into a "-qtables" file
|
||||||
|
more easily.
|
||||||
|
|
||||||
|
New system-dependent memory manager module for use on Apple Macintosh.
|
||||||
|
|
||||||
|
Fix bug in cjpeg's -smooth option: last one or two scanlines would be
|
||||||
|
duplicates of the prior line unless the image height mod 16 was 1 or 2.
|
||||||
|
|
||||||
|
Repair minor problems in VMS, BCC, MC6 makefiles.
|
||||||
|
|
||||||
|
New configure script based on latest GNU Autoconf.
|
||||||
|
|
||||||
|
Correct the list of include files needed by MetroWerks C for ccommand().
|
||||||
|
|
||||||
|
Numerous small documentation updates.
|
||||||
|
|
||||||
|
|
||||||
|
Version 6 2-Aug-95
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Progressive JPEG support: library can read and write full progressive JPEG
|
||||||
|
files. A "buffered image" mode supports incremental decoding for on-the-fly
|
||||||
|
display of progressive images. Simply recompiling an existing IJG-v5-based
|
||||||
|
decoder with v6 should allow it to read progressive files, though of course
|
||||||
|
without any special progressive display.
|
||||||
|
|
||||||
|
New "jpegtran" application performs lossless transcoding between different
|
||||||
|
JPEG formats; primarily, it can be used to convert baseline to progressive
|
||||||
|
JPEG and vice versa. In support of jpegtran, the library now allows lossless
|
||||||
|
reading and writing of JPEG files as DCT coefficient arrays. This ability
|
||||||
|
may be of use in other applications.
|
||||||
|
|
||||||
|
Notes for programmers:
|
||||||
|
* We changed jpeg_start_decompress() to be able to suspend; this makes all
|
||||||
|
decoding modes available to suspending-input applications. However,
|
||||||
|
existing applications that use suspending input will need to be changed
|
||||||
|
to check the return value from jpeg_start_decompress(). You don't need to
|
||||||
|
do anything if you don't use a suspending data source.
|
||||||
|
* We changed the interface to the virtual array routines: access_virt_array
|
||||||
|
routines now take a count of the number of rows to access this time. The
|
||||||
|
last parameter to request_virt_array routines is now interpreted as the
|
||||||
|
maximum number of rows that may be accessed at once, but not necessarily
|
||||||
|
the height of every access.
|
||||||
|
|
||||||
|
|
||||||
|
Version 5b 15-Mar-95
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Correct bugs with grayscale images having v_samp_factor > 1.
|
||||||
|
|
||||||
|
jpeg_write_raw_data() now supports output suspension.
|
||||||
|
|
||||||
|
Correct bugs in "configure" script for case of compiling in
|
||||||
|
a directory other than the one containing the source files.
|
||||||
|
|
||||||
|
Repair bug in jquant1.c: sometimes didn't use as many colors as it could.
|
||||||
|
|
||||||
|
Borland C makefile and jconfig file work under either MS-DOS or OS/2.
|
||||||
|
|
||||||
|
Miscellaneous improvements to documentation.
|
||||||
|
|
||||||
|
|
||||||
|
Version 5a 7-Dec-94
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Changed color conversion roundoff behavior so that grayscale values are
|
||||||
|
represented exactly. (This causes test image files to change.)
|
||||||
|
|
||||||
|
Make ordered dither use 16x16 instead of 4x4 pattern for a small quality
|
||||||
|
improvement.
|
||||||
|
|
||||||
|
New configure script based on latest GNU Autoconf.
|
||||||
|
Fix configure script to handle CFLAGS correctly.
|
||||||
|
Rename *.auto files to *.cfg, so that configure script still works if
|
||||||
|
file names have been truncated for DOS.
|
||||||
|
|
||||||
|
Fix bug in rdbmp.c: didn't allow for extra data between header and image.
|
||||||
|
|
||||||
|
Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data.
|
||||||
|
|
||||||
|
Fix several bugs in rdrle.c.
|
||||||
|
|
||||||
|
NEED_SHORT_EXTERNAL_NAMES option was broken.
|
||||||
|
|
||||||
|
Revise jerror.h/jerror.c for more flexibility in message table.
|
||||||
|
|
||||||
|
Repair oversight in jmemname.c NO_MKTEMP case: file could be there
|
||||||
|
but unreadable.
|
||||||
|
|
||||||
|
|
||||||
|
Version 5 24-Sep-94
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Version 5 represents a nearly complete redesign and rewrite of the IJG
|
||||||
|
software. Major user-visible changes include:
|
||||||
|
* Automatic configuration simplifies installation for most Unix systems.
|
||||||
|
* A range of speed vs. image quality tradeoffs are supported.
|
||||||
|
This includes resizing of an image during decompression: scaling down
|
||||||
|
by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
|
||||||
|
* New programs rdjpgcom and wrjpgcom allow insertion and extraction
|
||||||
|
of text comments in a JPEG file.
|
||||||
|
|
||||||
|
The application programmer's interface to the library has changed completely.
|
||||||
|
Notable improvements include:
|
||||||
|
* We have eliminated the use of callback routines for handling the
|
||||||
|
uncompressed image data. The application now sees the library as a
|
||||||
|
set of routines that it calls to read or write image data on a
|
||||||
|
scanline-by-scanline basis.
|
||||||
|
* The application image data is represented in a conventional interleaved-
|
||||||
|
pixel format, rather than as a separate array for each color channel.
|
||||||
|
This can save a copying step in many programs.
|
||||||
|
* The handling of compressed data has been cleaned up: the application can
|
||||||
|
supply routines to source or sink the compressed data. It is possible to
|
||||||
|
suspend processing on source/sink buffer overrun, although this is not
|
||||||
|
supported in all operating modes.
|
||||||
|
* All static state has been eliminated from the library, so that multiple
|
||||||
|
instances of compression or decompression can be active concurrently.
|
||||||
|
* JPEG abbreviated datastream formats are supported, ie, quantization and
|
||||||
|
Huffman tables can be stored separately from the image data.
|
||||||
|
* And not only that, but the documentation of the library has improved
|
||||||
|
considerably!
|
||||||
|
|
||||||
|
|
||||||
|
The last widely used release before the version 5 rewrite was version 4A of
|
||||||
|
18-Feb-93. Change logs before that point have been discarded, since they
|
||||||
|
are not of much interest after the rewrite.
|
||||||
290
cjpeg.1
290
cjpeg.1
@@ -1,13 +1,10 @@
|
|||||||
.TH CJPEG 1 "11 December 1991"
|
.TH CJPEG 1 "20 March 1998"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cjpeg \- compress an image file to a JPEG file
|
cjpeg \- compress an image file to a JPEG file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B cjpeg
|
.B cjpeg
|
||||||
[
|
[
|
||||||
.BI \-Q " quality"
|
.I options
|
||||||
]
|
|
||||||
[
|
|
||||||
.B \-oTIad
|
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
.I filename
|
.I filename
|
||||||
@@ -18,113 +15,278 @@ cjpeg \- compress an image file to a JPEG file
|
|||||||
.B cjpeg
|
.B cjpeg
|
||||||
compresses the named image file, or the standard input if no file is
|
compresses the named image file, or the standard input if no file is
|
||||||
named, and produces a JPEG/JFIF file on the standard output.
|
named, and produces a JPEG/JFIF file on the standard output.
|
||||||
The currently supported image file formats are: PPM (PBMPLUS color
|
The currently supported input file formats are: PPM (PBMPLUS color
|
||||||
format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster
|
format), PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster
|
||||||
Toolkit format). (RLE is supported only if the URT library is available.)
|
Toolkit format). (RLE is supported only if the URT library is available.)
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
All switch names may be abbreviated; for example,
|
||||||
|
.B \-grayscale
|
||||||
|
may be written
|
||||||
|
.B \-gray
|
||||||
|
or
|
||||||
|
.BR \-gr .
|
||||||
|
Most of the "basic" switches can be abbreviated to as little as one letter.
|
||||||
|
Upper and lower case are equivalent (thus
|
||||||
|
.B \-BMP
|
||||||
|
is the same as
|
||||||
|
.BR \-bmp ).
|
||||||
|
British spellings are also accepted (e.g.,
|
||||||
|
.BR \-greyscale ),
|
||||||
|
though for brevity these are not mentioned below.
|
||||||
|
.PP
|
||||||
|
The basic switches are:
|
||||||
.TP
|
.TP
|
||||||
.BI \-Q " quality"
|
.BI \-quality " N"
|
||||||
Scale quantization tables to adjust image quality. Quality is 0 (worst) to
|
Scale quantization tables to adjust image quality. Quality is 0 (worst) to
|
||||||
100 (best); default is 75. (See below for more info.)
|
100 (best); default is 75. (See below for more info.)
|
||||||
.TP
|
.TP
|
||||||
.B \-o
|
.B \-grayscale
|
||||||
|
Create monochrome JPEG file from color input. Be sure to use this switch when
|
||||||
|
compressing a grayscale BMP file, because
|
||||||
|
.B cjpeg
|
||||||
|
isn't bright enough to notice whether a BMP file uses only shades of gray.
|
||||||
|
By saying
|
||||||
|
.BR \-grayscale ,
|
||||||
|
you'll get a smaller JPEG file that takes less time to process.
|
||||||
|
.TP
|
||||||
|
.B \-optimize
|
||||||
Perform optimization of entropy encoding parameters. Without this, default
|
Perform optimization of entropy encoding parameters. Without this, default
|
||||||
encoding parameters are used.
|
encoding parameters are used.
|
||||||
.B \-o
|
.B \-optimize
|
||||||
usually makes the JPEG file a little smaller, but
|
usually makes the JPEG file a little smaller, but
|
||||||
.B cjpeg
|
.B cjpeg
|
||||||
runs much slower. Image quality and speed of decompression are unaffected by
|
runs somewhat slower and needs much more memory. Image quality and speed of
|
||||||
.BR \-o .
|
decompression are unaffected by
|
||||||
|
.BR \-optimize .
|
||||||
.TP
|
.TP
|
||||||
.B \-T
|
.B \-progressive
|
||||||
|
Create progressive JPEG file (see below).
|
||||||
|
.TP
|
||||||
|
.B \-targa
|
||||||
Input file is Targa format. Targa files that contain an "identification"
|
Input file is Targa format. Targa files that contain an "identification"
|
||||||
field will not be automatically recognized by
|
field will not be automatically recognized by
|
||||||
.BR cjpeg ;
|
.BR cjpeg ;
|
||||||
for such files you must specify
|
for such files you must specify
|
||||||
.B \-T
|
.B \-targa
|
||||||
to force
|
to make
|
||||||
.B cjpeg
|
.B cjpeg
|
||||||
to treat the input as Targa format.
|
treat the input as Targa format.
|
||||||
.TP
|
For most Targa files, you won't need this switch.
|
||||||
.B \-I
|
|
||||||
Generate noninterleaved JPEG file (not yet supported).
|
|
||||||
.TP
|
|
||||||
.B \-a
|
|
||||||
Use arithmetic coding rather than Huffman coding (not currently
|
|
||||||
supported for legal reasons).
|
|
||||||
.TP
|
|
||||||
.B \-d
|
|
||||||
Enable debug printout. More
|
|
||||||
.BR \-d 's
|
|
||||||
give more output. Also, version information is printed at startup.
|
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
.B \-Q
|
.B \-quality
|
||||||
switch lets you trade off compressed file size against quality of the
|
switch lets you trade off compressed file size against quality of the
|
||||||
reconstructed image: the higher the
|
reconstructed image: the higher the quality setting, the larger the JPEG file,
|
||||||
.B \-Q
|
and the closer the output image will be to the original input. Normally you
|
||||||
setting, the larger the JPEG file, and the closer the output image will be to
|
want to use the lowest quality setting (smallest file) that decompresses into
|
||||||
the original input. Normally you want to use the lowest
|
something visually indistinguishable from the original image. For this
|
||||||
.B \-Q
|
purpose the quality setting should be between 50 and 95; the default of 75 is
|
||||||
setting (smallest file) that decompresses into something visually
|
often about right. If you see defects at
|
||||||
indistinguishable from the original image. For this purpose the
|
.B \-quality
|
||||||
.B \-Q
|
|
||||||
setting should be between 50 and 95; the default of 75 is often about right.
|
|
||||||
If you see defects at
|
|
||||||
.B \-Q
|
|
||||||
75, then go up 5 or 10 counts at a time until you are happy with the output
|
75, then go up 5 or 10 counts at a time until you are happy with the output
|
||||||
image. (The optimal setting will vary from one image to another.)
|
image. (The optimal setting will vary from one image to another.)
|
||||||
.PP
|
.PP
|
||||||
.B \-Q
|
.B \-quality
|
||||||
100 will generate a quantization table of all 1's, eliminating loss in the
|
100 will generate a quantization table of all 1's, minimizing loss in the
|
||||||
quantization step (but there is still information loss in subsampling, as well
|
quantization step (but there is still information loss in subsampling, as well
|
||||||
as roundoff error). This setting is mainly of interest for experimental
|
as roundoff error). This setting is mainly of interest for experimental
|
||||||
purposes.
|
purposes. Quality values above about 95 are
|
||||||
.B \-Q
|
|
||||||
values above about 95 are
|
|
||||||
.B not
|
.B not
|
||||||
recommended for normal use; the compressed file size goes up dramatically for
|
recommended for normal use; the compressed file size goes up dramatically for
|
||||||
hardly any gain in output image quality.
|
hardly any gain in output image quality.
|
||||||
.PP
|
.PP
|
||||||
In the other direction,
|
In the other direction, quality values below 50 will produce very small files
|
||||||
.B \-Q
|
of low image quality. Settings around 5 to 10 might be useful in preparing an
|
||||||
values below 50 will produce very small files of low image quality. Settings
|
index of a large image library, for example. Try
|
||||||
around 5 to 10 might be useful in preparing an index of a large image library,
|
.B \-quality
|
||||||
for example. Try
|
2 (or so) for some amusing Cubist effects. (Note: quality
|
||||||
.B \-Q
|
|
||||||
2 (or so) for some amusing Cubist effects. (Note:
|
|
||||||
.B \-Q
|
|
||||||
values below about 25 generate 2-byte quantization tables, which are
|
values below about 25 generate 2-byte quantization tables, which are
|
||||||
considered optional in the JPEG standard.
|
considered optional in the JPEG standard.
|
||||||
.B cjpeg
|
.B cjpeg
|
||||||
emits a warning message when you give such a
|
emits a warning message when you give such a quality value, because some
|
||||||
.B \-Q
|
other JPEG programs may be unable to decode the resulting file. Use
|
||||||
value, because some commercial JPEG programs may be unable to decode the
|
.B \-baseline
|
||||||
resulting file.)
|
if you need to ensure compatibility at low quality values.)
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B \-progressive
|
||||||
|
switch creates a "progressive JPEG" file. In this type of JPEG file, the data
|
||||||
|
is stored in multiple scans of increasing quality. If the file is being
|
||||||
|
transmitted over a slow communications link, the decoder can use the first
|
||||||
|
scan to display a low-quality image very quickly, and can then improve the
|
||||||
|
display with each subsequent scan. The final image is exactly equivalent to a
|
||||||
|
standard JPEG file of the same quality setting, and the total file size is
|
||||||
|
about the same --- often a little smaller.
|
||||||
|
.B Caution:
|
||||||
|
progressive JPEG is not yet widely implemented, so many decoders will be
|
||||||
|
unable to view a progressive JPEG file at all.
|
||||||
|
.PP
|
||||||
|
Switches for advanced users:
|
||||||
|
.TP
|
||||||
|
.B \-dct int
|
||||||
|
Use integer DCT method (default).
|
||||||
|
.TP
|
||||||
|
.B \-dct fast
|
||||||
|
Use fast integer DCT (less accurate).
|
||||||
|
.TP
|
||||||
|
.B \-dct float
|
||||||
|
Use floating-point DCT method.
|
||||||
|
The float method is very slightly more accurate than the int method, but is
|
||||||
|
much slower unless your machine has very fast floating-point hardware. Also
|
||||||
|
note that results of the floating-point method may vary slightly across
|
||||||
|
machines, while the integer methods should give the same results everywhere.
|
||||||
|
The fast integer method is much less accurate than the other two.
|
||||||
|
.TP
|
||||||
|
.BI \-restart " N"
|
||||||
|
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
|
||||||
|
attached to the number.
|
||||||
|
.B \-restart 0
|
||||||
|
(the default) means no restart markers.
|
||||||
|
.TP
|
||||||
|
.BI \-smooth " N"
|
||||||
|
Smooth the input image to eliminate dithering noise. N, ranging from 1 to
|
||||||
|
100, indicates the strength of smoothing. 0 (the default) means no smoothing.
|
||||||
|
.TP
|
||||||
|
.BI \-maxmemory " N"
|
||||||
|
Set limit for amount of memory to use in processing large images. Value is
|
||||||
|
in thousands of bytes, or millions of bytes if "M" is attached to the
|
||||||
|
number. For example,
|
||||||
|
.B \-max 4m
|
||||||
|
selects 4000000 bytes. If more space is needed, temporary files will be used.
|
||||||
|
.TP
|
||||||
|
.BI \-outfile " name"
|
||||||
|
Send output image to the named file, not to standard output.
|
||||||
|
.TP
|
||||||
|
.B \-verbose
|
||||||
|
Enable debug printout. More
|
||||||
|
.BR \-v 's
|
||||||
|
give more output. Also, version information is printed at startup.
|
||||||
|
.TP
|
||||||
|
.B \-debug
|
||||||
|
Same as
|
||||||
|
.BR \-verbose .
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B \-restart
|
||||||
|
option inserts extra markers that allow a JPEG decoder to resynchronize after
|
||||||
|
a transmission error. Without restart markers, any damage to a compressed
|
||||||
|
file will usually ruin the image from the point of the error to the end of the
|
||||||
|
image; with restart markers, the damage is usually confined to the portion of
|
||||||
|
the image up to the next restart marker. Of course, the restart markers
|
||||||
|
occupy extra space. We recommend
|
||||||
|
.B \-restart 1
|
||||||
|
for images that will be transmitted across unreliable networks such as Usenet.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B \-smooth
|
||||||
|
option filters the input to eliminate fine-scale noise. This is often useful
|
||||||
|
when converting dithered images to JPEG: a moderate smoothing factor of 10 to
|
||||||
|
50 gets rid of dithering patterns in the input file, resulting in a smaller
|
||||||
|
JPEG file and a better-looking image. Too large a smoothing factor will
|
||||||
|
visibly blur the image, however.
|
||||||
|
.PP
|
||||||
|
Switches for wizards:
|
||||||
|
.TP
|
||||||
|
.B \-baseline
|
||||||
|
Force baseline-compatible quantization tables to be generated. This clamps
|
||||||
|
quantization values to 8 bits even at low quality settings. (This switch is
|
||||||
|
poorly named, since it does not ensure that the output is actually baseline
|
||||||
|
JPEG. For example, you can use
|
||||||
|
.B \-baseline
|
||||||
|
and
|
||||||
|
.B \-progressive
|
||||||
|
together.)
|
||||||
|
.TP
|
||||||
|
.BI \-qtables " file"
|
||||||
|
Use the quantization tables given in the specified text file.
|
||||||
|
.TP
|
||||||
|
.BI \-qslots " N[,...]"
|
||||||
|
Select which quantization table to use for each color component.
|
||||||
|
.TP
|
||||||
|
.BI \-sample " HxV[,...]"
|
||||||
|
Set JPEG sampling factors for each color component.
|
||||||
|
.TP
|
||||||
|
.BI \-scans " file"
|
||||||
|
Use the scan script given in the specified text file.
|
||||||
|
.PP
|
||||||
|
The "wizard" switches are intended for experimentation with JPEG. If you
|
||||||
|
don't know what you are doing, \fBdon't use them\fR. These switches are
|
||||||
|
documented further in the file wizard.doc.
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.LP
|
.LP
|
||||||
This example compresses the PPM file foo.ppm with a quality factor of
|
This example compresses the PPM file foo.ppm with a quality factor of
|
||||||
60 and saves the output as foo.jpg:
|
60 and saves the output as foo.jpg:
|
||||||
.IP
|
.IP
|
||||||
.B cjpeg \-Q
|
.B cjpeg \-quality
|
||||||
.I 60 foo.ppm
|
.I 60 foo.ppm
|
||||||
.B >
|
.B >
|
||||||
.I foo.jpg
|
.I foo.jpg
|
||||||
|
.SH HINTS
|
||||||
|
Color GIF files are not the ideal input for JPEG; JPEG is really intended for
|
||||||
|
compressing full-color (24-bit) images. In particular, don't try to convert
|
||||||
|
cartoons, line drawings, and other images that have only a few distinct
|
||||||
|
colors. GIF works great on these, JPEG does not. If you want to convert a
|
||||||
|
GIF to JPEG, you should experiment with
|
||||||
|
.BR cjpeg 's
|
||||||
|
.B \-quality
|
||||||
|
and
|
||||||
|
.B \-smooth
|
||||||
|
options to get a satisfactory conversion.
|
||||||
|
.B \-smooth 10
|
||||||
|
or so is often helpful.
|
||||||
|
.PP
|
||||||
|
Avoid running an image through a series of JPEG compression/decompression
|
||||||
|
cycles. Image quality loss will accumulate; after ten or so cycles the image
|
||||||
|
may be noticeably worse than it was after one cycle. It's best to use a
|
||||||
|
lossless format while manipulating an image, then convert to JPEG format when
|
||||||
|
you are ready to file the image away.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B \-optimize
|
||||||
|
option to
|
||||||
|
.B cjpeg
|
||||||
|
is worth using when you are making a "final" version for posting or archiving.
|
||||||
|
It's also a win when you are using low quality settings to make very small
|
||||||
|
JPEG files; the percentage improvement is often a lot more than it is on
|
||||||
|
larger files. (At present,
|
||||||
|
.B \-optimize
|
||||||
|
mode is always selected when generating progressive JPEG files.)
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
.TP
|
||||||
|
.B JPEGMEM
|
||||||
|
If this environment variable is set, its value is the default memory limit.
|
||||||
|
The value is specified as described for the
|
||||||
|
.B \-maxmemory
|
||||||
|
switch.
|
||||||
|
.B JPEGMEM
|
||||||
|
overrides the default value specified when the program was compiled, and
|
||||||
|
itself is overridden by an explicit
|
||||||
|
.BR \-maxmemory .
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR djpeg (1)
|
.BR djpeg (1),
|
||||||
|
.BR jpegtran (1),
|
||||||
|
.BR rdjpgcom (1),
|
||||||
|
.BR wrjpgcom (1)
|
||||||
|
.br
|
||||||
|
.BR ppm (5),
|
||||||
|
.BR pgm (5)
|
||||||
.br
|
.br
|
||||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||||
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
|
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Independent JPEG Group
|
Independent JPEG Group
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Arithmetic coding and interleaved output not yet supported.
|
Arithmetic coding is not supported for legal reasons.
|
||||||
.PP
|
.PP
|
||||||
Not all variants of Targa file format are supported.
|
GIF input files are no longer supported, to avoid the Unisys LZW patent.
|
||||||
|
Use a Unisys-licensed program if you need to read a GIF file. (Conversion
|
||||||
|
of GIF files to JPEG is usually a bad idea anyway.)
|
||||||
|
.PP
|
||||||
|
Not all variants of BMP and Targa file formats are supported.
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
.B -T
|
.B \-targa
|
||||||
switch is not a bug, it's a feature. (It would be a bug if the Targa format
|
switch is not a bug, it's a feature. (It would be a bug if the Targa format
|
||||||
designers had not been clueless.)
|
designers had not been clueless.)
|
||||||
.PP
|
.PP
|
||||||
Not as fast as we'd like.
|
Still not as fast as we'd like.
|
||||||
|
|||||||
668
cjpeg.c
Normal file
668
cjpeg.c
Normal file
@@ -0,0 +1,668 @@
|
|||||||
|
/*
|
||||||
|
* cjpeg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : August 23, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains a command-line user interface for the JPEG compressor.
|
||||||
|
* It should work on any system with Unix- or MS-DOS-style command lines.
|
||||||
|
*
|
||||||
|
* Two different command line styles are permitted, depending on the
|
||||||
|
* compile-time switch TWO_FILE_COMMANDLINE:
|
||||||
|
* cjpeg [options] inputfile outputfile
|
||||||
|
* cjpeg [options] [inputfile]
|
||||||
|
* In the second style, output is always to standard output, which you'd
|
||||||
|
* normally redirect to a file or pipe to some other program. Input is
|
||||||
|
* either from a named file or from standard input (typically redirected).
|
||||||
|
* The second style is convenient on Unix but is unhelpful on systems that
|
||||||
|
* don't support pipes. Also, you MUST use the first style if your system
|
||||||
|
* doesn't do binary I/O to stdin/stdout.
|
||||||
|
* To simplify script writing, the "-outfile" switch is provided. The syntax
|
||||||
|
* cjpeg [options] -outfile outputfile inputfile
|
||||||
|
* works regardless of which command line style is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||||
|
#include "jversion.h" /* for version message */
|
||||||
|
|
||||||
|
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||||
|
#ifdef __MWERKS__
|
||||||
|
#include <SIOUX.h> /* Metrowerks needs this */
|
||||||
|
#include <console.h> /* ... and this */
|
||||||
|
#endif
|
||||||
|
#ifdef THINK_C
|
||||||
|
#include <console.h> /* Think declares it here */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the add-on message string table. */
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) string ,
|
||||||
|
|
||||||
|
static const char * const cdjpeg_message_table[] = {
|
||||||
|
#include "cderror.h"
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine determines what format the input file is,
|
||||||
|
* and selects the appropriate input-reading module.
|
||||||
|
*
|
||||||
|
* To determine which family of input formats the file belongs to,
|
||||||
|
* we may look only at the first byte of the file, since C does not
|
||||||
|
* guarantee that more than one character can be pushed back with ungetc.
|
||||||
|
* Looking at additional bytes would require one of these approaches:
|
||||||
|
* 1) assume we can fseek() the input file (fails for piped input);
|
||||||
|
* 2) assume we can push back more than one character (works in
|
||||||
|
* some C implementations, but unportable);
|
||||||
|
* 3) provide our own buffering (breaks input readers that want to use
|
||||||
|
* stdio directly, such as the RLE library);
|
||||||
|
* or 4) don't put back the data, and modify the input_init methods to assume
|
||||||
|
* they start reading after the start of file (also breaks RLE library).
|
||||||
|
* #1 is attractive for MS-DOS but is untenable on Unix.
|
||||||
|
*
|
||||||
|
* The most portable solution for file types that can't be identified by their
|
||||||
|
* first byte is to make the user tell us what they are. This is also the
|
||||||
|
* only approach for "raw" file types that contain only arbitrary values.
|
||||||
|
* We presently apply this method for Targa files. Most of the time Targa
|
||||||
|
* files start with 0x00, so we recognize that case. Potentially, however,
|
||||||
|
* a Targa file could start with any byte value (byte 0 is the length of the
|
||||||
|
* seldom-used ID field), so we provide a switch to force Targa input mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static boolean is_targa; /* records user -targa switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(cjpeg_source_ptr)
|
||||||
|
select_file_type (j_compress_ptr cinfo, FILE * infile)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (is_targa) {
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
return jinit_read_targa(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_TGA_NOTCOMP);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c = getc(infile)) == EOF)
|
||||||
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||||
|
if (ungetc(c, infile) == EOF)
|
||||||
|
ERREXIT(cinfo, JERR_UNGETC_FAILED);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
case 'B':
|
||||||
|
return jinit_read_bmp(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
case 'G':
|
||||||
|
return jinit_read_gif(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
case 'P':
|
||||||
|
return jinit_read_ppm(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
case 'R':
|
||||||
|
return jinit_read_rle(cinfo);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
case 0x00:
|
||||||
|
return jinit_read_targa(cinfo);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; /* suppress compiler warnings */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argument-parsing code.
|
||||||
|
* The switch parser is designed to be useful with DOS-style command line
|
||||||
|
* syntax, ie, intermixed switches and file names, where only the switches
|
||||||
|
* to the left of a given file name affect processing of that file.
|
||||||
|
* The main program in this file doesn't actually use this capability...
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static const char * progname; /* program name for error messages */
|
||||||
|
static char * outfilename; /* for -outfile switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
usage (void)
|
||||||
|
/* complain about bad command line */
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [switches] ", progname);
|
||||||
|
#ifdef TWO_FILE_COMMANDLINE
|
||||||
|
fprintf(stderr, "inputfile outputfile\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "[inputfile]\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||||
|
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
|
||||||
|
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
|
||||||
|
#endif
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
fprintf(stderr, " -progressive Create progressive JPEG file\n");
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Switches for advanced users:\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
|
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||||
|
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||||
|
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||||
|
fprintf(stderr, "Switches for wizards:\n");
|
||||||
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
|
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -baseline Force baseline quantization tables\n");
|
||||||
|
fprintf(stderr, " -qtables file Use quantization tables given in file\n");
|
||||||
|
fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
|
||||||
|
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
|
||||||
|
#endif
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
print_simd_info (FILE * file, char * labelstr, unsigned int simd)
|
||||||
|
{
|
||||||
|
fprintf(file, "%s%s%s%s%s%s\n", labelstr,
|
||||||
|
simd & JSIMD_MMX ? " MMX" : "",
|
||||||
|
simd & JSIMD_3DNOW ? " 3DNow!" : "",
|
||||||
|
simd & JSIMD_SSE ? " SSE" : "",
|
||||||
|
simd & JSIMD_SSE2 ? " SSE2" : "",
|
||||||
|
simd == JSIMD_NONE ? " NONE" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||||
|
int last_file_arg_seen, boolean for_real)
|
||||||
|
/* Parse optional switches.
|
||||||
|
* Returns argv[] index of first file-name argument (== argc if none).
|
||||||
|
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||||
|
* they have presumably been processed in a previous iteration.
|
||||||
|
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||||
|
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int argn;
|
||||||
|
char * arg;
|
||||||
|
int quality; /* -quality parameter */
|
||||||
|
int q_scale_factor; /* scaling percentage for -qtables */
|
||||||
|
boolean force_baseline;
|
||||||
|
boolean simple_progressive;
|
||||||
|
char * qtablefile = NULL; /* saves -qtables filename if any */
|
||||||
|
char * qslotsarg = NULL; /* saves -qslots parm if any */
|
||||||
|
char * samplearg = NULL; /* saves -sample parm if any */
|
||||||
|
char * scansarg = NULL; /* saves -scans parm if any */
|
||||||
|
|
||||||
|
/* Set up default JPEG parameters. */
|
||||||
|
/* Note that default -quality level need not, and does not,
|
||||||
|
* match the default scaling for an explicit -qtables argument.
|
||||||
|
*/
|
||||||
|
quality = 75; /* default -quality value */
|
||||||
|
q_scale_factor = 100; /* default to no scaling for -qtables */
|
||||||
|
force_baseline = FALSE; /* by default, allow 16-bit quantizers */
|
||||||
|
simple_progressive = FALSE;
|
||||||
|
is_targa = FALSE;
|
||||||
|
outfilename = NULL;
|
||||||
|
cinfo->err->trace_level = 0;
|
||||||
|
|
||||||
|
/* Scan command line options, adjust parameters */
|
||||||
|
|
||||||
|
for (argn = 1; argn < argc; argn++) {
|
||||||
|
arg = argv[argn];
|
||||||
|
if (*arg != '-') {
|
||||||
|
/* Not a switch, must be a file name argument */
|
||||||
|
if (argn <= last_file_arg_seen) {
|
||||||
|
outfilename = NULL; /* -outfile applies to just one input file */
|
||||||
|
continue; /* ignore this name if previously processed */
|
||||||
|
}
|
||||||
|
break; /* else done parsing switches */
|
||||||
|
}
|
||||||
|
arg++; /* advance past switch marker character */
|
||||||
|
|
||||||
|
if (keymatch(arg, "arithmetic", 1)) {
|
||||||
|
/* Use arithmetic coding. */
|
||||||
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
|
cinfo->arith_code = TRUE;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "baseline", 1)) {
|
||||||
|
/* Force baseline-compatible output (8-bit quantizer values). */
|
||||||
|
force_baseline = TRUE;
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
} else if (keymatch(arg, "nosimd" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_ALL);
|
||||||
|
} else if (keymatch(arg, "nommx" , 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_MMX);
|
||||||
|
} else if (keymatch(arg, "no3dnow", 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_3DNOW);
|
||||||
|
} else if (keymatch(arg, "nosse" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE);
|
||||||
|
} else if (keymatch(arg, "nosse2" , 6)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE2);
|
||||||
|
#endif /* !JSIMD_MASKFUNC_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) {
|
||||||
|
/* Select DCT algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "int", 1)) {
|
||||||
|
cinfo->dct_method = JDCT_ISLOW;
|
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_IFAST;
|
||||||
|
} else if (keymatch(argv[argn], "float", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_FLOAT;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||||
|
/* Enable debug printouts. */
|
||||||
|
/* On first -d, print version identification */
|
||||||
|
static boolean printed_version = FALSE;
|
||||||
|
|
||||||
|
if (! printed_version) {
|
||||||
|
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
|
||||||
|
JVERSION, JCOPYRIGHT);
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nx86 SIMD extension for IJG JPEG library, version %s\n\n",
|
||||||
|
JPEG_SIMDEXT_VER_STR);
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "SIMD instructions supported by the system :",
|
||||||
|
jpeg_simd_support(NULL));
|
||||||
|
|
||||||
|
fprintf(stderr, "\n === SIMD Operation Modes ===\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Accurate integer DCT (-dct int) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_ISLOW));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Fast integer DCT (-dct fast) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_IFAST));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Floating-point DCT (-dct float) :",
|
||||||
|
jpeg_simd_forward_dct(cinfo, JDCT_FLOAT));
|
||||||
|
#endif
|
||||||
|
print_simd_info(stderr, "Downsampling (-sample 2x2 or 2x1) :",
|
||||||
|
jpeg_simd_downsampler(cinfo));
|
||||||
|
print_simd_info(stderr, "Colorspace conversion (RGB->YCbCr) :",
|
||||||
|
jpeg_simd_color_converter(cinfo));
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
printed_version = TRUE;
|
||||||
|
}
|
||||||
|
cinfo->err->trace_level++;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
|
||||||
|
/* Force a monochrome JPEG file to be generated. */
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (ch == 'm' || ch == 'M')
|
||||||
|
lval *= 1000L;
|
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
|
||||||
|
/* Enable entropy parm optimization. */
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
cinfo->optimize_coding = TRUE;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "outfile", 4)) {
|
||||||
|
/* Set output file name. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
outfilename = argv[argn]; /* save it away for later use */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "progressive", 1)) {
|
||||||
|
/* Select simple progressive mode. */
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
simple_progressive = TRUE;
|
||||||
|
/* We must postpone execution until num_components is known. */
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "quality", 1)) {
|
||||||
|
/* Quality factor (quantization table scaling factor). */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &quality) != 1)
|
||||||
|
usage();
|
||||||
|
/* Change scale factor in case -qtables is present. */
|
||||||
|
q_scale_factor = jpeg_quality_scaling(quality);
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "qslots", 2)) {
|
||||||
|
/* Quantization table slot numbers. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
qslotsarg = argv[argn];
|
||||||
|
/* Must delay setting qslots until after we have processed any
|
||||||
|
* colorspace-determining switches, since jpeg_set_colorspace sets
|
||||||
|
* default quant table numbers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "qtables", 2)) {
|
||||||
|
/* Quantization tables fetched from file. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
qtablefile = argv[argn];
|
||||||
|
/* We postpone actually reading the file in case -quality comes later. */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "restart", 1)) {
|
||||||
|
/* Restart interval in MCU rows (or in MCUs with 'b'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (lval < 0 || lval > 65535L)
|
||||||
|
usage();
|
||||||
|
if (ch == 'b' || ch == 'B') {
|
||||||
|
cinfo->restart_interval = (unsigned int) lval;
|
||||||
|
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
|
||||||
|
} else {
|
||||||
|
cinfo->restart_in_rows = (int) lval;
|
||||||
|
/* restart_interval will be computed during startup */
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "sample", 2)) {
|
||||||
|
/* Set sampling factors. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
samplearg = argv[argn];
|
||||||
|
/* Must delay setting sample factors until after we have processed any
|
||||||
|
* colorspace-determining switches, since jpeg_set_colorspace sets
|
||||||
|
* default sampling factors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "scans", 2)) {
|
||||||
|
/* Set scan script. */
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
scansarg = argv[argn];
|
||||||
|
/* We must postpone reading the file in case -progressive appears. */
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
|
||||||
|
progname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "smooth", 2)) {
|
||||||
|
/* Set input smoothing factor. */
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1)
|
||||||
|
usage();
|
||||||
|
if (val < 0 || val > 100)
|
||||||
|
usage();
|
||||||
|
cinfo->smoothing_factor = val;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "targa", 1)) {
|
||||||
|
/* Input file is Targa format. */
|
||||||
|
is_targa = TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
usage(); /* bogus switch */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Post-switch-scanning cleanup */
|
||||||
|
|
||||||
|
if (for_real) {
|
||||||
|
|
||||||
|
/* Set quantization tables for selected quality. */
|
||||||
|
/* Some or all may be overridden if -qtables is present. */
|
||||||
|
jpeg_set_quality(cinfo, quality, force_baseline);
|
||||||
|
|
||||||
|
if (qtablefile != NULL) /* process -qtables if it was present */
|
||||||
|
if (! read_quant_tables(cinfo, qtablefile,
|
||||||
|
q_scale_factor, force_baseline))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (qslotsarg != NULL) /* process -qslots if it was present */
|
||||||
|
if (! set_quant_slots(cinfo, qslotsarg))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (samplearg != NULL) /* process -sample if it was present */
|
||||||
|
if (! set_sample_factors(cinfo, samplearg))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
if (simple_progressive) /* process -progressive; -scans can override */
|
||||||
|
jpeg_simple_progression(cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
if (scansarg != NULL) /* process -scans if it was present */
|
||||||
|
if (! read_scan_script(cinfo, scansarg))
|
||||||
|
usage();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return argn; /* return index of next arg (file name) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct jpeg_compress_struct cinfo;
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
struct cdjpeg_progress_mgr progress;
|
||||||
|
#endif
|
||||||
|
int file_index;
|
||||||
|
cjpeg_source_ptr src_mgr;
|
||||||
|
FILE * input_file;
|
||||||
|
FILE * output_file;
|
||||||
|
JDIMENSION num_scanlines;
|
||||||
|
|
||||||
|
/* On Mac, fetch a command line. */
|
||||||
|
#ifdef USE_CCOMMAND
|
||||||
|
argc = ccommand(&argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (progname == NULL || progname[0] == 0)
|
||||||
|
progname = "cjpeg"; /* in case C library doesn't provide it */
|
||||||
|
|
||||||
|
/* Initialize the JPEG compression object with default error handling. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
jpeg_create_compress(&cinfo);
|
||||||
|
/* Add some application-specific error messages (from cderror.h) */
|
||||||
|
jerr.addon_message_table = cdjpeg_message_table;
|
||||||
|
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
||||||
|
jerr.last_addon_message = JMSG_LASTADDONCODE;
|
||||||
|
|
||||||
|
/* Now safe to enable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialize JPEG parameters.
|
||||||
|
* Much of this may be overridden later.
|
||||||
|
* In particular, we don't yet know the input file's color space,
|
||||||
|
* but we need to provide some value for jpeg_set_defaults() to work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
|
||||||
|
jpeg_set_defaults(&cinfo);
|
||||||
|
|
||||||
|
/* Scan command line to find file names.
|
||||||
|
* It is convenient to use just one switch-parsing routine, but the switch
|
||||||
|
* values read here are ignored; we will rescan the switches after opening
|
||||||
|
* the input file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
|
||||||
|
|
||||||
|
#ifdef TWO_FILE_COMMANDLINE
|
||||||
|
/* Must have either -outfile switch or explicit output file name */
|
||||||
|
if (outfilename == NULL) {
|
||||||
|
if (file_index != argc-2) {
|
||||||
|
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||||
|
progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
outfilename = argv[file_index+1];
|
||||||
|
} else {
|
||||||
|
if (file_index != argc-1) {
|
||||||
|
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||||
|
progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Unix style: expect zero or one file name */
|
||||||
|
if (file_index < argc-1) {
|
||||||
|
fprintf(stderr, "%s: only one input file\n", progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
#endif /* TWO_FILE_COMMANDLINE */
|
||||||
|
|
||||||
|
/* Open the input file. */
|
||||||
|
if (file_index < argc) {
|
||||||
|
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default input file is stdin */
|
||||||
|
input_file = read_stdin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the output file. */
|
||||||
|
if (outfilename != NULL) {
|
||||||
|
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default output file is stdout */
|
||||||
|
output_file = write_stdout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
start_progress_monitor((j_common_ptr) &cinfo, &progress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Figure out the input file format, and set up to read it. */
|
||||||
|
src_mgr = select_file_type(&cinfo, input_file);
|
||||||
|
src_mgr->input_file = input_file;
|
||||||
|
|
||||||
|
/* Read the input file header to obtain file size & colorspace. */
|
||||||
|
(*src_mgr->start_input) (&cinfo, src_mgr);
|
||||||
|
|
||||||
|
/* Now that we know input colorspace, fix colorspace-dependent defaults */
|
||||||
|
jpeg_default_colorspace(&cinfo);
|
||||||
|
|
||||||
|
/* Adjust default compression parameters by re-parsing the options */
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
|
||||||
|
|
||||||
|
/* Specify data destination for compression */
|
||||||
|
jpeg_stdio_dest(&cinfo, output_file);
|
||||||
|
|
||||||
|
/* Start compressor */
|
||||||
|
jpeg_start_compress(&cinfo, TRUE);
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
while (cinfo.next_scanline < cinfo.image_height) {
|
||||||
|
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
|
||||||
|
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish compression and release memory */
|
||||||
|
(*src_mgr->finish_input) (&cinfo, src_mgr);
|
||||||
|
jpeg_finish_compress(&cinfo);
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
/* Close files, if we opened them */
|
||||||
|
if (input_file != stdin)
|
||||||
|
fclose(input_file);
|
||||||
|
if (output_file != stdout)
|
||||||
|
fclose(output_file);
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
end_progress_monitor((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* All done. */
|
||||||
|
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
|
||||||
|
return 0; /* suppress no-return-value warnings */
|
||||||
|
}
|
||||||
424
ckconfig.c
Normal file
424
ckconfig.c
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/*
|
||||||
|
* ckconfig.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : March 28, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This program is intended to help you determine how to configure the JPEG
|
||||||
|
* software for installation on a particular system. The idea is to try to
|
||||||
|
* compile and execute this program. If your compiler fails to compile the
|
||||||
|
* program, make changes as indicated in the comments below. Once you can
|
||||||
|
* compile the program, run it, and it will produce a "jconfig.h" file for
|
||||||
|
* your system.
|
||||||
|
*
|
||||||
|
* As a general rule, each time you try to compile this program,
|
||||||
|
* pay attention only to the *first* error message you get from the compiler.
|
||||||
|
* Many C compilers will issue lots of spurious error messages once they
|
||||||
|
* have gotten confused. Go to the line indicated in the first error message,
|
||||||
|
* and read the comments preceding that line to see what to change.
|
||||||
|
*
|
||||||
|
* Almost all of the edits you may need to make to this program consist of
|
||||||
|
* changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
|
||||||
|
* or vice versa. This is called defining or undefining that symbol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* First we must see if your system has the include files we need.
|
||||||
|
* We start out with the assumption that your system has all the ANSI-standard
|
||||||
|
* include files. If you get any error trying to include one of these files,
|
||||||
|
* undefine the corresponding HAVE_xxx symbol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */
|
||||||
|
#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_STDLIB_H /* same thing for stdlib.h */
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h> /* If you ain't got this, you ain't got C. */
|
||||||
|
|
||||||
|
/* We have to see if your string functions are defined by
|
||||||
|
* strings.h (old BSD convention) or string.h (everybody else).
|
||||||
|
* We try the non-BSD convention first; define NEED_BSD_STRINGS
|
||||||
|
* if the compiler says it can't find string.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
|
||||||
|
#ifdef NEED_BSD_STRINGS
|
||||||
|
#include <strings.h>
|
||||||
|
#else
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* On some systems (especially older Unix machines), type size_t is
|
||||||
|
* defined only in the include file <sys/types.h>. If you get a failure
|
||||||
|
* on the size_t test below, try defining NEED_SYS_TYPES_H.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */
|
||||||
|
#ifdef NEED_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Usually type size_t is defined in one of the include files we've included
|
||||||
|
* above. If not, you'll get an error on the "typedef size_t my_size_t;" line.
|
||||||
|
* In that case, first try defining NEED_SYS_TYPES_H just above.
|
||||||
|
* If that doesn't work, you'll have to search through your system library
|
||||||
|
* to figure out which include file defines "size_t". Look for a line that
|
||||||
|
* says "typedef something-or-other size_t;". Then, change the line below
|
||||||
|
* that says "#include <someincludefile.h>" to instead include the file
|
||||||
|
* you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find
|
||||||
|
* type size_t anywhere, try replacing "#include <someincludefile.h>" with
|
||||||
|
* "typedef unsigned int size_t;".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
|
||||||
|
|
||||||
|
#ifdef NEED_SPECIAL_INCLUDE
|
||||||
|
#include <someincludefile.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
|
||||||
|
|
||||||
|
|
||||||
|
/* The next question is whether your compiler supports ANSI-style function
|
||||||
|
* prototypes. You need to know this in order to choose between using
|
||||||
|
* makefile.ansi and using makefile.unix.
|
||||||
|
* The #define line below is set to assume you have ANSI function prototypes.
|
||||||
|
* If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int testfunction (int arg1, int * arg2); /* check prototypes */
|
||||||
|
|
||||||
|
struct methods_struct { /* check method-pointer declarations */
|
||||||
|
int (*error_exit) (char *msgtext);
|
||||||
|
int (*trace_message) (char *msgtext);
|
||||||
|
int (*another_method) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
int testfunction (int arg1, int * arg2) /* check definitions */
|
||||||
|
{
|
||||||
|
return arg2[arg1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int test2function (void) /* check void arg list */
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Now we want to find out if your compiler knows what "unsigned char" means.
|
||||||
|
* If you get an error on the "unsigned char un_char;" line,
|
||||||
|
* then undefine HAVE_UNSIGNED_CHAR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_CHAR
|
||||||
|
unsigned char un_char;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Now we want to find out if your compiler knows what "unsigned short" means.
|
||||||
|
* If you get an error on the "unsigned short un_short;" line,
|
||||||
|
* then undefine HAVE_UNSIGNED_SHORT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_SHORT
|
||||||
|
unsigned short un_short;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Now we want to find out if your compiler understands type "void".
|
||||||
|
* If you get an error anywhere in here, undefine HAVE_VOID.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_VOID
|
||||||
|
|
||||||
|
#ifdef HAVE_VOID
|
||||||
|
/* Caution: a C++ compiler will insist on complete prototypes */
|
||||||
|
typedef void * void_ptr; /* check void * */
|
||||||
|
#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
|
||||||
|
typedef void (*void_func) (int a, int b);
|
||||||
|
#else
|
||||||
|
typedef void (*void_func) ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES /* check void function result */
|
||||||
|
void test3function (void_ptr arg1, void_func arg2)
|
||||||
|
#else
|
||||||
|
void test3function (arg1, arg2)
|
||||||
|
void_ptr arg1;
|
||||||
|
void_func arg2;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char * locptr = (char *) arg1; /* check casting to and from void * */
|
||||||
|
arg1 = (void *) locptr;
|
||||||
|
(*arg2) (1, 2); /* check call of fcn returning void */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Now we want to find out if your compiler knows what "const" means.
|
||||||
|
* If you get an error here, undefine HAVE_CONST.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HAVE_CONST
|
||||||
|
|
||||||
|
#ifdef HAVE_CONST
|
||||||
|
static const int carray[3] = {1, 2, 3};
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int test4function (const int arg1)
|
||||||
|
#else
|
||||||
|
int test4function (arg1)
|
||||||
|
const int arg1;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return carray[arg1];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* If you get an error or warning about this structure definition,
|
||||||
|
* define INCOMPLETE_TYPES_BROKEN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
#ifndef INCOMPLETE_TYPES_BROKEN
|
||||||
|
typedef struct undefined_structure * undef_struct_ptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* If you get an error about duplicate names,
|
||||||
|
* define NEED_SHORT_EXTERNAL_NAMES.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
|
||||||
|
#ifndef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
|
||||||
|
int possibly_duplicate_function ()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int possibly_dupli_function ()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* OK, that's it. You should not have to change anything beyond this
|
||||||
|
* point in order to compile and execute this program. (You might get
|
||||||
|
* some warnings, but you can ignore them.)
|
||||||
|
* When you run the program, it will make a couple more tests that it
|
||||||
|
* can do automatically, and then it will create jconfig.h and print out
|
||||||
|
* any additional suggestions it has.
|
||||||
|
************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int is_char_signed (int arg)
|
||||||
|
#else
|
||||||
|
int is_char_signed (arg)
|
||||||
|
int arg;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (arg == 189) { /* expected result for unsigned char */
|
||||||
|
return 0; /* type char is unsigned */
|
||||||
|
}
|
||||||
|
else if (arg != -67) { /* expected result for signed char */
|
||||||
|
printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
|
||||||
|
printf("I fear the JPEG software will not work at all.\n\n");
|
||||||
|
}
|
||||||
|
return 1; /* assume char is signed otherwise */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int is_shifting_signed (long arg)
|
||||||
|
#else
|
||||||
|
int is_shifting_signed (arg)
|
||||||
|
long arg;
|
||||||
|
#endif
|
||||||
|
/* See whether right-shift on a long is signed or not. */
|
||||||
|
{
|
||||||
|
long res = arg >> 4;
|
||||||
|
|
||||||
|
if (res == -0x7F7E80CL) { /* expected result for signed shift */
|
||||||
|
return 1; /* right shift is signed */
|
||||||
|
}
|
||||||
|
/* see if unsigned-shift hack will fix it. */
|
||||||
|
/* we can't just test exact value since it depends on width of long... */
|
||||||
|
res |= (~0L) << (32-4);
|
||||||
|
if (res == -0x7F7E80CL) { /* expected result now? */
|
||||||
|
return 0; /* right shift is unsigned */
|
||||||
|
}
|
||||||
|
printf("Right shift isn't acting as I expect it to.\n");
|
||||||
|
printf("I fear the JPEG software will not work at all.\n\n");
|
||||||
|
return 0; /* try it with unsigned anyway */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int main (int argc, char ** argv)
|
||||||
|
#else
|
||||||
|
int main (argc, argv)
|
||||||
|
int argc;
|
||||||
|
char ** argv;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char signed_char_check = (char) (-67);
|
||||||
|
FILE *outfile;
|
||||||
|
|
||||||
|
/* Attempt to write jconfig.h */
|
||||||
|
if ((outfile = fopen("jconfig.h", "w")) == NULL) {
|
||||||
|
printf("Failed to write jconfig.h\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out all the info */
|
||||||
|
fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
|
||||||
|
fprintf(outfile, "/* see jconfig.doc for explanations */\n\n");
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
fprintf(outfile, "#define HAVE_PROTOTYPES\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNSIGNED_CHAR
|
||||||
|
fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNSIGNED_SHORT
|
||||||
|
fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_VOID
|
||||||
|
fprintf(outfile, "/* #define void char */\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#define void char\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CONST
|
||||||
|
fprintf(outfile, "/* #define const */\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#define const\n");
|
||||||
|
#endif
|
||||||
|
if (is_char_signed((int) signed_char_check))
|
||||||
|
fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
|
||||||
|
else
|
||||||
|
fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
|
||||||
|
#ifdef HAVE_STDDEF_H
|
||||||
|
fprintf(outfile, "#define HAVE_STDDEF_H\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef HAVE_STDDEF_H\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
fprintf(outfile, "#define HAVE_STDLIB_H\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef HAVE_STDLIB_H\n");
|
||||||
|
#endif
|
||||||
|
#ifdef NEED_BSD_STRINGS
|
||||||
|
fprintf(outfile, "#define NEED_BSD_STRINGS\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
|
||||||
|
#endif
|
||||||
|
#ifdef NEED_SYS_TYPES_H
|
||||||
|
fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
|
||||||
|
#endif
|
||||||
|
fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
|
||||||
|
#endif
|
||||||
|
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||||
|
fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
|
||||||
|
#else
|
||||||
|
fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
fprintf(outfile, "\n/* Define "boolean" as unsigned char, not int, per Windows custom */\n");
|
||||||
|
fprintf(outfile, "#define TYPEDEF_UCHAR_BOOLEAN\n");
|
||||||
|
#endif
|
||||||
|
fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
|
||||||
|
if (is_shifting_signed(-0x7F7E80B1L))
|
||||||
|
fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
|
||||||
|
else
|
||||||
|
fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
|
||||||
|
fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
|
||||||
|
|
||||||
|
fprintf(outfile, "\n#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)\n");
|
||||||
|
fprintf(outfile, "#undef JSIMD_MMX_NOT_SUPPORTED\n");
|
||||||
|
fprintf(outfile, "#undef JSIMD_3DNOW_NOT_SUPPORTED\n");
|
||||||
|
fprintf(outfile, "#undef JSIMD_SSE_NOT_SUPPORTED\n");
|
||||||
|
fprintf(outfile, "#undef JSIMD_SSE2_NOT_SUPPORTED\n");
|
||||||
|
fprintf(outfile, "#endif\n");
|
||||||
|
|
||||||
|
fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
|
||||||
|
fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n");
|
||||||
|
fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n");
|
||||||
|
fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n");
|
||||||
|
fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n");
|
||||||
|
fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n");
|
||||||
|
fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n");
|
||||||
|
#ifdef _WIN32
|
||||||
|
fprintf(outfile, "#define USE_SETMODE /* Needed to make one-file style work */\n");
|
||||||
|
#endif
|
||||||
|
fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n");
|
||||||
|
fprintf(outfile, "#undef DONT_USE_B_MODE\n");
|
||||||
|
fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n");
|
||||||
|
fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
|
||||||
|
|
||||||
|
/* Close the jconfig.h file */
|
||||||
|
fclose(outfile);
|
||||||
|
|
||||||
|
/* User report */
|
||||||
|
printf("Configuration check for Independent JPEG Group's software done.\n");
|
||||||
|
printf("\nI have written the jconfig.h file for you.\n\n");
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
printf("You should use makefile.ansi as the starting point for your Makefile.\n");
|
||||||
|
#else
|
||||||
|
printf("You should use makefile.unix as the starting point for your Makefile.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_SPECIAL_INCLUDE
|
||||||
|
printf("\nYou'll need to change jconfig.h to include the system include file\n");
|
||||||
|
printf("that you found type size_t in, or add a direct definition of type\n");
|
||||||
|
printf("size_t if that's what you used. Just add it to the end.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
118
coderules.doc
Normal file
118
coderules.doc
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
IJG JPEG LIBRARY: CODING RULES
|
||||||
|
|
||||||
|
Copyright (C) 1991-1996, Thomas G. Lane.
|
||||||
|
This file is part of the Independent JPEG Group's software.
|
||||||
|
For conditions of distribution and use, see the accompanying README file.
|
||||||
|
|
||||||
|
|
||||||
|
Since numerous people will be contributing code and bug fixes, it's important
|
||||||
|
to establish a common coding style. The goal of using similar coding styles
|
||||||
|
is much more important than the details of just what that style is.
|
||||||
|
|
||||||
|
In general we follow the recommendations of "Recommended C Style and Coding
|
||||||
|
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
|
||||||
|
Brader). This document is available in the IJG FTP archive (see
|
||||||
|
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
|
||||||
|
|
||||||
|
Block comments should be laid out thusly:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block comments in this style.
|
||||||
|
*/
|
||||||
|
|
||||||
|
We indent statements in K&R style, e.g.,
|
||||||
|
if (test) {
|
||||||
|
then-part;
|
||||||
|
} else {
|
||||||
|
else-part;
|
||||||
|
}
|
||||||
|
with two spaces per indentation level. (This indentation convention is
|
||||||
|
handled automatically by GNU Emacs and many other text editors.)
|
||||||
|
|
||||||
|
Multi-word names should be written in lower case with underscores, e.g.,
|
||||||
|
multi_word_name (not multiWordName). Preprocessor symbols and enum constants
|
||||||
|
are similar but upper case (MULTI_WORD_NAME). Names should be unique within
|
||||||
|
the first fifteen characters. (On some older systems, global names must be
|
||||||
|
unique within six characters. We accommodate this without cluttering the
|
||||||
|
source code by using macros to substitute shorter names.)
|
||||||
|
|
||||||
|
We use function prototypes everywhere; we rely on automatic source code
|
||||||
|
transformation to feed prototype-less C compilers. Transformation is done
|
||||||
|
by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript).
|
||||||
|
ansi2knr is not very bright, so it imposes a format requirement on function
|
||||||
|
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
|
||||||
|
should be written in the following style:
|
||||||
|
|
||||||
|
LOCAL(int *)
|
||||||
|
function_name (int a, char *b)
|
||||||
|
{
|
||||||
|
code...
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that each function definition must begin with GLOBAL(type), LOCAL(type),
|
||||||
|
or METHODDEF(type). These macros expand to "static type" or just "type" as
|
||||||
|
appropriate. They provide a readable indication of the routine's usage and
|
||||||
|
can readily be changed for special needs. (For instance, special linkage
|
||||||
|
keywords can be inserted for use in Windows DLLs.)
|
||||||
|
|
||||||
|
ansi2knr does not transform method declarations (function pointers in
|
||||||
|
structs). We handle these with a macro JMETHOD, defined as
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
|
||||||
|
#else
|
||||||
|
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
|
||||||
|
#endif
|
||||||
|
which is used like this:
|
||||||
|
struct function_pointers {
|
||||||
|
JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp));
|
||||||
|
JMETHOD(void, term_entropy_encoder, (void));
|
||||||
|
};
|
||||||
|
Note the set of parentheses surrounding the parameter list.
|
||||||
|
|
||||||
|
A similar solution is used for forward and external function declarations
|
||||||
|
(see the EXTERN and JPP macros).
|
||||||
|
|
||||||
|
If the code is to work on non-ANSI compilers, we cannot rely on a prototype
|
||||||
|
declaration to coerce actual parameters into the right types. Therefore, use
|
||||||
|
explicit casts on actual parameters whenever the actual parameter type is not
|
||||||
|
identical to the formal parameter. Beware of implicit conversions to "int".
|
||||||
|
|
||||||
|
It seems there are some non-ANSI compilers in which the sizeof() operator
|
||||||
|
is defined to return int, yet size_t is defined as long. Needless to say,
|
||||||
|
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
|
||||||
|
so that the result is guaranteed to be of type size_t.
|
||||||
|
|
||||||
|
|
||||||
|
The JPEG library is intended to be used within larger programs. Furthermore,
|
||||||
|
we want it to be reentrant so that it can be used by applications that process
|
||||||
|
multiple images concurrently. The following rules support these requirements:
|
||||||
|
|
||||||
|
1. Avoid direct use of file I/O, "malloc", error report printouts, etc;
|
||||||
|
pass these through the common routines provided.
|
||||||
|
|
||||||
|
2. Minimize global namespace pollution. Functions should be declared static
|
||||||
|
wherever possible. (Note that our method-based calling conventions help this
|
||||||
|
a lot: in many modules only the initialization function will ever need to be
|
||||||
|
called directly, so only that function need be externally visible.) All
|
||||||
|
global function names should begin with "jpeg_", and should have an
|
||||||
|
abbreviated name (unique in the first six characters) substituted by macro
|
||||||
|
when NEED_SHORT_EXTERNAL_NAMES is set.
|
||||||
|
|
||||||
|
3. Don't use global variables; anything that must be used in another module
|
||||||
|
should be in the common data structures.
|
||||||
|
|
||||||
|
4. Don't use static variables except for read-only constant tables. Variables
|
||||||
|
that should be private to a module can be placed into private structures (see
|
||||||
|
the system architecture document, structure.doc).
|
||||||
|
|
||||||
|
5. Source file names should begin with "j" for files that are part of the
|
||||||
|
library proper; source files that are not part of the library, such as cjpeg.c
|
||||||
|
and djpeg.c, do not begin with "j". Keep source file names to eight
|
||||||
|
characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep
|
||||||
|
compression and decompression code in separate source files --- some
|
||||||
|
applications may want only one half of the library.
|
||||||
|
|
||||||
|
Note: these rules (particularly #4) are not followed religiously in the
|
||||||
|
modules that are used in cjpeg/djpeg but are not part of the JPEG library
|
||||||
|
proper. Those modules are not really intended to be used in other
|
||||||
|
applications.
|
||||||
99
codingrules
99
codingrules
@@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
JPEG SYSTEM CODING RULES 27-SEP-91
|
|
||||||
|
|
||||||
Since numerous people will be contributing code and bug fixes, it's important
|
|
||||||
to establish a common coding style. The goal of using similar coding styles
|
|
||||||
is much more important than the details of just what that style is.
|
|
||||||
|
|
||||||
I suggest we follow the recommendations of "Recommended C Style and Coding
|
|
||||||
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
|
|
||||||
Brader). I have placed a copy of this document in the jpeg FTP archive (see
|
|
||||||
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
|
|
||||||
|
|
||||||
Unless someone has a real strong objection, let's do block comments thusly:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block comments in this style.
|
|
||||||
*/
|
|
||||||
|
|
||||||
and indent statements in K&R style, e.g.,
|
|
||||||
|
|
||||||
if (test) {
|
|
||||||
then-part;
|
|
||||||
} else {
|
|
||||||
else-part;
|
|
||||||
}
|
|
||||||
|
|
||||||
I suggest that multi-word names be written in the style multi_word_name
|
|
||||||
rather than multiWordName, but I am open to argument on this.
|
|
||||||
|
|
||||||
|
|
||||||
I would like to use function prototypes everywhere, and rely on automatic
|
|
||||||
source code transformation to feed non-ANSI C compilers. The best tool
|
|
||||||
I have so far found for this is 'ansi2knr.c', which is part of Ghostscript.
|
|
||||||
ansi2knr is not very bright, so it imposes a format requirement on function
|
|
||||||
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
|
|
||||||
should be written in the following style:
|
|
||||||
|
|
||||||
static int *
|
|
||||||
function_name (int a, char *b)
|
|
||||||
{
|
|
||||||
code...
|
|
||||||
}
|
|
||||||
|
|
||||||
ansi2knr won't help with method declarations (function pointers in structs).
|
|
||||||
I suggest we use a macro to declare method pointers, something like this:
|
|
||||||
|
|
||||||
#ifdef PROTO
|
|
||||||
#define METHOD(type,methodname,arglist) type (*methodname) arglist
|
|
||||||
#else
|
|
||||||
#define METHOD(type,methodname,arglist) type (*methodname) ()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
which is used like this:
|
|
||||||
|
|
||||||
struct function_pointers {
|
|
||||||
METHOD(void, init_entropy_encoder, (functptrs fptrs, jparms *jp));
|
|
||||||
METHOD(void, term_entropy_encoder, (void));
|
|
||||||
};
|
|
||||||
|
|
||||||
Note the set of parentheses surrounding the parameter list.
|
|
||||||
|
|
||||||
A similar solution is used for external function declarations (see the PP
|
|
||||||
macro in jpegdata.h).
|
|
||||||
|
|
||||||
If the code is to work on non-ANSI compilers, you cannot rely on a prototype
|
|
||||||
declaration to coerce actual parameters into the right types. Therefore, use
|
|
||||||
explicit casts on actual parameters whenever the actual parameter type is not
|
|
||||||
identical to the formal parameter. Beware of implicit conversions to "int".
|
|
||||||
|
|
||||||
It seems there are some non-ANSI compilers in which the sizeof() operator
|
|
||||||
is defined to return int, while size_t is defined as long. Needless to say,
|
|
||||||
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
|
|
||||||
so that the result is guaranteed to be of type size_t.
|
|
||||||
|
|
||||||
|
|
||||||
We can expect that the JPEG compressor and decompressor will be incorporated
|
|
||||||
into larger programs. Therefore, the following rules are important:
|
|
||||||
|
|
||||||
1. Avoid direct use of any file I/O, "malloc", error report printouts, etc;
|
|
||||||
pass these through the common routines provided.
|
|
||||||
|
|
||||||
2. Assume that the JPEG code may be invoked more than once per program run;
|
|
||||||
therefore, do not rely on static initialization of variables, and be careful
|
|
||||||
to release all allocated storage at the end of processing.
|
|
||||||
|
|
||||||
3. Minimize global namespace pollution. Functions should be declared static
|
|
||||||
wherever possible. (Note that our method-based calling conventions help this
|
|
||||||
a lot: in many modules only the method-selector function will ever need to be
|
|
||||||
called directly, so only that function need be externally visible.) All
|
|
||||||
global function names should begin with "j", and should be unique in the first
|
|
||||||
six characters for portability reasons.
|
|
||||||
Don't use global variables at all; anything that must be used in another
|
|
||||||
module should be put into parameters (there'll be some large structs passed
|
|
||||||
around for this purpose).
|
|
||||||
|
|
||||||
4. Source file names should also begin with "j"; remember to keep them to
|
|
||||||
eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.
|
|
||||||
Do not put code for both compression and decompression into the same source
|
|
||||||
file.
|
|
||||||
403
config.c
403
config.c
@@ -1,403 +0,0 @@
|
|||||||
/*
|
|
||||||
* config.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 program is intended to help you determine how to configure the JPEG
|
|
||||||
* software for installation on a particular system. The idea is to try to
|
|
||||||
* compile and execute this program. If your compiler fails to compile the
|
|
||||||
* program, make changes as indicated in the comments below. Once you can
|
|
||||||
* compile the program, run it, and it will tell you how to set the various
|
|
||||||
* switches in jconfig.h and in your Makefile.
|
|
||||||
*
|
|
||||||
* This could all be done automatically if we could assume we were on a Unix
|
|
||||||
* system, but we don't want to assume that, so you'll have to edit and
|
|
||||||
* recompile this program until it works.
|
|
||||||
*
|
|
||||||
* As a general rule, each time you try to compile this program,
|
|
||||||
* pay attention only to the *first* error message you get from the compiler.
|
|
||||||
* Many C compilers will issue lots of spurious error messages once they
|
|
||||||
* have gotten confused. Go to the line indicated in the first error message,
|
|
||||||
* and read the comments preceding that line to see what to change.
|
|
||||||
*
|
|
||||||
* Almost all of the edits you may need to make to this program consist of
|
|
||||||
* changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
|
|
||||||
* or vice versa. This is called defining or undefining that symbol.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* First we must see if your system has the include files we need.
|
|
||||||
* We start out with the assumption that your system follows the ANSI
|
|
||||||
* conventions for include files. If you get any error in the next dozen
|
|
||||||
* lines, undefine INCLUDES_ARE_ANSI.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define INCLUDES_ARE_ANSI /* replace 'define' by 'undef' if error here */
|
|
||||||
|
|
||||||
#ifdef INCLUDES_ARE_ANSI /* this will be skipped if you undef... */
|
|
||||||
#include <stdio.h> /* If you ain't got this, you ain't got C. */
|
|
||||||
#ifdef __SASC /* Amiga SAS C provides size_t in stddef.h. */
|
|
||||||
#include <stddef.h> /* (They are wrong...) */
|
|
||||||
#endif
|
|
||||||
#include <string.h> /* size_t might be here too. */
|
|
||||||
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
|
|
||||||
#include <stdlib.h> /* Check other ANSI includes we use. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* If your system doesn't follow the ANSI conventions, we have to figure out
|
|
||||||
* what it does follow. If you didn't get an error before this line, you can
|
|
||||||
* ignore everything down to "#define HAVE_ANSI_DEFINITIONS".
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INCLUDES_ARE_ANSI /* skip these tests if INCLUDES_ARE_ANSI */
|
|
||||||
|
|
||||||
#include <stdio.h> /* If you ain't got this, you ain't got C. */
|
|
||||||
|
|
||||||
/* jinclude.h will try to include <sys/types.h> if you don't set
|
|
||||||
* INCLUDES_ARE_ANSI. We need to test whether that include file is provided.
|
|
||||||
* If you get an error here, undefine HAVE_TYPES_H.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_TYPES_H
|
|
||||||
|
|
||||||
#ifdef HAVE_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We have to see if your string functions are defined by
|
|
||||||
* strings.h (BSD convention) or string.h (everybody else).
|
|
||||||
* We try the non-BSD convention first; define BSD if the compiler
|
|
||||||
* says it can't find string.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef BSD
|
|
||||||
|
|
||||||
#ifdef BSD
|
|
||||||
#include <strings.h>
|
|
||||||
#else
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Usually size_t is defined in stdio.h, sys/types.h, and/or string.h.
|
|
||||||
* If not, you'll get an error on the "typedef size_t my_size_t;" line below.
|
|
||||||
* In that case, you'll have to search through your system library to
|
|
||||||
* figure out which include file defines "size_t". Look for a line that
|
|
||||||
* says "typedef something-or-other size_t;" (stddef.h and stdlib.h are
|
|
||||||
* good places to look first). Then, change the line below that says
|
|
||||||
* "#include <someincludefile.h>" to instead include the file
|
|
||||||
* you found size_t in, and define NEED_SPECIAL_INCLUDE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
|
|
||||||
|
|
||||||
#ifdef NEED_SPECIAL_INCLUDE
|
|
||||||
#include <someincludefile.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDES_ARE_ANSI */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The next question is whether your compiler supports ANSI-style function
|
|
||||||
* definitions. You need to know this in order to choose between using
|
|
||||||
* makefile.ansi and using makefile.unix.
|
|
||||||
* The #define line below is set to assume you have ANSI function definitions.
|
|
||||||
* If you get an error in this group of lines, undefine HAVE_ANSI_DEFINITIONS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_ANSI_DEFINITIONS
|
|
||||||
|
|
||||||
#ifdef HAVE_ANSI_DEFINITIONS
|
|
||||||
int testfunction (int arg1, int * arg2); /* check prototypes */
|
|
||||||
|
|
||||||
struct methods_struct { /* check method-pointer declarations */
|
|
||||||
int (*error_exit) (char *msgtext);
|
|
||||||
int (*trace_message) (char *msgtext);
|
|
||||||
};
|
|
||||||
|
|
||||||
int testfunction (int arg1, int * arg2) /* check definitions */
|
|
||||||
{
|
|
||||||
return arg2[arg1];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Now we want to find out if your compiler knows what "unsigned char" means.
|
|
||||||
* If you get an error on the "unsigned char un_char;" line,
|
|
||||||
* then undefine HAVE_UNSIGNED_CHAR.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_UNSIGNED_CHAR
|
|
||||||
|
|
||||||
#ifdef HAVE_UNSIGNED_CHAR
|
|
||||||
unsigned char un_char;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Now we want to find out if your compiler knows what "unsigned short" means.
|
|
||||||
* If you get an error on the "unsigned short un_short;" line,
|
|
||||||
* then undefine HAVE_UNSIGNED_SHORT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_UNSIGNED_SHORT
|
|
||||||
|
|
||||||
#ifdef HAVE_UNSIGNED_SHORT
|
|
||||||
unsigned short un_short;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Now we want to find out if your compiler understands type "void".
|
|
||||||
* If you get an error anywhere in here, undefine HAVE_VOID.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_VOID
|
|
||||||
|
|
||||||
#ifdef HAVE_VOID
|
|
||||||
typedef void * void_ptr; /* check void * */
|
|
||||||
typedef void (*void_func) (); /* check ptr to function returning void */
|
|
||||||
|
|
||||||
void testfunction2 (arg1, arg2) /* check void function result */
|
|
||||||
void_ptr arg1;
|
|
||||||
void_func arg2;
|
|
||||||
{
|
|
||||||
char * locptr = (char *) arg1; /* check casting to and from void * */
|
|
||||||
arg1 = (void *) locptr;
|
|
||||||
(*arg2) (1, 2); /* check call of fcn returning void */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Now we want to find out if your compiler knows what "const" means.
|
|
||||||
* If you get an error here, undefine HAVE_CONST.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_CONST
|
|
||||||
|
|
||||||
#ifdef HAVE_CONST
|
|
||||||
static const int carray[3] = {1, 2, 3};
|
|
||||||
|
|
||||||
int testfunction3 (arg1)
|
|
||||||
const int arg1;
|
|
||||||
{
|
|
||||||
return carray[arg1];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* OK, that's it. You should not have to change anything beyond this
|
|
||||||
* point in order to compile and execute this program. (You might get
|
|
||||||
* some warnings, but you can ignore them.)
|
|
||||||
* When you run the program, it will make a couple more tests that it
|
|
||||||
* can do automatically, and then it will print out a summary of the changes
|
|
||||||
* that you need to make to the makefile and jconfig.h.
|
|
||||||
************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static int any_changes = 0;
|
|
||||||
|
|
||||||
int new_change ()
|
|
||||||
{
|
|
||||||
if (! any_changes) {
|
|
||||||
printf("\nMost of the changes recommended by this program can be made either\n");
|
|
||||||
printf("by editing jconfig.h, or by adding -Dsymbol switches to the CFLAGS\n");
|
|
||||||
printf("line in your Makefile. (Some PC compilers expect /Dsymbol instead.)\n");
|
|
||||||
printf("The CFLAGS method is simpler, but if your system doesn't use makefiles,\n");
|
|
||||||
printf("or if your compiler doesn't support -D, then you must change jconfig.h.\n");
|
|
||||||
any_changes = 1;
|
|
||||||
}
|
|
||||||
printf("\n"); /* blank line before each problem report */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int test_char_sign (arg)
|
|
||||||
int arg;
|
|
||||||
{
|
|
||||||
if (arg == 189) { /* expected result for unsigned char */
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DCHAR_IS_UNSIGNED to CFLAGS,\n");
|
|
||||||
printf("or else remove the /* */ comment marks from the line\n");
|
|
||||||
printf("/* #define CHAR_IS_UNSIGNED */ in jconfig.h.\n");
|
|
||||||
printf("(Be sure to delete the space before the # character too.)\n");
|
|
||||||
}
|
|
||||||
else if (arg != -67) { /* expected result for signed char */
|
|
||||||
new_change();
|
|
||||||
printf("Hmm, it seems 'char' is less than eight bits wide on your machine.\n");
|
|
||||||
printf("I fear the JPEG software will not work at all.\n");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int test_shifting (arg)
|
|
||||||
long arg;
|
|
||||||
/* See whether right-shift on a long is signed or not. */
|
|
||||||
{
|
|
||||||
long res = arg >> 4;
|
|
||||||
|
|
||||||
if (res == 0x80817F4L) { /* expected result for unsigned */
|
|
||||||
new_change();
|
|
||||||
printf("You must add -DRIGHT_SHIFT_IS_UNSIGNED to CFLAGS,\n");
|
|
||||||
printf("or else remove the /* */ comment marks from the line\n");
|
|
||||||
printf("/* #define RIGHT_SHIFT_IS_UNSIGNED */ in jconfig.h.\n");
|
|
||||||
}
|
|
||||||
else if (res != -0x7F7E80CL) { /* expected result for signed */
|
|
||||||
new_change();
|
|
||||||
printf("Right shift isn't acting as I expect it to.\n");
|
|
||||||
printf("I fear the JPEG software will not work at all.\n");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main (argc, argv)
|
|
||||||
int argc;
|
|
||||||
char ** argv;
|
|
||||||
{
|
|
||||||
char signed_char_check = (char) (-67);
|
|
||||||
|
|
||||||
printf("Results of configuration check for Independent JPEG Group's software:\n");
|
|
||||||
printf("\nIf there's not a specific makefile provided for your compiler,\n");
|
|
||||||
#ifdef HAVE_ANSI_DEFINITIONS
|
|
||||||
printf("you should use makefile.ansi as the starting point for your Makefile.\n");
|
|
||||||
#else
|
|
||||||
printf("you should use makefile.unix as the starting point for your Makefile.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check whether we have all the ANSI features, */
|
|
||||||
/* and whether this agrees with __STDC__ being predefined. */
|
|
||||||
#ifdef __STDC__
|
|
||||||
#define MY__STDC__ /* ANSI compilers won't allow redefining __STDC__ */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_ANSI_DEFINITIONS
|
|
||||||
#ifdef HAVE_UNSIGNED_CHAR
|
|
||||||
#ifdef HAVE_UNSIGNED_SHORT
|
|
||||||
#ifdef HAVE_CONST
|
|
||||||
#define HAVE_ALL_ANSI_FEATURES
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_ALL_ANSI_FEATURES
|
|
||||||
#ifndef MY__STDC__
|
|
||||||
new_change();
|
|
||||||
printf("Your compiler doesn't claim to be ANSI-compliant, but it is close enough\n");
|
|
||||||
printf("for me. Either add -D__STDC__ to CFLAGS, or add #define __STDC__ at the\n");
|
|
||||||
printf("beginning of jinclude.h (NOT jconfig.h).\n");
|
|
||||||
printf("Some compilers will not let you do this: they will complain that __STDC__\n");
|
|
||||||
printf("is a reserved name. In that case you have a compiler that really is ANSI,\n");
|
|
||||||
printf("but you have to give it a special switch (often -ansi) to make it so.\n");
|
|
||||||
printf("Check your compiler documentation and add the proper switch to CFLAGS.\n");
|
|
||||||
#define MY__STDC__
|
|
||||||
#endif
|
|
||||||
#else /* !HAVE_ALL_ANSI_FEATURES */
|
|
||||||
#ifdef MY__STDC__
|
|
||||||
new_change();
|
|
||||||
printf("Your compiler claims to be ANSI-compliant, but it is lying!\n");
|
|
||||||
printf("Either add -U__STDC__ to CFLAGS, or add #undef __STDC__\n");
|
|
||||||
printf("at the beginning of jinclude.h (NOT jconfig.h).\n");
|
|
||||||
#undef MY__STDC__
|
|
||||||
#endif
|
|
||||||
#endif /* HAVE_ALL_ANSI_FEATURES */
|
|
||||||
|
|
||||||
#ifndef MY__STDC__
|
|
||||||
|
|
||||||
#ifdef HAVE_ANSI_DEFINITIONS
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DPROTO to CFLAGS, or else take out the several\n");
|
|
||||||
printf("#ifdef/#else/#endif lines surrounding #define PROTO in jconfig.h.\n");
|
|
||||||
printf("(Leave only one #define PROTO line.)\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_UNSIGNED_CHAR
|
|
||||||
#ifdef HAVE_UNSIGNED_SHORT
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DHAVE_UNSIGNED_CHAR and -DHAVE_UNSIGNED_SHORT\n");
|
|
||||||
printf("to CFLAGS, or else take out the #ifdef __STDC__/#endif lines\n");
|
|
||||||
printf("surrounding #define HAVE_UNSIGNED_CHAR and #define HAVE_UNSIGNED_SHORT\n");
|
|
||||||
printf("in jconfig.h.\n");
|
|
||||||
#else /* only unsigned char */
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DHAVE_UNSIGNED_CHAR to CFLAGS,\n");
|
|
||||||
printf("or else move #define HAVE_UNSIGNED_CHAR outside the\n");
|
|
||||||
printf("#ifdef __STDC__/#endif lines surrounding it in jconfig.h.\n");
|
|
||||||
#endif
|
|
||||||
#else /* !HAVE_UNSIGNED_CHAR */
|
|
||||||
#ifdef HAVE_UNSIGNED_SHORT
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DHAVE_UNSIGNED_SHORT to CFLAGS,\n");
|
|
||||||
printf("or else move #define HAVE_UNSIGNED_SHORT outside the\n");
|
|
||||||
printf("#ifdef __STDC__/#endif lines surrounding it in jconfig.h.\n");
|
|
||||||
#endif
|
|
||||||
#endif /* HAVE_UNSIGNED_CHAR */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONST
|
|
||||||
new_change();
|
|
||||||
printf("You can delete the #define const line from jconfig.h.\n");
|
|
||||||
printf("(But things should still work if you don't.)\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MY__STDC__ */
|
|
||||||
|
|
||||||
test_char_sign((int) signed_char_check);
|
|
||||||
|
|
||||||
test_shifting(-0x7F7E80B1L);
|
|
||||||
|
|
||||||
#ifndef HAVE_VOID
|
|
||||||
new_change();
|
|
||||||
printf("You should add -Dvoid=char to CFLAGS,\n");
|
|
||||||
printf("or else remove the /* */ comment marks from the line\n");
|
|
||||||
printf("/* #define void char */ in jconfig.h.\n");
|
|
||||||
printf("(Be sure to delete the space before the # character too.)\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef INCLUDES_ARE_ANSI
|
|
||||||
#ifndef MY__STDC__
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DINCLUDES_ARE_ANSI to CFLAGS, or else add\n");
|
|
||||||
printf("#define INCLUDES_ARE_ANSI at the beginning of jinclude.h (NOT jconfig.h).\n");
|
|
||||||
#endif
|
|
||||||
#else /* !INCLUDES_ARE_ANSI */
|
|
||||||
#ifdef MY__STDC__
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DNONANSI_INCLUDES to CFLAGS, or else add\n");
|
|
||||||
printf("#define NONANSI_INCLUDES at the beginning of jinclude.h (NOT jconfig.h).\n");
|
|
||||||
#endif
|
|
||||||
#ifdef NEED_SPECIAL_INCLUDE
|
|
||||||
new_change();
|
|
||||||
printf("In jinclude.h, change the line reading #include <sys/types.h>\n");
|
|
||||||
printf("to instead include the file you found size_t in.\n");
|
|
||||||
#else /* !NEED_SPECIAL_INCLUDE */
|
|
||||||
#ifndef HAVE_TYPES_H
|
|
||||||
new_change();
|
|
||||||
printf("In jinclude.h, delete the line reading #include <sys/types.h>.\n");
|
|
||||||
#endif
|
|
||||||
#endif /* NEED_SPECIAL_INCLUDE */
|
|
||||||
#ifdef BSD
|
|
||||||
new_change();
|
|
||||||
printf("You should add -DBSD to CFLAGS, or else add\n");
|
|
||||||
printf("#define BSD at the beginning of jinclude.h (NOT jconfig.h).\n");
|
|
||||||
#endif
|
|
||||||
#endif /* INCLUDES_ARE_ANSI */
|
|
||||||
|
|
||||||
if (any_changes) {
|
|
||||||
printf("\nI think that's everything...\n");
|
|
||||||
} else {
|
|
||||||
printf("\nI think jconfig.h is OK as distributed.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return any_changes;
|
|
||||||
}
|
|
||||||
1491
config.guess
vendored
Normal file
1491
config.guess
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1606
config.sub
vendored
Normal file
1606
config.sub
vendored
Normal file
File diff suppressed because it is too large
Load Diff
44
config.ver
Normal file
44
config.ver
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
JPEG_VER_MAJOR=62
|
||||||
|
JPEG_VER_MINOR=1
|
||||||
|
JPEG_REVISION=0
|
||||||
|
|
||||||
|
case $host_os in
|
||||||
|
cygwin*)
|
||||||
|
# The shared library built from this source code is *not* binary
|
||||||
|
# compatible with the cygwin's official binary release (cygjpeg-62.dll).
|
||||||
|
# This is because the official binary has been built with
|
||||||
|
# the lossless jpeg patch which is available as ljpeg-6b.tar.gz .
|
||||||
|
# Therefore we decided to give the shared library the version number
|
||||||
|
# other than 62.
|
||||||
|
#
|
||||||
|
JPEG_VER_MAJOR=162
|
||||||
|
JPEG_VER_MINOR=0
|
||||||
|
;;
|
||||||
|
freebsd*)
|
||||||
|
# This follows the official binary release in the ports collection.
|
||||||
|
JPEG_VER_MAJOR=9
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# convert absolute version numbers to libtool ages
|
||||||
|
case $version_type in
|
||||||
|
freebsd-aout|freebsd-elf|sunos)
|
||||||
|
JPEG_LT_CURRENT=$JPEG_VER_MAJOR
|
||||||
|
JPEG_LT_REVISION=$JPEG_VER_MINOR
|
||||||
|
JPEG_LT_AGE=0
|
||||||
|
;;
|
||||||
|
irix|nonstopux)
|
||||||
|
JPEG_LT_CURRENT=`expr $JPEG_VER_MAJOR + $JPEG_VER_MINOR - 1`
|
||||||
|
JPEG_LT_AGE=$JPEG_VER_MINOR
|
||||||
|
JPEG_LT_REVISION=$JPEG_VER_MINOR
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
JPEG_LT_CURRENT=`expr $JPEG_VER_MAJOR + $JPEG_VER_MINOR`
|
||||||
|
JPEG_LT_AGE=$JPEG_VER_MINOR
|
||||||
|
JPEG_LT_REVISION=$JPEG_REVISION
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
JPEG_LIB_VERSION=$JPEG_LT_CURRENT:$JPEG_LT_REVISION:$JPEG_LT_AGE
|
||||||
|
|
||||||
634
configure.in
Normal file
634
configure.in
Normal file
@@ -0,0 +1,634 @@
|
|||||||
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
AC_INIT([jcmaster.c])
|
||||||
|
AC_CONFIG_HEADER([jconfig.h:jconfig.cfg])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_CPP
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for function prototypes])
|
||||||
|
AC_CACHE_VAL([ijg_cv_have_prototypes],[AC_TRY_COMPILE([
|
||||||
|
int testfunction (int arg1, int * arg2); /* check prototypes */
|
||||||
|
struct methods_struct { /* check method-pointer declarations */
|
||||||
|
int (*error_exit) (char *msgtext);
|
||||||
|
int (*trace_message) (char *msgtext);
|
||||||
|
int (*another_method) (void);
|
||||||
|
};
|
||||||
|
int testfunction (int arg1, int * arg2) /* check definitions */
|
||||||
|
{ return arg2[arg1]; }
|
||||||
|
int test2function (void) /* check void arg list */
|
||||||
|
{ return 0; }
|
||||||
|
],[ ],[ijg_cv_have_prototypes=yes],[ijg_cv_have_prototypes=no])])
|
||||||
|
AC_MSG_RESULT([$ijg_cv_have_prototypes])
|
||||||
|
if test $ijg_cv_have_prototypes = yes; then
|
||||||
|
AC_DEFINE([HAVE_PROTOTYPES],)
|
||||||
|
else
|
||||||
|
echo [Your compiler does not seem to know about function prototypes.]
|
||||||
|
echo [Perhaps it needs a special switch to enable ANSI C mode.]
|
||||||
|
echo [If so, we recommend running configure like this:]
|
||||||
|
echo [" ./configure CC='cc -switch'"]
|
||||||
|
echo [where -switch is the proper switch.]
|
||||||
|
fi
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_CHECK_HEADER([stddef.h],[AC_DEFINE([HAVE_STDDEF_H],)])
|
||||||
|
AC_CHECK_HEADER([stdlib.h],[AC_DEFINE([HAVE_STDLIB_H],)])
|
||||||
|
AC_CHECK_HEADER([string.h],[:],[AC_DEFINE([NEED_BSD_STRINGS],)])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for size_t])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#ifdef HAVE_STDDEF_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef NEED_BSD_STRINGS
|
||||||
|
#include <strings.h>
|
||||||
|
#else
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
typedef size_t my_size_t;
|
||||||
|
],[ my_size_t foovar; ],
|
||||||
|
[ijg_size_t_ok=yes],
|
||||||
|
[ijg_size_t_ok="not ANSI, perhaps it is in sys/types.h"])
|
||||||
|
AC_MSG_RESULT([$ijg_size_t_ok])
|
||||||
|
if test "$ijg_size_t_ok" != yes; then
|
||||||
|
AC_CHECK_HEADER([sys/types.h],[AC_DEFINE([NEED_SYS_TYPES_H],)
|
||||||
|
AC_EGREP_HEADER([size_t],[sys/types.h],
|
||||||
|
[ijg_size_t_ok="size_t is in sys/types.h"],[ijg_size_t_ok=no])],
|
||||||
|
[ijg_size_t_ok=no])
|
||||||
|
AC_MSG_RESULT([$ijg_size_t_ok])
|
||||||
|
if test "$ijg_size_t_ok" = no; then
|
||||||
|
echo [Type size_t is not defined in any of the usual places.]
|
||||||
|
echo [Try putting '"typedef unsigned int size_t;"' in jconfig.h.]
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for type unsigned char])
|
||||||
|
AC_TRY_COMPILE(,[ unsigned char un_char; ],[AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE([HAVE_UNSIGNED_CHAR],)],[AC_MSG_RESULT(no)])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for type unsigned short])
|
||||||
|
AC_TRY_COMPILE(,[ unsigned short un_short; ],[AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE([HAVE_UNSIGNED_SHORT],)],[AC_MSG_RESULT(no)])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for type void])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
/* Caution: a C++ compiler will insist on valid prototypes */
|
||||||
|
typedef void * void_ptr; /* check void * */
|
||||||
|
#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
|
||||||
|
typedef void (*void_func) (int a, int b);
|
||||||
|
#else
|
||||||
|
typedef void (*void_func) ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES /* check void function result */
|
||||||
|
void test3function (void_ptr arg1, void_func arg2)
|
||||||
|
#else
|
||||||
|
void test3function (arg1, arg2)
|
||||||
|
void_ptr arg1;
|
||||||
|
void_func arg2;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char * locptr = (char *) arg1; /* check casting to and from void * */
|
||||||
|
arg1 = (void *) locptr;
|
||||||
|
(*arg2) (1, 2); /* check call of fcn returning void */
|
||||||
|
}
|
||||||
|
],[ ],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE([void],[char])])
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for working const])
|
||||||
|
AC_CACHE_VAL([ac_cv_c_const],[AC_TRY_COMPILE(,[
|
||||||
|
/* Ultrix mips cc rejects this. */
|
||||||
|
typedef int charset[2]; const charset x;
|
||||||
|
/* SunOS 4.1.1 cc rejects this. */
|
||||||
|
char const *const *ccp;
|
||||||
|
char **p;
|
||||||
|
/* NEC SVR4.0.2 mips cc rejects this. */
|
||||||
|
struct point {int x, y;};
|
||||||
|
static struct point const zero = {0,0};
|
||||||
|
/* AIX XL C 1.02.0.0 rejects this.
|
||||||
|
It does not let you subtract one const X* pointer from another in an arm
|
||||||
|
of an if-expression whose if-part is not a constant expression */
|
||||||
|
const char *g = "string";
|
||||||
|
ccp = &g + (g ? g-g : 0);
|
||||||
|
/* HPUX 7.0 cc rejects these. */
|
||||||
|
++ccp;
|
||||||
|
p = (char**) ccp;
|
||||||
|
ccp = (char const *const *) p;
|
||||||
|
{ /* SCO 3.2v4 cc rejects this. */
|
||||||
|
char *t;
|
||||||
|
char const *s = 0 ? (char *) 0 : (char const *) 0;
|
||||||
|
|
||||||
|
*t++ = 0;
|
||||||
|
}
|
||||||
|
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
|
||||||
|
int x[] = {25, 17};
|
||||||
|
const int *foo = &x[0];
|
||||||
|
++foo;
|
||||||
|
}
|
||||||
|
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
|
||||||
|
typedef const int *iptr;
|
||||||
|
iptr p = 0;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
{ /* AIX XL C 1.02.0.0 rejects this saying
|
||||||
|
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
|
||||||
|
struct s { int j; const int *ap[3]; };
|
||||||
|
struct s *b; b->j = 5;
|
||||||
|
}
|
||||||
|
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
|
||||||
|
const int foo = 10;
|
||||||
|
}
|
||||||
|
],[ac_cv_c_const=yes],[ac_cv_c_const=no])])
|
||||||
|
AC_MSG_RESULT([$ac_cv_c_const])
|
||||||
|
if test $ac_cv_c_const = no; then
|
||||||
|
AC_DEFINE([const],)
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for inline])
|
||||||
|
ijg_cv_inline=""
|
||||||
|
AC_TRY_COMPILE(,[} __inline__ int foo() { return 0; }
|
||||||
|
int bar() { return foo();],[ijg_cv_inline="__inline__"],
|
||||||
|
[AC_TRY_COMPILE(,[} __inline int foo() { return 0; }
|
||||||
|
int bar() { return foo();],[ijg_cv_inline="__inline"],
|
||||||
|
[AC_TRY_COMPILE(,[} inline int foo() { return 0; }
|
||||||
|
int bar() { return foo();],[ijg_cv_inline="inline"],)])])
|
||||||
|
AC_MSG_RESULT([$ijg_cv_inline])
|
||||||
|
AC_DEFINE_UNQUOTED([INLINE],[$ijg_cv_inline])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for broken incomplete types])
|
||||||
|
AC_TRY_COMPILE([ typedef struct undefined_structure * undef_struct_ptr; ],
|
||||||
|
,[AC_MSG_RESULT(ok)],[AC_MSG_RESULT(broken)
|
||||||
|
AC_DEFINE([INCOMPLETE_TYPES_BROKEN],)])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([for short external names])
|
||||||
|
AC_TRY_LINK([
|
||||||
|
int possibly_duplicate_function () { return 0; }
|
||||||
|
int possibly_dupli_function () { return 1; }
|
||||||
|
],[ ],[AC_MSG_RESULT(ok)],[AC_MSG_RESULT(short)
|
||||||
|
AC_DEFINE([NEED_SHORT_EXTERNAL_NAMES],)])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([to see if char is signed])
|
||||||
|
AC_TRY_RUN([
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int is_char_signed (int arg)
|
||||||
|
#else
|
||||||
|
int is_char_signed (arg)
|
||||||
|
int arg;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (arg == 189) { /* expected result for unsigned char */
|
||||||
|
return 0; /* type char is unsigned */
|
||||||
|
}
|
||||||
|
else if (arg != -67) { /* expected result for signed char */
|
||||||
|
printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
|
||||||
|
printf("I fear the JPEG software will not work at all.\n\n");
|
||||||
|
}
|
||||||
|
return 1; /* assume char is signed otherwise */
|
||||||
|
}
|
||||||
|
char signed_char_check = (char) (-67);
|
||||||
|
main() {
|
||||||
|
exit(is_char_signed((int) signed_char_check));
|
||||||
|
}],[AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE([CHAR_IS_UNSIGNED],)],[AC_MSG_RESULT(yes)],
|
||||||
|
[echo Assuming that char is signed on target machine.
|
||||||
|
echo If it is unsigned, this will be a little bit inefficient.
|
||||||
|
])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([to see if right shift is signed])
|
||||||
|
AC_TRY_RUN([
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
int is_shifting_signed (long arg)
|
||||||
|
#else
|
||||||
|
int is_shifting_signed (arg)
|
||||||
|
long arg;
|
||||||
|
#endif
|
||||||
|
/* See whether right-shift on a long is signed or not. */
|
||||||
|
{
|
||||||
|
long res = arg >> 4;
|
||||||
|
|
||||||
|
if (res == -0x7F7E80CL) { /* expected result for signed shift */
|
||||||
|
return 1; /* right shift is signed */
|
||||||
|
}
|
||||||
|
/* see if unsigned-shift hack will fix it. */
|
||||||
|
/* we can't just test exact value since it depends on width of long... */
|
||||||
|
res |= (~0L) << (32-4);
|
||||||
|
if (res == -0x7F7E80CL) { /* expected result now? */
|
||||||
|
return 0; /* right shift is unsigned */
|
||||||
|
}
|
||||||
|
printf("Right shift isn't acting as I expect it to.\n");
|
||||||
|
printf("I fear the JPEG software will not work at all.\n\n");
|
||||||
|
return 0; /* try it with unsigned anyway */
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
exit(is_shifting_signed(-0x7F7E80B1L));
|
||||||
|
}],[AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE([RIGHT_SHIFT_IS_UNSIGNED],)],[AC_MSG_RESULT(yes)],
|
||||||
|
[AC_MSG_RESULT([Assuming that right shift is signed on target machine.])])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_MSG_CHECKING([to see if fopen accepts b spec])
|
||||||
|
AC_TRY_RUN([
|
||||||
|
#include <stdio.h>
|
||||||
|
main() {
|
||||||
|
if (fopen("conftestdata", "wb") != NULL)
|
||||||
|
exit(0);
|
||||||
|
exit(1);
|
||||||
|
}],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE([DONT_USE_B_MODE],)],[AC_MSG_RESULT([Assuming that it does.])])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_EXEEXT
|
||||||
|
|
||||||
|
# Decide whether to use libtool,
|
||||||
|
# and if so whether to build shared, static, or both flavors of library.
|
||||||
|
AC_DISABLE_SHARED
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
if test "x$enable_shared" != xno -o "x$enable_static" != xno; then
|
||||||
|
USELIBTOOL="yes"
|
||||||
|
# LIBTOOL="./libtool"
|
||||||
|
O="lo"
|
||||||
|
A="la"
|
||||||
|
LN='$(LIBTOOL) --mode=link $(CC)'
|
||||||
|
INSTALL_LIB='$(LIBTOOL) --mode=install ${INSTALL}'
|
||||||
|
INSTALL_PROGRAM="\$(LIBTOOL) --mode=install $INSTALL_PROGRAM"
|
||||||
|
UNINSTALL='$(LIBTOOL) --mode=uninstall $(RM)'
|
||||||
|
else
|
||||||
|
USELIBTOOL="no"
|
||||||
|
LIBTOOL=""
|
||||||
|
O="o"
|
||||||
|
A="a"
|
||||||
|
LN='$(CC)'
|
||||||
|
INSTALL_LIB="$INSTALL_DATA"
|
||||||
|
UNINSTALL='$(RM)'
|
||||||
|
fi
|
||||||
|
AC_SUBST([LIBTOOL])
|
||||||
|
AC_SUBST([O])
|
||||||
|
AC_SUBST([A])
|
||||||
|
AC_SUBST([LN])
|
||||||
|
AC_SUBST([INSTALL_LIB])
|
||||||
|
AC_SUBST([UNINSTALL])
|
||||||
|
|
||||||
|
# Configure libtool if needed.
|
||||||
|
if test $USELIBTOOL = yes; then
|
||||||
|
AC_LIBTOOL_DLOPEN
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
fi
|
||||||
|
# if libtool >= 1.5
|
||||||
|
TAGCC=ifdef([AC_LIBTOOL_GCJ],[--tag=CC])
|
||||||
|
AC_SUBST([TAGCC])
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
# Select memory manager depending on user input.
|
||||||
|
# If no "-enable-maxmem", use jmemnobs
|
||||||
|
MEMORYMGR='jmemnobs.$(O)'
|
||||||
|
MAXMEM="no"
|
||||||
|
AC_ARG_ENABLE([maxmem],
|
||||||
|
[ --enable-maxmem[=N] enable use of temp files, set max mem usage to N MB],
|
||||||
|
[MAXMEM="$enableval"])
|
||||||
|
# support --with-maxmem for backwards compatibility with IJG V5.
|
||||||
|
AC_ARG_WITH([maxmem],,[MAXMEM="$withval"])
|
||||||
|
if test "x$MAXMEM" = xyes; then
|
||||||
|
MAXMEM=1
|
||||||
|
fi
|
||||||
|
if test "x$MAXMEM" != xno; then
|
||||||
|
if test -n "`echo $MAXMEM | sed 's/[[0-9]]//g'`"; then
|
||||||
|
AC_MSG_ERROR([non-numeric argument to --enable-maxmem])
|
||||||
|
fi
|
||||||
|
DEFAULTMAXMEM=`expr $MAXMEM \* 1048576`
|
||||||
|
AC_DEFINE_UNQUOTED([DEFAULT_MAX_MEM],[${DEFAULTMAXMEM}])
|
||||||
|
AC_MSG_CHECKING([for 'tmpfile()'])
|
||||||
|
AC_TRY_LINK([#include <stdio.h>],[ FILE * tfile = tmpfile(); ],
|
||||||
|
[AC_MSG_RESULT(yes)
|
||||||
|
MEMORYMGR='jmemansi.$(O)'],
|
||||||
|
[AC_MSG_RESULT(no)
|
||||||
|
MEMORYMGR='jmemname.$(O)'
|
||||||
|
AC_DEFINE([NEED_SIGNAL_CATCHER],)
|
||||||
|
AC_MSG_CHECKING([for 'mktemp()'])
|
||||||
|
AC_TRY_LINK(,[ char fname[80]; mktemp(fname); ],
|
||||||
|
[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE([NO_MKTEMP],)])])
|
||||||
|
fi
|
||||||
|
AC_SUBST([MEMORYMGR])
|
||||||
|
|
||||||
|
dnl ====================================================================
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([to see if the host cpu type is i386 or compatible])
|
||||||
|
case "$host_cpu" in
|
||||||
|
i*86 | x86 | ia32)
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
;;
|
||||||
|
x86_64 | amd64 | aa64)
|
||||||
|
AC_MSG_RESULT([no (x86_64)])
|
||||||
|
AC_MSG_ERROR([Currently, this version of JPEG library cannot be compiled as 64-bit code. sorry.])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_RESULT([no ("$host_cpu")])
|
||||||
|
AC_MSG_ERROR([This version of JPEG library is for i386 or compatible processors only.])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -z "$NAFLAGS" ; then
|
||||||
|
AC_MSG_CHECKING([for object file format of host system])
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32* | interix*)
|
||||||
|
objfmt='Win32-COFF'
|
||||||
|
;;
|
||||||
|
msdosdjgpp* | go32*)
|
||||||
|
objfmt='COFF'
|
||||||
|
;;
|
||||||
|
os2-emx*) # not tested
|
||||||
|
objfmt='MSOMF' # obj
|
||||||
|
;;
|
||||||
|
linux*coff* | linux*oldld*)
|
||||||
|
objfmt='COFF' # ???
|
||||||
|
;;
|
||||||
|
linux*aout*)
|
||||||
|
objfmt='a.out'
|
||||||
|
;;
|
||||||
|
linux*)
|
||||||
|
objfmt='ELF'
|
||||||
|
;;
|
||||||
|
freebsd* | netbsd* | openbsd*)
|
||||||
|
if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
|
||||||
|
objfmt='BSD-a.out'
|
||||||
|
else
|
||||||
|
objfmt='ELF'
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
solaris* | sunos* | sysv* | sco*)
|
||||||
|
objfmt='ELF'
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody* | nextstep* | openstep* | macos*)
|
||||||
|
objfmt='Mach-O'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
objfmt='ELF ?'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT([$objfmt])
|
||||||
|
if test "$objfmt" = 'ELF ?'; then
|
||||||
|
objfmt='ELF'
|
||||||
|
AC_MSG_WARN([unexpected host system. assumed that the format is $objfmt.])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
objfmt=''
|
||||||
|
fi
|
||||||
|
AC_MSG_CHECKING([for object file format specifier (NAFLAGS) ])
|
||||||
|
case "$objfmt" in
|
||||||
|
MSOMF) NAFLAGS='-fobj -DOBJ32';;
|
||||||
|
Win32-COFF) NAFLAGS='-fwin32 -DWIN32';;
|
||||||
|
COFF) NAFLAGS='-fcoff -DCOFF';;
|
||||||
|
a.out) NAFLAGS='-faout -DAOUT';;
|
||||||
|
BSD-a.out) NAFLAGS='-faoutb -DAOUT';;
|
||||||
|
ELF) NAFLAGS='-felf -DELF';;
|
||||||
|
RDF) NAFLAGS='-frdf -DRDF';;
|
||||||
|
Mach-O) NAFLAGS='-fmacho -DMACHO';;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT([$NAFLAGS])
|
||||||
|
AC_SUBST([NAFLAGS])
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_CHECK_PROGS(NASM, [nasm nasmw])
|
||||||
|
test -z "$NASM" && AC_MSG_ERROR([no nasm (Netwide Assembler) found in \$PATH])
|
||||||
|
if echo "$NASM" | grep yasm > /dev/null; then
|
||||||
|
AC_MSG_WARN([DON'T USE YASM! CURRENT VERSION (R0.4.0) IS BUGGY!])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether the assembler ($NASM $NAFLAGS) works])
|
||||||
|
cat > conftest.asm <<EOF
|
||||||
|
[%line __oline__ "configure"
|
||||||
|
section .text
|
||||||
|
bits 32
|
||||||
|
global _main,main
|
||||||
|
_main:
|
||||||
|
main: xor eax,eax
|
||||||
|
ret
|
||||||
|
]EOF
|
||||||
|
try_nasm='$NASM $NAFLAGS -o conftest.o conftest.asm'
|
||||||
|
if AC_TRY_EVAL(try_nasm) && test -s conftest.o; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
echo "configure: failed program was:" >&AC_FD_CC
|
||||||
|
cat conftest.asm >&AC_FD_CC
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_ERROR([installation or configuration problem: assembler cannot create object files.])
|
||||||
|
fi
|
||||||
|
AC_MSG_CHECKING([whether the linker accepts assembler output])
|
||||||
|
try_nasm='${CC-cc} -o conftest${ac_exeext} $LDFLAGS conftest.o $LIBS 1>&AC_FD_CC'
|
||||||
|
if AC_TRY_EVAL(try_nasm) && test -s conftest${ac_exeext}; then
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_ERROR([configuration problem: maybe object file format mismatch.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether the assembler supports line continuation character])
|
||||||
|
cat > conftest.asm <<\EOF
|
||||||
|
[%line __oline__ "configure"
|
||||||
|
; The line continuation character '\'
|
||||||
|
; was introduced in nasm 0.98.25.
|
||||||
|
section .text
|
||||||
|
bits 32
|
||||||
|
global _zero
|
||||||
|
_zero: xor \
|
||||||
|
eax,eax
|
||||||
|
ret
|
||||||
|
]EOF
|
||||||
|
try_nasm='$NASM $NAFLAGS -o conftest.o conftest.asm'
|
||||||
|
if AC_TRY_EVAL(try_nasm) && test -s conftest.o; then
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
echo "configure: failed program was:" >&AC_FD_CC
|
||||||
|
cat conftest.asm >&AC_FD_CC
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_ERROR([you have to use a more recent version of the assembler.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([SIMD instruction sets requested to use])
|
||||||
|
simd_to_use=""
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(mmx,
|
||||||
|
[ --disable-mmx do not use MMX instruction set],
|
||||||
|
[if test "x$enableval" = xno; then
|
||||||
|
AC_DEFINE([JSIMD_MMX_NOT_SUPPORTED],)
|
||||||
|
else
|
||||||
|
simd_to_use="$simd_to_use MMX"
|
||||||
|
fi], [simd_to_use="$simd_to_use MMX"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(3dnow,
|
||||||
|
[ --disable-3dnow do not use 3DNow! instruction set],
|
||||||
|
[if test "x$enableval" = xno; then
|
||||||
|
AC_DEFINE([JSIMD_3DNOW_NOT_SUPPORTED],)
|
||||||
|
else
|
||||||
|
simd_to_use="$simd_to_use 3DNow!"
|
||||||
|
fi], [simd_to_use="$simd_to_use 3DNow!"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(sse,
|
||||||
|
[ --disable-sse do not use SSE instruction set],
|
||||||
|
[if test "x$enableval" = xno; then
|
||||||
|
AC_DEFINE([JSIMD_SSE_NOT_SUPPORTED],)
|
||||||
|
else
|
||||||
|
simd_to_use="$simd_to_use SSE"
|
||||||
|
fi], [simd_to_use="$simd_to_use SSE"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(sse2,
|
||||||
|
[ --disable-sse2 do not use SSE2 instruction set],
|
||||||
|
[if test "x$enableval" = xno; then
|
||||||
|
AC_DEFINE([JSIMD_SSE2_NOT_SUPPORTED],)
|
||||||
|
else
|
||||||
|
simd_to_use="$simd_to_use SSE2"
|
||||||
|
fi], [simd_to_use="$simd_to_use SSE2"])
|
||||||
|
|
||||||
|
test -z "$simd_to_use" && simd_to_use="NONE"
|
||||||
|
AC_MSG_RESULT([$simd_to_use])
|
||||||
|
|
||||||
|
for simd_name in $simd_to_use; do
|
||||||
|
case "$simd_name" in
|
||||||
|
MMX) simd_instruction='psubw mm0,mm0';;
|
||||||
|
3DNow!) simd_instruction='pfsub mm0,mm0';;
|
||||||
|
SSE) simd_instruction='subps xmm0,xmm0';;
|
||||||
|
SSE2) simd_instruction='subpd xmm0,xmm0';;
|
||||||
|
*) continue;;
|
||||||
|
esac
|
||||||
|
AC_MSG_CHECKING([whether the assembler supports $simd_name instructions])
|
||||||
|
cat > conftest.asm <<EOF
|
||||||
|
[%line __oline__ "configure"
|
||||||
|
section .text
|
||||||
|
bits 32
|
||||||
|
global _simd
|
||||||
|
_simd: $simd_instruction
|
||||||
|
ret
|
||||||
|
]EOF
|
||||||
|
try_nasm='$NASM $NAFLAGS -o conftest.o conftest.asm'
|
||||||
|
if AC_TRY_EVAL(try_nasm) && test -s conftest.o; then
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
echo "configure: failed program was:" >&AC_FD_CC
|
||||||
|
cat conftest.asm >&AC_FD_CC
|
||||||
|
rm -rf conftest*
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_ERROR([you have to use a more recent version of the assembler.])
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
# Select OS-dependent SIMD instruction support checker.
|
||||||
|
# jsimdw32.$(O) (Win32) / jsimddjg.$(O) (DJGPP V.2) / jsimdgcc.$(O) (Unix/gcc)
|
||||||
|
if test "x$SIMDCHECKER" = x ; then
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32* | interix*)
|
||||||
|
SIMDCHECKER='jsimdw32.$(O)'
|
||||||
|
;;
|
||||||
|
msdosdjgpp* | go32*)
|
||||||
|
SIMDCHECKER='jsimddjg.$(O)'
|
||||||
|
;;
|
||||||
|
os2-emx*) # not tested
|
||||||
|
SIMDCHECKER='jsimdgcc.$(O)'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
SIMDCHECKER='jsimdgcc.$(O)'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
AC_SUBST([SIMDCHECKER])
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32* | os2-emx* | msdosdjgpp* | go32*)
|
||||||
|
AC_DEFINE([USE_SETMODE],)
|
||||||
|
;;
|
||||||
|
# _host_name_*)
|
||||||
|
# AC_DEFINE([USE_FDOPEN],)
|
||||||
|
# ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# This is for UNIX-like environments on Windows platform.
|
||||||
|
AC_ARG_ENABLE(uchar-boolean,
|
||||||
|
[ --enable-uchar-boolean define type \"boolean\" as unsigned char (for Windows)],
|
||||||
|
[if test "x$enableval" != xno; then
|
||||||
|
AC_DEFINE([TYPEDEF_UCHAR_BOOLEAN],)
|
||||||
|
fi])
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
|
||||||
|
JPEG_LIB_VERSION="63:0:1"
|
||||||
|
confv_dirs="$srcdir $srcdir/.. $srcdir/../.."
|
||||||
|
config_ver=
|
||||||
|
for ac_dir in $confv_dirs; do
|
||||||
|
if test -r $ac_dir/config.ver; then
|
||||||
|
config_ver=$ac_dir/config.ver
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$config_ver"; then
|
||||||
|
AC_MSG_WARN([cannot find config.ver in $confv_dirs])
|
||||||
|
AC_MSG_WARN([default version number $JPEG_LIB_VERSION is used])
|
||||||
|
AC_MSG_CHECKING([libjpeg version number for libtool])
|
||||||
|
AC_MSG_RESULT([$JPEG_LIB_VERSION])
|
||||||
|
else
|
||||||
|
AC_MSG_CHECKING([libjpeg version number for libtool])
|
||||||
|
. $config_ver
|
||||||
|
AC_MSG_RESULT([$JPEG_LIB_VERSION])
|
||||||
|
echo "configure: if you want to change the version number, modify $config_ver" 1>&2
|
||||||
|
fi
|
||||||
|
AC_SUBST([JPEG_LIB_VERSION])
|
||||||
|
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
# Prepare to massage makefile.cfg correctly.
|
||||||
|
if test $ijg_cv_have_prototypes = yes; then
|
||||||
|
A2K_DEPS=""
|
||||||
|
COM_A2K="# "
|
||||||
|
else
|
||||||
|
A2K_DEPS="ansi2knr"
|
||||||
|
COM_A2K=""
|
||||||
|
fi
|
||||||
|
AC_SUBST([A2K_DEPS])
|
||||||
|
AC_SUBST([COM_A2K])
|
||||||
|
# ansi2knr needs -DBSD if string.h is missing
|
||||||
|
if test $ac_cv_header_string_h = no; then
|
||||||
|
ANSI2KNRFLAGS="-DBSD"
|
||||||
|
else
|
||||||
|
ANSI2KNRFLAGS=""
|
||||||
|
fi
|
||||||
|
AC_SUBST([ANSI2KNRFLAGS])
|
||||||
|
# Substitutions to enable or disable libtool-related stuff
|
||||||
|
if test $USELIBTOOL = yes -a $ijg_cv_have_prototypes = yes; then
|
||||||
|
COM_LT=""
|
||||||
|
else
|
||||||
|
COM_LT="# "
|
||||||
|
fi
|
||||||
|
AC_SUBST([COM_LT])
|
||||||
|
if test "x$enable_shared" != xno; then
|
||||||
|
FORCE_INSTALL_LIB="install-lib"
|
||||||
|
UNINSTALL_LIB="uninstall-lib"
|
||||||
|
else
|
||||||
|
FORCE_INSTALL_LIB=""
|
||||||
|
UNINSTALL_LIB=""
|
||||||
|
fi
|
||||||
|
AC_SUBST([FORCE_INSTALL_LIB])
|
||||||
|
AC_SUBST([UNINSTALL_LIB])
|
||||||
|
# Set up -I directives
|
||||||
|
if test "x$srcdir" = x.; then
|
||||||
|
INCLUDEFLAGS='-I$(srcdir)'
|
||||||
|
else
|
||||||
|
INCLUDEFLAGS='-I. -I$(srcdir)'
|
||||||
|
fi
|
||||||
|
AC_SUBST([INCLUDEFLAGS])
|
||||||
|
dnl --------------------------------------------------------------------
|
||||||
|
AC_OUTPUT([Makefile:makefile.cfg])
|
||||||
275
djpeg.1
275
djpeg.1
@@ -1,13 +1,10 @@
|
|||||||
.TH DJPEG 1 "11 December 1991"
|
.TH DJPEG 1 "22 August 1997"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
djpeg \- decompress a JPEG file to an image file
|
djpeg \- decompress a JPEG file to an image file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B djpeg
|
.B djpeg
|
||||||
[
|
[
|
||||||
.B \-GPRTbgD2d
|
.I options
|
||||||
]
|
|
||||||
[
|
|
||||||
.BI \-q " N"
|
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
.I filename
|
.I filename
|
||||||
@@ -17,98 +14,240 @@ djpeg \- decompress a JPEG file to an image file
|
|||||||
.LP
|
.LP
|
||||||
.B djpeg
|
.B djpeg
|
||||||
decompresses the named JPEG file, or the standard input if no file is named,
|
decompresses the named JPEG file, or the standard input if no file is named,
|
||||||
and produces an image file on the standard output. PPM, GIF, Targa, or RLE
|
and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP,
|
||||||
output format can be selected. (RLE is supported only if the URT library is
|
GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected.
|
||||||
available.)
|
(RLE is supported only if the URT library is available.)
|
||||||
.LP
|
|
||||||
The color quantization algorithm is currently shoddy. Because of this, the
|
|
||||||
GIF output mode is not recommended in the current release, except for
|
|
||||||
gray-scale output (obtained with
|
|
||||||
.BR \-g ).
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
All switch names may be abbreviated; for example,
|
||||||
|
.B \-grayscale
|
||||||
|
may be written
|
||||||
|
.B \-gray
|
||||||
|
or
|
||||||
|
.BR \-gr .
|
||||||
|
Most of the "basic" switches can be abbreviated to as little as one letter.
|
||||||
|
Upper and lower case are equivalent (thus
|
||||||
|
.B \-BMP
|
||||||
|
is the same as
|
||||||
|
.BR \-bmp ).
|
||||||
|
British spellings are also accepted (e.g.,
|
||||||
|
.BR \-greyscale ),
|
||||||
|
though for brevity these are not mentioned below.
|
||||||
|
.PP
|
||||||
|
The basic switches are:
|
||||||
.TP
|
.TP
|
||||||
.B \-G
|
.BI \-colors " N"
|
||||||
Select GIF output format (implies
|
Reduce image to at most N colors. This reduces the number of colors used in
|
||||||
.BR \-q ,
|
the output image, so that it can be displayed on a colormapped display or
|
||||||
with default of 256 colors).
|
stored in a colormapped file format. For example, if you have an 8-bit
|
||||||
Currently the color quantization uses a shoddy algorithm and external
|
display, you'd need to reduce to 256 or fewer colors.
|
||||||
quantization (e.g.
|
|
||||||
.IR ppmquant ,
|
|
||||||
.IR rlequant )
|
|
||||||
is recommended before conversion to GIF format.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-P
|
.BI \-quantize " N"
|
||||||
Select PPM or PGM output format (this is the default). PGM is emitted if the
|
Same as
|
||||||
JPEG file is gray-scale or if
|
.BR \-colors .
|
||||||
.B \-g
|
.B \-colors
|
||||||
is specified.
|
is the recommended name,
|
||||||
|
.B \-quantize
|
||||||
|
is provided only for backwards compatibility.
|
||||||
.TP
|
.TP
|
||||||
.B \-R
|
.B \-fast
|
||||||
Select RLE output format. Requires URT library.
|
Select recommended processing options for fast, low quality output. (The
|
||||||
|
default options are chosen for highest quality output.) Currently, this is
|
||||||
|
equivalent to \fB\-dct fast \-nosmooth \-onepass \-dither ordered\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-T
|
.B \-grayscale
|
||||||
|
Force gray-scale output even if JPEG file is color. Useful for viewing on
|
||||||
|
monochrome displays; also,
|
||||||
|
.B djpeg
|
||||||
|
runs noticeably faster in this mode.
|
||||||
|
.TP
|
||||||
|
.BI \-scale " M/N"
|
||||||
|
Scale the output image by a factor M/N. Currently the scale factor must be
|
||||||
|
1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your
|
||||||
|
screen; also,
|
||||||
|
.B djpeg
|
||||||
|
runs much faster when scaling down the output.
|
||||||
|
.TP
|
||||||
|
.B \-bmp
|
||||||
|
Select BMP output format (Windows flavor). 8-bit colormapped format is
|
||||||
|
emitted if
|
||||||
|
.B \-colors
|
||||||
|
or
|
||||||
|
.B \-grayscale
|
||||||
|
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
|
||||||
|
format is emitted.
|
||||||
|
.TP
|
||||||
|
.B \-gif
|
||||||
|
Select GIF output format. Since GIF does not support more than 256 colors,
|
||||||
|
.B \-colors 256
|
||||||
|
is assumed (unless you specify a smaller number of colors).
|
||||||
|
.TP
|
||||||
|
.B \-os2
|
||||||
|
Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is
|
||||||
|
emitted if
|
||||||
|
.B \-colors
|
||||||
|
or
|
||||||
|
.B \-grayscale
|
||||||
|
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color
|
||||||
|
format is emitted.
|
||||||
|
.TP
|
||||||
|
.B \-pnm
|
||||||
|
Select PBMPLUS (PPM/PGM) output format (this is the default format).
|
||||||
|
PGM is emitted if the JPEG file is gray-scale or if
|
||||||
|
.B \-grayscale
|
||||||
|
is specified; otherwise PPM is emitted.
|
||||||
|
.TP
|
||||||
|
.B \-rle
|
||||||
|
Select RLE output format. (Requires URT library.)
|
||||||
|
.TP
|
||||||
|
.B \-targa
|
||||||
Select Targa output format. Gray-scale format is emitted if the JPEG file is
|
Select Targa output format. Gray-scale format is emitted if the JPEG file is
|
||||||
gray-scale or if
|
gray-scale or if
|
||||||
.B \-g
|
.B \-grayscale
|
||||||
is specified; otherwise, colormapped format is emitted if
|
is specified; otherwise, colormapped format is emitted if
|
||||||
.B \-q
|
.B \-colors
|
||||||
is specified; otherwise, 24-bit full-color format is emitted.
|
is specified; otherwise, 24-bit full-color format is emitted.
|
||||||
|
.PP
|
||||||
|
Switches for advanced users:
|
||||||
.TP
|
.TP
|
||||||
.B \-b
|
.B \-dct int
|
||||||
Perform cross-block smoothing. This is quite memory-intensive and only seems
|
Use integer DCT method (default).
|
||||||
to improve the image at low quality settings (\fB\-Q\fR 10 to 20 or so).
|
|
||||||
At normal
|
|
||||||
.B \-Q
|
|
||||||
settings it may make the image worse.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-g
|
.B \-dct fast
|
||||||
Force gray-scale output even if input is color.
|
Use fast integer DCT (less accurate).
|
||||||
.TP
|
.TP
|
||||||
.BI \-q " N"
|
.B \-dct float
|
||||||
Quantize to N colors.
|
Use floating-point DCT method.
|
||||||
|
The float method is very slightly more accurate than the int method, but is
|
||||||
|
much slower unless your machine has very fast floating-point hardware. Also
|
||||||
|
note that results of the floating-point method may vary slightly across
|
||||||
|
machines, while the integer methods should give the same results everywhere.
|
||||||
|
The fast integer method is much less accurate than the other two.
|
||||||
.TP
|
.TP
|
||||||
.B \-D
|
.B \-dither fs
|
||||||
Do not use dithering in color quantization. By default, Floyd-Steinberg
|
Use Floyd-Steinberg dithering in color quantization.
|
||||||
dithering is applied when quantizing colors, but on some images dithering may
|
|
||||||
result in objectionable "graininess". If that happens, you can turn off
|
|
||||||
dithering with
|
|
||||||
.BR \-D .
|
|
||||||
.TP
|
.TP
|
||||||
.B \-2
|
.B \-dither ordered
|
||||||
Use two-pass color quantization (not yet supported).
|
Use ordered dithering in color quantization.
|
||||||
.TP
|
.TP
|
||||||
.B \-d
|
.B \-dither none
|
||||||
|
Do not use dithering in color quantization.
|
||||||
|
By default, Floyd-Steinberg dithering is applied when quantizing colors; this
|
||||||
|
is slow but usually produces the best results. Ordered dither is a compromise
|
||||||
|
between speed and quality; no dithering is fast but usually looks awful. Note
|
||||||
|
that these switches have no effect unless color quantization is being done.
|
||||||
|
Ordered dither is only available in
|
||||||
|
.B \-onepass
|
||||||
|
mode.
|
||||||
|
.TP
|
||||||
|
.BI \-map " file"
|
||||||
|
Quantize to the colors used in the specified image file. This is useful for
|
||||||
|
producing multiple files with identical color maps, or for forcing a
|
||||||
|
predefined set of colors to be used. The
|
||||||
|
.I file
|
||||||
|
must be a GIF or PPM file. This option overrides
|
||||||
|
.B \-colors
|
||||||
|
and
|
||||||
|
.BR \-onepass .
|
||||||
|
.TP
|
||||||
|
.B \-nosmooth
|
||||||
|
Use a faster, lower-quality upsampling routine.
|
||||||
|
.TP
|
||||||
|
.B \-onepass
|
||||||
|
Use one-pass instead of two-pass color quantization. The one-pass method is
|
||||||
|
faster and needs less memory, but it produces a lower-quality image.
|
||||||
|
.B \-onepass
|
||||||
|
is ignored unless you also say
|
||||||
|
.B \-colors
|
||||||
|
.IR N .
|
||||||
|
Also, the one-pass method is always used for gray-scale output (the two-pass
|
||||||
|
method is no improvement then).
|
||||||
|
.TP
|
||||||
|
.BI \-maxmemory " N"
|
||||||
|
Set limit for amount of memory to use in processing large images. Value is
|
||||||
|
in thousands of bytes, or millions of bytes if "M" is attached to the
|
||||||
|
number. For example,
|
||||||
|
.B \-max 4m
|
||||||
|
selects 4000000 bytes. If more space is needed, temporary files will be used.
|
||||||
|
.TP
|
||||||
|
.BI \-outfile " name"
|
||||||
|
Send output image to the named file, not to standard output.
|
||||||
|
.TP
|
||||||
|
.B \-verbose
|
||||||
Enable debug printout. More
|
Enable debug printout. More
|
||||||
.BR \-d 's
|
.BR \-v 's
|
||||||
give more output. Also, version information is printed at startup.
|
give more output. Also, version information is printed at startup.
|
||||||
|
.TP
|
||||||
|
.B \-debug
|
||||||
|
Same as
|
||||||
|
.BR \-verbose .
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.LP
|
.LP
|
||||||
This example decompresses the JPEG file foo.jpg and saves the output
|
This example decompresses the JPEG file foo.jpg, quantizes it to
|
||||||
as a gray-scale image in foo.pgm:
|
256 colors, and saves the output in 8-bit BMP format in foo.bmp:
|
||||||
.IP
|
.IP
|
||||||
.B djpeg \-g
|
.B djpeg \-colors 256 \-bmp
|
||||||
.I foo.jpg
|
.I foo.jpg
|
||||||
.B >
|
.B >
|
||||||
.I foo.pgm
|
.I foo.bmp
|
||||||
|
.SH HINTS
|
||||||
|
To get a quick preview of an image, use the
|
||||||
|
.B \-grayscale
|
||||||
|
and/or
|
||||||
|
.B \-scale
|
||||||
|
switches.
|
||||||
|
.B \-grayscale \-scale 1/8
|
||||||
|
is the fastest case.
|
||||||
|
.PP
|
||||||
|
Several options are available that trade off image quality to gain speed.
|
||||||
|
.B \-fast
|
||||||
|
turns on the recommended settings.
|
||||||
|
.PP
|
||||||
|
.B \-dct fast
|
||||||
|
and/or
|
||||||
|
.B \-nosmooth
|
||||||
|
gain speed at a small sacrifice in quality.
|
||||||
|
When producing a color-quantized image,
|
||||||
|
.B \-onepass \-dither ordered
|
||||||
|
is fast but much lower quality than the default behavior.
|
||||||
|
.B \-dither none
|
||||||
|
may give acceptable results in two-pass mode, but is seldom tolerable in
|
||||||
|
one-pass mode.
|
||||||
|
.PP
|
||||||
|
If you are fortunate enough to have very fast floating point hardware,
|
||||||
|
\fB\-dct float\fR may be even faster than \fB\-dct fast\fR. But on most
|
||||||
|
machines \fB\-dct float\fR is slower than \fB\-dct int\fR; in this case it is
|
||||||
|
not worth using, because its theoretical accuracy advantage is too small to be
|
||||||
|
significant in practice.
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
.TP
|
||||||
|
.B JPEGMEM
|
||||||
|
If this environment variable is set, its value is the default memory limit.
|
||||||
|
The value is specified as described for the
|
||||||
|
.B \-maxmemory
|
||||||
|
switch.
|
||||||
|
.B JPEGMEM
|
||||||
|
overrides the default value specified when the program was compiled, and
|
||||||
|
itself is overridden by an explicit
|
||||||
|
.BR \-maxmemory .
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR cjpeg (1)
|
.BR cjpeg (1),
|
||||||
|
.BR jpegtran (1),
|
||||||
|
.BR rdjpgcom (1),
|
||||||
|
.BR wrjpgcom (1)
|
||||||
.br
|
.br
|
||||||
.BR ppmquant (1)
|
.BR ppm (5),
|
||||||
[From the PBMplus distribution]
|
.BR pgm (5)
|
||||||
.br
|
|
||||||
.BR rlequant (1)
|
|
||||||
[From the Utah Raster Toolkit distribution]
|
|
||||||
.br
|
.br
|
||||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||||
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
|
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Independent JPEG Group
|
Independent JPEG Group
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
.B djpeg
|
|
||||||
currently uses a shoddy color quantization algorithm. This leads to
|
|
||||||
poor GIF file output. Two-pass color quantization is not yet
|
|
||||||
supported.
|
|
||||||
.PP
|
|
||||||
Arithmetic coding is not supported for legal reasons.
|
Arithmetic coding is not supported for legal reasons.
|
||||||
.PP
|
.PP
|
||||||
Not as fast as we'd like.
|
To avoid the Unisys LZW patent,
|
||||||
|
.B djpeg
|
||||||
|
produces uncompressed GIF files. These are larger than they should be, but
|
||||||
|
are readable by standard GIF decoders.
|
||||||
|
.PP
|
||||||
|
Still not as fast as we'd like.
|
||||||
|
|||||||
684
djpeg.c
Normal file
684
djpeg.c
Normal file
@@ -0,0 +1,684 @@
|
|||||||
|
/*
|
||||||
|
* djpeg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : August 23, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains a command-line user interface for the JPEG decompressor.
|
||||||
|
* It should work on any system with Unix- or MS-DOS-style command lines.
|
||||||
|
*
|
||||||
|
* Two different command line styles are permitted, depending on the
|
||||||
|
* compile-time switch TWO_FILE_COMMANDLINE:
|
||||||
|
* djpeg [options] inputfile outputfile
|
||||||
|
* djpeg [options] [inputfile]
|
||||||
|
* In the second style, output is always to standard output, which you'd
|
||||||
|
* normally redirect to a file or pipe to some other program. Input is
|
||||||
|
* either from a named file or from standard input (typically redirected).
|
||||||
|
* The second style is convenient on Unix but is unhelpful on systems that
|
||||||
|
* don't support pipes. Also, you MUST use the first style if your system
|
||||||
|
* doesn't do binary I/O to stdin/stdout.
|
||||||
|
* To simplify script writing, the "-outfile" switch is provided. The syntax
|
||||||
|
* djpeg [options] -outfile outputfile inputfile
|
||||||
|
* works regardless of which command line style is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||||
|
#include "jversion.h" /* for version message */
|
||||||
|
|
||||||
|
#include <ctype.h> /* to declare isprint() */
|
||||||
|
|
||||||
|
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||||
|
#ifdef __MWERKS__
|
||||||
|
#include <SIOUX.h> /* Metrowerks needs this */
|
||||||
|
#include <console.h> /* ... and this */
|
||||||
|
#endif
|
||||||
|
#ifdef THINK_C
|
||||||
|
#include <console.h> /* Think declares it here */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the add-on message string table. */
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) string ,
|
||||||
|
|
||||||
|
static const char * const cdjpeg_message_table[] = {
|
||||||
|
#include "cderror.h"
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This list defines the known output image formats
|
||||||
|
* (not all of which need be supported by a given version).
|
||||||
|
* You can change the default output format by defining DEFAULT_FMT;
|
||||||
|
* indeed, you had better do so if you undefine PPM_SUPPORTED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FMT_BMP, /* BMP format (Windows flavor) */
|
||||||
|
FMT_GIF, /* GIF format */
|
||||||
|
FMT_OS2, /* BMP format (OS/2 flavor) */
|
||||||
|
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
|
||||||
|
FMT_RLE, /* RLE format */
|
||||||
|
FMT_TARGA, /* Targa format */
|
||||||
|
FMT_TIFF /* TIFF format */
|
||||||
|
} IMAGE_FORMATS;
|
||||||
|
|
||||||
|
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
|
||||||
|
#define DEFAULT_FMT FMT_PPM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static IMAGE_FORMATS requested_fmt;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argument-parsing code.
|
||||||
|
* The switch parser is designed to be useful with DOS-style command line
|
||||||
|
* syntax, ie, intermixed switches and file names, where only the switches
|
||||||
|
* to the left of a given file name affect processing of that file.
|
||||||
|
* The main program in this file doesn't actually use this capability...
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static const char * progname; /* program name for error messages */
|
||||||
|
static char * outfilename; /* for -outfile switch */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
usage (void)
|
||||||
|
/* complain about bad command line */
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [switches] ", progname);
|
||||||
|
#ifdef TWO_FILE_COMMANDLINE
|
||||||
|
fprintf(stderr, "inputfile outputfile\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "[inputfile]\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||||
|
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
|
||||||
|
fprintf(stderr, " -fast Fast, low-quality processing\n");
|
||||||
|
fprintf(stderr, " -grayscale Force grayscale output\n");
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
|
||||||
|
#endif
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
fprintf(stderr, " -gif Select GIF output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
fprintf(stderr, " -targa Select Targa output format%s\n",
|
||||||
|
(DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "Switches for advanced users:\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
|
||||||
|
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
|
||||||
|
fprintf(stderr, " -dither none Don't use dithering in quantization\n");
|
||||||
|
fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
fprintf(stderr, " -map FILE Map to colors used in named image file\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
|
||||||
|
#ifdef QUANT_1PASS_SUPPORTED
|
||||||
|
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||||
|
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||||
|
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
print_simd_info (FILE * file, char * labelstr, unsigned int simd)
|
||||||
|
{
|
||||||
|
fprintf(file, "%s%s%s%s%s%s\n", labelstr,
|
||||||
|
simd & JSIMD_MMX ? " MMX" : "",
|
||||||
|
simd & JSIMD_3DNOW ? " 3DNow!" : "",
|
||||||
|
simd & JSIMD_SSE ? " SSE" : "",
|
||||||
|
simd & JSIMD_SSE2 ? " SSE2" : "",
|
||||||
|
simd == JSIMD_NONE ? " NONE" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
||||||
|
int last_file_arg_seen, boolean for_real)
|
||||||
|
/* Parse optional switches.
|
||||||
|
* Returns argv[] index of first file-name argument (== argc if none).
|
||||||
|
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||||
|
* they have presumably been processed in a previous iteration.
|
||||||
|
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||||
|
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int argn;
|
||||||
|
char * arg;
|
||||||
|
|
||||||
|
/* Set up default JPEG parameters. */
|
||||||
|
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
||||||
|
outfilename = NULL;
|
||||||
|
cinfo->err->trace_level = 0;
|
||||||
|
|
||||||
|
/* Scan command line options, adjust parameters */
|
||||||
|
|
||||||
|
for (argn = 1; argn < argc; argn++) {
|
||||||
|
arg = argv[argn];
|
||||||
|
if (*arg != '-') {
|
||||||
|
/* Not a switch, must be a file name argument */
|
||||||
|
if (argn <= last_file_arg_seen) {
|
||||||
|
outfilename = NULL; /* -outfile applies to just one input file */
|
||||||
|
continue; /* ignore this name if previously processed */
|
||||||
|
}
|
||||||
|
break; /* else done parsing switches */
|
||||||
|
}
|
||||||
|
arg++; /* advance past switch marker character */
|
||||||
|
|
||||||
|
if (keymatch(arg, "bmp", 1)) {
|
||||||
|
/* BMP output format. */
|
||||||
|
requested_fmt = FMT_BMP;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
|
||||||
|
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
|
||||||
|
/* Do color quantization. */
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1)
|
||||||
|
usage();
|
||||||
|
cinfo->desired_number_of_colors = val;
|
||||||
|
cinfo->quantize_colors = TRUE;
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
} else if (keymatch(arg, "nosimd" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_ALL);
|
||||||
|
} else if (keymatch(arg, "nommx" , 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_MMX);
|
||||||
|
} else if (keymatch(arg, "no3dnow", 3)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_3DNOW);
|
||||||
|
} else if (keymatch(arg, "nosse" , 4)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE);
|
||||||
|
} else if (keymatch(arg, "nosse2" , 6)) {
|
||||||
|
jpeg_simd_mask((j_common_ptr) cinfo, JSIMD_NONE, JSIMD_SSE2);
|
||||||
|
#endif /* !JSIMD_MASKFUNC_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) {
|
||||||
|
/* Select IDCT algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "int", 1)) {
|
||||||
|
cinfo->dct_method = JDCT_ISLOW;
|
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_IFAST;
|
||||||
|
} else if (keymatch(argv[argn], "float", 2)) {
|
||||||
|
cinfo->dct_method = JDCT_FLOAT;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "dither", 2)) {
|
||||||
|
/* Select dithering algorithm. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (keymatch(argv[argn], "fs", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_FS;
|
||||||
|
} else if (keymatch(argv[argn], "none", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_NONE;
|
||||||
|
} else if (keymatch(argv[argn], "ordered", 2)) {
|
||||||
|
cinfo->dither_mode = JDITHER_ORDERED;
|
||||||
|
} else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||||
|
/* Enable debug printouts. */
|
||||||
|
/* On first -d, print version identification */
|
||||||
|
static boolean printed_version = FALSE;
|
||||||
|
|
||||||
|
if (! printed_version) {
|
||||||
|
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
|
||||||
|
JVERSION, JCOPYRIGHT);
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nx86 SIMD extension for IJG JPEG library, version %s\n\n",
|
||||||
|
JPEG_SIMDEXT_VER_STR);
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "SIMD instructions supported by the system :",
|
||||||
|
jpeg_simd_support(NULL));
|
||||||
|
|
||||||
|
fprintf(stderr, "\n === SIMD Operation Modes ===\n");
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Accurate integer DCT (-dct int) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_ISLOW));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Fast integer DCT (-dct fast) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_IFAST));
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Floating-point DCT (-dct float) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_FLOAT));
|
||||||
|
#endif
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
print_simd_info(stderr, "Reduced-size DCT (-scale M/N) :",
|
||||||
|
jpeg_simd_inverse_dct(cinfo, JDCT_FLOAT+1));
|
||||||
|
#endif
|
||||||
|
print_simd_info(stderr, "High-quality upsampling (default) :",
|
||||||
|
jpeg_simd_upsampler(cinfo, TRUE));
|
||||||
|
print_simd_info(stderr, "Low-quality upsampling (-nosmooth) :",
|
||||||
|
jpeg_simd_upsampler(cinfo, FALSE));
|
||||||
|
print_simd_info(stderr, "Colorspace conversion (YCbCr->RGB) :",
|
||||||
|
jpeg_simd_color_deconverter(cinfo));
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
printed_version = TRUE;
|
||||||
|
}
|
||||||
|
cinfo->err->trace_level++;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "fast", 1)) {
|
||||||
|
/* Select recommended processing options for quick-and-dirty output. */
|
||||||
|
cinfo->two_pass_quantize = FALSE;
|
||||||
|
cinfo->dither_mode = JDITHER_ORDERED;
|
||||||
|
if (! cinfo->quantize_colors) /* don't override an earlier -colors */
|
||||||
|
cinfo->desired_number_of_colors = 216;
|
||||||
|
cinfo->dct_method = JDCT_FASTEST;
|
||||||
|
cinfo->do_fancy_upsampling = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "gif", 1)) {
|
||||||
|
/* GIF output format. */
|
||||||
|
requested_fmt = FMT_GIF;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
|
||||||
|
/* Force monochrome output. */
|
||||||
|
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "map", 3)) {
|
||||||
|
/* Quantize to a color map taken from an input file. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (for_real) { /* too expensive to do twice! */
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
|
||||||
|
FILE * mapfile;
|
||||||
|
|
||||||
|
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
read_color_map(cinfo, mapfile);
|
||||||
|
fclose(mapfile);
|
||||||
|
cinfo->quantize_colors = TRUE;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||||
|
long lval;
|
||||||
|
char ch = 'x';
|
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||||
|
usage();
|
||||||
|
if (ch == 'm' || ch == 'M')
|
||||||
|
lval *= 1000L;
|
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "nosmooth", 3)) {
|
||||||
|
/* Suppress fancy upsampling */
|
||||||
|
cinfo->do_fancy_upsampling = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "onepass", 3)) {
|
||||||
|
/* Use fast one-pass quantization. */
|
||||||
|
cinfo->two_pass_quantize = FALSE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "os2", 3)) {
|
||||||
|
/* BMP output format (OS/2 flavor). */
|
||||||
|
requested_fmt = FMT_OS2;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "outfile", 4)) {
|
||||||
|
/* Set output file name. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
outfilename = argv[argn]; /* save it away for later use */
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
|
||||||
|
/* PPM/PGM output format. */
|
||||||
|
requested_fmt = FMT_PPM;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "rle", 1)) {
|
||||||
|
/* RLE output format. */
|
||||||
|
requested_fmt = FMT_RLE;
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "scale", 1)) {
|
||||||
|
/* Scale the output image by a fraction M/N. */
|
||||||
|
if (++argn >= argc) /* advance to next argument */
|
||||||
|
usage();
|
||||||
|
if (sscanf(argv[argn], "%d/%d",
|
||||||
|
&cinfo->scale_num, &cinfo->scale_denom) != 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
} else if (keymatch(arg, "targa", 1)) {
|
||||||
|
/* Targa output format. */
|
||||||
|
requested_fmt = FMT_TARGA;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
usage(); /* bogus switch */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argn; /* return index of next arg (file name) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marker processor for COM and interesting APPn markers.
|
||||||
|
* This replaces the library's built-in processor, which just skips the marker.
|
||||||
|
* We want to print out the marker as text, to the extent possible.
|
||||||
|
* Note this code relies on a non-suspending data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(unsigned int)
|
||||||
|
jpeg_getc (j_decompress_ptr cinfo)
|
||||||
|
/* Read next byte */
|
||||||
|
{
|
||||||
|
struct jpeg_source_mgr * datasrc = cinfo->src;
|
||||||
|
|
||||||
|
if (datasrc->bytes_in_buffer == 0) {
|
||||||
|
if (! (*datasrc->fill_input_buffer) (cinfo))
|
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||||
|
}
|
||||||
|
datasrc->bytes_in_buffer--;
|
||||||
|
return GETJOCTET(*datasrc->next_input_byte++);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
print_text_marker (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
boolean traceit = (cinfo->err->trace_level >= 1);
|
||||||
|
INT32 length;
|
||||||
|
unsigned int ch;
|
||||||
|
unsigned int lastch = 0;
|
||||||
|
|
||||||
|
length = jpeg_getc(cinfo) << 8;
|
||||||
|
length += jpeg_getc(cinfo);
|
||||||
|
length -= 2; /* discount the length word itself */
|
||||||
|
|
||||||
|
if (traceit) {
|
||||||
|
if (cinfo->unread_marker == JPEG_COM)
|
||||||
|
fprintf(stderr, "Comment, length %ld:\n", (long) length);
|
||||||
|
else /* assume it is an APPn otherwise */
|
||||||
|
fprintf(stderr, "APP%d, length %ld:\n",
|
||||||
|
cinfo->unread_marker - JPEG_APP0, (long) length);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--length >= 0) {
|
||||||
|
ch = jpeg_getc(cinfo);
|
||||||
|
if (traceit) {
|
||||||
|
/* Emit the character in a readable form.
|
||||||
|
* Nonprintables are converted to \nnn form,
|
||||||
|
* while \ is converted to \\.
|
||||||
|
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
|
||||||
|
*/
|
||||||
|
if (ch == '\r') {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
} else if (ch == '\n') {
|
||||||
|
if (lastch != '\r')
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
fprintf(stderr, "\\\\");
|
||||||
|
} else if (isprint(ch)) {
|
||||||
|
putc(ch, stderr);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\\%03o", ch);
|
||||||
|
}
|
||||||
|
lastch = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traceit)
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct jpeg_decompress_struct cinfo;
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
struct cdjpeg_progress_mgr progress;
|
||||||
|
#endif
|
||||||
|
int file_index;
|
||||||
|
djpeg_dest_ptr dest_mgr = NULL;
|
||||||
|
FILE * input_file;
|
||||||
|
FILE * output_file;
|
||||||
|
JDIMENSION num_scanlines;
|
||||||
|
|
||||||
|
/* On Mac, fetch a command line. */
|
||||||
|
#ifdef USE_CCOMMAND
|
||||||
|
argc = ccommand(&argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (progname == NULL || progname[0] == 0)
|
||||||
|
progname = "djpeg"; /* in case C library doesn't provide it */
|
||||||
|
|
||||||
|
/* Initialize the JPEG decompression object with default error handling. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
/* Add some application-specific error messages (from cderror.h) */
|
||||||
|
jerr.addon_message_table = cdjpeg_message_table;
|
||||||
|
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
||||||
|
jerr.last_addon_message = JMSG_LASTADDONCODE;
|
||||||
|
|
||||||
|
/* Insert custom marker processor for COM and APP12.
|
||||||
|
* APP12 is used by some digital camera makers for textual info,
|
||||||
|
* so we provide the ability to display it as text.
|
||||||
|
* If you like, additional APPn marker types can be selected for display,
|
||||||
|
* but don't try to override APP0 or APP14 this way (see libjpeg.doc).
|
||||||
|
*/
|
||||||
|
jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
|
||||||
|
jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
|
||||||
|
|
||||||
|
/* Now safe to enable signal catcher. */
|
||||||
|
#ifdef NEED_SIGNAL_CATCHER
|
||||||
|
enable_signal_catcher((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Scan command line to find file names. */
|
||||||
|
/* It is convenient to use just one switch-parsing routine, but the switch
|
||||||
|
* values read here are ignored; we will rescan the switches after opening
|
||||||
|
* the input file.
|
||||||
|
* (Exception: tracing level set here controls verbosity for COM markers
|
||||||
|
* found during jpeg_read_header...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
|
||||||
|
|
||||||
|
#ifdef TWO_FILE_COMMANDLINE
|
||||||
|
/* Must have either -outfile switch or explicit output file name */
|
||||||
|
if (outfilename == NULL) {
|
||||||
|
if (file_index != argc-2) {
|
||||||
|
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||||
|
progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
outfilename = argv[file_index+1];
|
||||||
|
} else {
|
||||||
|
if (file_index != argc-1) {
|
||||||
|
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||||
|
progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Unix style: expect zero or one file name */
|
||||||
|
if (file_index < argc-1) {
|
||||||
|
fprintf(stderr, "%s: only one input file\n", progname);
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
#endif /* TWO_FILE_COMMANDLINE */
|
||||||
|
|
||||||
|
/* Open the input file. */
|
||||||
|
if (file_index < argc) {
|
||||||
|
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default input file is stdin */
|
||||||
|
input_file = read_stdin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the output file. */
|
||||||
|
if (outfilename != NULL) {
|
||||||
|
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default output file is stdout */
|
||||||
|
output_file = write_stdout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
start_progress_monitor((j_common_ptr) &cinfo, &progress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specify data source for decompression */
|
||||||
|
jpeg_stdio_src(&cinfo, input_file);
|
||||||
|
|
||||||
|
/* Read file header, set default decompression parameters */
|
||||||
|
(void) jpeg_read_header(&cinfo, TRUE);
|
||||||
|
|
||||||
|
/* Adjust default decompression parameters by re-parsing the options */
|
||||||
|
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
|
||||||
|
|
||||||
|
/* Initialize the output module now to let it override any crucial
|
||||||
|
* option settings (for instance, GIF wants to force color quantization).
|
||||||
|
*/
|
||||||
|
switch (requested_fmt) {
|
||||||
|
#ifdef BMP_SUPPORTED
|
||||||
|
case FMT_BMP:
|
||||||
|
dest_mgr = jinit_write_bmp(&cinfo, FALSE);
|
||||||
|
break;
|
||||||
|
case FMT_OS2:
|
||||||
|
dest_mgr = jinit_write_bmp(&cinfo, TRUE);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef GIF_SUPPORTED
|
||||||
|
case FMT_GIF:
|
||||||
|
dest_mgr = jinit_write_gif(&cinfo);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef PPM_SUPPORTED
|
||||||
|
case FMT_PPM:
|
||||||
|
dest_mgr = jinit_write_ppm(&cinfo);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLE_SUPPORTED
|
||||||
|
case FMT_RLE:
|
||||||
|
dest_mgr = jinit_write_rle(&cinfo);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef TARGA_SUPPORTED
|
||||||
|
case FMT_TARGA:
|
||||||
|
dest_mgr = jinit_write_targa(&cinfo);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dest_mgr->output_file = output_file;
|
||||||
|
|
||||||
|
/* Start decompressor */
|
||||||
|
(void) jpeg_start_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Write output file header */
|
||||||
|
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
||||||
|
|
||||||
|
/* Process data */
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
|
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||||
|
dest_mgr->buffer_height);
|
||||||
|
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
/* Hack: count final pass as done in case finish_output does an extra pass.
|
||||||
|
* The library won't have updated completed_passes.
|
||||||
|
*/
|
||||||
|
progress.pub.completed_passes = progress.pub.total_passes;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Finish decompression and release memory.
|
||||||
|
* I must do it in this order because output module has allocated memory
|
||||||
|
* of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
||||||
|
*/
|
||||||
|
(*dest_mgr->finish_output) (&cinfo, dest_mgr);
|
||||||
|
(void) jpeg_finish_decompress(&cinfo);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Close files, if we opened them */
|
||||||
|
if (input_file != stdin)
|
||||||
|
fclose(input_file);
|
||||||
|
if (output_file != stdout)
|
||||||
|
fclose(output_file);
|
||||||
|
|
||||||
|
#ifdef PROGRESS_REPORT
|
||||||
|
end_progress_monitor((j_common_ptr) &cinfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* All done. */
|
||||||
|
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
|
||||||
|
return 0; /* suppress no-return-value warnings */
|
||||||
|
}
|
||||||
286
egetopt.c
286
egetopt.c
@@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
* egetopt.c -- Extended 'getopt'.
|
|
||||||
*
|
|
||||||
* A while back, a public-domain version of getopt() was posted to the
|
|
||||||
* net. A bit later, a gentleman by the name of Keith Bostic made some
|
|
||||||
* enhancements and reposted it.
|
|
||||||
*
|
|
||||||
* In recent weeks (i.e., early-to-mid 1988) there's been some
|
|
||||||
* heated discussion in comp.lang.c about the merits and drawbacks
|
|
||||||
* of getopt(), especially with regard to its handling of '?'.
|
|
||||||
*
|
|
||||||
* In light of this, I have taken Mr. Bostic's public-domain getopt()
|
|
||||||
* and have made some changes that I hope will be considered to be
|
|
||||||
* improvements. I call this routine 'egetopt' ("Extended getopt").
|
|
||||||
* The default behavior of this routine is the same as that of getopt(),
|
|
||||||
* but it has some optional features that make it more useful. These
|
|
||||||
* options are controlled by the settings of some global variables.
|
|
||||||
* By not setting any of these extra global variables, you will have
|
|
||||||
* the same functionality as getopt(), which should satisfy those
|
|
||||||
* purists who believe getopt() is perfect and can never be improved.
|
|
||||||
* If, on the other hand, you are someone who isn't satisfied with the
|
|
||||||
* status quo, egetopt() may very well give you the added capabilities
|
|
||||||
* you want.
|
|
||||||
*
|
|
||||||
* Look at the enclosed README file for a description of egetopt()'s
|
|
||||||
* new features.
|
|
||||||
*
|
|
||||||
* The code was originally posted to the net as getopt.c by ...
|
|
||||||
*
|
|
||||||
* Keith Bostic
|
|
||||||
* ARPA: keith@seismo
|
|
||||||
* UUCP: seismo!keith
|
|
||||||
*
|
|
||||||
* Current version: added enhancements and comments, reformatted code.
|
|
||||||
*
|
|
||||||
* Lloyd Zusman
|
|
||||||
* Master Byte Software
|
|
||||||
* Los Gatos, California
|
|
||||||
* Internet: ljz@fx.com
|
|
||||||
* UUCP: ...!ames!fxgrp!ljz
|
|
||||||
*
|
|
||||||
* May, 1988
|
|
||||||
*
|
|
||||||
* Modified for use in free JPEG code:
|
|
||||||
*
|
|
||||||
* Ed Hanway
|
|
||||||
* UUCP: uunet!sisd!jeh
|
|
||||||
*
|
|
||||||
* October, 1991
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The original egetopt.c was written not to need stdio.h.
|
|
||||||
* For the JPEG code this is an unnecessary and unportable assumption.
|
|
||||||
* Also, we make all the variables and routines "static" to avoid
|
|
||||||
* possible conflicts with a system-library version of getopt.
|
|
||||||
*
|
|
||||||
* In the JPEG code, this file is compiled by #including it in jcmain.c
|
|
||||||
* or jdmain.c. Since ANSI2KNR does not process include files, we can't
|
|
||||||
* rely on it to convert function definitions to K&R style. Hence we
|
|
||||||
* provide both styles of function header with an explicit #ifdef PROTO (ick).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GVAR static /* make empty to export these variables */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* None of these constants are referenced in the executable portion of
|
|
||||||
* the code ... their sole purpose is to initialize global variables.
|
|
||||||
*/
|
|
||||||
#define BADCH (int)'?'
|
|
||||||
#define NEEDSEP (int)':'
|
|
||||||
#define MAYBESEP (int)'\0'
|
|
||||||
#define EMSG ""
|
|
||||||
#define START "-"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Here are all the pertinent global variables.
|
|
||||||
*/
|
|
||||||
GVAR int opterr = 1; /* if true, output error message */
|
|
||||||
GVAR int optind = 1; /* index into parent argv vector */
|
|
||||||
GVAR int optopt; /* character checked for validity */
|
|
||||||
GVAR int optbad = BADCH; /* character returned on error */
|
|
||||||
GVAR int optchar = 0; /* character that begins returned option */
|
|
||||||
GVAR int optneed = NEEDSEP; /* flag for mandatory argument */
|
|
||||||
GVAR int optmaybe = MAYBESEP; /* flag for optional argument */
|
|
||||||
GVAR const char *optarg; /* argument associated with option */
|
|
||||||
GVAR const char *optstart = START; /* list of characters that start options */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macros.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Conditionally print out an error message and return (depends on the
|
|
||||||
* setting of 'opterr').
|
|
||||||
*/
|
|
||||||
#define TELL(S) { \
|
|
||||||
if (opterr) \
|
|
||||||
fprintf(stderr, "%s%s%c\n", *nargv, (S), optopt); \
|
|
||||||
return (optbad); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This works similarly to index() and strchr(). I include it so that you
|
|
||||||
* don't need to be concerned as to which one your system has.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef PROTO
|
|
||||||
LOCAL const char *
|
|
||||||
_sindex (const char *string, int ch)
|
|
||||||
#else
|
|
||||||
LOCAL const char *
|
|
||||||
_sindex (string, ch)
|
|
||||||
const char *string;
|
|
||||||
int ch;
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (string != NULL) {
|
|
||||||
for (; *string != '\0'; ++string) {
|
|
||||||
if (*string == (char)ch) {
|
|
||||||
return (string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Here it is:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef PROTO
|
|
||||||
LOCAL int
|
|
||||||
egetopt (int nargc, char **nargv, const char *ostr)
|
|
||||||
#else
|
|
||||||
LOCAL int
|
|
||||||
egetopt (nargc, nargv, ostr)
|
|
||||||
int nargc;
|
|
||||||
char **nargv;
|
|
||||||
const char *ostr;
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static const char *place = EMSG; /* option letter processing */
|
|
||||||
register const char *oli; /* option letter list index */
|
|
||||||
register const char *osi = NULL; /* option start list index */
|
|
||||||
|
|
||||||
if (nargv == (char **)NULL) {
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nargc <= optind || nargv[optind] == NULL) {
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (place == NULL) {
|
|
||||||
place = EMSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update scanning pointer.
|
|
||||||
*/
|
|
||||||
if (*place == '\0') {
|
|
||||||
place = nargv[optind];
|
|
||||||
if (place == NULL) {
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
osi = _sindex(optstart, *place);
|
|
||||||
if (osi != NULL) {
|
|
||||||
optchar = (int)*osi;
|
|
||||||
}
|
|
||||||
if (optind >= nargc || osi == NULL || *++place == '\0') {
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Two adjacent, identical flag characters were found.
|
|
||||||
* This takes care of "--", for example.
|
|
||||||
*/
|
|
||||||
if (*place == place[-1]) {
|
|
||||||
++optind;
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the option is a separator or the option isn't in the list,
|
|
||||||
* we've got an error.
|
|
||||||
*/
|
|
||||||
optopt = (int)*place++;
|
|
||||||
oli = _sindex(ostr, optopt);
|
|
||||||
if (optopt == optneed || optopt == optmaybe || oli == NULL) {
|
|
||||||
/*
|
|
||||||
* If we're at the end of the current argument, bump the
|
|
||||||
* argument index.
|
|
||||||
*/
|
|
||||||
if (*place == '\0') {
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
TELL(": illegal option -- "); /* byebye */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If there is no argument indicator, then we don't even try to
|
|
||||||
* return an argument.
|
|
||||||
*/
|
|
||||||
++oli;
|
|
||||||
if (*oli == '\0' || (*oli != optneed && *oli != optmaybe)) {
|
|
||||||
/*
|
|
||||||
* If we're at the end of the current argument, bump the
|
|
||||||
* argument index.
|
|
||||||
*/
|
|
||||||
if (*place == '\0') {
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
optarg = NULL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If we're here, there's an argument indicator. It's handled
|
|
||||||
* differently depending on whether it's a mandatory or an
|
|
||||||
* optional argument.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* If there's no white space, use the rest of the
|
|
||||||
* string as the argument. In this case, it doesn't
|
|
||||||
* matter if the argument is mandatory or optional.
|
|
||||||
*/
|
|
||||||
if (*place != '\0') {
|
|
||||||
optarg = place;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If we're here, there's whitespace after the option.
|
|
||||||
*
|
|
||||||
* Is it a mandatory argument? If so, return the
|
|
||||||
* next command-line argument if there is one.
|
|
||||||
*/
|
|
||||||
else if (*oli == optneed) {
|
|
||||||
/*
|
|
||||||
* If we're at the end of the argument list, there
|
|
||||||
* isn't an argument and hence we have an error.
|
|
||||||
* Otherwise, make 'optarg' point to the argument.
|
|
||||||
*/
|
|
||||||
if (nargc <= ++optind) {
|
|
||||||
place = EMSG;
|
|
||||||
TELL(": option requires an argument -- ");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
optarg = nargv[optind];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If we're here it must have been an optional argument.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
if (nargc <= ++optind) {
|
|
||||||
place = EMSG;
|
|
||||||
optarg = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
optarg = nargv[optind];
|
|
||||||
if (optarg == NULL) {
|
|
||||||
place = EMSG;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If the next item begins with a flag
|
|
||||||
* character, we treat it like a new
|
|
||||||
* argument. This is accomplished by
|
|
||||||
* decrementing 'optind' and returning
|
|
||||||
* a null argument.
|
|
||||||
*/
|
|
||||||
else if (_sindex(optstart, *optarg) != NULL) {
|
|
||||||
--optind;
|
|
||||||
optarg = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
place = EMSG;
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return option letter.
|
|
||||||
*/
|
|
||||||
return (optopt);
|
|
||||||
}
|
|
||||||
433
example.c
Normal file
433
example.c
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
/*
|
||||||
|
* example.c
|
||||||
|
*
|
||||||
|
* This file illustrates how to use the IJG code as a subroutine library
|
||||||
|
* to read or write JPEG image files. You should look at this code in
|
||||||
|
* conjunction with the documentation file libjpeg.doc.
|
||||||
|
*
|
||||||
|
* This code will not do anything useful as-is, but it may be helpful as a
|
||||||
|
* skeleton for constructing routines that call the JPEG library.
|
||||||
|
*
|
||||||
|
* We present these routines in the same coding style used in the JPEG code
|
||||||
|
* (ANSI function definitions, etc); but you are of course free to code your
|
||||||
|
* routines in a different style if you prefer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include file for users of JPEG library.
|
||||||
|
* You will need to have included system headers that define at least
|
||||||
|
* the typedefs FILE and size_t before you can include jpeglib.h.
|
||||||
|
* (stdio.h is sufficient on ANSI-conforming systems.)
|
||||||
|
* You may also wish to include "jerror.h".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <setjmp.h> is used for the optional error recovery mechanism shown in
|
||||||
|
* the second part of the example.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
|
||||||
|
|
||||||
|
/* This half of the example shows how to feed data into the JPEG compressor.
|
||||||
|
* We present a minimal version that does not worry about refinements such
|
||||||
|
* as error recovery (the JPEG code will just exit() if it gets an error).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IMAGE DATA FORMATS:
|
||||||
|
*
|
||||||
|
* The standard input image format is a rectangular array of pixels, with
|
||||||
|
* each pixel having the same number of "component" values (color channels).
|
||||||
|
* Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
|
||||||
|
* If you are working with color data, then the color values for each pixel
|
||||||
|
* must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
|
||||||
|
* RGB color.
|
||||||
|
*
|
||||||
|
* For this example, we'll assume that this data structure matches the way
|
||||||
|
* our application has stored the image in memory, so we can just pass a
|
||||||
|
* pointer to our image buffer. In particular, let's say that the image is
|
||||||
|
* RGB color and is described by:
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
|
||||||
|
extern int image_height; /* Number of rows in image */
|
||||||
|
extern int image_width; /* Number of columns in image */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sample routine for JPEG compression. We assume that the target file name
|
||||||
|
* and a compression quality factor are passed in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
write_JPEG_file (char * filename, int quality)
|
||||||
|
{
|
||||||
|
/* This struct contains the JPEG compression parameters and pointers to
|
||||||
|
* working space (which is allocated as needed by the JPEG library).
|
||||||
|
* It is possible to have several such structures, representing multiple
|
||||||
|
* compression/decompression processes, in existence at once. We refer
|
||||||
|
* to any one struct (and its associated working data) as a "JPEG object".
|
||||||
|
*/
|
||||||
|
struct jpeg_compress_struct cinfo;
|
||||||
|
/* This struct represents a JPEG error handler. It is declared separately
|
||||||
|
* because applications often want to supply a specialized error handler
|
||||||
|
* (see the second half of this file for an example). But here we just
|
||||||
|
* take the easy way out and use the standard error handler, which will
|
||||||
|
* print a message on stderr and call exit() if compression fails.
|
||||||
|
* Note that this struct must live as long as the main JPEG parameter
|
||||||
|
* struct, to avoid dangling-pointer problems.
|
||||||
|
*/
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
/* More stuff */
|
||||||
|
FILE * outfile; /* target file */
|
||||||
|
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||||
|
int row_stride; /* physical row width in image buffer */
|
||||||
|
|
||||||
|
/* Step 1: allocate and initialize JPEG compression object */
|
||||||
|
|
||||||
|
/* We have to set up the error handler first, in case the initialization
|
||||||
|
* step fails. (Unlikely, but it could happen if you are out of memory.)
|
||||||
|
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||||
|
* address which we place into the link field in cinfo.
|
||||||
|
*/
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
/* Now we can initialize the JPEG compression object. */
|
||||||
|
jpeg_create_compress(&cinfo);
|
||||||
|
|
||||||
|
/* Step 2: specify data destination (eg, a file) */
|
||||||
|
/* Note: steps 2 and 3 can be done in either order. */
|
||||||
|
|
||||||
|
/* Here we use the library-supplied code to send compressed data to a
|
||||||
|
* stdio stream. You can also write your own code to do something else.
|
||||||
|
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||||
|
* requires it in order to write binary files.
|
||||||
|
*/
|
||||||
|
if ((outfile = fopen(filename, "wb")) == NULL) {
|
||||||
|
fprintf(stderr, "can't open %s\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
jpeg_stdio_dest(&cinfo, outfile);
|
||||||
|
|
||||||
|
/* Step 3: set parameters for compression */
|
||||||
|
|
||||||
|
/* First we supply a description of the input image.
|
||||||
|
* Four fields of the cinfo struct must be filled in:
|
||||||
|
*/
|
||||||
|
cinfo.image_width = image_width; /* image width and height, in pixels */
|
||||||
|
cinfo.image_height = image_height;
|
||||||
|
cinfo.input_components = 3; /* # of color components per pixel */
|
||||||
|
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||||
|
/* Now use the library's routine to set default compression parameters.
|
||||||
|
* (You must set at least cinfo.in_color_space before calling this,
|
||||||
|
* since the defaults depend on the source color space.)
|
||||||
|
*/
|
||||||
|
jpeg_set_defaults(&cinfo);
|
||||||
|
/* Now you can set any non-default parameters you wish to.
|
||||||
|
* Here we just illustrate the use of quality (quantization table) scaling:
|
||||||
|
*/
|
||||||
|
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
||||||
|
|
||||||
|
/* Step 4: Start compressor */
|
||||||
|
|
||||||
|
/* TRUE ensures that we will write a complete interchange-JPEG file.
|
||||||
|
* Pass TRUE unless you are very sure of what you're doing.
|
||||||
|
*/
|
||||||
|
jpeg_start_compress(&cinfo, TRUE);
|
||||||
|
|
||||||
|
/* Step 5: while (scan lines remain to be written) */
|
||||||
|
/* jpeg_write_scanlines(...); */
|
||||||
|
|
||||||
|
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||||
|
* loop counter, so that we don't have to keep track ourselves.
|
||||||
|
* To keep things simple, we pass one scanline per call; you can pass
|
||||||
|
* more if you wish, though.
|
||||||
|
*/
|
||||||
|
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
|
||||||
|
|
||||||
|
while (cinfo.next_scanline < cinfo.image_height) {
|
||||||
|
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||||
|
* Here the array is only one element long, but you could pass
|
||||||
|
* more than one scanline at a time if that's more convenient.
|
||||||
|
*/
|
||||||
|
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
|
||||||
|
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 6: Finish compression */
|
||||||
|
|
||||||
|
jpeg_finish_compress(&cinfo);
|
||||||
|
/* After finish_compress, we can close the output file. */
|
||||||
|
fclose(outfile);
|
||||||
|
|
||||||
|
/* Step 7: release JPEG compression object */
|
||||||
|
|
||||||
|
/* This is an important step since it will release a good deal of memory. */
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
/* And we're done! */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SOME FINE POINTS:
|
||||||
|
*
|
||||||
|
* In the above loop, we ignored the return value of jpeg_write_scanlines,
|
||||||
|
* which is the number of scanlines actually written. We could get away
|
||||||
|
* with this because we were only relying on the value of cinfo.next_scanline,
|
||||||
|
* which will be incremented correctly. If you maintain additional loop
|
||||||
|
* variables then you should be careful to increment them properly.
|
||||||
|
* Actually, for output to a stdio stream you needn't worry, because
|
||||||
|
* then jpeg_write_scanlines will write all the lines passed (or else exit
|
||||||
|
* with a fatal error). Partial writes can only occur if you use a data
|
||||||
|
* destination module that can demand suspension of the compressor.
|
||||||
|
* (If you don't know what that's for, you don't need it.)
|
||||||
|
*
|
||||||
|
* If the compressor requires full-image buffers (for entropy-coding
|
||||||
|
* optimization or a multi-scan JPEG file), it will create temporary
|
||||||
|
* files for anything that doesn't fit within the maximum-memory setting.
|
||||||
|
* (Note that temp files are NOT needed if you use the default parameters.)
|
||||||
|
* On some systems you may need to set up a signal handler to ensure that
|
||||||
|
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
||||||
|
*
|
||||||
|
* Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
|
||||||
|
* files to be compatible with everyone else's. If you cannot readily read
|
||||||
|
* your data in that order, you'll need an intermediate array to hold the
|
||||||
|
* image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
|
||||||
|
* source data using the JPEG code's internal virtual-array mechanisms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
|
||||||
|
|
||||||
|
/* This half of the example shows how to read data from the JPEG decompressor.
|
||||||
|
* It's a bit more refined than the above, in that we show:
|
||||||
|
* (a) how to modify the JPEG library's standard error-reporting behavior;
|
||||||
|
* (b) how to allocate workspace using the library's memory manager.
|
||||||
|
*
|
||||||
|
* Just to make this example a little different from the first one, we'll
|
||||||
|
* assume that we do not intend to put the whole image into an in-memory
|
||||||
|
* buffer, but to send it line-by-line someplace else. We need a one-
|
||||||
|
* scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
|
||||||
|
* memory manager allocate it for us. This approach is actually quite useful
|
||||||
|
* because we don't need to remember to deallocate the buffer separately: it
|
||||||
|
* will go away automatically when the JPEG object is cleaned up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ERROR HANDLING:
|
||||||
|
*
|
||||||
|
* The JPEG library's standard error handler (jerror.c) is divided into
|
||||||
|
* several "methods" which you can override individually. This lets you
|
||||||
|
* adjust the behavior without duplicating a lot of code, which you might
|
||||||
|
* have to update with each future release.
|
||||||
|
*
|
||||||
|
* Our example here shows how to override the "error_exit" method so that
|
||||||
|
* control is returned to the library's caller when a fatal error occurs,
|
||||||
|
* rather than calling exit() as the standard error_exit method does.
|
||||||
|
*
|
||||||
|
* We use C's setjmp/longjmp facility to return control. This means that the
|
||||||
|
* routine which calls the JPEG library must first execute a setjmp() call to
|
||||||
|
* establish the return point. We want the replacement error_exit to do a
|
||||||
|
* longjmp(). But we need to make the setjmp buffer accessible to the
|
||||||
|
* error_exit routine. To do this, we make a private extension of the
|
||||||
|
* standard JPEG error handler object. (If we were using C++, we'd say we
|
||||||
|
* were making a subclass of the regular error handler.)
|
||||||
|
*
|
||||||
|
* Here's the extended error handler struct:
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct my_error_mgr {
|
||||||
|
struct jpeg_error_mgr pub; /* "public" fields */
|
||||||
|
|
||||||
|
jmp_buf setjmp_buffer; /* for return to caller */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct my_error_mgr * my_error_ptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here's the routine that will replace the standard error_exit method:
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
my_error_exit (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||||
|
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||||
|
|
||||||
|
/* Always display the message. */
|
||||||
|
/* We could postpone this until after returning, if we chose. */
|
||||||
|
(*cinfo->err->output_message) (cinfo);
|
||||||
|
|
||||||
|
/* Return control to the setjmp point */
|
||||||
|
longjmp(myerr->setjmp_buffer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sample routine for JPEG decompression. We assume that the source file name
|
||||||
|
* is passed in. We want to return 1 on success, 0 on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(int)
|
||||||
|
read_JPEG_file (char * filename)
|
||||||
|
{
|
||||||
|
/* This struct contains the JPEG decompression parameters and pointers to
|
||||||
|
* working space (which is allocated as needed by the JPEG library).
|
||||||
|
*/
|
||||||
|
struct jpeg_decompress_struct cinfo;
|
||||||
|
/* We use our private extension JPEG error handler.
|
||||||
|
* Note that this struct must live as long as the main JPEG parameter
|
||||||
|
* struct, to avoid dangling-pointer problems.
|
||||||
|
*/
|
||||||
|
struct my_error_mgr jerr;
|
||||||
|
/* More stuff */
|
||||||
|
FILE * infile; /* source file */
|
||||||
|
JSAMPARRAY buffer; /* Output row buffer */
|
||||||
|
int row_stride; /* physical row width in output buffer */
|
||||||
|
|
||||||
|
/* In this example we want to open the input file before doing anything else,
|
||||||
|
* so that the setjmp() error recovery below can assume the file is open.
|
||||||
|
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||||
|
* requires it in order to read binary files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((infile = fopen(filename, "rb")) == NULL) {
|
||||||
|
fprintf(stderr, "can't open %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 1: allocate and initialize JPEG decompression object */
|
||||||
|
|
||||||
|
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
|
jerr.pub.error_exit = my_error_exit;
|
||||||
|
/* Establish the setjmp return context for my_error_exit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer)) {
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object, close the input file, and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
fclose(infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Now we can initialize the JPEG decompression object. */
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Step 2: specify data source (eg, a file) */
|
||||||
|
|
||||||
|
jpeg_stdio_src(&cinfo, infile);
|
||||||
|
|
||||||
|
/* Step 3: read file parameters with jpeg_read_header() */
|
||||||
|
|
||||||
|
(void) jpeg_read_header(&cinfo, TRUE);
|
||||||
|
/* We can ignore the return value from jpeg_read_header since
|
||||||
|
* (a) suspension is not possible with the stdio data source, and
|
||||||
|
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||||
|
* See libjpeg.doc for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 4: set parameters for decompression */
|
||||||
|
|
||||||
|
/* In this example, we don't need to change any of the defaults set by
|
||||||
|
* jpeg_read_header(), so we do nothing here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 5: Start decompressor */
|
||||||
|
|
||||||
|
(void) jpeg_start_decompress(&cinfo);
|
||||||
|
/* We can ignore the return value since suspension is not possible
|
||||||
|
* with the stdio data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We may need to do some setup of our own at this point before reading
|
||||||
|
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||||
|
* output image dimensions available, as well as the output colormap
|
||||||
|
* if we asked for color quantization.
|
||||||
|
* In this example, we need to make an output work buffer of the right size.
|
||||||
|
*/
|
||||||
|
/* JSAMPLEs per row in output buffer */
|
||||||
|
row_stride = cinfo.output_width * cinfo.output_components;
|
||||||
|
/* Make a one-row-high sample array that will go away when done with image */
|
||||||
|
buffer = (*cinfo.mem->alloc_sarray)
|
||||||
|
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||||
|
|
||||||
|
/* Step 6: while (scan lines remain to be read) */
|
||||||
|
/* jpeg_read_scanlines(...); */
|
||||||
|
|
||||||
|
/* Here we use the library's state variable cinfo.output_scanline as the
|
||||||
|
* loop counter, so that we don't have to keep track ourselves.
|
||||||
|
*/
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
|
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||||
|
* Here the array is only one element long, but you could ask for
|
||||||
|
* more than one scanline at a time if that's more convenient.
|
||||||
|
*/
|
||||||
|
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||||
|
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||||
|
put_scanline_someplace(buffer[0], row_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 7: Finish decompression */
|
||||||
|
|
||||||
|
(void) jpeg_finish_decompress(&cinfo);
|
||||||
|
/* We can ignore the return value since suspension is not possible
|
||||||
|
* with the stdio data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 8: Release JPEG decompression object */
|
||||||
|
|
||||||
|
/* This is an important step since it will release a good deal of memory. */
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* After finish_decompress, we can close the input file.
|
||||||
|
* Here we postpone it until after no more JPEG errors are possible,
|
||||||
|
* so as to simplify the setjmp error logic above. (Actually, I don't
|
||||||
|
* think that jpeg_destroy can do an error exit, but why assume anything...)
|
||||||
|
*/
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
/* At this point you may want to check to see whether any corrupt-data
|
||||||
|
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* And we're done! */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SOME FINE POINTS:
|
||||||
|
*
|
||||||
|
* In the above code, we ignored the return value of jpeg_read_scanlines,
|
||||||
|
* which is the number of scanlines actually read. We could get away with
|
||||||
|
* this because we asked for only one line at a time and we weren't using
|
||||||
|
* a suspending data source. See libjpeg.doc for more info.
|
||||||
|
*
|
||||||
|
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
|
||||||
|
* we should have done it beforehand to ensure that the space would be
|
||||||
|
* counted against the JPEG max_memory setting. In some systems the above
|
||||||
|
* code would risk an out-of-memory error. However, in general we don't
|
||||||
|
* know the output image dimensions before jpeg_start_decompress(), unless we
|
||||||
|
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
|
||||||
|
*
|
||||||
|
* Scanlines are returned in the same order as they appear in the JPEG file,
|
||||||
|
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
|
||||||
|
* you can use one of the virtual arrays provided by the JPEG memory manager
|
||||||
|
* to invert the data. See wrbmp.c for an example.
|
||||||
|
*
|
||||||
|
* As with compression, some operating modes may require temporary files.
|
||||||
|
* On some systems you may need to set up a signal handler to ensure that
|
||||||
|
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
||||||
|
*/
|
||||||
210
filelist.doc
Normal file
210
filelist.doc
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
IJG JPEG LIBRARY: FILE LIST
|
||||||
|
|
||||||
|
Copyright (C) 1994-1998, Thomas G. Lane.
|
||||||
|
This file is part of the Independent JPEG Group's software.
|
||||||
|
For conditions of distribution and use, see the accompanying README file.
|
||||||
|
|
||||||
|
|
||||||
|
Here is a road map to the files in the IJG JPEG distribution. The
|
||||||
|
distribution includes the JPEG library proper, plus two application
|
||||||
|
programs ("cjpeg" and "djpeg") which use the library to convert JPEG
|
||||||
|
files to and from some other popular image formats. A third application
|
||||||
|
"jpegtran" uses the library to do lossless conversion between different
|
||||||
|
variants of JPEG. There are also two stand-alone applications,
|
||||||
|
"rdjpgcom" and "wrjpgcom".
|
||||||
|
|
||||||
|
|
||||||
|
THE JPEG LIBRARY
|
||||||
|
================
|
||||||
|
|
||||||
|
Include files:
|
||||||
|
|
||||||
|
jpeglib.h JPEG library's exported data and function declarations.
|
||||||
|
jconfig.h Configuration declarations. Note: this file is not present
|
||||||
|
in the distribution; it is generated during installation.
|
||||||
|
jmorecfg.h Additional configuration declarations; need not be changed
|
||||||
|
for a standard installation.
|
||||||
|
jerror.h Declares JPEG library's error and trace message codes.
|
||||||
|
jinclude.h Central include file used by all IJG .c files to reference
|
||||||
|
system include files.
|
||||||
|
jpegint.h JPEG library's internal data structures.
|
||||||
|
jchuff.h Private declarations for Huffman encoder modules.
|
||||||
|
jdhuff.h Private declarations for Huffman decoder modules.
|
||||||
|
jdct.h Private declarations for forward & reverse DCT subsystems.
|
||||||
|
jmemsys.h Private declarations for memory management subsystem.
|
||||||
|
jversion.h Version information.
|
||||||
|
|
||||||
|
Applications using the library should include jpeglib.h (which in turn
|
||||||
|
includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included
|
||||||
|
if the application needs to reference individual JPEG error codes. The
|
||||||
|
other include files are intended for internal use and would not normally
|
||||||
|
be included by an application program. (cjpeg/djpeg/etc do use jinclude.h,
|
||||||
|
since its function is to improve portability of the whole IJG distribution.
|
||||||
|
Most other applications will directly include the system include files they
|
||||||
|
want, and hence won't need jinclude.h.)
|
||||||
|
|
||||||
|
|
||||||
|
C source code files:
|
||||||
|
|
||||||
|
These files contain most of the functions intended to be called directly by
|
||||||
|
an application program:
|
||||||
|
|
||||||
|
jcapimin.c Application program interface: core routines for compression.
|
||||||
|
jcapistd.c Application program interface: standard compression.
|
||||||
|
jdapimin.c Application program interface: core routines for decompression.
|
||||||
|
jdapistd.c Application program interface: standard decompression.
|
||||||
|
jcomapi.c Application program interface routines common to compression
|
||||||
|
and decompression.
|
||||||
|
jcparam.c Compression parameter setting helper routines.
|
||||||
|
jctrans.c API and library routines for transcoding compression.
|
||||||
|
jdtrans.c API and library routines for transcoding decompression.
|
||||||
|
|
||||||
|
Compression side of the library:
|
||||||
|
|
||||||
|
jcinit.c Initialization: determines which other modules to use.
|
||||||
|
jcmaster.c Master control: setup and inter-pass sequencing logic.
|
||||||
|
jcmainct.c Main buffer controller (preprocessor => JPEG compressor).
|
||||||
|
jcprepct.c Preprocessor buffer controller.
|
||||||
|
jccoefct.c Buffer controller for DCT coefficient buffer.
|
||||||
|
jccolor.c Color space conversion.
|
||||||
|
jcsample.c Downsampling.
|
||||||
|
jcdctmgr.c DCT manager (DCT implementation selection & control).
|
||||||
|
jfdctint.c Forward DCT using slow-but-accurate integer method.
|
||||||
|
jfdctfst.c Forward DCT using faster, less accurate integer method.
|
||||||
|
jfdctflt.c Forward DCT using floating-point arithmetic.
|
||||||
|
jchuff.c Huffman entropy coding for sequential JPEG.
|
||||||
|
jcphuff.c Huffman entropy coding for progressive JPEG.
|
||||||
|
jcmarker.c JPEG marker writing.
|
||||||
|
jdatadst.c Data destination manager for stdio output.
|
||||||
|
|
||||||
|
Decompression side of the library:
|
||||||
|
|
||||||
|
jdmaster.c Master control: determines which other modules to use.
|
||||||
|
jdinput.c Input controller: controls input processing modules.
|
||||||
|
jdmainct.c Main buffer controller (JPEG decompressor => postprocessor).
|
||||||
|
jdcoefct.c Buffer controller for DCT coefficient buffer.
|
||||||
|
jdpostct.c Postprocessor buffer controller.
|
||||||
|
jdmarker.c JPEG marker reading.
|
||||||
|
jdhuff.c Huffman entropy decoding for sequential JPEG.
|
||||||
|
jdphuff.c Huffman entropy decoding for progressive JPEG.
|
||||||
|
jddctmgr.c IDCT manager (IDCT implementation selection & control).
|
||||||
|
jidctint.c Inverse DCT using slow-but-accurate integer method.
|
||||||
|
jidctfst.c Inverse DCT using faster, less accurate integer method.
|
||||||
|
jidctflt.c Inverse DCT using floating-point arithmetic.
|
||||||
|
jidctred.c Inverse DCTs with reduced-size outputs.
|
||||||
|
jdsample.c Upsampling.
|
||||||
|
jdcolor.c Color space conversion.
|
||||||
|
jdmerge.c Merged upsampling/color conversion (faster, lower quality).
|
||||||
|
jquant1.c One-pass color quantization using a fixed-spacing colormap.
|
||||||
|
jquant2.c Two-pass color quantization using a custom-generated colormap.
|
||||||
|
Also handles one-pass quantization to an externally given map.
|
||||||
|
jdatasrc.c Data source manager for stdio input.
|
||||||
|
|
||||||
|
Support files for both compression and decompression:
|
||||||
|
|
||||||
|
jerror.c Standard error handling routines (application replaceable).
|
||||||
|
jmemmgr.c System-independent (more or less) memory management code.
|
||||||
|
jutils.c Miscellaneous utility routines.
|
||||||
|
|
||||||
|
jmemmgr.c relies on a system-dependent memory management module. The IJG
|
||||||
|
distribution includes the following implementations of the system-dependent
|
||||||
|
module:
|
||||||
|
|
||||||
|
jmemnobs.c "No backing store": assumes adequate virtual memory exists.
|
||||||
|
jmemansi.c Makes temporary files with ANSI-standard routine tmpfile().
|
||||||
|
jmemname.c Makes temporary files with program-generated file names.
|
||||||
|
jmemdos.c Custom implementation for MS-DOS (16-bit environment only):
|
||||||
|
can use extended and expanded memory as well as temp files.
|
||||||
|
jmemmac.c Custom implementation for Apple Macintosh.
|
||||||
|
|
||||||
|
Exactly one of the system-dependent modules should be configured into an
|
||||||
|
installed JPEG library (see install.doc for hints about which one to use).
|
||||||
|
On unusual systems you may find it worthwhile to make a special
|
||||||
|
system-dependent memory manager.
|
||||||
|
|
||||||
|
|
||||||
|
Non-C source code files:
|
||||||
|
|
||||||
|
jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in
|
||||||
|
MS-DOS-specific configurations of the JPEG library.
|
||||||
|
|
||||||
|
|
||||||
|
CJPEG/DJPEG/JPEGTRAN
|
||||||
|
====================
|
||||||
|
|
||||||
|
Include files:
|
||||||
|
|
||||||
|
cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules.
|
||||||
|
cderror.h Additional error and trace message codes for cjpeg et al.
|
||||||
|
transupp.h Declarations for jpegtran support routines in transupp.c.
|
||||||
|
|
||||||
|
C source code files:
|
||||||
|
|
||||||
|
cjpeg.c Main program for cjpeg.
|
||||||
|
djpeg.c Main program for djpeg.
|
||||||
|
jpegtran.c Main program for jpegtran.
|
||||||
|
cdjpeg.c Utility routines used by all three programs.
|
||||||
|
rdcolmap.c Code to read a colormap file for djpeg's "-map" switch.
|
||||||
|
rdswitch.c Code to process some of cjpeg's more complex switches.
|
||||||
|
Also used by jpegtran.
|
||||||
|
transupp.c Support code for jpegtran: lossless image manipulations.
|
||||||
|
|
||||||
|
Image file reader modules for cjpeg:
|
||||||
|
|
||||||
|
rdbmp.c BMP file input.
|
||||||
|
rdgif.c GIF file input (now just a stub).
|
||||||
|
rdppm.c PPM/PGM file input.
|
||||||
|
rdrle.c Utah RLE file input.
|
||||||
|
rdtarga.c Targa file input.
|
||||||
|
|
||||||
|
Image file writer modules for djpeg:
|
||||||
|
|
||||||
|
wrbmp.c BMP file output.
|
||||||
|
wrgif.c GIF file output (a mere shadow of its former self).
|
||||||
|
wrppm.c PPM/PGM file output.
|
||||||
|
wrrle.c Utah RLE file output.
|
||||||
|
wrtarga.c Targa file output.
|
||||||
|
|
||||||
|
|
||||||
|
RDJPGCOM/WRJPGCOM
|
||||||
|
=================
|
||||||
|
|
||||||
|
C source code files:
|
||||||
|
|
||||||
|
rdjpgcom.c Stand-alone rdjpgcom application.
|
||||||
|
wrjpgcom.c Stand-alone wrjpgcom application.
|
||||||
|
|
||||||
|
These programs do not depend on the IJG library. They do use
|
||||||
|
jconfig.h and jinclude.h, only to improve portability.
|
||||||
|
|
||||||
|
|
||||||
|
ADDITIONAL FILES
|
||||||
|
================
|
||||||
|
|
||||||
|
Documentation (see README for a guide to the documentation files):
|
||||||
|
|
||||||
|
README Master documentation file.
|
||||||
|
*.doc Other documentation files.
|
||||||
|
*.1 Documentation in Unix man page format.
|
||||||
|
change.log Version-to-version change highlights.
|
||||||
|
example.c Sample code for calling JPEG library.
|
||||||
|
|
||||||
|
Configuration/installation files and programs (see install.doc for more info):
|
||||||
|
|
||||||
|
configure Unix shell script to perform automatic configuration.
|
||||||
|
ltconfig Support scripts for configure (from GNU libtool).
|
||||||
|
ltmain.sh
|
||||||
|
config.guess
|
||||||
|
config.sub
|
||||||
|
install-sh Install shell script for those Unix systems lacking one.
|
||||||
|
ckconfig.c Program to generate jconfig.h on non-Unix systems.
|
||||||
|
jconfig.doc Template for making jconfig.h by hand.
|
||||||
|
makefile.* Sample makefiles for particular systems.
|
||||||
|
jconfig.* Sample jconfig.h for particular systems.
|
||||||
|
ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of
|
||||||
|
L. Peter Deutsch and Aladdin Enterprises).
|
||||||
|
|
||||||
|
Test files (see install.doc for test procedure):
|
||||||
|
|
||||||
|
test*.* Source and comparison files for confidence test.
|
||||||
|
These are binary image files, NOT text files.
|
||||||
323
install-sh
Executable file
323
install-sh
Executable file
@@ -0,0 +1,323 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2005-05-14.22
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# `make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch. It can only install one file at a time, a restriction
|
||||||
|
# shared with many OS's install programs.
|
||||||
|
|
||||||
|
# set DOITPROG to echo to test this script
|
||||||
|
|
||||||
|
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||||
|
doit="${DOITPROG-}"
|
||||||
|
|
||||||
|
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||||
|
|
||||||
|
mvprog="${MVPROG-mv}"
|
||||||
|
cpprog="${CPPROG-cp}"
|
||||||
|
chmodprog="${CHMODPROG-chmod}"
|
||||||
|
chownprog="${CHOWNPROG-chown}"
|
||||||
|
chgrpprog="${CHGRPPROG-chgrp}"
|
||||||
|
stripprog="${STRIPPROG-strip}"
|
||||||
|
rmprog="${RMPROG-rm}"
|
||||||
|
mkdirprog="${MKDIRPROG-mkdir}"
|
||||||
|
|
||||||
|
chmodcmd="$chmodprog 0755"
|
||||||
|
chowncmd=
|
||||||
|
chgrpcmd=
|
||||||
|
stripcmd=
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
mvcmd="$mvprog"
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dstarg=
|
||||||
|
no_target_directory=
|
||||||
|
|
||||||
|
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||||
|
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||||
|
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||||
|
or: $0 [OPTION]... -d DIRECTORIES...
|
||||||
|
|
||||||
|
In the 1st form, copy SRCFILE to DSTFILE.
|
||||||
|
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||||
|
In the 4th, create DIRECTORIES.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-c (ignored)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||||
|
"
|
||||||
|
|
||||||
|
while test -n "$1"; do
|
||||||
|
case $1 in
|
||||||
|
-c) shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-d) dir_arg=true
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) chmodcmd="$chmodprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-t) dstarg=$2
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-T) no_target_directory=true
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
*) # When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
test -n "$dir_arg$dstarg" && break
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dstarg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dstarg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dstarg=$arg
|
||||||
|
done
|
||||||
|
break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -z "$1"; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call `install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names starting with `-'.
|
||||||
|
case $src in
|
||||||
|
-*) src=./$src ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
src=
|
||||||
|
|
||||||
|
if test -d "$dst"; then
|
||||||
|
mkdircmd=:
|
||||||
|
chmodcmd=
|
||||||
|
else
|
||||||
|
mkdircmd=$mkdirprog
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dstarg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dst=$dstarg
|
||||||
|
# Protect names starting with `-'.
|
||||||
|
case $dst in
|
||||||
|
-*) dst=./$dst ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename; won't work
|
||||||
|
# if double slashes aren't ignored.
|
||||||
|
if test -d "$dst"; then
|
||||||
|
if test -n "$no_target_directory"; then
|
||||||
|
echo "$0: $dstarg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dst=$dst/`basename "$src"`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This sed command emulates the dirname command.
|
||||||
|
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
|
||||||
|
|
||||||
|
# Make sure that the destination directory exists.
|
||||||
|
|
||||||
|
# Skip lots of stat calls in the usual case.
|
||||||
|
if test ! -d "$dstdir"; then
|
||||||
|
defaultIFS='
|
||||||
|
'
|
||||||
|
IFS="${IFS-$defaultIFS}"
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
# Some sh's can't handle IFS=/ for some reason.
|
||||||
|
IFS='%'
|
||||||
|
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||||
|
shift
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
pathcomp=
|
||||||
|
|
||||||
|
while test $# -ne 0 ; do
|
||||||
|
pathcomp=$pathcomp$1
|
||||||
|
shift
|
||||||
|
if test ! -d "$pathcomp"; then
|
||||||
|
$mkdirprog "$pathcomp"
|
||||||
|
# mkdir can fail with a `File exist' error in case several
|
||||||
|
# install-sh are creating the directory concurrently. This
|
||||||
|
# is OK.
|
||||||
|
test -d "$pathcomp" || exit
|
||||||
|
fi
|
||||||
|
pathcomp=$pathcomp/
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
$doit $mkdircmd "$dst" \
|
||||||
|
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||||
|
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||||
|
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||||
|
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||||
|
|
||||||
|
else
|
||||||
|
dstfile=`basename "$dst"`
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=$dstdir/_inst.$$_
|
||||||
|
rmtmp=$dstdir/_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
trap '(exit $?); exit' 1 2 13 15
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
$doit $cpprog "$src" "$dsttmp" &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|
||||||
|
|| {
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
if test -f "$dstdir/$dstfile"; then
|
||||||
|
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||||
|
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||||
|
|| {
|
||||||
|
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fi || { (exit 1); exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||||
|
{
|
||||||
|
(exit 0); exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-end: "$"
|
||||||
|
# End:
|
||||||
1063
install.doc
Normal file
1063
install.doc
Normal file
File diff suppressed because it is too large
Load Diff
120
jbsmooth.c
120
jbsmooth.c
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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] = (JCOEF) (_ac)
|
|
||||||
|
|
||||||
COND_ASSIGN(AC01, 1, 1);
|
|
||||||
COND_ASSIGN(AC02, 2, 5);
|
|
||||||
COND_ASSIGN(AC10, 8, 2);
|
|
||||||
COND_ASSIGN(AC11, 9, 4);
|
|
||||||
COND_ASSIGN(AC20, 16, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The method selection routine for cross-block smoothing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
jselbsmooth (decompress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
/* just one implementation for now */
|
|
||||||
cinfo->methods->smooth_coefficients = smooth_coefficients;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* BLOCK_SMOOTHING_SUPPORTED */
|
|
||||||
280
jcapimin.c
Normal file
280
jcapimin.c
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* jcapimin.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains application interface code for the compression half
|
||||||
|
* of the JPEG library. These are the "minimum" API routines that may be
|
||||||
|
* needed in either the normal full-compression case or the transcoding-only
|
||||||
|
* case.
|
||||||
|
*
|
||||||
|
* Most of the routines intended to be called directly by an application
|
||||||
|
* are in this file or in jcapistd.c. But also see jcparam.c for
|
||||||
|
* parameter-setup helper routines, jcomapi.c for routines shared by
|
||||||
|
* compression and decompression, and jctrans.c for the transcoding case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization of a JPEG compression object.
|
||||||
|
* The error manager must already be set up (in case memory manager fails).
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Guard against version mismatches between library and caller. */
|
||||||
|
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
|
||||||
|
if (version != JPEG_LIB_VERSION)
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||||
|
if (structsize != SIZEOF(struct jpeg_compress_struct))
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
|
||||||
|
(int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
|
||||||
|
|
||||||
|
/* For debugging purposes, we zero the whole master structure.
|
||||||
|
* But the application has already set the err pointer, and may have set
|
||||||
|
* client_data, so we have to save and restore those fields.
|
||||||
|
* Note: if application hasn't set client_data, tools like Purify may
|
||||||
|
* complain here.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr * err = cinfo->err;
|
||||||
|
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
|
||||||
|
MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
|
||||||
|
cinfo->err = err;
|
||||||
|
cinfo->client_data = client_data;
|
||||||
|
}
|
||||||
|
cinfo->is_decompressor = FALSE;
|
||||||
|
|
||||||
|
/* Initialize a memory manager instance for this object */
|
||||||
|
jinit_memory_mgr((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Zero out pointers to permanent structures. */
|
||||||
|
cinfo->progress = NULL;
|
||||||
|
cinfo->dest = NULL;
|
||||||
|
|
||||||
|
cinfo->comp_info = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||||
|
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||||
|
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->script_space = NULL;
|
||||||
|
|
||||||
|
cinfo->input_gamma = 1.0; /* in case application forgets */
|
||||||
|
|
||||||
|
/* OK, I'm ready */
|
||||||
|
cinfo->global_state = CSTATE_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destruction of a JPEG compression object
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_destroy_compress (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abort processing of a JPEG compression operation,
|
||||||
|
* but don't destroy the object itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_abort_compress (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forcibly suppress or un-suppress all quantization and Huffman tables.
|
||||||
|
* Marks all currently defined tables as already written (if suppress)
|
||||||
|
* or not written (if !suppress). This will control whether they get emitted
|
||||||
|
* by a subsequent jpeg_start_compress call.
|
||||||
|
*
|
||||||
|
* This routine is exported for use by applications that want to produce
|
||||||
|
* abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
|
||||||
|
* since it is called by jpeg_start_compress, we put it here --- otherwise
|
||||||
|
* jcparam.o would be linked whether the application used it or not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
JQUANT_TBL * qtbl;
|
||||||
|
JHUFF_TBL * htbl;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||||
|
if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
|
||||||
|
qtbl->sent_table = suppress;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
|
||||||
|
htbl->sent_table = suppress;
|
||||||
|
if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
|
||||||
|
htbl->sent_table = suppress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish JPEG compression.
|
||||||
|
*
|
||||||
|
* If a multipass operating mode was selected, this may do a great deal of
|
||||||
|
* work including most of the actual output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_finish_compress (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
JDIMENSION iMCU_row;
|
||||||
|
|
||||||
|
if (cinfo->global_state == CSTATE_SCANNING ||
|
||||||
|
cinfo->global_state == CSTATE_RAW_OK) {
|
||||||
|
/* Terminate first pass */
|
||||||
|
if (cinfo->next_scanline < cinfo->image_height)
|
||||||
|
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
|
||||||
|
(*cinfo->master->finish_pass) (cinfo);
|
||||||
|
} else if (cinfo->global_state != CSTATE_WRCOEFS)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
/* Perform any remaining passes */
|
||||||
|
while (! cinfo->master->is_last_pass) {
|
||||||
|
(*cinfo->master->prepare_for_pass) (cinfo);
|
||||||
|
for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) iMCU_row;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
/* We bypass the main controller and invoke coef controller directly;
|
||||||
|
* all work is being done from the coefficient buffer.
|
||||||
|
*/
|
||||||
|
if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
|
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||||
|
}
|
||||||
|
(*cinfo->master->finish_pass) (cinfo);
|
||||||
|
}
|
||||||
|
/* Write EOI, do final cleanup */
|
||||||
|
(*cinfo->marker->write_file_trailer) (cinfo);
|
||||||
|
(*cinfo->dest->term_destination) (cinfo);
|
||||||
|
/* We can use jpeg_abort to release memory and reset global_state */
|
||||||
|
jpeg_abort((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write a special marker.
|
||||||
|
* This is only recommended for writing COM or APPn markers.
|
||||||
|
* Must be called after jpeg_start_compress() and before
|
||||||
|
* first call to jpeg_write_scanlines() or jpeg_write_raw_data().
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_write_marker (j_compress_ptr cinfo, int marker,
|
||||||
|
const JOCTET *dataptr, unsigned int datalen)
|
||||||
|
{
|
||||||
|
JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
|
||||||
|
|
||||||
|
if (cinfo->next_scanline != 0 ||
|
||||||
|
(cinfo->global_state != CSTATE_SCANNING &&
|
||||||
|
cinfo->global_state != CSTATE_RAW_OK &&
|
||||||
|
cinfo->global_state != CSTATE_WRCOEFS))
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
(*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
|
||||||
|
write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
|
||||||
|
while (datalen--) {
|
||||||
|
(*write_marker_byte) (cinfo, *dataptr);
|
||||||
|
dataptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Same, but piecemeal. */
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
|
||||||
|
{
|
||||||
|
if (cinfo->next_scanline != 0 ||
|
||||||
|
(cinfo->global_state != CSTATE_SCANNING &&
|
||||||
|
cinfo->global_state != CSTATE_RAW_OK &&
|
||||||
|
cinfo->global_state != CSTATE_WRCOEFS))
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
(*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_write_m_byte (j_compress_ptr cinfo, int val)
|
||||||
|
{
|
||||||
|
(*cinfo->marker->write_marker_byte) (cinfo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alternate compression function: just write an abbreviated table file.
|
||||||
|
* Before calling this, all parameters and a data destination must be set up.
|
||||||
|
*
|
||||||
|
* To produce a pair of files containing abbreviated tables and abbreviated
|
||||||
|
* image data, one would proceed as follows:
|
||||||
|
*
|
||||||
|
* initialize JPEG object
|
||||||
|
* set JPEG parameters
|
||||||
|
* set destination to table file
|
||||||
|
* jpeg_write_tables(cinfo);
|
||||||
|
* set destination to image file
|
||||||
|
* jpeg_start_compress(cinfo, FALSE);
|
||||||
|
* write data...
|
||||||
|
* jpeg_finish_compress(cinfo);
|
||||||
|
*
|
||||||
|
* jpeg_write_tables has the side effect of marking all tables written
|
||||||
|
* (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
|
||||||
|
* will not re-emit the tables unless it is passed write_all_tables=TRUE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_write_tables (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* (Re)initialize error mgr and destination modules */
|
||||||
|
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||||
|
(*cinfo->dest->init_destination) (cinfo);
|
||||||
|
/* Initialize the marker writer ... bit of a crock to do it here. */
|
||||||
|
jinit_marker_writer(cinfo);
|
||||||
|
/* Write them tables! */
|
||||||
|
(*cinfo->marker->write_tables_only) (cinfo);
|
||||||
|
/* And clean up. */
|
||||||
|
(*cinfo->dest->term_destination) (cinfo);
|
||||||
|
/*
|
||||||
|
* In library releases up through v6a, we called jpeg_abort() here to free
|
||||||
|
* any working memory allocated by the destination manager and marker
|
||||||
|
* writer. Some applications had a problem with that: they allocated space
|
||||||
|
* of their own from the library memory manager, and didn't want it to go
|
||||||
|
* away during write_tables. So now we do nothing. This will cause a
|
||||||
|
* memory leak if an app calls write_tables repeatedly without doing a full
|
||||||
|
* compression cycle or otherwise resetting the JPEG object. However, that
|
||||||
|
* seems less bad than unexpectedly freeing memory in the normal case.
|
||||||
|
* An app that prefers the old behavior can call jpeg_abort for itself after
|
||||||
|
* each call to jpeg_write_tables().
|
||||||
|
*/
|
||||||
|
}
|
||||||
161
jcapistd.c
Normal file
161
jcapistd.c
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* jcapistd.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains application interface code for the compression half
|
||||||
|
* of the JPEG library. These are the "standard" API routines that are
|
||||||
|
* used in the normal full-compression case. They are not used by a
|
||||||
|
* transcoding-only application. Note that if an application links in
|
||||||
|
* jpeg_start_compress, it will end up linking in the entire compressor.
|
||||||
|
* We thus must separate this file from jcapimin.c to avoid linking the
|
||||||
|
* whole compression library into a transcoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compression initialization.
|
||||||
|
* Before calling this, all parameters and a data destination must be set up.
|
||||||
|
*
|
||||||
|
* We require a write_all_tables parameter as a failsafe check when writing
|
||||||
|
* multiple datastreams from the same compression object. Since prior runs
|
||||||
|
* will have left all the tables marked sent_table=TRUE, a subsequent run
|
||||||
|
* would emit an abbreviated stream (no tables) by default. This may be what
|
||||||
|
* is wanted, but for safety's sake it should not be the default behavior:
|
||||||
|
* programmers should have to make a deliberate choice to emit abbreviated
|
||||||
|
* images. Therefore the documentation and examples should encourage people
|
||||||
|
* to pass write_all_tables=TRUE; then it will take active thought to do the
|
||||||
|
* wrong thing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
if (write_all_tables)
|
||||||
|
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
|
||||||
|
|
||||||
|
/* (Re)initialize error mgr and destination modules */
|
||||||
|
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||||
|
(*cinfo->dest->init_destination) (cinfo);
|
||||||
|
/* Perform master selection of active modules */
|
||||||
|
jinit_compress_master(cinfo);
|
||||||
|
/* Set up for the first pass */
|
||||||
|
(*cinfo->master->prepare_for_pass) (cinfo);
|
||||||
|
/* Ready for application to drive first pass through jpeg_write_scanlines
|
||||||
|
* or jpeg_write_raw_data.
|
||||||
|
*/
|
||||||
|
cinfo->next_scanline = 0;
|
||||||
|
cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write some scanlines of data to the JPEG compressor.
|
||||||
|
*
|
||||||
|
* The return value will be the number of lines actually written.
|
||||||
|
* This should be less than the supplied num_lines only in case that
|
||||||
|
* the data destination module has requested suspension of the compressor,
|
||||||
|
* or if more than image_height scanlines are passed in.
|
||||||
|
*
|
||||||
|
* Note: we warn about excess calls to jpeg_write_scanlines() since
|
||||||
|
* this likely signals an application programmer error. However,
|
||||||
|
* excess scanlines passed in the last valid call are *silently* ignored,
|
||||||
|
* so that the application need not adjust num_lines for end-of-image
|
||||||
|
* when using a multiple-scanline buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JDIMENSION)
|
||||||
|
jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
|
||||||
|
JDIMENSION num_lines)
|
||||||
|
{
|
||||||
|
JDIMENSION row_ctr, rows_left;
|
||||||
|
|
||||||
|
if (cinfo->global_state != CSTATE_SCANNING)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
if (cinfo->next_scanline >= cinfo->image_height)
|
||||||
|
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||||
|
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->image_height;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give master control module another chance if this is first call to
|
||||||
|
* jpeg_write_scanlines. This lets output of the frame/scan headers be
|
||||||
|
* delayed so that application can write COM, etc, markers between
|
||||||
|
* jpeg_start_compress and jpeg_write_scanlines.
|
||||||
|
*/
|
||||||
|
if (cinfo->master->call_pass_startup)
|
||||||
|
(*cinfo->master->pass_startup) (cinfo);
|
||||||
|
|
||||||
|
/* Ignore any extra scanlines at bottom of image. */
|
||||||
|
rows_left = cinfo->image_height - cinfo->next_scanline;
|
||||||
|
if (num_lines > rows_left)
|
||||||
|
num_lines = rows_left;
|
||||||
|
|
||||||
|
row_ctr = 0;
|
||||||
|
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
|
||||||
|
cinfo->next_scanline += row_ctr;
|
||||||
|
return row_ctr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alternate entry point to write raw data.
|
||||||
|
* Processes exactly one iMCU row per call, unless suspended.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JDIMENSION)
|
||||||
|
jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
|
||||||
|
JDIMENSION num_lines)
|
||||||
|
{
|
||||||
|
JDIMENSION lines_per_iMCU_row;
|
||||||
|
|
||||||
|
if (cinfo->global_state != CSTATE_RAW_OK)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
if (cinfo->next_scanline >= cinfo->image_height) {
|
||||||
|
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) cinfo->next_scanline;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->image_height;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give master control module another chance if this is first call to
|
||||||
|
* jpeg_write_raw_data. This lets output of the frame/scan headers be
|
||||||
|
* delayed so that application can write COM, etc, markers between
|
||||||
|
* jpeg_start_compress and jpeg_write_raw_data.
|
||||||
|
*/
|
||||||
|
if (cinfo->master->call_pass_startup)
|
||||||
|
(*cinfo->master->pass_startup) (cinfo);
|
||||||
|
|
||||||
|
/* Verify that at least one iMCU row has been passed. */
|
||||||
|
lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
|
||||||
|
if (num_lines < lines_per_iMCU_row)
|
||||||
|
ERREXIT(cinfo, JERR_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* Directly compress the row. */
|
||||||
|
if (! (*cinfo->coef->compress_data) (cinfo, data)) {
|
||||||
|
/* If compressor did not consume the whole row, suspend processing. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, we processed one iMCU row. */
|
||||||
|
cinfo->next_scanline += lines_per_iMCU_row;
|
||||||
|
return lines_per_iMCU_row;
|
||||||
|
}
|
||||||
42
jcarith.c
42
jcarith.c
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 */
|
|
||||||
449
jccoefct.c
Normal file
449
jccoefct.c
Normal file
@@ -0,0 +1,449 @@
|
|||||||
|
/*
|
||||||
|
* jccoefct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains the coefficient buffer controller for compression.
|
||||||
|
* This controller is the top level of the JPEG compressor proper.
|
||||||
|
* The coefficient buffer lies between forward-DCT and entropy encoding steps.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* We use a full-image coefficient buffer when doing Huffman optimization,
|
||||||
|
* and also for writing multiple-scan JPEG files. In all cases, the DCT
|
||||||
|
* step is run during the first pass, and subsequent passes need only read
|
||||||
|
* the buffered coefficients.
|
||||||
|
*/
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
#define FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
#else
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
#define FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_c_coef_controller pub; /* public fields */
|
||||||
|
|
||||||
|
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||||
|
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||||
|
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||||
|
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||||
|
|
||||||
|
/* For single-pass compression, it's sufficient to buffer just one MCU
|
||||||
|
* (although this may prove a bit slow in practice). We allocate a
|
||||||
|
* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
|
||||||
|
* MCU constructed and sent. (On 80x86, the workspace is FAR even though
|
||||||
|
* it's not really very big; this is to keep the module interfaces unchanged
|
||||||
|
* when a large coefficient buffer is necessary.)
|
||||||
|
* In multi-pass modes, this array points to the current MCU's blocks
|
||||||
|
* within the virtual arrays.
|
||||||
|
*/
|
||||||
|
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||||
|
|
||||||
|
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||||
|
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
||||||
|
} my_coef_controller;
|
||||||
|
|
||||||
|
typedef my_coef_controller * my_coef_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(boolean) compress_data
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
|
||||||
|
#ifdef FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
METHODDEF(boolean) compress_first_pass
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
|
||||||
|
METHODDEF(boolean) compress_output
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
start_iMCU_row (j_compress_ptr cinfo)
|
||||||
|
/* Reset within-iMCU-row counters for a new row */
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||||
|
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||||
|
* But at the bottom of the image, process only what's left.
|
||||||
|
*/
|
||||||
|
if (cinfo->comps_in_scan > 1) {
|
||||||
|
coef->MCU_rows_per_iMCU_row = 1;
|
||||||
|
} else {
|
||||||
|
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||||
|
else
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
coef->mcu_ctr = 0;
|
||||||
|
coef->MCU_vert_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
coef->iMCU_row_num = 0;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
|
||||||
|
switch (pass_mode) {
|
||||||
|
case JBUF_PASS_THRU:
|
||||||
|
if (coef->whole_image[0] != NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
coef->pub.compress_data = compress_data;
|
||||||
|
break;
|
||||||
|
#ifdef FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
case JBUF_SAVE_AND_PASS:
|
||||||
|
if (coef->whole_image[0] == NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
coef->pub.compress_data = compress_first_pass;
|
||||||
|
break;
|
||||||
|
case JBUF_CRANK_DEST:
|
||||||
|
if (coef->whole_image[0] == NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
coef->pub.compress_data = compress_output;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data in the single-pass case.
|
||||||
|
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||||
|
* per call, ie, v_samp_factor block rows for each component in the image.
|
||||||
|
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
|
||||||
|
*
|
||||||
|
* NB: input_buf contains a plane for each component in image,
|
||||||
|
* which we index according to the component's SOF position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||||
|
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
int blkn, bi, ci, yindex, yoffset, blockcnt;
|
||||||
|
JDIMENSION ypos, xpos;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Loop to write as much as one whole iMCU row */
|
||||||
|
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||||
|
yoffset++) {
|
||||||
|
for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
|
||||||
|
MCU_col_num++) {
|
||||||
|
/* Determine where data comes from in input_buf and do the DCT thing.
|
||||||
|
* Each call on forward_DCT processes a horizontal row of DCT blocks
|
||||||
|
* as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
|
||||||
|
* sequentially. Dummy blocks at the right or bottom edge are filled in
|
||||||
|
* specially. The data in them does not matter for image reconstruction,
|
||||||
|
* so we fill them with values that will encode to the smallest amount of
|
||||||
|
* data, viz: all zeroes in the AC entries, DC entries equal to previous
|
||||||
|
* block's DC value. (Thanks to Thomas Kinsman for this idea.)
|
||||||
|
*/
|
||||||
|
blkn = 0;
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
|
||||||
|
: compptr->last_col_width;
|
||||||
|
xpos = MCU_col_num * compptr->MCU_sample_width;
|
||||||
|
ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
|
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||||
|
if (coef->iMCU_row_num < last_iMCU_row ||
|
||||||
|
yoffset+yindex < compptr->last_row_height) {
|
||||||
|
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
|
||||||
|
input_buf[compptr->component_index],
|
||||||
|
coef->MCU_buffer[blkn],
|
||||||
|
ypos, xpos, (JDIMENSION) blockcnt);
|
||||||
|
if (blockcnt < compptr->MCU_width) {
|
||||||
|
/* Create some dummy blocks at the right edge of the image. */
|
||||||
|
jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
|
||||||
|
(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
|
||||||
|
for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
|
||||||
|
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Create a row of dummy blocks at the bottom of the image. */
|
||||||
|
jzero_far((void FAR *) coef->MCU_buffer[blkn],
|
||||||
|
compptr->MCU_width * SIZEOF(JBLOCK));
|
||||||
|
for (bi = 0; bi < compptr->MCU_width; bi++) {
|
||||||
|
coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blkn += compptr->MCU_width;
|
||||||
|
ypos += DCTSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Try to write the MCU. In event of a suspension failure, we will
|
||||||
|
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
|
||||||
|
*/
|
||||||
|
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||||
|
/* Suspension forced; update state counters and exit */
|
||||||
|
coef->MCU_vert_offset = yoffset;
|
||||||
|
coef->mcu_ctr = MCU_col_num;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||||
|
coef->mcu_ctr = 0;
|
||||||
|
}
|
||||||
|
/* Completed the iMCU row, advance counters for next one */
|
||||||
|
coef->iMCU_row_num++;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data in the first pass of a multi-pass case.
|
||||||
|
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||||
|
* per call, ie, v_samp_factor block rows for each component in the image.
|
||||||
|
* This amount of data is read from the source buffer, DCT'd and quantized,
|
||||||
|
* and saved into the virtual arrays. We also generate suitable dummy blocks
|
||||||
|
* as needed at the right and lower edges. (The dummy blocks are constructed
|
||||||
|
* in the virtual arrays, which have been padded appropriately.) This makes
|
||||||
|
* it possible for subsequent passes not to worry about real vs. dummy blocks.
|
||||||
|
*
|
||||||
|
* We must also emit the data to the entropy encoder. This is conveniently
|
||||||
|
* done by calling compress_output() after we've loaded the current strip
|
||||||
|
* of the virtual arrays.
|
||||||
|
*
|
||||||
|
* NB: input_buf contains a plane for each component in image. All
|
||||||
|
* components are DCT'd and loaded into the virtual arrays in this pass.
|
||||||
|
* However, it may be that only a subset of the components are emitted to
|
||||||
|
* the entropy encoder during this first pass; be careful about looking
|
||||||
|
* at the scan-dependent variables (MCU dimensions, etc).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
JDIMENSION blocks_across, MCUs_across, MCUindex;
|
||||||
|
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
|
||||||
|
JCOEF lastDC;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JBLOCKARRAY buffer;
|
||||||
|
JBLOCKROW thisblockrow, lastblockrow;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Align the virtual buffer for this component. */
|
||||||
|
buffer = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||||
|
coef->iMCU_row_num * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||||
|
/* Count non-dummy DCT block rows in this iMCU row. */
|
||||||
|
if (coef->iMCU_row_num < last_iMCU_row)
|
||||||
|
block_rows = compptr->v_samp_factor;
|
||||||
|
else {
|
||||||
|
/* NB: can't use last_row_height here, since may not be set! */
|
||||||
|
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||||
|
}
|
||||||
|
blocks_across = compptr->width_in_blocks;
|
||||||
|
h_samp_factor = compptr->h_samp_factor;
|
||||||
|
/* Count number of dummy blocks to be added at the right margin. */
|
||||||
|
ndummy = (int) (blocks_across % h_samp_factor);
|
||||||
|
if (ndummy > 0)
|
||||||
|
ndummy = h_samp_factor - ndummy;
|
||||||
|
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
|
||||||
|
* on forward_DCT processes a complete horizontal row of DCT blocks.
|
||||||
|
*/
|
||||||
|
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||||
|
thisblockrow = buffer[block_row];
|
||||||
|
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
|
||||||
|
input_buf[ci], thisblockrow,
|
||||||
|
(JDIMENSION) (block_row * DCTSIZE),
|
||||||
|
(JDIMENSION) 0, blocks_across);
|
||||||
|
if (ndummy > 0) {
|
||||||
|
/* Create dummy blocks at the right edge of the image. */
|
||||||
|
thisblockrow += blocks_across; /* => first dummy block */
|
||||||
|
jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
|
||||||
|
lastDC = thisblockrow[-1][0];
|
||||||
|
for (bi = 0; bi < ndummy; bi++) {
|
||||||
|
thisblockrow[bi][0] = lastDC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If at end of image, create dummy block rows as needed.
|
||||||
|
* The tricky part here is that within each MCU, we want the DC values
|
||||||
|
* of the dummy blocks to match the last real block's DC value.
|
||||||
|
* This squeezes a few more bytes out of the resulting file...
|
||||||
|
*/
|
||||||
|
if (coef->iMCU_row_num == last_iMCU_row) {
|
||||||
|
blocks_across += ndummy; /* include lower right corner */
|
||||||
|
MCUs_across = blocks_across / h_samp_factor;
|
||||||
|
for (block_row = block_rows; block_row < compptr->v_samp_factor;
|
||||||
|
block_row++) {
|
||||||
|
thisblockrow = buffer[block_row];
|
||||||
|
lastblockrow = buffer[block_row-1];
|
||||||
|
jzero_far((void FAR *) thisblockrow,
|
||||||
|
(size_t) (blocks_across * SIZEOF(JBLOCK)));
|
||||||
|
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
|
||||||
|
lastDC = lastblockrow[h_samp_factor-1][0];
|
||||||
|
for (bi = 0; bi < h_samp_factor; bi++) {
|
||||||
|
thisblockrow[bi][0] = lastDC;
|
||||||
|
}
|
||||||
|
thisblockrow += h_samp_factor; /* advance to next MCU in row */
|
||||||
|
lastblockrow += h_samp_factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NB: compress_output will increment iMCU_row_num if successful.
|
||||||
|
* A suspension return will result in redoing all the work above next time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Emit data to the entropy encoder, sharing code with subsequent passes */
|
||||||
|
return compress_output(cinfo, input_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data in subsequent passes of a multi-pass case.
|
||||||
|
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||||
|
* per call, ie, v_samp_factor block rows for each component in the scan.
|
||||||
|
* The data is obtained from the virtual arrays and fed to the entropy coder.
|
||||||
|
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
|
||||||
|
*
|
||||||
|
* NB: input_buf is ignored; it is likely to be a NULL pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||||
|
int blkn, ci, xindex, yindex, yoffset;
|
||||||
|
JDIMENSION start_col;
|
||||||
|
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||||
|
JBLOCKROW buffer_ptr;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Align the virtual buffers for the components used in this scan.
|
||||||
|
* NB: during first pass, this is safe only because the buffers will
|
||||||
|
* already be aligned properly, so jmemmgr.c won't need to do any I/O.
|
||||||
|
*/
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
buffer[ci] = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
|
||||||
|
coef->iMCU_row_num * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop to process one whole iMCU row */
|
||||||
|
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||||
|
yoffset++) {
|
||||||
|
for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
|
||||||
|
MCU_col_num++) {
|
||||||
|
/* Construct list of pointers to DCT blocks belonging to this MCU */
|
||||||
|
blkn = 0; /* index of current DCT block within MCU */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
start_col = MCU_col_num * compptr->MCU_width;
|
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||||
|
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
|
||||||
|
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
|
||||||
|
coef->MCU_buffer[blkn++] = buffer_ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Try to write the MCU. */
|
||||||
|
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||||
|
/* Suspension forced; update state counters and exit */
|
||||||
|
coef->MCU_vert_offset = yoffset;
|
||||||
|
coef->mcu_ctr = MCU_col_num;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||||
|
coef->mcu_ctr = 0;
|
||||||
|
}
|
||||||
|
/* Completed the iMCU row, advance counters for next one */
|
||||||
|
coef->iMCU_row_num++;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FULL_COEF_BUFFER_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize coefficient buffer controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef;
|
||||||
|
|
||||||
|
coef = (my_coef_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_coef_controller));
|
||||||
|
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
|
||||||
|
coef->pub.start_pass = start_pass_coef;
|
||||||
|
|
||||||
|
/* Create the coefficient buffer. */
|
||||||
|
if (need_full_buffer) {
|
||||||
|
#ifdef FULL_COEF_BUFFER_SUPPORTED
|
||||||
|
/* Allocate a full-image virtual array for each component, */
|
||||||
|
/* padded to a multiple of samp_factor DCT blocks in each direction. */
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||||
|
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||||
|
(long) compptr->h_samp_factor),
|
||||||
|
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||||
|
(long) compptr->v_samp_factor),
|
||||||
|
(JDIMENSION) compptr->v_samp_factor);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* We only need a single-MCU buffer. */
|
||||||
|
JBLOCKROW buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buffer = (JBLOCKROW)
|
||||||
|
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||||
|
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
|
||||||
|
coef->MCU_buffer[i] = buffer + i;
|
||||||
|
}
|
||||||
|
coef->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||||
|
}
|
||||||
|
}
|
||||||
513
jccolmmx.asm
Normal file
513
jccolmmx.asm
Normal file
@@ -0,0 +1,513 @@
|
|||||||
|
;
|
||||||
|
; jccolmmx.asm - colorspace conversion (MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : February 4, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
%ifdef JCCOLOR_RGBYCC_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%define SCALEBITS 16
|
||||||
|
|
||||||
|
F_0_081 equ 5329 ; FIX(0.08131)
|
||||||
|
F_0_114 equ 7471 ; FIX(0.11400)
|
||||||
|
F_0_168 equ 11059 ; FIX(0.16874)
|
||||||
|
F_0_250 equ 16384 ; FIX(0.25000)
|
||||||
|
F_0_299 equ 19595 ; FIX(0.29900)
|
||||||
|
F_0_331 equ 21709 ; FIX(0.33126)
|
||||||
|
F_0_418 equ 27439 ; FIX(0.41869)
|
||||||
|
F_0_587 equ 38470 ; FIX(0.58700)
|
||||||
|
F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000)
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_CONST
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
global EXTN(jconst_rgb_ycc_convert_mmx)
|
||||||
|
|
||||||
|
EXTN(jconst_rgb_ycc_convert_mmx):
|
||||||
|
|
||||||
|
PW_F0299_F0337 times 2 dw F_0_299, F_0_337
|
||||||
|
PW_F0114_F0250 times 2 dw F_0_114, F_0_250
|
||||||
|
PW_MF016_MF033 times 2 dw -F_0_168,-F_0_331
|
||||||
|
PW_MF008_MF041 times 2 dw -F_0_081,-F_0_418
|
||||||
|
PD_ONEHALFM1_CJ times 2 dd (1 << (SCALEBITS-1)) - 1 + (CENTERJSAMPLE << SCALEBITS)
|
||||||
|
PD_ONEHALF times 2 dd (1 << (SCALEBITS-1))
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Convert some rows of samples to the output colorspace.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_rgb_ycc_convert_mmx (j_compress_ptr cinfo,
|
||||||
|
; JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
; JDIMENSION output_row, int num_rows);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define input_buf(b) (b)+12 ; JSAMPARRAY input_buf
|
||||||
|
%define output_buf(b) (b)+16 ; JSAMPIMAGE output_buf
|
||||||
|
%define output_row(b) (b)+20 ; JDIMENSION output_row
|
||||||
|
%define num_rows(b) (b)+24 ; int num_rows
|
||||||
|
|
||||||
|
%define original_ebp ebp+0
|
||||||
|
%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_MMWORD ; mmword wk[WK_NUM]
|
||||||
|
%define WK_NUM 8
|
||||||
|
%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_rgb_ycc_convert_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_rgb_ycc_convert_mmx):
|
||||||
|
push ebp
|
||||||
|
mov eax,esp ; eax = original ebp
|
||||||
|
sub esp, byte 4
|
||||||
|
and esp, byte (-SIZEOF_MMWORD) ; align to 64 bits
|
||||||
|
mov [esp],eax
|
||||||
|
mov ebp,esp ; ebp = aligned ebp
|
||||||
|
lea esp, [wk(0)]
|
||||||
|
pushpic eax ; make a room for GOT address
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
get_GOT ebx ; get GOT address
|
||||||
|
movpic POINTER [gotptr], ebx ; save GOT address
|
||||||
|
|
||||||
|
mov ecx, POINTER [cinfo(eax)]
|
||||||
|
mov ecx, JDIMENSION [jcstruct_image_width(ecx)] ; num_cols
|
||||||
|
test ecx,ecx
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov esi, JSAMPIMAGE [output_buf(eax)]
|
||||||
|
mov ecx, JDIMENSION [output_row(eax)]
|
||||||
|
mov edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY]
|
||||||
|
mov ebx, JSAMPARRAY [esi+1*SIZEOF_JSAMPARRAY]
|
||||||
|
mov edx, JSAMPARRAY [esi+2*SIZEOF_JSAMPARRAY]
|
||||||
|
lea edi, [edi+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea ebx, [ebx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea edx, [edx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_buf(eax)]
|
||||||
|
mov eax, INT [num_rows(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
pushpic eax
|
||||||
|
push edx
|
||||||
|
push ebx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
push ecx ; col
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr0
|
||||||
|
mov ebx, JSAMPROW [ebx] ; outptr1
|
||||||
|
mov edx, JSAMPROW [edx] ; outptr2
|
||||||
|
movpic eax, POINTER [gotptr] ; load GOT address (eax)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD
|
||||||
|
jae short .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 ; ---------------
|
||||||
|
|
||||||
|
.column_ld1:
|
||||||
|
push eax
|
||||||
|
push edx
|
||||||
|
lea ecx,[ecx+ecx*2] ; imul ecx,RGB_PIXELSIZE
|
||||||
|
test cl, SIZEOF_BYTE
|
||||||
|
jz short .column_ld2
|
||||||
|
sub ecx, byte SIZEOF_BYTE
|
||||||
|
xor eax,eax
|
||||||
|
mov al, BYTE [esi+ecx]
|
||||||
|
.column_ld2:
|
||||||
|
test cl, SIZEOF_WORD
|
||||||
|
jz short .column_ld4
|
||||||
|
sub ecx, byte SIZEOF_WORD
|
||||||
|
xor edx,edx
|
||||||
|
mov dx, WORD [esi+ecx]
|
||||||
|
shl eax, WORD_BIT
|
||||||
|
or eax,edx
|
||||||
|
.column_ld4:
|
||||||
|
movd mmA,eax
|
||||||
|
pop edx
|
||||||
|
pop eax
|
||||||
|
test cl, SIZEOF_DWORD
|
||||||
|
jz short .column_ld8
|
||||||
|
sub ecx, byte SIZEOF_DWORD
|
||||||
|
movd mmG, DWORD [esi+ecx]
|
||||||
|
psllq mmA, DWORD_BIT
|
||||||
|
por mmA,mmG
|
||||||
|
.column_ld8:
|
||||||
|
test cl, SIZEOF_MMWORD
|
||||||
|
jz short .column_ld16
|
||||||
|
movq mmG,mmA
|
||||||
|
movq mmA, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
mov ecx, SIZEOF_MMWORD
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
.column_ld16:
|
||||||
|
test cl, 2*SIZEOF_MMWORD
|
||||||
|
mov ecx, SIZEOF_MMWORD
|
||||||
|
jz short .rgb_ycc_cnv
|
||||||
|
movq mmF,mmA
|
||||||
|
movq mmA, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mmG, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movq mmA, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mmG, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
movq mmF, MMWORD [esi+2*SIZEOF_MMWORD]
|
||||||
|
|
||||||
|
.rgb_ycc_cnv:
|
||||||
|
; mmA=(00 10 20 01 11 21 02 12)
|
||||||
|
; mmG=(22 03 13 23 04 14 24 05)
|
||||||
|
; mmF=(15 25 06 16 26 07 17 27)
|
||||||
|
|
||||||
|
movq mmD,mmA
|
||||||
|
psllq mmA,4*BYTE_BIT ; mmA=(-- -- -- -- 00 10 20 01)
|
||||||
|
psrlq mmD,4*BYTE_BIT ; mmD=(11 21 02 12 -- -- -- --)
|
||||||
|
|
||||||
|
punpckhbw mmA,mmG ; mmA=(00 04 10 14 20 24 01 05)
|
||||||
|
psllq mmG,4*BYTE_BIT ; mmG=(-- -- -- -- 22 03 13 23)
|
||||||
|
|
||||||
|
punpcklbw mmD,mmF ; mmD=(11 15 21 25 02 06 12 16)
|
||||||
|
punpckhbw mmG,mmF ; mmG=(22 26 03 07 13 17 23 27)
|
||||||
|
|
||||||
|
movq mmE,mmA
|
||||||
|
psllq mmA,4*BYTE_BIT ; mmA=(-- -- -- -- 00 04 10 14)
|
||||||
|
psrlq mmE,4*BYTE_BIT ; mmE=(20 24 01 05 -- -- -- --)
|
||||||
|
|
||||||
|
punpckhbw mmA,mmD ; mmA=(00 02 04 06 10 12 14 16)
|
||||||
|
psllq mmD,4*BYTE_BIT ; mmD=(-- -- -- -- 11 15 21 25)
|
||||||
|
|
||||||
|
punpcklbw mmE,mmG ; mmE=(20 22 24 26 01 03 05 07)
|
||||||
|
punpckhbw mmD,mmG ; mmD=(11 13 15 17 21 23 25 27)
|
||||||
|
|
||||||
|
pxor mmH,mmH
|
||||||
|
|
||||||
|
movq mmC,mmA
|
||||||
|
punpcklbw mmA,mmH ; mmA=(00 02 04 06)
|
||||||
|
punpckhbw mmC,mmH ; mmC=(10 12 14 16)
|
||||||
|
|
||||||
|
movq mmB,mmE
|
||||||
|
punpcklbw mmE,mmH ; mmE=(20 22 24 26)
|
||||||
|
punpckhbw mmB,mmH ; mmB=(01 03 05 07)
|
||||||
|
|
||||||
|
movq mmF,mmD
|
||||||
|
punpcklbw mmD,mmH ; mmD=(11 13 15 17)
|
||||||
|
punpckhbw mmF,mmH ; mmF=(21 23 25 27)
|
||||||
|
|
||||||
|
%else ; RGB_PIXELSIZE == 4 ; -----------
|
||||||
|
|
||||||
|
.column_ld1:
|
||||||
|
test cl, SIZEOF_MMWORD/8
|
||||||
|
jz short .column_ld2
|
||||||
|
sub ecx, byte SIZEOF_MMWORD/8
|
||||||
|
movd mmA, DWORD [esi+ecx*RGB_PIXELSIZE]
|
||||||
|
.column_ld2:
|
||||||
|
test cl, SIZEOF_MMWORD/4
|
||||||
|
jz short .column_ld4
|
||||||
|
sub ecx, byte SIZEOF_MMWORD/4
|
||||||
|
movq mmF,mmA
|
||||||
|
movq mmA, MMWORD [esi+ecx*RGB_PIXELSIZE]
|
||||||
|
.column_ld4:
|
||||||
|
test cl, SIZEOF_MMWORD/2
|
||||||
|
mov ecx, SIZEOF_MMWORD
|
||||||
|
jz short .rgb_ycc_cnv
|
||||||
|
movq mmD,mmA
|
||||||
|
movq mmC,mmF
|
||||||
|
movq mmA, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mmF, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movq mmA, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mmF, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
movq mmD, MMWORD [esi+2*SIZEOF_MMWORD]
|
||||||
|
movq mmC, MMWORD [esi+3*SIZEOF_MMWORD]
|
||||||
|
|
||||||
|
.rgb_ycc_cnv:
|
||||||
|
; mmA=(00 10 20 30 01 11 21 31)
|
||||||
|
; mmF=(02 12 22 32 03 13 23 33)
|
||||||
|
; mmD=(04 14 24 34 05 15 25 35)
|
||||||
|
; mmC=(06 16 26 36 07 17 27 37)
|
||||||
|
|
||||||
|
movq mmB,mmA
|
||||||
|
punpcklbw mmA,mmF ; mmA=(00 02 10 12 20 22 30 32)
|
||||||
|
punpckhbw mmB,mmF ; mmB=(01 03 11 13 21 23 31 33)
|
||||||
|
|
||||||
|
movq mmG,mmD
|
||||||
|
punpcklbw mmD,mmC ; mmD=(04 06 14 16 24 26 34 36)
|
||||||
|
punpckhbw mmG,mmC ; mmG=(05 07 15 17 25 27 35 37)
|
||||||
|
|
||||||
|
movq mmE,mmA
|
||||||
|
punpcklwd mmA,mmD ; mmA=(00 02 04 06 10 12 14 16)
|
||||||
|
punpckhwd mmE,mmD ; mmE=(20 22 24 26 30 32 34 36)
|
||||||
|
|
||||||
|
movq mmH,mmB
|
||||||
|
punpcklwd mmB,mmG ; mmB=(01 03 05 07 11 13 15 17)
|
||||||
|
punpckhwd mmH,mmG ; mmH=(21 23 25 27 31 33 35 37)
|
||||||
|
|
||||||
|
pxor mmF,mmF
|
||||||
|
|
||||||
|
movq mmC,mmA
|
||||||
|
punpcklbw mmA,mmF ; mmA=(00 02 04 06)
|
||||||
|
punpckhbw mmC,mmF ; mmC=(10 12 14 16)
|
||||||
|
|
||||||
|
movq mmD,mmB
|
||||||
|
punpcklbw mmB,mmF ; mmB=(01 03 05 07)
|
||||||
|
punpckhbw mmD,mmF ; mmD=(11 13 15 17)
|
||||||
|
|
||||||
|
movq mmG,mmE
|
||||||
|
punpcklbw mmE,mmF ; mmE=(20 22 24 26)
|
||||||
|
punpckhbw mmG,mmF ; mmG=(30 32 34 36)
|
||||||
|
|
||||||
|
punpcklbw mmF,mmH
|
||||||
|
punpckhbw mmH,mmH
|
||||||
|
psrlw mmF,BYTE_BIT ; mmF=(21 23 25 27)
|
||||||
|
psrlw mmH,BYTE_BIT ; mmH=(31 33 35 37)
|
||||||
|
|
||||||
|
%endif ; RGB_PIXELSIZE ; ---------------
|
||||||
|
|
||||||
|
; mm0=(R0 R2 R4 R6)=RE, mm2=(G0 G2 G4 G6)=GE, mm4=(B0 B2 B4 B6)=BE
|
||||||
|
; mm1=(R1 R3 R5 R7)=RO, mm3=(G1 G3 G5 G7)=GO, mm5=(B1 B3 B5 B7)=BO
|
||||||
|
|
||||||
|
; (Original)
|
||||||
|
; Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
|
||||||
|
; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
|
||||||
|
; Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
|
||||||
|
;
|
||||||
|
; (This implementation)
|
||||||
|
; Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
|
||||||
|
; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
|
||||||
|
; Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
|
||||||
|
|
||||||
|
movq MMWORD [wk(0)], mm0 ; wk(0)=RE
|
||||||
|
movq MMWORD [wk(1)], mm1 ; wk(1)=RO
|
||||||
|
movq MMWORD [wk(2)], mm4 ; wk(2)=BE
|
||||||
|
movq MMWORD [wk(3)], mm5 ; wk(3)=BO
|
||||||
|
|
||||||
|
movq mm6,mm1
|
||||||
|
punpcklwd mm1,mm3
|
||||||
|
punpckhwd mm6,mm3
|
||||||
|
movq mm7,mm1
|
||||||
|
movq mm4,mm6
|
||||||
|
pmaddwd mm1,[GOTOFF(eax,PW_F0299_F0337)] ; mm1=ROL*FIX(0.299)+GOL*FIX(0.337)
|
||||||
|
pmaddwd mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=ROH*FIX(0.299)+GOH*FIX(0.337)
|
||||||
|
pmaddwd mm7,[GOTOFF(eax,PW_MF016_MF033)] ; mm7=ROL*-FIX(0.168)+GOL*-FIX(0.331)
|
||||||
|
pmaddwd mm4,[GOTOFF(eax,PW_MF016_MF033)] ; mm4=ROH*-FIX(0.168)+GOH*-FIX(0.331)
|
||||||
|
|
||||||
|
movq MMWORD [wk(4)], mm1 ; wk(4)=ROL*FIX(0.299)+GOL*FIX(0.337)
|
||||||
|
movq MMWORD [wk(5)], mm6 ; wk(5)=ROH*FIX(0.299)+GOH*FIX(0.337)
|
||||||
|
|
||||||
|
pxor mm1,mm1
|
||||||
|
pxor mm6,mm6
|
||||||
|
punpcklwd mm1,mm5 ; mm1=BOL
|
||||||
|
punpckhwd mm6,mm5 ; mm6=BOH
|
||||||
|
psrld mm1,1 ; mm1=BOL*FIX(0.500)
|
||||||
|
psrld mm6,1 ; mm6=BOH*FIX(0.500)
|
||||||
|
|
||||||
|
movq mm5,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; mm5=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd mm7,mm1
|
||||||
|
paddd mm4,mm6
|
||||||
|
paddd mm7,mm5
|
||||||
|
paddd mm4,mm5
|
||||||
|
psrld mm7,SCALEBITS ; mm7=CbOL
|
||||||
|
psrld mm4,SCALEBITS ; mm4=CbOH
|
||||||
|
packssdw mm7,mm4 ; mm7=CbO
|
||||||
|
|
||||||
|
movq mm1, MMWORD [wk(2)] ; mm1=BE
|
||||||
|
|
||||||
|
movq mm6,mm0
|
||||||
|
punpcklwd mm0,mm2
|
||||||
|
punpckhwd mm6,mm2
|
||||||
|
movq mm5,mm0
|
||||||
|
movq mm4,mm6
|
||||||
|
pmaddwd mm0,[GOTOFF(eax,PW_F0299_F0337)] ; mm0=REL*FIX(0.299)+GEL*FIX(0.337)
|
||||||
|
pmaddwd mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=REH*FIX(0.299)+GEH*FIX(0.337)
|
||||||
|
pmaddwd mm5,[GOTOFF(eax,PW_MF016_MF033)] ; mm5=REL*-FIX(0.168)+GEL*-FIX(0.331)
|
||||||
|
pmaddwd mm4,[GOTOFF(eax,PW_MF016_MF033)] ; mm4=REH*-FIX(0.168)+GEH*-FIX(0.331)
|
||||||
|
|
||||||
|
movq MMWORD [wk(6)], mm0 ; wk(6)=REL*FIX(0.299)+GEL*FIX(0.337)
|
||||||
|
movq MMWORD [wk(7)], mm6 ; wk(7)=REH*FIX(0.299)+GEH*FIX(0.337)
|
||||||
|
|
||||||
|
pxor mm0,mm0
|
||||||
|
pxor mm6,mm6
|
||||||
|
punpcklwd mm0,mm1 ; mm0=BEL
|
||||||
|
punpckhwd mm6,mm1 ; mm6=BEH
|
||||||
|
psrld mm0,1 ; mm0=BEL*FIX(0.500)
|
||||||
|
psrld mm6,1 ; mm6=BEH*FIX(0.500)
|
||||||
|
|
||||||
|
movq mm1,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; mm1=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd mm5,mm0
|
||||||
|
paddd mm4,mm6
|
||||||
|
paddd mm5,mm1
|
||||||
|
paddd mm4,mm1
|
||||||
|
psrld mm5,SCALEBITS ; mm5=CbEL
|
||||||
|
psrld mm4,SCALEBITS ; mm4=CbEH
|
||||||
|
packssdw mm5,mm4 ; mm5=CbE
|
||||||
|
|
||||||
|
psllw mm7,BYTE_BIT
|
||||||
|
por mm5,mm7 ; mm5=Cb
|
||||||
|
movq MMWORD [ebx], mm5 ; Save Cb
|
||||||
|
|
||||||
|
movq mm0, MMWORD [wk(3)] ; mm0=BO
|
||||||
|
movq mm6, MMWORD [wk(2)] ; mm6=BE
|
||||||
|
movq mm1, MMWORD [wk(1)] ; mm1=RO
|
||||||
|
|
||||||
|
movq mm4,mm0
|
||||||
|
punpcklwd mm0,mm3
|
||||||
|
punpckhwd mm4,mm3
|
||||||
|
movq mm7,mm0
|
||||||
|
movq mm5,mm4
|
||||||
|
pmaddwd mm0,[GOTOFF(eax,PW_F0114_F0250)] ; mm0=BOL*FIX(0.114)+GOL*FIX(0.250)
|
||||||
|
pmaddwd mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BOH*FIX(0.114)+GOH*FIX(0.250)
|
||||||
|
pmaddwd mm7,[GOTOFF(eax,PW_MF008_MF041)] ; mm7=BOL*-FIX(0.081)+GOL*-FIX(0.418)
|
||||||
|
pmaddwd mm5,[GOTOFF(eax,PW_MF008_MF041)] ; mm5=BOH*-FIX(0.081)+GOH*-FIX(0.418)
|
||||||
|
|
||||||
|
movq mm3,[GOTOFF(eax,PD_ONEHALF)] ; mm3=[PD_ONEHALF]
|
||||||
|
|
||||||
|
paddd mm0, MMWORD [wk(4)]
|
||||||
|
paddd mm4, MMWORD [wk(5)]
|
||||||
|
paddd mm0,mm3
|
||||||
|
paddd mm4,mm3
|
||||||
|
psrld mm0,SCALEBITS ; mm0=YOL
|
||||||
|
psrld mm4,SCALEBITS ; mm4=YOH
|
||||||
|
packssdw mm0,mm4 ; mm0=YO
|
||||||
|
|
||||||
|
pxor mm3,mm3
|
||||||
|
pxor mm4,mm4
|
||||||
|
punpcklwd mm3,mm1 ; mm3=ROL
|
||||||
|
punpckhwd mm4,mm1 ; mm4=ROH
|
||||||
|
psrld mm3,1 ; mm3=ROL*FIX(0.500)
|
||||||
|
psrld mm4,1 ; mm4=ROH*FIX(0.500)
|
||||||
|
|
||||||
|
movq mm1,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; mm1=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd mm7,mm3
|
||||||
|
paddd mm5,mm4
|
||||||
|
paddd mm7,mm1
|
||||||
|
paddd mm5,mm1
|
||||||
|
psrld mm7,SCALEBITS ; mm7=CrOL
|
||||||
|
psrld mm5,SCALEBITS ; mm5=CrOH
|
||||||
|
packssdw mm7,mm5 ; mm7=CrO
|
||||||
|
|
||||||
|
movq mm3, MMWORD [wk(0)] ; mm3=RE
|
||||||
|
|
||||||
|
movq mm4,mm6
|
||||||
|
punpcklwd mm6,mm2
|
||||||
|
punpckhwd mm4,mm2
|
||||||
|
movq mm1,mm6
|
||||||
|
movq mm5,mm4
|
||||||
|
pmaddwd mm6,[GOTOFF(eax,PW_F0114_F0250)] ; mm6=BEL*FIX(0.114)+GEL*FIX(0.250)
|
||||||
|
pmaddwd mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BEH*FIX(0.114)+GEH*FIX(0.250)
|
||||||
|
pmaddwd mm1,[GOTOFF(eax,PW_MF008_MF041)] ; mm1=BEL*-FIX(0.081)+GEL*-FIX(0.418)
|
||||||
|
pmaddwd mm5,[GOTOFF(eax,PW_MF008_MF041)] ; mm5=BEH*-FIX(0.081)+GEH*-FIX(0.418)
|
||||||
|
|
||||||
|
movq mm2,[GOTOFF(eax,PD_ONEHALF)] ; mm2=[PD_ONEHALF]
|
||||||
|
|
||||||
|
paddd mm6, MMWORD [wk(6)]
|
||||||
|
paddd mm4, MMWORD [wk(7)]
|
||||||
|
paddd mm6,mm2
|
||||||
|
paddd mm4,mm2
|
||||||
|
psrld mm6,SCALEBITS ; mm6=YEL
|
||||||
|
psrld mm4,SCALEBITS ; mm4=YEH
|
||||||
|
packssdw mm6,mm4 ; mm6=YE
|
||||||
|
|
||||||
|
psllw mm0,BYTE_BIT
|
||||||
|
por mm6,mm0 ; mm6=Y
|
||||||
|
movq MMWORD [edi], mm6 ; Save Y
|
||||||
|
|
||||||
|
pxor mm2,mm2
|
||||||
|
pxor mm4,mm4
|
||||||
|
punpcklwd mm2,mm3 ; mm2=REL
|
||||||
|
punpckhwd mm4,mm3 ; mm4=REH
|
||||||
|
psrld mm2,1 ; mm2=REL*FIX(0.500)
|
||||||
|
psrld mm4,1 ; mm4=REH*FIX(0.500)
|
||||||
|
|
||||||
|
movq mm0,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; mm0=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd mm1,mm2
|
||||||
|
paddd mm5,mm4
|
||||||
|
paddd mm1,mm0
|
||||||
|
paddd mm5,mm0
|
||||||
|
psrld mm1,SCALEBITS ; mm1=CrEL
|
||||||
|
psrld mm5,SCALEBITS ; mm5=CrEH
|
||||||
|
packssdw mm1,mm5 ; mm1=CrE
|
||||||
|
|
||||||
|
psllw mm7,BYTE_BIT
|
||||||
|
por mm1,mm7 ; mm1=Cr
|
||||||
|
movq MMWORD [edx], mm1 ; Save Cr
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_MMWORD
|
||||||
|
add esi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; inptr
|
||||||
|
add edi, byte SIZEOF_MMWORD ; outptr0
|
||||||
|
add ebx, byte SIZEOF_MMWORD ; outptr1
|
||||||
|
add edx, byte SIZEOF_MMWORD ; outptr2
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD
|
||||||
|
jae near .columnloop
|
||||||
|
test ecx,ecx
|
||||||
|
jnz near .column_ld1
|
||||||
|
|
||||||
|
pop ecx ; col
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ebx
|
||||||
|
pop edx
|
||||||
|
poppic eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW ; input_buf
|
||||||
|
add edi, byte SIZEOF_JSAMPROW
|
||||||
|
add ebx, byte SIZEOF_JSAMPROW
|
||||||
|
add edx, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax ; num_rows
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
mov esp,ebp ; esp <- aligned ebp
|
||||||
|
pop esp ; esp <- original ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JCCOLOR_RGBYCC_MMX_SUPPORTED
|
||||||
|
%endif ; RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
530
jccolor.c
530
jccolor.c
@@ -1,206 +1,508 @@
|
|||||||
/*
|
/*
|
||||||
* jccolor.c
|
* jccolor.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, Thomas G. Lane.
|
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||||
* This file is part of the Independent JPEG Group's software.
|
* This file is part of the Independent JPEG Group's software.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 5, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
* This file contains input colorspace conversion routines.
|
* This file contains input colorspace conversion routines.
|
||||||
* These routines are invoked via the methods get_sample_rows
|
|
||||||
* and colorin_init/term.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jcolsamp.h" /* Private declarations */
|
||||||
|
|
||||||
|
|
||||||
static JSAMPARRAY pixel_row; /* Workspace for a pixel row in input format */
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_color_converter pub; /* public fields */
|
||||||
|
|
||||||
|
/* Private state for RGB->YCC conversion */
|
||||||
|
INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
|
||||||
|
} my_color_converter;
|
||||||
|
|
||||||
|
typedef my_color_converter * my_cconvert_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/**************** RGB -> YCbCr conversion: most common case **************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize for colorspace conversion.
|
|
||||||
*/
|
|
||||||
|
|
||||||
METHODDEF void
|
|
||||||
colorin_init (compress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
/* Allocate a workspace for the result of get_input_row. */
|
|
||||||
pixel_row = (*cinfo->emethods->alloc_small_sarray)
|
|
||||||
(cinfo->image_width, (long) cinfo->input_components);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fetch some rows of pixels from get_input_row and convert to the
|
|
||||||
* JPEG colorspace.
|
|
||||||
* This version handles RGB -> YCbCr conversion.
|
|
||||||
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
* 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.
|
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
||||||
|
* The conversion equations to be implemented are therefore
|
||||||
|
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
|
||||||
|
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
|
||||||
|
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
|
||||||
|
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
|
||||||
|
* Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
|
||||||
|
* rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
|
||||||
|
* negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
|
||||||
|
* were not represented exactly. Now we sacrifice exact representation of
|
||||||
|
* maximum red and maximum blue in order to get exact grayscales.
|
||||||
|
*
|
||||||
|
* To avoid floating-point arithmetic, we represent the fractional constants
|
||||||
|
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
|
||||||
|
* the products by 2^16, with appropriate rounding, to get the correct answer.
|
||||||
|
*
|
||||||
|
* For even more speed, we avoid doing any multiplications in the inner loop
|
||||||
|
* by precalculating the constants times R,G,B for all possible values.
|
||||||
|
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
|
||||||
|
* for 12-bit samples it is still acceptable. It's not very reasonable for
|
||||||
|
* 16-bit samples, but if you want lossless storage you shouldn't be changing
|
||||||
|
* colorspace anyway.
|
||||||
|
* The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
|
||||||
|
* in the tables to save adding them separately in the inner loop.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
#define SCALEBITS 16 /* speediest right-shift on some machines */
|
||||||
get_rgb_ycc_rows (compress_info_ptr cinfo,
|
#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
|
||||||
int rows_to_read, JSAMPIMAGE image_data)
|
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
|
||||||
{
|
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
|
||||||
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++) {
|
/* We allocate one big table and divide it up into eight parts, instead of
|
||||||
/* Read one row from the source file */
|
* doing eight alloc_small requests. This lets us use a single table base
|
||||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
* address, which can be held in a register in the inner loops on many
|
||||||
/* Convert colorspace */
|
* machines (more than can hold all eight addresses, anyway).
|
||||||
inptr0 = pixel_row[0];
|
*/
|
||||||
inptr1 = pixel_row[1];
|
|
||||||
inptr2 = pixel_row[2];
|
#define R_Y_OFF 0 /* offset to R => Y section */
|
||||||
outptr0 = image_data[0][row];
|
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
|
||||||
outptr1 = image_data[1][row];
|
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
|
||||||
outptr2 = image_data[2][row];
|
#define R_CB_OFF (3*(MAXJSAMPLE+1))
|
||||||
for (col = width; col > 0; col--) {
|
#define G_CB_OFF (4*(MAXJSAMPLE+1))
|
||||||
r = GETJSAMPLE(*inptr0++);
|
#define B_CB_OFF (5*(MAXJSAMPLE+1))
|
||||||
g = GETJSAMPLE(*inptr1++);
|
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
|
||||||
b = GETJSAMPLE(*inptr2++);
|
#define G_CR_OFF (6*(MAXJSAMPLE+1))
|
||||||
|
#define B_CR_OFF (7*(MAXJSAMPLE+1))
|
||||||
|
#define TABLE_SIZE (8*(MAXJSAMPLE+1))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for RGB->YCC colorspace conversion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
rgb_ycc_start (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
INT32 * rgb_ycc_tab;
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
/* Allocate and fill in the conversion tables. */
|
||||||
|
cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(TABLE_SIZE * SIZEOF(INT32)));
|
||||||
|
|
||||||
|
for (i = 0; i <= MAXJSAMPLE; i++) {
|
||||||
|
rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
|
||||||
|
rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
|
||||||
|
rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
|
||||||
|
rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
|
||||||
|
rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
|
||||||
|
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
|
||||||
|
* This ensures that the maximum output will round to MAXJSAMPLE
|
||||||
|
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
|
||||||
|
*/
|
||||||
|
rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
|
||||||
|
/* B=>Cb and R=>Cr tables are the same
|
||||||
|
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
|
||||||
|
*/
|
||||||
|
rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
|
||||||
|
rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace.
|
||||||
|
*
|
||||||
|
* Note that we change from the application's interleaved-pixel format
|
||||||
|
* to our internal noninterleaved, one-plane-per-component format.
|
||||||
|
* The input buffer is therefore three times as wide as the output buffer.
|
||||||
|
*
|
||||||
|
* A starting row offset is provided only for the output buffer. The caller
|
||||||
|
* can easily adjust the passed input_buf value to accommodate any row
|
||||||
|
* offset required on that side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
rgb_ycc_convert (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows)
|
||||||
|
{
|
||||||
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
register int r, g, b;
|
||||||
|
register INT32 * ctab = cconvert->rgb_ycc_tab;
|
||||||
|
register JSAMPROW inptr;
|
||||||
|
register JSAMPROW outptr0, outptr1, outptr2;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->image_width;
|
||||||
|
|
||||||
|
while (--num_rows >= 0) {
|
||||||
|
inptr = *input_buf++;
|
||||||
|
outptr0 = output_buf[0][output_row];
|
||||||
|
outptr1 = output_buf[1][output_row];
|
||||||
|
outptr2 = output_buf[2][output_row];
|
||||||
|
output_row++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
r = GETJSAMPLE(inptr[RGB_RED]);
|
||||||
|
g = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||||
|
b = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||||
|
inptr += RGB_PIXELSIZE;
|
||||||
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||||
* must be too; do not need an explicit range-limiting operation.
|
* must be too; we do not need an explicit range-limiting operation.
|
||||||
|
* Hence the value being shifted is never negative, and we don't
|
||||||
|
* need the general RIGHT_SHIFT macro.
|
||||||
*/
|
*/
|
||||||
/* Y */
|
/* Y */
|
||||||
*outptr0++ = (JSAMPLE)
|
outptr0[col] = (JSAMPLE)
|
||||||
(( 306*r + 601*g + 117*b + (INT32) 512) >> 10);
|
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
/* Cb */
|
/* Cb */
|
||||||
*outptr1++ = (JSAMPLE)
|
outptr1[col] = (JSAMPLE)
|
||||||
(((-173)*r - 339*g + 512*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10);
|
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
/* Cr */
|
/* Cr */
|
||||||
*outptr2++ = (JSAMPLE)
|
outptr2[col] = (JSAMPLE)
|
||||||
(( 512*r - 429*g - 83*b + (INT32) 512*(MAXJSAMPLE+1)) >> 10);
|
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************** Cases other than RGB -> YCbCr **************/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace.
|
||||||
|
* This version handles RGB->grayscale conversion, which is the same
|
||||||
|
* as the RGB->Y portion of RGB->YCbCr.
|
||||||
|
* We assume rgb_ycc_start has been called (we only use the Y tables).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
rgb_gray_convert (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows)
|
||||||
|
{
|
||||||
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
register int r, g, b;
|
||||||
|
register INT32 * ctab = cconvert->rgb_ycc_tab;
|
||||||
|
register JSAMPROW inptr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->image_width;
|
||||||
|
|
||||||
|
while (--num_rows >= 0) {
|
||||||
|
inptr = *input_buf++;
|
||||||
|
outptr = output_buf[0][output_row];
|
||||||
|
output_row++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
r = GETJSAMPLE(inptr[RGB_RED]);
|
||||||
|
g = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||||
|
b = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||||
|
inptr += RGB_PIXELSIZE;
|
||||||
|
/* Y */
|
||||||
|
outptr[col] = (JSAMPLE)
|
||||||
|
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch some rows of pixels from get_input_row and convert to the
|
* Convert some rows of samples to the JPEG colorspace.
|
||||||
* JPEG colorspace.
|
* This version handles Adobe-style CMYK->YCCK conversion,
|
||||||
* This version handles grayscale (no conversion).
|
* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
|
||||||
|
* conversion as above, while passing K (black) unchanged.
|
||||||
|
* We assume rgb_ycc_start has been called.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
get_grayscale_rows (compress_info_ptr cinfo,
|
cmyk_ycck_convert (j_compress_ptr cinfo,
|
||||||
int rows_to_read, JSAMPIMAGE image_data)
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows)
|
||||||
{
|
{
|
||||||
int row;
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
register int r, g, b;
|
||||||
|
register INT32 * ctab = cconvert->rgb_ycc_tab;
|
||||||
|
register JSAMPROW inptr;
|
||||||
|
register JSAMPROW outptr0, outptr1, outptr2, outptr3;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->image_width;
|
||||||
|
|
||||||
for (row = 0; row < rows_to_read; row++) {
|
while (--num_rows >= 0) {
|
||||||
/* Read one row from the source file */
|
inptr = *input_buf++;
|
||||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
outptr0 = output_buf[0][output_row];
|
||||||
/* Convert colorspace (gamma mapping needed here) */
|
outptr1 = output_buf[1][output_row];
|
||||||
jcopy_sample_rows(pixel_row, 0, image_data[0], row,
|
outptr2 = output_buf[2][output_row];
|
||||||
1, cinfo->image_width);
|
outptr3 = output_buf[3][output_row];
|
||||||
|
output_row++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
|
||||||
|
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
|
||||||
|
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
|
||||||
|
/* K passes through as-is */
|
||||||
|
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
|
||||||
|
inptr += 4;
|
||||||
|
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||||
|
* must be too; we do not need an explicit range-limiting operation.
|
||||||
|
* Hence the value being shifted is never negative, and we don't
|
||||||
|
* need the general RIGHT_SHIFT macro.
|
||||||
|
*/
|
||||||
|
/* Y */
|
||||||
|
outptr0[col] = (JSAMPLE)
|
||||||
|
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
|
/* Cb */
|
||||||
|
outptr1[col] = (JSAMPLE)
|
||||||
|
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
|
/* Cr */
|
||||||
|
outptr2[col] = (JSAMPLE)
|
||||||
|
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
|
||||||
|
>> SCALEBITS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch some rows of pixels from get_input_row and convert to the
|
* Convert some rows of samples to the JPEG colorspace.
|
||||||
* JPEG colorspace.
|
* This version handles grayscale output with no conversion.
|
||||||
|
* The source can be either plain grayscale or YCbCr (since Y == gray).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
grayscale_convert (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows)
|
||||||
|
{
|
||||||
|
register JSAMPROW inptr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->image_width;
|
||||||
|
int instride = cinfo->input_components;
|
||||||
|
|
||||||
|
while (--num_rows >= 0) {
|
||||||
|
inptr = *input_buf++;
|
||||||
|
outptr = output_buf[0][output_row];
|
||||||
|
output_row++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
|
||||||
|
inptr += instride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace.
|
||||||
* This version handles multi-component colorspaces without conversion.
|
* This version handles multi-component colorspaces without conversion.
|
||||||
|
* We assume input_components == num_components.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
get_noconvert_rows (compress_info_ptr cinfo,
|
null_convert (j_compress_ptr cinfo,
|
||||||
int rows_to_read, JSAMPIMAGE image_data)
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows)
|
||||||
{
|
{
|
||||||
int row, ci;
|
register JSAMPROW inptr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
|
register JDIMENSION col;
|
||||||
|
register int ci;
|
||||||
|
int nc = cinfo->num_components;
|
||||||
|
JDIMENSION num_cols = cinfo->image_width;
|
||||||
|
|
||||||
for (row = 0; row < rows_to_read; row++) {
|
while (--num_rows >= 0) {
|
||||||
/* Read one row from the source file */
|
/* It seems fastest to make a separate pass for each component. */
|
||||||
(*cinfo->methods->get_input_row) (cinfo, pixel_row);
|
for (ci = 0; ci < nc; ci++) {
|
||||||
/* Convert colorspace (gamma mapping needed here) */
|
inptr = *input_buf;
|
||||||
for (ci = 0; ci < cinfo->input_components; ci++) {
|
outptr = output_buf[ci][output_row];
|
||||||
jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
|
for (col = 0; col < num_cols; col++) {
|
||||||
1, cinfo->image_width);
|
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
|
||||||
|
inptr += nc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
input_buf++;
|
||||||
|
output_row++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish up at the end of the file.
|
* Empty method for start_pass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
colorin_term (compress_info_ptr cinfo)
|
null_method (j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
/* Release the workspace. */
|
/* no work needed */
|
||||||
(*cinfo->emethods->free_small_sarray)
|
|
||||||
(pixel_row, (long) cinfo->input_components);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The method selection routine for input colorspace conversion.
|
* Module initialization routine for input colorspace conversion.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GLOBAL void
|
GLOBAL(void)
|
||||||
jselccolor (compress_info_ptr cinfo)
|
jinit_color_converter (j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
|
my_cconvert_ptr cconvert;
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
cconvert = (my_cconvert_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_color_converter));
|
||||||
|
cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
|
||||||
|
/* set start_pass to null method until we find out differently */
|
||||||
|
cconvert->pub.start_pass = null_method;
|
||||||
|
|
||||||
/* Make sure input_components agrees with in_color_space */
|
/* Make sure input_components agrees with in_color_space */
|
||||||
switch (cinfo->in_color_space) {
|
switch (cinfo->in_color_space) {
|
||||||
case CS_GRAYSCALE:
|
case JCS_GRAYSCALE:
|
||||||
if (cinfo->input_components != 1)
|
if (cinfo->input_components != 1)
|
||||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_RGB:
|
case JCS_RGB:
|
||||||
|
#if RGB_PIXELSIZE != 3
|
||||||
|
if (cinfo->input_components != RGB_PIXELSIZE)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
|
break;
|
||||||
|
#endif /* else share code with YCbCr */
|
||||||
|
|
||||||
|
case JCS_YCbCr:
|
||||||
if (cinfo->input_components != 3)
|
if (cinfo->input_components != 3)
|
||||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_CMYK:
|
case JCS_CMYK:
|
||||||
|
case JCS_YCCK:
|
||||||
if (cinfo->input_components != 4)
|
if (cinfo->input_components != 4)
|
||||||
ERREXIT(cinfo->emethods, "Bogus input colorspace");
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default: /* JCS_UNKNOWN can be anything */
|
||||||
ERREXIT(cinfo->emethods, "Unsupported input colorspace");
|
if (cinfo->input_components < 1)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check num_components, set conversion method based on requested space */
|
/* Check num_components, set conversion method based on requested space */
|
||||||
switch (cinfo->jpeg_color_space) {
|
switch (cinfo->jpeg_color_space) {
|
||||||
case CS_GRAYSCALE:
|
case JCS_GRAYSCALE:
|
||||||
if (cinfo->num_components != 1)
|
if (cinfo->num_components != 1)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == CS_GRAYSCALE)
|
if (cinfo->in_color_space == JCS_GRAYSCALE)
|
||||||
cinfo->methods->get_sample_rows = get_grayscale_rows;
|
cconvert->pub.color_convert = grayscale_convert;
|
||||||
|
else if (cinfo->in_color_space == JCS_RGB) {
|
||||||
|
cconvert->pub.start_pass = rgb_ycc_start;
|
||||||
|
cconvert->pub.color_convert = rgb_gray_convert;
|
||||||
|
} else if (cinfo->in_color_space == JCS_YCbCr)
|
||||||
|
cconvert->pub.color_convert = grayscale_convert;
|
||||||
else
|
else
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_YCbCr:
|
case JCS_RGB:
|
||||||
if (cinfo->num_components != 3)
|
if (cinfo->num_components != 3)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == CS_RGB)
|
if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
|
||||||
cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
|
cconvert->pub.color_convert = null_convert;
|
||||||
else
|
else
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_CMYK:
|
case JCS_YCbCr:
|
||||||
|
if (cinfo->num_components != 3)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
|
if (cinfo->in_color_space == JCS_RGB) {
|
||||||
|
#if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
#ifdef JCCOLOR_RGBYCC_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_rgb_ycc_convert_sse2)) {
|
||||||
|
cconvert->pub.color_convert = jpeg_rgb_ycc_convert_sse2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JCCOLOR_RGBYCC_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX) {
|
||||||
|
cconvert->pub.color_convert = jpeg_rgb_ycc_convert_mmx;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#endif /* RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4 */
|
||||||
|
{
|
||||||
|
cconvert->pub.start_pass = rgb_ycc_start;
|
||||||
|
cconvert->pub.color_convert = rgb_ycc_convert;
|
||||||
|
}
|
||||||
|
} else if (cinfo->in_color_space == JCS_YCbCr)
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
|
else
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JCS_CMYK:
|
||||||
if (cinfo->num_components != 4)
|
if (cinfo->num_components != 4)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == CS_CMYK)
|
if (cinfo->in_color_space == JCS_CMYK)
|
||||||
cinfo->methods->get_sample_rows = get_noconvert_rows;
|
cconvert->pub.color_convert = null_convert;
|
||||||
else
|
else
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case JCS_YCCK:
|
||||||
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
|
if (cinfo->num_components != 4)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
|
if (cinfo->in_color_space == JCS_CMYK) {
|
||||||
|
cconvert->pub.start_pass = rgb_ycc_start;
|
||||||
|
cconvert->pub.color_convert = cmyk_ycck_convert;
|
||||||
|
} else if (cinfo->in_color_space == JCS_YCCK)
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
|
else
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* allow null conversion of JCS_UNKNOWN */
|
||||||
|
if (cinfo->jpeg_color_space != cinfo->in_color_space ||
|
||||||
|
cinfo->num_components != cinfo->input_components)
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cinfo->methods->colorin_init = colorin_init;
|
|
||||||
cinfo->methods->colorin_term = colorin_term;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_color_converter (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
#if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
#ifdef JCCOLOR_RGBYCC_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_rgb_ycc_convert_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JCCOLOR_RGBYCC_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
#endif /* RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4 */
|
||||||
|
|
||||||
|
return JSIMD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|||||||
541
jccolss2.asm
Normal file
541
jccolss2.asm
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
;
|
||||||
|
; jccolss2.asm - colorspace conversion (SSE2)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : February 4, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
%ifdef JCCOLOR_RGBYCC_SSE2_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%define SCALEBITS 16
|
||||||
|
|
||||||
|
F_0_081 equ 5329 ; FIX(0.08131)
|
||||||
|
F_0_114 equ 7471 ; FIX(0.11400)
|
||||||
|
F_0_168 equ 11059 ; FIX(0.16874)
|
||||||
|
F_0_250 equ 16384 ; FIX(0.25000)
|
||||||
|
F_0_299 equ 19595 ; FIX(0.29900)
|
||||||
|
F_0_331 equ 21709 ; FIX(0.33126)
|
||||||
|
F_0_418 equ 27439 ; FIX(0.41869)
|
||||||
|
F_0_587 equ 38470 ; FIX(0.58700)
|
||||||
|
F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000)
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_CONST
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
global EXTN(jconst_rgb_ycc_convert_sse2)
|
||||||
|
|
||||||
|
EXTN(jconst_rgb_ycc_convert_sse2):
|
||||||
|
|
||||||
|
PW_F0299_F0337 times 4 dw F_0_299, F_0_337
|
||||||
|
PW_F0114_F0250 times 4 dw F_0_114, F_0_250
|
||||||
|
PW_MF016_MF033 times 4 dw -F_0_168,-F_0_331
|
||||||
|
PW_MF008_MF041 times 4 dw -F_0_081,-F_0_418
|
||||||
|
PD_ONEHALFM1_CJ times 4 dd (1 << (SCALEBITS-1)) - 1 + (CENTERJSAMPLE << SCALEBITS)
|
||||||
|
PD_ONEHALF times 4 dd (1 << (SCALEBITS-1))
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Convert some rows of samples to the output colorspace.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_rgb_ycc_convert_sse2 (j_compress_ptr cinfo,
|
||||||
|
; JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
; JDIMENSION output_row, int num_rows);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define input_buf(b) (b)+12 ; JSAMPARRAY input_buf
|
||||||
|
%define output_buf(b) (b)+16 ; JSAMPIMAGE output_buf
|
||||||
|
%define output_row(b) (b)+20 ; JDIMENSION output_row
|
||||||
|
%define num_rows(b) (b)+24 ; int num_rows
|
||||||
|
|
||||||
|
%define original_ebp ebp+0
|
||||||
|
%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_XMMWORD ; xmmword wk[WK_NUM]
|
||||||
|
%define WK_NUM 8
|
||||||
|
%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_rgb_ycc_convert_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_rgb_ycc_convert_sse2):
|
||||||
|
push ebp
|
||||||
|
mov eax,esp ; eax = original ebp
|
||||||
|
sub esp, byte 4
|
||||||
|
and esp, byte (-SIZEOF_XMMWORD) ; align to 128 bits
|
||||||
|
mov [esp],eax
|
||||||
|
mov ebp,esp ; ebp = aligned ebp
|
||||||
|
lea esp, [wk(0)]
|
||||||
|
pushpic eax ; make a room for GOT address
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
get_GOT ebx ; get GOT address
|
||||||
|
movpic POINTER [gotptr], ebx ; save GOT address
|
||||||
|
|
||||||
|
mov ecx, POINTER [cinfo(eax)]
|
||||||
|
mov ecx, JDIMENSION [jcstruct_image_width(ecx)] ; num_cols
|
||||||
|
test ecx,ecx
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov esi, JSAMPIMAGE [output_buf(eax)]
|
||||||
|
mov ecx, JDIMENSION [output_row(eax)]
|
||||||
|
mov edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY]
|
||||||
|
mov ebx, JSAMPARRAY [esi+1*SIZEOF_JSAMPARRAY]
|
||||||
|
mov edx, JSAMPARRAY [esi+2*SIZEOF_JSAMPARRAY]
|
||||||
|
lea edi, [edi+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea ebx, [ebx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea edx, [edx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_buf(eax)]
|
||||||
|
mov eax, INT [num_rows(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
pushpic eax
|
||||||
|
push edx
|
||||||
|
push ebx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
push ecx ; col
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr0
|
||||||
|
mov ebx, JSAMPROW [ebx] ; outptr1
|
||||||
|
mov edx, JSAMPROW [edx] ; outptr2
|
||||||
|
movpic eax, POINTER [gotptr] ; load GOT address (eax)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae near .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 ; ---------------
|
||||||
|
|
||||||
|
.column_ld1:
|
||||||
|
push eax
|
||||||
|
push edx
|
||||||
|
lea ecx,[ecx+ecx*2] ; imul ecx,RGB_PIXELSIZE
|
||||||
|
test cl, SIZEOF_BYTE
|
||||||
|
jz short .column_ld2
|
||||||
|
sub ecx, byte SIZEOF_BYTE
|
||||||
|
movzx eax, BYTE [esi+ecx]
|
||||||
|
.column_ld2:
|
||||||
|
test cl, SIZEOF_WORD
|
||||||
|
jz short .column_ld4
|
||||||
|
sub ecx, byte SIZEOF_WORD
|
||||||
|
movzx edx, WORD [esi+ecx]
|
||||||
|
shl eax, WORD_BIT
|
||||||
|
or eax,edx
|
||||||
|
.column_ld4:
|
||||||
|
movd xmmA,eax
|
||||||
|
pop edx
|
||||||
|
pop eax
|
||||||
|
test cl, SIZEOF_DWORD
|
||||||
|
jz short .column_ld8
|
||||||
|
sub ecx, byte SIZEOF_DWORD
|
||||||
|
movd xmmF, _DWORD [esi+ecx]
|
||||||
|
pslldq xmmA, SIZEOF_DWORD
|
||||||
|
por xmmA,xmmF
|
||||||
|
.column_ld8:
|
||||||
|
test cl, SIZEOF_MMWORD
|
||||||
|
jz short .column_ld16
|
||||||
|
sub ecx, byte SIZEOF_MMWORD
|
||||||
|
movq xmmB, _MMWORD [esi+ecx]
|
||||||
|
pslldq xmmA, SIZEOF_MMWORD
|
||||||
|
por xmmA,xmmB
|
||||||
|
.column_ld16:
|
||||||
|
test cl, SIZEOF_XMMWORD
|
||||||
|
jz short .column_ld32
|
||||||
|
movdqa xmmF,xmmA
|
||||||
|
movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
mov ecx, SIZEOF_XMMWORD
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
.column_ld32:
|
||||||
|
test cl, 2*SIZEOF_XMMWORD
|
||||||
|
mov ecx, SIZEOF_XMMWORD
|
||||||
|
jz short .rgb_ycc_cnv
|
||||||
|
movdqa xmmB,xmmA
|
||||||
|
movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmB, XMMWORD [esi+2*SIZEOF_XMMWORD]
|
||||||
|
|
||||||
|
.rgb_ycc_cnv:
|
||||||
|
; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05)
|
||||||
|
; xmmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
|
||||||
|
; xmmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F)
|
||||||
|
|
||||||
|
movdqa xmmG,xmmA
|
||||||
|
pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12)
|
||||||
|
psrldq xmmG,8 ; xmmG=(22 03 13 23 04 14 24 05 -- -- -- -- -- -- -- --)
|
||||||
|
|
||||||
|
punpckhbw xmmA,xmmF ; xmmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A)
|
||||||
|
pslldq xmmF,8 ; xmmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27)
|
||||||
|
|
||||||
|
punpcklbw xmmG,xmmB ; xmmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D)
|
||||||
|
punpckhbw xmmF,xmmB ; xmmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F)
|
||||||
|
|
||||||
|
movdqa xmmD,xmmA
|
||||||
|
pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09)
|
||||||
|
psrldq xmmD,8 ; xmmD=(11 19 21 29 02 0A 12 1A -- -- -- -- -- -- -- --)
|
||||||
|
|
||||||
|
punpckhbw xmmA,xmmG ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D)
|
||||||
|
pslldq xmmG,8 ; xmmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B)
|
||||||
|
|
||||||
|
punpcklbw xmmD,xmmF ; xmmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E)
|
||||||
|
punpckhbw xmmG,xmmF ; xmmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F)
|
||||||
|
|
||||||
|
movdqa xmmE,xmmA
|
||||||
|
pslldq xmmA,8 ; xmmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C)
|
||||||
|
psrldq xmmE,8 ; xmmE=(20 24 28 2C 01 05 09 0D -- -- -- -- -- -- -- --)
|
||||||
|
|
||||||
|
punpckhbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
|
||||||
|
pslldq xmmD,8 ; xmmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D)
|
||||||
|
|
||||||
|
punpcklbw xmmE,xmmG ; xmmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F)
|
||||||
|
punpckhbw xmmD,xmmG ; xmmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F)
|
||||||
|
|
||||||
|
pxor xmmH,xmmH
|
||||||
|
|
||||||
|
movdqa xmmC,xmmA
|
||||||
|
punpcklbw xmmA,xmmH ; xmmA=(00 02 04 06 08 0A 0C 0E)
|
||||||
|
punpckhbw xmmC,xmmH ; xmmC=(10 12 14 16 18 1A 1C 1E)
|
||||||
|
|
||||||
|
movdqa xmmB,xmmE
|
||||||
|
punpcklbw xmmE,xmmH ; xmmE=(20 22 24 26 28 2A 2C 2E)
|
||||||
|
punpckhbw xmmB,xmmH ; xmmB=(01 03 05 07 09 0B 0D 0F)
|
||||||
|
|
||||||
|
movdqa xmmF,xmmD
|
||||||
|
punpcklbw xmmD,xmmH ; xmmD=(11 13 15 17 19 1B 1D 1F)
|
||||||
|
punpckhbw xmmF,xmmH ; xmmF=(21 23 25 27 29 2B 2D 2F)
|
||||||
|
|
||||||
|
%else ; RGB_PIXELSIZE == 4 ; -----------
|
||||||
|
|
||||||
|
.column_ld1:
|
||||||
|
test cl, SIZEOF_XMMWORD/16
|
||||||
|
jz short .column_ld2
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD/16
|
||||||
|
movd xmmA, _DWORD [esi+ecx*RGB_PIXELSIZE]
|
||||||
|
.column_ld2:
|
||||||
|
test cl, SIZEOF_XMMWORD/8
|
||||||
|
jz short .column_ld4
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD/8
|
||||||
|
movq xmmE, _MMWORD [esi+ecx*RGB_PIXELSIZE]
|
||||||
|
pslldq xmmA, SIZEOF_MMWORD
|
||||||
|
por xmmA,xmmE
|
||||||
|
.column_ld4:
|
||||||
|
test cl, SIZEOF_XMMWORD/4
|
||||||
|
jz short .column_ld8
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD/4
|
||||||
|
movdqa xmmE,xmmA
|
||||||
|
movdqu xmmA, XMMWORD [esi+ecx*RGB_PIXELSIZE]
|
||||||
|
.column_ld8:
|
||||||
|
test cl, SIZEOF_XMMWORD/2
|
||||||
|
mov ecx, SIZEOF_XMMWORD
|
||||||
|
jz short .rgb_ycc_cnv
|
||||||
|
movdqa xmmF,xmmA
|
||||||
|
movdqa xmmH,xmmE
|
||||||
|
movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
jmp short .rgb_ycc_cnv
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmF, XMMWORD [esi+2*SIZEOF_XMMWORD]
|
||||||
|
movdqu xmmH, XMMWORD [esi+3*SIZEOF_XMMWORD]
|
||||||
|
|
||||||
|
.rgb_ycc_cnv:
|
||||||
|
; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33)
|
||||||
|
; xmmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37)
|
||||||
|
; xmmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B)
|
||||||
|
; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F)
|
||||||
|
|
||||||
|
movdqa xmmD,xmmA
|
||||||
|
punpcklbw xmmA,xmmE ; xmmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35)
|
||||||
|
punpckhbw xmmD,xmmE ; xmmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37)
|
||||||
|
|
||||||
|
movdqa xmmC,xmmF
|
||||||
|
punpcklbw xmmF,xmmH ; xmmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D)
|
||||||
|
punpckhbw xmmC,xmmH ; xmmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F)
|
||||||
|
|
||||||
|
movdqa xmmB,xmmA
|
||||||
|
punpcklwd xmmA,xmmF ; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C)
|
||||||
|
punpckhwd xmmB,xmmF ; xmmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D)
|
||||||
|
|
||||||
|
movdqa xmmG,xmmD
|
||||||
|
punpcklwd xmmD,xmmC ; xmmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E)
|
||||||
|
punpckhwd xmmG,xmmC ; xmmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F)
|
||||||
|
|
||||||
|
movdqa xmmE,xmmA
|
||||||
|
punpcklbw xmmA,xmmD ; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
|
||||||
|
punpckhbw xmmE,xmmD ; xmmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E)
|
||||||
|
|
||||||
|
movdqa xmmH,xmmB
|
||||||
|
punpcklbw xmmB,xmmG ; xmmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F)
|
||||||
|
punpckhbw xmmH,xmmG ; xmmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F)
|
||||||
|
|
||||||
|
pxor xmmF,xmmF
|
||||||
|
|
||||||
|
movdqa xmmC,xmmA
|
||||||
|
punpcklbw xmmA,xmmF ; xmmA=(00 02 04 06 08 0A 0C 0E)
|
||||||
|
punpckhbw xmmC,xmmF ; xmmC=(10 12 14 16 18 1A 1C 1E)
|
||||||
|
|
||||||
|
movdqa xmmD,xmmB
|
||||||
|
punpcklbw xmmB,xmmF ; xmmB=(01 03 05 07 09 0B 0D 0F)
|
||||||
|
punpckhbw xmmD,xmmF ; xmmD=(11 13 15 17 19 1B 1D 1F)
|
||||||
|
|
||||||
|
movdqa xmmG,xmmE
|
||||||
|
punpcklbw xmmE,xmmF ; xmmE=(20 22 24 26 28 2A 2C 2E)
|
||||||
|
punpckhbw xmmG,xmmF ; xmmG=(30 32 34 36 38 3A 3C 3E)
|
||||||
|
|
||||||
|
punpcklbw xmmF,xmmH
|
||||||
|
punpckhbw xmmH,xmmH
|
||||||
|
psrlw xmmF,BYTE_BIT ; xmmF=(21 23 25 27 29 2B 2D 2F)
|
||||||
|
psrlw xmmH,BYTE_BIT ; xmmH=(31 33 35 37 39 3B 3D 3F)
|
||||||
|
|
||||||
|
%endif ; RGB_PIXELSIZE ; ---------------
|
||||||
|
|
||||||
|
; xmm0=R(02468ACE)=RE, xmm2=G(02468ACE)=GE, xmm4=B(02468ACE)=BE
|
||||||
|
; xmm1=R(13579BDF)=RO, xmm3=G(13579BDF)=GO, xmm5=B(13579BDF)=BO
|
||||||
|
|
||||||
|
; (Original)
|
||||||
|
; Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
|
||||||
|
; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
|
||||||
|
; Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
|
||||||
|
;
|
||||||
|
; (This implementation)
|
||||||
|
; Y = 0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
|
||||||
|
; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
|
||||||
|
; Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
|
||||||
|
|
||||||
|
movdqa XMMWORD [wk(0)], xmm0 ; wk(0)=RE
|
||||||
|
movdqa XMMWORD [wk(1)], xmm1 ; wk(1)=RO
|
||||||
|
movdqa XMMWORD [wk(2)], xmm4 ; wk(2)=BE
|
||||||
|
movdqa XMMWORD [wk(3)], xmm5 ; wk(3)=BO
|
||||||
|
|
||||||
|
movdqa xmm6,xmm1
|
||||||
|
punpcklwd xmm1,xmm3
|
||||||
|
punpckhwd xmm6,xmm3
|
||||||
|
movdqa xmm7,xmm1
|
||||||
|
movdqa xmm4,xmm6
|
||||||
|
pmaddwd xmm1,[GOTOFF(eax,PW_F0299_F0337)] ; xmm1=ROL*FIX(0.299)+GOL*FIX(0.337)
|
||||||
|
pmaddwd xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=ROH*FIX(0.299)+GOH*FIX(0.337)
|
||||||
|
pmaddwd xmm7,[GOTOFF(eax,PW_MF016_MF033)] ; xmm7=ROL*-FIX(0.168)+GOL*-FIX(0.331)
|
||||||
|
pmaddwd xmm4,[GOTOFF(eax,PW_MF016_MF033)] ; xmm4=ROH*-FIX(0.168)+GOH*-FIX(0.331)
|
||||||
|
|
||||||
|
movdqa XMMWORD [wk(4)], xmm1 ; wk(4)=ROL*FIX(0.299)+GOL*FIX(0.337)
|
||||||
|
movdqa XMMWORD [wk(5)], xmm6 ; wk(5)=ROH*FIX(0.299)+GOH*FIX(0.337)
|
||||||
|
|
||||||
|
pxor xmm1,xmm1
|
||||||
|
pxor xmm6,xmm6
|
||||||
|
punpcklwd xmm1,xmm5 ; xmm1=BOL
|
||||||
|
punpckhwd xmm6,xmm5 ; xmm6=BOH
|
||||||
|
psrld xmm1,1 ; xmm1=BOL*FIX(0.500)
|
||||||
|
psrld xmm6,1 ; xmm6=BOH*FIX(0.500)
|
||||||
|
|
||||||
|
movdqa xmm5,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; xmm5=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd xmm7,xmm1
|
||||||
|
paddd xmm4,xmm6
|
||||||
|
paddd xmm7,xmm5
|
||||||
|
paddd xmm4,xmm5
|
||||||
|
psrld xmm7,SCALEBITS ; xmm7=CbOL
|
||||||
|
psrld xmm4,SCALEBITS ; xmm4=CbOH
|
||||||
|
packssdw xmm7,xmm4 ; xmm7=CbO
|
||||||
|
|
||||||
|
movdqa xmm1, XMMWORD [wk(2)] ; xmm1=BE
|
||||||
|
|
||||||
|
movdqa xmm6,xmm0
|
||||||
|
punpcklwd xmm0,xmm2
|
||||||
|
punpckhwd xmm6,xmm2
|
||||||
|
movdqa xmm5,xmm0
|
||||||
|
movdqa xmm4,xmm6
|
||||||
|
pmaddwd xmm0,[GOTOFF(eax,PW_F0299_F0337)] ; xmm0=REL*FIX(0.299)+GEL*FIX(0.337)
|
||||||
|
pmaddwd xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=REH*FIX(0.299)+GEH*FIX(0.337)
|
||||||
|
pmaddwd xmm5,[GOTOFF(eax,PW_MF016_MF033)] ; xmm5=REL*-FIX(0.168)+GEL*-FIX(0.331)
|
||||||
|
pmaddwd xmm4,[GOTOFF(eax,PW_MF016_MF033)] ; xmm4=REH*-FIX(0.168)+GEH*-FIX(0.331)
|
||||||
|
|
||||||
|
movdqa XMMWORD [wk(6)], xmm0 ; wk(6)=REL*FIX(0.299)+GEL*FIX(0.337)
|
||||||
|
movdqa XMMWORD [wk(7)], xmm6 ; wk(7)=REH*FIX(0.299)+GEH*FIX(0.337)
|
||||||
|
|
||||||
|
pxor xmm0,xmm0
|
||||||
|
pxor xmm6,xmm6
|
||||||
|
punpcklwd xmm0,xmm1 ; xmm0=BEL
|
||||||
|
punpckhwd xmm6,xmm1 ; xmm6=BEH
|
||||||
|
psrld xmm0,1 ; xmm0=BEL*FIX(0.500)
|
||||||
|
psrld xmm6,1 ; xmm6=BEH*FIX(0.500)
|
||||||
|
|
||||||
|
movdqa xmm1,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; xmm1=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd xmm5,xmm0
|
||||||
|
paddd xmm4,xmm6
|
||||||
|
paddd xmm5,xmm1
|
||||||
|
paddd xmm4,xmm1
|
||||||
|
psrld xmm5,SCALEBITS ; xmm5=CbEL
|
||||||
|
psrld xmm4,SCALEBITS ; xmm4=CbEH
|
||||||
|
packssdw xmm5,xmm4 ; xmm5=CbE
|
||||||
|
|
||||||
|
psllw xmm7,BYTE_BIT
|
||||||
|
por xmm5,xmm7 ; xmm5=Cb
|
||||||
|
movdqa XMMWORD [ebx], xmm5 ; Save Cb
|
||||||
|
|
||||||
|
movdqa xmm0, XMMWORD [wk(3)] ; xmm0=BO
|
||||||
|
movdqa xmm6, XMMWORD [wk(2)] ; xmm6=BE
|
||||||
|
movdqa xmm1, XMMWORD [wk(1)] ; xmm1=RO
|
||||||
|
|
||||||
|
movdqa xmm4,xmm0
|
||||||
|
punpcklwd xmm0,xmm3
|
||||||
|
punpckhwd xmm4,xmm3
|
||||||
|
movdqa xmm7,xmm0
|
||||||
|
movdqa xmm5,xmm4
|
||||||
|
pmaddwd xmm0,[GOTOFF(eax,PW_F0114_F0250)] ; xmm0=BOL*FIX(0.114)+GOL*FIX(0.250)
|
||||||
|
pmaddwd xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BOH*FIX(0.114)+GOH*FIX(0.250)
|
||||||
|
pmaddwd xmm7,[GOTOFF(eax,PW_MF008_MF041)] ; xmm7=BOL*-FIX(0.081)+GOL*-FIX(0.418)
|
||||||
|
pmaddwd xmm5,[GOTOFF(eax,PW_MF008_MF041)] ; xmm5=BOH*-FIX(0.081)+GOH*-FIX(0.418)
|
||||||
|
|
||||||
|
movdqa xmm3,[GOTOFF(eax,PD_ONEHALF)] ; xmm3=[PD_ONEHALF]
|
||||||
|
|
||||||
|
paddd xmm0, XMMWORD [wk(4)]
|
||||||
|
paddd xmm4, XMMWORD [wk(5)]
|
||||||
|
paddd xmm0,xmm3
|
||||||
|
paddd xmm4,xmm3
|
||||||
|
psrld xmm0,SCALEBITS ; xmm0=YOL
|
||||||
|
psrld xmm4,SCALEBITS ; xmm4=YOH
|
||||||
|
packssdw xmm0,xmm4 ; xmm0=YO
|
||||||
|
|
||||||
|
pxor xmm3,xmm3
|
||||||
|
pxor xmm4,xmm4
|
||||||
|
punpcklwd xmm3,xmm1 ; xmm3=ROL
|
||||||
|
punpckhwd xmm4,xmm1 ; xmm4=ROH
|
||||||
|
psrld xmm3,1 ; xmm3=ROL*FIX(0.500)
|
||||||
|
psrld xmm4,1 ; xmm4=ROH*FIX(0.500)
|
||||||
|
|
||||||
|
movdqa xmm1,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; xmm1=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd xmm7,xmm3
|
||||||
|
paddd xmm5,xmm4
|
||||||
|
paddd xmm7,xmm1
|
||||||
|
paddd xmm5,xmm1
|
||||||
|
psrld xmm7,SCALEBITS ; xmm7=CrOL
|
||||||
|
psrld xmm5,SCALEBITS ; xmm5=CrOH
|
||||||
|
packssdw xmm7,xmm5 ; xmm7=CrO
|
||||||
|
|
||||||
|
movdqa xmm3, XMMWORD [wk(0)] ; xmm3=RE
|
||||||
|
|
||||||
|
movdqa xmm4,xmm6
|
||||||
|
punpcklwd xmm6,xmm2
|
||||||
|
punpckhwd xmm4,xmm2
|
||||||
|
movdqa xmm1,xmm6
|
||||||
|
movdqa xmm5,xmm4
|
||||||
|
pmaddwd xmm6,[GOTOFF(eax,PW_F0114_F0250)] ; xmm6=BEL*FIX(0.114)+GEL*FIX(0.250)
|
||||||
|
pmaddwd xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BEH*FIX(0.114)+GEH*FIX(0.250)
|
||||||
|
pmaddwd xmm1,[GOTOFF(eax,PW_MF008_MF041)] ; xmm1=BEL*-FIX(0.081)+GEL*-FIX(0.418)
|
||||||
|
pmaddwd xmm5,[GOTOFF(eax,PW_MF008_MF041)] ; xmm5=BEH*-FIX(0.081)+GEH*-FIX(0.418)
|
||||||
|
|
||||||
|
movdqa xmm2,[GOTOFF(eax,PD_ONEHALF)] ; xmm2=[PD_ONEHALF]
|
||||||
|
|
||||||
|
paddd xmm6, XMMWORD [wk(6)]
|
||||||
|
paddd xmm4, XMMWORD [wk(7)]
|
||||||
|
paddd xmm6,xmm2
|
||||||
|
paddd xmm4,xmm2
|
||||||
|
psrld xmm6,SCALEBITS ; xmm6=YEL
|
||||||
|
psrld xmm4,SCALEBITS ; xmm4=YEH
|
||||||
|
packssdw xmm6,xmm4 ; xmm6=YE
|
||||||
|
|
||||||
|
psllw xmm0,BYTE_BIT
|
||||||
|
por xmm6,xmm0 ; xmm6=Y
|
||||||
|
movdqa XMMWORD [edi], xmm6 ; Save Y
|
||||||
|
|
||||||
|
pxor xmm2,xmm2
|
||||||
|
pxor xmm4,xmm4
|
||||||
|
punpcklwd xmm2,xmm3 ; xmm2=REL
|
||||||
|
punpckhwd xmm4,xmm3 ; xmm4=REH
|
||||||
|
psrld xmm2,1 ; xmm2=REL*FIX(0.500)
|
||||||
|
psrld xmm4,1 ; xmm4=REH*FIX(0.500)
|
||||||
|
|
||||||
|
movdqa xmm0,[GOTOFF(eax,PD_ONEHALFM1_CJ)] ; xmm0=[PD_ONEHALFM1_CJ]
|
||||||
|
|
||||||
|
paddd xmm1,xmm2
|
||||||
|
paddd xmm5,xmm4
|
||||||
|
paddd xmm1,xmm0
|
||||||
|
paddd xmm5,xmm0
|
||||||
|
psrld xmm1,SCALEBITS ; xmm1=CrEL
|
||||||
|
psrld xmm5,SCALEBITS ; xmm5=CrEH
|
||||||
|
packssdw xmm1,xmm5 ; xmm1=CrE
|
||||||
|
|
||||||
|
psllw xmm7,BYTE_BIT
|
||||||
|
por xmm1,xmm7 ; xmm1=Cr
|
||||||
|
movdqa XMMWORD [edx], xmm1 ; Save Cr
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD
|
||||||
|
add esi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD ; inptr
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr0
|
||||||
|
add ebx, byte SIZEOF_XMMWORD ; outptr1
|
||||||
|
add edx, byte SIZEOF_XMMWORD ; outptr2
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae near .columnloop
|
||||||
|
test ecx,ecx
|
||||||
|
jnz near .column_ld1
|
||||||
|
|
||||||
|
pop ecx ; col
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ebx
|
||||||
|
pop edx
|
||||||
|
poppic eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW ; input_buf
|
||||||
|
add edi, byte SIZEOF_JSAMPROW
|
||||||
|
add ebx, byte SIZEOF_JSAMPROW
|
||||||
|
add edx, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax ; num_rows
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
mov esp,ebp ; esp <- aligned ebp
|
||||||
|
pop esp ; esp <- original ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JCCOLOR_RGBYCC_SSE2_SUPPORTED
|
||||||
|
%endif ; RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
515
jcdctmgr.c
Normal file
515
jcdctmgr.c
Normal file
@@ -0,0 +1,515 @@
|
|||||||
|
/*
|
||||||
|
* jcdctmgr.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : December 24, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains the forward-DCT management logic.
|
||||||
|
* This code selects a particular DCT implementation to be used,
|
||||||
|
* and it performs related housekeeping chores including coefficient
|
||||||
|
* quantization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||||
|
|
||||||
|
|
||||||
|
/* Private subobject for this module */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_forward_dct pub; /* public fields */
|
||||||
|
|
||||||
|
/* Pointer to the DCT routine actually in use */
|
||||||
|
forward_DCT_method_ptr do_dct;
|
||||||
|
convsamp_int_method_ptr convsamp;
|
||||||
|
quantize_int_method_ptr quantize;
|
||||||
|
|
||||||
|
/* The actual post-DCT divisors --- not identical to the quant table
|
||||||
|
* entries, because of scaling (especially for an unnormalized DCT).
|
||||||
|
* Each table is given in normal array order.
|
||||||
|
*/
|
||||||
|
DCTELEM * divisors[NUM_QUANT_TBLS];
|
||||||
|
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
/* Same as above for the floating-point case. */
|
||||||
|
float_DCT_method_ptr do_float_dct;
|
||||||
|
convsamp_float_method_ptr float_convsamp;
|
||||||
|
quantize_float_method_ptr float_quantize;
|
||||||
|
FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
|
||||||
|
#endif
|
||||||
|
} my_fdct_controller;
|
||||||
|
|
||||||
|
typedef my_fdct_controller * my_fdct_ptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: Most of SSE/SSE2 instructions require that the memory address
|
||||||
|
* is aligned to a 16-byte boundary; if not, a general-protection exception
|
||||||
|
* (#GP) is generated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ALIGN_SIZE 16 /* sizeof SSE/SSE2 register */
|
||||||
|
#define ALIGN_MEM(p,a) ((void *) (((size_t) (p) + (a) - 1) & -(a)))
|
||||||
|
|
||||||
|
#ifdef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
#undef jpeg_quantize_int
|
||||||
|
#undef jpeg_quantize_int_mmx
|
||||||
|
#undef jpeg_quantize_int_sse2
|
||||||
|
#define jpeg_quantize_int jpeg_quantize_idiv
|
||||||
|
#define jpeg_quantize_int_mmx jpeg_quantize_idiv
|
||||||
|
#define jpeg_quantize_int_sse2 jpeg_quantize_idiv
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: compute the reciprocal of the divisor
|
||||||
|
*
|
||||||
|
* This implementation is based on an algorithm described in
|
||||||
|
* "How to optimize for the Pentium family of microprocessors"
|
||||||
|
* (http://www.agner.org/assem/).
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
compute_reciprocal (DCTELEM divisor, DCTELEM * dtbl)
|
||||||
|
{
|
||||||
|
unsigned long d = ((unsigned long) divisor) & 0x0000FFFF;
|
||||||
|
unsigned long fq, fr;
|
||||||
|
int b, r, c;
|
||||||
|
|
||||||
|
for (b = 0; (1UL << b) <= d; b++) ;
|
||||||
|
|
||||||
|
r = 16 + (--b);
|
||||||
|
fq = (1UL << r) / d;
|
||||||
|
fr = (1UL << r) % d;
|
||||||
|
r -= 16;
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
if (fr == 0) {
|
||||||
|
fq >>= 1;
|
||||||
|
r--;
|
||||||
|
} else if (fr <= (d / 2)) {
|
||||||
|
c++;
|
||||||
|
} else {
|
||||||
|
fq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dtbl[DCTSIZE2 * 0] = (DCTELEM) fq; /* reciprocal */
|
||||||
|
dtbl[DCTSIZE2 * 1] = (DCTELEM) (c + (d / 2)); /* correction + roundfactor */
|
||||||
|
dtbl[DCTSIZE2 * 2] = (DCTELEM) (1 << (16 - (r + 1 + 1))); /* scale */
|
||||||
|
dtbl[DCTSIZE2 * 3] = (DCTELEM) (r + 1); /* shift */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JFDCT_INT_QUANTIZE_WITH_DIVISION */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
* Verify that all referenced Q-tables are present, and set up
|
||||||
|
* the divisor table for each one.
|
||||||
|
* In the current implementation, DCT of all components is done during
|
||||||
|
* the first pass, even if only some components will be output in the
|
||||||
|
* first scan. Hence all components should be examined here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_fdctmgr (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||||
|
int ci, qtblno, i;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JQUANT_TBL * qtbl;
|
||||||
|
DCTELEM * dtbl;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
qtblno = compptr->quant_tbl_no;
|
||||||
|
/* Make sure specified quantization table is present */
|
||||||
|
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||||
|
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||||
|
qtbl = cinfo->quant_tbl_ptrs[qtblno];
|
||||||
|
/* Compute divisors for this quant table */
|
||||||
|
/* We may do this more than once for same table, but it's not a big deal */
|
||||||
|
switch (cinfo->dct_method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
/* For LL&M IDCT method, divisors are equal to raw quantization
|
||||||
|
* coefficients multiplied by 8 (to counteract scaling).
|
||||||
|
*/
|
||||||
|
#ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
if (fdct->divisors[qtblno] == NULL) {
|
||||||
|
fdct->divisors[qtblno] = (DCTELEM *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(DCTSIZE2 * 4) * SIZEOF(DCTELEM));
|
||||||
|
}
|
||||||
|
dtbl = fdct->divisors[qtblno];
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
compute_reciprocal ((DCTELEM) (qtbl->quantval[i] << 3), &dtbl[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else /* JFDCT_INT_QUANTIZE_WITH_DIVISION */
|
||||||
|
if (fdct->divisors[qtblno] == NULL) {
|
||||||
|
fdct->divisors[qtblno] = (DCTELEM *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
DCTSIZE2 * SIZEOF(DCTELEM));
|
||||||
|
}
|
||||||
|
dtbl = fdct->divisors[qtblno];
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* JFDCT_INT_QUANTIZE_WITH_DIVISION */
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
{
|
||||||
|
/* For AA&N IDCT method, divisors are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||||
|
* scalefactor[0] = 1
|
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||||
|
* We apply a further scale factor of 8.
|
||||||
|
*/
|
||||||
|
#define CONST_BITS 14
|
||||||
|
static const INT16 aanscales[DCTSIZE2] = {
|
||||||
|
/* precomputed values scaled up by 14 bits */
|
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||||
|
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
|
||||||
|
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
|
||||||
|
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
|
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||||
|
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
|
||||||
|
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
|
||||||
|
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
|
||||||
|
};
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
#ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
if (fdct->divisors[qtblno] == NULL) {
|
||||||
|
fdct->divisors[qtblno] = (DCTELEM *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(DCTSIZE2 * 4) * SIZEOF(DCTELEM));
|
||||||
|
}
|
||||||
|
dtbl = fdct->divisors[qtblno];
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
compute_reciprocal ((DCTELEM)
|
||||||
|
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
|
||||||
|
(INT32) aanscales[i]),
|
||||||
|
CONST_BITS-3),
|
||||||
|
&dtbl[i]);
|
||||||
|
}
|
||||||
|
#else /* JFDCT_INT_QUANTIZE_WITH_DIVISION */
|
||||||
|
if (fdct->divisors[qtblno] == NULL) {
|
||||||
|
fdct->divisors[qtblno] = (DCTELEM *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
DCTSIZE2 * SIZEOF(DCTELEM));
|
||||||
|
}
|
||||||
|
dtbl = fdct->divisors[qtblno];
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
dtbl[i] = (DCTELEM)
|
||||||
|
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
|
||||||
|
(INT32) aanscales[i]),
|
||||||
|
CONST_BITS-3);
|
||||||
|
}
|
||||||
|
#endif /* JFDCT_INT_QUANTIZE_WITH_DIVISION */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* DCT_IFAST_SUPPORTED */
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
{
|
||||||
|
/* For float AA&N IDCT method, divisors are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||||
|
* scalefactor[0] = 1
|
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||||
|
* We apply a further scale factor of 8.
|
||||||
|
* What's actually stored is 1/divisor so that the inner loop can
|
||||||
|
* use a multiplication rather than a division.
|
||||||
|
*/
|
||||||
|
FAST_FLOAT * fdtbl;
|
||||||
|
int row, col;
|
||||||
|
static const double aanscalefactor[DCTSIZE] = {
|
||||||
|
1.0, 1.387039845, 1.306562965, 1.175875602,
|
||||||
|
1.0, 0.785694958, 0.541196100, 0.275899379
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fdct->float_divisors[qtblno] == NULL) {
|
||||||
|
fdct->float_divisors[qtblno] = (FAST_FLOAT *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
DCTSIZE2 * SIZEOF(FAST_FLOAT));
|
||||||
|
}
|
||||||
|
fdtbl = fdct->float_divisors[qtblno];
|
||||||
|
i = 0;
|
||||||
|
for (row = 0; row < DCTSIZE; row++) {
|
||||||
|
for (col = 0; col < DCTSIZE; col++) {
|
||||||
|
fdtbl[i] = (FAST_FLOAT)
|
||||||
|
(1.0 / (((double) qtbl->quantval[i] *
|
||||||
|
aanscalefactor[row] * aanscalefactor[col] * 8.0)));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform forward DCT on one or more blocks of a component.
|
||||||
|
*
|
||||||
|
* The input samples are taken from the sample_data[] array starting at
|
||||||
|
* position start_row/start_col, and moving to the right for any additional
|
||||||
|
* blocks. The quantized coefficients are returned in coef_blocks[].
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||||
|
JDIMENSION start_row, JDIMENSION start_col,
|
||||||
|
JDIMENSION num_blocks)
|
||||||
|
/* This version is used for integer DCT implementations. */
|
||||||
|
{
|
||||||
|
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||||
|
DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
|
||||||
|
DCTELEM workspace[DCTSIZE2 + ALIGN_SIZE/sizeof(DCTELEM)];
|
||||||
|
DCTELEM * wkptr = (DCTELEM *) ALIGN_MEM(workspace, ALIGN_SIZE);
|
||||||
|
JDIMENSION bi;
|
||||||
|
|
||||||
|
sample_data += start_row; /* fold in the vertical offset once */
|
||||||
|
|
||||||
|
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
|
||||||
|
/* Load data into workspace, applying unsigned->signed conversion */
|
||||||
|
(*fdct->convsamp) (sample_data, start_col, wkptr);
|
||||||
|
|
||||||
|
/* Perform the DCT */
|
||||||
|
(*fdct->do_dct) (wkptr);
|
||||||
|
|
||||||
|
/* Quantize/descale the coefficients, and store into coef_blocks[] */
|
||||||
|
(*fdct->quantize) (coef_blocks[bi], divisors, wkptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||||
|
JDIMENSION start_row, JDIMENSION start_col,
|
||||||
|
JDIMENSION num_blocks)
|
||||||
|
/* This version is used for floating-point DCT implementations. */
|
||||||
|
{
|
||||||
|
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||||
|
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
|
||||||
|
FAST_FLOAT workspace[DCTSIZE2 + ALIGN_SIZE/sizeof(FAST_FLOAT)];
|
||||||
|
FAST_FLOAT * wkptr = (FAST_FLOAT *) ALIGN_MEM(workspace, ALIGN_SIZE);
|
||||||
|
JDIMENSION bi;
|
||||||
|
|
||||||
|
sample_data += start_row; /* fold in the vertical offset once */
|
||||||
|
|
||||||
|
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
|
||||||
|
/* Load data into workspace, applying unsigned->signed conversion */
|
||||||
|
(*fdct->float_convsamp) (sample_data, start_col, wkptr);
|
||||||
|
|
||||||
|
/* Perform the DCT */
|
||||||
|
(*fdct->do_float_dct) (wkptr);
|
||||||
|
|
||||||
|
/* Quantize/descale the coefficients, and store into coef_blocks[] */
|
||||||
|
(*fdct->float_quantize) (coef_blocks[bi], divisors, wkptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize FDCT manager.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_forward_dct (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_fdct_ptr fdct;
|
||||||
|
int i;
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
fdct = (my_fdct_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_fdct_controller));
|
||||||
|
cinfo->fdct = (struct jpeg_forward_dct *) fdct;
|
||||||
|
fdct->pub.start_pass = start_pass_fdctmgr;
|
||||||
|
|
||||||
|
switch (cinfo->dct_method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
fdct->pub.forward_DCT = forward_DCT;
|
||||||
|
#ifdef JFDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_islow_sse2)) {
|
||||||
|
fdct->do_dct = jpeg_fdct_islow_sse2;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int_sse2;
|
||||||
|
fdct->quantize = jpeg_quantize_int_sse2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX) {
|
||||||
|
fdct->do_dct = jpeg_fdct_islow_mmx;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int_mmx;
|
||||||
|
fdct->quantize = jpeg_quantize_int_mmx;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fdct->do_dct = jpeg_fdct_islow;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int;
|
||||||
|
fdct->quantize = jpeg_quantize_int;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
fdct->pub.forward_DCT = forward_DCT;
|
||||||
|
#ifdef JFDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_ifast_sse2)) {
|
||||||
|
fdct->do_dct = jpeg_fdct_ifast_sse2;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int_sse2;
|
||||||
|
fdct->quantize = jpeg_quantize_int_sse2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX) {
|
||||||
|
fdct->do_dct = jpeg_fdct_ifast_mmx;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int_mmx;
|
||||||
|
fdct->quantize = jpeg_quantize_int_mmx;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fdct->do_dct = jpeg_fdct_ifast;
|
||||||
|
fdct->convsamp = jpeg_convsamp_int;
|
||||||
|
fdct->quantize = jpeg_quantize_int;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* DCT_IFAST_SUPPORTED */
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
fdct->pub.forward_DCT = forward_DCT_float;
|
||||||
|
#ifdef JFDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE && simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_float_sse)) {
|
||||||
|
fdct->do_float_dct = jpeg_fdct_float_sse;
|
||||||
|
fdct->float_convsamp = jpeg_convsamp_flt_sse2;
|
||||||
|
fdct->float_quantize = jpeg_quantize_flt_sse2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_float_sse)) {
|
||||||
|
fdct->do_float_dct = jpeg_fdct_float_sse;
|
||||||
|
fdct->float_convsamp = jpeg_convsamp_flt_sse;
|
||||||
|
fdct->float_quantize = jpeg_quantize_flt_sse;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_3DNOW) {
|
||||||
|
fdct->do_float_dct = jpeg_fdct_float_3dnow;
|
||||||
|
fdct->float_convsamp = jpeg_convsamp_flt_3dnow;
|
||||||
|
fdct->float_quantize = jpeg_quantize_flt_3dnow;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fdct->do_float_dct = jpeg_fdct_float;
|
||||||
|
fdct->float_convsamp = jpeg_convsamp_float;
|
||||||
|
fdct->float_quantize = jpeg_quantize_float;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark divisor tables unallocated */
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||||
|
fdct->divisors[i] = NULL;
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
fdct->float_divisors[i] = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_forward_dct (j_compress_ptr cinfo, int method)
|
||||||
|
{
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
#ifdef JFDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_islow_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
#ifdef JFDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_ifast_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_IFAST_SUPPORTED */
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
#ifdef JFDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE && simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_float_sse))
|
||||||
|
return JSIMD_SSE; /* (JSIMD_SSE | JSIMD_SSE2); */
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_fdct_float_sse))
|
||||||
|
return JSIMD_SSE; /* (JSIMD_SSE | JSIMD_MMX); */
|
||||||
|
#endif
|
||||||
|
#ifdef JFDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_3DNOW)
|
||||||
|
return JSIMD_3DNOW; /* (JSIMD_3DNOW | JSIMD_MMX); */
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSIMD_NONE; /* not compiled */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
367
jcdeflts.c
367
jcdeflts.c
@@ -1,367 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
* User interfaces do not have to use this file, but those that don't use it
|
|
||||||
* must know a lot more about the innards of the JPEG code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jinclude.h"
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
|
||||||
add_huff_table (compress_info_ptr cinfo,
|
|
||||||
HUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
|
|
||||||
/* Define a Huffman table */
|
|
||||||
{
|
|
||||||
if (*htblptr == NULL)
|
|
||||||
*htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
|
|
||||||
|
|
||||||
memcpy((void *) (*htblptr)->bits, (const void *) bits,
|
|
||||||
SIZEOF((*htblptr)->bits));
|
|
||||||
memcpy((void *) (*htblptr)->huffval, (const void *) val,
|
|
||||||
SIZEOF((*htblptr)->huffval));
|
|
||||||
|
|
||||||
/* Initialize sent_table FALSE so table will be written to JPEG file.
|
|
||||||
* In an application where we are writing non-interchange JPEG files,
|
|
||||||
* it might be desirable to save space by leaving default Huffman tables
|
|
||||||
* out of the file. To do that, just initialize sent_table = TRUE...
|
|
||||||
*/
|
|
||||||
|
|
||||||
(*htblptr)->sent_table = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
|
||||||
std_huff_tables (compress_info_ptr cinfo)
|
|
||||||
/* Set up the standard Huffman tables (cf. JPEG-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 = (QUANT_TBL_PTR) (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
|
|
||||||
|
|
||||||
for (i = 0; i < DCTSIZE2; i++) {
|
|
||||||
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
|
|
||||||
/* limit the values to the valid range */
|
|
||||||
if (temp <= 0L) temp = 1L;
|
|
||||||
#ifdef EIGHT_BIT_SAMPLES
|
|
||||||
if (temp > 32767L) temp = 32767L; /* QUANT_VALs are 'short' */
|
|
||||||
#else
|
|
||||||
if (temp > 65535L) temp = 65535L; /* QUANT_VALs are 'UINT16' */
|
|
||||||
#endif
|
|
||||||
if (force_baseline && temp > 255L)
|
|
||||||
temp = 255L; /* limit to baseline range if requested */
|
|
||||||
(*qtblptr)[i] = (QUANT_VAL) temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_set_quality (compress_info_ptr cinfo, int quality, boolean force_baseline)
|
|
||||||
/* Set or change the 'quality' (quantization) setting. */
|
|
||||||
/* The 'quality' factor should be 0 (terrible) to 100 (very good). */
|
|
||||||
/* Quality 50 corresponds to the JPEG basic tables given above; */
|
|
||||||
/* quality 100 results in no quantization scaling at all. */
|
|
||||||
/* If force_baseline is TRUE, quantization table entries are limited */
|
|
||||||
/* to 0..255 for JPEG baseline compatibility; this is only an issue */
|
|
||||||
/* for quality settings below 24. */
|
|
||||||
{
|
|
||||||
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
|
|
||||||
if (quality <= 0) quality = 1;
|
|
||||||
if (quality > 100) quality = 100;
|
|
||||||
|
|
||||||
/* Convert quality rating to a percentage scaling of the basic tables.
|
|
||||||
* The basic table is used as-is (scaling 100) for a quality of 50.
|
|
||||||
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
|
|
||||||
* note that at Q=100 the scaling is 0, which will cause add_quant_table
|
|
||||||
* to make all the table entries 1 (hence, no quantization loss).
|
|
||||||
* Qualities 1..50 are converted to scaling percentage 5000/Q.
|
|
||||||
*/
|
|
||||||
if (quality < 50)
|
|
||||||
quality = 5000 / quality;
|
|
||||||
else
|
|
||||||
quality = 200 - quality*2;
|
|
||||||
|
|
||||||
/* Set up two quantization tables using the specified quality scaling */
|
|
||||||
add_quant_table(cinfo, 0, std_luminance_quant_tbl, quality, force_baseline);
|
|
||||||
add_quant_table(cinfo, 1, std_chrominance_quant_tbl, quality, force_baseline);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Default parameter setup for compression.
|
|
||||||
*
|
|
||||||
* User interfaces that don't choose to use this routine must do their
|
|
||||||
* own setup of all these parameters. Alternately, you can call this
|
|
||||||
* to establish defaults and then alter parameters selectively. This
|
|
||||||
* is the recommended approach since, if we add any new parameters,
|
|
||||||
* your code will still work (they'll be set to reasonable defaults).
|
|
||||||
*
|
|
||||||
* See above for the meaning of the 'quality' and 'force_baseline' parameters.
|
|
||||||
* Typically, the application's default quality setting will be passed to this
|
|
||||||
* routine. A later call on j_set_quality() can be used to change to a
|
|
||||||
* user-specified quality setting.
|
|
||||||
*
|
|
||||||
* This routine sets up for a color image; to output a grayscale image,
|
|
||||||
* do this first and call j_monochrome_default() afterwards.
|
|
||||||
* (The latter can be called within c_ui_method_selection, so the
|
|
||||||
* choice can depend on the input file header.)
|
|
||||||
* Note that if you want a JPEG colorspace other than GRAYSCALE or YCbCr,
|
|
||||||
* you should also change the component ID codes, and you should NOT emit
|
|
||||||
* a JFIF header (set write_JFIF_header = FALSE).
|
|
||||||
*
|
|
||||||
* CAUTION: if you want to compress multiple images per run, it's safest
|
|
||||||
* to call j_c_defaults before *each* call to jpeg_compress (and
|
|
||||||
* j_c_free_defaults afterwards). If this isn't practical, you'll have to
|
|
||||||
* be careful to reset any individual parameters that may change during
|
|
||||||
* the compression run. The main thing you need to worry about at present
|
|
||||||
* is that the sent_table boolean in each Huffman table must be reset to
|
|
||||||
* FALSE before each compression; otherwise, Huffman tables won't get
|
|
||||||
* emitted for the second and subsequent images.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline)
|
|
||||||
/* NB: the external methods must already be set up. */
|
|
||||||
{
|
|
||||||
short i;
|
|
||||||
jpeg_component_info * compptr;
|
|
||||||
|
|
||||||
/* Initialize pointers as needed to mark stuff unallocated. */
|
|
||||||
cinfo->comp_info = NULL;
|
|
||||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
|
||||||
cinfo->quant_tbl_ptrs[i] = NULL;
|
|
||||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
|
||||||
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
|
||||||
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cinfo->data_precision = 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 = (jpeg_component_info *)
|
|
||||||
(*cinfo->emethods->alloc_small) (4 * SIZEOF(jpeg_component_info));
|
|
||||||
/* Note: we allocate a 4-entry comp_info array so that user interface can
|
|
||||||
* easily change over to CMYK color space if desired.
|
|
||||||
*/
|
|
||||||
|
|
||||||
compptr = &cinfo->comp_info[0];
|
|
||||||
compptr->component_index = 0;
|
|
||||||
compptr->component_id = 1; /* JFIF specifies IDs 1,2,3 */
|
|
||||||
compptr->h_samp_factor = 2; /* default to 2x2 subsamples of chrominance */
|
|
||||||
compptr->v_samp_factor = 2;
|
|
||||||
compptr->quant_tbl_no = 0; /* use tables 0 for luminance */
|
|
||||||
compptr->dc_tbl_no = 0;
|
|
||||||
compptr->ac_tbl_no = 0;
|
|
||||||
|
|
||||||
compptr = &cinfo->comp_info[1];
|
|
||||||
compptr->component_index = 1;
|
|
||||||
compptr->component_id = 2;
|
|
||||||
compptr->h_samp_factor = 1;
|
|
||||||
compptr->v_samp_factor = 1;
|
|
||||||
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
|
|
||||||
compptr->dc_tbl_no = 1;
|
|
||||||
compptr->ac_tbl_no = 1;
|
|
||||||
|
|
||||||
compptr = &cinfo->comp_info[2];
|
|
||||||
compptr->component_index = 2;
|
|
||||||
compptr->component_id = 3;
|
|
||||||
compptr->h_samp_factor = 1;
|
|
||||||
compptr->v_samp_factor = 1;
|
|
||||||
compptr->quant_tbl_no = 1; /* use tables 1 for chrominance */
|
|
||||||
compptr->dc_tbl_no = 1;
|
|
||||||
compptr->ac_tbl_no = 1;
|
|
||||||
|
|
||||||
/* Set up two quantization tables using the specified quality scaling */
|
|
||||||
j_set_quality(cinfo, quality, force_baseline);
|
|
||||||
|
|
||||||
/* Set up two Huffman tables in case user interface wants Huffman coding */
|
|
||||||
std_huff_tables(cinfo);
|
|
||||||
|
|
||||||
/* Initialize default arithmetic coding conditioning */
|
|
||||||
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
|
||||||
cinfo->arith_dc_L[i] = 0;
|
|
||||||
cinfo->arith_dc_U[i] = 1;
|
|
||||||
cinfo->arith_ac_K[i] = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use Huffman coding, not arithmetic coding, by default */
|
|
||||||
cinfo->arith_code = FALSE;
|
|
||||||
|
|
||||||
/* Color images are interleaved by default */
|
|
||||||
cinfo->interleave = TRUE;
|
|
||||||
|
|
||||||
/* By default, don't do extra passes to optimize entropy coding */
|
|
||||||
cinfo->optimize_coding = FALSE;
|
|
||||||
|
|
||||||
/* By default, use the simpler non-cosited sampling alignment */
|
|
||||||
cinfo->CCIR601_sampling = FALSE;
|
|
||||||
|
|
||||||
/* No restart markers */
|
|
||||||
cinfo->restart_interval = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_monochrome_default (compress_info_ptr cinfo)
|
|
||||||
/* Change the j_c_defaults() values to emit a monochrome JPEG file. */
|
|
||||||
{
|
|
||||||
jpeg_component_info * compptr;
|
|
||||||
|
|
||||||
cinfo->jpeg_color_space = CS_GRAYSCALE;
|
|
||||||
cinfo->num_components = 1;
|
|
||||||
/* Set single component to 1x1 subsampling */
|
|
||||||
compptr = &cinfo->comp_info[0];
|
|
||||||
compptr->h_samp_factor = 1;
|
|
||||||
compptr->v_samp_factor = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This routine releases storage allocated by j_c_defaults.
|
|
||||||
* Note that freeing the method pointer structs and the compress_info_struct
|
|
||||||
* itself are the responsibility of the user interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_c_free_defaults (compress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
short i;
|
|
||||||
|
|
||||||
#define FREE(ptr) if ((ptr) != NULL) \
|
|
||||||
(*cinfo->emethods->free_small) ((void *) ptr)
|
|
||||||
|
|
||||||
FREE(cinfo->comp_info);
|
|
||||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
|
||||||
FREE(cinfo->quant_tbl_ptrs[i]);
|
|
||||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
|
||||||
FREE(cinfo->dc_huff_tbl_ptrs[i]);
|
|
||||||
FREE(cinfo->ac_huff_tbl_ptrs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
75
jcexpand.c
75
jcexpand.c
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
47
jchuff.h
Normal file
47
jchuff.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* jchuff.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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 declarations for Huffman entropy encoding routines
|
||||||
|
* that are shared between the sequential encoder (jchuff.c) and the
|
||||||
|
* progressive encoder (jcphuff.c). No other modules need to see these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The legal range of a DCT coefficient is
|
||||||
|
* -1024 .. +1023 for 8-bit data;
|
||||||
|
* -16384 .. +16383 for 12-bit data.
|
||||||
|
* Hence the magnitude should always fit in 10 or 14 bits respectively.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
#define MAX_COEF_BITS 10
|
||||||
|
#else
|
||||||
|
#define MAX_COEF_BITS 14
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Derived data constructed for each Huffman table */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int ehufco[256]; /* code for each symbol */
|
||||||
|
char ehufsi[256]; /* length of code for each symbol */
|
||||||
|
/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
|
||||||
|
} c_derived_tbl;
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#define jpeg_make_c_derived_tbl jMkCDerived
|
||||||
|
#define jpeg_gen_optimal_table jGenOptTbl
|
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||||
|
|
||||||
|
/* Expand a Huffman table definition into the derived format */
|
||||||
|
EXTERN(void) jpeg_make_c_derived_tbl
|
||||||
|
JPP((j_compress_ptr cinfo, boolean isDC, int tblno,
|
||||||
|
c_derived_tbl ** pdtbl));
|
||||||
|
|
||||||
|
/* Generate an optimal table definition given the specified counts */
|
||||||
|
EXTERN(void) jpeg_gen_optimal_table
|
||||||
|
JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
|
||||||
72
jcinit.c
Normal file
72
jcinit.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* jcinit.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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 initialization logic for the JPEG compressor.
|
||||||
|
* This routine is in charge of selecting the modules to be executed and
|
||||||
|
* making an initialization call to each one.
|
||||||
|
*
|
||||||
|
* Logically, this code belongs in jcmaster.c. It's split out because
|
||||||
|
* linking this routine implies linking the entire compression library.
|
||||||
|
* For a transcoding-only application, we want to be able to use jcmaster.c
|
||||||
|
* without linking in the whole library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Master selection of compression modules.
|
||||||
|
* This is done once at the start of processing an image. We determine
|
||||||
|
* which modules will be used and give them appropriate initialization calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_compress_master (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Initialize master control (includes parameter checking/processing) */
|
||||||
|
jinit_c_master_control(cinfo, FALSE /* full compression */);
|
||||||
|
|
||||||
|
/* Preprocessing */
|
||||||
|
if (! cinfo->raw_data_in) {
|
||||||
|
jinit_color_converter(cinfo);
|
||||||
|
jinit_downsampler(cinfo);
|
||||||
|
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
|
}
|
||||||
|
/* Forward DCT */
|
||||||
|
jinit_forward_dct(cinfo);
|
||||||
|
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
|
} else {
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
jinit_phuff_encoder(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
jinit_huff_encoder(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need a full-image coefficient buffer in any multi-pass mode. */
|
||||||
|
jinit_c_coef_controller(cinfo,
|
||||||
|
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
|
||||||
|
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
|
|
||||||
|
jinit_marker_writer(cinfo);
|
||||||
|
|
||||||
|
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||||
|
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Write the datastream header (SOI) immediately.
|
||||||
|
* Frame and scan headers are postponed till later.
|
||||||
|
* This lets application insert special markers after the SOI.
|
||||||
|
*/
|
||||||
|
(*cinfo->marker->write_file_header) (cinfo);
|
||||||
|
}
|
||||||
306
jcmain.c
306
jcmain.c
@@ -1,306 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 INCLUDES_ARE_ANSI
|
|
||||||
#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
|
|
||||||
|
|
||||||
#include "jversion.h" /* for version message */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PD version of getopt(3).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "egetopt.c"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This routine determines what format the input file is,
|
|
||||||
* and selects the appropriate input-reading module.
|
|
||||||
*
|
|
||||||
* To determine which family of input formats the file belongs to,
|
|
||||||
* we may look only at the first byte of the file, since C does not
|
|
||||||
* guarantee that more than one character can be pushed back with ungetc.
|
|
||||||
* Looking at additional bytes would require one of these approaches:
|
|
||||||
* 1) assume we can fseek() the input file (fails for piped input);
|
|
||||||
* 2) assume we can push back more than one character (works in
|
|
||||||
* some C implementations, but unportable);
|
|
||||||
* 3) provide our own buffering as is done in djpeg (breaks input readers
|
|
||||||
* that want to use stdio directly, such as the RLE library);
|
|
||||||
* or 4) don't put back the data, and modify the input_init methods to assume
|
|
||||||
* they start reading after the start of file (also breaks RLE library).
|
|
||||||
* #1 is attractive for MS-DOS but is untenable on Unix.
|
|
||||||
*
|
|
||||||
* The most portable solution for file types that can't be identified by their
|
|
||||||
* first byte is to make the user tell us what they are. This is also the
|
|
||||||
* only approach for "raw" file types that contain only arbitrary values.
|
|
||||||
* We presently apply this method for Targa files. Most of the time Targa
|
|
||||||
* files start with 0x00, so we recognize that case. Potentially, however,
|
|
||||||
* a Targa file could start with any byte value (byte 0 is the length of the
|
|
||||||
* seldom-used ID field), so we accept a -T switch to force Targa input mode.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static boolean is_targa; /* records user -T switch */
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
|
||||||
select_file_type (compress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (is_targa) {
|
|
||||||
#ifdef TARGA_SUPPORTED
|
|
||||||
jselrtarga(cinfo);
|
|
||||||
#else
|
|
||||||
ERREXIT(cinfo->emethods, "Targa support was not compiled");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((c = getc(cinfo->input_file)) == EOF)
|
|
||||||
ERREXIT(cinfo->emethods, "Empty input file");
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
#ifdef GIF_SUPPORTED
|
|
||||||
case 'G':
|
|
||||||
jselrgif(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef PPM_SUPPORTED
|
|
||||||
case 'P':
|
|
||||||
jselrppm(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef RLE_SUPPORTED
|
|
||||||
case 'R':
|
|
||||||
jselrrle(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef TARGA_SUPPORTED
|
|
||||||
case 0x00:
|
|
||||||
jselrtarga(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
#ifdef TARGA_SUPPORTED
|
|
||||||
ERREXIT(cinfo->emethods, "Unrecognized input file format --- did you forget -T ?");
|
|
||||||
#else
|
|
||||||
ERREXIT(cinfo->emethods, "Unrecognized input file format");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ungetc(c, cinfo->input_file) == EOF)
|
|
||||||
ERREXIT(cinfo->emethods, "ungetc failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This routine gets control after the input file header has been read.
|
|
||||||
* It must determine what output JPEG file format is to be written,
|
|
||||||
* and make any other compression parameter changes that are desirable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
METHODDEF void
|
|
||||||
c_ui_method_selection (compress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
/* If the input is gray scale, generate a monochrome JPEG file. */
|
|
||||||
if (cinfo->in_color_space == CS_GRAYSCALE)
|
|
||||||
j_monochrome_default(cinfo);
|
|
||||||
/* For now, always select JFIF output format. */
|
|
||||||
#ifdef JFIF_SUPPORTED
|
|
||||||
jselwjfif(cinfo);
|
|
||||||
#else
|
|
||||||
You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
|
||||||
usage (char * progname)
|
|
||||||
/* complain about bad command line */
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s ", progname);
|
|
||||||
fprintf(stderr, "[-Q quality 0..100] [-o] [-T] [-I] [-a] [-d]");
|
|
||||||
#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 JPEG parameters. */
|
|
||||||
j_c_defaults(&cinfo, 75, FALSE); /* default quality level = 75 */
|
|
||||||
is_targa = FALSE;
|
|
||||||
|
|
||||||
/* Scan command line options, adjust parameters */
|
|
||||||
|
|
||||||
while ((c = egetopt(argc, argv, "IQ:Taod")) != EOF)
|
|
||||||
switch (c) {
|
|
||||||
case 'I': /* Create noninterleaved file. */
|
|
||||||
#ifdef MULTISCAN_FILES_SUPPORTED
|
|
||||||
cinfo.interleave = FALSE;
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
|
|
||||||
argv[0]);
|
|
||||||
exit(2);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 'Q': /* Quality factor. */
|
|
||||||
{ int val;
|
|
||||||
if (optarg == NULL)
|
|
||||||
usage(argv[0]);
|
|
||||||
if (sscanf(optarg, "%d", &val) != 1)
|
|
||||||
usage(argv[0]);
|
|
||||||
/* Note: for now, we make force_baseline FALSE.
|
|
||||||
* This means non-baseline JPEG files can be created with low Q values.
|
|
||||||
* To ensure only baseline files are generated, pass TRUE instead.
|
|
||||||
*/
|
|
||||||
j_set_quality(&cinfo, val, FALSE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'T': /* Input file is Targa format. */
|
|
||||||
is_targa = TRUE;
|
|
||||||
break;
|
|
||||||
case 'a': /* Use arithmetic coding. */
|
|
||||||
#ifdef ARITH_CODING_SUPPORTED
|
|
||||||
cinfo.arith_code = TRUE;
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
|
||||||
argv[0]);
|
|
||||||
exit(2);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 'o': /* Enable entropy parm optimization. */
|
|
||||||
#ifdef ENTROPY_OPT_SUPPORTED
|
|
||||||
cinfo.optimize_coding = TRUE;
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
|
||||||
argv[0]);
|
|
||||||
exit(2);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 'd': /* Debugging. */
|
|
||||||
e_methods.trace_level++;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
usage(argv[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If -d appeared, print version identification */
|
|
||||||
if (e_methods.trace_level > 0)
|
|
||||||
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
|
|
||||||
JVERSION, JCOPYRIGHT);
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
cinfo.input_file = stdin; /* default input file */
|
|
||||||
cinfo.output_file = stdout; /* always the output file */
|
|
||||||
|
|
||||||
if (optind < argc-1) {
|
|
||||||
fprintf(stderr, "%s: only one input file\n", argv[0]);
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
if (optind < argc) {
|
|
||||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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_c_free_defaults(&cinfo);
|
|
||||||
#ifdef MEM_STATS
|
|
||||||
if (e_methods.trace_level > 0) /* Optional memory-usage statistics */
|
|
||||||
j_mem_stats();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* All done. */
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
293
jcmainct.c
Normal file
293
jcmainct.c
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
* jcmainct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains the main buffer controller for compression.
|
||||||
|
* The main buffer lies between the pre-processor and the JPEG
|
||||||
|
* compressor proper; it holds downsampled data in the JPEG colorspace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: currently, there is no operating mode in which a full-image buffer
|
||||||
|
* is needed at this step. If there were, that mode could not be used with
|
||||||
|
* "raw data" input, since this module is bypassed in that case. However,
|
||||||
|
* we've left the code here for possible use in special applications.
|
||||||
|
*/
|
||||||
|
#undef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_c_main_controller pub; /* public fields */
|
||||||
|
|
||||||
|
JDIMENSION cur_iMCU_row; /* number of current iMCU row */
|
||||||
|
JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
|
||||||
|
boolean suspended; /* remember if we suspended output */
|
||||||
|
J_BUF_MODE pass_mode; /* current operating mode */
|
||||||
|
|
||||||
|
/* If using just a strip buffer, this points to the entire set of buffers
|
||||||
|
* (we allocate one for each component). In the full-image case, this
|
||||||
|
* points to the currently accessible strips of the virtual arrays.
|
||||||
|
*/
|
||||||
|
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
/* If using full-image storage, this array holds pointers to virtual-array
|
||||||
|
* control blocks for each component. Unused if not full-image storage.
|
||||||
|
*/
|
||||||
|
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
|
||||||
|
#endif
|
||||||
|
} my_main_controller;
|
||||||
|
|
||||||
|
typedef my_main_controller * my_main_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(void) process_data_simple_main
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
|
||||||
|
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
METHODDEF(void) process_data_buffer_main
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
|
||||||
|
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
/* Do nothing in raw-data mode. */
|
||||||
|
if (cinfo->raw_data_in)
|
||||||
|
return;
|
||||||
|
|
||||||
|
main->cur_iMCU_row = 0; /* initialize counters */
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
main->suspended = FALSE;
|
||||||
|
main->pass_mode = pass_mode; /* save mode for use by process_data */
|
||||||
|
|
||||||
|
switch (pass_mode) {
|
||||||
|
case JBUF_PASS_THRU:
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
if (main->whole_image[0] != NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
#endif
|
||||||
|
main->pub.process_data = process_data_simple_main;
|
||||||
|
break;
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
case JBUF_SAVE_SOURCE:
|
||||||
|
case JBUF_CRANK_DEST:
|
||||||
|
case JBUF_SAVE_AND_PASS:
|
||||||
|
if (main->whole_image[0] == NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
main->pub.process_data = process_data_buffer_main;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* This routine handles the simple pass-through mode,
|
||||||
|
* where we have only a strip buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
process_data_simple_main (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||||
|
JDIMENSION in_rows_avail)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||||
|
/* Read input data if we haven't filled the main buffer yet */
|
||||||
|
if (main->rowgroup_ctr < DCTSIZE)
|
||||||
|
(*cinfo->prep->pre_process_data) (cinfo,
|
||||||
|
input_buf, in_row_ctr, in_rows_avail,
|
||||||
|
main->buffer, &main->rowgroup_ctr,
|
||||||
|
(JDIMENSION) DCTSIZE);
|
||||||
|
|
||||||
|
/* If we don't have a full iMCU row buffered, return to application for
|
||||||
|
* more data. Note that preprocessor will always pad to fill the iMCU row
|
||||||
|
* at the bottom of the image.
|
||||||
|
*/
|
||||||
|
if (main->rowgroup_ctr != DCTSIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send the completed row to the compressor */
|
||||||
|
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
|
||||||
|
/* If compressor did not consume the whole row, then we must need to
|
||||||
|
* suspend processing and return to the application. In this situation
|
||||||
|
* we pretend we didn't yet consume the last input row; otherwise, if
|
||||||
|
* it happened to be the last row of the image, the application would
|
||||||
|
* think we were done.
|
||||||
|
*/
|
||||||
|
if (! main->suspended) {
|
||||||
|
(*in_row_ctr)--;
|
||||||
|
main->suspended = TRUE;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* We did finish the row. Undo our little suspension hack if a previous
|
||||||
|
* call suspended; then mark the main buffer empty.
|
||||||
|
*/
|
||||||
|
if (main->suspended) {
|
||||||
|
(*in_row_ctr)++;
|
||||||
|
main->suspended = FALSE;
|
||||||
|
}
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
main->cur_iMCU_row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* This routine handles all of the modes that use a full-size buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
process_data_buffer_main (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||||
|
JDIMENSION in_rows_avail)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
|
||||||
|
|
||||||
|
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||||
|
/* Realign the virtual buffers if at the start of an iMCU row. */
|
||||||
|
if (main->rowgroup_ctr == 0) {
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
|
||||||
|
((j_common_ptr) cinfo, main->whole_image[ci],
|
||||||
|
main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE),
|
||||||
|
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing);
|
||||||
|
}
|
||||||
|
/* In a read pass, pretend we just read some source data. */
|
||||||
|
if (! writing) {
|
||||||
|
*in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
|
||||||
|
main->rowgroup_ctr = DCTSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a write pass, read input data until the current iMCU row is full. */
|
||||||
|
/* Note: preprocessor will pad if necessary to fill the last iMCU row. */
|
||||||
|
if (writing) {
|
||||||
|
(*cinfo->prep->pre_process_data) (cinfo,
|
||||||
|
input_buf, in_row_ctr, in_rows_avail,
|
||||||
|
main->buffer, &main->rowgroup_ctr,
|
||||||
|
(JDIMENSION) DCTSIZE);
|
||||||
|
/* Return to application if we need more data to fill the iMCU row. */
|
||||||
|
if (main->rowgroup_ctr < DCTSIZE)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit data, unless this is a sink-only pass. */
|
||||||
|
if (main->pass_mode != JBUF_SAVE_SOURCE) {
|
||||||
|
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
|
||||||
|
/* If compressor did not consume the whole row, then we must need to
|
||||||
|
* suspend processing and return to the application. In this situation
|
||||||
|
* we pretend we didn't yet consume the last input row; otherwise, if
|
||||||
|
* it happened to be the last row of the image, the application would
|
||||||
|
* think we were done.
|
||||||
|
*/
|
||||||
|
if (! main->suspended) {
|
||||||
|
(*in_row_ctr)--;
|
||||||
|
main->suspended = TRUE;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* We did finish the row. Undo our little suspension hack if a previous
|
||||||
|
* call suspended; then mark the main buffer empty.
|
||||||
|
*/
|
||||||
|
if (main->suspended) {
|
||||||
|
(*in_row_ctr)++;
|
||||||
|
main->suspended = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If get here, we are done with this iMCU row. Mark buffer empty. */
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
main->cur_iMCU_row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FULL_MAIN_BUFFER_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize main buffer controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_main_ptr main;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
main = (my_main_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_main_controller));
|
||||||
|
cinfo->main = (struct jpeg_c_main_controller *) main;
|
||||||
|
main->pub.start_pass = start_pass_main;
|
||||||
|
|
||||||
|
/* We don't need to create a buffer in raw-data mode. */
|
||||||
|
if (cinfo->raw_data_in)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Create the buffer. It holds downsampled data, so each component
|
||||||
|
* may be of a different size.
|
||||||
|
*/
|
||||||
|
if (need_full_buffer) {
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
/* Allocate a full-image virtual array for each component */
|
||||||
|
/* Note we pad the bottom to a multiple of the iMCU height */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||||
|
compptr->width_in_blocks * DCTSIZE,
|
||||||
|
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||||
|
(long) compptr->v_samp_factor) * DCTSIZE,
|
||||||
|
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef FULL_MAIN_BUFFER_SUPPORTED
|
||||||
|
main->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||||
|
#endif
|
||||||
|
/* Allocate a strip buffer for each component */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
compptr->width_in_blocks * DCTSIZE,
|
||||||
|
(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
664
jcmarker.c
Normal file
664
jcmarker.c
Normal file
@@ -0,0 +1,664 @@
|
|||||||
|
/*
|
||||||
|
* jcmarker.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains routines to write JPEG datastream markers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum { /* JPEG marker codes */
|
||||||
|
M_SOF0 = 0xc0,
|
||||||
|
M_SOF1 = 0xc1,
|
||||||
|
M_SOF2 = 0xc2,
|
||||||
|
M_SOF3 = 0xc3,
|
||||||
|
|
||||||
|
M_SOF5 = 0xc5,
|
||||||
|
M_SOF6 = 0xc6,
|
||||||
|
M_SOF7 = 0xc7,
|
||||||
|
|
||||||
|
M_JPG = 0xc8,
|
||||||
|
M_SOF9 = 0xc9,
|
||||||
|
M_SOF10 = 0xca,
|
||||||
|
M_SOF11 = 0xcb,
|
||||||
|
|
||||||
|
M_SOF13 = 0xcd,
|
||||||
|
M_SOF14 = 0xce,
|
||||||
|
M_SOF15 = 0xcf,
|
||||||
|
|
||||||
|
M_DHT = 0xc4,
|
||||||
|
|
||||||
|
M_DAC = 0xcc,
|
||||||
|
|
||||||
|
M_RST0 = 0xd0,
|
||||||
|
M_RST1 = 0xd1,
|
||||||
|
M_RST2 = 0xd2,
|
||||||
|
M_RST3 = 0xd3,
|
||||||
|
M_RST4 = 0xd4,
|
||||||
|
M_RST5 = 0xd5,
|
||||||
|
M_RST6 = 0xd6,
|
||||||
|
M_RST7 = 0xd7,
|
||||||
|
|
||||||
|
M_SOI = 0xd8,
|
||||||
|
M_EOI = 0xd9,
|
||||||
|
M_SOS = 0xda,
|
||||||
|
M_DQT = 0xdb,
|
||||||
|
M_DNL = 0xdc,
|
||||||
|
M_DRI = 0xdd,
|
||||||
|
M_DHP = 0xde,
|
||||||
|
M_EXP = 0xdf,
|
||||||
|
|
||||||
|
M_APP0 = 0xe0,
|
||||||
|
M_APP1 = 0xe1,
|
||||||
|
M_APP2 = 0xe2,
|
||||||
|
M_APP3 = 0xe3,
|
||||||
|
M_APP4 = 0xe4,
|
||||||
|
M_APP5 = 0xe5,
|
||||||
|
M_APP6 = 0xe6,
|
||||||
|
M_APP7 = 0xe7,
|
||||||
|
M_APP8 = 0xe8,
|
||||||
|
M_APP9 = 0xe9,
|
||||||
|
M_APP10 = 0xea,
|
||||||
|
M_APP11 = 0xeb,
|
||||||
|
M_APP12 = 0xec,
|
||||||
|
M_APP13 = 0xed,
|
||||||
|
M_APP14 = 0xee,
|
||||||
|
M_APP15 = 0xef,
|
||||||
|
|
||||||
|
M_JPG0 = 0xf0,
|
||||||
|
M_JPG13 = 0xfd,
|
||||||
|
M_COM = 0xfe,
|
||||||
|
|
||||||
|
M_TEM = 0x01,
|
||||||
|
|
||||||
|
M_ERROR = 0x100
|
||||||
|
} JPEG_MARKER;
|
||||||
|
|
||||||
|
|
||||||
|
/* Private state */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_marker_writer pub; /* public fields */
|
||||||
|
|
||||||
|
unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
|
||||||
|
} my_marker_writer;
|
||||||
|
|
||||||
|
typedef my_marker_writer * my_marker_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic output routines.
|
||||||
|
*
|
||||||
|
* Note that we do not support suspension while writing a marker.
|
||||||
|
* Therefore, an application using suspension must ensure that there is
|
||||||
|
* enough buffer space for the initial markers (typ. 600-700 bytes) before
|
||||||
|
* calling jpeg_start_compress, and enough space to write the trailing EOI
|
||||||
|
* (a few bytes) before calling jpeg_finish_compress. Multipass compression
|
||||||
|
* modes are not supported at all with suspension, so those two are the only
|
||||||
|
* points where markers will be written.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_byte (j_compress_ptr cinfo, int val)
|
||||||
|
/* Emit a byte */
|
||||||
|
{
|
||||||
|
struct jpeg_destination_mgr * dest = cinfo->dest;
|
||||||
|
|
||||||
|
*(dest->next_output_byte)++ = (JOCTET) val;
|
||||||
|
if (--dest->free_in_buffer == 0) {
|
||||||
|
if (! (*dest->empty_output_buffer) (cinfo))
|
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
|
||||||
|
/* Emit a marker code */
|
||||||
|
{
|
||||||
|
emit_byte(cinfo, 0xFF);
|
||||||
|
emit_byte(cinfo, (int) mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_2bytes (j_compress_ptr cinfo, int value)
|
||||||
|
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
|
||||||
|
{
|
||||||
|
emit_byte(cinfo, (value >> 8) & 0xFF);
|
||||||
|
emit_byte(cinfo, value & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines to write specific marker types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(int)
|
||||||
|
emit_dqt (j_compress_ptr cinfo, int index)
|
||||||
|
/* Emit a DQT marker */
|
||||||
|
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
|
||||||
|
{
|
||||||
|
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
|
||||||
|
int prec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (qtbl == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
|
||||||
|
|
||||||
|
prec = 0;
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
if (qtbl->quantval[i] > 255)
|
||||||
|
prec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! qtbl->sent_table) {
|
||||||
|
emit_marker(cinfo, M_DQT);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
|
||||||
|
|
||||||
|
emit_byte(cinfo, index + (prec<<4));
|
||||||
|
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
/* The table entries must be emitted in zigzag order. */
|
||||||
|
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
|
||||||
|
if (prec)
|
||||||
|
emit_byte(cinfo, (int) (qval >> 8));
|
||||||
|
emit_byte(cinfo, (int) (qval & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
qtbl->sent_table = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
|
||||||
|
/* Emit a DHT marker */
|
||||||
|
{
|
||||||
|
JHUFF_TBL * htbl;
|
||||||
|
int length, i;
|
||||||
|
|
||||||
|
if (is_ac) {
|
||||||
|
htbl = cinfo->ac_huff_tbl_ptrs[index];
|
||||||
|
index += 0x10; /* output index has AC bit set */
|
||||||
|
} else {
|
||||||
|
htbl = cinfo->dc_huff_tbl_ptrs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htbl == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
|
||||||
|
|
||||||
|
if (! htbl->sent_table) {
|
||||||
|
emit_marker(cinfo, M_DHT);
|
||||||
|
|
||||||
|
length = 0;
|
||||||
|
for (i = 1; i <= 16; i++)
|
||||||
|
length += htbl->bits[i];
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, length + 2 + 1 + 16);
|
||||||
|
emit_byte(cinfo, index);
|
||||||
|
|
||||||
|
for (i = 1; i <= 16; i++)
|
||||||
|
emit_byte(cinfo, htbl->bits[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
emit_byte(cinfo, htbl->huffval[i]);
|
||||||
|
|
||||||
|
htbl->sent_table = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_dac (j_compress_ptr cinfo)
|
||||||
|
/* Emit a DAC marker */
|
||||||
|
/* Since the useful info is so small, we want to emit all the tables in */
|
||||||
|
/* one DAC marker. Therefore this routine does its own scan of the table. */
|
||||||
|
{
|
||||||
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
|
char dc_in_use[NUM_ARITH_TBLS];
|
||||||
|
char ac_in_use[NUM_ARITH_TBLS];
|
||||||
|
int length, i;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++)
|
||||||
|
dc_in_use[i] = ac_in_use[i] = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||||
|
compptr = cinfo->cur_comp_info[i];
|
||||||
|
dc_in_use[compptr->dc_tbl_no] = 1;
|
||||||
|
ac_in_use[compptr->ac_tbl_no] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = 0;
|
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++)
|
||||||
|
length += dc_in_use[i] + ac_in_use[i];
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_DAC);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, length*2 + 2);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
||||||
|
if (dc_in_use[i]) {
|
||||||
|
emit_byte(cinfo, i);
|
||||||
|
emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
|
||||||
|
}
|
||||||
|
if (ac_in_use[i]) {
|
||||||
|
emit_byte(cinfo, i + 0x10);
|
||||||
|
emit_byte(cinfo, cinfo->arith_ac_K[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* C_ARITH_CODING_SUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_dri (j_compress_ptr cinfo)
|
||||||
|
/* Emit a DRI marker */
|
||||||
|
{
|
||||||
|
emit_marker(cinfo, M_DRI);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, 4); /* fixed length */
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, (int) cinfo->restart_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
|
||||||
|
/* Emit a SOF marker */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
emit_marker(cinfo, code);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
|
||||||
|
|
||||||
|
/* Make sure image isn't bigger than SOF field can handle */
|
||||||
|
if ((long) cinfo->image_height > 65535L ||
|
||||||
|
(long) cinfo->image_width > 65535L)
|
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
|
||||||
|
|
||||||
|
emit_byte(cinfo, cinfo->data_precision);
|
||||||
|
emit_2bytes(cinfo, (int) cinfo->image_height);
|
||||||
|
emit_2bytes(cinfo, (int) cinfo->image_width);
|
||||||
|
|
||||||
|
emit_byte(cinfo, cinfo->num_components);
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
emit_byte(cinfo, compptr->component_id);
|
||||||
|
emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
|
||||||
|
emit_byte(cinfo, compptr->quant_tbl_no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_sos (j_compress_ptr cinfo)
|
||||||
|
/* Emit a SOS marker */
|
||||||
|
{
|
||||||
|
int i, td, ta;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_SOS);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
|
||||||
|
|
||||||
|
emit_byte(cinfo, cinfo->comps_in_scan);
|
||||||
|
|
||||||
|
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||||
|
compptr = cinfo->cur_comp_info[i];
|
||||||
|
emit_byte(cinfo, compptr->component_id);
|
||||||
|
td = compptr->dc_tbl_no;
|
||||||
|
ta = compptr->ac_tbl_no;
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
/* Progressive mode: only DC or only AC tables are used in one scan;
|
||||||
|
* furthermore, Huffman coding of DC refinement uses no table at all.
|
||||||
|
* We emit 0 for unused field(s); this is recommended by the P&M text
|
||||||
|
* but does not seem to be specified in the standard.
|
||||||
|
*/
|
||||||
|
if (cinfo->Ss == 0) {
|
||||||
|
ta = 0; /* DC scan */
|
||||||
|
if (cinfo->Ah != 0 && !cinfo->arith_code)
|
||||||
|
td = 0; /* no DC table either */
|
||||||
|
} else {
|
||||||
|
td = 0; /* AC scan */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit_byte(cinfo, (td << 4) + ta);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_byte(cinfo, cinfo->Ss);
|
||||||
|
emit_byte(cinfo, cinfo->Se);
|
||||||
|
emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_jfif_app0 (j_compress_ptr cinfo)
|
||||||
|
/* Emit a JFIF-compliant APP0 marker */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Length of APP0 block (2 bytes)
|
||||||
|
* Block ID (4 bytes - ASCII "JFIF")
|
||||||
|
* Zero byte (1 byte to terminate the ID string)
|
||||||
|
* Version Major, Minor (2 bytes - major first)
|
||||||
|
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
|
||||||
|
* Xdpu (2 bytes - dots per unit horizontal)
|
||||||
|
* Ydpu (2 bytes - dots per unit vertical)
|
||||||
|
* Thumbnail X size (1 byte)
|
||||||
|
* Thumbnail Y size (1 byte)
|
||||||
|
*/
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_APP0);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
|
||||||
|
|
||||||
|
emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
|
||||||
|
emit_byte(cinfo, 0x46);
|
||||||
|
emit_byte(cinfo, 0x49);
|
||||||
|
emit_byte(cinfo, 0x46);
|
||||||
|
emit_byte(cinfo, 0);
|
||||||
|
emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
|
||||||
|
emit_byte(cinfo, cinfo->JFIF_minor_version);
|
||||||
|
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
|
||||||
|
emit_2bytes(cinfo, (int) cinfo->X_density);
|
||||||
|
emit_2bytes(cinfo, (int) cinfo->Y_density);
|
||||||
|
emit_byte(cinfo, 0); /* No thumbnail image */
|
||||||
|
emit_byte(cinfo, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_adobe_app14 (j_compress_ptr cinfo)
|
||||||
|
/* Emit an Adobe APP14 marker */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Length of APP14 block (2 bytes)
|
||||||
|
* Block ID (5 bytes - ASCII "Adobe")
|
||||||
|
* Version Number (2 bytes - currently 100)
|
||||||
|
* Flags0 (2 bytes - currently 0)
|
||||||
|
* Flags1 (2 bytes - currently 0)
|
||||||
|
* Color transform (1 byte)
|
||||||
|
*
|
||||||
|
* Although Adobe TN 5116 mentions Version = 101, all the Adobe files
|
||||||
|
* now in circulation seem to use Version = 100, so that's what we write.
|
||||||
|
*
|
||||||
|
* We write the color transform byte as 1 if the JPEG color space is
|
||||||
|
* YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
|
||||||
|
* whether the encoder performed a transformation, which is pretty useless.
|
||||||
|
*/
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_APP14);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
|
||||||
|
|
||||||
|
emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
|
||||||
|
emit_byte(cinfo, 0x64);
|
||||||
|
emit_byte(cinfo, 0x6F);
|
||||||
|
emit_byte(cinfo, 0x62);
|
||||||
|
emit_byte(cinfo, 0x65);
|
||||||
|
emit_2bytes(cinfo, 100); /* Version */
|
||||||
|
emit_2bytes(cinfo, 0); /* Flags0 */
|
||||||
|
emit_2bytes(cinfo, 0); /* Flags1 */
|
||||||
|
switch (cinfo->jpeg_color_space) {
|
||||||
|
case JCS_YCbCr:
|
||||||
|
emit_byte(cinfo, 1); /* Color transform = 1 */
|
||||||
|
break;
|
||||||
|
case JCS_YCCK:
|
||||||
|
emit_byte(cinfo, 2); /* Color transform = 2 */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
emit_byte(cinfo, 0); /* Color transform = 0 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These routines allow writing an arbitrary marker with parameters.
|
||||||
|
* The only intended use is to emit COM or APPn markers after calling
|
||||||
|
* write_file_header and before calling write_frame_header.
|
||||||
|
* Other uses are not guaranteed to produce desirable results.
|
||||||
|
* Counting the parameter bytes properly is the caller's responsibility.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
|
||||||
|
/* Emit an arbitrary marker header */
|
||||||
|
{
|
||||||
|
if (datalen > (unsigned int) 65533) /* safety check */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_LENGTH);
|
||||||
|
|
||||||
|
emit_marker(cinfo, (JPEG_MARKER) marker);
|
||||||
|
|
||||||
|
emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
|
||||||
|
}
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_marker_byte (j_compress_ptr cinfo, int val)
|
||||||
|
/* Emit one byte of marker parameters following write_marker_header */
|
||||||
|
{
|
||||||
|
emit_byte(cinfo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write datastream header.
|
||||||
|
* This consists of an SOI and optional APPn markers.
|
||||||
|
* We recommend use of the JFIF marker, but not the Adobe marker,
|
||||||
|
* when using YCbCr or grayscale data. The JFIF marker should NOT
|
||||||
|
* be used for any other JPEG colorspace. The Adobe marker is helpful
|
||||||
|
* to distinguish RGB, CMYK, and YCCK colorspaces.
|
||||||
|
* Note that an application can write additional header markers after
|
||||||
|
* jpeg_start_compress returns.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_file_header (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_SOI); /* first the SOI */
|
||||||
|
|
||||||
|
/* SOI is defined to reset restart interval to 0 */
|
||||||
|
marker->last_restart_interval = 0;
|
||||||
|
|
||||||
|
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
|
||||||
|
emit_jfif_app0(cinfo);
|
||||||
|
if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
|
||||||
|
emit_adobe_app14(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write frame header.
|
||||||
|
* This consists of DQT and SOFn markers.
|
||||||
|
* Note that we do not emit the SOF until we have emitted the DQT(s).
|
||||||
|
* This avoids compatibility problems with incorrect implementations that
|
||||||
|
* try to error-check the quant table numbers as soon as they see the SOF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_frame_header (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int ci, prec;
|
||||||
|
boolean is_baseline;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Emit DQT for each quantization table.
|
||||||
|
* Note that emit_dqt() suppresses any duplicate tables.
|
||||||
|
*/
|
||||||
|
prec = 0;
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
|
||||||
|
}
|
||||||
|
/* now prec is nonzero iff there are any 16-bit quant tables. */
|
||||||
|
|
||||||
|
/* Check for a non-baseline specification.
|
||||||
|
* Note we assume that Huffman table numbers won't be changed later.
|
||||||
|
*/
|
||||||
|
if (cinfo->arith_code || cinfo->progressive_mode ||
|
||||||
|
cinfo->data_precision != 8) {
|
||||||
|
is_baseline = FALSE;
|
||||||
|
} else {
|
||||||
|
is_baseline = TRUE;
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
|
||||||
|
is_baseline = FALSE;
|
||||||
|
}
|
||||||
|
if (prec && is_baseline) {
|
||||||
|
is_baseline = FALSE;
|
||||||
|
/* If it's baseline except for quantizer size, warn the user */
|
||||||
|
TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit the proper SOF marker */
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
|
||||||
|
} else {
|
||||||
|
if (cinfo->progressive_mode)
|
||||||
|
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
|
||||||
|
else if (is_baseline)
|
||||||
|
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
|
||||||
|
else
|
||||||
|
emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write scan header.
|
||||||
|
* This consists of DHT or DAC markers, optional DRI, and SOS.
|
||||||
|
* Compressed data will be written following the SOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_scan_header (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
|
||||||
|
int i;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
/* Emit arith conditioning info. We may have some duplication
|
||||||
|
* if the file has multiple scans, but it's so small it's hardly
|
||||||
|
* worth worrying about.
|
||||||
|
*/
|
||||||
|
emit_dac(cinfo);
|
||||||
|
} else {
|
||||||
|
/* Emit Huffman tables.
|
||||||
|
* Note that emit_dht() suppresses any duplicate tables.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||||
|
compptr = cinfo->cur_comp_info[i];
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
/* Progressive mode: only DC or only AC tables are used in one scan */
|
||||||
|
if (cinfo->Ss == 0) {
|
||||||
|
if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
|
||||||
|
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
|
||||||
|
} else {
|
||||||
|
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Sequential mode: need both DC and AC tables */
|
||||||
|
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
|
||||||
|
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit DRI if required --- note that DRI value could change for each scan.
|
||||||
|
* We avoid wasting space with unnecessary DRIs, however.
|
||||||
|
*/
|
||||||
|
if (cinfo->restart_interval != marker->last_restart_interval) {
|
||||||
|
emit_dri(cinfo);
|
||||||
|
marker->last_restart_interval = cinfo->restart_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_sos(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write datastream trailer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_file_trailer (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
emit_marker(cinfo, M_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write an abbreviated table-specification datastream.
|
||||||
|
* This consists of SOI, DQT and DHT tables, and EOI.
|
||||||
|
* Any table that is defined and not marked sent_table = TRUE will be
|
||||||
|
* emitted. Note that all tables will be marked sent_table = TRUE at exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
write_tables_only (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_SOI);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||||
|
if (cinfo->quant_tbl_ptrs[i] != NULL)
|
||||||
|
(void) emit_dqt(cinfo, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! cinfo->arith_code) {
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
|
||||||
|
emit_dht(cinfo, i, FALSE);
|
||||||
|
if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
|
||||||
|
emit_dht(cinfo, i, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_marker(cinfo, M_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the marker writer module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_marker_writer (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_marker_ptr marker;
|
||||||
|
|
||||||
|
/* Create the subobject */
|
||||||
|
marker = (my_marker_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_marker_writer));
|
||||||
|
cinfo->marker = (struct jpeg_marker_writer *) marker;
|
||||||
|
/* Initialize method pointers */
|
||||||
|
marker->pub.write_file_header = write_file_header;
|
||||||
|
marker->pub.write_frame_header = write_frame_header;
|
||||||
|
marker->pub.write_scan_header = write_scan_header;
|
||||||
|
marker->pub.write_file_trailer = write_file_trailer;
|
||||||
|
marker->pub.write_tables_only = write_tables_only;
|
||||||
|
marker->pub.write_marker_header = write_marker_header;
|
||||||
|
marker->pub.write_marker_byte = write_marker_byte;
|
||||||
|
/* Initialize private state */
|
||||||
|
marker->last_restart_interval = 0;
|
||||||
|
}
|
||||||
643
jcmaster.c
643
jcmaster.c
@@ -1,127 +1,590 @@
|
|||||||
/*
|
/*
|
||||||
* jcmaster.c
|
* jcmaster.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* This file is part of the Independent JPEG Group's software.
|
* This file is part of the Independent JPEG Group's software.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains the main control for the JPEG compressor.
|
* This file contains master control logic for the JPEG compressor.
|
||||||
* The system-dependent (user interface) code should call jpeg_compress()
|
* These routines are concerned with parameter validation, initial setup,
|
||||||
* after doing appropriate setup of the compress_info_struct parameter.
|
* and inter-pass control (determining the number of passes and the work
|
||||||
|
* to be done in each pass).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
METHODDEF void
|
/* Private state */
|
||||||
c_per_scan_method_selection (compress_info_ptr cinfo)
|
|
||||||
/* Central point for per-scan method selection */
|
typedef enum {
|
||||||
|
main_pass, /* input data, also do first output step */
|
||||||
|
huff_opt_pass, /* Huffman code optimization pass */
|
||||||
|
output_pass /* data output pass */
|
||||||
|
} c_pass_type;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_comp_master pub; /* public fields */
|
||||||
|
|
||||||
|
c_pass_type pass_type; /* the type of the current pass */
|
||||||
|
|
||||||
|
int pass_number; /* # of passes completed */
|
||||||
|
int total_passes; /* total # of passes needed */
|
||||||
|
|
||||||
|
int scan_number; /* current index in scan_info[] */
|
||||||
|
} my_comp_master;
|
||||||
|
|
||||||
|
typedef my_comp_master * my_master_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support routines that do various essential calculations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
initial_setup (j_compress_ptr cinfo)
|
||||||
|
/* Do computations that are needed before master selection phase */
|
||||||
{
|
{
|
||||||
/* Edge expansion */
|
int ci;
|
||||||
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;
|
jpeg_component_info *compptr;
|
||||||
|
long samplesperrow;
|
||||||
|
JDIMENSION jd_samplesperrow;
|
||||||
|
|
||||||
|
/* Sanity check on image dimensions */
|
||||||
|
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|
||||||
|
|| cinfo->num_components <= 0 || cinfo->input_components <= 0)
|
||||||
|
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
|
||||||
|
|
||||||
|
/* Make sure image isn't bigger than I can handle */
|
||||||
|
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
|
||||||
|
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
|
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
|
||||||
|
|
||||||
|
/* Width of an input scanline must be representable as JDIMENSION. */
|
||||||
|
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
|
||||||
|
jd_samplesperrow = (JDIMENSION) samplesperrow;
|
||||||
|
if ((long) jd_samplesperrow != samplesperrow)
|
||||||
|
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
||||||
|
|
||||||
|
/* For now, precision must match compiled-in value... */
|
||||||
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
/* Check that number of components won't exceed internal array sizes */
|
||||||
|
if (cinfo->num_components > MAX_COMPONENTS)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||||
|
MAX_COMPONENTS);
|
||||||
|
|
||||||
/* Compute maximum sampling factors; check factor validity */
|
/* Compute maximum sampling factors; check factor validity */
|
||||||
cinfo->max_h_samp_factor = 1;
|
cinfo->max_h_samp_factor = 1;
|
||||||
cinfo->max_v_samp_factor = 1;
|
cinfo->max_v_samp_factor = 1;
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
compptr = &cinfo->comp_info[ci];
|
ci++, compptr++) {
|
||||||
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
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)
|
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||||
ERREXIT(cinfo->emethods, "Bogus sampling factors");
|
ERREXIT(cinfo, JERR_BAD_SAMPLING);
|
||||||
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||||
compptr->h_samp_factor);
|
compptr->h_samp_factor);
|
||||||
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||||
compptr->v_samp_factor);
|
compptr->v_samp_factor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute logical subsampled dimensions of components */
|
/* Compute dimensions of components */
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
compptr = &cinfo->comp_info[ci];
|
ci++, compptr++) {
|
||||||
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
|
/* Fill in the correct component_index value; don't rely on application */
|
||||||
+ cinfo->max_h_samp_factor - 1)
|
compptr->component_index = ci;
|
||||||
/ cinfo->max_h_samp_factor;
|
/* For compression, we never do DCT scaling. */
|
||||||
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
|
compptr->DCT_scaled_size = DCTSIZE;
|
||||||
+ cinfo->max_v_samp_factor - 1)
|
/* Size in DCT blocks */
|
||||||
/ cinfo->max_v_samp_factor;
|
compptr->width_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||||
|
compptr->height_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||||
|
/* Size in samples */
|
||||||
|
compptr->downsampled_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) cinfo->max_h_samp_factor);
|
||||||
|
compptr->downsampled_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) cinfo->max_v_samp_factor);
|
||||||
|
/* Mark component needed (this flag isn't actually used for compression) */
|
||||||
|
compptr->component_needed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute number of fully interleaved MCU rows (number of times that
|
||||||
|
* main controller will call coefficient controller).
|
||||||
|
*/
|
||||||
|
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
validate_script (j_compress_ptr cinfo)
|
||||||
|
/* Verify that the scan script in cinfo->scan_info[] is valid; also
|
||||||
|
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const jpeg_scan_info * scanptr;
|
||||||
|
int scanno, ncomps, ci, coefi, thisi;
|
||||||
|
int Ss, Se, Ah, Al;
|
||||||
|
boolean component_sent[MAX_COMPONENTS];
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
int * last_bitpos_ptr;
|
||||||
|
int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
|
||||||
|
/* -1 until that coefficient has been seen; then last Al for it */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cinfo->num_scans <= 0)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
|
||||||
|
|
||||||
|
/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
|
||||||
|
* for progressive JPEG, no scan can have this.
|
||||||
|
*/
|
||||||
|
scanptr = cinfo->scan_info;
|
||||||
|
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
cinfo->progressive_mode = TRUE;
|
||||||
|
last_bitpos_ptr = & last_bitpos[0][0];
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||||
|
for (coefi = 0; coefi < DCTSIZE2; coefi++)
|
||||||
|
*last_bitpos_ptr++ = -1;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
cinfo->progressive_mode = FALSE;
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||||
|
component_sent[ci] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
|
||||||
|
/* Validate component indexes */
|
||||||
|
ncomps = scanptr->comps_in_scan;
|
||||||
|
if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
|
||||||
|
for (ci = 0; ci < ncomps; ci++) {
|
||||||
|
thisi = scanptr->component_index[ci];
|
||||||
|
if (thisi < 0 || thisi >= cinfo->num_components)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
|
||||||
|
/* Components must appear in SOF order within each scan */
|
||||||
|
if (ci > 0 && thisi <= scanptr->component_index[ci-1])
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
|
||||||
|
}
|
||||||
|
/* Validate progression parameters */
|
||||||
|
Ss = scanptr->Ss;
|
||||||
|
Se = scanptr->Se;
|
||||||
|
Ah = scanptr->Ah;
|
||||||
|
Al = scanptr->Al;
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
/* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
|
||||||
|
* seems wrong: the upper bound ought to depend on data precision.
|
||||||
|
* Perhaps they really meant 0..N+1 for N-bit precision.
|
||||||
|
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
|
||||||
|
* out-of-range reconstructed DC values during the first DC scan,
|
||||||
|
* which might cause problems for some decoders.
|
||||||
|
*/
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
#define MAX_AH_AL 10
|
||||||
|
#else
|
||||||
|
#define MAX_AH_AL 13
|
||||||
|
#endif
|
||||||
|
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
|
||||||
|
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
if (Ss == 0) {
|
||||||
|
if (Se != 0) /* DC and AC together not OK */
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
} else {
|
||||||
|
if (ncomps != 1) /* AC scans must be for only one component */
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
}
|
||||||
|
for (ci = 0; ci < ncomps; ci++) {
|
||||||
|
last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
|
||||||
|
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
for (coefi = Ss; coefi <= Se; coefi++) {
|
||||||
|
if (last_bitpos_ptr[coefi] < 0) {
|
||||||
|
/* first scan of this coefficient */
|
||||||
|
if (Ah != 0)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
} else {
|
||||||
|
/* not first scan */
|
||||||
|
if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
}
|
||||||
|
last_bitpos_ptr[coefi] = Al;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* For sequential JPEG, all progression parameters must be these: */
|
||||||
|
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||||
|
/* Make sure components are not sent twice */
|
||||||
|
for (ci = 0; ci < ncomps; ci++) {
|
||||||
|
thisi = scanptr->component_index[ci];
|
||||||
|
if (component_sent[thisi])
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
|
||||||
|
component_sent[thisi] = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now verify that everything got sent. */
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
/* For progressive mode, we only check that at least some DC data
|
||||||
|
* got sent for each component; the spec does not require that all bits
|
||||||
|
* of all coefficients be transmitted. Would it be wiser to enforce
|
||||||
|
* transmission of all coefficient bits??
|
||||||
|
*/
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
if (last_bitpos[ci][0] < 0)
|
||||||
|
ERREXIT(cinfo, JERR_MISSING_DATA);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
if (! component_sent[ci])
|
||||||
|
ERREXIT(cinfo, JERR_MISSING_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* C_MULTISCAN_FILES_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
select_scan_parameters (j_compress_ptr cinfo)
|
||||||
|
/* Set up the scan parameters for the current scan */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
if (cinfo->scan_info != NULL) {
|
||||||
|
/* Prepare for current scan --- the script is already validated */
|
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
|
const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
|
||||||
|
|
||||||
|
cinfo->comps_in_scan = scanptr->comps_in_scan;
|
||||||
|
for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
|
||||||
|
cinfo->cur_comp_info[ci] =
|
||||||
|
&cinfo->comp_info[scanptr->component_index[ci]];
|
||||||
|
}
|
||||||
|
cinfo->Ss = scanptr->Ss;
|
||||||
|
cinfo->Se = scanptr->Se;
|
||||||
|
cinfo->Ah = scanptr->Ah;
|
||||||
|
cinfo->Al = scanptr->Al;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Prepare for single sequential-JPEG scan containing all components */
|
||||||
|
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||||
|
MAX_COMPS_IN_SCAN);
|
||||||
|
cinfo->comps_in_scan = cinfo->num_components;
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||||
|
}
|
||||||
|
cinfo->Ss = 0;
|
||||||
|
cinfo->Se = DCTSIZE2-1;
|
||||||
|
cinfo->Ah = 0;
|
||||||
|
cinfo->Al = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
per_scan_setup (j_compress_ptr cinfo)
|
||||||
|
/* Do computations that are needed before processing a JPEG scan */
|
||||||
|
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
|
||||||
|
{
|
||||||
|
int ci, mcublks, tmp;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
if (cinfo->comps_in_scan == 1) {
|
||||||
|
|
||||||
|
/* Noninterleaved (single-component) scan */
|
||||||
|
compptr = cinfo->cur_comp_info[0];
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||||
|
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||||
|
|
||||||
|
/* For noninterleaved scan, always one block per MCU */
|
||||||
|
compptr->MCU_width = 1;
|
||||||
|
compptr->MCU_height = 1;
|
||||||
|
compptr->MCU_blocks = 1;
|
||||||
|
compptr->MCU_sample_width = DCTSIZE;
|
||||||
|
compptr->last_col_width = 1;
|
||||||
|
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||||
|
* as the number of block rows present in the last iMCU row.
|
||||||
|
*/
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
cinfo->blocks_in_MCU = 1;
|
||||||
|
cinfo->MCU_membership[0] = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Interleaved (multi-component) scan */
|
||||||
|
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
|
||||||
|
MAX_COMPS_IN_SCAN);
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width,
|
||||||
|
(long) (cinfo->max_h_samp_factor*DCTSIZE));
|
||||||
|
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
|
||||||
|
cinfo->blocks_in_MCU = 0;
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Sampling factors give # of blocks of component in each MCU */
|
||||||
|
compptr->MCU_width = compptr->h_samp_factor;
|
||||||
|
compptr->MCU_height = compptr->v_samp_factor;
|
||||||
|
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||||
|
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
|
||||||
|
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||||
|
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_width;
|
||||||
|
compptr->last_col_width = tmp;
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_height;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
mcublks = compptr->MCU_blocks;
|
||||||
|
if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||||
|
while (mcublks-- > 0) {
|
||||||
|
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert restart specified in rows to actual MCU count. */
|
||||||
|
/* Note that count must fit in 16 bits, so we provide limiting. */
|
||||||
|
if (cinfo->restart_in_rows > 0) {
|
||||||
|
long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
|
||||||
|
cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the main entry point to the JPEG compressor.
|
* Per-pass setup.
|
||||||
|
* This is called at the beginning of each pass. We determine which modules
|
||||||
|
* will be active during this pass and give them appropriate start_pass calls.
|
||||||
|
* We also set is_last_pass to indicate whether any more passes will be
|
||||||
|
* required.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
GLOBAL void
|
prepare_for_pass (j_compress_ptr cinfo)
|
||||||
jpeg_compress (compress_info_ptr cinfo)
|
|
||||||
{
|
{
|
||||||
/* Read the input file header: determine image size & component count.
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
* 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 */
|
switch (master->pass_type) {
|
||||||
/* output file format based on results of input_init. */
|
case main_pass:
|
||||||
(*cinfo->methods->c_ui_method_selection) (cinfo);
|
/* Initial pass: will collect input data, and do either Huffman
|
||||||
|
* optimization or data output for the first scan.
|
||||||
|
*/
|
||||||
|
select_scan_parameters(cinfo);
|
||||||
|
per_scan_setup(cinfo);
|
||||||
|
if (! cinfo->raw_data_in) {
|
||||||
|
(*cinfo->cconvert->start_pass) (cinfo);
|
||||||
|
(*cinfo->downsample->start_pass) (cinfo);
|
||||||
|
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||||
|
}
|
||||||
|
(*cinfo->fdct->start_pass) (cinfo);
|
||||||
|
(*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
|
||||||
|
(*cinfo->coef->start_pass) (cinfo,
|
||||||
|
(master->total_passes > 1 ?
|
||||||
|
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
|
||||||
|
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||||
|
if (cinfo->optimize_coding) {
|
||||||
|
/* No immediate data output; postpone writing frame/scan headers */
|
||||||
|
master->pub.call_pass_startup = FALSE;
|
||||||
|
} else {
|
||||||
|
/* Will write frame/scan headers at first jpeg_write_scanlines call */
|
||||||
|
master->pub.call_pass_startup = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef ENTROPY_OPT_SUPPORTED
|
||||||
|
case huff_opt_pass:
|
||||||
|
/* Do Huffman optimization for a scan after the first one. */
|
||||||
|
select_scan_parameters(cinfo);
|
||||||
|
per_scan_setup(cinfo);
|
||||||
|
if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
|
||||||
|
(*cinfo->entropy->start_pass) (cinfo, TRUE);
|
||||||
|
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||||
|
master->pub.call_pass_startup = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Special case: Huffman DC refinement scans need no Huffman table
|
||||||
|
* and therefore we can skip the optimization pass for them.
|
||||||
|
*/
|
||||||
|
master->pass_type = output_pass;
|
||||||
|
master->pass_number++;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
#endif
|
||||||
|
case output_pass:
|
||||||
|
/* Do a data-output pass. */
|
||||||
|
/* We need not repeat per-scan setup if prior optimization pass did it. */
|
||||||
|
if (! cinfo->optimize_coding) {
|
||||||
|
select_scan_parameters(cinfo);
|
||||||
|
per_scan_setup(cinfo);
|
||||||
|
}
|
||||||
|
(*cinfo->entropy->start_pass) (cinfo, FALSE);
|
||||||
|
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||||
|
/* We emit frame/scan headers now */
|
||||||
|
if (master->scan_number == 0)
|
||||||
|
(*cinfo->marker->write_frame_header) (cinfo);
|
||||||
|
(*cinfo->marker->write_scan_header) (cinfo);
|
||||||
|
master->pub.call_pass_startup = FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now select methods for compression steps. */
|
master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
|
||||||
initial_setup(cinfo);
|
|
||||||
c_initial_method_selection(cinfo);
|
|
||||||
|
|
||||||
/* Initialize the output file & other modules as needed */
|
/* Set up progress monitor's pass info if present */
|
||||||
/* (entropy_encoder is inited by pipeline controller) */
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->completed_passes = master->pass_number;
|
||||||
(*cinfo->methods->colorin_init) (cinfo);
|
cinfo->progress->total_passes = master->total_passes;
|
||||||
(*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 */
|
* Special start-of-pass hook.
|
||||||
(*cinfo->methods->write_file_trailer) (cinfo);
|
* This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
|
||||||
(*cinfo->methods->colorin_term) (cinfo);
|
* In single-pass processing, we need this hook because we don't want to
|
||||||
(*cinfo->methods->input_term) (cinfo);
|
* write frame/scan headers during jpeg_start_compress; we want to let the
|
||||||
|
* application write COM markers etc. between jpeg_start_compress and the
|
||||||
/* My, that was easy, wasn't it? */
|
* jpeg_write_scanlines loop.
|
||||||
|
* In multi-pass processing, this routine is not used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
pass_startup (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
|
||||||
|
|
||||||
|
(*cinfo->marker->write_frame_header) (cinfo);
|
||||||
|
(*cinfo->marker->write_scan_header) (cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up at end of pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
finish_pass_master (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
|
|
||||||
|
/* The entropy coder always needs an end-of-pass call,
|
||||||
|
* either to analyze statistics or to flush its output buffer.
|
||||||
|
*/
|
||||||
|
(*cinfo->entropy->finish_pass) (cinfo);
|
||||||
|
|
||||||
|
/* Update state for next pass */
|
||||||
|
switch (master->pass_type) {
|
||||||
|
case main_pass:
|
||||||
|
/* next pass is either output of scan 0 (after optimization)
|
||||||
|
* or output of scan 1 (if no optimization).
|
||||||
|
*/
|
||||||
|
master->pass_type = output_pass;
|
||||||
|
if (! cinfo->optimize_coding)
|
||||||
|
master->scan_number++;
|
||||||
|
break;
|
||||||
|
case huff_opt_pass:
|
||||||
|
/* next pass is always output of current scan */
|
||||||
|
master->pass_type = output_pass;
|
||||||
|
break;
|
||||||
|
case output_pass:
|
||||||
|
/* next pass is either optimization or output of next scan */
|
||||||
|
if (cinfo->optimize_coding)
|
||||||
|
master->pass_type = huff_opt_pass;
|
||||||
|
master->scan_number++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
master->pass_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize master compression control.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
|
||||||
|
{
|
||||||
|
my_master_ptr master;
|
||||||
|
|
||||||
|
master = (my_master_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_comp_master));
|
||||||
|
cinfo->master = (struct jpeg_comp_master *) master;
|
||||||
|
master->pub.prepare_for_pass = prepare_for_pass;
|
||||||
|
master->pub.pass_startup = pass_startup;
|
||||||
|
master->pub.finish_pass = finish_pass_master;
|
||||||
|
master->pub.is_last_pass = FALSE;
|
||||||
|
|
||||||
|
/* Validate parameters, determine derived values */
|
||||||
|
initial_setup(cinfo);
|
||||||
|
|
||||||
|
if (cinfo->scan_info != NULL) {
|
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||||
|
validate_script(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
cinfo->progressive_mode = FALSE;
|
||||||
|
cinfo->num_scans = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */
|
||||||
|
cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
|
||||||
|
|
||||||
|
/* Initialize my private state */
|
||||||
|
if (transcode_only) {
|
||||||
|
/* no main pass in transcoding */
|
||||||
|
if (cinfo->optimize_coding)
|
||||||
|
master->pass_type = huff_opt_pass;
|
||||||
|
else
|
||||||
|
master->pass_type = output_pass;
|
||||||
|
} else {
|
||||||
|
/* for normal compression, first pass is always this type: */
|
||||||
|
master->pass_type = main_pass;
|
||||||
|
}
|
||||||
|
master->scan_number = 0;
|
||||||
|
master->pass_number = 0;
|
||||||
|
if (cinfo->optimize_coding)
|
||||||
|
master->total_passes = cinfo->num_scans * 2;
|
||||||
|
else
|
||||||
|
master->total_passes = cinfo->num_scans;
|
||||||
}
|
}
|
||||||
|
|||||||
212
jcmcu.c
212
jcmcu.c
@@ -1,212 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
143
jcolsamp.h
Normal file
143
jcolsamp.h
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* jcolsamp.h - private declarations for color conversion & up/downsampling
|
||||||
|
*
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
*
|
||||||
|
* Last Modified : February 4, 2006
|
||||||
|
*
|
||||||
|
* [TAB8]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* configuration check: BITS_IN_JSAMPLE==8 (8-bit sample values) is the only
|
||||||
|
* valid setting on this SIMD extension.
|
||||||
|
*/
|
||||||
|
#if BITS_IN_JSAMPLE != 8
|
||||||
|
#error "Sorry, this SIMD code only copes with 8-bit sample values."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#define jpeg_rgb_ycc_convert_mmx jMRgbYccCnv /* jccolmmx.asm */
|
||||||
|
#define jpeg_rgb_ycc_convert_sse2 jSRgbYccCnv /* jccolss2.asm */
|
||||||
|
#define jpeg_h2v1_downsample_mmx jM21Downsample /* jcsammmx.asm */
|
||||||
|
#define jpeg_h2v2_downsample_mmx jM22Downsample /* jcsammmx.asm */
|
||||||
|
#define jpeg_h2v1_downsample_sse2 jS21Downsample /* jcsamss2.asm */
|
||||||
|
#define jpeg_h2v2_downsample_sse2 jS22Downsample /* jcsamss2.asm */
|
||||||
|
#define jpeg_ycc_rgb_convert_mmx jMYccRgbCnv /* jdcolmmx.asm */
|
||||||
|
#define jpeg_ycc_rgb_convert_sse2 jSYccRgbCnv /* jdcolss2.asm */
|
||||||
|
#define jpeg_h2v1_merged_upsample_mmx jM21MerUpsample /* jdmermmx.asm */
|
||||||
|
#define jpeg_h2v2_merged_upsample_mmx jM22MerUpsample /* jdmermmx.asm */
|
||||||
|
#define jpeg_h2v1_merged_upsample_sse2 jS21MerUpsample /* jdmerss2.asm */
|
||||||
|
#define jpeg_h2v2_merged_upsample_sse2 jS22MerUpsample /* jdmerss2.asm */
|
||||||
|
#define jpeg_h2v1_fancy_upsample_mmx jM21FanUpsample /* jdsammmx.asm */
|
||||||
|
#define jpeg_h2v2_fancy_upsample_mmx jM22FanUpsample /* jdsammmx.asm */
|
||||||
|
#define jpeg_h1v2_fancy_upsample_mmx jM12FanUpsample /* jdsammmx.asm */
|
||||||
|
#define jpeg_h2v1_upsample_mmx jM21Upsample /* jdsammmx.asm */
|
||||||
|
#define jpeg_h2v2_upsample_mmx jM22Upsample /* jdsammmx.asm */
|
||||||
|
#define jpeg_h2v1_fancy_upsample_sse2 jS21FanUpsample /* jdsamss2.asm */
|
||||||
|
#define jpeg_h2v2_fancy_upsample_sse2 jS22FanUpsample /* jdsamss2.asm */
|
||||||
|
#define jpeg_h1v2_fancy_upsample_sse2 jS12FanUpsample /* jdsamss2.asm */
|
||||||
|
#define jpeg_h2v1_upsample_sse2 jS21Upsample /* jdsamss2.asm */
|
||||||
|
#define jpeg_h2v2_upsample_sse2 jS22Upsample /* jdsamss2.asm */
|
||||||
|
#define jconst_rgb_ycc_convert_mmx jMCRgbYccCnv /* jccolmmx.asm */
|
||||||
|
#define jconst_rgb_ycc_convert_sse2 jSCRgbYccCnv /* jccolss2.asm */
|
||||||
|
#define jconst_ycc_rgb_convert_mmx jMCYccRgbCnv /* jdcolmmx.asm */
|
||||||
|
#define jconst_ycc_rgb_convert_sse2 jSCYccRgbCnv /* jdcolss2.asm */
|
||||||
|
#define jconst_merged_upsample_mmx jMCMerUpsample /* jdmermmx.asm */
|
||||||
|
#define jconst_merged_upsample_sse2 jSCMerUpsample /* jdmerss2.asm */
|
||||||
|
#define jconst_fancy_upsample_mmx jMCFanUpsample /* jdsammmx.asm */
|
||||||
|
#define jconst_fancy_upsample_sse2 jSCFanUpsample /* jdsamss2.asm */
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
#define jpeg_simd_merged_upsampler jSiMUpsampler /* jdmerge.c */
|
||||||
|
#endif
|
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||||
|
|
||||||
|
/* Extern declarations for color conversion & up/downsampling routines. */
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_rgb_ycc_convert_mmx
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows));
|
||||||
|
EXTERN(void) jpeg_rgb_ycc_convert_sse2
|
||||||
|
JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||||
|
JDIMENSION output_row, int num_rows));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_h2v1_downsample_mmx
|
||||||
|
JPP((j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data));
|
||||||
|
EXTERN(void) jpeg_h2v2_downsample_mmx
|
||||||
|
JPP((j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data));
|
||||||
|
EXTERN(void) jpeg_h2v1_downsample_sse2
|
||||||
|
JPP((j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data));
|
||||||
|
EXTERN(void) jpeg_h2v2_downsample_sse2
|
||||||
|
JPP((j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_ycc_rgb_convert_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows));
|
||||||
|
EXTERN(void) jpeg_ycc_rgb_convert_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_h2v1_merged_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf));
|
||||||
|
EXTERN(void) jpeg_h2v2_merged_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf));
|
||||||
|
EXTERN(void) jpeg_h2v1_merged_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf));
|
||||||
|
EXTERN(void) jpeg_h2v2_merged_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_h2v1_fancy_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v2_fancy_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h1v2_fancy_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v1_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v2_upsample_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v1_fancy_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v2_fancy_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h1v2_fancy_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v1_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
EXTERN(void) jpeg_h2v2_upsample_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
|
||||||
|
extern const int jconst_rgb_ycc_convert_mmx[];
|
||||||
|
extern const int jconst_rgb_ycc_convert_sse2[];
|
||||||
|
extern const int jconst_ycc_rgb_convert_mmx[];
|
||||||
|
extern const int jconst_ycc_rgb_convert_sse2[];
|
||||||
|
extern const int jconst_merged_upsample_mmx[];
|
||||||
|
extern const int jconst_merged_upsample_sse2[];
|
||||||
|
extern const int jconst_fancy_upsample_mmx[];
|
||||||
|
extern const int jconst_fancy_upsample_sse2[];
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
EXTERN(unsigned int) jpeg_simd_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||||
|
#endif
|
||||||
156
jcolsamp.inc
Normal file
156
jcolsamp.inc
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
;
|
||||||
|
; jcolsamp.inc - private declarations for color conversion & up/downsampling
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; Last Modified : January 5, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; configuration check: BITS_IN_JSAMPLE==8 (8-bit sample values) is the only
|
||||||
|
; valid setting on this SIMD extension.
|
||||||
|
;
|
||||||
|
%if BITS_IN_JSAMPLE != 8
|
||||||
|
%error "Sorry, this SIMD code only copes with 8-bit sample values."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; Short forms of external names for systems with brain-damaged linkers.
|
||||||
|
;
|
||||||
|
%ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
%define jpeg_rgb_ycc_convert_mmx jMRgbYccCnv ; jccolmmx.asm
|
||||||
|
%define jpeg_rgb_ycc_convert_sse2 jSRgbYccCnv ; jccolss2.asm
|
||||||
|
%define jpeg_h2v1_downsample_mmx jM21Downsample ; jcsammmx.asm
|
||||||
|
%define jpeg_h2v2_downsample_mmx jM22Downsample ; jcsammmx.asm
|
||||||
|
%define jpeg_h2v1_downsample_sse2 jS21Downsample ; jcsamss2.asm
|
||||||
|
%define jpeg_h2v2_downsample_sse2 jS22Downsample ; jcsamss2.asm
|
||||||
|
%define jpeg_ycc_rgb_convert_mmx jMYccRgbCnv ; jdcolmmx.asm
|
||||||
|
%define jpeg_ycc_rgb_convert_sse2 jSYccRgbCnv ; jdcolss2.asm
|
||||||
|
%define jpeg_h2v1_merged_upsample_mmx jM21MerUpsample ; jdmermmx.asm
|
||||||
|
%define jpeg_h2v2_merged_upsample_mmx jM22MerUpsample ; jdmermmx.asm
|
||||||
|
%define jpeg_h2v1_merged_upsample_sse2 jS21MerUpsample ; jdmerss2.asm
|
||||||
|
%define jpeg_h2v2_merged_upsample_sse2 jS22MerUpsample ; jdmerss2.asm
|
||||||
|
%define jpeg_h2v1_fancy_upsample_mmx jM21FanUpsample ; jdsammmx.asm
|
||||||
|
%define jpeg_h2v2_fancy_upsample_mmx jM22FanUpsample ; jdsammmx.asm
|
||||||
|
%define jpeg_h1v2_fancy_upsample_mmx jM12FanUpsample ; jdsammmx.asm
|
||||||
|
%define jpeg_h2v1_upsample_mmx jM21Upsample ; jdsammmx.asm
|
||||||
|
%define jpeg_h2v2_upsample_mmx jM22Upsample ; jdsammmx.asm
|
||||||
|
%define jpeg_h2v1_fancy_upsample_sse2 jS21FanUpsample ; jdsamss2.asm
|
||||||
|
%define jpeg_h2v2_fancy_upsample_sse2 jS22FanUpsample ; jdsamss2.asm
|
||||||
|
%define jpeg_h1v2_fancy_upsample_sse2 jS12FanUpsample ; jdsamss2.asm
|
||||||
|
%define jpeg_h2v1_upsample_sse2 jS21Upsample ; jdsamss2.asm
|
||||||
|
%define jpeg_h2v2_upsample_sse2 jS22Upsample ; jdsamss2.asm
|
||||||
|
%define jconst_rgb_ycc_convert_mmx jMCRgbYccCnv ; jccolmmx.asm
|
||||||
|
%define jconst_rgb_ycc_convert_sse2 jSCRgbYccCnv ; jccolss2.asm
|
||||||
|
%define jconst_ycc_rgb_convert_mmx jMCYccRgbCnv ; jdcolmmx.asm
|
||||||
|
%define jconst_ycc_rgb_convert_sse2 jSCYccRgbCnv ; jdcolss2.asm
|
||||||
|
%define jconst_merged_upsample_mmx jMCMerUpsample ; jdmermmx.asm
|
||||||
|
%define jconst_merged_upsample_sse2 jSCMerUpsample ; jdmerss2.asm
|
||||||
|
%define jconst_fancy_upsample_mmx jMCFanUpsample ; jdsammmx.asm
|
||||||
|
%define jconst_fancy_upsample_sse2 jSCFanUpsample ; jdsamss2.asm
|
||||||
|
%endif ; NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
; pseudo-resisters to make ordering of RGB configurable
|
||||||
|
;
|
||||||
|
%if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
%if RGB_RED < 0 || RGB_RED >= RGB_PIXELSIZE || RGB_GREEN < 0 || \
|
||||||
|
RGB_GREEN >= RGB_PIXELSIZE || RGB_BLUE < 0 || RGB_BLUE >= RGB_PIXELSIZE || \
|
||||||
|
RGB_RED == RGB_GREEN || RGB_GREEN == RGB_BLUE || RGB_RED == RGB_BLUE
|
||||||
|
%error "Incorrect RGB pixel offset."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if RGB_RED == 0
|
||||||
|
%define mmA mm0
|
||||||
|
%define mmB mm1
|
||||||
|
%define xmmA xmm0
|
||||||
|
%define xmmB xmm1
|
||||||
|
%elif RGB_GREEN == 0
|
||||||
|
%define mmA mm2
|
||||||
|
%define mmB mm3
|
||||||
|
%define xmmA xmm2
|
||||||
|
%define xmmB xmm3
|
||||||
|
%elif RGB_BLUE == 0
|
||||||
|
%define mmA mm4
|
||||||
|
%define mmB mm5
|
||||||
|
%define xmmA xmm4
|
||||||
|
%define xmmB xmm5
|
||||||
|
%else
|
||||||
|
%define mmA mm6
|
||||||
|
%define mmB mm7
|
||||||
|
%define xmmA xmm6
|
||||||
|
%define xmmB xmm7
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if RGB_RED == 1
|
||||||
|
%define mmC mm0
|
||||||
|
%define mmD mm1
|
||||||
|
%define xmmC xmm0
|
||||||
|
%define xmmD xmm1
|
||||||
|
%elif RGB_GREEN == 1
|
||||||
|
%define mmC mm2
|
||||||
|
%define mmD mm3
|
||||||
|
%define xmmC xmm2
|
||||||
|
%define xmmD xmm3
|
||||||
|
%elif RGB_BLUE == 1
|
||||||
|
%define mmC mm4
|
||||||
|
%define mmD mm5
|
||||||
|
%define xmmC xmm4
|
||||||
|
%define xmmD xmm5
|
||||||
|
%else
|
||||||
|
%define mmC mm6
|
||||||
|
%define mmD mm7
|
||||||
|
%define xmmC xmm6
|
||||||
|
%define xmmD xmm7
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if RGB_RED == 2
|
||||||
|
%define mmE mm0
|
||||||
|
%define mmF mm1
|
||||||
|
%define xmmE xmm0
|
||||||
|
%define xmmF xmm1
|
||||||
|
%elif RGB_GREEN == 2
|
||||||
|
%define mmE mm2
|
||||||
|
%define mmF mm3
|
||||||
|
%define xmmE xmm2
|
||||||
|
%define xmmF xmm3
|
||||||
|
%elif RGB_BLUE == 2
|
||||||
|
%define mmE mm4
|
||||||
|
%define mmF mm5
|
||||||
|
%define xmmE xmm4
|
||||||
|
%define xmmF xmm5
|
||||||
|
%else
|
||||||
|
%define mmE mm6
|
||||||
|
%define mmF mm7
|
||||||
|
%define xmmE xmm6
|
||||||
|
%define xmmF xmm7
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if RGB_RED == 3
|
||||||
|
%define mmG mm0
|
||||||
|
%define mmH mm1
|
||||||
|
%define xmmG xmm0
|
||||||
|
%define xmmH xmm1
|
||||||
|
%elif RGB_GREEN == 3
|
||||||
|
%define mmG mm2
|
||||||
|
%define mmH mm3
|
||||||
|
%define xmmG xmm2
|
||||||
|
%define xmmH xmm3
|
||||||
|
%elif RGB_BLUE == 3
|
||||||
|
%define mmG mm4
|
||||||
|
%define mmH mm5
|
||||||
|
%define xmmG xmm4
|
||||||
|
%define xmmH xmm5
|
||||||
|
%else
|
||||||
|
%define mmG mm6
|
||||||
|
%define mmH mm7
|
||||||
|
%define xmmG xmm6
|
||||||
|
%define xmmH xmm7
|
||||||
|
%endif
|
||||||
|
%endif ; RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
164
jcomapi.c
Normal file
164
jcomapi.c
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* jcomapi.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : March 11, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains application interface routines that are used for both
|
||||||
|
* compression and decompression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abort processing of a JPEG compression or decompression operation,
|
||||||
|
* but don't destroy the object itself.
|
||||||
|
*
|
||||||
|
* For this, we merely clean up all the nonpermanent memory pools.
|
||||||
|
* Note that temp files (virtual arrays) are not allowed to belong to
|
||||||
|
* the permanent pool, so we will be able to close all temp files here.
|
||||||
|
* Closing a data source or destination, if necessary, is the application's
|
||||||
|
* responsibility.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_abort (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
int pool;
|
||||||
|
|
||||||
|
/* Do nothing if called on a not-initialized or destroyed JPEG object. */
|
||||||
|
if (cinfo->mem == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Releasing pools in reverse order might help avoid fragmentation
|
||||||
|
* with some (brain-damaged) malloc libraries.
|
||||||
|
*/
|
||||||
|
for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
|
||||||
|
(*cinfo->mem->free_pool) (cinfo, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset overall state for possible reuse of object */
|
||||||
|
if (cinfo->is_decompressor) {
|
||||||
|
cinfo->global_state = DSTATE_START;
|
||||||
|
/* Try to keep application from accessing now-deleted marker list.
|
||||||
|
* A bit kludgy to do it here, but this is the most central place.
|
||||||
|
*/
|
||||||
|
((j_decompress_ptr) cinfo)->marker_list = NULL;
|
||||||
|
} else {
|
||||||
|
cinfo->global_state = CSTATE_START;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destruction of a JPEG object.
|
||||||
|
*
|
||||||
|
* Everything gets deallocated except the master jpeg_compress_struct itself
|
||||||
|
* and the error manager struct. Both of these are supplied by the application
|
||||||
|
* and must be freed, if necessary, by the application. (Often they are on
|
||||||
|
* the stack and so don't need to be freed anyway.)
|
||||||
|
* Closing a data source or destination, if necessary, is the application's
|
||||||
|
* responsibility.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_destroy (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* We need only tell the memory manager to release everything. */
|
||||||
|
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
|
||||||
|
if (cinfo->mem != NULL)
|
||||||
|
(*cinfo->mem->self_destruct) (cinfo);
|
||||||
|
cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
|
||||||
|
cinfo->global_state = 0; /* mark it destroyed */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convenience routines for allocating quantization and Huffman tables.
|
||||||
|
* (Would jutils.c be a more reasonable place to put these?)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JQUANT_TBL *)
|
||||||
|
jpeg_alloc_quant_table (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
JQUANT_TBL *tbl;
|
||||||
|
|
||||||
|
tbl = (JQUANT_TBL *)
|
||||||
|
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
|
||||||
|
tbl->sent_table = FALSE; /* make sure this is false in any new table */
|
||||||
|
return tbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(JHUFF_TBL *)
|
||||||
|
jpeg_alloc_huff_table (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
JHUFF_TBL *tbl;
|
||||||
|
|
||||||
|
tbl = (JHUFF_TBL *)
|
||||||
|
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
|
||||||
|
tbl->sent_table = FALSE; /* make sure this is false in any new table */
|
||||||
|
return tbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: Checking for support of SIMD instruction set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_support (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
enum { JSIMD_INVALID = ~0 };
|
||||||
|
static volatile unsigned int simd_supported = JSIMD_INVALID;
|
||||||
|
|
||||||
|
if (simd_supported == JSIMD_INVALID)
|
||||||
|
simd_supported = jpeg_simd_os_support(jpeg_simd_cpu_support());
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
if (cinfo != NULL) /* Turn off the masked flags */
|
||||||
|
return simd_supported & ~jpeg_simd_mask(cinfo, JSIMD_NONE, JSIMD_NONE);
|
||||||
|
#endif
|
||||||
|
return simd_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef JSIMD_MASKFUNC_NOT_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: modify/retrieve SIMD instruction mask
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_mask (j_common_ptr cinfo, unsigned int remove, unsigned int add)
|
||||||
|
{
|
||||||
|
unsigned long *gp;
|
||||||
|
unsigned int oldmask;
|
||||||
|
|
||||||
|
if (cinfo->is_decompressor)
|
||||||
|
gp = (unsigned long *) &((j_decompress_ptr) cinfo)->output_gamma;
|
||||||
|
else /* compressor */
|
||||||
|
gp = (unsigned long *) &((j_compress_ptr) cinfo)->input_gamma;
|
||||||
|
|
||||||
|
if ((gp[1] == 0x3FF00000 || gp[1] == 0x00000000) && /* +1.0 or +0.0 */
|
||||||
|
(gp[0] & ~JSIMD_ALL) == 0) {
|
||||||
|
oldmask = gp[0];
|
||||||
|
if (((remove | add) & ~JSIMD_ALL) == 0)
|
||||||
|
gp[0] = (oldmask & ~remove) | add;
|
||||||
|
} else {
|
||||||
|
oldmask = 0; /* error */
|
||||||
|
}
|
||||||
|
return oldmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MASKFUNC_NOT_SUPPORTED */
|
||||||
48
jconfig.bc5
Normal file
48
jconfig.bc5
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* jconfig.bc5 --- jconfig.h for Borland C++ Compiler 5.5 (win32) */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN /* this assumes you have -w-stu in CFLAGS */
|
||||||
|
|
||||||
|
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||||
|
#define TYPEDEF_UCHAR_BOOLEAN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE
|
||||||
|
#define USE_SETMODE /* Borland has setmode() */
|
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
#undef PROGRESS_REPORT /* optional */
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
56
jconfig.cfg
Normal file
56
jconfig.cfg
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* jconfig.cfg --- source file edited by configure script */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#undef HAVE_PROTOTYPES
|
||||||
|
#undef HAVE_UNSIGNED_CHAR
|
||||||
|
#undef HAVE_UNSIGNED_SHORT
|
||||||
|
#undef void
|
||||||
|
#undef const
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#undef HAVE_STDDEF_H
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
/* Define this if you get warnings about undefined structures. */
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||||
|
#undef TYPEDEF_UCHAR_BOOLEAN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
#undef INLINE
|
||||||
|
/* These are for configuring the JPEG memory manager. */
|
||||||
|
#undef DEFAULT_MAX_MEM
|
||||||
|
#undef NO_MKTEMP
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE
|
||||||
|
#undef USE_SETMODE
|
||||||
|
#undef USE_FDOPEN
|
||||||
|
#undef NEED_SIGNAL_CATCHER
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
|
||||||
|
/* Define this if you want percent-done progress reports from cjpeg/djpeg. */
|
||||||
|
#undef PROGRESS_REPORT
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
47
jconfig.dj
Normal file
47
jconfig.dj
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* jconfig.dj --- jconfig.h for DJGPP (Delorie's GNU C port) on MS-DOS. */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE /* optional */
|
||||||
|
#define USE_SETMODE /* Needed to make one-file style work in DJGPP */
|
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
#undef PROGRESS_REPORT /* optional */
|
||||||
|
|
||||||
|
#define FREE_MEM_ESTIMATE 0 /* for alternate cjpeg/djpeg */
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
155
jconfig.doc
Normal file
155
jconfig.doc
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* jconfig.doc
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file documents the configuration options that are required to
|
||||||
|
* customize the JPEG software for a particular system.
|
||||||
|
*
|
||||||
|
* The actual configuration options for a particular installation are stored
|
||||||
|
* in jconfig.h. On many machines, jconfig.h can be generated automatically
|
||||||
|
* or copied from one of the "canned" jconfig files that we supply. But if
|
||||||
|
* you need to generate a jconfig.h file by hand, this file tells you how.
|
||||||
|
*
|
||||||
|
* DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
|
||||||
|
* EDIT A COPY NAMED JCONFIG.H.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These symbols indicate the properties of your machine or compiler.
|
||||||
|
* #define the symbol if yes, #undef it if no.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Does your compiler support function prototypes?
|
||||||
|
* (If not, you also need to use ansi2knr, see install.doc)
|
||||||
|
*/
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
|
||||||
|
/* Does your compiler support the declaration "unsigned char" ?
|
||||||
|
* How about "unsigned short" ?
|
||||||
|
*/
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
|
||||||
|
/* Define "void" as "char" if your compiler doesn't know about type void.
|
||||||
|
* NOTE: be sure to define void such that "void *" represents the most general
|
||||||
|
* pointer type, e.g., that returned by malloc().
|
||||||
|
*/
|
||||||
|
/* #define void char */
|
||||||
|
|
||||||
|
/* Define "const" as empty if your compiler doesn't know the "const" keyword.
|
||||||
|
*/
|
||||||
|
/* #define const */
|
||||||
|
|
||||||
|
/* Define this if an ordinary "char" type is unsigned.
|
||||||
|
* If you're not sure, leaving it undefined will work at some cost in speed.
|
||||||
|
* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
|
||||||
|
*/
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
|
||||||
|
/* Define this if your system has an ANSI-conforming <stddef.h> file.
|
||||||
|
*/
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
|
||||||
|
/* Define this if your system has an ANSI-conforming <stdlib.h> file.
|
||||||
|
*/
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define this if your system does not have an ANSI/SysV <string.h>,
|
||||||
|
* but does have a BSD-style <strings.h>.
|
||||||
|
*/
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
|
||||||
|
/* Define this if your system does not provide typedef size_t in any of the
|
||||||
|
* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
|
||||||
|
* <sys/types.h> instead.
|
||||||
|
*/
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
|
||||||
|
* unless you are using a large-data memory model or 80386 flat-memory mode.
|
||||||
|
* On less brain-damaged CPUs this symbol must not be defined.
|
||||||
|
* (Defining this symbol causes large data structures to be referenced through
|
||||||
|
* "far" pointers and to be allocated with a special version of malloc.)
|
||||||
|
*/
|
||||||
|
#undef NEED_FAR_POINTERS
|
||||||
|
|
||||||
|
/* Define this if your linker needs global names to be unique in less
|
||||||
|
* than the first 15 characters.
|
||||||
|
*/
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
|
||||||
|
/* Although a real ANSI C compiler can deal perfectly well with pointers to
|
||||||
|
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
|
||||||
|
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
|
||||||
|
* define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
|
||||||
|
* actually get "missing structure definition" warnings or errors while
|
||||||
|
* compiling the JPEG code.
|
||||||
|
*/
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following options affect code selection within the JPEG library,
|
||||||
|
* but they don't need to be visible to applications using the library.
|
||||||
|
* To minimize application namespace pollution, the symbols won't be
|
||||||
|
* defined unless JPEG_INTERNALS has been defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
/* Define this if your compiler implements ">>" on signed values as a logical
|
||||||
|
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
|
||||||
|
* which is the normal and rational definition.
|
||||||
|
*/
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining options do not affect the JPEG library proper,
|
||||||
|
* but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
|
||||||
|
* Other applications can ignore these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
/* These defines indicate which image (non-JPEG) file formats are allowed. */
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
/* Define this if you want to name both input and output files on the command
|
||||||
|
* line, rather than using stdout and optionally stdin. You MUST do this if
|
||||||
|
* your system can't cope with binary I/O to stdin/stdout. See comments at
|
||||||
|
* head of cjpeg.c or djpeg.c.
|
||||||
|
*/
|
||||||
|
#undef TWO_FILE_COMMANDLINE
|
||||||
|
|
||||||
|
/* Define this if your system needs explicit cleanup of temporary files.
|
||||||
|
* This is crucial under MS-DOS, where the temporary "files" may be areas
|
||||||
|
* of extended memory; on most other systems it's not as important.
|
||||||
|
*/
|
||||||
|
#undef NEED_SIGNAL_CATCHER
|
||||||
|
|
||||||
|
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
|
||||||
|
* This is necessary on systems that distinguish text files from binary files,
|
||||||
|
* and is harmless on most systems that don't. If you have one of the rare
|
||||||
|
* systems that complains about the "b" spec, define this symbol.
|
||||||
|
*/
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
|
||||||
|
/* Define this if you want percent-done progress reports from cjpeg/djpeg.
|
||||||
|
*/
|
||||||
|
#undef PROGRESS_REPORT
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
334
jconfig.h
334
jconfig.h
@@ -1,334 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 SETUP) */
|
|
||||||
|
|
||||||
#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;
|
|
||||||
#undef FALSE /* in case these macros already exist */
|
|
||||||
#undef TRUE
|
|
||||||
#define FALSE 0 /* values of boolean */
|
|
||||||
#define TRUE 1
|
|
||||||
|
|
||||||
/* This defines the size of the I/O buffers for entropy compression
|
|
||||||
* and decompression; you could reduce it if memory is tight.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define JPEG_BUF_SIZE 4096 /* bytes */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* These symbols determine the JPEG functionality supported. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These defines indicate whether to include various optional functions.
|
|
||||||
* Undefining some of these symbols will produce a smaller but less capable
|
|
||||||
* program file. Note that you can leave certain source files out of the
|
|
||||||
* compilation/linking process if you've #undef'd the corresponding symbols.
|
|
||||||
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
|
|
||||||
#undef ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
|
||||||
#define MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
|
||||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
|
||||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */
|
|
||||||
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
|
|
||||||
#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 GIF_SUPPORTED /* GIF image file format */
|
|
||||||
/* #define RLE_SUPPORTED */ /* RLE image file format */
|
|
||||||
#define PPM_SUPPORTED /* PPM/PGM image file format */
|
|
||||||
#define TARGA_SUPPORTED /* Targa image file format */
|
|
||||||
#undef TIFF_SUPPORTED /* TIFF image file format (not yet impl.) */
|
|
||||||
|
|
||||||
/* more capability options later, no doubt */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Define exactly one of these three symbols to indicate whether you want
|
|
||||||
* 8-bit, 12-bit, or 16-bit sample (pixel component) values. 8-bit is the
|
|
||||||
* default and is nearly always the right thing to use. You can use 12-bit if
|
|
||||||
* you need to support image formats with more than 8 bits of resolution in a
|
|
||||||
* color value. 16-bit should only be used for the lossless JPEG mode (not
|
|
||||||
* currently supported). Note that 12- and 16-bit values take up twice as
|
|
||||||
* much memory as 8-bit!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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
|
|
||||||
#define BITS_IN_JSAMPLE 8
|
|
||||||
|
|
||||||
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
|
||||||
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
|
||||||
* If you have only signed chars, and you are more worried about speed than
|
|
||||||
* 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
|
|
||||||
#define BITS_IN_JSAMPLE 12
|
|
||||||
|
|
||||||
/* JSAMPLE should be the smallest type that will hold the values 0..4095. */
|
|
||||||
/* On nearly all machines "short" will do nicely. */
|
|
||||||
|
|
||||||
typedef short JSAMPLE;
|
|
||||||
#define GETJSAMPLE(value) (value)
|
|
||||||
|
|
||||||
#define MAXJSAMPLE 4095
|
|
||||||
#define CENTERJSAMPLE 2048
|
|
||||||
|
|
||||||
#endif /* TWELVE_BIT_SAMPLES */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SIXTEEN_BIT_SAMPLES
|
|
||||||
#define BITS_IN_JSAMPLE 16
|
|
||||||
|
|
||||||
/* JSAMPLE should be the smallest type that will hold the values 0..65535. */
|
|
||||||
|
|
||||||
#ifdef HAVE_UNSIGNED_SHORT
|
|
||||||
|
|
||||||
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. */
|
|
||||||
|
|
||||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
|
|
||||||
typedef short INT16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* INT32 must hold signed 32-bit values; if your machine happens */
|
|
||||||
/* to have 64-bit longs, you might want to change this. */
|
|
||||||
|
|
||||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
|
|
||||||
typedef long INT32;
|
|
||||||
#endif
|
|
||||||
44
jconfig.linux
Normal file
44
jconfig.linux
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* jconfig.linux --- jconfig.h for Linux ELF with gcc */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE
|
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
#undef PROGRESS_REPORT /* optional */
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
48
jconfig.mgw
Normal file
48
jconfig.mgw
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* jconfig.mgw --- jconfig.h for MinGW */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||||
|
#define TYPEDEF_UCHAR_BOOLEAN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE /* optional */
|
||||||
|
#define USE_SETMODE /* MinGW has setmode() */
|
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
#undef PROGRESS_REPORT /* optional */
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
48
jconfig.vc
Normal file
48
jconfig.vc
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
|
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#undef INCOMPLETE_TYPES_BROKEN
|
||||||
|
|
||||||
|
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||||
|
#define TYPEDEF_UCHAR_BOOLEAN
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */
|
||||||
|
|
||||||
|
#if defined(JPEG_INTERNALS) || defined(JPEG_INTERNAL_OPTIONS)
|
||||||
|
#undef JSIMD_MMX_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_3DNOW_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE_NOT_SUPPORTED
|
||||||
|
#undef JSIMD_SSE2_NOT_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG
|
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */
|
||||||
|
#define GIF_SUPPORTED /* GIF image file format */
|
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */
|
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE /* optional */
|
||||||
|
#define USE_SETMODE /* Microsoft has setmode() */
|
||||||
|
#undef NEED_SIGNAL_CATCHER
|
||||||
|
#undef DONT_USE_B_MODE
|
||||||
|
#undef PROGRESS_REPORT /* optional */
|
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */
|
||||||
610
jcparam.c
Normal file
610
jcparam.c
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
/*
|
||||||
|
* jcparam.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains optional default-setting code for the JPEG compressor.
|
||||||
|
* Applications do not have to use this file, but those that don't use it
|
||||||
|
* must know a lot more about the innards of the JPEG code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quantization table setup routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
|
||||||
|
const unsigned int *basic_table,
|
||||||
|
int scale_factor, boolean force_baseline)
|
||||||
|
/* Define a quantization table equal to the basic_table times
|
||||||
|
* a scale factor (given as a percentage).
|
||||||
|
* If force_baseline is TRUE, the computed quantization table entries
|
||||||
|
* are limited to 1..255 for JPEG baseline compatibility.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
JQUANT_TBL ** qtblptr;
|
||||||
|
int i;
|
||||||
|
long temp;
|
||||||
|
|
||||||
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
|
||||||
|
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
|
||||||
|
|
||||||
|
qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
|
||||||
|
|
||||||
|
if (*qtblptr == NULL)
|
||||||
|
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
|
||||||
|
/* limit the values to the valid range */
|
||||||
|
if (temp <= 0L) temp = 1L;
|
||||||
|
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
|
||||||
|
if (force_baseline && temp > 255L)
|
||||||
|
temp = 255L; /* limit to baseline range if requested */
|
||||||
|
(*qtblptr)->quantval[i] = (UINT16) temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize sent_table FALSE so table will be written to JPEG file. */
|
||||||
|
(*qtblptr)->sent_table = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
|
||||||
|
boolean force_baseline)
|
||||||
|
/* Set or change the 'quality' (quantization) setting, using default tables
|
||||||
|
* and a straight percentage-scaling quality scale. In most cases it's better
|
||||||
|
* to use jpeg_set_quality (below); this entry point is provided for
|
||||||
|
* applications that insist on a linear percentage scaling.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* These are the sample quantization tables given in JPEG spec section K.1.
|
||||||
|
* The spec says that the values given produce "good" quality, and
|
||||||
|
* when divided by 2, "very good" quality.
|
||||||
|
*/
|
||||||
|
static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
|
||||||
|
16, 11, 10, 16, 24, 40, 51, 61,
|
||||||
|
12, 12, 14, 19, 26, 58, 60, 55,
|
||||||
|
14, 13, 16, 24, 40, 57, 69, 56,
|
||||||
|
14, 17, 22, 29, 51, 87, 80, 62,
|
||||||
|
18, 22, 37, 56, 68, 109, 103, 77,
|
||||||
|
24, 35, 55, 64, 81, 104, 113, 92,
|
||||||
|
49, 64, 78, 87, 103, 121, 120, 101,
|
||||||
|
72, 92, 95, 98, 112, 100, 103, 99
|
||||||
|
};
|
||||||
|
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
|
||||||
|
17, 18, 24, 47, 99, 99, 99, 99,
|
||||||
|
18, 21, 26, 66, 99, 99, 99, 99,
|
||||||
|
24, 26, 56, 99, 99, 99, 99, 99,
|
||||||
|
47, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set up two quantization tables using the specified scaling */
|
||||||
|
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
|
||||||
|
scale_factor, force_baseline);
|
||||||
|
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
|
||||||
|
scale_factor, force_baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(int)
|
||||||
|
jpeg_quality_scaling (int quality)
|
||||||
|
/* Convert a user-specified quality rating to a percentage scaling factor
|
||||||
|
* for an underlying quantization table, using our recommended scaling curve.
|
||||||
|
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
|
||||||
|
if (quality <= 0) quality = 1;
|
||||||
|
if (quality > 100) quality = 100;
|
||||||
|
|
||||||
|
/* The basic table is used as-is (scaling 100) for a quality of 50.
|
||||||
|
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
|
||||||
|
* note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
|
||||||
|
* to make all the table entries 1 (hence, minimum quantization loss).
|
||||||
|
* Qualities 1..50 are converted to scaling percentage 5000/Q.
|
||||||
|
*/
|
||||||
|
if (quality < 50)
|
||||||
|
quality = 5000 / quality;
|
||||||
|
else
|
||||||
|
quality = 200 - quality*2;
|
||||||
|
|
||||||
|
return quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
|
||||||
|
/* Set or change the 'quality' (quantization) setting, using default tables.
|
||||||
|
* This is the standard quality-adjusting entry point for typical user
|
||||||
|
* interfaces; only those who want detailed control over quantization tables
|
||||||
|
* would use the preceding three routines directly.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Convert user 0-100 rating to percentage scaling */
|
||||||
|
quality = jpeg_quality_scaling(quality);
|
||||||
|
|
||||||
|
/* Set up standard quality tables */
|
||||||
|
jpeg_set_linear_quality(cinfo, quality, force_baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Huffman table setup routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
add_huff_table (j_compress_ptr cinfo,
|
||||||
|
JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
|
||||||
|
/* Define a Huffman table */
|
||||||
|
{
|
||||||
|
int nsymbols, len;
|
||||||
|
|
||||||
|
if (*htblptr == NULL)
|
||||||
|
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Copy the number-of-symbols-of-each-code-length counts */
|
||||||
|
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
|
||||||
|
|
||||||
|
/* Validate the counts. We do this here mainly so we can copy the right
|
||||||
|
* number of symbols from the val[] array, without risking marching off
|
||||||
|
* the end of memory. jchuff.c will do a more thorough test later.
|
||||||
|
*/
|
||||||
|
nsymbols = 0;
|
||||||
|
for (len = 1; len <= 16; len++)
|
||||||
|
nsymbols += bits[len];
|
||||||
|
if (nsymbols < 1 || nsymbols > 256)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||||
|
|
||||||
|
MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
|
||||||
|
|
||||||
|
/* Initialize sent_table FALSE so table will be written to JPEG file. */
|
||||||
|
(*htblptr)->sent_table = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
std_huff_tables (j_compress_ptr cinfo)
|
||||||
|
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
|
||||||
|
/* IMPORTANT: these are only valid for 8-bit data precision! */
|
||||||
|
{
|
||||||
|
static const UINT8 bits_dc_luminance[17] =
|
||||||
|
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
static const UINT8 val_dc_luminance[] =
|
||||||
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||||
|
|
||||||
|
static const UINT8 bits_dc_chrominance[17] =
|
||||||
|
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
|
||||||
|
static const UINT8 val_dc_chrominance[] =
|
||||||
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||||
|
|
||||||
|
static const UINT8 bits_ac_luminance[17] =
|
||||||
|
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
|
||||||
|
static const UINT8 val_ac_luminance[] =
|
||||||
|
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
|
||||||
|
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
|
||||||
|
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
|
||||||
|
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
|
||||||
|
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
|
||||||
|
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
|
||||||
|
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
||||||
|
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
||||||
|
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||||
|
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||||
|
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
||||||
|
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||||
|
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
|
||||||
|
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||||
|
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||||
|
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
|
||||||
|
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
|
||||||
|
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
|
||||||
|
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
|
||||||
|
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||||
|
0xf9, 0xfa };
|
||||||
|
|
||||||
|
static const UINT8 bits_ac_chrominance[17] =
|
||||||
|
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
|
||||||
|
static const UINT8 val_ac_chrominance[] =
|
||||||
|
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
|
||||||
|
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
|
||||||
|
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
|
||||||
|
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
|
||||||
|
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
|
||||||
|
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
|
||||||
|
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
|
||||||
|
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||||
|
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||||
|
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
|
||||||
|
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||||
|
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||||
|
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
|
||||||
|
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||||
|
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
|
||||||
|
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
|
||||||
|
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
|
||||||
|
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
|
||||||
|
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||||
|
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||||
|
0xf9, 0xfa };
|
||||||
|
|
||||||
|
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
|
||||||
|
bits_dc_luminance, val_dc_luminance);
|
||||||
|
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
|
||||||
|
bits_ac_luminance, val_ac_luminance);
|
||||||
|
add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
|
||||||
|
bits_dc_chrominance, val_dc_chrominance);
|
||||||
|
add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
|
||||||
|
bits_ac_chrominance, val_ac_chrominance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default parameter setup for compression.
|
||||||
|
*
|
||||||
|
* Applications that don't choose to use this routine must do their
|
||||||
|
* own setup of all these parameters. Alternately, you can call this
|
||||||
|
* to establish defaults and then alter parameters selectively. This
|
||||||
|
* is the recommended approach since, if we add any new parameters,
|
||||||
|
* your code will still work (they'll be set to reasonable defaults).
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_set_defaults (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* Allocate comp_info array large enough for maximum component count.
|
||||||
|
* Array is made permanent in case application wants to compress
|
||||||
|
* multiple images at same param settings.
|
||||||
|
*/
|
||||||
|
if (cinfo->comp_info == NULL)
|
||||||
|
cinfo->comp_info = (jpeg_component_info *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
MAX_COMPONENTS * SIZEOF(jpeg_component_info));
|
||||||
|
|
||||||
|
/* Initialize everything not dependent on the color space */
|
||||||
|
|
||||||
|
cinfo->data_precision = BITS_IN_JSAMPLE;
|
||||||
|
/* Set up two quantization tables using default quality of 75 */
|
||||||
|
jpeg_set_quality(cinfo, 75, TRUE);
|
||||||
|
/* Set up two Huffman tables */
|
||||||
|
std_huff_tables(cinfo);
|
||||||
|
|
||||||
|
/* Initialize default arithmetic coding conditioning */
|
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++) {
|
||||||
|
cinfo->arith_dc_L[i] = 0;
|
||||||
|
cinfo->arith_dc_U[i] = 1;
|
||||||
|
cinfo->arith_ac_K[i] = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default is no multiple-scan output */
|
||||||
|
cinfo->scan_info = NULL;
|
||||||
|
cinfo->num_scans = 0;
|
||||||
|
|
||||||
|
/* Expect normal source image, not raw downsampled data */
|
||||||
|
cinfo->raw_data_in = FALSE;
|
||||||
|
|
||||||
|
/* Use Huffman coding, not arithmetic coding, by default */
|
||||||
|
cinfo->arith_code = FALSE;
|
||||||
|
|
||||||
|
/* By default, don't do extra passes to optimize entropy coding */
|
||||||
|
cinfo->optimize_coding = FALSE;
|
||||||
|
/* The standard Huffman tables are only valid for 8-bit data precision.
|
||||||
|
* If the precision is higher, force optimization on so that usable
|
||||||
|
* tables will be computed. This test can be removed if default tables
|
||||||
|
* are supplied that are valid for the desired precision.
|
||||||
|
*/
|
||||||
|
if (cinfo->data_precision > 8)
|
||||||
|
cinfo->optimize_coding = TRUE;
|
||||||
|
|
||||||
|
/* By default, use the simpler non-cosited sampling alignment */
|
||||||
|
cinfo->CCIR601_sampling = FALSE;
|
||||||
|
|
||||||
|
/* No input smoothing */
|
||||||
|
cinfo->smoothing_factor = 0;
|
||||||
|
|
||||||
|
/* DCT algorithm preference */
|
||||||
|
cinfo->dct_method = JDCT_DEFAULT;
|
||||||
|
|
||||||
|
/* No restart markers */
|
||||||
|
cinfo->restart_interval = 0;
|
||||||
|
cinfo->restart_in_rows = 0;
|
||||||
|
|
||||||
|
/* Fill in default JFIF marker parameters. Note that whether the marker
|
||||||
|
* will actually be written is determined by jpeg_set_colorspace.
|
||||||
|
*
|
||||||
|
* By default, the library emits JFIF version code 1.01.
|
||||||
|
* An application that wants to emit JFIF 1.02 extension markers should set
|
||||||
|
* JFIF_minor_version to 2. We could probably get away with just defaulting
|
||||||
|
* to 1.02, but there may still be some decoders in use that will complain
|
||||||
|
* about that; saying 1.01 should minimize compatibility problems.
|
||||||
|
*/
|
||||||
|
cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
|
||||||
|
cinfo->JFIF_minor_version = 1;
|
||||||
|
cinfo->density_unit = 0; /* Pixel size is unknown by default */
|
||||||
|
cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
|
||||||
|
cinfo->Y_density = 1;
|
||||||
|
|
||||||
|
/* Choose JPEG colorspace based on input space, set defaults accordingly */
|
||||||
|
|
||||||
|
jpeg_default_colorspace(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select an appropriate JPEG colorspace for in_color_space.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_default_colorspace (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
switch (cinfo->in_color_space) {
|
||||||
|
case JCS_GRAYSCALE:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||||
|
break;
|
||||||
|
case JCS_RGB:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||||
|
break;
|
||||||
|
case JCS_YCbCr:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||||
|
break;
|
||||||
|
case JCS_CMYK:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
|
||||||
|
break;
|
||||||
|
case JCS_YCCK:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_YCCK);
|
||||||
|
break;
|
||||||
|
case JCS_UNKNOWN:
|
||||||
|
jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the JPEG colorspace, and choose colorspace-dependent default values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
|
||||||
|
{
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
|
||||||
|
(compptr = &cinfo->comp_info[index], \
|
||||||
|
compptr->component_id = (id), \
|
||||||
|
compptr->h_samp_factor = (hsamp), \
|
||||||
|
compptr->v_samp_factor = (vsamp), \
|
||||||
|
compptr->quant_tbl_no = (quant), \
|
||||||
|
compptr->dc_tbl_no = (dctbl), \
|
||||||
|
compptr->ac_tbl_no = (actbl) )
|
||||||
|
|
||||||
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* For all colorspaces, we use Q and Huff tables 0 for luminance components,
|
||||||
|
* tables 1 for chrominance components.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cinfo->jpeg_color_space = colorspace;
|
||||||
|
|
||||||
|
cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
|
||||||
|
cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
|
||||||
|
|
||||||
|
switch (colorspace) {
|
||||||
|
case JCS_GRAYSCALE:
|
||||||
|
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
|
||||||
|
cinfo->num_components = 1;
|
||||||
|
/* JFIF specifies component ID 1 */
|
||||||
|
SET_COMP(0, 1, 1,1, 0, 0,0);
|
||||||
|
break;
|
||||||
|
case JCS_RGB:
|
||||||
|
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
|
||||||
|
cinfo->num_components = 3;
|
||||||
|
SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
|
||||||
|
SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
|
||||||
|
SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
|
||||||
|
break;
|
||||||
|
case JCS_YCbCr:
|
||||||
|
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
|
||||||
|
cinfo->num_components = 3;
|
||||||
|
/* JFIF specifies component IDs 1,2,3 */
|
||||||
|
/* We default to 2x2 subsamples of chrominance */
|
||||||
|
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||||
|
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||||
|
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||||
|
break;
|
||||||
|
case JCS_CMYK:
|
||||||
|
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
|
||||||
|
cinfo->num_components = 4;
|
||||||
|
SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
|
||||||
|
SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
|
||||||
|
SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
|
||||||
|
SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
|
||||||
|
break;
|
||||||
|
case JCS_YCCK:
|
||||||
|
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
|
||||||
|
cinfo->num_components = 4;
|
||||||
|
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||||
|
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||||
|
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||||
|
SET_COMP(3, 4, 2,2, 0, 0,0);
|
||||||
|
break;
|
||||||
|
case JCS_UNKNOWN:
|
||||||
|
cinfo->num_components = cinfo->input_components;
|
||||||
|
if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||||
|
MAX_COMPONENTS);
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
SET_COMP(ci, ci, 1,1, 0, 0,0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
|
||||||
|
LOCAL(jpeg_scan_info *)
|
||||||
|
fill_a_scan (jpeg_scan_info * scanptr, int ci,
|
||||||
|
int Ss, int Se, int Ah, int Al)
|
||||||
|
/* Support routine: generate one scan for specified component */
|
||||||
|
{
|
||||||
|
scanptr->comps_in_scan = 1;
|
||||||
|
scanptr->component_index[0] = ci;
|
||||||
|
scanptr->Ss = Ss;
|
||||||
|
scanptr->Se = Se;
|
||||||
|
scanptr->Ah = Ah;
|
||||||
|
scanptr->Al = Al;
|
||||||
|
scanptr++;
|
||||||
|
return scanptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL(jpeg_scan_info *)
|
||||||
|
fill_scans (jpeg_scan_info * scanptr, int ncomps,
|
||||||
|
int Ss, int Se, int Ah, int Al)
|
||||||
|
/* Support routine: generate one scan for each component */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
for (ci = 0; ci < ncomps; ci++) {
|
||||||
|
scanptr->comps_in_scan = 1;
|
||||||
|
scanptr->component_index[0] = ci;
|
||||||
|
scanptr->Ss = Ss;
|
||||||
|
scanptr->Se = Se;
|
||||||
|
scanptr->Ah = Ah;
|
||||||
|
scanptr->Al = Al;
|
||||||
|
scanptr++;
|
||||||
|
}
|
||||||
|
return scanptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL(jpeg_scan_info *)
|
||||||
|
fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
|
||||||
|
/* Support routine: generate interleaved DC scan if possible, else N scans */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
if (ncomps <= MAX_COMPS_IN_SCAN) {
|
||||||
|
/* Single interleaved DC scan */
|
||||||
|
scanptr->comps_in_scan = ncomps;
|
||||||
|
for (ci = 0; ci < ncomps; ci++)
|
||||||
|
scanptr->component_index[ci] = ci;
|
||||||
|
scanptr->Ss = scanptr->Se = 0;
|
||||||
|
scanptr->Ah = Ah;
|
||||||
|
scanptr->Al = Al;
|
||||||
|
scanptr++;
|
||||||
|
} else {
|
||||||
|
/* Noninterleaved DC scan for each component */
|
||||||
|
scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
|
||||||
|
}
|
||||||
|
return scanptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a recommended progressive-JPEG script.
|
||||||
|
* cinfo->num_components and cinfo->jpeg_color_space must be correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_simple_progression (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int ncomps = cinfo->num_components;
|
||||||
|
int nscans;
|
||||||
|
jpeg_scan_info * scanptr;
|
||||||
|
|
||||||
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* Figure space needed for script. Calculation must match code below! */
|
||||||
|
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
|
/* Custom script for YCbCr color images. */
|
||||||
|
nscans = 10;
|
||||||
|
} else {
|
||||||
|
/* All-purpose script for other color spaces. */
|
||||||
|
if (ncomps > MAX_COMPS_IN_SCAN)
|
||||||
|
nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
|
||||||
|
else
|
||||||
|
nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate space for script.
|
||||||
|
* We need to put it in the permanent pool in case the application performs
|
||||||
|
* multiple compressions without changing the settings. To avoid a memory
|
||||||
|
* leak if jpeg_simple_progression is called repeatedly for the same JPEG
|
||||||
|
* object, we try to re-use previously allocated space, and we allocate
|
||||||
|
* enough space to handle YCbCr even if initially asked for grayscale.
|
||||||
|
*/
|
||||||
|
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
|
||||||
|
cinfo->script_space_size = MAX(nscans, 10);
|
||||||
|
cinfo->script_space = (jpeg_scan_info *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
cinfo->script_space_size * SIZEOF(jpeg_scan_info));
|
||||||
|
}
|
||||||
|
scanptr = cinfo->script_space;
|
||||||
|
cinfo->scan_info = scanptr;
|
||||||
|
cinfo->num_scans = nscans;
|
||||||
|
|
||||||
|
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
|
/* Custom script for YCbCr color images. */
|
||||||
|
/* Initial DC scan */
|
||||||
|
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
|
||||||
|
/* Initial AC scan: get some luma data out in a hurry */
|
||||||
|
scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
|
||||||
|
/* Chroma data is too small to be worth expending many scans on */
|
||||||
|
scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
|
||||||
|
scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
|
||||||
|
/* Complete spectral selection for luma AC */
|
||||||
|
scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
|
||||||
|
/* Refine next bit of luma AC */
|
||||||
|
scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
|
||||||
|
/* Finish DC successive approximation */
|
||||||
|
scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
|
||||||
|
/* Finish AC successive approximation */
|
||||||
|
scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
|
||||||
|
scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
|
||||||
|
/* Luma bottom bit comes last since it's usually largest scan */
|
||||||
|
scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
|
||||||
|
} else {
|
||||||
|
/* All-purpose script for other color spaces. */
|
||||||
|
/* Successive approximation first pass */
|
||||||
|
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
|
||||||
|
scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
|
||||||
|
scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
|
||||||
|
/* Successive approximation second pass */
|
||||||
|
scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
|
||||||
|
/* Successive approximation final pass */
|
||||||
|
scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
|
||||||
|
scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* C_PROGRESSIVE_SUPPORTED */
|
||||||
833
jcphuff.c
Normal file
833
jcphuff.c
Normal file
@@ -0,0 +1,833 @@
|
|||||||
|
/*
|
||||||
|
* jcphuff.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995-1997, 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 for progressive JPEG.
|
||||||
|
*
|
||||||
|
* We do not support output suspension in this module, since the library
|
||||||
|
* currently does not allow multiple-scan files to be written with output
|
||||||
|
* suspension.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jchuff.h" /* Declarations shared with jchuff.c */
|
||||||
|
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
|
||||||
|
/* Expanded entropy encoder object for progressive Huffman encoding. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_entropy_encoder pub; /* public fields */
|
||||||
|
|
||||||
|
/* Mode flag: TRUE for optimization, FALSE for actual data output */
|
||||||
|
boolean gather_statistics;
|
||||||
|
|
||||||
|
/* Bit-level coding status.
|
||||||
|
* next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
|
||||||
|
*/
|
||||||
|
JOCTET * next_output_byte; /* => next byte to write in buffer */
|
||||||
|
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
|
||||||
|
INT32 put_buffer; /* current bit-accumulation buffer */
|
||||||
|
int put_bits; /* # of bits now in it */
|
||||||
|
j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */
|
||||||
|
|
||||||
|
/* Coding status for DC components */
|
||||||
|
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||||
|
|
||||||
|
/* Coding status for AC components */
|
||||||
|
int ac_tbl_no; /* the table number of the single component */
|
||||||
|
unsigned int EOBRUN; /* run length of EOBs */
|
||||||
|
unsigned int BE; /* # of buffered correction bits before MCU */
|
||||||
|
char * bit_buffer; /* buffer for correction bits (1 per char) */
|
||||||
|
/* packing correction bits tightly would save some space but cost time... */
|
||||||
|
|
||||||
|
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||||
|
int next_restart_num; /* next restart number to write (0-7) */
|
||||||
|
|
||||||
|
/* Pointers to derived tables (these workspaces have image lifespan).
|
||||||
|
* Since any one scan codes only DC or only AC, we only need one set
|
||||||
|
* of tables, not one for DC and one for AC.
|
||||||
|
*/
|
||||||
|
c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
|
||||||
|
|
||||||
|
/* Statistics tables for optimization; again, one set is enough */
|
||||||
|
long * count_ptrs[NUM_HUFF_TBLS];
|
||||||
|
} phuff_entropy_encoder;
|
||||||
|
|
||||||
|
typedef phuff_entropy_encoder * phuff_entropy_ptr;
|
||||||
|
|
||||||
|
/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
|
||||||
|
* buffer can hold. Larger sizes may slightly improve compression, but
|
||||||
|
* 1000 is already well into the realm of overkill.
|
||||||
|
* The minimum safe size is 64 bits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */
|
||||||
|
|
||||||
|
/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
|
||||||
|
* We assume that int right shift is unsigned if INT32 right shift is,
|
||||||
|
* which should be safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
#define ISHIFT_TEMPS int ishift_temp;
|
||||||
|
#define IRIGHT_SHIFT(x,shft) \
|
||||||
|
((ishift_temp = (x)) < 0 ? \
|
||||||
|
(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
|
||||||
|
(ishift_temp >> (shft)))
|
||||||
|
#else
|
||||||
|
#define ISHIFT_TEMPS
|
||||||
|
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
|
||||||
|
METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a Huffman-compressed scan using progressive JPEG.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
boolean is_DC_band;
|
||||||
|
int ci, tbl;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
entropy->cinfo = cinfo;
|
||||||
|
entropy->gather_statistics = gather_statistics;
|
||||||
|
|
||||||
|
is_DC_band = (cinfo->Ss == 0);
|
||||||
|
|
||||||
|
/* We assume jcmaster.c already validated the scan parameters. */
|
||||||
|
|
||||||
|
/* Select execution routines */
|
||||||
|
if (cinfo->Ah == 0) {
|
||||||
|
if (is_DC_band)
|
||||||
|
entropy->pub.encode_mcu = encode_mcu_DC_first;
|
||||||
|
else
|
||||||
|
entropy->pub.encode_mcu = encode_mcu_AC_first;
|
||||||
|
} else {
|
||||||
|
if (is_DC_band)
|
||||||
|
entropy->pub.encode_mcu = encode_mcu_DC_refine;
|
||||||
|
else {
|
||||||
|
entropy->pub.encode_mcu = encode_mcu_AC_refine;
|
||||||
|
/* AC refinement needs a correction bit buffer */
|
||||||
|
if (entropy->bit_buffer == NULL)
|
||||||
|
entropy->bit_buffer = (char *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
MAX_CORR_BITS * SIZEOF(char));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gather_statistics)
|
||||||
|
entropy->pub.finish_pass = finish_pass_gather_phuff;
|
||||||
|
else
|
||||||
|
entropy->pub.finish_pass = finish_pass_phuff;
|
||||||
|
|
||||||
|
/* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
|
||||||
|
* for AC coefficients.
|
||||||
|
*/
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Initialize DC predictions to 0 */
|
||||||
|
entropy->last_dc_val[ci] = 0;
|
||||||
|
/* Get table index */
|
||||||
|
if (is_DC_band) {
|
||||||
|
if (cinfo->Ah != 0) /* DC refinement needs no table */
|
||||||
|
continue;
|
||||||
|
tbl = compptr->dc_tbl_no;
|
||||||
|
} else {
|
||||||
|
entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
|
||||||
|
}
|
||||||
|
if (gather_statistics) {
|
||||||
|
/* Check for invalid table index */
|
||||||
|
/* (make_c_derived_tbl does this in the other path) */
|
||||||
|
if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
|
||||||
|
/* Allocate and zero the statistics tables */
|
||||||
|
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
|
||||||
|
if (entropy->count_ptrs[tbl] == NULL)
|
||||||
|
entropy->count_ptrs[tbl] = (long *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
257 * SIZEOF(long));
|
||||||
|
MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
|
||||||
|
} else {
|
||||||
|
/* Compute derived values for Huffman table */
|
||||||
|
/* We may do this more than once for a table, but it's not expensive */
|
||||||
|
jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
|
||||||
|
& entropy->derived_tbls[tbl]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize AC stuff */
|
||||||
|
entropy->EOBRUN = 0;
|
||||||
|
entropy->BE = 0;
|
||||||
|
|
||||||
|
/* Initialize bit buffer to empty */
|
||||||
|
entropy->put_buffer = 0;
|
||||||
|
entropy->put_bits = 0;
|
||||||
|
|
||||||
|
/* Initialize restart stuff */
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
entropy->next_restart_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Outputting bytes to the file.
|
||||||
|
* NB: these must be called only when actually outputting,
|
||||||
|
* that is, entropy->gather_statistics == FALSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Emit a byte */
|
||||||
|
#define emit_byte(entropy,val) \
|
||||||
|
{ *(entropy)->next_output_byte++ = (JOCTET) (val); \
|
||||||
|
if (--(entropy)->free_in_buffer == 0) \
|
||||||
|
dump_buffer(entropy); }
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
dump_buffer (phuff_entropy_ptr entropy)
|
||||||
|
/* Empty the output buffer; we do not support suspension in this module. */
|
||||||
|
{
|
||||||
|
struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
|
||||||
|
|
||||||
|
if (! (*dest->empty_output_buffer) (entropy->cinfo))
|
||||||
|
ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
|
||||||
|
/* After a successful buffer dump, must reset buffer pointers */
|
||||||
|
entropy->next_output_byte = dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = dest->free_in_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Outputting bits to the file */
|
||||||
|
|
||||||
|
/* Only the right 24 bits of 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 put_buffer
|
||||||
|
* between calls, so 24 bits are sufficient.
|
||||||
|
*/
|
||||||
|
|
||||||
|
INLINE
|
||||||
|
LOCAL(void)
|
||||||
|
emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
|
||||||
|
/* Emit some bits, unless we are in gather mode */
|
||||||
|
{
|
||||||
|
/* This routine is heavily used, so it's worth coding tightly. */
|
||||||
|
register INT32 put_buffer = (INT32) code;
|
||||||
|
register int put_bits = entropy->put_bits;
|
||||||
|
|
||||||
|
/* if size is 0, caller used an invalid Huffman table entry */
|
||||||
|
if (size == 0)
|
||||||
|
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
|
||||||
|
|
||||||
|
if (entropy->gather_statistics)
|
||||||
|
return; /* do nothing if we're only getting stats */
|
||||||
|
|
||||||
|
put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
|
||||||
|
|
||||||
|
put_bits += size; /* new number of bits in buffer */
|
||||||
|
|
||||||
|
put_buffer <<= 24 - put_bits; /* align incoming bits */
|
||||||
|
|
||||||
|
put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
|
||||||
|
|
||||||
|
while (put_bits >= 8) {
|
||||||
|
int c = (int) ((put_buffer >> 16) & 0xFF);
|
||||||
|
|
||||||
|
emit_byte(entropy, c);
|
||||||
|
if (c == 0xFF) { /* need to stuff a zero byte? */
|
||||||
|
emit_byte(entropy, 0);
|
||||||
|
}
|
||||||
|
put_buffer <<= 8;
|
||||||
|
put_bits -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
entropy->put_buffer = put_buffer; /* update variables */
|
||||||
|
entropy->put_bits = put_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
flush_bits (phuff_entropy_ptr entropy)
|
||||||
|
{
|
||||||
|
emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
|
||||||
|
entropy->put_buffer = 0; /* and reset bit-buffer to empty */
|
||||||
|
entropy->put_bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit (or just count) a Huffman symbol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
INLINE
|
||||||
|
LOCAL(void)
|
||||||
|
emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
|
||||||
|
{
|
||||||
|
if (entropy->gather_statistics)
|
||||||
|
entropy->count_ptrs[tbl_no][symbol]++;
|
||||||
|
else {
|
||||||
|
c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
|
||||||
|
emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit bits from a correction bit buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
|
||||||
|
unsigned int nbits)
|
||||||
|
{
|
||||||
|
if (entropy->gather_statistics)
|
||||||
|
return; /* no real work */
|
||||||
|
|
||||||
|
while (nbits > 0) {
|
||||||
|
emit_bits(entropy, (unsigned int) (*bufstart), 1);
|
||||||
|
bufstart++;
|
||||||
|
nbits--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit any pending EOBRUN symbol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_eobrun (phuff_entropy_ptr entropy)
|
||||||
|
{
|
||||||
|
register int temp, nbits;
|
||||||
|
|
||||||
|
if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
|
||||||
|
temp = entropy->EOBRUN;
|
||||||
|
nbits = 0;
|
||||||
|
while ((temp >>= 1))
|
||||||
|
nbits++;
|
||||||
|
/* safety check: shouldn't happen given limited correction-bit buffer */
|
||||||
|
if (nbits > 14)
|
||||||
|
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
|
||||||
|
|
||||||
|
emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
|
||||||
|
if (nbits)
|
||||||
|
emit_bits(entropy, entropy->EOBRUN, nbits);
|
||||||
|
|
||||||
|
entropy->EOBRUN = 0;
|
||||||
|
|
||||||
|
/* Emit any buffered correction bits */
|
||||||
|
emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
|
||||||
|
entropy->BE = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit a restart marker & resynchronize predictions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
emit_restart (phuff_entropy_ptr entropy, int restart_num)
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
|
||||||
|
if (! entropy->gather_statistics) {
|
||||||
|
flush_bits(entropy);
|
||||||
|
emit_byte(entropy, 0xFF);
|
||||||
|
emit_byte(entropy, JPEG_RST0 + restart_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entropy->cinfo->Ss == 0) {
|
||||||
|
/* Re-initialize DC predictions to 0 */
|
||||||
|
for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
|
||||||
|
entropy->last_dc_val[ci] = 0;
|
||||||
|
} else {
|
||||||
|
/* Re-initialize all AC-related fields to 0 */
|
||||||
|
entropy->EOBRUN = 0;
|
||||||
|
entropy->BE = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for DC initial scan (either spectral selection,
|
||||||
|
* or first pass of successive approximation).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
register int temp, temp2;
|
||||||
|
register int nbits;
|
||||||
|
int blkn, ci;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
JBLOCKROW block;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
ISHIFT_TEMPS
|
||||||
|
|
||||||
|
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||||
|
|
||||||
|
/* Emit restart marker if needed */
|
||||||
|
if (cinfo->restart_interval)
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
emit_restart(entropy, entropy->next_restart_num);
|
||||||
|
|
||||||
|
/* Encode the MCU data blocks */
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
block = MCU_data[blkn];
|
||||||
|
ci = cinfo->MCU_membership[blkn];
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
|
||||||
|
/* Compute the DC value after the required point transform by Al.
|
||||||
|
* This is simply an arithmetic right shift.
|
||||||
|
*/
|
||||||
|
temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
|
||||||
|
|
||||||
|
/* DC differences are figured on the point-transformed values. */
|
||||||
|
temp = temp2 - entropy->last_dc_val[ci];
|
||||||
|
entropy->last_dc_val[ci] = temp2;
|
||||||
|
|
||||||
|
/* Encode the DC coefficient difference per section G.1.2.1 */
|
||||||
|
temp2 = temp;
|
||||||
|
if (temp < 0) {
|
||||||
|
temp = -temp; /* temp is abs value of input */
|
||||||
|
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||||
|
/* This code assumes we are on a two's complement machine */
|
||||||
|
temp2--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||||
|
nbits = 0;
|
||||||
|
while (temp) {
|
||||||
|
nbits++;
|
||||||
|
temp >>= 1;
|
||||||
|
}
|
||||||
|
/* Check for out-of-range coefficient values.
|
||||||
|
* Since we're encoding a difference, the range limit is twice as much.
|
||||||
|
*/
|
||||||
|
if (nbits > MAX_COEF_BITS+1)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||||
|
|
||||||
|
/* Count/emit the Huffman-coded symbol for the number of bits */
|
||||||
|
emit_symbol(entropy, compptr->dc_tbl_no, nbits);
|
||||||
|
|
||||||
|
/* Emit that number of bits of the value, if positive, */
|
||||||
|
/* or the complement of its magnitude, if negative. */
|
||||||
|
if (nbits) /* emit_bits rejects calls with size 0 */
|
||||||
|
emit_bits(entropy, (unsigned int) temp2, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||||
|
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
|
||||||
|
|
||||||
|
/* Update restart-interval state too */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0) {
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
entropy->next_restart_num++;
|
||||||
|
entropy->next_restart_num &= 7;
|
||||||
|
}
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for AC initial scan (either spectral selection,
|
||||||
|
* or first pass of successive approximation).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
register int temp, temp2;
|
||||||
|
register int nbits;
|
||||||
|
register int r, k;
|
||||||
|
int Se = cinfo->Se;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
JBLOCKROW block;
|
||||||
|
|
||||||
|
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||||
|
|
||||||
|
/* Emit restart marker if needed */
|
||||||
|
if (cinfo->restart_interval)
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
emit_restart(entropy, entropy->next_restart_num);
|
||||||
|
|
||||||
|
/* Encode the MCU data block */
|
||||||
|
block = MCU_data[0];
|
||||||
|
|
||||||
|
/* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
|
||||||
|
|
||||||
|
r = 0; /* r = run length of zeros */
|
||||||
|
|
||||||
|
for (k = cinfo->Ss; k <= Se; k++) {
|
||||||
|
if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
|
||||||
|
r++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* We must apply the point transform by Al. For AC coefficients this
|
||||||
|
* is an integer division with rounding towards 0. To do this portably
|
||||||
|
* in C, we shift after obtaining the absolute value; so the code is
|
||||||
|
* interwoven with finding the abs value (temp) and output bits (temp2).
|
||||||
|
*/
|
||||||
|
if (temp < 0) {
|
||||||
|
temp = -temp; /* temp is abs value of input */
|
||||||
|
temp >>= Al; /* apply the point transform */
|
||||||
|
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
|
||||||
|
temp2 = ~temp;
|
||||||
|
} else {
|
||||||
|
temp >>= Al; /* apply the point transform */
|
||||||
|
temp2 = temp;
|
||||||
|
}
|
||||||
|
/* Watch out for case that nonzero coef is zero after point transform */
|
||||||
|
if (temp == 0) {
|
||||||
|
r++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit any pending EOBRUN */
|
||||||
|
if (entropy->EOBRUN > 0)
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||||
|
while (r > 15) {
|
||||||
|
emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
|
||||||
|
r -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||||
|
nbits = 1; /* there must be at least one 1 bit */
|
||||||
|
while ((temp >>= 1))
|
||||||
|
nbits++;
|
||||||
|
/* Check for out-of-range coefficient values */
|
||||||
|
if (nbits > MAX_COEF_BITS)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||||
|
|
||||||
|
/* Count/emit Huffman symbol for run length / number of bits */
|
||||||
|
emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
|
||||||
|
|
||||||
|
/* Emit that number of bits of the value, if positive, */
|
||||||
|
/* or the complement of its magnitude, if negative. */
|
||||||
|
emit_bits(entropy, (unsigned int) temp2, nbits);
|
||||||
|
|
||||||
|
r = 0; /* reset zero run length */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r > 0) { /* If there are trailing zeroes, */
|
||||||
|
entropy->EOBRUN++; /* count an EOB */
|
||||||
|
if (entropy->EOBRUN == 0x7FFF)
|
||||||
|
emit_eobrun(entropy); /* force it out to avoid overflow */
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||||
|
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
|
||||||
|
|
||||||
|
/* Update restart-interval state too */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0) {
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
entropy->next_restart_num++;
|
||||||
|
entropy->next_restart_num &= 7;
|
||||||
|
}
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for DC successive approximation refinement scan.
|
||||||
|
* Note: we assume such scans can be multi-component, although the spec
|
||||||
|
* is not very clear on the point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
register int temp;
|
||||||
|
int blkn;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
JBLOCKROW block;
|
||||||
|
|
||||||
|
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||||
|
|
||||||
|
/* Emit restart marker if needed */
|
||||||
|
if (cinfo->restart_interval)
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
emit_restart(entropy, entropy->next_restart_num);
|
||||||
|
|
||||||
|
/* Encode the MCU data blocks */
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
block = MCU_data[blkn];
|
||||||
|
|
||||||
|
/* We simply emit the Al'th bit of the DC coefficient value. */
|
||||||
|
temp = (*block)[0];
|
||||||
|
emit_bits(entropy, (unsigned int) (temp >> Al), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||||
|
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
|
||||||
|
|
||||||
|
/* Update restart-interval state too */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0) {
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
entropy->next_restart_num++;
|
||||||
|
entropy->next_restart_num &= 7;
|
||||||
|
}
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for AC successive approximation refinement scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
register int temp;
|
||||||
|
register int r, k;
|
||||||
|
int EOB;
|
||||||
|
char *BR_buffer;
|
||||||
|
unsigned int BR;
|
||||||
|
int Se = cinfo->Se;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
JBLOCKROW block;
|
||||||
|
int absvalues[DCTSIZE2];
|
||||||
|
|
||||||
|
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||||
|
|
||||||
|
/* Emit restart marker if needed */
|
||||||
|
if (cinfo->restart_interval)
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
emit_restart(entropy, entropy->next_restart_num);
|
||||||
|
|
||||||
|
/* Encode the MCU data block */
|
||||||
|
block = MCU_data[0];
|
||||||
|
|
||||||
|
/* It is convenient to make a pre-pass to determine the transformed
|
||||||
|
* coefficients' absolute values and the EOB position.
|
||||||
|
*/
|
||||||
|
EOB = 0;
|
||||||
|
for (k = cinfo->Ss; k <= Se; k++) {
|
||||||
|
temp = (*block)[jpeg_natural_order[k]];
|
||||||
|
/* We must apply the point transform by Al. For AC coefficients this
|
||||||
|
* is an integer division with rounding towards 0. To do this portably
|
||||||
|
* in C, we shift after obtaining the absolute value.
|
||||||
|
*/
|
||||||
|
if (temp < 0)
|
||||||
|
temp = -temp; /* temp is abs value of input */
|
||||||
|
temp >>= Al; /* apply the point transform */
|
||||||
|
absvalues[k] = temp; /* save abs value for main pass */
|
||||||
|
if (temp == 1)
|
||||||
|
EOB = k; /* EOB = index of last newly-nonzero coef */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
|
||||||
|
|
||||||
|
r = 0; /* r = run length of zeros */
|
||||||
|
BR = 0; /* BR = count of buffered bits added now */
|
||||||
|
BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
|
||||||
|
|
||||||
|
for (k = cinfo->Ss; k <= Se; k++) {
|
||||||
|
if ((temp = absvalues[k]) == 0) {
|
||||||
|
r++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit any required ZRLs, but not if they can be folded into EOB */
|
||||||
|
while (r > 15 && k <= EOB) {
|
||||||
|
/* emit any pending EOBRUN and the BE correction bits */
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
/* Emit ZRL */
|
||||||
|
emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
|
||||||
|
r -= 16;
|
||||||
|
/* Emit buffered correction bits that must be associated with ZRL */
|
||||||
|
emit_buffered_bits(entropy, BR_buffer, BR);
|
||||||
|
BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
|
||||||
|
BR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the coef was previously nonzero, it only needs a correction bit.
|
||||||
|
* NOTE: a straight translation of the spec's figure G.7 would suggest
|
||||||
|
* that we also need to test r > 15. But if r > 15, we can only get here
|
||||||
|
* if k > EOB, which implies that this coefficient is not 1.
|
||||||
|
*/
|
||||||
|
if (temp > 1) {
|
||||||
|
/* The correction bit is the next bit of the absolute value. */
|
||||||
|
BR_buffer[BR++] = (char) (temp & 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit any pending EOBRUN and the BE correction bits */
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
|
||||||
|
/* Count/emit Huffman symbol for run length / number of bits */
|
||||||
|
emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
|
||||||
|
|
||||||
|
/* Emit output bit for newly-nonzero coef */
|
||||||
|
temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
|
||||||
|
emit_bits(entropy, (unsigned int) temp, 1);
|
||||||
|
|
||||||
|
/* Emit buffered correction bits that must be associated with this code */
|
||||||
|
emit_buffered_bits(entropy, BR_buffer, BR);
|
||||||
|
BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
|
||||||
|
BR = 0;
|
||||||
|
r = 0; /* reset zero run length */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
|
||||||
|
entropy->EOBRUN++; /* count an EOB */
|
||||||
|
entropy->BE += BR; /* concat my correction bits to older ones */
|
||||||
|
/* We force out the EOB if we risk either:
|
||||||
|
* 1. overflow of the EOB counter;
|
||||||
|
* 2. overflow of the correction bit buffer during the next MCU.
|
||||||
|
*/
|
||||||
|
if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||||
|
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
|
||||||
|
|
||||||
|
/* Update restart-interval state too */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0) {
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
entropy->next_restart_num++;
|
||||||
|
entropy->next_restart_num &= 7;
|
||||||
|
}
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up at the end of a Huffman-compressed progressive scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
finish_pass_phuff (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
|
||||||
|
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||||
|
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||||
|
|
||||||
|
/* Flush out any buffered data */
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
flush_bits(entropy);
|
||||||
|
|
||||||
|
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||||
|
cinfo->dest->free_in_buffer = entropy->free_in_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up a statistics-gathering pass and create the new Huffman tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
finish_pass_gather_phuff (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
boolean is_DC_band;
|
||||||
|
int ci, tbl;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
JHUFF_TBL **htblptr;
|
||||||
|
boolean did[NUM_HUFF_TBLS];
|
||||||
|
|
||||||
|
/* Flush out buffered data (all we care about is counting the EOB symbol) */
|
||||||
|
emit_eobrun(entropy);
|
||||||
|
|
||||||
|
is_DC_band = (cinfo->Ss == 0);
|
||||||
|
|
||||||
|
/* It's important not to apply jpeg_gen_optimal_table more than once
|
||||||
|
* per table, because it clobbers the input frequency counts!
|
||||||
|
*/
|
||||||
|
MEMZERO(did, SIZEOF(did));
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
if (is_DC_band) {
|
||||||
|
if (cinfo->Ah != 0) /* DC refinement needs no table */
|
||||||
|
continue;
|
||||||
|
tbl = compptr->dc_tbl_no;
|
||||||
|
} else {
|
||||||
|
tbl = compptr->ac_tbl_no;
|
||||||
|
}
|
||||||
|
if (! did[tbl]) {
|
||||||
|
if (is_DC_band)
|
||||||
|
htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
|
||||||
|
else
|
||||||
|
htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
|
||||||
|
if (*htblptr == NULL)
|
||||||
|
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||||
|
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
|
||||||
|
did[tbl] = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for progressive Huffman entropy encoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_phuff_encoder (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
entropy = (phuff_entropy_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(phuff_entropy_encoder));
|
||||||
|
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
|
||||||
|
entropy->pub.start_pass = start_pass_phuff;
|
||||||
|
|
||||||
|
/* Mark tables unallocated */
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
entropy->derived_tbls[i] = NULL;
|
||||||
|
entropy->count_ptrs[i] = NULL;
|
||||||
|
}
|
||||||
|
entropy->bit_buffer = NULL; /* needed only in AC refinement scan */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* C_PROGRESSIVE_SUPPORTED */
|
||||||
717
jcpipe.c
717
jcpipe.c
@@ -1,717 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ((int) (65500 / SIZEOF(JBLOCK))) /* max blocks/row */
|
|
||||||
|
|
||||||
static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
|
|
||||||
static int MCUs_in_big_row; /* # of MCUs in each row of whole_scan_MCUs */
|
|
||||||
static long next_whole_row; /* next row to access in whole_scan_MCUs */
|
|
||||||
static int next_MCU_index; /* next MCU in current row */
|
|
||||||
|
|
||||||
|
|
||||||
METHODDEF void
|
|
||||||
MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
|
|
||||||
/* Output method for siphoning off extract_MCUs output into a big array */
|
|
||||||
{
|
|
||||||
static JBLOCKARRAY rowptr;
|
|
||||||
|
|
||||||
if (next_MCU_index >= MCUs_in_big_row) {
|
|
||||||
rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
|
|
||||||
next_whole_row, TRUE);
|
|
||||||
next_whole_row++;
|
|
||||||
next_MCU_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* note that on 80x86, the cast applied to MCU_data implies
|
|
||||||
* near to far pointer conversion.
|
|
||||||
*/
|
|
||||||
jcopy_block_row((JBLOCKROW) MCU_data,
|
|
||||||
rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
|
|
||||||
(long) cinfo->blocks_in_MCU);
|
|
||||||
next_MCU_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
METHODDEF void
|
|
||||||
dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
|
|
||||||
/* Dump the MCUs saved in whole_scan_MCUs to the output method. */
|
|
||||||
/* The method may be either the entropy encoder or some routine supplied */
|
|
||||||
/* by the entropy optimizer. */
|
|
||||||
{
|
|
||||||
/* On an 80x86 machine, the entropy encoder expects the passed data block
|
|
||||||
* to be in NEAR memory (for performance reasons), so we have to copy it
|
|
||||||
* back from the big array to a local array. On less brain-damaged CPUs
|
|
||||||
* we needn't do that.
|
|
||||||
*/
|
|
||||||
#ifdef NEED_FAR_POINTERS
|
|
||||||
JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
|
|
||||||
#endif
|
|
||||||
long mcurow, mcuindex, next_row;
|
|
||||||
int next_index;
|
|
||||||
JBLOCKARRAY rowptr = NULL; /* init only to suppress compiler complaint */
|
|
||||||
|
|
||||||
next_row = 0;
|
|
||||||
next_index = MCUs_in_big_row;
|
|
||||||
|
|
||||||
for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
|
|
||||||
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 = (int) MIN((long) rows_in_mem,
|
|
||||||
cinfo->image_height - cur_pixel_row);
|
|
||||||
|
|
||||||
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
|
|
||||||
fullsize_data[whichss]);
|
|
||||||
(*cinfo->methods->edge_expand) (cinfo,
|
|
||||||
cinfo->image_width, rows_this_time,
|
|
||||||
fullsize_width, rows_in_mem,
|
|
||||||
fullsize_data[whichss]);
|
|
||||||
|
|
||||||
/* Subsample the data (all components) */
|
|
||||||
/* First time through is a special case */
|
|
||||||
|
|
||||||
if (cur_pixel_row) {
|
|
||||||
/* Subsample last row group of previous set */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
|
|
||||||
(short) (DCTSIZE-1));
|
|
||||||
/* and dump the previous set's subsampled data */
|
|
||||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
|
||||||
mcu_rows_per_loop,
|
|
||||||
cinfo->methods->entropy_encode);
|
|
||||||
mcu_rows_output += mcu_rows_per_loop;
|
|
||||||
/* Subsample first row group of this set */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (DCTSIZE+1), (short) 0, (short) 1,
|
|
||||||
(short) 0);
|
|
||||||
} else {
|
|
||||||
/* Subsample first row group with dummy above-context */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (-1), (short) 0, (short) 1,
|
|
||||||
(short) 0);
|
|
||||||
}
|
|
||||||
/* Subsample second through next-to-last row groups of this set */
|
|
||||||
for (i = 1; i <= DCTSIZE-2; i++) {
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (i-1), (short) i, (short) (i+1),
|
|
||||||
(short) i);
|
|
||||||
}
|
|
||||||
} /* end of outer loop */
|
|
||||||
|
|
||||||
/* Subsample the last row group with dummy below-context */
|
|
||||||
/* Note whichss points to last buffer side used */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
|
|
||||||
(short) (DCTSIZE-1));
|
|
||||||
/* Dump the remaining data (may be less than full height if uninterleaved) */
|
|
||||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
|
||||||
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
|
|
||||||
cinfo->methods->entropy_encode);
|
|
||||||
|
|
||||||
/* Finish output file */
|
|
||||||
(*cinfo->methods->extract_term) (cinfo);
|
|
||||||
(*cinfo->methods->subsample_term) (cinfo);
|
|
||||||
(*cinfo->methods->entropy_encoder_term) (cinfo);
|
|
||||||
(*cinfo->methods->write_scan_trailer) (cinfo);
|
|
||||||
|
|
||||||
/* 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 = (int) MIN((long) rows_in_mem,
|
|
||||||
cinfo->image_height - cur_pixel_row);
|
|
||||||
|
|
||||||
(*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
|
|
||||||
fullsize_data[whichss]);
|
|
||||||
(*cinfo->methods->edge_expand) (cinfo,
|
|
||||||
cinfo->image_width, rows_this_time,
|
|
||||||
fullsize_width, rows_in_mem,
|
|
||||||
fullsize_data[whichss]);
|
|
||||||
|
|
||||||
/* Subsample the data (all components) */
|
|
||||||
/* First time through is a special case */
|
|
||||||
|
|
||||||
if (cur_pixel_row) {
|
|
||||||
/* Subsample last row group of previous set */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
|
|
||||||
(short) (DCTSIZE-1));
|
|
||||||
/* and dump the previous set's subsampled data */
|
|
||||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
|
||||||
mcu_rows_per_loop,
|
|
||||||
MCU_output_catcher);
|
|
||||||
mcu_rows_output += mcu_rows_per_loop;
|
|
||||||
/* Subsample first row group of this set */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (DCTSIZE+1), (short) 0, (short) 1,
|
|
||||||
(short) 0);
|
|
||||||
} else {
|
|
||||||
/* Subsample first row group with dummy above-context */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (-1), (short) 0, (short) 1,
|
|
||||||
(short) 0);
|
|
||||||
}
|
|
||||||
/* Subsample second through next-to-last row groups of this set */
|
|
||||||
for (i = 1; i <= DCTSIZE-2; i++) {
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (i-1), (short) i, (short) (i+1),
|
|
||||||
(short) i);
|
|
||||||
}
|
|
||||||
} /* end of outer loop */
|
|
||||||
|
|
||||||
/* Subsample the last row group with dummy below-context */
|
|
||||||
/* Note whichss points to last buffer side used */
|
|
||||||
subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
|
|
||||||
(short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
|
|
||||||
(short) (DCTSIZE-1));
|
|
||||||
/* Dump the remaining data (may be less than full height if uninterleaved) */
|
|
||||||
(*cinfo->methods->extract_MCUs) (cinfo, subsampled_data,
|
|
||||||
(int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
|
|
||||||
MCU_output_catcher);
|
|
||||||
|
|
||||||
/* Clean up after that stuff, then find the optimal entropy parameters */
|
|
||||||
|
|
||||||
(*cinfo->methods->extract_term) (cinfo);
|
|
||||||
(*cinfo->methods->subsample_term) (cinfo);
|
|
||||||
|
|
||||||
(*cinfo->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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
354
jcprepct.c
Normal file
354
jcprepct.c
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* jcprepct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains the compression preprocessing controller.
|
||||||
|
* This controller manages the color conversion, downsampling,
|
||||||
|
* and edge expansion steps.
|
||||||
|
*
|
||||||
|
* Most of the complexity here is associated with buffering input rows
|
||||||
|
* as required by the downsampler. See the comments at the head of
|
||||||
|
* jcsample.c for the downsampler's needs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* At present, jcsample.c can request context rows only for smoothing.
|
||||||
|
* In the future, we might also need context rows for CCIR601 sampling
|
||||||
|
* or other more-complex downsampling procedures. The code to support
|
||||||
|
* context rows should be compiled only if needed.
|
||||||
|
*/
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
|
#define CONTEXT_ROWS_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the simple (no-context-row) case, we just need to buffer one
|
||||||
|
* row group's worth of pixels for the downsampling step. At the bottom of
|
||||||
|
* the image, we pad to a full row group by replicating the last pixel row.
|
||||||
|
* The downsampler's last output row is then replicated if needed to pad
|
||||||
|
* out to a full iMCU row.
|
||||||
|
*
|
||||||
|
* When providing context rows, we must buffer three row groups' worth of
|
||||||
|
* pixels. Three row groups are physically allocated, but the row pointer
|
||||||
|
* arrays are made five row groups high, with the extra pointers above and
|
||||||
|
* below "wrapping around" to point to the last and first real row groups.
|
||||||
|
* This allows the downsampler to access the proper context rows.
|
||||||
|
* At the top and bottom of the image, we create dummy context rows by
|
||||||
|
* copying the first or last real pixel row. This copying could be avoided
|
||||||
|
* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
|
||||||
|
* trouble on the compression side.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_c_prep_controller pub; /* public fields */
|
||||||
|
|
||||||
|
/* Downsampling input buffer. This buffer holds color-converted data
|
||||||
|
* until we have enough to do a downsample step.
|
||||||
|
*/
|
||||||
|
JSAMPARRAY color_buf[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
JDIMENSION rows_to_go; /* counts rows remaining in source image */
|
||||||
|
int next_buf_row; /* index of next row to store in color_buf */
|
||||||
|
|
||||||
|
#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
|
||||||
|
int this_row_group; /* starting row index of group to process */
|
||||||
|
int next_buf_stop; /* downsample when we reach this index */
|
||||||
|
#endif
|
||||||
|
} my_prep_controller;
|
||||||
|
|
||||||
|
typedef my_prep_controller * my_prep_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
|
||||||
|
|
||||||
|
if (pass_mode != JBUF_PASS_THRU)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
|
||||||
|
/* Initialize total-height counter for detecting bottom of image */
|
||||||
|
prep->rows_to_go = cinfo->image_height;
|
||||||
|
/* Mark the conversion buffer empty */
|
||||||
|
prep->next_buf_row = 0;
|
||||||
|
#ifdef CONTEXT_ROWS_SUPPORTED
|
||||||
|
/* Preset additional state variables for context mode.
|
||||||
|
* These aren't used in non-context mode, so we needn't test which mode.
|
||||||
|
*/
|
||||||
|
prep->this_row_group = 0;
|
||||||
|
/* Set next_buf_stop to stop after two row groups have been read in. */
|
||||||
|
prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand an image vertically from height input_rows to height output_rows,
|
||||||
|
* by duplicating the bottom row.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
|
||||||
|
int input_rows, int output_rows)
|
||||||
|
{
|
||||||
|
register int row;
|
||||||
|
|
||||||
|
for (row = input_rows; row < output_rows; row++) {
|
||||||
|
jcopy_sample_rows(image_data, input_rows-1, image_data, row,
|
||||||
|
1, num_cols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data in the simple no-context case.
|
||||||
|
*
|
||||||
|
* Preprocessor output data is counted in "row groups". A row group
|
||||||
|
* is defined to be v_samp_factor sample rows of each component.
|
||||||
|
* Downsampling will produce this much data from each max_v_samp_factor
|
||||||
|
* input rows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
pre_process_data (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||||
|
JDIMENSION in_rows_avail,
|
||||||
|
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
|
||||||
|
JDIMENSION out_row_groups_avail)
|
||||||
|
{
|
||||||
|
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
|
||||||
|
int numrows, ci;
|
||||||
|
JDIMENSION inrows;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
while (*in_row_ctr < in_rows_avail &&
|
||||||
|
*out_row_group_ctr < out_row_groups_avail) {
|
||||||
|
/* Do color conversion to fill the conversion buffer. */
|
||||||
|
inrows = in_rows_avail - *in_row_ctr;
|
||||||
|
numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
|
||||||
|
numrows = (int) MIN((JDIMENSION) numrows, inrows);
|
||||||
|
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
|
||||||
|
prep->color_buf,
|
||||||
|
(JDIMENSION) prep->next_buf_row,
|
||||||
|
numrows);
|
||||||
|
*in_row_ctr += numrows;
|
||||||
|
prep->next_buf_row += numrows;
|
||||||
|
prep->rows_to_go -= numrows;
|
||||||
|
/* If at bottom of image, pad to fill the conversion buffer. */
|
||||||
|
if (prep->rows_to_go == 0 &&
|
||||||
|
prep->next_buf_row < cinfo->max_v_samp_factor) {
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
|
||||||
|
prep->next_buf_row, cinfo->max_v_samp_factor);
|
||||||
|
}
|
||||||
|
prep->next_buf_row = cinfo->max_v_samp_factor;
|
||||||
|
}
|
||||||
|
/* If we've filled the conversion buffer, empty it. */
|
||||||
|
if (prep->next_buf_row == cinfo->max_v_samp_factor) {
|
||||||
|
(*cinfo->downsample->downsample) (cinfo,
|
||||||
|
prep->color_buf, (JDIMENSION) 0,
|
||||||
|
output_buf, *out_row_group_ctr);
|
||||||
|
prep->next_buf_row = 0;
|
||||||
|
(*out_row_group_ctr)++;
|
||||||
|
}
|
||||||
|
/* If at bottom of image, pad the output to a full iMCU height.
|
||||||
|
* Note we assume the caller is providing a one-iMCU-height output buffer!
|
||||||
|
*/
|
||||||
|
if (prep->rows_to_go == 0 &&
|
||||||
|
*out_row_group_ctr < out_row_groups_avail) {
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
expand_bottom_edge(output_buf[ci],
|
||||||
|
compptr->width_in_blocks * DCTSIZE,
|
||||||
|
(int) (*out_row_group_ctr * compptr->v_samp_factor),
|
||||||
|
(int) (out_row_groups_avail * compptr->v_samp_factor));
|
||||||
|
}
|
||||||
|
*out_row_group_ctr = out_row_groups_avail;
|
||||||
|
break; /* can exit outer loop without test */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONTEXT_ROWS_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data in the context case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
pre_process_context (j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||||
|
JDIMENSION in_rows_avail,
|
||||||
|
JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
|
||||||
|
JDIMENSION out_row_groups_avail)
|
||||||
|
{
|
||||||
|
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
|
||||||
|
int numrows, ci;
|
||||||
|
int buf_height = cinfo->max_v_samp_factor * 3;
|
||||||
|
JDIMENSION inrows;
|
||||||
|
|
||||||
|
while (*out_row_group_ctr < out_row_groups_avail) {
|
||||||
|
if (*in_row_ctr < in_rows_avail) {
|
||||||
|
/* Do color conversion to fill the conversion buffer. */
|
||||||
|
inrows = in_rows_avail - *in_row_ctr;
|
||||||
|
numrows = prep->next_buf_stop - prep->next_buf_row;
|
||||||
|
numrows = (int) MIN((JDIMENSION) numrows, inrows);
|
||||||
|
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
|
||||||
|
prep->color_buf,
|
||||||
|
(JDIMENSION) prep->next_buf_row,
|
||||||
|
numrows);
|
||||||
|
/* Pad at top of image, if first time through */
|
||||||
|
if (prep->rows_to_go == cinfo->image_height) {
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
int row;
|
||||||
|
for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
|
||||||
|
jcopy_sample_rows(prep->color_buf[ci], 0,
|
||||||
|
prep->color_buf[ci], -row,
|
||||||
|
1, cinfo->image_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*in_row_ctr += numrows;
|
||||||
|
prep->next_buf_row += numrows;
|
||||||
|
prep->rows_to_go -= numrows;
|
||||||
|
} else {
|
||||||
|
/* Return for more data, unless we are at the bottom of the image. */
|
||||||
|
if (prep->rows_to_go != 0)
|
||||||
|
break;
|
||||||
|
/* When at bottom of image, pad to fill the conversion buffer. */
|
||||||
|
if (prep->next_buf_row < prep->next_buf_stop) {
|
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
|
expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
|
||||||
|
prep->next_buf_row, prep->next_buf_stop);
|
||||||
|
}
|
||||||
|
prep->next_buf_row = prep->next_buf_stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If we've gotten enough data, downsample a row group. */
|
||||||
|
if (prep->next_buf_row == prep->next_buf_stop) {
|
||||||
|
(*cinfo->downsample->downsample) (cinfo,
|
||||||
|
prep->color_buf,
|
||||||
|
(JDIMENSION) prep->this_row_group,
|
||||||
|
output_buf, *out_row_group_ctr);
|
||||||
|
(*out_row_group_ctr)++;
|
||||||
|
/* Advance pointers with wraparound as necessary. */
|
||||||
|
prep->this_row_group += cinfo->max_v_samp_factor;
|
||||||
|
if (prep->this_row_group >= buf_height)
|
||||||
|
prep->this_row_group = 0;
|
||||||
|
if (prep->next_buf_row >= buf_height)
|
||||||
|
prep->next_buf_row = 0;
|
||||||
|
prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the wrapped-around downsampling input buffer needed for context mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
create_context_buffer (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
|
||||||
|
int rgroup_height = cinfo->max_v_samp_factor;
|
||||||
|
int ci, i;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
JSAMPARRAY true_buffer, fake_buffer;
|
||||||
|
|
||||||
|
/* Grab enough space for fake row pointers for all the components;
|
||||||
|
* we need five row groups' worth of pointers for each component.
|
||||||
|
*/
|
||||||
|
fake_buffer = (JSAMPARRAY)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(cinfo->num_components * 5 * rgroup_height) *
|
||||||
|
SIZEOF(JSAMPROW));
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Allocate the actual buffer space (3 row groups) for this component.
|
||||||
|
* We make the buffer wide enough to allow the downsampler to edge-expand
|
||||||
|
* horizontally within the buffer, if it so chooses.
|
||||||
|
*/
|
||||||
|
true_buffer = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
|
||||||
|
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||||
|
(JDIMENSION) (3 * rgroup_height));
|
||||||
|
/* Copy true buffer row pointers into the middle of the fake row array */
|
||||||
|
MEMCOPY(fake_buffer + rgroup_height, true_buffer,
|
||||||
|
3 * rgroup_height * SIZEOF(JSAMPROW));
|
||||||
|
/* Fill in the above and below wraparound pointers */
|
||||||
|
for (i = 0; i < rgroup_height; i++) {
|
||||||
|
fake_buffer[i] = true_buffer[2 * rgroup_height + i];
|
||||||
|
fake_buffer[4 * rgroup_height + i] = true_buffer[i];
|
||||||
|
}
|
||||||
|
prep->color_buf[ci] = fake_buffer + rgroup_height;
|
||||||
|
fake_buffer += 5 * rgroup_height; /* point to space for next component */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONTEXT_ROWS_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize preprocessing controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_prep_ptr prep;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
if (need_full_buffer) /* safety check */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
|
||||||
|
prep = (my_prep_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_prep_controller));
|
||||||
|
cinfo->prep = (struct jpeg_c_prep_controller *) prep;
|
||||||
|
prep->pub.start_pass = start_pass_prep;
|
||||||
|
|
||||||
|
/* Allocate the color conversion buffer.
|
||||||
|
* We make the buffer wide enough to allow the downsampler to edge-expand
|
||||||
|
* horizontally within the buffer, if it so chooses.
|
||||||
|
*/
|
||||||
|
if (cinfo->downsample->need_context_rows) {
|
||||||
|
/* Set up to provide context rows */
|
||||||
|
#ifdef CONTEXT_ROWS_SUPPORTED
|
||||||
|
prep->pub.pre_process_data = pre_process_context;
|
||||||
|
create_context_buffer(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* No context, just make it tall enough for one row group */
|
||||||
|
prep->pub.pre_process_data = pre_process_data;
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
|
||||||
|
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||||
|
(JDIMENSION) cinfo->max_v_samp_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
240
jcqnt3dn.asm
Normal file
240
jcqnt3dn.asm
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
;
|
||||||
|
; jcqnt3dn.asm - sample data conversion and quantization (3DNow! & MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 23, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
%ifdef JFDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_flt_3dnow (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_flt_3dnow)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_flt_3dnow):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
pcmpeqw mm7,mm7
|
||||||
|
psllw mm7,7
|
||||||
|
packsswb mm7,mm7 ; mm7 = PB_CENTERJSAMPLE (0x808080..)
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov eax, JDIMENSION [start_col]
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE/2
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq mm0, MMWORD [ebx+eax*SIZEOF_JSAMPLE]
|
||||||
|
movq mm1, MMWORD [edx+eax*SIZEOF_JSAMPLE]
|
||||||
|
|
||||||
|
psubb mm0,mm7 ; mm0=(01234567)
|
||||||
|
psubb mm1,mm7 ; mm1=(89ABCDEF)
|
||||||
|
|
||||||
|
punpcklbw mm2,mm0 ; mm2=(*0*1*2*3)
|
||||||
|
punpckhbw mm0,mm0 ; mm0=(*4*5*6*7)
|
||||||
|
punpcklbw mm3,mm1 ; mm3=(*8*9*A*B)
|
||||||
|
punpckhbw mm1,mm1 ; mm1=(*C*D*E*F)
|
||||||
|
|
||||||
|
punpcklwd mm4,mm2 ; mm4=(***0***1)
|
||||||
|
punpckhwd mm2,mm2 ; mm2=(***2***3)
|
||||||
|
punpcklwd mm5,mm0 ; mm5=(***4***5)
|
||||||
|
punpckhwd mm0,mm0 ; mm0=(***6***7)
|
||||||
|
|
||||||
|
psrad mm4,(DWORD_BIT-BYTE_BIT) ; mm4=(01)
|
||||||
|
psrad mm2,(DWORD_BIT-BYTE_BIT) ; mm2=(23)
|
||||||
|
pi2fd mm4,mm4
|
||||||
|
pi2fd mm2,mm2
|
||||||
|
psrad mm5,(DWORD_BIT-BYTE_BIT) ; mm5=(45)
|
||||||
|
psrad mm0,(DWORD_BIT-BYTE_BIT) ; mm0=(67)
|
||||||
|
pi2fd mm5,mm5
|
||||||
|
pi2fd mm0,mm0
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(0,0,edi,SIZEOF_FAST_FLOAT)], mm4
|
||||||
|
movq MMWORD [MMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], mm2
|
||||||
|
movq MMWORD [MMBLOCK(0,2,edi,SIZEOF_FAST_FLOAT)], mm5
|
||||||
|
movq MMWORD [MMBLOCK(0,3,edi,SIZEOF_FAST_FLOAT)], mm0
|
||||||
|
|
||||||
|
punpcklwd mm6,mm3 ; mm6=(***8***9)
|
||||||
|
punpckhwd mm3,mm3 ; mm3=(***A***B)
|
||||||
|
punpcklwd mm4,mm1 ; mm4=(***C***D)
|
||||||
|
punpckhwd mm1,mm1 ; mm1=(***E***F)
|
||||||
|
|
||||||
|
psrad mm6,(DWORD_BIT-BYTE_BIT) ; mm6=(89)
|
||||||
|
psrad mm3,(DWORD_BIT-BYTE_BIT) ; mm3=(AB)
|
||||||
|
pi2fd mm6,mm6
|
||||||
|
pi2fd mm3,mm3
|
||||||
|
psrad mm4,(DWORD_BIT-BYTE_BIT) ; mm4=(CD)
|
||||||
|
psrad mm1,(DWORD_BIT-BYTE_BIT) ; mm1=(EF)
|
||||||
|
pi2fd mm4,mm4
|
||||||
|
pi2fd mm1,mm1
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(1,0,edi,SIZEOF_FAST_FLOAT)], mm6
|
||||||
|
movq MMWORD [MMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], mm3
|
||||||
|
movq MMWORD [MMBLOCK(1,2,edi,SIZEOF_FAST_FLOAT)], mm4
|
||||||
|
movq MMWORD [MMBLOCK(1,3,edi,SIZEOF_FAST_FLOAT)], mm1
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_JSAMPROW
|
||||||
|
add edi, byte 2*DCTSIZE*SIZEOF_FAST_FLOAT
|
||||||
|
dec ecx
|
||||||
|
jnz near .convloop
|
||||||
|
|
||||||
|
femms ; empty MMX/3DNow! state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_flt_3dnow (JCOEFPTR coef_block, FAST_FLOAT * divisors,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; FAST_FLOAT * divisors
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_flt_3dnow)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_flt_3dnow):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov eax, 0x4B400000 ; (float)0x00C00000 (rndint_magic)
|
||||||
|
movd mm7,eax
|
||||||
|
punpckldq mm7,mm7 ; mm7={12582912.0F 12582912.0F}
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov edx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov eax, DCTSIZE2/16
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
movq mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm1, MMWORD [MMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm1, MMWORD [MMBLOCK(0,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm2, MMWORD [MMBLOCK(0,2,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm3, MMWORD [MMBLOCK(0,3,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm2, MMWORD [MMBLOCK(0,2,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm3, MMWORD [MMBLOCK(0,3,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
|
||||||
|
pfadd mm0,mm7 ; mm0=(00 ** 01 **)
|
||||||
|
pfadd mm1,mm7 ; mm1=(02 ** 03 **)
|
||||||
|
pfadd mm2,mm7 ; mm0=(04 ** 05 **)
|
||||||
|
pfadd mm3,mm7 ; mm1=(06 ** 07 **)
|
||||||
|
|
||||||
|
movq mm4,mm0
|
||||||
|
punpcklwd mm0,mm1 ; mm0=(00 02 ** **)
|
||||||
|
punpckhwd mm4,mm1 ; mm4=(01 03 ** **)
|
||||||
|
movq mm5,mm2
|
||||||
|
punpcklwd mm2,mm3 ; mm2=(04 06 ** **)
|
||||||
|
punpckhwd mm5,mm3 ; mm5=(05 07 ** **)
|
||||||
|
|
||||||
|
punpcklwd mm0,mm4 ; mm0=(00 01 02 03)
|
||||||
|
punpcklwd mm2,mm5 ; mm2=(04 05 06 07)
|
||||||
|
|
||||||
|
movq mm6, MMWORD [MMBLOCK(1,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm1, MMWORD [MMBLOCK(1,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm6, MMWORD [MMBLOCK(1,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm1, MMWORD [MMBLOCK(1,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm3, MMWORD [MMBLOCK(1,2,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movq mm4, MMWORD [MMBLOCK(1,3,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm3, MMWORD [MMBLOCK(1,2,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
pfmul mm4, MMWORD [MMBLOCK(1,3,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
|
||||||
|
pfadd mm6,mm7 ; mm0=(10 ** 11 **)
|
||||||
|
pfadd mm1,mm7 ; mm4=(12 ** 13 **)
|
||||||
|
pfadd mm3,mm7 ; mm0=(14 ** 15 **)
|
||||||
|
pfadd mm4,mm7 ; mm4=(16 ** 17 **)
|
||||||
|
|
||||||
|
movq mm5,mm6
|
||||||
|
punpcklwd mm6,mm1 ; mm6=(10 12 ** **)
|
||||||
|
punpckhwd mm5,mm1 ; mm5=(11 13 ** **)
|
||||||
|
movq mm1,mm3
|
||||||
|
punpcklwd mm3,mm4 ; mm3=(14 16 ** **)
|
||||||
|
punpckhwd mm1,mm4 ; mm1=(15 17 ** **)
|
||||||
|
|
||||||
|
punpcklwd mm6,mm5 ; mm6=(10 11 12 13)
|
||||||
|
punpcklwd mm3,mm1 ; mm3=(14 15 16 17)
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(0,0,edi,SIZEOF_JCOEF)], mm0
|
||||||
|
movq MMWORD [MMBLOCK(0,1,edi,SIZEOF_JCOEF)], mm2
|
||||||
|
movq MMWORD [MMBLOCK(1,0,edi,SIZEOF_JCOEF)], mm6
|
||||||
|
movq MMWORD [MMBLOCK(1,1,edi,SIZEOF_JCOEF)], mm3
|
||||||
|
|
||||||
|
add esi, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edx, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edi, byte 16*SIZEOF_JCOEF
|
||||||
|
dec eax
|
||||||
|
jnz near .quantloop
|
||||||
|
|
||||||
|
femms ; empty MMX/3DNow! state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; unused
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JFDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
%endif ; DCT_FLOAT_SUPPORTED
|
||||||
202
jcqntflt.asm
Normal file
202
jcqntflt.asm
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
;
|
||||||
|
; jcqntflt.asm - sample data conversion and quantization (non-SIMD, FP)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : March 21, 2004
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_float)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_float):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi] ; (JSAMPLE *)
|
||||||
|
add ebx, JDIMENSION [start_col]
|
||||||
|
|
||||||
|
%assign i 0 ; i=0
|
||||||
|
%rep 4 ; -- repeat 4 times ---
|
||||||
|
xor eax,eax
|
||||||
|
xor edx,edx
|
||||||
|
mov al, JSAMPLE [ebx+(i+0)*SIZEOF_JSAMPLE]
|
||||||
|
mov dl, JSAMPLE [ebx+(i+1)*SIZEOF_JSAMPLE]
|
||||||
|
add eax, byte -CENTERJSAMPLE
|
||||||
|
add edx, byte -CENTERJSAMPLE
|
||||||
|
push eax
|
||||||
|
push edx
|
||||||
|
%assign i i+2 ; i+=2
|
||||||
|
%endrep ; -- repeat end ---
|
||||||
|
|
||||||
|
fild INT32 [esp+0*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+1*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+2*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+3*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+4*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+5*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+6*SIZEOF_INT32]
|
||||||
|
fild INT32 [esp+7*SIZEOF_INT32]
|
||||||
|
|
||||||
|
add esp, byte DCTSIZE*SIZEOF_INT32
|
||||||
|
|
||||||
|
fstp FAST_FLOAT [edi+0*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+1*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+2*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+3*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+4*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+5*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+6*SIZEOF_FAST_FLOAT]
|
||||||
|
fstp FAST_FLOAT [edi+7*SIZEOF_FAST_FLOAT]
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
add edi, byte DCTSIZE*SIZEOF_FAST_FLOAT
|
||||||
|
dec ecx
|
||||||
|
jnz near .convloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; FAST_FLOAT * divisors
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
%define FLT_ROUNDS 1 ; from <float.h>
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_float)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_float):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; unused
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
%if (FLT_ROUNDS != 1)
|
||||||
|
push eax
|
||||||
|
fnstcw word [esp]
|
||||||
|
mov eax, [esp]
|
||||||
|
and eax, (~0x0C00) ; round to nearest integer
|
||||||
|
push eax
|
||||||
|
fldcw word [esp]
|
||||||
|
pop eax
|
||||||
|
%endif
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov ebx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov eax, DCTSIZE2/8
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
fld FAST_FLOAT [esi+0*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+0*SIZEOF_FAST_FLOAT]
|
||||||
|
fld FAST_FLOAT [esi+1*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+1*SIZEOF_FAST_FLOAT]
|
||||||
|
fld FAST_FLOAT [esi+2*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+2*SIZEOF_FAST_FLOAT]
|
||||||
|
fld FAST_FLOAT [esi+3*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+3*SIZEOF_FAST_FLOAT]
|
||||||
|
|
||||||
|
fld FAST_FLOAT [esi+4*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+4*SIZEOF_FAST_FLOAT]
|
||||||
|
fxch st0,st1
|
||||||
|
fld FAST_FLOAT [esi+5*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+5*SIZEOF_FAST_FLOAT]
|
||||||
|
fxch st0,st3
|
||||||
|
fld FAST_FLOAT [esi+6*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+6*SIZEOF_FAST_FLOAT]
|
||||||
|
fxch st0,st5
|
||||||
|
fld FAST_FLOAT [esi+7*SIZEOF_FAST_FLOAT]
|
||||||
|
fmul FAST_FLOAT [ebx+7*SIZEOF_FAST_FLOAT]
|
||||||
|
fxch st0,st7
|
||||||
|
|
||||||
|
fistp JCOEF [edi+0*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+1*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+2*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+3*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+4*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+5*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+6*SIZEOF_JCOEF]
|
||||||
|
fistp JCOEF [edi+7*SIZEOF_JCOEF]
|
||||||
|
|
||||||
|
add esi, byte 8*SIZEOF_FAST_FLOAT
|
||||||
|
add ebx, byte 8*SIZEOF_FAST_FLOAT
|
||||||
|
add edi, byte 8*SIZEOF_JCOEF
|
||||||
|
dec eax
|
||||||
|
jnz short .quantloop
|
||||||
|
|
||||||
|
%if (FLT_ROUNDS != 1)
|
||||||
|
fldcw word [esp]
|
||||||
|
pop eax ; pop old control word
|
||||||
|
%endif
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; unused
|
||||||
|
; pop ecx ; unused
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; DCT_FLOAT_SUPPORTED
|
||||||
243
jcqntint.asm
Normal file
243
jcqntint.asm
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
;
|
||||||
|
; jcqntint.asm - sample data conversion and quantization (non-SIMD, integer)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 27, 2005
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_int (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_int)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_int):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi] ; (JSAMPLE *)
|
||||||
|
add ebx, JDIMENSION [start_col]
|
||||||
|
|
||||||
|
%assign i 0 ; i=0
|
||||||
|
%rep 4 ; -- repeat 4 times ---
|
||||||
|
xor eax,eax
|
||||||
|
xor edx,edx
|
||||||
|
mov al, JSAMPLE [ebx+(i+0)*SIZEOF_JSAMPLE]
|
||||||
|
mov dl, JSAMPLE [ebx+(i+1)*SIZEOF_JSAMPLE]
|
||||||
|
add eax, byte -CENTERJSAMPLE
|
||||||
|
add edx, byte -CENTERJSAMPLE
|
||||||
|
mov DCTELEM [edi+(i+0)*SIZEOF_DCTELEM], ax
|
||||||
|
mov DCTELEM [edi+(i+1)*SIZEOF_DCTELEM], dx
|
||||||
|
%assign i i+2 ; i+=2
|
||||||
|
%endrep ; -- repeat end ---
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
add edi, byte DCTSIZE*SIZEOF_DCTELEM
|
||||||
|
dec ecx
|
||||||
|
jnz short .convloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; This implementation is based on an algorithm described in
|
||||||
|
; "How to optimize for the Pentium family of microprocessors"
|
||||||
|
; (http://www.agner.org/assem/).
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_int (JCOEFPTR coef_block, DCTELEM * divisors,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define RECIPROCAL(i,b) ((b)+((i)+DCTSIZE2*0)*SIZEOF_DCTELEM)
|
||||||
|
%define CORRECTION(i,b) ((b)+((i)+DCTSIZE2*1)*SIZEOF_DCTELEM)
|
||||||
|
%define SHIFT(i,b) ((b)+((i)+DCTSIZE2*3)*SIZEOF_DCTELEM)
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; DCTELEM * divisors
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
%define UNROLL 2
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_int)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_int):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov ebx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov ecx, DCTSIZE2/UNROLL
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
%assign i 0 ; i=0;
|
||||||
|
%rep UNROLL ; ---- repeat (UNROLL) times ----
|
||||||
|
mov cx, DCTELEM [esi+(i)*SIZEOF_DCTELEM]
|
||||||
|
mov ax,cx
|
||||||
|
sar cx,(WORD_BIT-1)
|
||||||
|
xor ax,cx ; if (ax < 0) ax = -ax;
|
||||||
|
sub ax,cx
|
||||||
|
add ax, DCTELEM [CORRECTION(i,ebx)] ; correction + roundfactor
|
||||||
|
shl ax,1
|
||||||
|
mul DCTELEM [RECIPROCAL(i,ebx)] ; reciprocal
|
||||||
|
mov ax,cx
|
||||||
|
mov cx, DCTELEM [SHIFT(i,ebx)] ; shift
|
||||||
|
shr dx,cl
|
||||||
|
xor dx,ax
|
||||||
|
sub dx,ax
|
||||||
|
mov JCOEF [edi+(i)*SIZEOF_JCOEF], dx
|
||||||
|
%assign i i+1 ; i++;
|
||||||
|
%endrep ; ---- repeat end ----
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte UNROLL*SIZEOF_DCTELEM
|
||||||
|
add ebx, byte UNROLL*SIZEOF_DCTELEM
|
||||||
|
add edi, byte UNROLL*SIZEOF_JCOEF
|
||||||
|
dec ecx
|
||||||
|
jnz .quantloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%else ; JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_idiv (JCOEFPTR coef_block, DCTELEM * divisors,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; DCTELEM * divisors
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_idiv)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_idiv):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov ebx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov ecx, DCTSIZE2
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
movsx ecx, DCTELEM [esi] ; temp
|
||||||
|
mov eax,ecx
|
||||||
|
sar ecx,(DWORD_BIT-1)
|
||||||
|
xor edx,edx
|
||||||
|
mov dx, DCTELEM [ebx] ; qval
|
||||||
|
xor eax,ecx ; if (eax < 0) eax = -eax;
|
||||||
|
shr edx,1
|
||||||
|
sub eax,ecx
|
||||||
|
cmp eax,edx ; if (temp + qval/2 >= qval)
|
||||||
|
jge short .quant
|
||||||
|
; ---- if the quantized coefficient is zero
|
||||||
|
xor eax,eax
|
||||||
|
jmp short .output
|
||||||
|
alignx 16,7
|
||||||
|
.quant: ; ---- do quantization
|
||||||
|
add eax,edx
|
||||||
|
xor edx,edx
|
||||||
|
div DCTELEM [ebx] ; Q:ax,R:dx
|
||||||
|
xor ax,cx
|
||||||
|
sub ax,cx
|
||||||
|
alignx 16,7
|
||||||
|
.output:
|
||||||
|
mov JCOEF [edi], ax
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_DCTELEM
|
||||||
|
add ebx, byte SIZEOF_DCTELEM
|
||||||
|
add edi, byte SIZEOF_JCOEF
|
||||||
|
dec ecx
|
||||||
|
jnz short .quantloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; !JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
254
jcqntmmx.asm
Normal file
254
jcqntmmx.asm
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
;
|
||||||
|
; jcqntmmx.asm - sample data conversion and quantization (MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 27, 2005
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef JFDCT_INT_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_int_mmx (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_int_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_int_mmx):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
pxor mm6,mm6 ; mm6=(all 0's)
|
||||||
|
pcmpeqw mm7,mm7
|
||||||
|
psllw mm7,7 ; mm7={0xFF80 0xFF80 0xFF80 0xFF80}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov eax, JDIMENSION [start_col]
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE/4
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq mm0, MMWORD [ebx+eax*SIZEOF_JSAMPLE] ; mm0=(01234567)
|
||||||
|
movq mm1, MMWORD [edx+eax*SIZEOF_JSAMPLE] ; mm1=(89ABCDEF)
|
||||||
|
|
||||||
|
mov ebx, JSAMPROW [esi+2*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+3*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq mm2, MMWORD [ebx+eax*SIZEOF_JSAMPLE] ; mm2=(GHIJKLMN)
|
||||||
|
movq mm3, MMWORD [edx+eax*SIZEOF_JSAMPLE] ; mm3=(OPQRSTUV)
|
||||||
|
|
||||||
|
movq mm4,mm0
|
||||||
|
punpcklbw mm0,mm6 ; mm0=(0123)
|
||||||
|
punpckhbw mm4,mm6 ; mm4=(4567)
|
||||||
|
movq mm5,mm1
|
||||||
|
punpcklbw mm1,mm6 ; mm1=(89AB)
|
||||||
|
punpckhbw mm5,mm6 ; mm5=(CDEF)
|
||||||
|
|
||||||
|
paddw mm0,mm7
|
||||||
|
paddw mm4,mm7
|
||||||
|
paddw mm1,mm7
|
||||||
|
paddw mm5,mm7
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(0,0,edi,SIZEOF_DCTELEM)], mm0
|
||||||
|
movq MMWORD [MMBLOCK(0,1,edi,SIZEOF_DCTELEM)], mm4
|
||||||
|
movq MMWORD [MMBLOCK(1,0,edi,SIZEOF_DCTELEM)], mm1
|
||||||
|
movq MMWORD [MMBLOCK(1,1,edi,SIZEOF_DCTELEM)], mm5
|
||||||
|
|
||||||
|
movq mm0,mm2
|
||||||
|
punpcklbw mm2,mm6 ; mm2=(GHIJ)
|
||||||
|
punpckhbw mm0,mm6 ; mm0=(KLMN)
|
||||||
|
movq mm4,mm3
|
||||||
|
punpcklbw mm3,mm6 ; mm3=(OPQR)
|
||||||
|
punpckhbw mm4,mm6 ; mm4=(STUV)
|
||||||
|
|
||||||
|
paddw mm2,mm7
|
||||||
|
paddw mm0,mm7
|
||||||
|
paddw mm3,mm7
|
||||||
|
paddw mm4,mm7
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(2,0,edi,SIZEOF_DCTELEM)], mm2
|
||||||
|
movq MMWORD [MMBLOCK(2,1,edi,SIZEOF_DCTELEM)], mm0
|
||||||
|
movq MMWORD [MMBLOCK(3,0,edi,SIZEOF_DCTELEM)], mm3
|
||||||
|
movq MMWORD [MMBLOCK(3,1,edi,SIZEOF_DCTELEM)], mm4
|
||||||
|
|
||||||
|
add esi, byte 4*SIZEOF_JSAMPROW
|
||||||
|
add edi, byte 4*DCTSIZE*SIZEOF_DCTELEM
|
||||||
|
dec ecx
|
||||||
|
jnz short .convloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; This implementation is based on an algorithm described in
|
||||||
|
; "How to optimize for the Pentium family of microprocessors"
|
||||||
|
; (http://www.agner.org/assem/).
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_int_mmx (JCOEFPTR coef_block, DCTELEM * divisors,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define RECIPROCAL(m,n,b) MMBLOCK(DCTSIZE*0+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
%define CORRECTION(m,n,b) MMBLOCK(DCTSIZE*1+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
%define SCALE(m,n,b) MMBLOCK(DCTSIZE*2+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; DCTELEM * divisors
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_int_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_int_mmx):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov edx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov ah, 2
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop1:
|
||||||
|
mov al, DCTSIZE2/8/2
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop2:
|
||||||
|
movq mm2, MMWORD [MMBLOCK(0,0,esi,SIZEOF_DCTELEM)]
|
||||||
|
movq mm3, MMWORD [MMBLOCK(0,1,esi,SIZEOF_DCTELEM)]
|
||||||
|
movq mm0,mm2
|
||||||
|
movq mm1,mm3
|
||||||
|
psraw mm2,(WORD_BIT-1)
|
||||||
|
psraw mm3,(WORD_BIT-1)
|
||||||
|
pxor mm0,mm2
|
||||||
|
pxor mm1,mm3
|
||||||
|
psubw mm0,mm2 ; if (mm0 < 0) mm0 = -mm0;
|
||||||
|
psubw mm1,mm3 ; if (mm1 < 0) mm1 = -mm1;
|
||||||
|
|
||||||
|
; unsigned long unsigned_multiply(unsigned short x, unsigned short y)
|
||||||
|
; {
|
||||||
|
; enum { SHORT_BIT = 16 };
|
||||||
|
; signed short sx = (signed short) x;
|
||||||
|
; signed short sy = (signed short) y;
|
||||||
|
; signed long sz;
|
||||||
|
;
|
||||||
|
; sz = (long) sx * (long) sy; /* signed multiply */
|
||||||
|
;
|
||||||
|
; if (sx < 0) sz += (long) sy << SHORT_BIT;
|
||||||
|
; if (sy < 0) sz += (long) sx << SHORT_BIT;
|
||||||
|
;
|
||||||
|
; return (unsigned long) sz;
|
||||||
|
; }
|
||||||
|
|
||||||
|
paddw mm0, MMWORD [CORRECTION(0,0,edx)] ; correction + roundfactor
|
||||||
|
paddw mm1, MMWORD [CORRECTION(0,1,edx)]
|
||||||
|
psllw mm0,1
|
||||||
|
psllw mm1,1
|
||||||
|
movq mm4,mm0
|
||||||
|
movq mm5,mm1
|
||||||
|
pmulhw mm0, MMWORD [RECIPROCAL(0,0,edx)] ; reciprocal
|
||||||
|
pmulhw mm1, MMWORD [RECIPROCAL(0,1,edx)]
|
||||||
|
movq mm6, MMWORD [SCALE(0,0,edx)] ; scale
|
||||||
|
movq mm7, MMWORD [SCALE(0,1,edx)]
|
||||||
|
paddw mm0,mm4 ; reciprocal is always negative (MSB=1)
|
||||||
|
paddw mm1,mm5
|
||||||
|
psllw mm0,1
|
||||||
|
psllw mm1,1
|
||||||
|
movq mm4,mm0
|
||||||
|
movq mm5,mm1
|
||||||
|
pmulhw mm0,mm6
|
||||||
|
pmulhw mm1,mm7
|
||||||
|
psraw mm6,(WORD_BIT-1)
|
||||||
|
psraw mm7,(WORD_BIT-1)
|
||||||
|
pand mm6,mm4
|
||||||
|
pand mm7,mm5
|
||||||
|
paddw mm0,mm6
|
||||||
|
paddw mm1,mm7
|
||||||
|
psraw mm4,(WORD_BIT-1)
|
||||||
|
psraw mm5,(WORD_BIT-1)
|
||||||
|
pand mm4, MMWORD [SCALE(0,0,edx)] ; scale
|
||||||
|
pand mm5, MMWORD [SCALE(0,1,edx)]
|
||||||
|
paddw mm0,mm4
|
||||||
|
paddw mm1,mm5
|
||||||
|
|
||||||
|
pxor mm0,mm2
|
||||||
|
pxor mm1,mm3
|
||||||
|
psubw mm0,mm2
|
||||||
|
psubw mm1,mm3
|
||||||
|
movq MMWORD [MMBLOCK(0,0,edi,SIZEOF_DCTELEM)], mm0
|
||||||
|
movq MMWORD [MMBLOCK(0,1,edi,SIZEOF_DCTELEM)], mm1
|
||||||
|
|
||||||
|
add esi, byte 8*SIZEOF_DCTELEM
|
||||||
|
add edx, byte 8*SIZEOF_DCTELEM
|
||||||
|
add edi, byte 8*SIZEOF_JCOEF
|
||||||
|
dec al
|
||||||
|
jnz near .quantloop2
|
||||||
|
dec ah
|
||||||
|
jnz near .quantloop1 ; to avoid branch misprediction
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; unused
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; !JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
%endif ; JFDCT_INT_MMX_SUPPORTED
|
||||||
178
jcqnts2f.asm
Normal file
178
jcqnts2f.asm
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
;
|
||||||
|
; jcqnts2f.asm - sample data conversion and quantization (SSE & SSE2)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 18, 2005
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
%ifdef JFDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_flt_sse2 (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_flt_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_flt_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
pcmpeqw xmm7,xmm7
|
||||||
|
psllw xmm7,7
|
||||||
|
packsswb xmm7,xmm7 ; xmm7 = PB_CENTERJSAMPLE (0x808080..)
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov eax, JDIMENSION [start_col]
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE/2
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq xmm0, _MMWORD [ebx+eax*SIZEOF_JSAMPLE]
|
||||||
|
movq xmm1, _MMWORD [edx+eax*SIZEOF_JSAMPLE]
|
||||||
|
|
||||||
|
psubb xmm0,xmm7 ; xmm0=(01234567)
|
||||||
|
psubb xmm1,xmm7 ; xmm1=(89ABCDEF)
|
||||||
|
|
||||||
|
punpcklbw xmm0,xmm0 ; xmm0=(*0*1*2*3*4*5*6*7)
|
||||||
|
punpcklbw xmm1,xmm1 ; xmm1=(*8*9*A*B*C*D*E*F)
|
||||||
|
|
||||||
|
punpcklwd xmm2,xmm0 ; xmm2=(***0***1***2***3)
|
||||||
|
punpckhwd xmm0,xmm0 ; xmm0=(***4***5***6***7)
|
||||||
|
punpcklwd xmm3,xmm1 ; xmm3=(***8***9***A***B)
|
||||||
|
punpckhwd xmm1,xmm1 ; xmm1=(***C***D***E***F)
|
||||||
|
|
||||||
|
psrad xmm2,(DWORD_BIT-BYTE_BIT) ; xmm2=(0123)
|
||||||
|
psrad xmm0,(DWORD_BIT-BYTE_BIT) ; xmm0=(4567)
|
||||||
|
cvtdq2ps xmm2,xmm2 ; xmm2=(0123)
|
||||||
|
cvtdq2ps xmm0,xmm0 ; xmm0=(4567)
|
||||||
|
psrad xmm3,(DWORD_BIT-BYTE_BIT) ; xmm3=(89AB)
|
||||||
|
psrad xmm1,(DWORD_BIT-BYTE_BIT) ; xmm1=(CDEF)
|
||||||
|
cvtdq2ps xmm3,xmm3 ; xmm3=(89AB)
|
||||||
|
cvtdq2ps xmm1,xmm1 ; xmm1=(CDEF)
|
||||||
|
|
||||||
|
movaps XMMWORD [XMMBLOCK(0,0,edi,SIZEOF_FAST_FLOAT)], xmm2
|
||||||
|
movaps XMMWORD [XMMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], xmm0
|
||||||
|
movaps XMMWORD [XMMBLOCK(1,0,edi,SIZEOF_FAST_FLOAT)], xmm3
|
||||||
|
movaps XMMWORD [XMMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], xmm1
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_JSAMPROW
|
||||||
|
add edi, byte 2*DCTSIZE*SIZEOF_FAST_FLOAT
|
||||||
|
dec ecx
|
||||||
|
jnz short .convloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_flt_sse2 (JCOEFPTR coef_block, FAST_FLOAT * divisors,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; FAST_FLOAT * divisors
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_flt_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_flt_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov edx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov eax, DCTSIZE2/16
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
movaps xmm0, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm1, XMMWORD [XMMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm0, XMMWORD [XMMBLOCK(0,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm1, XMMWORD [XMMBLOCK(0,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm2, XMMWORD [XMMBLOCK(1,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm3, XMMWORD [XMMBLOCK(1,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm2, XMMWORD [XMMBLOCK(1,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm3, XMMWORD [XMMBLOCK(1,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
|
||||||
|
cvtps2dq xmm0,xmm0
|
||||||
|
cvtps2dq xmm1,xmm1
|
||||||
|
cvtps2dq xmm2,xmm2
|
||||||
|
cvtps2dq xmm3,xmm3
|
||||||
|
|
||||||
|
packssdw xmm0,xmm1
|
||||||
|
packssdw xmm2,xmm3
|
||||||
|
|
||||||
|
movdqa XMMWORD [XMMBLOCK(0,0,edi,SIZEOF_JCOEF)], xmm0
|
||||||
|
movdqa XMMWORD [XMMBLOCK(1,0,edi,SIZEOF_JCOEF)], xmm2
|
||||||
|
|
||||||
|
add esi, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edx, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edi, byte 16*SIZEOF_JCOEF
|
||||||
|
dec eax
|
||||||
|
jnz short .quantloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; unused
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JFDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
%endif ; DCT_FLOAT_SUPPORTED
|
||||||
216
jcqnts2i.asm
Normal file
216
jcqnts2i.asm
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
;
|
||||||
|
; jcqnts2i.asm - sample data conversion and quantization (SSE2)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 27, 2005
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef JFDCT_INT_SSE2_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_int_sse2 (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_int_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_int_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
pxor xmm6,xmm6 ; xmm6=(all 0's)
|
||||||
|
pcmpeqw xmm7,xmm7
|
||||||
|
psllw xmm7,7 ; xmm7={0xFF80 0xFF80 0xFF80 0xFF80 ..}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov eax, JDIMENSION [start_col]
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE/4
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq xmm0, _MMWORD [ebx+eax*SIZEOF_JSAMPLE] ; xmm0=(01234567)
|
||||||
|
movq xmm1, _MMWORD [edx+eax*SIZEOF_JSAMPLE] ; xmm1=(89ABCDEF)
|
||||||
|
|
||||||
|
mov ebx, JSAMPROW [esi+2*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+3*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq xmm2, _MMWORD [ebx+eax*SIZEOF_JSAMPLE] ; xmm2=(GHIJKLMN)
|
||||||
|
movq xmm3, _MMWORD [edx+eax*SIZEOF_JSAMPLE] ; xmm3=(OPQRSTUV)
|
||||||
|
|
||||||
|
punpcklbw xmm0,xmm6 ; xmm0=(01234567)
|
||||||
|
punpcklbw xmm1,xmm6 ; xmm1=(89ABCDEF)
|
||||||
|
paddw xmm0,xmm7
|
||||||
|
paddw xmm1,xmm7
|
||||||
|
punpcklbw xmm2,xmm6 ; xmm2=(GHIJKLMN)
|
||||||
|
punpcklbw xmm3,xmm6 ; xmm3=(OPQRSTUV)
|
||||||
|
paddw xmm2,xmm7
|
||||||
|
paddw xmm3,xmm7
|
||||||
|
|
||||||
|
movdqa XMMWORD [XMMBLOCK(0,0,edi,SIZEOF_DCTELEM)], xmm0
|
||||||
|
movdqa XMMWORD [XMMBLOCK(1,0,edi,SIZEOF_DCTELEM)], xmm1
|
||||||
|
movdqa XMMWORD [XMMBLOCK(2,0,edi,SIZEOF_DCTELEM)], xmm2
|
||||||
|
movdqa XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_DCTELEM)], xmm3
|
||||||
|
|
||||||
|
add esi, byte 4*SIZEOF_JSAMPROW
|
||||||
|
add edi, byte 4*DCTSIZE*SIZEOF_DCTELEM
|
||||||
|
dec ecx
|
||||||
|
jnz short .convloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%ifndef JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; This implementation is based on an algorithm described in
|
||||||
|
; "How to optimize for the Pentium family of microprocessors"
|
||||||
|
; (http://www.agner.org/assem/).
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_int_sse2 (JCOEFPTR coef_block, DCTELEM * divisors,
|
||||||
|
; DCTELEM * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define RECIPROCAL(m,n,b) XMMBLOCK(DCTSIZE*0+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
%define CORRECTION(m,n,b) XMMBLOCK(DCTSIZE*1+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
%define SCALE(m,n,b) XMMBLOCK(DCTSIZE*2+(m),(n),(b),SIZEOF_DCTELEM)
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; DCTELEM * divisors
|
||||||
|
%define workspace ebp+16 ; DCTELEM * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_int_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_int_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov edx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov eax, DCTSIZE2/32
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
movdqa xmm4, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_DCTELEM)]
|
||||||
|
movdqa xmm5, XMMWORD [XMMBLOCK(1,0,esi,SIZEOF_DCTELEM)]
|
||||||
|
movdqa xmm6, XMMWORD [XMMBLOCK(2,0,esi,SIZEOF_DCTELEM)]
|
||||||
|
movdqa xmm7, XMMWORD [XMMBLOCK(3,0,esi,SIZEOF_DCTELEM)]
|
||||||
|
movdqa xmm0,xmm4
|
||||||
|
movdqa xmm1,xmm5
|
||||||
|
movdqa xmm2,xmm6
|
||||||
|
movdqa xmm3,xmm7
|
||||||
|
psraw xmm4,(WORD_BIT-1)
|
||||||
|
psraw xmm5,(WORD_BIT-1)
|
||||||
|
psraw xmm6,(WORD_BIT-1)
|
||||||
|
psraw xmm7,(WORD_BIT-1)
|
||||||
|
pxor xmm0,xmm4
|
||||||
|
pxor xmm1,xmm5
|
||||||
|
pxor xmm2,xmm6
|
||||||
|
pxor xmm3,xmm7
|
||||||
|
psubw xmm0,xmm4 ; if (xmm0 < 0) xmm0 = -xmm0;
|
||||||
|
psubw xmm1,xmm5 ; if (xmm1 < 0) xmm1 = -xmm1;
|
||||||
|
psubw xmm2,xmm6 ; if (xmm2 < 0) xmm2 = -xmm2;
|
||||||
|
psubw xmm3,xmm7 ; if (xmm3 < 0) xmm3 = -xmm3;
|
||||||
|
|
||||||
|
paddw xmm0, XMMWORD [CORRECTION(0,0,edx)] ; correction + roundfactor
|
||||||
|
paddw xmm1, XMMWORD [CORRECTION(1,0,edx)]
|
||||||
|
paddw xmm2, XMMWORD [CORRECTION(2,0,edx)]
|
||||||
|
paddw xmm3, XMMWORD [CORRECTION(3,0,edx)]
|
||||||
|
psllw xmm0,1
|
||||||
|
psllw xmm1,1
|
||||||
|
psllw xmm2,1
|
||||||
|
psllw xmm3,1
|
||||||
|
pmulhuw xmm0, XMMWORD [RECIPROCAL(0,0,edx)] ; reciprocal
|
||||||
|
pmulhuw xmm1, XMMWORD [RECIPROCAL(1,0,edx)]
|
||||||
|
pmulhuw xmm2, XMMWORD [RECIPROCAL(2,0,edx)]
|
||||||
|
pmulhuw xmm3, XMMWORD [RECIPROCAL(3,0,edx)]
|
||||||
|
psllw xmm0,1
|
||||||
|
psllw xmm1,1
|
||||||
|
psllw xmm2,1
|
||||||
|
psllw xmm3,1
|
||||||
|
pmulhuw xmm0, XMMWORD [SCALE(0,0,edx)] ; scale
|
||||||
|
pmulhuw xmm1, XMMWORD [SCALE(1,0,edx)]
|
||||||
|
pmulhuw xmm2, XMMWORD [SCALE(2,0,edx)]
|
||||||
|
pmulhuw xmm3, XMMWORD [SCALE(3,0,edx)]
|
||||||
|
|
||||||
|
pxor xmm0,xmm4
|
||||||
|
pxor xmm1,xmm5
|
||||||
|
pxor xmm2,xmm6
|
||||||
|
pxor xmm3,xmm7
|
||||||
|
psubw xmm0,xmm4
|
||||||
|
psubw xmm1,xmm5
|
||||||
|
psubw xmm2,xmm6
|
||||||
|
psubw xmm3,xmm7
|
||||||
|
movdqa XMMWORD [XMMBLOCK(0,0,edi,SIZEOF_DCTELEM)], xmm0
|
||||||
|
movdqa XMMWORD [XMMBLOCK(1,0,edi,SIZEOF_DCTELEM)], xmm1
|
||||||
|
movdqa XMMWORD [XMMBLOCK(2,0,edi,SIZEOF_DCTELEM)], xmm2
|
||||||
|
movdqa XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_DCTELEM)], xmm3
|
||||||
|
|
||||||
|
add esi, byte 32*SIZEOF_DCTELEM
|
||||||
|
add edx, byte 32*SIZEOF_DCTELEM
|
||||||
|
add edi, byte 32*SIZEOF_JCOEF
|
||||||
|
dec eax
|
||||||
|
jnz near .quantloop
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; unused
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; !JFDCT_INT_QUANTIZE_WITH_DIVISION
|
||||||
|
%endif ; JFDCT_INT_SSE2_SUPPORTED
|
||||||
218
jcqntsse.asm
Normal file
218
jcqntsse.asm
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
;
|
||||||
|
; jcqntsse.asm - sample data conversion and quantization (SSE & MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 12, 2005
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jdct.inc"
|
||||||
|
|
||||||
|
%ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
%ifdef JFDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; This module is specialized to the case DCTSIZE = 8.
|
||||||
|
;
|
||||||
|
%if DCTSIZE != 8
|
||||||
|
%error "Sorry, this code only copes with 8x8 DCTs."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Load data into workspace, applying unsigned->signed conversion
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_convsamp_flt_sse (JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define sample_data ebp+8 ; JSAMPARRAY sample_data
|
||||||
|
%define start_col ebp+12 ; JDIMENSION start_col
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_convsamp_flt_sse)
|
||||||
|
|
||||||
|
EXTN(jpeg_convsamp_flt_sse):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
pcmpeqw mm7,mm7
|
||||||
|
psllw mm7,7
|
||||||
|
packsswb mm7,mm7 ; mm7 = PB_CENTERJSAMPLE (0x808080..)
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [sample_data] ; (JSAMPROW *)
|
||||||
|
mov eax, JDIMENSION [start_col]
|
||||||
|
mov edi, POINTER [workspace] ; (DCTELEM *)
|
||||||
|
mov ecx, DCTSIZE/2
|
||||||
|
alignx 16,7
|
||||||
|
.convloop:
|
||||||
|
mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *)
|
||||||
|
|
||||||
|
movq mm0, MMWORD [ebx+eax*SIZEOF_JSAMPLE]
|
||||||
|
movq mm1, MMWORD [edx+eax*SIZEOF_JSAMPLE]
|
||||||
|
|
||||||
|
psubb mm0,mm7 ; mm0=(01234567)
|
||||||
|
psubb mm1,mm7 ; mm1=(89ABCDEF)
|
||||||
|
|
||||||
|
punpcklbw mm2,mm0 ; mm2=(*0*1*2*3)
|
||||||
|
punpckhbw mm0,mm0 ; mm0=(*4*5*6*7)
|
||||||
|
punpcklbw mm3,mm1 ; mm3=(*8*9*A*B)
|
||||||
|
punpckhbw mm1,mm1 ; mm1=(*C*D*E*F)
|
||||||
|
|
||||||
|
punpcklwd mm4,mm2 ; mm4=(***0***1)
|
||||||
|
punpckhwd mm2,mm2 ; mm2=(***2***3)
|
||||||
|
punpcklwd mm5,mm0 ; mm5=(***4***5)
|
||||||
|
punpckhwd mm0,mm0 ; mm0=(***6***7)
|
||||||
|
|
||||||
|
psrad mm4,(DWORD_BIT-BYTE_BIT) ; mm4=(01)
|
||||||
|
psrad mm2,(DWORD_BIT-BYTE_BIT) ; mm2=(23)
|
||||||
|
cvtpi2ps xmm0,mm4 ; xmm0=(01**)
|
||||||
|
cvtpi2ps xmm1,mm2 ; xmm1=(23**)
|
||||||
|
psrad mm5,(DWORD_BIT-BYTE_BIT) ; mm5=(45)
|
||||||
|
psrad mm0,(DWORD_BIT-BYTE_BIT) ; mm0=(67)
|
||||||
|
cvtpi2ps xmm2,mm5 ; xmm2=(45**)
|
||||||
|
cvtpi2ps xmm3,mm0 ; xmm3=(67**)
|
||||||
|
|
||||||
|
punpcklwd mm6,mm3 ; mm6=(***8***9)
|
||||||
|
punpckhwd mm3,mm3 ; mm3=(***A***B)
|
||||||
|
punpcklwd mm4,mm1 ; mm4=(***C***D)
|
||||||
|
punpckhwd mm1,mm1 ; mm1=(***E***F)
|
||||||
|
|
||||||
|
psrad mm6,(DWORD_BIT-BYTE_BIT) ; mm6=(89)
|
||||||
|
psrad mm3,(DWORD_BIT-BYTE_BIT) ; mm3=(AB)
|
||||||
|
cvtpi2ps xmm4,mm6 ; xmm4=(89**)
|
||||||
|
cvtpi2ps xmm5,mm3 ; xmm5=(AB**)
|
||||||
|
psrad mm4,(DWORD_BIT-BYTE_BIT) ; mm4=(CD)
|
||||||
|
psrad mm1,(DWORD_BIT-BYTE_BIT) ; mm1=(EF)
|
||||||
|
cvtpi2ps xmm6,mm4 ; xmm6=(CD**)
|
||||||
|
cvtpi2ps xmm7,mm1 ; xmm7=(EF**)
|
||||||
|
|
||||||
|
movlhps xmm0,xmm1 ; xmm0=(0123)
|
||||||
|
movlhps xmm2,xmm3 ; xmm2=(4567)
|
||||||
|
movlhps xmm4,xmm5 ; xmm4=(89AB)
|
||||||
|
movlhps xmm6,xmm7 ; xmm6=(CDEF)
|
||||||
|
|
||||||
|
movaps XMMWORD [XMMBLOCK(0,0,edi,SIZEOF_FAST_FLOAT)], xmm0
|
||||||
|
movaps XMMWORD [XMMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], xmm2
|
||||||
|
movaps XMMWORD [XMMBLOCK(1,0,edi,SIZEOF_FAST_FLOAT)], xmm4
|
||||||
|
movaps XMMWORD [XMMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], xmm6
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_JSAMPROW
|
||||||
|
add edi, byte 2*DCTSIZE*SIZEOF_FAST_FLOAT
|
||||||
|
dec ecx
|
||||||
|
jnz near .convloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Quantize/descale the coefficients, and store into coef_block
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_quantize_flt_sse (JCOEFPTR coef_block, FAST_FLOAT * divisors,
|
||||||
|
; FAST_FLOAT * workspace);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define coef_block ebp+8 ; JCOEFPTR coef_block
|
||||||
|
%define divisors ebp+12 ; FAST_FLOAT * divisors
|
||||||
|
%define workspace ebp+16 ; FAST_FLOAT * workspace
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_quantize_flt_sse)
|
||||||
|
|
||||||
|
EXTN(jpeg_quantize_flt_sse):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; unused
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov esi, POINTER [workspace]
|
||||||
|
mov edx, POINTER [divisors]
|
||||||
|
mov edi, JCOEFPTR [coef_block]
|
||||||
|
mov eax, DCTSIZE2/16
|
||||||
|
alignx 16,7
|
||||||
|
.quantloop:
|
||||||
|
movaps xmm0, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm1, XMMWORD [XMMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm0, XMMWORD [XMMBLOCK(0,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm1, XMMWORD [XMMBLOCK(0,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm2, XMMWORD [XMMBLOCK(1,0,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
movaps xmm3, XMMWORD [XMMBLOCK(1,1,esi,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm2, XMMWORD [XMMBLOCK(1,0,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
mulps xmm3, XMMWORD [XMMBLOCK(1,1,edx,SIZEOF_FAST_FLOAT)]
|
||||||
|
|
||||||
|
movhlps xmm4,xmm0
|
||||||
|
movhlps xmm5,xmm1
|
||||||
|
|
||||||
|
cvtps2pi mm0,xmm0
|
||||||
|
cvtps2pi mm1,xmm1
|
||||||
|
cvtps2pi mm4,xmm4
|
||||||
|
cvtps2pi mm5,xmm5
|
||||||
|
|
||||||
|
movhlps xmm6,xmm2
|
||||||
|
movhlps xmm7,xmm3
|
||||||
|
|
||||||
|
cvtps2pi mm2,xmm2
|
||||||
|
cvtps2pi mm3,xmm3
|
||||||
|
cvtps2pi mm6,xmm6
|
||||||
|
cvtps2pi mm7,xmm7
|
||||||
|
|
||||||
|
packssdw mm0,mm4
|
||||||
|
packssdw mm1,mm5
|
||||||
|
packssdw mm2,mm6
|
||||||
|
packssdw mm3,mm7
|
||||||
|
|
||||||
|
movq MMWORD [MMBLOCK(0,0,edi,SIZEOF_JCOEF)], mm0
|
||||||
|
movq MMWORD [MMBLOCK(0,1,edi,SIZEOF_JCOEF)], mm1
|
||||||
|
movq MMWORD [MMBLOCK(1,0,edi,SIZEOF_JCOEF)], mm2
|
||||||
|
movq MMWORD [MMBLOCK(1,1,edi,SIZEOF_JCOEF)], mm3
|
||||||
|
|
||||||
|
add esi, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edx, byte 16*SIZEOF_FAST_FLOAT
|
||||||
|
add edi, byte 16*SIZEOF_JCOEF
|
||||||
|
dec eax
|
||||||
|
jnz short .quantloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; unused
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JFDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
%endif ; DCT_FLOAT_SUPPORTED
|
||||||
328
jcsammmx.asm
Normal file
328
jcsammmx.asm
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
;
|
||||||
|
; jcsammmx.asm - downsampling (MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 23, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%ifdef JCSAMPLE_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Downsample pixel values of a single component.
|
||||||
|
; This version handles the common case of 2:1 horizontal and 1:1 vertical,
|
||||||
|
; without smoothing.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_h2v1_downsample_mmx (j_compress_ptr cinfo,
|
||||||
|
; jpeg_component_info * compptr,
|
||||||
|
; JSAMPARRAY input_data, JSAMPARRAY output_data);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define compptr(b) (b)+12 ; jpeg_component_info * compptr
|
||||||
|
%define input_data(b) (b)+16 ; JSAMPARRAY input_data
|
||||||
|
%define output_data(b) (b)+20 ; JSAMPARRAY output_data
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_h2v1_downsample_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_h2v1_downsample_mmx):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov ecx, POINTER [compptr(ebp)]
|
||||||
|
mov ecx, JDIMENSION [jcompinfo_width_in_blocks(ecx)]
|
||||||
|
shl ecx,3 ; imul ecx,DCTSIZE (ecx = output_cols)
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
mov edx, POINTER [cinfo(ebp)]
|
||||||
|
mov edx, JDIMENSION [jcstruct_image_width(edx)]
|
||||||
|
|
||||||
|
; -- expand_right_edge
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
shl ecx,1 ; output_cols * 2
|
||||||
|
sub ecx,edx
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
mov eax, POINTER [cinfo(ebp)]
|
||||||
|
mov eax, INT [jcstruct_max_v_samp_factor(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
cld
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
alignx 16,7
|
||||||
|
.expandloop:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPROW [esi]
|
||||||
|
add edi,edx
|
||||||
|
mov al, JSAMPLE [edi-1]
|
||||||
|
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax
|
||||||
|
jg short .expandloop
|
||||||
|
|
||||||
|
.expand_end:
|
||||||
|
pop ecx ; output_cols
|
||||||
|
|
||||||
|
; -- h2v1_downsample
|
||||||
|
|
||||||
|
mov eax, POINTER [compptr(ebp)]
|
||||||
|
mov eax, JDIMENSION [jcompinfo_v_samp_factor(eax)] ; rowctr
|
||||||
|
test eax,eax
|
||||||
|
jle short .return
|
||||||
|
|
||||||
|
mov edx, 0x00010000 ; bias pattern
|
||||||
|
movd mm7,edx
|
||||||
|
pcmpeqw mm6,mm6
|
||||||
|
punpckldq mm7,mm7 ; mm7={0, 1, 0, 1}
|
||||||
|
psrlw mm6,BYTE_BIT ; mm6={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
mov edi, JSAMPARRAY [output_data(ebp)] ; output_data
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
alignx 16,7
|
||||||
|
.columnloop:
|
||||||
|
|
||||||
|
movq mm0, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mm1, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
movq mm2,mm0
|
||||||
|
movq mm3,mm1
|
||||||
|
|
||||||
|
pand mm0,mm6
|
||||||
|
psrlw mm2,BYTE_BIT
|
||||||
|
pand mm1,mm6
|
||||||
|
psrlw mm3,BYTE_BIT
|
||||||
|
|
||||||
|
paddw mm0,mm2
|
||||||
|
paddw mm1,mm3
|
||||||
|
paddw mm0,mm7
|
||||||
|
paddw mm1,mm7
|
||||||
|
psrlw mm0,1
|
||||||
|
psrlw mm1,1
|
||||||
|
|
||||||
|
packuswb mm0,mm1
|
||||||
|
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mm0
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_MMWORD ; inptr
|
||||||
|
add edi, byte 1*SIZEOF_MMWORD ; outptr
|
||||||
|
sub ecx, byte SIZEOF_MMWORD ; outcol
|
||||||
|
jnz short .columnloop
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW ; input_data
|
||||||
|
add edi, byte SIZEOF_JSAMPROW ; output_data
|
||||||
|
dec eax ; rowctr
|
||||||
|
jg short .rowloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Downsample pixel values of a single component.
|
||||||
|
; This version handles the standard case of 2:1 horizontal and 2:1 vertical,
|
||||||
|
; without smoothing.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_h2v2_downsample_mmx (j_compress_ptr cinfo,
|
||||||
|
; jpeg_component_info * compptr,
|
||||||
|
; JSAMPARRAY input_data, JSAMPARRAY output_data);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define compptr(b) (b)+12 ; jpeg_component_info * compptr
|
||||||
|
%define input_data(b) (b)+16 ; JSAMPARRAY input_data
|
||||||
|
%define output_data(b) (b)+20 ; JSAMPARRAY output_data
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_h2v2_downsample_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_h2v2_downsample_mmx):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov ecx, POINTER [compptr(ebp)]
|
||||||
|
mov ecx, JDIMENSION [jcompinfo_width_in_blocks(ecx)]
|
||||||
|
shl ecx,3 ; imul ecx,DCTSIZE (ecx = output_cols)
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
mov edx, POINTER [cinfo(ebp)]
|
||||||
|
mov edx, JDIMENSION [jcstruct_image_width(edx)]
|
||||||
|
|
||||||
|
; -- expand_right_edge
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
shl ecx,1 ; output_cols * 2
|
||||||
|
sub ecx,edx
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
mov eax, POINTER [cinfo(ebp)]
|
||||||
|
mov eax, INT [jcstruct_max_v_samp_factor(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
cld
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
alignx 16,7
|
||||||
|
.expandloop:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPROW [esi]
|
||||||
|
add edi,edx
|
||||||
|
mov al, JSAMPLE [edi-1]
|
||||||
|
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax
|
||||||
|
jg short .expandloop
|
||||||
|
|
||||||
|
.expand_end:
|
||||||
|
pop ecx ; output_cols
|
||||||
|
|
||||||
|
; -- h2v2_downsample
|
||||||
|
|
||||||
|
mov eax, POINTER [compptr(ebp)]
|
||||||
|
mov eax, JDIMENSION [jcompinfo_v_samp_factor(eax)] ; rowctr
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
|
||||||
|
mov edx, 0x00020001 ; bias pattern
|
||||||
|
movd mm7,edx
|
||||||
|
pcmpeqw mm6,mm6
|
||||||
|
punpckldq mm7,mm7 ; mm7={1, 2, 1, 2}
|
||||||
|
psrlw mm6,BYTE_BIT ; mm6={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
mov edi, JSAMPARRAY [output_data(ebp)] ; output_data
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov edx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; inptr0
|
||||||
|
mov esi, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; inptr1
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
alignx 16,7
|
||||||
|
.columnloop:
|
||||||
|
|
||||||
|
movq mm0, MMWORD [edx+0*SIZEOF_MMWORD]
|
||||||
|
movq mm1, MMWORD [esi+0*SIZEOF_MMWORD]
|
||||||
|
movq mm2, MMWORD [edx+1*SIZEOF_MMWORD]
|
||||||
|
movq mm3, MMWORD [esi+1*SIZEOF_MMWORD]
|
||||||
|
|
||||||
|
movq mm4,mm0
|
||||||
|
movq mm5,mm1
|
||||||
|
pand mm0,mm6
|
||||||
|
psrlw mm4,BYTE_BIT
|
||||||
|
pand mm1,mm6
|
||||||
|
psrlw mm5,BYTE_BIT
|
||||||
|
paddw mm0,mm4
|
||||||
|
paddw mm1,mm5
|
||||||
|
|
||||||
|
movq mm4,mm2
|
||||||
|
movq mm5,mm3
|
||||||
|
pand mm2,mm6
|
||||||
|
psrlw mm4,BYTE_BIT
|
||||||
|
pand mm3,mm6
|
||||||
|
psrlw mm5,BYTE_BIT
|
||||||
|
paddw mm2,mm4
|
||||||
|
paddw mm3,mm5
|
||||||
|
|
||||||
|
paddw mm0,mm1
|
||||||
|
paddw mm2,mm3
|
||||||
|
paddw mm0,mm7
|
||||||
|
paddw mm2,mm7
|
||||||
|
psrlw mm0,2
|
||||||
|
psrlw mm2,2
|
||||||
|
|
||||||
|
packuswb mm0,mm2
|
||||||
|
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mm0
|
||||||
|
|
||||||
|
add edx, byte 2*SIZEOF_MMWORD ; inptr0
|
||||||
|
add esi, byte 2*SIZEOF_MMWORD ; inptr1
|
||||||
|
add edi, byte 1*SIZEOF_MMWORD ; outptr
|
||||||
|
sub ecx, byte SIZEOF_MMWORD ; outcol
|
||||||
|
jnz near .columnloop
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_JSAMPROW ; input_data
|
||||||
|
add edi, byte 1*SIZEOF_JSAMPROW ; output_data
|
||||||
|
dec eax ; rowctr
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JCSAMPLE_MMX_SUPPORTED
|
||||||
555
jcsample.c
555
jcsample.c
@@ -1,67 +1,179 @@
|
|||||||
/*
|
/*
|
||||||
* jcsample.c
|
* jcsample.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, Thomas G. Lane.
|
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||||
* This file is part of the Independent JPEG Group's software.
|
* This file is part of the Independent JPEG Group's software.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains subsampling routines.
|
* ---------------------------------------------------------------------
|
||||||
* These routines are invoked via the subsample and
|
* x86 SIMD extension for IJG JPEG library
|
||||||
* subsample_init/term methods.
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 5, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains downsampling routines.
|
||||||
|
*
|
||||||
|
* Downsampling input data is counted in "row groups". A row group
|
||||||
|
* is defined to be max_v_samp_factor pixel rows of each component,
|
||||||
|
* from which the downsampler produces v_samp_factor sample rows.
|
||||||
|
* A single row group is processed in each call to the downsampler module.
|
||||||
|
*
|
||||||
|
* The downsampler is responsible for edge-expansion of its output data
|
||||||
|
* to fill an integral number of DCT blocks horizontally. The source buffer
|
||||||
|
* may be modified if it is helpful for this purpose (the source buffer is
|
||||||
|
* allocated wide enough to correspond to the desired output width).
|
||||||
|
* The caller (the prep controller) is responsible for vertical padding.
|
||||||
|
*
|
||||||
|
* The downsampler may request "context rows" by setting need_context_rows
|
||||||
|
* during startup. In this case, the input arrays will contain at least
|
||||||
|
* one row group's worth of pixels above and below the passed-in data;
|
||||||
|
* the caller will create dummy rows at image top and bottom by replicating
|
||||||
|
* the first or last real pixel row.
|
||||||
|
*
|
||||||
|
* An excellent reference for image resampling is
|
||||||
|
* Digital Image Warping, George Wolberg, 1990.
|
||||||
|
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
|
||||||
|
*
|
||||||
|
* The downsampling algorithm used here is a simple average of the source
|
||||||
|
* pixels covered by the output pixel. The hi-falutin sampling literature
|
||||||
|
* refers to this as a "box filter". In general the characteristics of a box
|
||||||
|
* filter are not very good, but for the specific cases we normally use (1:1
|
||||||
|
* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
|
||||||
|
* nearly so bad. If you intend to use other sampling ratios, you'd be well
|
||||||
|
* advised to improve this code.
|
||||||
|
*
|
||||||
|
* A simple input-smoothing capability is provided. This is mainly intended
|
||||||
|
* for cleaning up color-dithered GIF input files (if you find it inadequate,
|
||||||
|
* we suggest using an external filtering program such as pnmconvol). When
|
||||||
|
* enabled, each input pixel P is replaced by a weighted sum of itself and its
|
||||||
|
* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
|
||||||
|
* where SF = (smoothing_factor / 1024).
|
||||||
|
* Currently, smoothing is only supported for 2h2v sampling factors.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jcolsamp.h" /* Private declarations */
|
||||||
|
|
||||||
|
|
||||||
|
/* Pointer to routine to downsample a single component */
|
||||||
|
typedef JMETHOD(void, downsample1_ptr,
|
||||||
|
(j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data));
|
||||||
|
|
||||||
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_downsampler pub; /* public fields */
|
||||||
|
|
||||||
|
/* Downsampling method pointers, one per component */
|
||||||
|
downsample1_ptr methods[MAX_COMPONENTS];
|
||||||
|
} my_downsampler;
|
||||||
|
|
||||||
|
typedef my_downsampler * my_downsample_ptr;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize for subsampling a scan.
|
* Initialize for a downsampling pass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
subsample_init (compress_info_ptr cinfo)
|
start_pass_downsample (j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
/* no work for now */
|
/* no work for now */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Subsample pixel values of a single component.
|
* Expand a component horizontally from width input_cols to width output_cols,
|
||||||
* This version only handles integral sampling ratios.
|
* by duplicating the rightmost samples.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
LOCAL(void)
|
||||||
subsample (compress_info_ptr cinfo, int which_component,
|
expand_right_edge (JSAMPARRAY image_data, int num_rows,
|
||||||
long input_cols, int input_rows,
|
JDIMENSION input_cols, JDIMENSION output_cols)
|
||||||
long output_cols, int output_rows,
|
{
|
||||||
JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
|
register JSAMPROW ptr;
|
||||||
JSAMPARRAY output_data)
|
register JSAMPLE pixval;
|
||||||
|
register int count;
|
||||||
|
int row;
|
||||||
|
int numcols = (int) (output_cols - input_cols);
|
||||||
|
|
||||||
|
if (numcols > 0) {
|
||||||
|
for (row = 0; row < num_rows; row++) {
|
||||||
|
ptr = image_data[row] + input_cols;
|
||||||
|
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
|
||||||
|
for (count = numcols; count > 0; count--)
|
||||||
|
*ptr++ = pixval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do downsampling for a whole row group (all components).
|
||||||
|
*
|
||||||
|
* In this version we simply downsample each component independently.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
sep_downsample (j_compress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
|
||||||
|
JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
|
||||||
|
{
|
||||||
|
my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
JSAMPARRAY in_ptr, out_ptr;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
in_ptr = input_buf[ci] + in_row_index;
|
||||||
|
out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
|
||||||
|
(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Downsample pixel values of a single component.
|
||||||
|
* One row group is processed per call.
|
||||||
|
* This version handles arbitrary integral sampling ratios, without smoothing.
|
||||||
|
* Note that this version is not actually used for customary sampling ratios.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
{
|
{
|
||||||
jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
|
|
||||||
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
|
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
|
||||||
long outcol;
|
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
|
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||||
JSAMPROW inptr, outptr;
|
JSAMPROW inptr, outptr;
|
||||||
INT32 outvalue;
|
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;
|
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
|
||||||
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
|
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
|
||||||
numpix = h_expand * v_expand;
|
numpix = h_expand * v_expand;
|
||||||
numpix2 = numpix/2;
|
numpix2 = numpix/2;
|
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more
|
||||||
|
* efficient.
|
||||||
|
*/
|
||||||
|
expand_right_edge(input_data, cinfo->max_v_samp_factor,
|
||||||
|
cinfo->image_width, output_cols * h_expand);
|
||||||
|
|
||||||
inrow = 0;
|
inrow = 0;
|
||||||
for (outrow = 0; outrow < output_rows; outrow++) {
|
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
|
||||||
outptr = output_data[outrow];
|
outptr = output_data[outrow];
|
||||||
for (outcol = 0; outcol < output_cols; outcol++) {
|
for (outcol = 0, outcol_h = 0; outcol < output_cols;
|
||||||
|
outcol++, outcol_h += h_expand) {
|
||||||
outvalue = 0;
|
outvalue = 0;
|
||||||
for (v = 0; v < v_expand; v++) {
|
for (v = 0; v < v_expand; v++) {
|
||||||
inptr = input_data[inrow+v] + (outcol*h_expand);
|
inptr = input_data[inrow+v] + outcol_h;
|
||||||
for (h = 0; h < h_expand; h++) {
|
for (h = 0; h < h_expand; h++) {
|
||||||
outvalue += (INT32) GETJSAMPLE(*inptr++);
|
outvalue += (INT32) GETJSAMPLE(*inptr++);
|
||||||
}
|
}
|
||||||
@@ -74,62 +186,385 @@ subsample (compress_info_ptr cinfo, int which_component,
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Subsample pixel values of a single component.
|
* Downsample pixel values of a single component.
|
||||||
* This version handles the special case of a full-size component.
|
* This version handles the special case of a full-size component,
|
||||||
|
* without smoothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
fullsize_subsample (compress_info_ptr cinfo, int which_component,
|
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
long input_cols, int input_rows,
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
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 */
|
/* Copy the data */
|
||||||
ERREXIT(cinfo->emethods, "Pipeline controller messed up");
|
jcopy_sample_rows(input_data, 0, output_data, 0,
|
||||||
|
cinfo->max_v_samp_factor, cinfo->image_width);
|
||||||
jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
|
/* Edge-expand */
|
||||||
|
expand_right_edge(output_data, cinfo->max_v_samp_factor,
|
||||||
|
cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up after a scan.
|
* Downsample pixel values of a single component.
|
||||||
|
* This version handles the common case of 2:1 horizontal and 1:1 vertical,
|
||||||
|
* without smoothing.
|
||||||
|
*
|
||||||
|
* A note about the "bias" calculations: when rounding fractional values to
|
||||||
|
* integer, we do not want to always round 0.5 up to the next integer.
|
||||||
|
* If we did that, we'd introduce a noticeable bias towards larger values.
|
||||||
|
* Instead, this code is arranged so that 0.5 will be rounded up or down at
|
||||||
|
* alternate pixel locations (a simple ordered dither pattern).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
subsample_term (compress_info_ptr cinfo)
|
h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
{
|
{
|
||||||
/* no work for now */
|
int outrow;
|
||||||
|
JDIMENSION outcol;
|
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register int bias;
|
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more
|
||||||
|
* efficient.
|
||||||
|
*/
|
||||||
|
expand_right_edge(input_data, cinfo->max_v_samp_factor,
|
||||||
|
cinfo->image_width, output_cols * 2);
|
||||||
|
|
||||||
|
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
inptr = input_data[outrow];
|
||||||
|
bias = 0; /* bias = 0,1,0,1,... for successive samples */
|
||||||
|
for (outcol = 0; outcol < output_cols; outcol++) {
|
||||||
|
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
|
||||||
|
+ bias) >> 1);
|
||||||
|
bias ^= 1; /* 0=>1, 1=>0 */
|
||||||
|
inptr += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Downsample pixel values of a single component.
|
||||||
|
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
|
||||||
|
* without smoothing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
|
{
|
||||||
|
int inrow, outrow;
|
||||||
|
JDIMENSION outcol;
|
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||||
|
register JSAMPROW inptr0, inptr1, outptr;
|
||||||
|
register int bias;
|
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more
|
||||||
|
* efficient.
|
||||||
|
*/
|
||||||
|
expand_right_edge(input_data, cinfo->max_v_samp_factor,
|
||||||
|
cinfo->image_width, output_cols * 2);
|
||||||
|
|
||||||
|
inrow = 0;
|
||||||
|
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
inptr0 = input_data[inrow];
|
||||||
|
inptr1 = input_data[inrow+1];
|
||||||
|
bias = 1; /* bias = 1,2,1,2,... for successive samples */
|
||||||
|
for (outcol = 0; outcol < output_cols; outcol++) {
|
||||||
|
*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||||
|
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
|
||||||
|
+ bias) >> 2);
|
||||||
|
bias ^= 3; /* 1=>2, 2=>1 */
|
||||||
|
inptr0 += 2; inptr1 += 2;
|
||||||
|
}
|
||||||
|
inrow += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The method selection routine for subsampling.
|
* Downsample pixel values of a single component.
|
||||||
|
* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
|
||||||
|
* with smoothing. One row of context is required.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
|
{
|
||||||
|
int inrow, outrow;
|
||||||
|
JDIMENSION colctr;
|
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||||
|
register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
|
||||||
|
INT32 membersum, neighsum, memberscale, neighscale;
|
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more
|
||||||
|
* efficient.
|
||||||
|
*/
|
||||||
|
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
|
||||||
|
cinfo->image_width, output_cols * 2);
|
||||||
|
|
||||||
|
/* We don't bother to form the individual "smoothed" input pixel values;
|
||||||
|
* we can directly compute the output which is the average of the four
|
||||||
|
* smoothed values. Each of the four member pixels contributes a fraction
|
||||||
|
* (1-8*SF) to its own smoothed image and a fraction SF to each of the three
|
||||||
|
* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
|
||||||
|
* output. The four corner-adjacent neighbor pixels contribute a fraction
|
||||||
|
* SF to just one smoothed pixel, or SF/4 to the final output; while the
|
||||||
|
* eight edge-adjacent neighbors contribute SF to each of two smoothed
|
||||||
|
* pixels, or SF/2 overall. In order to use integer arithmetic, these
|
||||||
|
* factors are scaled by 2^16 = 65536.
|
||||||
|
* Also recall that SF = smoothing_factor / 1024.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
|
||||||
|
neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
|
||||||
|
|
||||||
|
inrow = 0;
|
||||||
|
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
inptr0 = input_data[inrow];
|
||||||
|
inptr1 = input_data[inrow+1];
|
||||||
|
above_ptr = input_data[inrow-1];
|
||||||
|
below_ptr = input_data[inrow+2];
|
||||||
|
|
||||||
|
/* Special case for first column: pretend column -1 is same as column 0 */
|
||||||
|
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||||
|
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||||
|
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||||
|
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||||
|
GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
|
||||||
|
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
|
||||||
|
neighsum += neighsum;
|
||||||
|
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
|
||||||
|
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
|
||||||
|
|
||||||
|
for (colctr = output_cols - 2; colctr > 0; colctr--) {
|
||||||
|
/* sum of pixels directly mapped to this output element */
|
||||||
|
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||||
|
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||||
|
/* sum of edge-neighbor pixels */
|
||||||
|
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||||
|
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||||
|
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
|
||||||
|
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
|
||||||
|
/* The edge-neighbors count twice as much as corner-neighbors */
|
||||||
|
neighsum += neighsum;
|
||||||
|
/* Add in the corner-neighbors */
|
||||||
|
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
|
||||||
|
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
|
||||||
|
/* form final output scaled up by 2^16 */
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
/* round, descale and output it */
|
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special case for last column */
|
||||||
|
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||||
|
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||||
|
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||||
|
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||||
|
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
|
||||||
|
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
|
||||||
|
neighsum += neighsum;
|
||||||
|
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
|
||||||
|
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
|
||||||
|
inrow += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Downsample pixel values of a single component.
|
||||||
|
* This version handles the special case of a full-size component,
|
||||||
|
* with smoothing. One row of context is required.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||||
|
{
|
||||||
|
int outrow;
|
||||||
|
JDIMENSION colctr;
|
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||||
|
register JSAMPROW inptr, above_ptr, below_ptr, outptr;
|
||||||
|
INT32 membersum, neighsum, memberscale, neighscale;
|
||||||
|
int colsum, lastcolsum, nextcolsum;
|
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more
|
||||||
|
* efficient.
|
||||||
|
*/
|
||||||
|
expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
|
||||||
|
cinfo->image_width, output_cols);
|
||||||
|
|
||||||
|
/* Each of the eight neighbor pixels contributes a fraction SF to the
|
||||||
|
* smoothed pixel, while the main pixel contributes (1-8*SF). In order
|
||||||
|
* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
|
||||||
|
* Also recall that SF = smoothing_factor / 1024.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
|
||||||
|
neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
|
||||||
|
|
||||||
|
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
inptr = input_data[outrow];
|
||||||
|
above_ptr = input_data[outrow-1];
|
||||||
|
below_ptr = input_data[outrow+1];
|
||||||
|
|
||||||
|
/* Special case for first column */
|
||||||
|
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
|
||||||
|
GETJSAMPLE(*inptr);
|
||||||
|
membersum = GETJSAMPLE(*inptr++);
|
||||||
|
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
|
||||||
|
GETJSAMPLE(*inptr);
|
||||||
|
neighsum = colsum + (colsum - membersum) + nextcolsum;
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
lastcolsum = colsum; colsum = nextcolsum;
|
||||||
|
|
||||||
|
for (colctr = output_cols - 2; colctr > 0; colctr--) {
|
||||||
|
membersum = GETJSAMPLE(*inptr++);
|
||||||
|
above_ptr++; below_ptr++;
|
||||||
|
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
|
||||||
|
GETJSAMPLE(*inptr);
|
||||||
|
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
lastcolsum = colsum; colsum = nextcolsum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special case for last column */
|
||||||
|
membersum = GETJSAMPLE(*inptr);
|
||||||
|
neighsum = lastcolsum + (colsum - membersum) + colsum;
|
||||||
|
membersum = membersum * memberscale + neighsum * neighscale;
|
||||||
|
*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INPUT_SMOOTHING_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for downsampling.
|
||||||
* Note that we must select a routine for each component.
|
* Note that we must select a routine for each component.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GLOBAL void
|
GLOBAL(void)
|
||||||
jselsubsample (compress_info_ptr cinfo)
|
jinit_downsampler (j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
short ci;
|
my_downsample_ptr downsample;
|
||||||
|
int ci;
|
||||||
jpeg_component_info * compptr;
|
jpeg_component_info * compptr;
|
||||||
|
boolean smoothok = TRUE;
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
downsample = (my_downsample_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_downsampler));
|
||||||
|
cinfo->downsample = (struct jpeg_downsampler *) downsample;
|
||||||
|
downsample->pub.start_pass = start_pass_downsample;
|
||||||
|
downsample->pub.downsample = sep_downsample;
|
||||||
|
downsample->pub.need_context_rows = FALSE;
|
||||||
|
|
||||||
if (cinfo->CCIR601_sampling)
|
if (cinfo->CCIR601_sampling)
|
||||||
ERREXIT(cinfo->emethods, "CCIR601 subsampling not implemented yet");
|
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
|
||||||
|
|
||||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
/* Verify we can handle the sampling factors, and set up method pointers */
|
||||||
compptr = cinfo->cur_comp_info[ci];
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
|
if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
|
||||||
compptr->v_samp_factor == cinfo->max_v_samp_factor)
|
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
|
||||||
cinfo->methods->subsample[ci] = fullsize_subsample;
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
|
if (cinfo->smoothing_factor) {
|
||||||
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0)
|
downsample->methods[ci] = fullsize_smooth_downsample;
|
||||||
cinfo->methods->subsample[ci] = subsample;
|
downsample->pub.need_context_rows = TRUE;
|
||||||
else
|
} else
|
||||||
ERREXIT(cinfo->emethods, "Fractional subsampling not implemented yet");
|
#endif
|
||||||
|
downsample->methods[ci] = fullsize_downsample;
|
||||||
|
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
|
||||||
|
compptr->v_samp_factor == cinfo->max_v_samp_factor) {
|
||||||
|
smoothok = FALSE;
|
||||||
|
#ifdef JCSAMPLE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2)
|
||||||
|
downsample->methods[ci] = jpeg_h2v1_downsample_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JCSAMPLE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
downsample->methods[ci] = jpeg_h2v1_downsample_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
downsample->methods[ci] = h2v1_downsample;
|
||||||
|
} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
|
||||||
|
compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
|
if (cinfo->smoothing_factor) {
|
||||||
|
downsample->methods[ci] = h2v2_smooth_downsample;
|
||||||
|
downsample->pub.need_context_rows = TRUE;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JCSAMPLE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2)
|
||||||
|
downsample->methods[ci] = jpeg_h2v2_downsample_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JCSAMPLE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
downsample->methods[ci] = jpeg_h2v2_downsample_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
downsample->methods[ci] = h2v2_downsample;
|
||||||
|
} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
|
||||||
|
(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
|
||||||
|
smoothok = FALSE;
|
||||||
|
downsample->methods[ci] = int_downsample;
|
||||||
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
|
||||||
}
|
}
|
||||||
|
|
||||||
cinfo->methods->subsample_init = subsample_init;
|
#ifdef INPUT_SMOOTHING_SUPPORTED
|
||||||
cinfo->methods->subsample_term = subsample_term;
|
if (cinfo->smoothing_factor && !smoothok)
|
||||||
|
TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_downsampler (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
#ifdef JCSAMPLE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2)
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JCSAMPLE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return JSIMD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|||||||
355
jcsamss2.asm
Normal file
355
jcsamss2.asm
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
;
|
||||||
|
; jcsamss2.asm - downsampling (SSE2)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : January 23, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%ifdef JCSAMPLE_SSE2_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Downsample pixel values of a single component.
|
||||||
|
; This version handles the common case of 2:1 horizontal and 1:1 vertical,
|
||||||
|
; without smoothing.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_h2v1_downsample_sse2 (j_compress_ptr cinfo,
|
||||||
|
; jpeg_component_info * compptr,
|
||||||
|
; JSAMPARRAY input_data, JSAMPARRAY output_data);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define compptr(b) (b)+12 ; jpeg_component_info * compptr
|
||||||
|
%define input_data(b) (b)+16 ; JSAMPARRAY input_data
|
||||||
|
%define output_data(b) (b)+20 ; JSAMPARRAY output_data
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_h2v1_downsample_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_h2v1_downsample_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov ecx, POINTER [compptr(ebp)]
|
||||||
|
mov ecx, JDIMENSION [jcompinfo_width_in_blocks(ecx)]
|
||||||
|
shl ecx,3 ; imul ecx,DCTSIZE (ecx = output_cols)
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
mov edx, POINTER [cinfo(ebp)]
|
||||||
|
mov edx, JDIMENSION [jcstruct_image_width(edx)]
|
||||||
|
|
||||||
|
; -- expand_right_edge
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
shl ecx,1 ; output_cols * 2
|
||||||
|
sub ecx,edx
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
mov eax, POINTER [cinfo(ebp)]
|
||||||
|
mov eax, INT [jcstruct_max_v_samp_factor(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
cld
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
alignx 16,7
|
||||||
|
.expandloop:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPROW [esi]
|
||||||
|
add edi,edx
|
||||||
|
mov al, JSAMPLE [edi-1]
|
||||||
|
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax
|
||||||
|
jg short .expandloop
|
||||||
|
|
||||||
|
.expand_end:
|
||||||
|
pop ecx ; output_cols
|
||||||
|
|
||||||
|
; -- h2v1_downsample
|
||||||
|
|
||||||
|
mov eax, POINTER [compptr(ebp)]
|
||||||
|
mov eax, JDIMENSION [jcompinfo_v_samp_factor(eax)] ; rowctr
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
|
||||||
|
mov edx, 0x00010000 ; bias pattern
|
||||||
|
movd xmm7,edx
|
||||||
|
pcmpeqw xmm6,xmm6
|
||||||
|
pshufd xmm7,xmm7,0x00 ; xmm7={0, 1, 0, 1, 0, 1, 0, 1}
|
||||||
|
psrlw xmm6,BYTE_BIT ; xmm6={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
mov edi, JSAMPARRAY [output_data(ebp)] ; output_data
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae short .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop_r8:
|
||||||
|
movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
pxor xmm1,xmm1
|
||||||
|
mov ecx, SIZEOF_XMMWORD
|
||||||
|
jmp short .downsample
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqa xmm1, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
|
||||||
|
.downsample:
|
||||||
|
movdqa xmm2,xmm0
|
||||||
|
movdqa xmm3,xmm1
|
||||||
|
|
||||||
|
pand xmm0,xmm6
|
||||||
|
psrlw xmm2,BYTE_BIT
|
||||||
|
pand xmm1,xmm6
|
||||||
|
psrlw xmm3,BYTE_BIT
|
||||||
|
|
||||||
|
paddw xmm0,xmm2
|
||||||
|
paddw xmm1,xmm3
|
||||||
|
paddw xmm0,xmm7
|
||||||
|
paddw xmm1,xmm7
|
||||||
|
psrlw xmm0,1
|
||||||
|
psrlw xmm1,1
|
||||||
|
|
||||||
|
packuswb xmm0,xmm1
|
||||||
|
|
||||||
|
movdqa XMMWORD [edi+0*SIZEOF_XMMWORD], xmm0
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD ; outcol
|
||||||
|
add esi, byte 2*SIZEOF_XMMWORD ; inptr
|
||||||
|
add edi, byte 1*SIZEOF_XMMWORD ; outptr
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae short .columnloop
|
||||||
|
test ecx,ecx
|
||||||
|
jnz short .columnloop_r8
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW ; input_data
|
||||||
|
add edi, byte SIZEOF_JSAMPROW ; output_data
|
||||||
|
dec eax ; rowctr
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Downsample pixel values of a single component.
|
||||||
|
; This version handles the standard case of 2:1 horizontal and 2:1 vertical,
|
||||||
|
; without smoothing.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_h2v2_downsample_sse2 (j_compress_ptr cinfo,
|
||||||
|
; jpeg_component_info * compptr,
|
||||||
|
; JSAMPARRAY input_data, JSAMPARRAY output_data);
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_compress_ptr cinfo
|
||||||
|
%define compptr(b) (b)+12 ; jpeg_component_info * compptr
|
||||||
|
%define input_data(b) (b)+16 ; JSAMPARRAY input_data
|
||||||
|
%define output_data(b) (b)+20 ; JSAMPARRAY output_data
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_h2v2_downsample_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_h2v2_downsample_sse2):
|
||||||
|
push ebp
|
||||||
|
mov ebp,esp
|
||||||
|
; push ebx ; unused
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov ecx, POINTER [compptr(ebp)]
|
||||||
|
mov ecx, JDIMENSION [jcompinfo_width_in_blocks(ecx)]
|
||||||
|
shl ecx,3 ; imul ecx,DCTSIZE (ecx = output_cols)
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
mov edx, POINTER [cinfo(ebp)]
|
||||||
|
mov edx, JDIMENSION [jcstruct_image_width(edx)]
|
||||||
|
|
||||||
|
; -- expand_right_edge
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
shl ecx,1 ; output_cols * 2
|
||||||
|
sub ecx,edx
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
mov eax, POINTER [cinfo(ebp)]
|
||||||
|
mov eax, INT [jcstruct_max_v_samp_factor(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle short .expand_end
|
||||||
|
|
||||||
|
cld
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
alignx 16,7
|
||||||
|
.expandloop:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPROW [esi]
|
||||||
|
add edi,edx
|
||||||
|
mov al, JSAMPLE [edi-1]
|
||||||
|
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
dec eax
|
||||||
|
jg short .expandloop
|
||||||
|
|
||||||
|
.expand_end:
|
||||||
|
pop ecx ; output_cols
|
||||||
|
|
||||||
|
; -- h2v2_downsample
|
||||||
|
|
||||||
|
mov eax, POINTER [compptr(ebp)]
|
||||||
|
mov eax, JDIMENSION [jcompinfo_v_samp_factor(eax)] ; rowctr
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
|
||||||
|
mov edx, 0x00020001 ; bias pattern
|
||||||
|
movd xmm7,edx
|
||||||
|
pcmpeqw xmm6,xmm6
|
||||||
|
pshufd xmm7,xmm7,0x00 ; xmm7={1, 2, 1, 2, 1, 2, 1, 2}
|
||||||
|
psrlw xmm6,BYTE_BIT ; xmm6={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
mov esi, JSAMPARRAY [input_data(ebp)] ; input_data
|
||||||
|
mov edi, JSAMPARRAY [output_data(ebp)] ; output_data
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov edx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; inptr0
|
||||||
|
mov esi, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; inptr1
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae short .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop_r8:
|
||||||
|
movdqa xmm0, XMMWORD [edx+0*SIZEOF_XMMWORD]
|
||||||
|
movdqa xmm1, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
pxor xmm2,xmm2
|
||||||
|
pxor xmm3,xmm3
|
||||||
|
mov ecx, SIZEOF_XMMWORD
|
||||||
|
jmp short .downsample
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.columnloop:
|
||||||
|
movdqa xmm0, XMMWORD [edx+0*SIZEOF_XMMWORD]
|
||||||
|
movdqa xmm1, XMMWORD [esi+0*SIZEOF_XMMWORD]
|
||||||
|
movdqa xmm2, XMMWORD [edx+1*SIZEOF_XMMWORD]
|
||||||
|
movdqa xmm3, XMMWORD [esi+1*SIZEOF_XMMWORD]
|
||||||
|
|
||||||
|
.downsample:
|
||||||
|
movdqa xmm4,xmm0
|
||||||
|
movdqa xmm5,xmm1
|
||||||
|
pand xmm0,xmm6
|
||||||
|
psrlw xmm4,BYTE_BIT
|
||||||
|
pand xmm1,xmm6
|
||||||
|
psrlw xmm5,BYTE_BIT
|
||||||
|
paddw xmm0,xmm4
|
||||||
|
paddw xmm1,xmm5
|
||||||
|
|
||||||
|
movdqa xmm4,xmm2
|
||||||
|
movdqa xmm5,xmm3
|
||||||
|
pand xmm2,xmm6
|
||||||
|
psrlw xmm4,BYTE_BIT
|
||||||
|
pand xmm3,xmm6
|
||||||
|
psrlw xmm5,BYTE_BIT
|
||||||
|
paddw xmm2,xmm4
|
||||||
|
paddw xmm3,xmm5
|
||||||
|
|
||||||
|
paddw xmm0,xmm1
|
||||||
|
paddw xmm2,xmm3
|
||||||
|
paddw xmm0,xmm7
|
||||||
|
paddw xmm2,xmm7
|
||||||
|
psrlw xmm0,2
|
||||||
|
psrlw xmm2,2
|
||||||
|
|
||||||
|
packuswb xmm0,xmm2
|
||||||
|
|
||||||
|
movdqa XMMWORD [edi+0*SIZEOF_XMMWORD], xmm0
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD ; outcol
|
||||||
|
add edx, byte 2*SIZEOF_XMMWORD ; inptr0
|
||||||
|
add esi, byte 2*SIZEOF_XMMWORD ; inptr1
|
||||||
|
add edi, byte 1*SIZEOF_XMMWORD ; outptr
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jae near .columnloop
|
||||||
|
test ecx,ecx
|
||||||
|
jnz near .columnloop_r8
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
add esi, byte 2*SIZEOF_JSAMPROW ; input_data
|
||||||
|
add edi, byte 1*SIZEOF_JSAMPROW ; output_data
|
||||||
|
dec eax ; rowctr
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
; pop ebx ; unused
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JCSAMPLE_SSE2_SUPPORTED
|
||||||
388
jctrans.c
Normal file
388
jctrans.c
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
/*
|
||||||
|
* jctrans.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995-1998, 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 library routines for transcoding compression,
|
||||||
|
* that is, writing raw DCT coefficient arrays to an output JPEG file.
|
||||||
|
* The routines in jcapimin.c will also be needed by a transcoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
LOCAL(void) transencode_master_selection
|
||||||
|
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
|
||||||
|
LOCAL(void) transencode_coef_controller
|
||||||
|
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compression initialization for writing raw-coefficient data.
|
||||||
|
* Before calling this, all parameters and a data destination must be set up.
|
||||||
|
* Call jpeg_finish_compress() to actually write the data.
|
||||||
|
*
|
||||||
|
* The number of passed virtual arrays must match cinfo->num_components.
|
||||||
|
* Note that the virtual arrays need not be filled or even realized at
|
||||||
|
* the time write_coefficients is called; indeed, if the virtual arrays
|
||||||
|
* were requested from this compression object's memory manager, they
|
||||||
|
* typically will be realized during this routine and filled afterwards.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
/* Mark all tables to be written */
|
||||||
|
jpeg_suppress_tables(cinfo, FALSE);
|
||||||
|
/* (Re)initialize error mgr and destination modules */
|
||||||
|
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||||
|
(*cinfo->dest->init_destination) (cinfo);
|
||||||
|
/* Perform master selection of active modules */
|
||||||
|
transencode_master_selection(cinfo, coef_arrays);
|
||||||
|
/* Wait for jpeg_finish_compress() call */
|
||||||
|
cinfo->next_scanline = 0; /* so jpeg_write_marker works */
|
||||||
|
cinfo->global_state = CSTATE_WRCOEFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the compression object with default parameters,
|
||||||
|
* then copy from the source object all parameters needed for lossless
|
||||||
|
* transcoding. Parameters that can be varied without loss (such as
|
||||||
|
* scan script and Huffman optimization) are left in their default states.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
|
||||||
|
j_compress_ptr dstinfo)
|
||||||
|
{
|
||||||
|
JQUANT_TBL ** qtblptr;
|
||||||
|
jpeg_component_info *incomp, *outcomp;
|
||||||
|
JQUANT_TBL *c_quant, *slot_quant;
|
||||||
|
int tblno, ci, coefi;
|
||||||
|
|
||||||
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
|
if (dstinfo->global_state != CSTATE_START)
|
||||||
|
ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
|
||||||
|
/* Copy fundamental image dimensions */
|
||||||
|
dstinfo->image_width = srcinfo->image_width;
|
||||||
|
dstinfo->image_height = srcinfo->image_height;
|
||||||
|
dstinfo->input_components = srcinfo->num_components;
|
||||||
|
dstinfo->in_color_space = srcinfo->jpeg_color_space;
|
||||||
|
/* Initialize all parameters to default values */
|
||||||
|
jpeg_set_defaults(dstinfo);
|
||||||
|
/* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
|
||||||
|
* Fix it to get the right header markers for the image colorspace.
|
||||||
|
*/
|
||||||
|
jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
|
||||||
|
dstinfo->data_precision = srcinfo->data_precision;
|
||||||
|
dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
|
||||||
|
/* Copy the source's quantization tables. */
|
||||||
|
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
|
||||||
|
if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
|
||||||
|
qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
|
||||||
|
if (*qtblptr == NULL)
|
||||||
|
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
|
||||||
|
MEMCOPY((*qtblptr)->quantval,
|
||||||
|
srcinfo->quant_tbl_ptrs[tblno]->quantval,
|
||||||
|
SIZEOF((*qtblptr)->quantval));
|
||||||
|
(*qtblptr)->sent_table = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Copy the source's per-component info.
|
||||||
|
* Note we assume jpeg_set_defaults has allocated the dest comp_info array.
|
||||||
|
*/
|
||||||
|
dstinfo->num_components = srcinfo->num_components;
|
||||||
|
if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
|
||||||
|
ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
|
||||||
|
MAX_COMPONENTS);
|
||||||
|
for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
|
||||||
|
ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
|
||||||
|
outcomp->component_id = incomp->component_id;
|
||||||
|
outcomp->h_samp_factor = incomp->h_samp_factor;
|
||||||
|
outcomp->v_samp_factor = incomp->v_samp_factor;
|
||||||
|
outcomp->quant_tbl_no = incomp->quant_tbl_no;
|
||||||
|
/* Make sure saved quantization table for component matches the qtable
|
||||||
|
* slot. If not, the input file re-used this qtable slot.
|
||||||
|
* IJG encoder currently cannot duplicate this.
|
||||||
|
*/
|
||||||
|
tblno = outcomp->quant_tbl_no;
|
||||||
|
if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
|
||||||
|
srcinfo->quant_tbl_ptrs[tblno] == NULL)
|
||||||
|
ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
|
||||||
|
slot_quant = srcinfo->quant_tbl_ptrs[tblno];
|
||||||
|
c_quant = incomp->quant_table;
|
||||||
|
if (c_quant != NULL) {
|
||||||
|
for (coefi = 0; coefi < DCTSIZE2; coefi++) {
|
||||||
|
if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
|
||||||
|
ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Note: we do not copy the source's Huffman table assignments;
|
||||||
|
* instead we rely on jpeg_set_colorspace to have made a suitable choice.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
/* Also copy JFIF version and resolution information, if available.
|
||||||
|
* Strictly speaking this isn't "critical" info, but it's nearly
|
||||||
|
* always appropriate to copy it if available. In particular,
|
||||||
|
* if the application chooses to copy JFIF 1.02 extension markers from
|
||||||
|
* the source file, we need to copy the version to make sure we don't
|
||||||
|
* emit a file that has 1.02 extensions but a claimed version of 1.01.
|
||||||
|
* We will *not*, however, copy version info from mislabeled "2.01" files.
|
||||||
|
*/
|
||||||
|
if (srcinfo->saw_JFIF_marker) {
|
||||||
|
if (srcinfo->JFIF_major_version == 1) {
|
||||||
|
dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
|
||||||
|
dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
|
||||||
|
}
|
||||||
|
dstinfo->density_unit = srcinfo->density_unit;
|
||||||
|
dstinfo->X_density = srcinfo->X_density;
|
||||||
|
dstinfo->Y_density = srcinfo->Y_density;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Master selection of compression modules for transcoding.
|
||||||
|
* This substitutes for jcinit.c's initialization of the full compressor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
transencode_master_selection (j_compress_ptr cinfo,
|
||||||
|
jvirt_barray_ptr * coef_arrays)
|
||||||
|
{
|
||||||
|
/* Although we don't actually use input_components for transcoding,
|
||||||
|
* jcmaster.c's initial_setup will complain if input_components is 0.
|
||||||
|
*/
|
||||||
|
cinfo->input_components = 1;
|
||||||
|
/* Initialize master control (includes parameter checking/processing) */
|
||||||
|
jinit_c_master_control(cinfo, TRUE /* transcode only */);
|
||||||
|
|
||||||
|
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
|
} else {
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
|
jinit_phuff_encoder(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
jinit_huff_encoder(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need a special coefficient buffer controller. */
|
||||||
|
transencode_coef_controller(cinfo, coef_arrays);
|
||||||
|
|
||||||
|
jinit_marker_writer(cinfo);
|
||||||
|
|
||||||
|
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||||
|
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Write the datastream header (SOI, JFIF) immediately.
|
||||||
|
* Frame and scan headers are postponed till later.
|
||||||
|
* This lets application insert special markers after the SOI.
|
||||||
|
*/
|
||||||
|
(*cinfo->marker->write_file_header) (cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The rest of this file is a special implementation of the coefficient
|
||||||
|
* buffer controller. This is similar to jccoefct.c, but it handles only
|
||||||
|
* output from presupplied virtual arrays. Furthermore, we generate any
|
||||||
|
* dummy padding blocks on-the-fly rather than expecting them to be present
|
||||||
|
* in the arrays.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_c_coef_controller pub; /* public fields */
|
||||||
|
|
||||||
|
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||||
|
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||||
|
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||||
|
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||||
|
|
||||||
|
/* Virtual block array for each component. */
|
||||||
|
jvirt_barray_ptr * whole_image;
|
||||||
|
|
||||||
|
/* Workspace for constructing dummy blocks at right/bottom edges. */
|
||||||
|
JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||||
|
} my_coef_controller;
|
||||||
|
|
||||||
|
typedef my_coef_controller * my_coef_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
start_iMCU_row (j_compress_ptr cinfo)
|
||||||
|
/* Reset within-iMCU-row counters for a new row */
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||||
|
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||||
|
* But at the bottom of the image, process only what's left.
|
||||||
|
*/
|
||||||
|
if (cinfo->comps_in_scan > 1) {
|
||||||
|
coef->MCU_rows_per_iMCU_row = 1;
|
||||||
|
} else {
|
||||||
|
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||||
|
else
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
coef->mcu_ctr = 0;
|
||||||
|
coef->MCU_vert_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
if (pass_mode != JBUF_CRANK_DEST)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
|
||||||
|
coef->iMCU_row_num = 0;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||||
|
* per call, ie, v_samp_factor block rows for each component in the scan.
|
||||||
|
* The data is obtained from the virtual arrays and fed to the entropy coder.
|
||||||
|
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
|
||||||
|
*
|
||||||
|
* NB: input_buf is ignored; it is likely to be a NULL pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||||
|
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
int blkn, ci, xindex, yindex, yoffset, blockcnt;
|
||||||
|
JDIMENSION start_col;
|
||||||
|
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||||
|
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||||
|
JBLOCKROW buffer_ptr;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Align the virtual buffers for the components used in this scan. */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
buffer[ci] = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
|
||||||
|
coef->iMCU_row_num * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop to process one whole iMCU row */
|
||||||
|
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||||
|
yoffset++) {
|
||||||
|
for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
|
||||||
|
MCU_col_num++) {
|
||||||
|
/* Construct list of pointers to DCT blocks belonging to this MCU */
|
||||||
|
blkn = 0; /* index of current DCT block within MCU */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
start_col = MCU_col_num * compptr->MCU_width;
|
||||||
|
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
|
||||||
|
: compptr->last_col_width;
|
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||||
|
if (coef->iMCU_row_num < last_iMCU_row ||
|
||||||
|
yindex+yoffset < compptr->last_row_height) {
|
||||||
|
/* Fill in pointers to real blocks in this row */
|
||||||
|
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
|
||||||
|
for (xindex = 0; xindex < blockcnt; xindex++)
|
||||||
|
MCU_buffer[blkn++] = buffer_ptr++;
|
||||||
|
} else {
|
||||||
|
/* At bottom of image, need a whole row of dummy blocks */
|
||||||
|
xindex = 0;
|
||||||
|
}
|
||||||
|
/* Fill in any dummy blocks needed in this row.
|
||||||
|
* Dummy blocks are filled in the same way as in jccoefct.c:
|
||||||
|
* all zeroes in the AC entries, DC entries equal to previous
|
||||||
|
* block's DC value. The init routine has already zeroed the
|
||||||
|
* AC entries, so we need only set the DC entries correctly.
|
||||||
|
*/
|
||||||
|
for (; xindex < compptr->MCU_width; xindex++) {
|
||||||
|
MCU_buffer[blkn] = coef->dummy_buffer[blkn];
|
||||||
|
MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
|
||||||
|
blkn++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Try to write the MCU. */
|
||||||
|
if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
|
||||||
|
/* Suspension forced; update state counters and exit */
|
||||||
|
coef->MCU_vert_offset = yoffset;
|
||||||
|
coef->mcu_ctr = MCU_col_num;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||||
|
coef->mcu_ctr = 0;
|
||||||
|
}
|
||||||
|
/* Completed the iMCU row, advance counters for next one */
|
||||||
|
coef->iMCU_row_num++;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize coefficient buffer controller.
|
||||||
|
*
|
||||||
|
* Each passed coefficient array must be the right size for that
|
||||||
|
* coefficient: width_in_blocks wide and height_in_blocks high,
|
||||||
|
* with unitheight at least v_samp_factor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
transencode_coef_controller (j_compress_ptr cinfo,
|
||||||
|
jvirt_barray_ptr * coef_arrays)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef;
|
||||||
|
JBLOCKROW buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
coef = (my_coef_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_coef_controller));
|
||||||
|
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
|
||||||
|
coef->pub.start_pass = start_pass_coef;
|
||||||
|
coef->pub.compress_data = compress_output;
|
||||||
|
|
||||||
|
/* Save pointer to virtual arrays */
|
||||||
|
coef->whole_image = coef_arrays;
|
||||||
|
|
||||||
|
/* Allocate and pre-zero space for dummy DCT blocks. */
|
||||||
|
buffer = (JBLOCKROW)
|
||||||
|
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||||
|
jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||||
|
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
|
||||||
|
coef->dummy_buffer[i] = buffer + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
395
jdapimin.c
Normal file
395
jdapimin.c
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* jdapimin.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains application interface code for the decompression half
|
||||||
|
* of the JPEG library. These are the "minimum" API routines that may be
|
||||||
|
* needed in either the normal full-decompression case or the
|
||||||
|
* transcoding-only case.
|
||||||
|
*
|
||||||
|
* Most of the routines intended to be called directly by an application
|
||||||
|
* are in this file or in jdapistd.c. But also see jcomapi.c for routines
|
||||||
|
* shared by compression and decompression, and jdtrans.c for the transcoding
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization of a JPEG decompression object.
|
||||||
|
* The error manager must already be set up (in case memory manager fails).
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Guard against version mismatches between library and caller. */
|
||||||
|
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
|
||||||
|
if (version != JPEG_LIB_VERSION)
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||||
|
if (structsize != SIZEOF(struct jpeg_decompress_struct))
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
|
||||||
|
(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
|
||||||
|
|
||||||
|
/* For debugging purposes, we zero the whole master structure.
|
||||||
|
* But the application has already set the err pointer, and may have set
|
||||||
|
* client_data, so we have to save and restore those fields.
|
||||||
|
* Note: if application hasn't set client_data, tools like Purify may
|
||||||
|
* complain here.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr * err = cinfo->err;
|
||||||
|
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
|
||||||
|
MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
|
||||||
|
cinfo->err = err;
|
||||||
|
cinfo->client_data = client_data;
|
||||||
|
}
|
||||||
|
cinfo->is_decompressor = TRUE;
|
||||||
|
|
||||||
|
/* Initialize a memory manager instance for this object */
|
||||||
|
jinit_memory_mgr((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Zero out pointers to permanent structures. */
|
||||||
|
cinfo->progress = NULL;
|
||||||
|
cinfo->src = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||||
|
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||||
|
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize marker processor so application can override methods
|
||||||
|
* for COM, APPn markers before calling jpeg_read_header.
|
||||||
|
*/
|
||||||
|
cinfo->marker_list = NULL;
|
||||||
|
jinit_marker_reader(cinfo);
|
||||||
|
|
||||||
|
/* And initialize the overall input controller. */
|
||||||
|
jinit_input_controller(cinfo);
|
||||||
|
|
||||||
|
/* OK, I'm ready */
|
||||||
|
cinfo->global_state = DSTATE_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destruction of a JPEG decompression object
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_destroy_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abort processing of a JPEG decompression operation,
|
||||||
|
* but don't destroy the object itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_abort_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set default decompression parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
default_decompress_parms (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Guess the input colorspace, and set output colorspace accordingly. */
|
||||||
|
/* (Wish JPEG committee had provided a real way to specify this...) */
|
||||||
|
/* Note application may override our guesses. */
|
||||||
|
switch (cinfo->num_components) {
|
||||||
|
case 1:
|
||||||
|
cinfo->jpeg_color_space = JCS_GRAYSCALE;
|
||||||
|
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (cinfo->saw_JFIF_marker) {
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
|
||||||
|
} else if (cinfo->saw_Adobe_marker) {
|
||||||
|
switch (cinfo->Adobe_transform) {
|
||||||
|
case 0:
|
||||||
|
cinfo->jpeg_color_space = JCS_RGB;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Saw no special markers, try to guess from the component IDs */
|
||||||
|
int cid0 = cinfo->comp_info[0].component_id;
|
||||||
|
int cid1 = cinfo->comp_info[1].component_id;
|
||||||
|
int cid2 = cinfo->comp_info[2].component_id;
|
||||||
|
|
||||||
|
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
|
||||||
|
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
|
||||||
|
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||||
|
else {
|
||||||
|
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Always guess RGB is proper output colorspace. */
|
||||||
|
cinfo->out_color_space = JCS_RGB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (cinfo->saw_Adobe_marker) {
|
||||||
|
switch (cinfo->Adobe_transform) {
|
||||||
|
case 0:
|
||||||
|
cinfo->jpeg_color_space = JCS_CMYK;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cinfo->jpeg_color_space = JCS_YCCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No special markers, assume straight CMYK. */
|
||||||
|
cinfo->jpeg_color_space = JCS_CMYK;
|
||||||
|
}
|
||||||
|
cinfo->out_color_space = JCS_CMYK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cinfo->jpeg_color_space = JCS_UNKNOWN;
|
||||||
|
cinfo->out_color_space = JCS_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set defaults for other decompression parameters. */
|
||||||
|
cinfo->scale_num = 1; /* 1:1 scaling */
|
||||||
|
cinfo->scale_denom = 1;
|
||||||
|
cinfo->output_gamma = 1.0;
|
||||||
|
cinfo->buffered_image = FALSE;
|
||||||
|
cinfo->raw_data_out = FALSE;
|
||||||
|
cinfo->dct_method = JDCT_DEFAULT;
|
||||||
|
cinfo->do_fancy_upsampling = TRUE;
|
||||||
|
cinfo->do_block_smoothing = TRUE;
|
||||||
|
cinfo->quantize_colors = FALSE;
|
||||||
|
/* We set these in case application only sets quantize_colors. */
|
||||||
|
cinfo->dither_mode = JDITHER_FS;
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
cinfo->two_pass_quantize = TRUE;
|
||||||
|
#else
|
||||||
|
cinfo->two_pass_quantize = FALSE;
|
||||||
|
#endif
|
||||||
|
cinfo->desired_number_of_colors = 256;
|
||||||
|
cinfo->colormap = NULL;
|
||||||
|
/* Initialize for no mode change in buffered-image mode. */
|
||||||
|
cinfo->enable_1pass_quant = FALSE;
|
||||||
|
cinfo->enable_external_quant = FALSE;
|
||||||
|
cinfo->enable_2pass_quant = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompression startup: read start of JPEG datastream to see what's there.
|
||||||
|
* Need only initialize JPEG object and supply a data source before calling.
|
||||||
|
*
|
||||||
|
* This routine will read as far as the first SOS marker (ie, actual start of
|
||||||
|
* compressed data), and will save all tables and parameters in the JPEG
|
||||||
|
* object. It will also initialize the decompression parameters to default
|
||||||
|
* values, and finally return JPEG_HEADER_OK. On return, the application may
|
||||||
|
* adjust the decompression parameters and then call jpeg_start_decompress.
|
||||||
|
* (Or, if the application only wanted to determine the image parameters,
|
||||||
|
* the data need not be decompressed. In that case, call jpeg_abort or
|
||||||
|
* jpeg_destroy to release any temporary space.)
|
||||||
|
* If an abbreviated (tables only) datastream is presented, the routine will
|
||||||
|
* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
|
||||||
|
* re-use the JPEG object to read the abbreviated image datastream(s).
|
||||||
|
* It is unnecessary (but OK) to call jpeg_abort in this case.
|
||||||
|
* The JPEG_SUSPENDED return code only occurs if the data source module
|
||||||
|
* requests suspension of the decompressor. In this case the application
|
||||||
|
* should load more source data and then re-call jpeg_read_header to resume
|
||||||
|
* processing.
|
||||||
|
* If a non-suspending data source is used and require_image is TRUE, then the
|
||||||
|
* return code need not be inspected since only JPEG_HEADER_OK is possible.
|
||||||
|
*
|
||||||
|
* This routine is now just a front end to jpeg_consume_input, with some
|
||||||
|
* extra error checking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(int)
|
||||||
|
jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
|
||||||
|
{
|
||||||
|
int retcode;
|
||||||
|
|
||||||
|
if (cinfo->global_state != DSTATE_START &&
|
||||||
|
cinfo->global_state != DSTATE_INHEADER)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
retcode = jpeg_consume_input(cinfo);
|
||||||
|
|
||||||
|
switch (retcode) {
|
||||||
|
case JPEG_REACHED_SOS:
|
||||||
|
retcode = JPEG_HEADER_OK;
|
||||||
|
break;
|
||||||
|
case JPEG_REACHED_EOI:
|
||||||
|
if (require_image) /* Complain if application wanted an image */
|
||||||
|
ERREXIT(cinfo, JERR_NO_IMAGE);
|
||||||
|
/* Reset to start state; it would be safer to require the application to
|
||||||
|
* call jpeg_abort, but we can't change it now for compatibility reasons.
|
||||||
|
* A side effect is to free any temporary memory (there shouldn't be any).
|
||||||
|
*/
|
||||||
|
jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
|
||||||
|
retcode = JPEG_HEADER_TABLES_ONLY;
|
||||||
|
break;
|
||||||
|
case JPEG_SUSPENDED:
|
||||||
|
/* no work */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Consume data in advance of what the decompressor requires.
|
||||||
|
* This can be called at any time once the decompressor object has
|
||||||
|
* been created and a data source has been set up.
|
||||||
|
*
|
||||||
|
* This routine is essentially a state machine that handles a couple
|
||||||
|
* of critical state-transition actions, namely initial setup and
|
||||||
|
* transition from header scanning to ready-for-start_decompress.
|
||||||
|
* All the actual input is done via the input controller's consume_input
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(int)
|
||||||
|
jpeg_consume_input (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int retcode = JPEG_SUSPENDED;
|
||||||
|
|
||||||
|
/* NB: every possible DSTATE value should be listed in this switch */
|
||||||
|
switch (cinfo->global_state) {
|
||||||
|
case DSTATE_START:
|
||||||
|
/* Start-of-datastream actions: reset appropriate modules */
|
||||||
|
(*cinfo->inputctl->reset_input_controller) (cinfo);
|
||||||
|
/* Initialize application's data source module */
|
||||||
|
(*cinfo->src->init_source) (cinfo);
|
||||||
|
cinfo->global_state = DSTATE_INHEADER;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case DSTATE_INHEADER:
|
||||||
|
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||||
|
if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
|
||||||
|
/* Set up default parameters based on header data */
|
||||||
|
default_decompress_parms(cinfo);
|
||||||
|
/* Set global state: ready for start_decompress */
|
||||||
|
cinfo->global_state = DSTATE_READY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DSTATE_READY:
|
||||||
|
/* Can't advance past first SOS until start_decompress is called */
|
||||||
|
retcode = JPEG_REACHED_SOS;
|
||||||
|
break;
|
||||||
|
case DSTATE_PRELOAD:
|
||||||
|
case DSTATE_PRESCAN:
|
||||||
|
case DSTATE_SCANNING:
|
||||||
|
case DSTATE_RAW_OK:
|
||||||
|
case DSTATE_BUFIMAGE:
|
||||||
|
case DSTATE_BUFPOST:
|
||||||
|
case DSTATE_STOPPING:
|
||||||
|
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have we finished reading the input file?
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_input_complete (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Check for valid jpeg object */
|
||||||
|
if (cinfo->global_state < DSTATE_START ||
|
||||||
|
cinfo->global_state > DSTATE_STOPPING)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
return cinfo->inputctl->eoi_reached;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is there more than one scan?
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_has_multiple_scans (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Only valid after jpeg_read_header completes */
|
||||||
|
if (cinfo->global_state < DSTATE_READY ||
|
||||||
|
cinfo->global_state > DSTATE_STOPPING)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
return cinfo->inputctl->has_multiple_scans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish JPEG decompression.
|
||||||
|
*
|
||||||
|
* This will normally just verify the file trailer and release temp storage.
|
||||||
|
*
|
||||||
|
* Returns FALSE if suspended. The return value need be inspected only if
|
||||||
|
* a suspending data source is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_finish_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
if ((cinfo->global_state == DSTATE_SCANNING ||
|
||||||
|
cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
|
||||||
|
/* Terminate final pass of non-buffered mode */
|
||||||
|
if (cinfo->output_scanline < cinfo->output_height)
|
||||||
|
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
|
||||||
|
(*cinfo->master->finish_output_pass) (cinfo);
|
||||||
|
cinfo->global_state = DSTATE_STOPPING;
|
||||||
|
} else if (cinfo->global_state == DSTATE_BUFIMAGE) {
|
||||||
|
/* Finishing after a buffered-image operation */
|
||||||
|
cinfo->global_state = DSTATE_STOPPING;
|
||||||
|
} else if (cinfo->global_state != DSTATE_STOPPING) {
|
||||||
|
/* STOPPING = repeat call after a suspension, anything else is error */
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
}
|
||||||
|
/* Read until EOI */
|
||||||
|
while (! cinfo->inputctl->eoi_reached) {
|
||||||
|
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||||
|
return FALSE; /* Suspend, come back later */
|
||||||
|
}
|
||||||
|
/* Do final cleanup */
|
||||||
|
(*cinfo->src->term_source) (cinfo);
|
||||||
|
/* We can use jpeg_abort to release memory and reset global_state */
|
||||||
|
jpeg_abort((j_common_ptr) cinfo);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
275
jdapistd.c
Normal file
275
jdapistd.c
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* jdapistd.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains application interface code for the decompression half
|
||||||
|
* of the JPEG library. These are the "standard" API routines that are
|
||||||
|
* used in the normal full-decompression case. They are not used by a
|
||||||
|
* transcoding-only application. Note that if an application links in
|
||||||
|
* jpeg_start_decompress, it will end up linking in the entire decompressor.
|
||||||
|
* We thus must separate this file from jdapimin.c to avoid linking the
|
||||||
|
* whole decompression library into a transcoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompression initialization.
|
||||||
|
* jpeg_read_header must be completed before calling this.
|
||||||
|
*
|
||||||
|
* If a multipass operating mode was selected, this will do all but the
|
||||||
|
* last pass, and thus may take a great deal of time.
|
||||||
|
*
|
||||||
|
* Returns FALSE if suspended. The return value need be inspected only if
|
||||||
|
* a suspending data source is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_start_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state == DSTATE_READY) {
|
||||||
|
/* First call: initialize master control, select active modules */
|
||||||
|
jinit_master_decompress(cinfo);
|
||||||
|
if (cinfo->buffered_image) {
|
||||||
|
/* No more work here; expecting jpeg_start_output next */
|
||||||
|
cinfo->global_state = DSTATE_BUFIMAGE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
cinfo->global_state = DSTATE_PRELOAD;
|
||||||
|
}
|
||||||
|
if (cinfo->global_state == DSTATE_PRELOAD) {
|
||||||
|
/* If file has multiple scans, absorb them all into the coef buffer */
|
||||||
|
if (cinfo->inputctl->has_multiple_scans) {
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
for (;;) {
|
||||||
|
int retcode;
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL)
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
/* Absorb some more input */
|
||||||
|
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||||
|
if (retcode == JPEG_SUSPENDED)
|
||||||
|
return FALSE;
|
||||||
|
if (retcode == JPEG_REACHED_EOI)
|
||||||
|
break;
|
||||||
|
/* Advance progress counter if appropriate */
|
||||||
|
if (cinfo->progress != NULL &&
|
||||||
|
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
|
||||||
|
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
|
||||||
|
/* jdmaster underestimated number of scans; ratchet up one scan */
|
||||||
|
cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
|
}
|
||||||
|
cinfo->output_scan_number = cinfo->input_scan_number;
|
||||||
|
} else if (cinfo->global_state != DSTATE_PRESCAN)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
/* Perform any dummy output passes, and set up for the final pass */
|
||||||
|
return output_pass_setup(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up for an output pass, and perform any dummy pass(es) needed.
|
||||||
|
* Common subroutine for jpeg_start_decompress and jpeg_start_output.
|
||||||
|
* Entry: global_state = DSTATE_PRESCAN only if previously suspended.
|
||||||
|
* Exit: If done, returns TRUE and sets global_state for proper output mode.
|
||||||
|
* If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
output_pass_setup (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state != DSTATE_PRESCAN) {
|
||||||
|
/* First call: do pass setup */
|
||||||
|
(*cinfo->master->prepare_for_output_pass) (cinfo);
|
||||||
|
cinfo->output_scanline = 0;
|
||||||
|
cinfo->global_state = DSTATE_PRESCAN;
|
||||||
|
}
|
||||||
|
/* Loop over any required dummy passes */
|
||||||
|
while (cinfo->master->is_dummy_pass) {
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
/* Crank through the dummy pass */
|
||||||
|
while (cinfo->output_scanline < cinfo->output_height) {
|
||||||
|
JDIMENSION last_scanline;
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
/* Process some data */
|
||||||
|
last_scanline = cinfo->output_scanline;
|
||||||
|
(*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
|
||||||
|
&cinfo->output_scanline, (JDIMENSION) 0);
|
||||||
|
if (cinfo->output_scanline == last_scanline)
|
||||||
|
return FALSE; /* No progress made, must suspend */
|
||||||
|
}
|
||||||
|
/* Finish up dummy pass, and set up for another one */
|
||||||
|
(*cinfo->master->finish_output_pass) (cinfo);
|
||||||
|
(*cinfo->master->prepare_for_output_pass) (cinfo);
|
||||||
|
cinfo->output_scanline = 0;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif /* QUANT_2PASS_SUPPORTED */
|
||||||
|
}
|
||||||
|
/* Ready for application to drive output pass through
|
||||||
|
* jpeg_read_scanlines or jpeg_read_raw_data.
|
||||||
|
*/
|
||||||
|
cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read some scanlines of data from the JPEG decompressor.
|
||||||
|
*
|
||||||
|
* The return value will be the number of lines actually read.
|
||||||
|
* This may be less than the number requested in several cases,
|
||||||
|
* including bottom of image, data source suspension, and operating
|
||||||
|
* modes that emit multiple scanlines at a time.
|
||||||
|
*
|
||||||
|
* Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||||
|
* this likely signals an application programmer error. However,
|
||||||
|
* an oversize buffer (max_lines > scanlines remaining) is not an error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JDIMENSION)
|
||||||
|
jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
|
||||||
|
JDIMENSION max_lines)
|
||||||
|
{
|
||||||
|
JDIMENSION row_ctr;
|
||||||
|
|
||||||
|
if (cinfo->global_state != DSTATE_SCANNING)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||||
|
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process some data */
|
||||||
|
row_ctr = 0;
|
||||||
|
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
|
||||||
|
cinfo->output_scanline += row_ctr;
|
||||||
|
return row_ctr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alternate entry point to read raw data.
|
||||||
|
* Processes exactly one iMCU row per call, unless suspended.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(JDIMENSION)
|
||||||
|
jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
||||||
|
JDIMENSION max_lines)
|
||||||
|
{
|
||||||
|
JDIMENSION lines_per_iMCU_row;
|
||||||
|
|
||||||
|
if (cinfo->global_state != DSTATE_RAW_OK)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||||
|
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call progress monitor hook if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||||
|
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that at least one iMCU row can be returned. */
|
||||||
|
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
|
||||||
|
if (max_lines < lines_per_iMCU_row)
|
||||||
|
ERREXIT(cinfo, JERR_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* Decompress directly into user's buffer. */
|
||||||
|
if (! (*cinfo->coef->decompress_data) (cinfo, data))
|
||||||
|
return 0; /* suspension forced, can do nothing more */
|
||||||
|
|
||||||
|
/* OK, we processed one iMCU row. */
|
||||||
|
cinfo->output_scanline += lines_per_iMCU_row;
|
||||||
|
return lines_per_iMCU_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Additional entry points for buffered-image mode. */
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an output pass in buffered-image mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
|
||||||
|
{
|
||||||
|
if (cinfo->global_state != DSTATE_BUFIMAGE &&
|
||||||
|
cinfo->global_state != DSTATE_PRESCAN)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
/* Limit scan number to valid range */
|
||||||
|
if (scan_number <= 0)
|
||||||
|
scan_number = 1;
|
||||||
|
if (cinfo->inputctl->eoi_reached &&
|
||||||
|
scan_number > cinfo->input_scan_number)
|
||||||
|
scan_number = cinfo->input_scan_number;
|
||||||
|
cinfo->output_scan_number = scan_number;
|
||||||
|
/* Perform any dummy output passes, and set up for the real pass */
|
||||||
|
return output_pass_setup(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up after an output pass in buffered-image mode.
|
||||||
|
*
|
||||||
|
* Returns FALSE if suspended. The return value need be inspected only if
|
||||||
|
* a suspending data source is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_finish_output (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
if ((cinfo->global_state == DSTATE_SCANNING ||
|
||||||
|
cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
|
||||||
|
/* Terminate this pass. */
|
||||||
|
/* We do not require the whole pass to have been completed. */
|
||||||
|
(*cinfo->master->finish_output_pass) (cinfo);
|
||||||
|
cinfo->global_state = DSTATE_BUFPOST;
|
||||||
|
} else if (cinfo->global_state != DSTATE_BUFPOST) {
|
||||||
|
/* BUFPOST = repeat call after a suspension, anything else is error */
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
}
|
||||||
|
/* Read markers looking for SOS or EOI */
|
||||||
|
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
|
||||||
|
! cinfo->inputctl->eoi_reached) {
|
||||||
|
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||||
|
return FALSE; /* Suspend, come back later */
|
||||||
|
}
|
||||||
|
cinfo->global_state = DSTATE_BUFIMAGE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
42
jdarith.c
42
jdarith.c
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 */
|
|
||||||
151
jdatadst.c
Normal file
151
jdatadst.c
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* jdatadst.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains compression data destination routines for the case of
|
||||||
|
* emitting JPEG data to a file (or any stdio stream). While these routines
|
||||||
|
* are sufficient for most applications, some will want to use a different
|
||||||
|
* destination manager.
|
||||||
|
* IMPORTANT: we assume that fwrite() will correctly transcribe an array of
|
||||||
|
* JOCTETs into 8-bit-wide elements on external storage. If char is wider
|
||||||
|
* than 8 bits on your machine, you may need to do some tweaking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jerror.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Expanded data destination object for stdio output */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_destination_mgr pub; /* public fields */
|
||||||
|
|
||||||
|
FILE * outfile; /* target stream */
|
||||||
|
JOCTET * buffer; /* start of buffer */
|
||||||
|
} my_destination_mgr;
|
||||||
|
|
||||||
|
typedef my_destination_mgr * my_dest_ptr;
|
||||||
|
|
||||||
|
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize destination --- called by jpeg_start_compress
|
||||||
|
* before any data is actually written.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
init_destination (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
|
||||||
|
|
||||||
|
/* Allocate the output buffer --- it will be released when done with image */
|
||||||
|
dest->buffer = (JOCTET *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||||
|
|
||||||
|
dest->pub.next_output_byte = dest->buffer;
|
||||||
|
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empty the output buffer --- called whenever buffer fills up.
|
||||||
|
*
|
||||||
|
* In typical applications, this should write the entire output buffer
|
||||||
|
* (ignoring the current state of next_output_byte & free_in_buffer),
|
||||||
|
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||||
|
* indicating that the buffer has been dumped.
|
||||||
|
*
|
||||||
|
* In applications that need to be able to suspend compression due to output
|
||||||
|
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
|
||||||
|
* In this situation, the compressor will return to its caller (possibly with
|
||||||
|
* an indication that it has not accepted all the supplied scanlines). The
|
||||||
|
* application should resume compression after it has made more room in the
|
||||||
|
* output buffer. Note that there are substantial restrictions on the use of
|
||||||
|
* suspension --- see the documentation.
|
||||||
|
*
|
||||||
|
* When suspending, the compressor will back up to a convenient restart point
|
||||||
|
* (typically the start of the current MCU). next_output_byte & free_in_buffer
|
||||||
|
* indicate where the restart point will be if the current call returns FALSE.
|
||||||
|
* Data beyond this point will be regenerated after resumption, so do not
|
||||||
|
* write it out when emptying the buffer externally.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
empty_output_buffer (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
|
||||||
|
|
||||||
|
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
|
||||||
|
(size_t) OUTPUT_BUF_SIZE)
|
||||||
|
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||||
|
|
||||||
|
dest->pub.next_output_byte = dest->buffer;
|
||||||
|
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminate destination --- called by jpeg_finish_compress
|
||||||
|
* after all data has been written. Usually needs to flush buffer.
|
||||||
|
*
|
||||||
|
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||||
|
* application must deal with any cleanup that should happen even
|
||||||
|
* for error exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
term_destination (j_compress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
|
||||||
|
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
|
||||||
|
|
||||||
|
/* Write any data remaining in the buffer */
|
||||||
|
if (datacount > 0) {
|
||||||
|
if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
|
||||||
|
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||||
|
}
|
||||||
|
fflush(dest->outfile);
|
||||||
|
/* Make sure we wrote the output file OK */
|
||||||
|
if (ferror(dest->outfile))
|
||||||
|
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for output to a stdio stream.
|
||||||
|
* The caller must have already opened the stream, and is responsible
|
||||||
|
* for closing it after finishing compression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
|
||||||
|
{
|
||||||
|
my_dest_ptr dest;
|
||||||
|
|
||||||
|
/* The destination object is made permanent so that multiple JPEG images
|
||||||
|
* can be written to the same file without re-executing jpeg_stdio_dest.
|
||||||
|
* This makes it dangerous to use this manager and a different destination
|
||||||
|
* manager serially with the same JPEG object, because their private object
|
||||||
|
* sizes may be different. Caveat programmer.
|
||||||
|
*/
|
||||||
|
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
|
||||||
|
cinfo->dest = (struct jpeg_destination_mgr *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
SIZEOF(my_destination_mgr));
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = (my_dest_ptr) cinfo->dest;
|
||||||
|
dest->pub.init_destination = init_destination;
|
||||||
|
dest->pub.empty_output_buffer = empty_output_buffer;
|
||||||
|
dest->pub.term_destination = term_destination;
|
||||||
|
dest->outfile = outfile;
|
||||||
|
}
|
||||||
212
jdatasrc.c
Normal file
212
jdatasrc.c
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* jdatasrc.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains decompression data source routines for the case of
|
||||||
|
* reading JPEG data from a file (or any stdio stream). While these routines
|
||||||
|
* are sufficient for most applications, some will want to use a different
|
||||||
|
* source manager.
|
||||||
|
* IMPORTANT: we assume that fread() will correctly transcribe an array of
|
||||||
|
* JOCTETs from 8-bit-wide elements on external storage. If char is wider
|
||||||
|
* than 8 bits on your machine, you may need to do some tweaking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jerror.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Expanded data source object for stdio input */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_source_mgr pub; /* public fields */
|
||||||
|
|
||||||
|
FILE * infile; /* source stream */
|
||||||
|
JOCTET * buffer; /* start of buffer */
|
||||||
|
boolean start_of_file; /* have we gotten any data yet? */
|
||||||
|
} my_source_mgr;
|
||||||
|
|
||||||
|
typedef my_source_mgr * my_src_ptr;
|
||||||
|
|
||||||
|
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize source --- called by jpeg_read_header
|
||||||
|
* before any data is actually read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
init_source (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
|
||||||
|
/* We reset the empty-input-file flag for each image,
|
||||||
|
* but we don't clear the input buffer.
|
||||||
|
* This is correct behavior for reading a series of images from one source.
|
||||||
|
*/
|
||||||
|
src->start_of_file = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill the input buffer --- called whenever buffer is emptied.
|
||||||
|
*
|
||||||
|
* In typical applications, this should read fresh data into the buffer
|
||||||
|
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
||||||
|
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||||
|
* indicating that the buffer has been reloaded. It is not necessary to
|
||||||
|
* fill the buffer entirely, only to obtain at least one more byte.
|
||||||
|
*
|
||||||
|
* There is no such thing as an EOF return. If the end of the file has been
|
||||||
|
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
||||||
|
* the buffer. In most cases, generating a warning message and inserting a
|
||||||
|
* fake EOI marker is the best course of action --- this will allow the
|
||||||
|
* decompressor to output however much of the image is there. However,
|
||||||
|
* the resulting error message is misleading if the real problem is an empty
|
||||||
|
* input file, so we handle that case specially.
|
||||||
|
*
|
||||||
|
* In applications that need to be able to suspend compression due to input
|
||||||
|
* not being available yet, a FALSE return indicates that no more data can be
|
||||||
|
* obtained right now, but more may be forthcoming later. In this situation,
|
||||||
|
* the decompressor will return to its caller (with an indication of the
|
||||||
|
* number of scanlines it has read, if any). The application should resume
|
||||||
|
* decompression after it has loaded more data into the input buffer. Note
|
||||||
|
* that there are substantial restrictions on the use of suspension --- see
|
||||||
|
* the documentation.
|
||||||
|
*
|
||||||
|
* When suspending, the decompressor will back up to a convenient restart point
|
||||||
|
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
|
||||||
|
* indicate where the restart point will be if the current call returns FALSE.
|
||||||
|
* Data beyond this point must be rescanned after resumption, so move it to
|
||||||
|
* the front of the buffer rather than discarding it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
fill_input_buffer (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
size_t nbytes;
|
||||||
|
|
||||||
|
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
|
||||||
|
|
||||||
|
if (nbytes <= 0) {
|
||||||
|
if (src->start_of_file) /* Treat empty input file as fatal error */
|
||||||
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||||
|
WARNMS(cinfo, JWRN_JPEG_EOF);
|
||||||
|
/* Insert a fake EOI marker */
|
||||||
|
src->buffer[0] = (JOCTET) 0xFF;
|
||||||
|
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||||
|
nbytes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->pub.next_input_byte = src->buffer;
|
||||||
|
src->pub.bytes_in_buffer = nbytes;
|
||||||
|
src->start_of_file = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip data --- used to skip over a potentially large amount of
|
||||||
|
* uninteresting data (such as an APPn marker).
|
||||||
|
*
|
||||||
|
* Writers of suspendable-input applications must note that skip_input_data
|
||||||
|
* is not granted the right to give a suspension return. If the skip extends
|
||||||
|
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||||
|
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||||
|
* Arranging for additional bytes to be discarded before reloading the input
|
||||||
|
* buffer is the application writer's problem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
|
||||||
|
/* Just a dumb implementation for now. Could use fseek() except
|
||||||
|
* it doesn't work on pipes. Not clear that being smart is worth
|
||||||
|
* any trouble anyway --- large skips are infrequent.
|
||||||
|
*/
|
||||||
|
if (num_bytes > 0) {
|
||||||
|
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||||
|
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||||
|
(void) fill_input_buffer(cinfo);
|
||||||
|
/* note we assume that fill_input_buffer will never return FALSE,
|
||||||
|
* so suspension need not be handled.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
src->pub.next_input_byte += (size_t) num_bytes;
|
||||||
|
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An additional method that can be provided by data source modules is the
|
||||||
|
* resync_to_restart method for error recovery in the presence of RST markers.
|
||||||
|
* For the moment, this source module just uses the default resync method
|
||||||
|
* provided by the JPEG library. That method assumes that no backtracking
|
||||||
|
* is possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminate source --- called by jpeg_finish_decompress
|
||||||
|
* after all data has been read. Often a no-op.
|
||||||
|
*
|
||||||
|
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||||
|
* application must deal with any cleanup that should happen even
|
||||||
|
* for error exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
term_source (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* no work necessary here */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for input from a stdio stream.
|
||||||
|
* The caller must have already opened the stream, and is responsible
|
||||||
|
* for closing it after finishing decompression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
|
||||||
|
{
|
||||||
|
my_src_ptr src;
|
||||||
|
|
||||||
|
/* The source object and input buffer are made permanent so that a series
|
||||||
|
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||||
|
* only before the first one. (If we discarded the buffer at the end of
|
||||||
|
* one image, we'd likely lose the start of the next one.)
|
||||||
|
* This makes it unsafe to use this manager and a different source
|
||||||
|
* manager serially with the same JPEG object. Caveat programmer.
|
||||||
|
*/
|
||||||
|
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||||
|
cinfo->src = (struct jpeg_source_mgr *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
SIZEOF(my_source_mgr));
|
||||||
|
src = (my_src_ptr) cinfo->src;
|
||||||
|
src->buffer = (JOCTET *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
INPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||||
|
}
|
||||||
|
|
||||||
|
src = (my_src_ptr) cinfo->src;
|
||||||
|
src->pub.init_source = init_source;
|
||||||
|
src->pub.fill_input_buffer = fill_input_buffer;
|
||||||
|
src->pub.skip_input_data = skip_input_data;
|
||||||
|
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||||
|
src->pub.term_source = term_source;
|
||||||
|
src->infile = infile;
|
||||||
|
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||||
|
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||||
|
}
|
||||||
789
jdcoefct.c
Normal file
789
jdcoefct.c
Normal file
@@ -0,0 +1,789 @@
|
|||||||
|
/*
|
||||||
|
* jdcoefct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified to improve performance.
|
||||||
|
* Last Modified : December 18, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains the coefficient buffer controller for decompression.
|
||||||
|
* This controller is the top level of the JPEG decompressor proper.
|
||||||
|
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
|
||||||
|
*
|
||||||
|
* In buffered-image mode, this controller is the interface between
|
||||||
|
* input-oriented processing and output-oriented processing.
|
||||||
|
* Also, the input side (only) is used when reading a file for transcoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
/* Block smoothing is only applicable for progressive JPEG, so: */
|
||||||
|
#ifndef D_PROGRESSIVE_SUPPORTED
|
||||||
|
#undef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_d_coef_controller pub; /* public fields */
|
||||||
|
|
||||||
|
/* These variables keep track of the current location of the input side. */
|
||||||
|
/* cinfo->input_iMCU_row is also used for this. */
|
||||||
|
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||||
|
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||||
|
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||||
|
|
||||||
|
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||||
|
|
||||||
|
/* In single-pass modes, it's sufficient to buffer just one MCU.
|
||||||
|
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
|
||||||
|
* and let the entropy decoder write into that workspace each time.
|
||||||
|
* (On 80x86, the workspace is FAR even though it's not really very big;
|
||||||
|
* this is to keep the module interfaces unchanged when a large coefficient
|
||||||
|
* buffer is necessary.)
|
||||||
|
* In multi-pass modes, this array points to the current MCU's blocks
|
||||||
|
* within the virtual arrays; it is used only by the input side.
|
||||||
|
*/
|
||||||
|
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||||
|
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
/* When doing block smoothing, we latch coefficient Al values here */
|
||||||
|
int * coef_bits_latch;
|
||||||
|
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
||||||
|
#endif
|
||||||
|
} my_coef_controller;
|
||||||
|
|
||||||
|
typedef my_coef_controller * my_coef_ptr;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(int) decompress_onepass
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
METHODDEF(int) decompress_data
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||||
|
#endif
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
|
||||||
|
METHODDEF(int) decompress_smooth_data
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
start_iMCU_row (j_decompress_ptr cinfo)
|
||||||
|
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||||
|
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||||
|
* But at the bottom of the image, process only what's left.
|
||||||
|
*/
|
||||||
|
if (cinfo->comps_in_scan > 1) {
|
||||||
|
coef->MCU_rows_per_iMCU_row = 1;
|
||||||
|
} else {
|
||||||
|
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||||
|
else
|
||||||
|
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
coef->MCU_ctr = 0;
|
||||||
|
coef->MCU_vert_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an input processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_input_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
cinfo->input_iMCU_row = 0;
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an output processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_output_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
|
||||||
|
/* If multipass, check to see whether to use block smoothing on this pass */
|
||||||
|
if (coef->pub.coef_arrays != NULL) {
|
||||||
|
if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
|
||||||
|
coef->pub.decompress_data = decompress_smooth_data;
|
||||||
|
else
|
||||||
|
coef->pub.decompress_data = decompress_data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cinfo->output_iMCU_row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NEED_FAR_POINTERS
|
||||||
|
#undef jzero_far
|
||||||
|
#define jzero_far(target, bytestozero) MEMZERO(target, bytestozero)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompress and return some data in the single-pass case.
|
||||||
|
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||||
|
* Input and output must run in lockstep since we have only a one-MCU buffer.
|
||||||
|
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||||
|
*
|
||||||
|
* NB: output_buf contains a plane for each component in image,
|
||||||
|
* which we index according to the component's SOF position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||||
|
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
int blkn, ci, ctr, xindex, yindex, yoffset;
|
||||||
|
JSAMPARRAY output_ptr;
|
||||||
|
JDIMENSION output_col;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
inverse_DCT_method_ptr inverse_DCT;
|
||||||
|
JSAMPARRAY output_ptr_blk[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
JDIMENSION output_col_off[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
jpeg_component_info *compptr_blk[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
inverse_DCT_method_ptr inverse_DCT_blk_1[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
inverse_DCT_method_ptr inverse_DCT_blk_2[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
inverse_DCT_method_ptr *inverse_DCT_blk;
|
||||||
|
|
||||||
|
/* Loop to process as much as one whole iMCU row */
|
||||||
|
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||||
|
yoffset++) {
|
||||||
|
/* Determine where data should go in output_buf and do the IDCT thing.
|
||||||
|
* We skip dummy blocks at the right and bottom edges (but blkn gets
|
||||||
|
* incremented past them!). Note the inner loop relies on having
|
||||||
|
* allocated the MCU_buffer[] blocks sequentially.
|
||||||
|
*/
|
||||||
|
blkn = 0; /* index of current DCT block within MCU */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Don't bother to IDCT an uninteresting component. */
|
||||||
|
if (! compptr->component_needed) {
|
||||||
|
for (ctr = compptr->MCU_blocks; ctr > 0; ctr--) {
|
||||||
|
inverse_DCT_blk_1[blkn] = inverse_DCT_blk_2[blkn] = NULL;
|
||||||
|
blkn++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
|
||||||
|
output_ptr = output_buf[compptr->component_index] +
|
||||||
|
yoffset * compptr->DCT_scaled_size;
|
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||||
|
if (cinfo->input_iMCU_row < last_iMCU_row ||
|
||||||
|
yoffset+yindex < compptr->last_row_height) {
|
||||||
|
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
|
||||||
|
compptr_blk[blkn] = compptr;
|
||||||
|
output_ptr_blk[blkn] = output_ptr;
|
||||||
|
output_col_off[blkn] = xindex * compptr->DCT_scaled_size;
|
||||||
|
inverse_DCT_blk_1[blkn] = inverse_DCT;
|
||||||
|
inverse_DCT_blk_2[blkn] = (xindex < compptr->last_col_width) ?
|
||||||
|
inverse_DCT : NULL;
|
||||||
|
blkn++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (ctr = compptr->MCU_width; ctr > 0; ctr--) {
|
||||||
|
inverse_DCT_blk_1[blkn] = inverse_DCT_blk_2[blkn] = NULL;
|
||||||
|
blkn++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output_ptr += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
|
||||||
|
MCU_col_num++) {
|
||||||
|
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
|
||||||
|
jzero_far((void FAR *) coef->MCU_buffer[0],
|
||||||
|
(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
|
||||||
|
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||||
|
/* Suspension forced; update state counters and exit */
|
||||||
|
coef->MCU_vert_offset = yoffset;
|
||||||
|
coef->MCU_ctr = MCU_col_num;
|
||||||
|
return JPEG_SUSPENDED;
|
||||||
|
}
|
||||||
|
inverse_DCT_blk = (MCU_col_num < last_MCU_col) ? inverse_DCT_blk_1
|
||||||
|
: inverse_DCT_blk_2;
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
inverse_DCT = inverse_DCT_blk[blkn];
|
||||||
|
if (inverse_DCT == NULL)
|
||||||
|
continue;
|
||||||
|
compptr = compptr_blk[blkn];
|
||||||
|
output_col = MCU_col_num * compptr->MCU_sample_width +
|
||||||
|
output_col_off[blkn];
|
||||||
|
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn],
|
||||||
|
output_ptr_blk[blkn], output_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||||
|
coef->MCU_ctr = 0;
|
||||||
|
}
|
||||||
|
/* Completed the iMCU row, advance counters for next one */
|
||||||
|
cinfo->output_iMCU_row++;
|
||||||
|
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
return JPEG_ROW_COMPLETED;
|
||||||
|
}
|
||||||
|
/* Completed the scan */
|
||||||
|
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||||
|
return JPEG_SCAN_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy consume-input routine for single-pass operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
dummy_consume_data (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
return JPEG_SUSPENDED; /* Always indicate nothing was done */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Consume input data and store it in the full-image coefficient buffer.
|
||||||
|
* We read as much as one fully interleaved MCU row ("iMCU" row) per call,
|
||||||
|
* ie, v_samp_factor block rows for each component in the scan.
|
||||||
|
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
consume_data (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||||
|
int blkn, ci, xindex, yindex, yoffset;
|
||||||
|
JDIMENSION start_col;
|
||||||
|
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||||
|
JBLOCKROW buffer_ptr;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
int MCU_width[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
JBLOCKROW MCU_buffer_base[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
|
||||||
|
/* Align the virtual buffers for the components used in this scan. */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
buffer[ci] = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
|
||||||
|
cinfo->input_iMCU_row * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||||
|
/* Note: entropy decoder expects buffer to be zeroed,
|
||||||
|
* but this is handled automatically by the memory manager
|
||||||
|
* because we requested a pre-zeroed array.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop to process one whole iMCU row */
|
||||||
|
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||||
|
yoffset++) {
|
||||||
|
/* Construct list of pointers to DCT blocks belonging to this MCU */
|
||||||
|
blkn = 0; /* index of current DCT block within MCU */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||||
|
buffer_ptr = buffer[ci][yindex+yoffset];
|
||||||
|
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
|
||||||
|
MCU_width[blkn] = compptr->MCU_width;
|
||||||
|
MCU_buffer_base[blkn] = buffer_ptr++;
|
||||||
|
blkn++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
|
||||||
|
MCU_col_num++) {
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
start_col = MCU_col_num * MCU_width[blkn];
|
||||||
|
coef->MCU_buffer[blkn] = MCU_buffer_base[blkn] + start_col;
|
||||||
|
}
|
||||||
|
/* Try to fetch the MCU. */
|
||||||
|
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||||
|
/* Suspension forced; update state counters and exit */
|
||||||
|
coef->MCU_vert_offset = yoffset;
|
||||||
|
coef->MCU_ctr = MCU_col_num;
|
||||||
|
return JPEG_SUSPENDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||||
|
coef->MCU_ctr = 0;
|
||||||
|
}
|
||||||
|
/* Completed the iMCU row, advance counters for next one */
|
||||||
|
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
|
||||||
|
start_iMCU_row(cinfo);
|
||||||
|
return JPEG_ROW_COMPLETED;
|
||||||
|
}
|
||||||
|
/* Completed the scan */
|
||||||
|
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||||
|
return JPEG_SCAN_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompress and return some data in the multi-pass case.
|
||||||
|
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||||
|
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||||
|
*
|
||||||
|
* NB: output_buf contains a plane for each component in image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
JDIMENSION block_num;
|
||||||
|
int ci, block_row, block_rows;
|
||||||
|
JBLOCKARRAY buffer;
|
||||||
|
JBLOCKROW buffer_ptr;
|
||||||
|
JSAMPARRAY output_ptr;
|
||||||
|
JDIMENSION output_col;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
inverse_DCT_method_ptr inverse_DCT;
|
||||||
|
|
||||||
|
/* Force some input to be done if we are getting ahead of the input. */
|
||||||
|
while (cinfo->input_scan_number < cinfo->output_scan_number ||
|
||||||
|
(cinfo->input_scan_number == cinfo->output_scan_number &&
|
||||||
|
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
|
||||||
|
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
|
||||||
|
return JPEG_SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, output from the virtual arrays. */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Don't bother to IDCT an uninteresting component. */
|
||||||
|
if (! compptr->component_needed)
|
||||||
|
continue;
|
||||||
|
/* Align the virtual buffer for this component. */
|
||||||
|
buffer = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||||
|
cinfo->output_iMCU_row * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||||
|
/* Count non-dummy DCT block rows in this iMCU row. */
|
||||||
|
if (cinfo->output_iMCU_row < last_iMCU_row)
|
||||||
|
block_rows = compptr->v_samp_factor;
|
||||||
|
else {
|
||||||
|
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||||
|
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||||
|
}
|
||||||
|
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||||
|
output_ptr = output_buf[ci];
|
||||||
|
/* Loop over all DCT blocks to be processed. */
|
||||||
|
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||||
|
buffer_ptr = buffer[block_row];
|
||||||
|
output_col = 0;
|
||||||
|
for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
|
||||||
|
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
|
||||||
|
output_ptr, output_col);
|
||||||
|
buffer_ptr++;
|
||||||
|
output_col += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
output_ptr += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||||
|
return JPEG_ROW_COMPLETED;
|
||||||
|
return JPEG_SCAN_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code applies interblock smoothing as described by section K.8
|
||||||
|
* of the JPEG standard: the first 5 AC coefficients are estimated from
|
||||||
|
* the DC values of a DCT block and its 8 neighboring blocks.
|
||||||
|
* We apply smoothing only for progressive JPEG decoding, and only if
|
||||||
|
* the coefficients it can estimate are not yet known to full precision.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Natural-order array positions of the first 5 zigzag-order coefficients */
|
||||||
|
#define Q01_POS 1
|
||||||
|
#define Q10_POS 8
|
||||||
|
#define Q20_POS 16
|
||||||
|
#define Q11_POS 9
|
||||||
|
#define Q02_POS 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine whether block smoothing is applicable and safe.
|
||||||
|
* We also latch the current states of the coef_bits[] entries for the
|
||||||
|
* AC coefficients; otherwise, if the input side of the decompressor
|
||||||
|
* advances into a new scan, we might think the coefficients are known
|
||||||
|
* more accurately than they really are.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
smoothing_ok (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
boolean smoothing_useful = FALSE;
|
||||||
|
int ci, coefi;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JQUANT_TBL * qtable;
|
||||||
|
int * coef_bits;
|
||||||
|
int * coef_bits_latch;
|
||||||
|
|
||||||
|
if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Allocate latch area if not already done */
|
||||||
|
if (coef->coef_bits_latch == NULL)
|
||||||
|
coef->coef_bits_latch = (int *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
cinfo->num_components *
|
||||||
|
(SAVED_COEFS * SIZEOF(int)));
|
||||||
|
coef_bits_latch = coef->coef_bits_latch;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* All components' quantization values must already be latched. */
|
||||||
|
if ((qtable = compptr->quant_table) == NULL)
|
||||||
|
return FALSE;
|
||||||
|
/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
|
||||||
|
if (qtable->quantval[0] == 0 ||
|
||||||
|
qtable->quantval[Q01_POS] == 0 ||
|
||||||
|
qtable->quantval[Q10_POS] == 0 ||
|
||||||
|
qtable->quantval[Q20_POS] == 0 ||
|
||||||
|
qtable->quantval[Q11_POS] == 0 ||
|
||||||
|
qtable->quantval[Q02_POS] == 0)
|
||||||
|
return FALSE;
|
||||||
|
/* DC values must be at least partly known for all components. */
|
||||||
|
coef_bits = cinfo->coef_bits[ci];
|
||||||
|
if (coef_bits[0] < 0)
|
||||||
|
return FALSE;
|
||||||
|
/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
|
||||||
|
for (coefi = 1; coefi <= 5; coefi++) {
|
||||||
|
coef_bits_latch[coefi] = coef_bits[coefi];
|
||||||
|
if (coef_bits[coefi] != 0)
|
||||||
|
smoothing_useful = TRUE;
|
||||||
|
}
|
||||||
|
coef_bits_latch += SAVED_COEFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return smoothing_useful;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIMD Ext: Most of SSE/SSE2 instructions require that the memory address
|
||||||
|
* is aligned to a 16-byte boundary; if not, a general-protection exception
|
||||||
|
* (#GP) is generated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ALIGN_SIZE 16 /* sizeof SSE/SSE2 register */
|
||||||
|
#define ALIGN_MEM(p,a) ((void *) (((size_t) (p) + (a) - 1) & -(a)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variant of decompress_data for use when doing block smoothing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||||
|
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||||
|
JDIMENSION block_num, last_block_column;
|
||||||
|
int ci, block_row, block_rows, access_rows;
|
||||||
|
JBLOCKARRAY buffer;
|
||||||
|
JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
|
||||||
|
JSAMPARRAY output_ptr;
|
||||||
|
JDIMENSION output_col;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
inverse_DCT_method_ptr inverse_DCT;
|
||||||
|
boolean first_row, last_row;
|
||||||
|
JCOEF workspace[DCTSIZE2 + ALIGN_SIZE/sizeof(JCOEF)];
|
||||||
|
JCOEF * workptr = (JCOEF *) ALIGN_MEM(workspace, ALIGN_SIZE);
|
||||||
|
int *coef_bits;
|
||||||
|
JQUANT_TBL *quanttbl;
|
||||||
|
INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
|
||||||
|
int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
|
||||||
|
int Al, pred;
|
||||||
|
|
||||||
|
/* Force some input to be done if we are getting ahead of the input. */
|
||||||
|
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
|
||||||
|
! cinfo->inputctl->eoi_reached) {
|
||||||
|
if (cinfo->input_scan_number == cinfo->output_scan_number) {
|
||||||
|
/* If input is working on current scan, we ordinarily want it to
|
||||||
|
* have completed the current row. But if input scan is DC,
|
||||||
|
* we want it to keep one row ahead so that next block row's DC
|
||||||
|
* values are up to date.
|
||||||
|
*/
|
||||||
|
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
|
||||||
|
if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
|
||||||
|
return JPEG_SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, output from the virtual arrays. */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Don't bother to IDCT an uninteresting component. */
|
||||||
|
if (! compptr->component_needed)
|
||||||
|
continue;
|
||||||
|
/* Count non-dummy DCT block rows in this iMCU row. */
|
||||||
|
if (cinfo->output_iMCU_row < last_iMCU_row) {
|
||||||
|
block_rows = compptr->v_samp_factor;
|
||||||
|
access_rows = block_rows * 2; /* this and next iMCU row */
|
||||||
|
last_row = FALSE;
|
||||||
|
} else {
|
||||||
|
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||||
|
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||||
|
access_rows = block_rows; /* this iMCU row only */
|
||||||
|
last_row = TRUE;
|
||||||
|
}
|
||||||
|
/* Align the virtual buffer for this component. */
|
||||||
|
if (cinfo->output_iMCU_row > 0) {
|
||||||
|
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
|
||||||
|
buffer = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||||
|
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
|
||||||
|
(JDIMENSION) access_rows, FALSE);
|
||||||
|
buffer += compptr->v_samp_factor; /* point to current iMCU row */
|
||||||
|
first_row = FALSE;
|
||||||
|
} else {
|
||||||
|
buffer = (*cinfo->mem->access_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||||
|
(JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
|
||||||
|
first_row = TRUE;
|
||||||
|
}
|
||||||
|
/* Fetch component-dependent info */
|
||||||
|
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
|
||||||
|
quanttbl = compptr->quant_table;
|
||||||
|
Q00 = quanttbl->quantval[0];
|
||||||
|
Q01 = quanttbl->quantval[Q01_POS];
|
||||||
|
Q10 = quanttbl->quantval[Q10_POS];
|
||||||
|
Q20 = quanttbl->quantval[Q20_POS];
|
||||||
|
Q11 = quanttbl->quantval[Q11_POS];
|
||||||
|
Q02 = quanttbl->quantval[Q02_POS];
|
||||||
|
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||||
|
output_ptr = output_buf[ci];
|
||||||
|
/* Loop over all DCT blocks to be processed. */
|
||||||
|
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||||
|
buffer_ptr = buffer[block_row];
|
||||||
|
if (first_row && block_row == 0)
|
||||||
|
prev_block_row = buffer_ptr;
|
||||||
|
else
|
||||||
|
prev_block_row = buffer[block_row-1];
|
||||||
|
if (last_row && block_row == block_rows-1)
|
||||||
|
next_block_row = buffer_ptr;
|
||||||
|
else
|
||||||
|
next_block_row = buffer[block_row+1];
|
||||||
|
/* We fetch the surrounding DC values using a sliding-register approach.
|
||||||
|
* Initialize all nine here so as to do the right thing on narrow pics.
|
||||||
|
*/
|
||||||
|
DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
|
||||||
|
DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
|
||||||
|
DC7 = DC8 = DC9 = (int) next_block_row[0][0];
|
||||||
|
output_col = 0;
|
||||||
|
last_block_column = compptr->width_in_blocks - 1;
|
||||||
|
for (block_num = 0; block_num <= last_block_column; block_num++) {
|
||||||
|
/* Fetch current DCT block into workspace so we can modify it. */
|
||||||
|
jcopy_block_row(buffer_ptr, (JBLOCKROW) workptr, (JDIMENSION) 1);
|
||||||
|
/* Update DC values */
|
||||||
|
if (block_num < last_block_column) {
|
||||||
|
DC3 = (int) prev_block_row[1][0];
|
||||||
|
DC6 = (int) buffer_ptr[1][0];
|
||||||
|
DC9 = (int) next_block_row[1][0];
|
||||||
|
}
|
||||||
|
/* Compute coefficient estimates per K.8.
|
||||||
|
* An estimate is applied only if coefficient is still zero,
|
||||||
|
* and is not known to be fully accurate.
|
||||||
|
*/
|
||||||
|
/* AC01 */
|
||||||
|
if ((Al=coef_bits[1]) != 0 && workptr[1] == 0) {
|
||||||
|
num = 36 * Q00 * (DC4 - DC6);
|
||||||
|
if (num >= 0) {
|
||||||
|
pred = (int) (((Q01<<7) + num) / (Q01<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
} else {
|
||||||
|
pred = (int) (((Q01<<7) - num) / (Q01<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
pred = -pred;
|
||||||
|
}
|
||||||
|
workptr[1] = (JCOEF) pred;
|
||||||
|
}
|
||||||
|
/* AC10 */
|
||||||
|
if ((Al=coef_bits[2]) != 0 && workptr[8] == 0) {
|
||||||
|
num = 36 * Q00 * (DC2 - DC8);
|
||||||
|
if (num >= 0) {
|
||||||
|
pred = (int) (((Q10<<7) + num) / (Q10<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
} else {
|
||||||
|
pred = (int) (((Q10<<7) - num) / (Q10<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
pred = -pred;
|
||||||
|
}
|
||||||
|
workptr[8] = (JCOEF) pred;
|
||||||
|
}
|
||||||
|
/* AC20 */
|
||||||
|
if ((Al=coef_bits[3]) != 0 && workptr[16] == 0) {
|
||||||
|
num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
|
||||||
|
if (num >= 0) {
|
||||||
|
pred = (int) (((Q20<<7) + num) / (Q20<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
} else {
|
||||||
|
pred = (int) (((Q20<<7) - num) / (Q20<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
pred = -pred;
|
||||||
|
}
|
||||||
|
workptr[16] = (JCOEF) pred;
|
||||||
|
}
|
||||||
|
/* AC11 */
|
||||||
|
if ((Al=coef_bits[4]) != 0 && workptr[9] == 0) {
|
||||||
|
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
|
||||||
|
if (num >= 0) {
|
||||||
|
pred = (int) (((Q11<<7) + num) / (Q11<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
} else {
|
||||||
|
pred = (int) (((Q11<<7) - num) / (Q11<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
pred = -pred;
|
||||||
|
}
|
||||||
|
workptr[9] = (JCOEF) pred;
|
||||||
|
}
|
||||||
|
/* AC02 */
|
||||||
|
if ((Al=coef_bits[5]) != 0 && workptr[2] == 0) {
|
||||||
|
num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
|
||||||
|
if (num >= 0) {
|
||||||
|
pred = (int) (((Q02<<7) + num) / (Q02<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
} else {
|
||||||
|
pred = (int) (((Q02<<7) - num) / (Q02<<8));
|
||||||
|
if (Al > 0 && pred >= (1<<Al))
|
||||||
|
pred = (1<<Al)-1;
|
||||||
|
pred = -pred;
|
||||||
|
}
|
||||||
|
workptr[2] = (JCOEF) pred;
|
||||||
|
}
|
||||||
|
/* OK, do the IDCT */
|
||||||
|
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workptr,
|
||||||
|
output_ptr, output_col);
|
||||||
|
/* Advance for next column */
|
||||||
|
DC1 = DC2; DC2 = DC3;
|
||||||
|
DC4 = DC5; DC5 = DC6;
|
||||||
|
DC7 = DC8; DC8 = DC9;
|
||||||
|
buffer_ptr++, prev_block_row++, next_block_row++;
|
||||||
|
output_col += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
output_ptr += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||||
|
return JPEG_ROW_COMPLETED;
|
||||||
|
return JPEG_SCAN_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BLOCK_SMOOTHING_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize coefficient buffer controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_coef_ptr coef;
|
||||||
|
|
||||||
|
coef = (my_coef_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_coef_controller));
|
||||||
|
cinfo->coef = (struct jpeg_d_coef_controller *) coef;
|
||||||
|
coef->pub.start_input_pass = start_input_pass;
|
||||||
|
coef->pub.start_output_pass = start_output_pass;
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
coef->coef_bits_latch = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create the coefficient buffer. */
|
||||||
|
if (need_full_buffer) {
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
/* Allocate a full-image virtual array for each component, */
|
||||||
|
/* padded to a multiple of samp_factor DCT blocks in each direction. */
|
||||||
|
/* Note we ask for a pre-zeroed array. */
|
||||||
|
int ci, access_rows;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
access_rows = compptr->v_samp_factor;
|
||||||
|
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||||
|
/* If block smoothing could be used, need a bigger window */
|
||||||
|
if (cinfo->progressive_mode)
|
||||||
|
access_rows *= 3;
|
||||||
|
#endif
|
||||||
|
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
|
||||||
|
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||||
|
(long) compptr->h_samp_factor),
|
||||||
|
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||||
|
(long) compptr->v_samp_factor),
|
||||||
|
(JDIMENSION) access_rows);
|
||||||
|
}
|
||||||
|
coef->pub.consume_data = consume_data;
|
||||||
|
coef->pub.decompress_data = decompress_data;
|
||||||
|
coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* We only need a single-MCU buffer. */
|
||||||
|
JBLOCKROW buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buffer = (JBLOCKROW)
|
||||||
|
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||||
|
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
|
||||||
|
coef->MCU_buffer[i] = buffer + i;
|
||||||
|
}
|
||||||
|
coef->pub.consume_data = dummy_consume_data;
|
||||||
|
coef->pub.decompress_data = decompress_onepass;
|
||||||
|
coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
|
||||||
|
}
|
||||||
|
}
|
||||||
438
jdcolmmx.asm
Normal file
438
jdcolmmx.asm
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
;
|
||||||
|
; jdcolmmx.asm - colorspace conversion (MMX)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : February 4, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
%ifdef JDCOLOR_YCCRGB_MMX_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%define SCALEBITS 16
|
||||||
|
|
||||||
|
F_0_344 equ 22554 ; FIX(0.34414)
|
||||||
|
F_0_714 equ 46802 ; FIX(0.71414)
|
||||||
|
F_1_402 equ 91881 ; FIX(1.40200)
|
||||||
|
F_1_772 equ 116130 ; FIX(1.77200)
|
||||||
|
F_0_402 equ (F_1_402 - 65536) ; FIX(1.40200) - FIX(1)
|
||||||
|
F_0_285 equ ( 65536 - F_0_714) ; FIX(1) - FIX(0.71414)
|
||||||
|
F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200)
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_CONST
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
global EXTN(jconst_ycc_rgb_convert_mmx)
|
||||||
|
|
||||||
|
EXTN(jconst_ycc_rgb_convert_mmx):
|
||||||
|
|
||||||
|
PW_F0402 times 4 dw F_0_402
|
||||||
|
PW_MF0228 times 4 dw -F_0_228
|
||||||
|
PW_MF0344_F0285 times 2 dw -F_0_344, F_0_285
|
||||||
|
PW_ONE times 4 dw 1
|
||||||
|
PD_ONEHALF times 2 dd 1 << (SCALEBITS-1)
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Convert some rows of samples to the output colorspace.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_ycc_rgb_convert_mmx (j_decompress_ptr cinfo,
|
||||||
|
; JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
; JSAMPARRAY output_buf, int num_rows)
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_decompress_ptr cinfo
|
||||||
|
%define input_buf(b) (b)+12 ; JSAMPIMAGE input_buf
|
||||||
|
%define input_row(b) (b)+16 ; JDIMENSION input_row
|
||||||
|
%define output_buf(b) (b)+20 ; JSAMPARRAY output_buf
|
||||||
|
%define num_rows(b) (b)+24 ; int num_rows
|
||||||
|
|
||||||
|
%define original_ebp ebp+0
|
||||||
|
%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_MMWORD ; mmword wk[WK_NUM]
|
||||||
|
%define WK_NUM 2
|
||||||
|
%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_ycc_rgb_convert_mmx)
|
||||||
|
|
||||||
|
EXTN(jpeg_ycc_rgb_convert_mmx):
|
||||||
|
push ebp
|
||||||
|
mov eax,esp ; eax = original ebp
|
||||||
|
sub esp, byte 4
|
||||||
|
and esp, byte (-SIZEOF_MMWORD) ; align to 64 bits
|
||||||
|
mov [esp],eax
|
||||||
|
mov ebp,esp ; ebp = aligned ebp
|
||||||
|
lea esp, [wk(0)]
|
||||||
|
pushpic eax ; make a room for GOT address
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
get_GOT ebx ; get GOT address
|
||||||
|
movpic POINTER [gotptr], ebx ; save GOT address
|
||||||
|
|
||||||
|
mov ecx, POINTER [cinfo(eax)]
|
||||||
|
mov ecx, JDIMENSION [jdstruct_output_width(ecx)] ; num_cols
|
||||||
|
test ecx,ecx
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPIMAGE [input_buf(eax)]
|
||||||
|
mov ecx, JDIMENSION [input_row(eax)]
|
||||||
|
mov esi, JSAMPARRAY [edi+0*SIZEOF_JSAMPARRAY]
|
||||||
|
mov ebx, JSAMPARRAY [edi+1*SIZEOF_JSAMPARRAY]
|
||||||
|
mov edx, JSAMPARRAY [edi+2*SIZEOF_JSAMPARRAY]
|
||||||
|
lea esi, [esi+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea ebx, [ebx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea edx, [edx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPARRAY [output_buf(eax)]
|
||||||
|
mov eax, INT [num_rows(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push eax
|
||||||
|
push edi
|
||||||
|
push edx
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push ecx ; col
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr0
|
||||||
|
mov ebx, JSAMPROW [ebx] ; inptr1
|
||||||
|
mov edx, JSAMPROW [edx] ; inptr2
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
movpic eax, POINTER [gotptr] ; load GOT address (eax)
|
||||||
|
alignx 16,7
|
||||||
|
.columnloop:
|
||||||
|
|
||||||
|
movq mm5, MMWORD [ebx] ; mm5=Cb(01234567)
|
||||||
|
movq mm1, MMWORD [edx] ; mm1=Cr(01234567)
|
||||||
|
|
||||||
|
pcmpeqw mm4,mm4
|
||||||
|
pcmpeqw mm7,mm7
|
||||||
|
psrlw mm4,BYTE_BIT
|
||||||
|
psllw mm7,7 ; mm7={0xFF80 0xFF80 0xFF80 0xFF80}
|
||||||
|
movq mm0,mm4 ; mm0=mm4={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
pand mm4,mm5 ; mm4=Cb(0246)=CbE
|
||||||
|
psrlw mm5,BYTE_BIT ; mm5=Cb(1357)=CbO
|
||||||
|
pand mm0,mm1 ; mm0=Cr(0246)=CrE
|
||||||
|
psrlw mm1,BYTE_BIT ; mm1=Cr(1357)=CrO
|
||||||
|
|
||||||
|
paddw mm4,mm7
|
||||||
|
paddw mm5,mm7
|
||||||
|
paddw mm0,mm7
|
||||||
|
paddw mm1,mm7
|
||||||
|
|
||||||
|
; (Original)
|
||||||
|
; R = Y + 1.40200 * Cr
|
||||||
|
; G = Y - 0.34414 * Cb - 0.71414 * Cr
|
||||||
|
; B = Y + 1.77200 * Cb
|
||||||
|
;
|
||||||
|
; (This implementation)
|
||||||
|
; R = Y + 0.40200 * Cr + Cr
|
||||||
|
; G = Y - 0.34414 * Cb + 0.28586 * Cr - Cr
|
||||||
|
; B = Y - 0.22800 * Cb + Cb + Cb
|
||||||
|
|
||||||
|
movq mm2,mm4 ; mm2=CbE
|
||||||
|
movq mm3,mm5 ; mm3=CbO
|
||||||
|
paddw mm4,mm4 ; mm4=2*CbE
|
||||||
|
paddw mm5,mm5 ; mm5=2*CbO
|
||||||
|
movq mm6,mm0 ; mm6=CrE
|
||||||
|
movq mm7,mm1 ; mm7=CrO
|
||||||
|
paddw mm0,mm0 ; mm0=2*CrE
|
||||||
|
paddw mm1,mm1 ; mm1=2*CrO
|
||||||
|
|
||||||
|
pmulhw mm4,[GOTOFF(eax,PW_MF0228)] ; mm4=(2*CbE * -FIX(0.22800))
|
||||||
|
pmulhw mm5,[GOTOFF(eax,PW_MF0228)] ; mm5=(2*CbO * -FIX(0.22800))
|
||||||
|
pmulhw mm0,[GOTOFF(eax,PW_F0402)] ; mm0=(2*CrE * FIX(0.40200))
|
||||||
|
pmulhw mm1,[GOTOFF(eax,PW_F0402)] ; mm1=(2*CrO * FIX(0.40200))
|
||||||
|
|
||||||
|
paddw mm4,[GOTOFF(eax,PW_ONE)]
|
||||||
|
paddw mm5,[GOTOFF(eax,PW_ONE)]
|
||||||
|
psraw mm4,1 ; mm4=(CbE * -FIX(0.22800))
|
||||||
|
psraw mm5,1 ; mm5=(CbO * -FIX(0.22800))
|
||||||
|
paddw mm0,[GOTOFF(eax,PW_ONE)]
|
||||||
|
paddw mm1,[GOTOFF(eax,PW_ONE)]
|
||||||
|
psraw mm0,1 ; mm0=(CrE * FIX(0.40200))
|
||||||
|
psraw mm1,1 ; mm1=(CrO * FIX(0.40200))
|
||||||
|
|
||||||
|
paddw mm4,mm2
|
||||||
|
paddw mm5,mm3
|
||||||
|
paddw mm4,mm2 ; mm4=(CbE * FIX(1.77200))=(B-Y)E
|
||||||
|
paddw mm5,mm3 ; mm5=(CbO * FIX(1.77200))=(B-Y)O
|
||||||
|
paddw mm0,mm6 ; mm0=(CrE * FIX(1.40200))=(R-Y)E
|
||||||
|
paddw mm1,mm7 ; mm1=(CrO * FIX(1.40200))=(R-Y)O
|
||||||
|
|
||||||
|
movq MMWORD [wk(0)], mm4 ; wk(0)=(B-Y)E
|
||||||
|
movq MMWORD [wk(1)], mm5 ; wk(1)=(B-Y)O
|
||||||
|
|
||||||
|
movq mm4,mm2
|
||||||
|
movq mm5,mm3
|
||||||
|
punpcklwd mm2,mm6
|
||||||
|
punpckhwd mm4,mm6
|
||||||
|
pmaddwd mm2,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
pmaddwd mm4,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
punpcklwd mm3,mm7
|
||||||
|
punpckhwd mm5,mm7
|
||||||
|
pmaddwd mm3,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
pmaddwd mm5,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
|
||||||
|
paddd mm2,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
paddd mm4,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
psrad mm2,SCALEBITS
|
||||||
|
psrad mm4,SCALEBITS
|
||||||
|
paddd mm3,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
paddd mm5,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
psrad mm3,SCALEBITS
|
||||||
|
psrad mm5,SCALEBITS
|
||||||
|
|
||||||
|
packssdw mm2,mm4 ; mm2=CbE*-FIX(0.344)+CrE*FIX(0.285)
|
||||||
|
packssdw mm3,mm5 ; mm3=CbO*-FIX(0.344)+CrO*FIX(0.285)
|
||||||
|
psubw mm2,mm6 ; mm2=CbE*-FIX(0.344)+CrE*-FIX(0.714)=(G-Y)E
|
||||||
|
psubw mm3,mm7 ; mm3=CbO*-FIX(0.344)+CrO*-FIX(0.714)=(G-Y)O
|
||||||
|
|
||||||
|
movq mm5, MMWORD [esi] ; mm5=Y(01234567)
|
||||||
|
|
||||||
|
pcmpeqw mm4,mm4
|
||||||
|
psrlw mm4,BYTE_BIT ; mm4={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
pand mm4,mm5 ; mm4=Y(0246)=YE
|
||||||
|
psrlw mm5,BYTE_BIT ; mm5=Y(1357)=YO
|
||||||
|
|
||||||
|
paddw mm0,mm4 ; mm0=((R-Y)E+YE)=RE=(R0 R2 R4 R6)
|
||||||
|
paddw mm1,mm5 ; mm1=((R-Y)O+YO)=RO=(R1 R3 R5 R7)
|
||||||
|
packuswb mm0,mm0 ; mm0=(R0 R2 R4 R6 ** ** ** **)
|
||||||
|
packuswb mm1,mm1 ; mm1=(R1 R3 R5 R7 ** ** ** **)
|
||||||
|
|
||||||
|
paddw mm2,mm4 ; mm2=((G-Y)E+YE)=GE=(G0 G2 G4 G6)
|
||||||
|
paddw mm3,mm5 ; mm3=((G-Y)O+YO)=GO=(G1 G3 G5 G7)
|
||||||
|
packuswb mm2,mm2 ; mm2=(G0 G2 G4 G6 ** ** ** **)
|
||||||
|
packuswb mm3,mm3 ; mm3=(G1 G3 G5 G7 ** ** ** **)
|
||||||
|
|
||||||
|
paddw mm4, MMWORD [wk(0)] ; mm4=(YE+(B-Y)E)=BE=(B0 B2 B4 B6)
|
||||||
|
paddw mm5, MMWORD [wk(1)] ; mm5=(YO+(B-Y)O)=BO=(B1 B3 B5 B7)
|
||||||
|
packuswb mm4,mm4 ; mm4=(B0 B2 B4 B6 ** ** ** **)
|
||||||
|
packuswb mm5,mm5 ; mm5=(B1 B3 B5 B7 ** ** ** **)
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 ; ---------------
|
||||||
|
|
||||||
|
; mmA=(00 02 04 06 ** ** ** **), mmB=(01 03 05 07 ** ** ** **)
|
||||||
|
; mmC=(10 12 14 16 ** ** ** **), mmD=(11 13 15 17 ** ** ** **)
|
||||||
|
; mmE=(20 22 24 26 ** ** ** **), mmF=(21 23 25 27 ** ** ** **)
|
||||||
|
; mmG=(** ** ** ** ** ** ** **), mmH=(** ** ** ** ** ** ** **)
|
||||||
|
|
||||||
|
punpcklbw mmA,mmC ; mmA=(00 10 02 12 04 14 06 16)
|
||||||
|
punpcklbw mmE,mmB ; mmE=(20 01 22 03 24 05 26 07)
|
||||||
|
punpcklbw mmD,mmF ; mmD=(11 21 13 23 15 25 17 27)
|
||||||
|
|
||||||
|
movq mmG,mmA
|
||||||
|
movq mmH,mmA
|
||||||
|
punpcklwd mmA,mmE ; mmA=(00 10 20 01 02 12 22 03)
|
||||||
|
punpckhwd mmG,mmE ; mmG=(04 14 24 05 06 16 26 07)
|
||||||
|
|
||||||
|
psrlq mmH,2*BYTE_BIT ; mmH=(02 12 04 14 06 16 -- --)
|
||||||
|
psrlq mmE,2*BYTE_BIT ; mmE=(22 03 24 05 26 07 -- --)
|
||||||
|
|
||||||
|
movq mmC,mmD
|
||||||
|
movq mmB,mmD
|
||||||
|
punpcklwd mmD,mmH ; mmD=(11 21 02 12 13 23 04 14)
|
||||||
|
punpckhwd mmC,mmH ; mmC=(15 25 06 16 17 27 -- --)
|
||||||
|
|
||||||
|
psrlq mmB,2*BYTE_BIT ; mmB=(13 23 15 25 17 27 -- --)
|
||||||
|
|
||||||
|
movq mmF,mmE
|
||||||
|
punpcklwd mmE,mmB ; mmE=(22 03 13 23 24 05 15 25)
|
||||||
|
punpckhwd mmF,mmB ; mmF=(26 07 17 27 -- -- -- --)
|
||||||
|
|
||||||
|
punpckldq mmA,mmD ; mmA=(00 10 20 01 11 21 02 12)
|
||||||
|
punpckldq mmE,mmG ; mmE=(22 03 13 23 04 14 24 05)
|
||||||
|
punpckldq mmC,mmF ; mmC=(15 25 06 16 26 07 17 27)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD
|
||||||
|
jb short .column_st16
|
||||||
|
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq MMWORD [edi+1*SIZEOF_MMWORD], mmE
|
||||||
|
movq MMWORD [edi+2*SIZEOF_MMWORD], mmC
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_MMWORD
|
||||||
|
jz short .nextrow
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_MMWORD ; inptr0
|
||||||
|
add ebx, byte SIZEOF_MMWORD ; inptr1
|
||||||
|
add edx, byte SIZEOF_MMWORD ; inptr2
|
||||||
|
add edi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; outptr
|
||||||
|
jmp near .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.column_st16:
|
||||||
|
lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE
|
||||||
|
cmp ecx, byte 2*SIZEOF_MMWORD
|
||||||
|
jb short .column_st8
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq MMWORD [edi+1*SIZEOF_MMWORD], mmE
|
||||||
|
movq mmA,mmC
|
||||||
|
sub ecx, byte 2*SIZEOF_MMWORD
|
||||||
|
add edi, byte 2*SIZEOF_MMWORD
|
||||||
|
jmp short .column_st4
|
||||||
|
.column_st8:
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD
|
||||||
|
jb short .column_st4
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq mmA,mmE
|
||||||
|
sub ecx, byte SIZEOF_MMWORD
|
||||||
|
add edi, byte SIZEOF_MMWORD
|
||||||
|
.column_st4:
|
||||||
|
movd eax,mmA
|
||||||
|
cmp ecx, byte SIZEOF_DWORD
|
||||||
|
jb short .column_st2
|
||||||
|
mov DWORD [edi+0*SIZEOF_DWORD], eax
|
||||||
|
psrlq mmA,DWORD_BIT
|
||||||
|
movd eax,mmA
|
||||||
|
sub ecx, byte SIZEOF_DWORD
|
||||||
|
add edi, byte SIZEOF_DWORD
|
||||||
|
.column_st2:
|
||||||
|
cmp ecx, byte SIZEOF_WORD
|
||||||
|
jb short .column_st1
|
||||||
|
mov WORD [edi+0*SIZEOF_WORD], ax
|
||||||
|
shr eax,WORD_BIT
|
||||||
|
sub ecx, byte SIZEOF_WORD
|
||||||
|
add edi, byte SIZEOF_WORD
|
||||||
|
.column_st1:
|
||||||
|
cmp ecx, byte SIZEOF_BYTE
|
||||||
|
jb short .nextrow
|
||||||
|
mov BYTE [edi+0*SIZEOF_BYTE], al
|
||||||
|
|
||||||
|
%else ; RGB_PIXELSIZE == 4 ; -----------
|
||||||
|
|
||||||
|
%ifdef RGBX_FILLER_0XFF
|
||||||
|
pcmpeqb mm6,mm6 ; mm6=(X0 X2 X4 X6 ** ** ** **)
|
||||||
|
pcmpeqb mm7,mm7 ; mm7=(X1 X3 X5 X7 ** ** ** **)
|
||||||
|
%else
|
||||||
|
pxor mm6,mm6 ; mm6=(X0 X2 X4 X6 ** ** ** **)
|
||||||
|
pxor mm7,mm7 ; mm7=(X1 X3 X5 X7 ** ** ** **)
|
||||||
|
%endif
|
||||||
|
; mmA=(00 02 04 06 ** ** ** **), mmB=(01 03 05 07 ** ** ** **)
|
||||||
|
; mmC=(10 12 14 16 ** ** ** **), mmD=(11 13 15 17 ** ** ** **)
|
||||||
|
; mmE=(20 22 24 26 ** ** ** **), mmF=(21 23 25 27 ** ** ** **)
|
||||||
|
; mmG=(30 32 34 36 ** ** ** **), mmH=(31 33 35 37 ** ** ** **)
|
||||||
|
|
||||||
|
punpcklbw mmA,mmC ; mmA=(00 10 02 12 04 14 06 16)
|
||||||
|
punpcklbw mmE,mmG ; mmE=(20 30 22 32 24 34 26 36)
|
||||||
|
punpcklbw mmB,mmD ; mmB=(01 11 03 13 05 15 07 17)
|
||||||
|
punpcklbw mmF,mmH ; mmF=(21 31 23 33 25 35 27 37)
|
||||||
|
|
||||||
|
movq mmC,mmA
|
||||||
|
punpcklwd mmA,mmE ; mmA=(00 10 20 30 02 12 22 32)
|
||||||
|
punpckhwd mmC,mmE ; mmC=(04 14 24 34 06 16 26 36)
|
||||||
|
movq mmG,mmB
|
||||||
|
punpcklwd mmB,mmF ; mmB=(01 11 21 31 03 13 23 33)
|
||||||
|
punpckhwd mmG,mmF ; mmG=(05 15 25 35 07 17 27 37)
|
||||||
|
|
||||||
|
movq mmD,mmA
|
||||||
|
punpckldq mmA,mmB ; mmA=(00 10 20 30 01 11 21 31)
|
||||||
|
punpckhdq mmD,mmB ; mmD=(02 12 22 32 03 13 23 33)
|
||||||
|
movq mmH,mmC
|
||||||
|
punpckldq mmC,mmG ; mmC=(04 14 24 34 05 15 25 35)
|
||||||
|
punpckhdq mmH,mmG ; mmH=(06 16 26 36 07 17 27 37)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD
|
||||||
|
jb short .column_st16
|
||||||
|
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq MMWORD [edi+1*SIZEOF_MMWORD], mmD
|
||||||
|
movq MMWORD [edi+2*SIZEOF_MMWORD], mmC
|
||||||
|
movq MMWORD [edi+3*SIZEOF_MMWORD], mmH
|
||||||
|
|
||||||
|
sub ecx, byte SIZEOF_MMWORD
|
||||||
|
jz short .nextrow
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_MMWORD ; inptr0
|
||||||
|
add ebx, byte SIZEOF_MMWORD ; inptr1
|
||||||
|
add edx, byte SIZEOF_MMWORD ; inptr2
|
||||||
|
add edi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; outptr
|
||||||
|
jmp near .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.column_st16:
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD/2
|
||||||
|
jb short .column_st8
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq MMWORD [edi+1*SIZEOF_MMWORD], mmD
|
||||||
|
movq mmA,mmC
|
||||||
|
movq mmD,mmH
|
||||||
|
sub ecx, byte SIZEOF_MMWORD/2
|
||||||
|
add edi, byte 2*SIZEOF_MMWORD
|
||||||
|
.column_st8:
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD/4
|
||||||
|
jb short .column_st4
|
||||||
|
movq MMWORD [edi+0*SIZEOF_MMWORD], mmA
|
||||||
|
movq mmA,mmD
|
||||||
|
sub ecx, byte SIZEOF_MMWORD/4
|
||||||
|
add edi, byte 1*SIZEOF_MMWORD
|
||||||
|
.column_st4:
|
||||||
|
cmp ecx, byte SIZEOF_MMWORD/8
|
||||||
|
jb short .nextrow
|
||||||
|
movd DWORD [edi+0*SIZEOF_DWORD], mmA
|
||||||
|
|
||||||
|
%endif ; RGB_PIXELSIZE ; ---------------
|
||||||
|
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.nextrow:
|
||||||
|
pop ecx
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
pop edx
|
||||||
|
pop edi
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
add ebx, byte SIZEOF_JSAMPROW
|
||||||
|
add edx, byte SIZEOF_JSAMPROW
|
||||||
|
add edi, byte SIZEOF_JSAMPROW ; output_buf
|
||||||
|
dec eax ; num_rows
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
emms ; empty MMX state
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
mov esp,ebp ; esp <- aligned ebp
|
||||||
|
pop esp ; esp <- original ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JDCOLOR_YCCRGB_MMX_SUPPORTED
|
||||||
|
%endif ; RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
480
jdcolor.c
480
jdcolor.c
@@ -1,194 +1,462 @@
|
|||||||
/*
|
/*
|
||||||
* jdcolor.c
|
* jdcolor.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* This file is part of the Independent JPEG Group's software.
|
* This file is part of the Independent JPEG Group's software.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 5, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
* This file contains output colorspace conversion routines.
|
* This file contains output colorspace conversion routines.
|
||||||
* These routines are invoked via the methods color_convert
|
|
||||||
* and colorout_init/term.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jcolsamp.h" /* Private declarations */
|
||||||
|
|
||||||
|
|
||||||
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_color_deconverter pub; /* public fields */
|
||||||
|
|
||||||
|
/* Private state for YCC->RGB conversion */
|
||||||
|
int * Cr_r_tab; /* => table for Cr to R conversion */
|
||||||
|
int * Cb_b_tab; /* => table for Cb to B conversion */
|
||||||
|
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
|
||||||
|
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
|
||||||
|
} my_color_deconverter;
|
||||||
|
|
||||||
|
typedef my_color_deconverter * my_cconvert_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/**************** YCbCr -> RGB conversion: most common case **************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
||||||
|
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
||||||
|
* The conversion equations to be implemented are therefore
|
||||||
|
* R = Y + 1.40200 * Cr
|
||||||
|
* G = Y - 0.34414 * Cb - 0.71414 * Cr
|
||||||
|
* B = Y + 1.77200 * Cb
|
||||||
|
* where Cb and Cr represent the incoming values less CENTERJSAMPLE.
|
||||||
|
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
|
||||||
|
*
|
||||||
|
* To avoid floating-point arithmetic, we represent the fractional constants
|
||||||
|
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
|
||||||
|
* the products by 2^16, with appropriate rounding, to get the correct answer.
|
||||||
|
* Notice that Y, being an integral input, does not contribute any fraction
|
||||||
|
* so it need not participate in the rounding.
|
||||||
|
*
|
||||||
|
* For even more speed, we avoid doing any multiplications in the inner loop
|
||||||
|
* by precalculating the constants times Cb and Cr for all possible values.
|
||||||
|
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
|
||||||
|
* for 12-bit samples it is still acceptable. It's not very reasonable for
|
||||||
|
* 16-bit samples, but if you want lossless storage you shouldn't be changing
|
||||||
|
* colorspace anyway.
|
||||||
|
* The Cr=>R and Cb=>B values can be rounded to integers in advance; the
|
||||||
|
* values for the G calculation are left scaled up, since we must add them
|
||||||
|
* together before rounding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCALEBITS 16 /* speediest right-shift on some machines */
|
||||||
|
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
|
||||||
|
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize for colorspace conversion.
|
* Initialize tables for YCC->RGB colorspace conversion.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
LOCAL(void)
|
||||||
colorout_init (decompress_info_ptr cinfo)
|
build_ycc_rgb_table (j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
/* no work needed */
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
int i;
|
||||||
|
INT32 x;
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
cconvert->Cr_r_tab = (int *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||||
|
cconvert->Cb_b_tab = (int *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||||
|
cconvert->Cr_g_tab = (INT32 *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||||
|
cconvert->Cb_g_tab = (INT32 *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||||
|
|
||||||
|
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
|
||||||
|
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
|
||||||
|
/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
|
||||||
|
/* Cr=>R value is nearest int to 1.40200 * x */
|
||||||
|
cconvert->Cr_r_tab[i] = (int)
|
||||||
|
RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
|
||||||
|
/* Cb=>B value is nearest int to 1.77200 * x */
|
||||||
|
cconvert->Cb_b_tab[i] = (int)
|
||||||
|
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
|
||||||
|
/* Cr=>G value is scaled-up -0.71414 * x */
|
||||||
|
cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
|
||||||
|
/* Cb=>G value is scaled-up -0.34414 * x */
|
||||||
|
/* We also add in ONE_HALF so that need not do it in inner loop */
|
||||||
|
cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if RGB_PIXELSIZE == 4
|
||||||
|
/* offset of filler byte */
|
||||||
|
#define RGB_FILLER (6 - (RGB_RED) - (RGB_GREEN) - (RGB_BLUE))
|
||||||
|
/* byte pattern to fill with */
|
||||||
|
#ifdef RGBX_FILLER_0XFF
|
||||||
|
#define RGB_FILLER_BYTE 0xFF
|
||||||
|
#else
|
||||||
|
#define RGB_FILLER_BYTE 0x00
|
||||||
|
#endif
|
||||||
|
#endif /* RGB_PIXELSIZE == 4 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert some rows of samples to the output colorspace.
|
* 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
|
* Note that we change from noninterleaved, one-plane-per-component format
|
||||||
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
* to interleaved-pixel format. The output buffer is therefore three times
|
||||||
|
* as wide as the input buffer.
|
||||||
|
* A starting row offset is provided only for the input buffer. The caller
|
||||||
|
* can easily adjust the passed output_buf value to accommodate any row
|
||||||
|
* offset required on that side.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows,
|
ycc_rgb_convert (j_decompress_ptr cinfo,
|
||||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows)
|
||||||
{
|
{
|
||||||
register INT32 y, u, v, x;
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
register int y, cb, cr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
register JSAMPROW inptr0, inptr1, inptr2;
|
register JSAMPROW inptr0, inptr1, inptr2;
|
||||||
register JSAMPROW outptr0, outptr1, outptr2;
|
register JDIMENSION col;
|
||||||
register long col;
|
JDIMENSION num_cols = cinfo->output_width;
|
||||||
register long width = cinfo->image_width;
|
/* copy these pointers into registers if possible */
|
||||||
register int row;
|
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||||
|
register int * Crrtab = cconvert->Cr_r_tab;
|
||||||
for (row = 0; row < num_rows; row++) {
|
register int * Cbbtab = cconvert->Cb_b_tab;
|
||||||
inptr0 = input_data[0][row];
|
register INT32 * Crgtab = cconvert->Cr_g_tab;
|
||||||
inptr1 = input_data[1][row];
|
register INT32 * Cbgtab = cconvert->Cb_g_tab;
|
||||||
inptr2 = input_data[2][row];
|
SHIFT_TEMPS
|
||||||
outptr0 = output_data[0][row];
|
|
||||||
outptr1 = output_data[1][row];
|
while (--num_rows >= 0) {
|
||||||
outptr2 = output_data[2][row];
|
inptr0 = input_buf[0][input_row];
|
||||||
for (col = width; col > 0; col--) {
|
inptr1 = input_buf[1][input_row];
|
||||||
y = GETJSAMPLE(*inptr0++);
|
inptr2 = input_buf[2][input_row];
|
||||||
u = (int) GETJSAMPLE(*inptr1++) - CENTERJSAMPLE;
|
input_row++;
|
||||||
v = (int) GETJSAMPLE(*inptr2++) - CENTERJSAMPLE;
|
outptr = *output_buf++;
|
||||||
/* Note: if the inputs were computed directly from RGB values,
|
for (col = 0; col < num_cols; col++) {
|
||||||
* range-limiting would be unnecessary here; but due to possible
|
y = GETJSAMPLE(inptr0[col]);
|
||||||
* noise in the DCT/IDCT phase, we do need to apply range limits.
|
cb = GETJSAMPLE(inptr1[col]);
|
||||||
*/
|
cr = GETJSAMPLE(inptr2[col]);
|
||||||
y *= 1024; /* in case compiler can't spot common subexpression */
|
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||||
x = y + 1436*v + 512; /* red */
|
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
|
||||||
if (x < 0) x = 0;
|
outptr[RGB_GREEN] = range_limit[y +
|
||||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||||
*outptr0++ = (JSAMPLE) (x >> 10);
|
SCALEBITS))];
|
||||||
x = y - 352*u - 731*v + 512; /* green */
|
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
|
||||||
if (x < 0) x = 0;
|
#if RGB_PIXELSIZE == 4
|
||||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
outptr[RGB_FILLER] = RGB_FILLER_BYTE;
|
||||||
*outptr1++ = (JSAMPLE) (x >> 10);
|
#endif
|
||||||
x = y + 1815*u + 512; /* blue */
|
outptr += RGB_PIXELSIZE;
|
||||||
if (x < 0) x = 0;
|
|
||||||
if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
|
|
||||||
*outptr2++ = (JSAMPLE) (x >> 10);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************** Cases other than YCbCr -> RGB **************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color conversion for no colorspace change: just copy the data.
|
* Color conversion for no colorspace change: just copy the data,
|
||||||
|
* converting from separate-planes to interleaved representation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
null_convert (decompress_info_ptr cinfo, int num_rows,
|
null_convert (j_decompress_ptr cinfo,
|
||||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows)
|
||||||
{
|
{
|
||||||
short ci;
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JDIMENSION count;
|
||||||
|
register int num_components = cinfo->num_components;
|
||||||
|
JDIMENSION num_cols = cinfo->output_width;
|
||||||
|
int ci;
|
||||||
|
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
while (--num_rows >= 0) {
|
||||||
jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
|
for (ci = 0; ci < num_components; ci++) {
|
||||||
num_rows, cinfo->image_width);
|
inptr = input_buf[ci][input_row];
|
||||||
|
outptr = output_buf[0] + ci;
|
||||||
|
for (count = num_cols; count > 0; count--) {
|
||||||
|
*outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
|
||||||
|
outptr += num_components;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input_row++;
|
||||||
|
output_buf++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color conversion for grayscale: just copy the data.
|
* Color conversion for grayscale: just copy the data.
|
||||||
* This also works for YCbCr/YIQ -> grayscale conversion, in which
|
* This also works for YCbCr -> grayscale conversion, in which
|
||||||
* we just copy the Y (luminance) component and ignore chrominance.
|
* we just copy the Y (luminance) component and ignore chrominance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
grayscale_convert (decompress_info_ptr cinfo, int num_rows,
|
grayscale_convert (j_decompress_ptr cinfo,
|
||||||
JSAMPIMAGE input_data, JSAMPIMAGE output_data)
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows)
|
||||||
{
|
{
|
||||||
jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
|
jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
|
||||||
num_rows, cinfo->image_width);
|
num_rows, cinfo->output_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish up at the end of the file.
|
* Convert grayscale to RGB: just duplicate the graylevel three times.
|
||||||
|
* This is provided to support applications that don't want to cope
|
||||||
|
* with grayscale as a separate case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF void
|
METHODDEF(void)
|
||||||
colorout_term (decompress_info_ptr cinfo)
|
gray_rgb_convert (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows)
|
||||||
|
{
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->output_width;
|
||||||
|
|
||||||
|
while (--num_rows >= 0) {
|
||||||
|
inptr = input_buf[0][input_row++];
|
||||||
|
outptr = *output_buf++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
/* We can dispense with GETJSAMPLE() here */
|
||||||
|
outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
|
||||||
|
#if RGB_PIXELSIZE == 4
|
||||||
|
outptr[RGB_FILLER] = RGB_FILLER_BYTE;
|
||||||
|
#endif
|
||||||
|
outptr += RGB_PIXELSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adobe-style YCCK->CMYK conversion.
|
||||||
|
* We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
|
||||||
|
* conversion as above, while passing K (black) unchanged.
|
||||||
|
* We assume build_ycc_rgb_table has been called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
ycck_cmyk_convert (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows)
|
||||||
|
{
|
||||||
|
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||||
|
register int y, cb, cr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
|
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
|
||||||
|
register JDIMENSION col;
|
||||||
|
JDIMENSION num_cols = cinfo->output_width;
|
||||||
|
/* copy these pointers into registers if possible */
|
||||||
|
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||||
|
register int * Crrtab = cconvert->Cr_r_tab;
|
||||||
|
register int * Cbbtab = cconvert->Cb_b_tab;
|
||||||
|
register INT32 * Crgtab = cconvert->Cr_g_tab;
|
||||||
|
register INT32 * Cbgtab = cconvert->Cb_g_tab;
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
while (--num_rows >= 0) {
|
||||||
|
inptr0 = input_buf[0][input_row];
|
||||||
|
inptr1 = input_buf[1][input_row];
|
||||||
|
inptr2 = input_buf[2][input_row];
|
||||||
|
inptr3 = input_buf[3][input_row];
|
||||||
|
input_row++;
|
||||||
|
outptr = *output_buf++;
|
||||||
|
for (col = 0; col < num_cols; col++) {
|
||||||
|
y = GETJSAMPLE(inptr0[col]);
|
||||||
|
cb = GETJSAMPLE(inptr1[col]);
|
||||||
|
cr = GETJSAMPLE(inptr2[col]);
|
||||||
|
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||||
|
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
|
||||||
|
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
|
||||||
|
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||||
|
SCALEBITS)))];
|
||||||
|
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
|
||||||
|
/* K passes through unchanged */
|
||||||
|
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
|
||||||
|
outptr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empty method for start_pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_dcolor (j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
/* no work needed */
|
/* no work needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The method selection routine for output colorspace conversion.
|
* Module initialization routine for output colorspace conversion.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GLOBAL void
|
GLOBAL(void)
|
||||||
jseldcolor (decompress_info_ptr cinfo)
|
jinit_color_deconverter (j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
|
my_cconvert_ptr cconvert;
|
||||||
|
int ci;
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
cconvert = (my_cconvert_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_color_deconverter));
|
||||||
|
cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
|
||||||
|
cconvert->pub.start_pass = start_pass_dcolor;
|
||||||
|
|
||||||
/* Make sure num_components agrees with jpeg_color_space */
|
/* Make sure num_components agrees with jpeg_color_space */
|
||||||
switch (cinfo->jpeg_color_space) {
|
switch (cinfo->jpeg_color_space) {
|
||||||
case CS_GRAYSCALE:
|
case JCS_GRAYSCALE:
|
||||||
if (cinfo->num_components != 1)
|
if (cinfo->num_components != 1)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_RGB:
|
case JCS_RGB:
|
||||||
case CS_YIQ:
|
case JCS_YCbCr:
|
||||||
case CS_YCbCr:
|
|
||||||
if (cinfo->num_components != 3)
|
if (cinfo->num_components != 3)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_CMYK:
|
case JCS_CMYK:
|
||||||
|
case JCS_YCCK:
|
||||||
if (cinfo->num_components != 4)
|
if (cinfo->num_components != 4)
|
||||||
ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default: /* JCS_UNKNOWN can be anything */
|
||||||
ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
|
if (cinfo->num_components < 1)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set color_out_comps and conversion method based on requested space */
|
/* Set out_color_components and conversion method based on requested space.
|
||||||
|
* Also clear the component_needed flags for any unused components,
|
||||||
|
* so that earlier pipeline stages can avoid useless computation.
|
||||||
|
*/
|
||||||
|
|
||||||
switch (cinfo->out_color_space) {
|
switch (cinfo->out_color_space) {
|
||||||
case CS_GRAYSCALE:
|
case JCS_GRAYSCALE:
|
||||||
cinfo->color_out_comps = 1;
|
cinfo->out_color_components = 1;
|
||||||
if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
|
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
||||||
cinfo->jpeg_color_space == CS_YCbCr ||
|
cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
cinfo->jpeg_color_space == CS_YIQ)
|
cconvert->pub.color_convert = grayscale_convert;
|
||||||
cinfo->methods->color_convert = grayscale_convert;
|
/* For color->grayscale conversion, only the Y (0) component is needed */
|
||||||
else
|
for (ci = 1; ci < cinfo->num_components; ci++)
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
cinfo->comp_info[ci].component_needed = FALSE;
|
||||||
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_RGB:
|
case JCS_RGB:
|
||||||
cinfo->color_out_comps = 3;
|
cinfo->out_color_components = RGB_PIXELSIZE;
|
||||||
if (cinfo->jpeg_color_space == CS_YCbCr)
|
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
cinfo->methods->color_convert = ycc_rgb_convert;
|
#if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
else if (cinfo->jpeg_color_space == CS_RGB)
|
#ifdef JDCOLOR_YCCRGB_SSE2_SUPPORTED
|
||||||
cinfo->methods->color_convert = null_convert;
|
if (simd & JSIMD_SSE2 &&
|
||||||
else
|
IS_CONST_ALIGNED_16(jconst_ycc_rgb_convert_sse2)) {
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
cconvert->pub.color_convert = jpeg_ycc_rgb_convert_sse2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef JDCOLOR_YCCRGB_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX) {
|
||||||
|
cconvert->pub.color_convert = jpeg_ycc_rgb_convert_mmx;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#endif /* RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4 */
|
||||||
|
{
|
||||||
|
cconvert->pub.color_convert = ycc_rgb_convert;
|
||||||
|
build_ycc_rgb_table(cinfo);
|
||||||
|
}
|
||||||
|
} else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
|
||||||
|
cconvert->pub.color_convert = gray_rgb_convert;
|
||||||
|
} else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_CMYK:
|
case JCS_CMYK:
|
||||||
cinfo->color_out_comps = 4;
|
cinfo->out_color_components = 4;
|
||||||
if (cinfo->jpeg_color_space == CS_CMYK)
|
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
||||||
cinfo->methods->color_convert = null_convert;
|
cconvert->pub.color_convert = ycck_cmyk_convert;
|
||||||
else
|
build_ycc_rgb_table(cinfo);
|
||||||
ERREXIT(cinfo->emethods, "Unsupported color conversion request");
|
} else if (cinfo->jpeg_color_space == JCS_CMYK) {
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERREXIT(cinfo->emethods, "Unsupported output colorspace");
|
/* Permit null conversion to same output space */
|
||||||
|
if (cinfo->out_color_space == cinfo->jpeg_color_space) {
|
||||||
|
cinfo->out_color_components = cinfo->num_components;
|
||||||
|
cconvert->pub.color_convert = null_convert;
|
||||||
|
} else /* unsupported non-null conversion */
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cinfo->quantize_colors)
|
if (cinfo->quantize_colors)
|
||||||
cinfo->final_out_comps = 1; /* single colormapped output component */
|
cinfo->output_components = 1; /* single colormapped output component */
|
||||||
else
|
else
|
||||||
cinfo->final_out_comps = cinfo->color_out_comps;
|
cinfo->output_components = cinfo->out_color_components;
|
||||||
|
|
||||||
cinfo->methods->colorout_init = colorout_init;
|
|
||||||
cinfo->methods->colorout_term = colorout_term;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_color_deconverter (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
#if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
#ifdef JDCOLOR_YCCRGB_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_ycc_rgb_convert_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JDCOLOR_YCCRGB_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
#endif /* RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4 */
|
||||||
|
|
||||||
|
return JSIMD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
|
|||||||
536
jdcolss2.asm
Normal file
536
jdcolss2.asm
Normal file
@@ -0,0 +1,536 @@
|
|||||||
|
;
|
||||||
|
; jdcolss2.asm - colorspace conversion (SSE2)
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; This file should be assembled with NASM (Netwide Assembler),
|
||||||
|
; can *not* be assembled with Microsoft's MASM or any compatible
|
||||||
|
; assembler (including Borland's Turbo Assembler).
|
||||||
|
; NASM is available from http://nasm.sourceforge.net/ or
|
||||||
|
; http://sourceforge.net/project/showfiles.php?group_id=6208
|
||||||
|
;
|
||||||
|
; Last Modified : February 4, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
%include "jsimdext.inc"
|
||||||
|
%include "jcolsamp.inc"
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
|
%ifdef JDCOLOR_YCCRGB_SSE2_SUPPORTED
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%define SCALEBITS 16
|
||||||
|
|
||||||
|
F_0_344 equ 22554 ; FIX(0.34414)
|
||||||
|
F_0_714 equ 46802 ; FIX(0.71414)
|
||||||
|
F_1_402 equ 91881 ; FIX(1.40200)
|
||||||
|
F_1_772 equ 116130 ; FIX(1.77200)
|
||||||
|
F_0_402 equ (F_1_402 - 65536) ; FIX(1.40200) - FIX(1)
|
||||||
|
F_0_285 equ ( 65536 - F_0_714) ; FIX(1) - FIX(0.71414)
|
||||||
|
F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200)
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_CONST
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
global EXTN(jconst_ycc_rgb_convert_sse2)
|
||||||
|
|
||||||
|
EXTN(jconst_ycc_rgb_convert_sse2):
|
||||||
|
|
||||||
|
PW_F0402 times 8 dw F_0_402
|
||||||
|
PW_MF0228 times 8 dw -F_0_228
|
||||||
|
PW_MF0344_F0285 times 4 dw -F_0_344, F_0_285
|
||||||
|
PW_ONE times 8 dw 1
|
||||||
|
PD_ONEHALF times 4 dd 1 << (SCALEBITS-1)
|
||||||
|
|
||||||
|
alignz 16
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
SECTION SEG_TEXT
|
||||||
|
BITS 32
|
||||||
|
;
|
||||||
|
; Convert some rows of samples to the output colorspace.
|
||||||
|
;
|
||||||
|
; GLOBAL(void)
|
||||||
|
; jpeg_ycc_rgb_convert_sse2 (j_decompress_ptr cinfo,
|
||||||
|
; JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
; JSAMPARRAY output_buf, int num_rows)
|
||||||
|
;
|
||||||
|
|
||||||
|
%define cinfo(b) (b)+8 ; j_decompress_ptr cinfo
|
||||||
|
%define input_buf(b) (b)+12 ; JSAMPIMAGE input_buf
|
||||||
|
%define input_row(b) (b)+16 ; JDIMENSION input_row
|
||||||
|
%define output_buf(b) (b)+20 ; JSAMPARRAY output_buf
|
||||||
|
%define num_rows(b) (b)+24 ; int num_rows
|
||||||
|
|
||||||
|
%define original_ebp ebp+0
|
||||||
|
%define wk(i) ebp-(WK_NUM-(i))*SIZEOF_XMMWORD ; xmmword wk[WK_NUM]
|
||||||
|
%define WK_NUM 2
|
||||||
|
%define gotptr wk(0)-SIZEOF_POINTER ; void * gotptr
|
||||||
|
|
||||||
|
align 16
|
||||||
|
global EXTN(jpeg_ycc_rgb_convert_sse2)
|
||||||
|
|
||||||
|
EXTN(jpeg_ycc_rgb_convert_sse2):
|
||||||
|
push ebp
|
||||||
|
mov eax,esp ; eax = original ebp
|
||||||
|
sub esp, byte 4
|
||||||
|
and esp, byte (-SIZEOF_XMMWORD) ; align to 128 bits
|
||||||
|
mov [esp],eax
|
||||||
|
mov ebp,esp ; ebp = aligned ebp
|
||||||
|
lea esp, [wk(0)]
|
||||||
|
pushpic eax ; make a room for GOT address
|
||||||
|
push ebx
|
||||||
|
; push ecx ; need not be preserved
|
||||||
|
; push edx ; need not be preserved
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
get_GOT ebx ; get GOT address
|
||||||
|
movpic POINTER [gotptr], ebx ; save GOT address
|
||||||
|
|
||||||
|
mov ecx, POINTER [cinfo(eax)]
|
||||||
|
mov ecx, JDIMENSION [jdstruct_output_width(ecx)] ; num_cols
|
||||||
|
test ecx,ecx
|
||||||
|
jz near .return
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPIMAGE [input_buf(eax)]
|
||||||
|
mov ecx, JDIMENSION [input_row(eax)]
|
||||||
|
mov esi, JSAMPARRAY [edi+0*SIZEOF_JSAMPARRAY]
|
||||||
|
mov ebx, JSAMPARRAY [edi+1*SIZEOF_JSAMPARRAY]
|
||||||
|
mov edx, JSAMPARRAY [edi+2*SIZEOF_JSAMPARRAY]
|
||||||
|
lea esi, [esi+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea ebx, [ebx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
lea edx, [edx+ecx*SIZEOF_JSAMPROW]
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
mov edi, JSAMPARRAY [output_buf(eax)]
|
||||||
|
mov eax, INT [num_rows(eax)]
|
||||||
|
test eax,eax
|
||||||
|
jle near .return
|
||||||
|
alignx 16,7
|
||||||
|
.rowloop:
|
||||||
|
push eax
|
||||||
|
push edi
|
||||||
|
push edx
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push ecx ; col
|
||||||
|
|
||||||
|
mov esi, JSAMPROW [esi] ; inptr0
|
||||||
|
mov ebx, JSAMPROW [ebx] ; inptr1
|
||||||
|
mov edx, JSAMPROW [edx] ; inptr2
|
||||||
|
mov edi, JSAMPROW [edi] ; outptr
|
||||||
|
movpic eax, POINTER [gotptr] ; load GOT address (eax)
|
||||||
|
alignx 16,7
|
||||||
|
.columnloop:
|
||||||
|
|
||||||
|
movdqa xmm5, XMMWORD [ebx] ; xmm5=Cb(0123456789ABCDEF)
|
||||||
|
movdqa xmm1, XMMWORD [edx] ; xmm1=Cr(0123456789ABCDEF)
|
||||||
|
|
||||||
|
pcmpeqw xmm4,xmm4
|
||||||
|
pcmpeqw xmm7,xmm7
|
||||||
|
psrlw xmm4,BYTE_BIT
|
||||||
|
psllw xmm7,7 ; xmm7={0xFF80 0xFF80 0xFF80 0xFF80 ..}
|
||||||
|
movdqa xmm0,xmm4 ; xmm0=xmm4={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
|
||||||
|
pand xmm4,xmm5 ; xmm4=Cb(02468ACE)=CbE
|
||||||
|
psrlw xmm5,BYTE_BIT ; xmm5=Cb(13579BDF)=CbO
|
||||||
|
pand xmm0,xmm1 ; xmm0=Cr(02468ACE)=CrE
|
||||||
|
psrlw xmm1,BYTE_BIT ; xmm1=Cr(13579BDF)=CrO
|
||||||
|
|
||||||
|
paddw xmm4,xmm7
|
||||||
|
paddw xmm5,xmm7
|
||||||
|
paddw xmm0,xmm7
|
||||||
|
paddw xmm1,xmm7
|
||||||
|
|
||||||
|
; (Original)
|
||||||
|
; R = Y + 1.40200 * Cr
|
||||||
|
; G = Y - 0.34414 * Cb - 0.71414 * Cr
|
||||||
|
; B = Y + 1.77200 * Cb
|
||||||
|
;
|
||||||
|
; (This implementation)
|
||||||
|
; R = Y + 0.40200 * Cr + Cr
|
||||||
|
; G = Y - 0.34414 * Cb + 0.28586 * Cr - Cr
|
||||||
|
; B = Y - 0.22800 * Cb + Cb + Cb
|
||||||
|
|
||||||
|
movdqa xmm2,xmm4 ; xmm2=CbE
|
||||||
|
movdqa xmm3,xmm5 ; xmm3=CbO
|
||||||
|
paddw xmm4,xmm4 ; xmm4=2*CbE
|
||||||
|
paddw xmm5,xmm5 ; xmm5=2*CbO
|
||||||
|
movdqa xmm6,xmm0 ; xmm6=CrE
|
||||||
|
movdqa xmm7,xmm1 ; xmm7=CrO
|
||||||
|
paddw xmm0,xmm0 ; xmm0=2*CrE
|
||||||
|
paddw xmm1,xmm1 ; xmm1=2*CrO
|
||||||
|
|
||||||
|
pmulhw xmm4,[GOTOFF(eax,PW_MF0228)] ; xmm4=(2*CbE * -FIX(0.22800))
|
||||||
|
pmulhw xmm5,[GOTOFF(eax,PW_MF0228)] ; xmm5=(2*CbO * -FIX(0.22800))
|
||||||
|
pmulhw xmm0,[GOTOFF(eax,PW_F0402)] ; xmm0=(2*CrE * FIX(0.40200))
|
||||||
|
pmulhw xmm1,[GOTOFF(eax,PW_F0402)] ; xmm1=(2*CrO * FIX(0.40200))
|
||||||
|
|
||||||
|
paddw xmm4,[GOTOFF(eax,PW_ONE)]
|
||||||
|
paddw xmm5,[GOTOFF(eax,PW_ONE)]
|
||||||
|
psraw xmm4,1 ; xmm4=(CbE * -FIX(0.22800))
|
||||||
|
psraw xmm5,1 ; xmm5=(CbO * -FIX(0.22800))
|
||||||
|
paddw xmm0,[GOTOFF(eax,PW_ONE)]
|
||||||
|
paddw xmm1,[GOTOFF(eax,PW_ONE)]
|
||||||
|
psraw xmm0,1 ; xmm0=(CrE * FIX(0.40200))
|
||||||
|
psraw xmm1,1 ; xmm1=(CrO * FIX(0.40200))
|
||||||
|
|
||||||
|
paddw xmm4,xmm2
|
||||||
|
paddw xmm5,xmm3
|
||||||
|
paddw xmm4,xmm2 ; xmm4=(CbE * FIX(1.77200))=(B-Y)E
|
||||||
|
paddw xmm5,xmm3 ; xmm5=(CbO * FIX(1.77200))=(B-Y)O
|
||||||
|
paddw xmm0,xmm6 ; xmm0=(CrE * FIX(1.40200))=(R-Y)E
|
||||||
|
paddw xmm1,xmm7 ; xmm1=(CrO * FIX(1.40200))=(R-Y)O
|
||||||
|
|
||||||
|
movdqa XMMWORD [wk(0)], xmm4 ; wk(0)=(B-Y)E
|
||||||
|
movdqa XMMWORD [wk(1)], xmm5 ; wk(1)=(B-Y)O
|
||||||
|
|
||||||
|
movdqa xmm4,xmm2
|
||||||
|
movdqa xmm5,xmm3
|
||||||
|
punpcklwd xmm2,xmm6
|
||||||
|
punpckhwd xmm4,xmm6
|
||||||
|
pmaddwd xmm2,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
pmaddwd xmm4,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
punpcklwd xmm3,xmm7
|
||||||
|
punpckhwd xmm5,xmm7
|
||||||
|
pmaddwd xmm3,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
pmaddwd xmm5,[GOTOFF(eax,PW_MF0344_F0285)]
|
||||||
|
|
||||||
|
paddd xmm2,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
paddd xmm4,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
psrad xmm2,SCALEBITS
|
||||||
|
psrad xmm4,SCALEBITS
|
||||||
|
paddd xmm3,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
paddd xmm5,[GOTOFF(eax,PD_ONEHALF)]
|
||||||
|
psrad xmm3,SCALEBITS
|
||||||
|
psrad xmm5,SCALEBITS
|
||||||
|
|
||||||
|
packssdw xmm2,xmm4 ; xmm2=CbE*-FIX(0.344)+CrE*FIX(0.285)
|
||||||
|
packssdw xmm3,xmm5 ; xmm3=CbO*-FIX(0.344)+CrO*FIX(0.285)
|
||||||
|
psubw xmm2,xmm6 ; xmm2=CbE*-FIX(0.344)+CrE*-FIX(0.714)=(G-Y)E
|
||||||
|
psubw xmm3,xmm7 ; xmm3=CbO*-FIX(0.344)+CrO*-FIX(0.714)=(G-Y)O
|
||||||
|
|
||||||
|
movdqa xmm5, XMMWORD [esi] ; xmm5=Y(0123456789ABCDEF)
|
||||||
|
|
||||||
|
pcmpeqw xmm4,xmm4
|
||||||
|
psrlw xmm4,BYTE_BIT ; xmm4={0xFF 0x00 0xFF 0x00 ..}
|
||||||
|
pand xmm4,xmm5 ; xmm4=Y(02468ACE)=YE
|
||||||
|
psrlw xmm5,BYTE_BIT ; xmm5=Y(13579BDF)=YO
|
||||||
|
|
||||||
|
paddw xmm0,xmm4 ; xmm0=((R-Y)E+YE)=RE=R(02468ACE)
|
||||||
|
paddw xmm1,xmm5 ; xmm1=((R-Y)O+YO)=RO=R(13579BDF)
|
||||||
|
packuswb xmm0,xmm0 ; xmm0=R(02468ACE********)
|
||||||
|
packuswb xmm1,xmm1 ; xmm1=R(13579BDF********)
|
||||||
|
|
||||||
|
paddw xmm2,xmm4 ; xmm2=((G-Y)E+YE)=GE=G(02468ACE)
|
||||||
|
paddw xmm3,xmm5 ; xmm3=((G-Y)O+YO)=GO=G(13579BDF)
|
||||||
|
packuswb xmm2,xmm2 ; xmm2=G(02468ACE********)
|
||||||
|
packuswb xmm3,xmm3 ; xmm3=G(13579BDF********)
|
||||||
|
|
||||||
|
paddw xmm4, XMMWORD [wk(0)] ; xmm4=(YE+(B-Y)E)=BE=B(02468ACE)
|
||||||
|
paddw xmm5, XMMWORD [wk(1)] ; xmm5=(YO+(B-Y)O)=BO=B(13579BDF)
|
||||||
|
packuswb xmm4,xmm4 ; xmm4=B(02468ACE********)
|
||||||
|
packuswb xmm5,xmm5 ; xmm5=B(13579BDF********)
|
||||||
|
|
||||||
|
%if RGB_PIXELSIZE == 3 ; ---------------
|
||||||
|
|
||||||
|
; xmmA=(00 02 04 06 08 0A 0C 0E **), xmmB=(01 03 05 07 09 0B 0D 0F **)
|
||||||
|
; xmmC=(10 12 14 16 18 1A 1C 1E **), xmmD=(11 13 15 17 19 1B 1D 1F **)
|
||||||
|
; xmmE=(20 22 24 26 28 2A 2C 2E **), xmmF=(21 23 25 27 29 2B 2D 2F **)
|
||||||
|
; xmmG=(** ** ** ** ** ** ** ** **), xmmH=(** ** ** ** ** ** ** ** **)
|
||||||
|
|
||||||
|
punpcklbw xmmA,xmmC ; xmmA=(00 10 02 12 04 14 06 16 08 18 0A 1A 0C 1C 0E 1E)
|
||||||
|
punpcklbw xmmE,xmmB ; xmmE=(20 01 22 03 24 05 26 07 28 09 2A 0B 2C 0D 2E 0F)
|
||||||
|
punpcklbw xmmD,xmmF ; xmmD=(11 21 13 23 15 25 17 27 19 29 1B 2B 1D 2D 1F 2F)
|
||||||
|
|
||||||
|
movdqa xmmG,xmmA
|
||||||
|
movdqa xmmH,xmmA
|
||||||
|
punpcklwd xmmA,xmmE ; xmmA=(00 10 20 01 02 12 22 03 04 14 24 05 06 16 26 07)
|
||||||
|
punpckhwd xmmG,xmmE ; xmmG=(08 18 28 09 0A 1A 2A 0B 0C 1C 2C 0D 0E 1E 2E 0F)
|
||||||
|
|
||||||
|
psrldq xmmH,2 ; xmmH=(02 12 04 14 06 16 08 18 0A 1A 0C 1C 0E 1E -- --)
|
||||||
|
psrldq xmmE,2 ; xmmE=(22 03 24 05 26 07 28 09 2A 0B 2C 0D 2E 0F -- --)
|
||||||
|
|
||||||
|
movdqa xmmC,xmmD
|
||||||
|
movdqa xmmB,xmmD
|
||||||
|
punpcklwd xmmD,xmmH ; xmmD=(11 21 02 12 13 23 04 14 15 25 06 16 17 27 08 18)
|
||||||
|
punpckhwd xmmC,xmmH ; xmmC=(19 29 0A 1A 1B 2B 0C 1C 1D 2D 0E 1E 1F 2F -- --)
|
||||||
|
|
||||||
|
psrldq xmmB,2 ; xmmB=(13 23 15 25 17 27 19 29 1B 2B 1D 2D 1F 2F -- --)
|
||||||
|
|
||||||
|
movdqa xmmF,xmmE
|
||||||
|
punpcklwd xmmE,xmmB ; xmmE=(22 03 13 23 24 05 15 25 26 07 17 27 28 09 19 29)
|
||||||
|
punpckhwd xmmF,xmmB ; xmmF=(2A 0B 1B 2B 2C 0D 1D 2D 2E 0F 1F 2F -- -- -- --)
|
||||||
|
|
||||||
|
pshufd xmmH,xmmA,0x4E; xmmH=(04 14 24 05 06 16 26 07 00 10 20 01 02 12 22 03)
|
||||||
|
movdqa xmmB,xmmE
|
||||||
|
punpckldq xmmA,xmmD ; xmmA=(00 10 20 01 11 21 02 12 02 12 22 03 13 23 04 14)
|
||||||
|
punpckldq xmmE,xmmH ; xmmE=(22 03 13 23 04 14 24 05 24 05 15 25 06 16 26 07)
|
||||||
|
punpckhdq xmmD,xmmB ; xmmD=(15 25 06 16 26 07 17 27 17 27 08 18 28 09 19 29)
|
||||||
|
|
||||||
|
pshufd xmmH,xmmG,0x4E; xmmH=(0C 1C 2C 0D 0E 1E 2E 0F 08 18 28 09 0A 1A 2A 0B)
|
||||||
|
movdqa xmmB,xmmF
|
||||||
|
punpckldq xmmG,xmmC ; xmmG=(08 18 28 09 19 29 0A 1A 0A 1A 2A 0B 1B 2B 0C 1C)
|
||||||
|
punpckldq xmmF,xmmH ; xmmF=(2A 0B 1B 2B 0C 1C 2C 0D 2C 0D 1D 2D 0E 1E 2E 0F)
|
||||||
|
punpckhdq xmmC,xmmB ; xmmC=(1D 2D 0E 1E 2E 0F 1F 2F 1F 2F -- -- -- -- -- --)
|
||||||
|
|
||||||
|
punpcklqdq xmmA,xmmE ; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05)
|
||||||
|
punpcklqdq xmmD,xmmG ; xmmD=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
|
||||||
|
punpcklqdq xmmF,xmmC ; xmmF=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jb short .column_st32
|
||||||
|
|
||||||
|
test edi, SIZEOF_XMMWORD-1
|
||||||
|
jnz short .out1
|
||||||
|
; --(aligned)-------------------
|
||||||
|
movntdq XMMWORD [edi+0*SIZEOF_XMMWORD], xmmA
|
||||||
|
movntdq XMMWORD [edi+1*SIZEOF_XMMWORD], xmmD
|
||||||
|
movntdq XMMWORD [edi+2*SIZEOF_XMMWORD], xmmF
|
||||||
|
add edi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD ; outptr
|
||||||
|
jmp short .out0
|
||||||
|
.out1: ; --(unaligned)-----------------
|
||||||
|
pcmpeqb xmmH,xmmH ; xmmH=(all 1's)
|
||||||
|
maskmovdqu xmmA,xmmH ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmD,xmmH ; movntdqu XMMWORD [edi], xmmD
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmF,xmmH ; movntdqu XMMWORD [edi], xmmF
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
.out0:
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD
|
||||||
|
jz near .nextrow
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_XMMWORD ; inptr0
|
||||||
|
add ebx, byte SIZEOF_XMMWORD ; inptr1
|
||||||
|
add edx, byte SIZEOF_XMMWORD ; inptr2
|
||||||
|
jmp near .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.column_st32:
|
||||||
|
pcmpeqb xmmH,xmmH ; xmmH=(all 1's)
|
||||||
|
lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE
|
||||||
|
cmp ecx, byte 2*SIZEOF_XMMWORD
|
||||||
|
jb short .column_st16
|
||||||
|
maskmovdqu xmmA,xmmH ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmD,xmmH ; movntdqu XMMWORD [edi], xmmD
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
movdqa xmmA,xmmF
|
||||||
|
sub ecx, byte 2*SIZEOF_XMMWORD
|
||||||
|
jmp short .column_st15
|
||||||
|
.column_st16:
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jb short .column_st15
|
||||||
|
maskmovdqu xmmA,xmmH ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
movdqa xmmA,xmmD
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD
|
||||||
|
.column_st15:
|
||||||
|
mov eax,ecx
|
||||||
|
xor ecx, byte 0x0F
|
||||||
|
shl ecx, 2
|
||||||
|
movd xmmB,ecx
|
||||||
|
psrlq xmmH,4
|
||||||
|
pcmpeqb xmmE,xmmE
|
||||||
|
psrlq xmmH,xmmB
|
||||||
|
psrlq xmmE,xmmB
|
||||||
|
punpcklbw xmmE,xmmH
|
||||||
|
; ----------------
|
||||||
|
mov ecx,edi
|
||||||
|
and ecx, byte SIZEOF_XMMWORD-1
|
||||||
|
jz short .adj0
|
||||||
|
add eax,ecx
|
||||||
|
cmp eax, byte SIZEOF_XMMWORD
|
||||||
|
ja short .adj0
|
||||||
|
and edi, byte (-SIZEOF_XMMWORD) ; align to 16-byte boundary
|
||||||
|
shl ecx, 3 ; pslldq xmmA,ecx & pslldq xmmE,ecx
|
||||||
|
movdqa xmmG,xmmA
|
||||||
|
movdqa xmmC,xmmE
|
||||||
|
pslldq xmmA, SIZEOF_XMMWORD/2
|
||||||
|
pslldq xmmE, SIZEOF_XMMWORD/2
|
||||||
|
movd xmmD,ecx
|
||||||
|
sub ecx, byte (SIZEOF_XMMWORD/2)*BYTE_BIT
|
||||||
|
jb short .adj1
|
||||||
|
movd xmmF,ecx
|
||||||
|
psllq xmmA,xmmF
|
||||||
|
psllq xmmE,xmmF
|
||||||
|
jmp short .adj0
|
||||||
|
.adj1: neg ecx
|
||||||
|
movd xmmF,ecx
|
||||||
|
psrlq xmmA,xmmF
|
||||||
|
psrlq xmmE,xmmF
|
||||||
|
psllq xmmG,xmmD
|
||||||
|
psllq xmmC,xmmD
|
||||||
|
por xmmA,xmmG
|
||||||
|
por xmmE,xmmC
|
||||||
|
.adj0: ; ----------------
|
||||||
|
maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
|
||||||
|
%else ; RGB_PIXELSIZE == 4 ; -----------
|
||||||
|
|
||||||
|
%ifdef RGBX_FILLER_0XFF
|
||||||
|
pcmpeqb xmm6,xmm6 ; xmm6=XE=X(02468ACE********)
|
||||||
|
pcmpeqb xmm7,xmm7 ; xmm7=XO=X(13579BDF********)
|
||||||
|
%else
|
||||||
|
pxor xmm6,xmm6 ; xmm6=XE=X(02468ACE********)
|
||||||
|
pxor xmm7,xmm7 ; xmm7=XO=X(13579BDF********)
|
||||||
|
%endif
|
||||||
|
; xmmA=(00 02 04 06 08 0A 0C 0E **), xmmB=(01 03 05 07 09 0B 0D 0F **)
|
||||||
|
; xmmC=(10 12 14 16 18 1A 1C 1E **), xmmD=(11 13 15 17 19 1B 1D 1F **)
|
||||||
|
; xmmE=(20 22 24 26 28 2A 2C 2E **), xmmF=(21 23 25 27 29 2B 2D 2F **)
|
||||||
|
; xmmG=(30 32 34 36 38 3A 3C 3E **), xmmH=(31 33 35 37 39 3B 3D 3F **)
|
||||||
|
|
||||||
|
punpcklbw xmmA,xmmC ; xmmA=(00 10 02 12 04 14 06 16 08 18 0A 1A 0C 1C 0E 1E)
|
||||||
|
punpcklbw xmmE,xmmG ; xmmE=(20 30 22 32 24 34 26 36 28 38 2A 3A 2C 3C 2E 3E)
|
||||||
|
punpcklbw xmmB,xmmD ; xmmB=(01 11 03 13 05 15 07 17 09 19 0B 1B 0D 1D 0F 1F)
|
||||||
|
punpcklbw xmmF,xmmH ; xmmF=(21 31 23 33 25 35 27 37 29 39 2B 3B 2D 3D 2F 3F)
|
||||||
|
|
||||||
|
movdqa xmmC,xmmA
|
||||||
|
punpcklwd xmmA,xmmE ; xmmA=(00 10 20 30 02 12 22 32 04 14 24 34 06 16 26 36)
|
||||||
|
punpckhwd xmmC,xmmE ; xmmC=(08 18 28 38 0A 1A 2A 3A 0C 1C 2C 3C 0E 1E 2E 3E)
|
||||||
|
movdqa xmmG,xmmB
|
||||||
|
punpcklwd xmmB,xmmF ; xmmB=(01 11 21 31 03 13 23 33 05 15 25 35 07 17 27 37)
|
||||||
|
punpckhwd xmmG,xmmF ; xmmG=(09 19 29 39 0B 1B 2B 3B 0D 1D 2D 3D 0F 1F 2F 3F)
|
||||||
|
|
||||||
|
movdqa xmmD,xmmA
|
||||||
|
punpckldq xmmA,xmmB ; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33)
|
||||||
|
punpckhdq xmmD,xmmB ; xmmD=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37)
|
||||||
|
movdqa xmmH,xmmC
|
||||||
|
punpckldq xmmC,xmmG ; xmmC=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B)
|
||||||
|
punpckhdq xmmH,xmmG ; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F)
|
||||||
|
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD
|
||||||
|
jb short .column_st32
|
||||||
|
|
||||||
|
test edi, SIZEOF_XMMWORD-1
|
||||||
|
jnz short .out1
|
||||||
|
; --(aligned)-------------------
|
||||||
|
movntdq XMMWORD [edi+0*SIZEOF_XMMWORD], xmmA
|
||||||
|
movntdq XMMWORD [edi+1*SIZEOF_XMMWORD], xmmD
|
||||||
|
movntdq XMMWORD [edi+2*SIZEOF_XMMWORD], xmmC
|
||||||
|
movntdq XMMWORD [edi+3*SIZEOF_XMMWORD], xmmH
|
||||||
|
add edi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD ; outptr
|
||||||
|
jmp short .out0
|
||||||
|
.out1: ; --(unaligned)-----------------
|
||||||
|
pcmpeqb xmmE,xmmE ; xmmE=(all 1's)
|
||||||
|
maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmD,xmmE ; movntdqu XMMWORD [edi], xmmD
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmC,xmmE ; movntdqu XMMWORD [edi], xmmC
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmH,xmmE ; movntdqu XMMWORD [edi], xmmH
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
.out0:
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD
|
||||||
|
jz near .nextrow
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_XMMWORD ; inptr0
|
||||||
|
add ebx, byte SIZEOF_XMMWORD ; inptr1
|
||||||
|
add edx, byte SIZEOF_XMMWORD ; inptr2
|
||||||
|
jmp near .columnloop
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.column_st32:
|
||||||
|
pcmpeqb xmmE,xmmE ; xmmE=(all 1's)
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD/2
|
||||||
|
jb short .column_st16
|
||||||
|
maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
maskmovdqu xmmD,xmmE ; movntdqu XMMWORD [edi], xmmD
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
movdqa xmmA,xmmC
|
||||||
|
movdqa xmmD,xmmH
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD/2
|
||||||
|
.column_st16:
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD/4
|
||||||
|
jb short .column_st15
|
||||||
|
maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
add edi, byte SIZEOF_XMMWORD ; outptr
|
||||||
|
movdqa xmmA,xmmD
|
||||||
|
sub ecx, byte SIZEOF_XMMWORD/4
|
||||||
|
.column_st15:
|
||||||
|
cmp ecx, byte SIZEOF_XMMWORD/16
|
||||||
|
jb short .nextrow
|
||||||
|
mov eax,ecx
|
||||||
|
xor ecx, byte 0x03
|
||||||
|
inc ecx
|
||||||
|
shl ecx, 4
|
||||||
|
movd xmmF,ecx
|
||||||
|
psrlq xmmE,xmmF
|
||||||
|
punpcklbw xmmE,xmmE
|
||||||
|
; ----------------
|
||||||
|
mov ecx,edi
|
||||||
|
and ecx, byte SIZEOF_XMMWORD-1
|
||||||
|
jz short .adj0
|
||||||
|
lea eax, [ecx+eax*4] ; RGB_PIXELSIZE
|
||||||
|
cmp eax, byte SIZEOF_XMMWORD
|
||||||
|
ja short .adj0
|
||||||
|
and edi, byte (-SIZEOF_XMMWORD) ; align to 16-byte boundary
|
||||||
|
shl ecx, 3 ; pslldq xmmA,ecx & pslldq xmmE,ecx
|
||||||
|
movdqa xmmB,xmmA
|
||||||
|
movdqa xmmG,xmmE
|
||||||
|
pslldq xmmA, SIZEOF_XMMWORD/2
|
||||||
|
pslldq xmmE, SIZEOF_XMMWORD/2
|
||||||
|
movd xmmC,ecx
|
||||||
|
sub ecx, byte (SIZEOF_XMMWORD/2)*BYTE_BIT
|
||||||
|
jb short .adj1
|
||||||
|
movd xmmH,ecx
|
||||||
|
psllq xmmA,xmmH
|
||||||
|
psllq xmmE,xmmH
|
||||||
|
jmp short .adj0
|
||||||
|
.adj1: neg ecx
|
||||||
|
movd xmmH,ecx
|
||||||
|
psrlq xmmA,xmmH
|
||||||
|
psrlq xmmE,xmmH
|
||||||
|
psllq xmmB,xmmC
|
||||||
|
psllq xmmG,xmmC
|
||||||
|
por xmmA,xmmB
|
||||||
|
por xmmE,xmmG
|
||||||
|
.adj0: ; ----------------
|
||||||
|
maskmovdqu xmmA,xmmE ; movntdqu XMMWORD [edi], xmmA
|
||||||
|
|
||||||
|
%endif ; RGB_PIXELSIZE ; ---------------
|
||||||
|
|
||||||
|
alignx 16,7
|
||||||
|
|
||||||
|
.nextrow:
|
||||||
|
pop ecx
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
pop edx
|
||||||
|
pop edi
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esi, byte SIZEOF_JSAMPROW
|
||||||
|
add ebx, byte SIZEOF_JSAMPROW
|
||||||
|
add edx, byte SIZEOF_JSAMPROW
|
||||||
|
add edi, byte SIZEOF_JSAMPROW ; output_buf
|
||||||
|
dec eax ; num_rows
|
||||||
|
jg near .rowloop
|
||||||
|
|
||||||
|
sfence ; flush the write buffer
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
; pop edx ; need not be preserved
|
||||||
|
; pop ecx ; need not be preserved
|
||||||
|
pop ebx
|
||||||
|
mov esp,ebp ; esp <- aligned ebp
|
||||||
|
pop esp ; esp <- original ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif ; JDCOLOR_YCCRGB_SSE2_SUPPORTED
|
||||||
|
%endif ; RGB_PIXELSIZE == 3 || RGB_PIXELSIZE == 4
|
||||||
348
jdct.h
Normal file
348
jdct.h
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
/*
|
||||||
|
* jdct.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : January 5, 2006
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This include file contains common declarations for the forward and
|
||||||
|
* inverse DCT modules. These declarations are private to the DCT managers
|
||||||
|
* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
|
||||||
|
* The individual DCT algorithms are kept in separate files to ease
|
||||||
|
* machine-dependent tuning (e.g., assembly coding).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* SIMD Ext: configuration check */
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE != 8
|
||||||
|
#error "Sorry, this SIMD code only copes with 8-bit sample values."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A forward DCT routine is given a pointer to a work area of type DCTELEM[];
|
||||||
|
* the DCT is to be performed in-place in that buffer. Type DCTELEM is int
|
||||||
|
* for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
|
||||||
|
* implementations use an array of type FAST_FLOAT, instead.)
|
||||||
|
* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
|
||||||
|
* The DCT outputs are returned scaled up by a factor of 8; they therefore
|
||||||
|
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
|
||||||
|
* convention improves accuracy in integer implementations and saves some
|
||||||
|
* work in floating-point ones.
|
||||||
|
* Quantization of the output coefficients is done by jcdctmgr.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* SIMD Ext: To maximize parallelism, Type DCTELEM is changed to short
|
||||||
|
* (originally, int).
|
||||||
|
*/
|
||||||
|
typedef short DCTELEM; /* SIMD Ext: must be short */
|
||||||
|
|
||||||
|
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
|
||||||
|
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
|
||||||
|
typedef JMETHOD(void, convsamp_int_method_ptr,
|
||||||
|
(JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
DCTELEM * workspace));
|
||||||
|
typedef JMETHOD(void, convsamp_float_method_ptr,
|
||||||
|
(JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||||
|
FAST_FLOAT *workspace));
|
||||||
|
typedef JMETHOD(void, quantize_int_method_ptr,
|
||||||
|
(JCOEFPTR coef_block, DCTELEM * divisors,
|
||||||
|
DCTELEM * workspace));
|
||||||
|
typedef JMETHOD(void, quantize_float_method_ptr,
|
||||||
|
(JCOEFPTR coef_block, FAST_FLOAT * divisors,
|
||||||
|
FAST_FLOAT * workspace));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
|
||||||
|
* to an output sample array. The routine must dequantize the input data as
|
||||||
|
* well as perform the IDCT; for dequantization, it uses the multiplier table
|
||||||
|
* pointed to by compptr->dct_table. The output data is to be placed into the
|
||||||
|
* sample array starting at a specified column. (Any row offset needed will
|
||||||
|
* be applied to the array pointer before it is passed to the IDCT code.)
|
||||||
|
* Note that the number of samples emitted by the IDCT routine is
|
||||||
|
* DCT_scaled_size * DCT_scaled_size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
|
||||||
|
|
||||||
|
/* SIMD Ext: To maximize parallelism, Type MULTIPLIER is changed to short.
|
||||||
|
* Macro definitions of MULTIPLIER and FAST_FLOAT in jmorecfg.h are ignored.
|
||||||
|
*/
|
||||||
|
#undef MULTIPLIER
|
||||||
|
#define MULTIPLIER short /* SIMD Ext: must be short */
|
||||||
|
#undef FAST_FLOAT
|
||||||
|
#define FAST_FLOAT float /* SIMD Ext: must be float */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine has its own ideas about the best dct_table element type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef MULTIPLIER ISLOW_MULT_TYPE; /* SIMD Ext: must be short */
|
||||||
|
typedef MULTIPLIER IFAST_MULT_TYPE; /* SIMD Ext: must be short */
|
||||||
|
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
|
||||||
|
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* SIMD Ext: must be float */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine is responsible for range-limiting its results and
|
||||||
|
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
|
||||||
|
* be quite far out of range if the input data is corrupt, so a bulletproof
|
||||||
|
* range-limiting step is required. We use a mask-and-table-lookup method
|
||||||
|
* to do the combined operations quickly. See the comments with
|
||||||
|
* prepare_range_limit_table (in jdmaster.c) for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
|
||||||
|
|
||||||
|
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
|
||||||
|
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#define jpeg_fdct_islow jFDislow /* jfdctint.asm */
|
||||||
|
#define jpeg_fdct_ifast jFDifast /* jfdctfst.asm */
|
||||||
|
#define jpeg_fdct_float jFDfloat /* jfdctflt.asm */
|
||||||
|
#define jpeg_fdct_islow_mmx jFDMislow /* jfmmxint.asm */
|
||||||
|
#define jpeg_fdct_ifast_mmx jFDMifast /* jfmmxfst.asm */
|
||||||
|
#define jpeg_fdct_float_3dnow jFD3float /* jf3dnflt.asm */
|
||||||
|
#define jpeg_fdct_islow_sse2 jFDSislow /* jfss2int.asm */
|
||||||
|
#define jpeg_fdct_ifast_sse2 jFDSifast /* jfss2fst.asm */
|
||||||
|
#define jpeg_fdct_float_sse jFDSfloat /* jfsseflt.asm */
|
||||||
|
#define jpeg_convsamp_int jCnvInt /* jcqntint.asm */
|
||||||
|
#define jpeg_quantize_int jQntInt /* jcqntint.asm */
|
||||||
|
#define jpeg_quantize_idiv jQntIDiv /* jcqntint.asm */
|
||||||
|
#define jpeg_convsamp_float jCnvFloat /* jcqntflt.asm */
|
||||||
|
#define jpeg_quantize_float jQntFloat /* jcqntflt.asm */
|
||||||
|
#define jpeg_convsamp_int_mmx jCnvMmx /* jcqntmmx.asm */
|
||||||
|
#define jpeg_quantize_int_mmx jQntMmx /* jcqntmmx.asm */
|
||||||
|
#define jpeg_convsamp_flt_3dnow jCnv3dnow /* jcqnt3dn.asm */
|
||||||
|
#define jpeg_quantize_flt_3dnow jQnt3dnow /* jcqnt3dn.asm */
|
||||||
|
#define jpeg_convsamp_int_sse2 jCnvISse2 /* jcqnts2i.asm */
|
||||||
|
#define jpeg_quantize_int_sse2 jQntISse2 /* jcqnts2i.asm */
|
||||||
|
#define jpeg_convsamp_flt_sse jCnvSse /* jcqntsse.asm */
|
||||||
|
#define jpeg_quantize_flt_sse jQntSse /* jcqntsse.asm */
|
||||||
|
#define jpeg_convsamp_flt_sse2 jCnvFSse2 /* jcqnts2f.asm */
|
||||||
|
#define jpeg_quantize_flt_sse2 jQntFSse2 /* jcqnts2f.asm */
|
||||||
|
#define jpeg_idct_islow jRDislow /* jidctint.asm */
|
||||||
|
#define jpeg_idct_ifast jRDifast /* jidctfst.asm */
|
||||||
|
#define jpeg_idct_float jRDfloat /* jidctflt.asm */
|
||||||
|
#define jpeg_idct_4x4 jRD4x4 /* jidctred.asm */
|
||||||
|
#define jpeg_idct_2x2 jRD2x2 /* jidctred.asm */
|
||||||
|
#define jpeg_idct_1x1 jRD1x1 /* jidctred.asm */
|
||||||
|
#define jpeg_idct_islow_mmx jRDMislow /* jimmxint.asm */
|
||||||
|
#define jpeg_idct_ifast_mmx jRDMifast /* jimmxfst.asm */
|
||||||
|
#define jpeg_idct_float_3dnow jRD3float /* ji3dnflt.asm */
|
||||||
|
#define jpeg_idct_4x4_mmx jRDM4x4 /* jimmxred.asm */
|
||||||
|
#define jpeg_idct_2x2_mmx jRDM2x2 /* jimmxred.asm */
|
||||||
|
#define jpeg_idct_islow_sse2 jRDSislow /* jiss2int.asm */
|
||||||
|
#define jpeg_idct_ifast_sse2 jRDSifast /* jiss2fst.asm */
|
||||||
|
#define jpeg_idct_float_sse jRDSfloat /* jisseflt.asm */
|
||||||
|
#define jpeg_idct_float_sse2 jRD2float /* jiss2flt.asm */
|
||||||
|
#define jpeg_idct_4x4_sse2 jRDS4x4 /* jiss2red.asm */
|
||||||
|
#define jpeg_idct_2x2_sse2 jRDS2x2 /* jiss2red.asm */
|
||||||
|
#define jconst_fdct_float jFCfloat /* jfdctflt.asm */
|
||||||
|
#define jconst_fdct_islow_mmx jFCMislow /* jfmmxint.asm */
|
||||||
|
#define jconst_fdct_ifast_mmx jFCMifast /* jfmmxfst.asm */
|
||||||
|
#define jconst_fdct_float_3dnow jFC3float /* jf3dnflt.asm */
|
||||||
|
#define jconst_fdct_islow_sse2 jFCSislow /* jfss2int.asm */
|
||||||
|
#define jconst_fdct_ifast_sse2 jFCSifast /* jfss2fst.asm */
|
||||||
|
#define jconst_fdct_float_sse jFCSfloat /* jfsseflt.asm */
|
||||||
|
#define jconst_idct_float jRCfloat /* jidctflt.asm */
|
||||||
|
#define jconst_idct_islow_mmx jRCMislow /* jimmxint.asm */
|
||||||
|
#define jconst_idct_ifast_mmx jRCMifast /* jimmxfst.asm */
|
||||||
|
#define jconst_idct_float_3dnow jRC3float /* ji3dnflt.asm */
|
||||||
|
#define jconst_idct_red_mmx jRCMred /* jimmxred.asm */
|
||||||
|
#define jconst_idct_islow_sse2 jRCSislow /* jiss2int.asm */
|
||||||
|
#define jconst_idct_ifast_sse2 jRCSifast /* jiss2fst.asm */
|
||||||
|
#define jconst_idct_float_sse jRCSfloat /* jisseflt.asm */
|
||||||
|
#define jconst_idct_float_sse2 jRC2float /* jiss2flt.asm */
|
||||||
|
#define jconst_idct_red_sse2 jRCSred /* jiss2red.asm */
|
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||||
|
|
||||||
|
/* Extern declarations for the forward and inverse DCT routines. */
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_fdct_islow_mmx JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_ifast_mmx JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_float_3dnow JPP((FAST_FLOAT * data));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_fdct_islow_sse2 JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_ifast_sse2 JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_float_sse JPP((FAST_FLOAT * data));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_convsamp_int
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_int
|
||||||
|
JPP((JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_idiv
|
||||||
|
JPP((JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_convsamp_float
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_float
|
||||||
|
JPP((JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_convsamp_int_mmx
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_int_mmx
|
||||||
|
JPP((JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_convsamp_flt_3dnow
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_flt_3dnow
|
||||||
|
JPP((JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_convsamp_int_sse2
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_int_sse2
|
||||||
|
JPP((JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace));
|
||||||
|
EXTERN(void) jpeg_convsamp_flt_sse
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_flt_sse
|
||||||
|
JPP((JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace));
|
||||||
|
EXTERN(void) jpeg_convsamp_flt_sse2
|
||||||
|
JPP((JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace));
|
||||||
|
EXTERN(void) jpeg_quantize_flt_sse2
|
||||||
|
JPP((JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_idct_islow
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_ifast
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_float
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_4x4
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_2x2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_1x1
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_idct_islow_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_ifast_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_4x4_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_2x2_mmx
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_idct_float_3dnow
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_float_sse
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_float_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_idct_islow_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_ifast_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_4x4_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_2x2_sse2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
extern const int jconst_fdct_float[];
|
||||||
|
extern const int jconst_fdct_islow_mmx[];
|
||||||
|
extern const int jconst_fdct_ifast_mmx[];
|
||||||
|
extern const int jconst_fdct_float_3dnow[];
|
||||||
|
extern const int jconst_fdct_islow_sse2[];
|
||||||
|
extern const int jconst_fdct_ifast_sse2[];
|
||||||
|
extern const int jconst_fdct_float_sse[];
|
||||||
|
extern const int jconst_idct_float[];
|
||||||
|
extern const int jconst_idct_islow_mmx[];
|
||||||
|
extern const int jconst_idct_ifast_mmx[];
|
||||||
|
extern const int jconst_idct_float_3dnow[];
|
||||||
|
extern const int jconst_idct_red_mmx[];
|
||||||
|
extern const int jconst_idct_islow_sse2[];
|
||||||
|
extern const int jconst_idct_ifast_sse2[];
|
||||||
|
extern const int jconst_idct_float_sse[];
|
||||||
|
extern const int jconst_idct_float_sse2[];
|
||||||
|
extern const int jconst_idct_red_sse2[];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for handling fixed-point arithmetic; these are used by many
|
||||||
|
* but not all of the DCT/IDCT modules.
|
||||||
|
*
|
||||||
|
* All values are expected to be of type INT32.
|
||||||
|
* Fractional constants are scaled left by CONST_BITS bits.
|
||||||
|
* CONST_BITS is defined within each module using these macros,
|
||||||
|
* and may differ from one module to the next.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ONE ((INT32) 1)
|
||||||
|
#define CONST_SCALE (ONE << CONST_BITS)
|
||||||
|
|
||||||
|
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
|
||||||
|
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
|
||||||
|
* thus causing a lot of useless floating-point operations at run time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
|
||||||
|
|
||||||
|
/* Descale and correctly round an INT32 value that's scaled by N bits.
|
||||||
|
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
|
||||||
|
* the fudge factor is correct for either sign of X.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
|
||||||
|
|
||||||
|
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
|
||||||
|
* This macro is used only when the two inputs will actually be no more than
|
||||||
|
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
|
||||||
|
* full 32x32 multiply. This provides a useful speedup on many machines.
|
||||||
|
* Unfortunately there is no way to specify a 16x16->32 multiply portably
|
||||||
|
* in C, but some C compilers will do the right thing if you provide the
|
||||||
|
* correct combination of casts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
|
||||||
|
#endif
|
||||||
|
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
|
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MULTIPLY16C16 /* default definition */
|
||||||
|
#define MULTIPLY16C16(var,const) ((var) * (const))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Same except both inputs are variables. */
|
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||||
|
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MULTIPLY16V16 /* default definition */
|
||||||
|
#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
|
||||||
|
#endif
|
||||||
125
jdct.inc
Normal file
125
jdct.inc
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
;
|
||||||
|
; jdct.inc - private declarations for forward & reverse DCT subsystems
|
||||||
|
;
|
||||||
|
; x86 SIMD extension for IJG JPEG library
|
||||||
|
; Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
; For conditions of distribution and use, see copyright notice in jsimdext.inc
|
||||||
|
;
|
||||||
|
; Last Modified : January 5, 2006
|
||||||
|
;
|
||||||
|
; [TAB8]
|
||||||
|
|
||||||
|
; ---- jdct.h --------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; configuration check: BITS_IN_JSAMPLE==8 (8-bit sample values) is the only
|
||||||
|
; valid setting on this SIMD extension.
|
||||||
|
;
|
||||||
|
%if BITS_IN_JSAMPLE != 8
|
||||||
|
%error "Sorry, this SIMD code only copes with 8-bit sample values."
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; A forward DCT routine is given a pointer to a work area of type DCTELEM[];
|
||||||
|
; the DCT is to be performed in-place in that buffer.
|
||||||
|
; To maximize parallelism, Type DCTELEM is changed to short (originally, int).
|
||||||
|
;
|
||||||
|
%define DCTELEM word ; short
|
||||||
|
%define SIZEOF_DCTELEM SIZEOF_WORD ; sizeof(DCTELEM)
|
||||||
|
|
||||||
|
; To maximize parallelism, Type MULTIPLIER is changed to short.
|
||||||
|
;
|
||||||
|
%define MULTIPLIER word ; short
|
||||||
|
%define SIZEOF_MULTIPLIER SIZEOF_WORD ; sizeof(MULTIPLIER)
|
||||||
|
%define FAST_FLOAT FP32 ; float
|
||||||
|
%define SIZEOF_FAST_FLOAT SIZEOF_FP32 ; sizeof(FAST_FLOAT)
|
||||||
|
|
||||||
|
; Each IDCT routine has its own ideas about the best dct_table element type.
|
||||||
|
;
|
||||||
|
%define ISLOW_MULT_TYPE MULTIPLIER ; must be short
|
||||||
|
%define SIZEOF_ISLOW_MULT_TYPE SIZEOF_MULTIPLIER ; sizeof(ISLOW_MULT_TYPE)
|
||||||
|
%define IFAST_MULT_TYPE MULTIPLIER ; must be short
|
||||||
|
%define SIZEOF_IFAST_MULT_TYPE SIZEOF_MULTIPLIER ; sizeof(IFAST_MULT_TYPE)
|
||||||
|
%define IFAST_SCALE_BITS 2 ; fractional bits in scale factors
|
||||||
|
%define FLOAT_MULT_TYPE FAST_FLOAT ; must be float
|
||||||
|
%define SIZEOF_FLOAT_MULT_TYPE SIZEOF_FAST_FLOAT ; sizeof(FLOAT_MULT_TYPE)
|
||||||
|
|
||||||
|
; Each IDCT routine is responsible for range-limiting its results and
|
||||||
|
; converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
|
||||||
|
; be quite far out of range if the input data is corrupt, so a bulletproof
|
||||||
|
; range-limiting step is required. We use a mask-and-table-lookup method
|
||||||
|
; to do the combined operations quickly.
|
||||||
|
;
|
||||||
|
%define RANGE_MASK (MAXJSAMPLE * 4 + 3) ; 2 bits wider than legal samples
|
||||||
|
|
||||||
|
; Short forms of external names for systems with brain-damaged linkers.
|
||||||
|
;
|
||||||
|
%ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
%define jpeg_fdct_islow jFDislow ; jfdctint.asm
|
||||||
|
%define jpeg_fdct_ifast jFDifast ; jfdctfst.asm
|
||||||
|
%define jpeg_fdct_float jFDfloat ; jfdctflt.asm
|
||||||
|
%define jpeg_fdct_islow_mmx jFDMislow ; jfmmxint.asm
|
||||||
|
%define jpeg_fdct_ifast_mmx jFDMifast ; jfmmxfst.asm
|
||||||
|
%define jpeg_fdct_float_3dnow jFD3float ; jf3dnflt.asm
|
||||||
|
%define jpeg_fdct_islow_sse2 jFDSislow ; jfss2int.asm
|
||||||
|
%define jpeg_fdct_ifast_sse2 jFDSifast ; jfss2fst.asm
|
||||||
|
%define jpeg_fdct_float_sse jFDSfloat ; jfsseflt.asm
|
||||||
|
%define jpeg_convsamp_int jCnvInt ; jcqntint.asm
|
||||||
|
%define jpeg_quantize_int jQntInt ; jcqntint.asm
|
||||||
|
%define jpeg_quantize_idiv jQntIDiv ; jcqntint.asm
|
||||||
|
%define jpeg_convsamp_float jCnvFloat ; jcqntflt.asm
|
||||||
|
%define jpeg_quantize_float jQntFloat ; jcqntflt.asm
|
||||||
|
%define jpeg_convsamp_int_mmx jCnvMmx ; jcqntmmx.asm
|
||||||
|
%define jpeg_quantize_int_mmx jQntMmx ; jcqntmmx.asm
|
||||||
|
%define jpeg_convsamp_flt_3dnow jCnv3dnow ; jcqnt3dn.asm
|
||||||
|
%define jpeg_quantize_flt_3dnow jQnt3dnow ; jcqnt3dn.asm
|
||||||
|
%define jpeg_convsamp_int_sse2 jCnvISse2 ; jcqnts2i.asm
|
||||||
|
%define jpeg_quantize_int_sse2 jQntISse2 ; jcqnts2i.asm
|
||||||
|
%define jpeg_convsamp_flt_sse jCnvSse ; jcqntsse.asm
|
||||||
|
%define jpeg_quantize_flt_sse jQntSse ; jcqntsse.asm
|
||||||
|
%define jpeg_convsamp_flt_sse2 jCnvFSse2 ; jcqnts2f.asm
|
||||||
|
%define jpeg_quantize_flt_sse2 jQntFSse2 ; jcqnts2f.asm
|
||||||
|
%define jpeg_idct_islow jRDislow ; jidctint.asm
|
||||||
|
%define jpeg_idct_ifast jRDifast ; jidctfst.asm
|
||||||
|
%define jpeg_idct_float jRDfloat ; jidctflt.asm
|
||||||
|
%define jpeg_idct_4x4 jRD4x4 ; jidctred.asm
|
||||||
|
%define jpeg_idct_2x2 jRD2x2 ; jidctred.asm
|
||||||
|
%define jpeg_idct_1x1 jRD1x1 ; jidctred.asm
|
||||||
|
%define jpeg_idct_islow_mmx jRDMislow ; jimmxint.asm
|
||||||
|
%define jpeg_idct_ifast_mmx jRDMifast ; jimmxfst.asm
|
||||||
|
%define jpeg_idct_float_3dnow jRD3float ; ji3dnflt.asm
|
||||||
|
%define jpeg_idct_4x4_mmx jRDM4x4 ; jimmxred.asm
|
||||||
|
%define jpeg_idct_2x2_mmx jRDM2x2 ; jimmxred.asm
|
||||||
|
%define jpeg_idct_islow_sse2 jRDSislow ; jiss2int.asm
|
||||||
|
%define jpeg_idct_ifast_sse2 jRDSifast ; jiss2fst.asm
|
||||||
|
%define jpeg_idct_float_sse jRDSfloat ; jisseflt.asm
|
||||||
|
%define jpeg_idct_float_sse2 jRD2float ; jiss2flt.asm
|
||||||
|
%define jpeg_idct_4x4_sse2 jRDS4x4 ; jiss2red.asm
|
||||||
|
%define jpeg_idct_2x2_sse2 jRDS2x2 ; jiss2red.asm
|
||||||
|
%define jconst_fdct_float jFCfloat ; jfdctflt.asm
|
||||||
|
%define jconst_fdct_islow_mmx jFCMislow ; jfmmxint.asm
|
||||||
|
%define jconst_fdct_ifast_mmx jFCMifast ; jfmmxfst.asm
|
||||||
|
%define jconst_fdct_float_3dnow jFC3float ; jf3dnflt.asm
|
||||||
|
%define jconst_fdct_islow_sse2 jFCSislow ; jfss2int.asm
|
||||||
|
%define jconst_fdct_ifast_sse2 jFCSifast ; jfss2fst.asm
|
||||||
|
%define jconst_fdct_float_sse jFCSfloat ; jfsseflt.asm
|
||||||
|
%define jconst_idct_float jRCfloat ; jidctflt.asm
|
||||||
|
%define jconst_idct_islow_mmx jRCMislow ; jimmxint.asm
|
||||||
|
%define jconst_idct_ifast_mmx jRCMifast ; jimmxfst.asm
|
||||||
|
%define jconst_idct_float_3dnow jRC3float ; ji3dnflt.asm
|
||||||
|
%define jconst_idct_red_mmx jRCMred ; jimmxred.asm
|
||||||
|
%define jconst_idct_islow_sse2 jRCSislow ; jiss2int.asm
|
||||||
|
%define jconst_idct_ifast_sse2 jRCSifast ; jiss2fst.asm
|
||||||
|
%define jconst_idct_float_sse jRCSfloat ; jisseflt.asm
|
||||||
|
%define jconst_idct_float_sse2 jRC2float ; jiss2flt.asm
|
||||||
|
%define jconst_idct_red_sse2 jRCSred ; jiss2red.asm
|
||||||
|
%endif ; NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%define ROW(n,b,s) ((b)+(n)*(s))
|
||||||
|
%define COL(n,b,s) ((b)+(n)*(s)*DCTSIZE)
|
||||||
|
|
||||||
|
%define DWBLOCK(m,n,b,s) ((b)+(m)*DCTSIZE*(s)+(n)*SIZEOF_DWORD)
|
||||||
|
%define MMBLOCK(m,n,b,s) ((b)+(m)*DCTSIZE*(s)+(n)*SIZEOF_MMWORD)
|
||||||
|
%define XMMBLOCK(m,n,b,s) ((b)+(m)*DCTSIZE*(s)+(n)*SIZEOF_XMMWORD)
|
||||||
|
|
||||||
|
; --------------------------------------------------------------------------
|
||||||
413
jddctmgr.c
Normal file
413
jddctmgr.c
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
* jddctmgr.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified for SIMD extension.
|
||||||
|
* Last Modified : December 24, 2005
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains the inverse-DCT management logic.
|
||||||
|
* This code selects a particular IDCT implementation to be used,
|
||||||
|
* and it performs related housekeeping chores. No code in this file
|
||||||
|
* is executed per IDCT step, only during output pass setup.
|
||||||
|
*
|
||||||
|
* Note that the IDCT routines are responsible for performing coefficient
|
||||||
|
* dequantization as well as the IDCT proper. This module sets up the
|
||||||
|
* dequantization multiplier table needed by the IDCT routine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The decompressor input side (jdinput.c) saves away the appropriate
|
||||||
|
* quantization table for each component at the start of the first scan
|
||||||
|
* involving that component. (This is necessary in order to correctly
|
||||||
|
* decode files that reuse Q-table slots.)
|
||||||
|
* When we are ready to make an output pass, the saved Q-table is converted
|
||||||
|
* to a multiplier table that will actually be used by the IDCT routine.
|
||||||
|
* The multiplier table contents are IDCT-method-dependent. To support
|
||||||
|
* application changes in IDCT method between scans, we can remake the
|
||||||
|
* multiplier tables if necessary.
|
||||||
|
* In buffered-image mode, the first output pass may occur before any data
|
||||||
|
* has been seen for some components, and thus before their Q-tables have
|
||||||
|
* been saved away. To handle this case, multiplier tables are preset
|
||||||
|
* to zeroes; the result of the IDCT will be a neutral gray level.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Private subobject for this module */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_inverse_dct pub; /* public fields */
|
||||||
|
|
||||||
|
/* This array contains the IDCT method code that each multiplier table
|
||||||
|
* is currently set up for, or -1 if it's not yet set up.
|
||||||
|
* The actual multiplier tables are pointed to by dct_table in the
|
||||||
|
* per-component comp_info structures.
|
||||||
|
*/
|
||||||
|
int cur_method[MAX_COMPONENTS];
|
||||||
|
} my_idct_controller;
|
||||||
|
|
||||||
|
typedef my_idct_controller * my_idct_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocated multiplier tables: big enough for any supported variant */
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
ISLOW_MULT_TYPE islow_array[DCTSIZE2];
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
IFAST_MULT_TYPE ifast_array[DCTSIZE2];
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
FLOAT_MULT_TYPE float_array[DCTSIZE2];
|
||||||
|
#endif
|
||||||
|
} multiplier_table;
|
||||||
|
|
||||||
|
|
||||||
|
/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
|
||||||
|
* so be sure to compile that code if either ISLOW or SCALING is requested.
|
||||||
|
*/
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
#define PROVIDE_ISLOW_TABLES
|
||||||
|
#else
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
#define PROVIDE_ISLOW_TABLES
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for an output pass.
|
||||||
|
* Here we select the proper IDCT routine for each component and build
|
||||||
|
* a matching multiplier table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
|
||||||
|
int ci, i;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
int method = 0;
|
||||||
|
inverse_DCT_method_ptr method_ptr = NULL;
|
||||||
|
JQUANT_TBL * qtbl;
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Select the proper IDCT routine for this component's scaling */
|
||||||
|
switch (compptr->DCT_scaled_size) {
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
case 1:
|
||||||
|
method_ptr = jpeg_idct_1x1;
|
||||||
|
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_red_sse2))
|
||||||
|
method_ptr = jpeg_idct_2x2_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
method_ptr = jpeg_idct_2x2_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
method_ptr = jpeg_idct_2x2;
|
||||||
|
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_red_sse2))
|
||||||
|
method_ptr = jpeg_idct_4x4_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
method_ptr = jpeg_idct_4x4_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
method_ptr = jpeg_idct_4x4;
|
||||||
|
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||||
|
break;
|
||||||
|
#endif /* IDCT_SCALING_SUPPORTED */
|
||||||
|
case DCTSIZE:
|
||||||
|
switch (cinfo->dct_method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_islow_sse2))
|
||||||
|
method_ptr = jpeg_idct_islow_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
method_ptr = jpeg_idct_islow_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
method_ptr = jpeg_idct_islow;
|
||||||
|
method = JDCT_ISLOW;
|
||||||
|
break;
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_ifast_sse2))
|
||||||
|
method_ptr = jpeg_idct_ifast_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
method_ptr = jpeg_idct_ifast_mmx;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
method_ptr = jpeg_idct_ifast;
|
||||||
|
method = JDCT_IFAST;
|
||||||
|
break;
|
||||||
|
#endif /* DCT_IFAST_SUPPORTED */
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
#ifdef JIDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE && simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_float_sse2))
|
||||||
|
method_ptr = jpeg_idct_float_sse2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_float_sse))
|
||||||
|
method_ptr = jpeg_idct_float_sse;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_3DNOW)
|
||||||
|
method_ptr = jpeg_idct_float_3dnow;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
method_ptr = jpeg_idct_float;
|
||||||
|
method = JDCT_FLOAT;
|
||||||
|
break;
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
idct->pub.inverse_DCT[ci] = method_ptr;
|
||||||
|
/* Create multiplier table from quant table.
|
||||||
|
* However, we can skip this if the component is uninteresting
|
||||||
|
* or if we already built the table. Also, if no quant table
|
||||||
|
* has yet been saved for the component, we leave the
|
||||||
|
* multiplier table all-zero; we'll be reading zeroes from the
|
||||||
|
* coefficient controller's buffer anyway.
|
||||||
|
*/
|
||||||
|
if (! compptr->component_needed || idct->cur_method[ci] == method)
|
||||||
|
continue;
|
||||||
|
qtbl = compptr->quant_table;
|
||||||
|
if (qtbl == NULL) /* happens if no data yet for component */
|
||||||
|
continue;
|
||||||
|
idct->cur_method[ci] = method;
|
||||||
|
switch (method) {
|
||||||
|
#ifdef PROVIDE_ISLOW_TABLES
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
{
|
||||||
|
/* For LL&M IDCT method, multipliers are equal to raw quantization
|
||||||
|
* coefficients, but are stored as ints to ensure access efficiency.
|
||||||
|
*/
|
||||||
|
ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
{
|
||||||
|
/* For AA&N IDCT method, multipliers are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||||
|
* scalefactor[0] = 1
|
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||||
|
* For integer operation, the multiplier table is to be scaled by
|
||||||
|
* IFAST_SCALE_BITS.
|
||||||
|
*/
|
||||||
|
IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
|
||||||
|
#define CONST_BITS 14
|
||||||
|
static const INT16 aanscales[DCTSIZE2] = {
|
||||||
|
/* precomputed values scaled up by 14 bits */
|
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||||
|
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
|
||||||
|
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
|
||||||
|
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
|
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||||
|
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
|
||||||
|
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
|
||||||
|
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
|
||||||
|
};
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
ifmtbl[i] = (IFAST_MULT_TYPE)
|
||||||
|
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
|
||||||
|
(INT32) aanscales[i]),
|
||||||
|
CONST_BITS-IFAST_SCALE_BITS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
{
|
||||||
|
/* For float AA&N IDCT method, multipliers are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||||
|
* scalefactor[0] = 1
|
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||||
|
*/
|
||||||
|
FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
|
||||||
|
int row, col;
|
||||||
|
static const double aanscalefactor[DCTSIZE] = {
|
||||||
|
1.0, 1.387039845, 1.306562965, 1.175875602,
|
||||||
|
1.0, 0.785694958, 0.541196100, 0.275899379
|
||||||
|
};
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (row = 0; row < DCTSIZE; row++) {
|
||||||
|
for (col = 0; col < DCTSIZE; col++) {
|
||||||
|
fmtbl[i] = (FLOAT_MULT_TYPE)
|
||||||
|
((double) qtbl->quantval[i] *
|
||||||
|
aanscalefactor[row] * aanscalefactor[col]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize IDCT manager.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_inverse_dct (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_idct_ptr idct;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
idct = (my_idct_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_idct_controller));
|
||||||
|
cinfo->idct = (struct jpeg_inverse_dct *) idct;
|
||||||
|
idct->pub.start_pass = start_pass;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Allocate and pre-zero a multiplier table for each component */
|
||||||
|
compptr->dct_table =
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(multiplier_table));
|
||||||
|
MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
|
||||||
|
/* Mark multiplier table not yet set up for any method */
|
||||||
|
idct->cur_method[ci] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JSIMD_MODEINFO_NOT_SUPPORTED
|
||||||
|
|
||||||
|
GLOBAL(unsigned int)
|
||||||
|
jpeg_simd_inverse_dct (j_decompress_ptr cinfo, int method)
|
||||||
|
{
|
||||||
|
unsigned int simd = jpeg_simd_support((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_islow_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
||||||
|
#ifdef DCT_IFAST_SUPPORTED
|
||||||
|
case JDCT_IFAST:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_ifast_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_IFAST_SUPPORTED */
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED
|
||||||
|
case JDCT_FLOAT:
|
||||||
|
#ifdef JIDCT_FLT_SSE_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE && simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_float_sse2))
|
||||||
|
return JSIMD_SSE; /* (JSIMD_SSE | JSIMD_SSE2); */
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_FLT_SSE_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_float_sse))
|
||||||
|
return JSIMD_SSE; /* (JSIMD_SSE | JSIMD_MMX); */
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_FLT_3DNOW_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_3DNOW)
|
||||||
|
return JSIMD_3DNOW; /* (JSIMD_3DNOW | JSIMD_MMX); */
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
case JDCT_FLOAT + 1:
|
||||||
|
#ifdef JIDCT_INT_SSE2_SUPPORTED
|
||||||
|
if (simd & JSIMD_SSE2 &&
|
||||||
|
IS_CONST_ALIGNED_16(jconst_idct_red_sse2))
|
||||||
|
return JSIMD_SSE2;
|
||||||
|
#endif
|
||||||
|
#ifdef JIDCT_INT_MMX_SUPPORTED
|
||||||
|
if (simd & JSIMD_MMX)
|
||||||
|
return JSIMD_MMX;
|
||||||
|
#endif
|
||||||
|
return JSIMD_NONE;
|
||||||
|
#endif /* IDCT_SCALING_SUPPORTED */
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSIMD_NONE; /* not compiled */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JSIMD_MODEINFO_NOT_SUPPORTED */
|
||||||
117
jddeflts.c
117
jddeflts.c
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* jddeflts.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 decompressor.
|
|
||||||
* User interfaces do not have to use this file, but those that don't use it
|
|
||||||
* must know more about the innards of the JPEG code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jinclude.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reload the input buffer after it's been emptied, and return the next byte.
|
|
||||||
* See the JGETC macro for calling conditions.
|
|
||||||
*
|
|
||||||
* This routine is used only if the system-dependent user interface passes
|
|
||||||
* standard_buffering = TRUE to j_d_defaults. Otherwise, the UI must supply
|
|
||||||
* a corresponding routine. Note that in any case, this routine is likely
|
|
||||||
* to be used only for JFIF or similar serial-access JPEG file formats.
|
|
||||||
* The input file control module for a random-access format such as TIFF/JPEG
|
|
||||||
* would need to override the read_jpeg_data method with its own routine.
|
|
||||||
*
|
|
||||||
* This routine would need to be replaced if reading JPEG data from something
|
|
||||||
* other than a stdio stream.
|
|
||||||
*/
|
|
||||||
|
|
||||||
METHODDEF int
|
|
||||||
read_jpeg_data (decompress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
|
|
||||||
|
|
||||||
cinfo->bytes_in_buffer = (int) FREAD(cinfo->input_file,
|
|
||||||
cinfo->next_input_byte,
|
|
||||||
JPEG_BUF_SIZE);
|
|
||||||
|
|
||||||
if (cinfo->bytes_in_buffer <= 0)
|
|
||||||
ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
|
|
||||||
|
|
||||||
return JGETC(cinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Default parameter setup for decompression.
|
|
||||||
*
|
|
||||||
* User interfaces that don't choose to use this routine must do their
|
|
||||||
* own setup of all these parameters. Alternately, you can call this
|
|
||||||
* to establish defaults and then alter parameters selectively. This
|
|
||||||
* is the recommended approach since, if we add any new parameters,
|
|
||||||
* your code will still work (they'll be set to reasonable defaults).
|
|
||||||
*
|
|
||||||
* standard_buffering should be TRUE if the JPEG data is to come from
|
|
||||||
* a stdio stream and the user interface isn't interested in changing
|
|
||||||
* the normal input-buffering logic. If FALSE is passed, the user
|
|
||||||
* interface must provide its own read_jpeg_data method and must
|
|
||||||
* set up its own input buffer. (Alternately, you can pass TRUE to
|
|
||||||
* let the buffer be allocated here, then override read_jpeg_data with
|
|
||||||
* your own routine.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
|
|
||||||
/* NB: the external methods must already be set up. */
|
|
||||||
{
|
|
||||||
/* Default to RGB output */
|
|
||||||
/* UI can override by changing out_color_space */
|
|
||||||
cinfo->out_color_space = CS_RGB;
|
|
||||||
cinfo->jpeg_color_space = CS_UNKNOWN;
|
|
||||||
/* Setting any other value in jpeg_color_space overrides heuristics in */
|
|
||||||
/* jrdjfif.c. That might be useful when reading non-JFIF JPEG files, */
|
|
||||||
/* but ordinarily the UI shouldn't change it. */
|
|
||||||
|
|
||||||
/* Default to no gamma correction of output */
|
|
||||||
cinfo->output_gamma = 1.0;
|
|
||||||
|
|
||||||
/* Default to no color quantization */
|
|
||||||
cinfo->quantize_colors = FALSE;
|
|
||||||
/* but set reasonable default parameters for quantization, */
|
|
||||||
/* so that turning on quantize_colors is sufficient to do something useful */
|
|
||||||
cinfo->two_pass_quantize = FALSE; /* may change to TRUE later */
|
|
||||||
cinfo->use_dithering = TRUE;
|
|
||||||
cinfo->desired_number_of_colors = 256;
|
|
||||||
|
|
||||||
/* Default to no smoothing */
|
|
||||||
cinfo->do_block_smoothing = FALSE;
|
|
||||||
cinfo->do_pixel_smoothing = FALSE;
|
|
||||||
|
|
||||||
if (standard_buffering) {
|
|
||||||
/* Allocate memory for input buffer. */
|
|
||||||
cinfo->input_buffer = (char *) (*cinfo->emethods->alloc_small)
|
|
||||||
((size_t) (JPEG_BUF_SIZE + MIN_UNGET));
|
|
||||||
cinfo->bytes_in_buffer = 0; /* initialize buffer to empty */
|
|
||||||
|
|
||||||
/* Install standard buffer-reloading method. */
|
|
||||||
cinfo->methods->read_jpeg_data = read_jpeg_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This routine releases storage allocated by j_d_defaults.
|
|
||||||
* Note that freeing the method pointer structs and the decompress_info_struct
|
|
||||||
* itself are the responsibility of the user interface.
|
|
||||||
*
|
|
||||||
* standard_buffering must agree with what was passed to j_d_defaults.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GLOBAL void
|
|
||||||
j_d_free_defaults (decompress_info_ptr cinfo, boolean standard_buffering)
|
|
||||||
{
|
|
||||||
if (standard_buffering) {
|
|
||||||
(*cinfo->emethods->free_small) ((void *) cinfo->input_buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
192
jdhuff.h
Normal file
192
jdhuff.h
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* jdhuff.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
* x86 SIMD extension for IJG JPEG library
|
||||||
|
* Copyright (C) 1999-2006, MIYASAKA Masaru.
|
||||||
|
* This file has been modified to improve performance.
|
||||||
|
* Last Modified : October 31, 2004
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This file contains declarations for Huffman entropy decoding routines
|
||||||
|
* that are shared between the sequential decoder (jdhuff.c) and the
|
||||||
|
* progressive decoder (jdphuff.c). No other modules need to see these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||||
|
#define jpeg_make_d_derived_tbl jMkDDerived
|
||||||
|
#define jpeg_fill_bit_buffer jFilBitBuf
|
||||||
|
#define jpeg_huff_decode jHufDecode
|
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||||
|
|
||||||
|
|
||||||
|
/* Derived data constructed for each Huffman table */
|
||||||
|
|
||||||
|
#define HUFFX_LOOKAHEAD 9 /* # of bits of lookahead */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Basic tables: (element [0] of each array is unused) */
|
||||||
|
INT32 maxcode[18]; /* largest code of length k (-1 if none) */
|
||||||
|
/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
|
||||||
|
INT32 valoffset[17]; /* huffval[] offset for codes of length k */
|
||||||
|
/* valoffset[k] = huffval[] index of 1st symbol of code length k, less
|
||||||
|
* the smallest code of length k; so given a code of length k, the
|
||||||
|
* corresponding symbol is huffval[code + valoffset[k]]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Link to public Huffman table (needed only in jpeg_huff_decode) */
|
||||||
|
JHUFF_TBL *pub;
|
||||||
|
|
||||||
|
/* Lookahead tables: indexed by the next HUFFX_LOOKAHEAD bits of
|
||||||
|
* the input data stream. If the next Huffman code is no more
|
||||||
|
* than HUFFX_LOOKAHEAD-1 bits long, we can obtain its length,
|
||||||
|
* the corresponding symbol, and the encoded coefficient value
|
||||||
|
* directly from these tables.
|
||||||
|
*/
|
||||||
|
UINT8 lookx_nbits[1<<HUFFX_LOOKAHEAD]; /* # bits, or 0 if too long */
|
||||||
|
INT16 lookx_val[1<<HUFFX_LOOKAHEAD]; /* coefficient value, or unused */
|
||||||
|
UINT8 lookx_sym[1<<HUFFX_LOOKAHEAD]; /* symbol, or unused */
|
||||||
|
} d_derived_tbl;
|
||||||
|
|
||||||
|
/* Expand a Huffman table definition into the derived format */
|
||||||
|
EXTERN(void) jpeg_make_d_derived_tbl
|
||||||
|
JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||||
|
d_derived_tbl ** pdtbl));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetching the next N bits from the input stream is a time-critical operation
|
||||||
|
* for the Huffman decoders. We implement it with a combination of inline
|
||||||
|
* macros and out-of-line subroutines. Note that N (the number of bits
|
||||||
|
* demanded at one time) never exceeds 15 for JPEG use.
|
||||||
|
*
|
||||||
|
* We read source bytes into get_buffer and dole out bits as needed.
|
||||||
|
* If get_buffer already contains enough bits, they are fetched in-line
|
||||||
|
* by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
|
||||||
|
* bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
|
||||||
|
* as full as possible (not just to the number of bits needed; this
|
||||||
|
* prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
|
||||||
|
* Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
|
||||||
|
* On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
|
||||||
|
* at least the requested number of bits --- dummy zeroes are inserted if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
|
||||||
|
#define BIT_BUF_SIZE 32 /* size of buffer in bits */
|
||||||
|
|
||||||
|
/* If long is > 32 bits on your machine, and shifting/masking longs is
|
||||||
|
* reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
|
||||||
|
* appropriately should be a win. Unfortunately we can't define the size
|
||||||
|
* with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
|
||||||
|
* because not all machines measure sizeof in 8-bit bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SLOW_SHIFT_32
|
||||||
|
#define MIN_GET_BITS 15 /* minimum allowable value */
|
||||||
|
#else
|
||||||
|
#define MIN_GET_BITS (BIT_BUF_SIZE-7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
|
||||||
|
* of get_buffer to be used. (On machines with wider words, an even larger
|
||||||
|
* buffer could be used.) However, on some machines 32-bit shifts are
|
||||||
|
* quite slow and take time proportional to the number of places shifted.
|
||||||
|
* (This is true with most PC compilers, for instance.) In this case it may
|
||||||
|
* be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
|
||||||
|
* average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct { /* Bitreading state saved across MCUs */
|
||||||
|
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||||
|
int bits_left; /* # of unused bits in it */
|
||||||
|
} bitread_perm_state;
|
||||||
|
|
||||||
|
typedef struct { /* Bitreading working state within an MCU */
|
||||||
|
/* Current data source location */
|
||||||
|
/* We need a copy, rather than munging the original, in case of suspension */
|
||||||
|
const JOCTET * next_input_byte; /* => next byte to read from source */
|
||||||
|
size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
|
||||||
|
/* Bit input buffer --- note these values are kept in register variables,
|
||||||
|
* not in this struct, inside the inner loops.
|
||||||
|
*/
|
||||||
|
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||||
|
int bits_left; /* # of unused bits in it */
|
||||||
|
/* Pointer needed by jpeg_fill_bit_buffer. */
|
||||||
|
j_decompress_ptr cinfo; /* back link to decompress master record */
|
||||||
|
} bitread_working_state;
|
||||||
|
|
||||||
|
/* Macros to declare and load/save bitread local variables. */
|
||||||
|
#define BITREAD_STATE_VARS \
|
||||||
|
register bit_buf_type get_buffer; \
|
||||||
|
register int bits_left; \
|
||||||
|
bitread_working_state br_state
|
||||||
|
|
||||||
|
#define BITREAD_LOAD_STATE(cinfop,permstate) \
|
||||||
|
br_state.cinfo = cinfop; \
|
||||||
|
br_state.next_input_byte = cinfop->src->next_input_byte; \
|
||||||
|
br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
|
||||||
|
get_buffer = permstate.get_buffer; \
|
||||||
|
bits_left = permstate.bits_left
|
||||||
|
|
||||||
|
#define BITREAD_SAVE_STATE(cinfop,permstate) \
|
||||||
|
cinfop->src->next_input_byte = br_state.next_input_byte; \
|
||||||
|
cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
|
||||||
|
permstate.get_buffer = get_buffer; \
|
||||||
|
permstate.bits_left = bits_left
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros provide the in-line portion of bit fetching.
|
||||||
|
* Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
|
||||||
|
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
|
||||||
|
* The variables get_buffer and bits_left are assumed to be locals,
|
||||||
|
* but the state struct might not be (jpeg_huff_decode needs this).
|
||||||
|
* CHECK_BIT_BUFFER(state,n,action);
|
||||||
|
* Ensure there are N bits in get_buffer; if suspend, take action.
|
||||||
|
* val = GET_BITS(n);
|
||||||
|
* Fetch next N bits.
|
||||||
|
* val = PEEK_BITS(n);
|
||||||
|
* Fetch next N bits without removing them from the buffer.
|
||||||
|
* DROP_BITS(n);
|
||||||
|
* Discard next N bits.
|
||||||
|
* The value N should be a simple variable, not an expression, because it
|
||||||
|
* is evaluated multiple times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CHECK_BIT_BUFFER(state,nbits,action) \
|
||||||
|
{ if (bits_left < (nbits)) { \
|
||||||
|
if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
|
||||||
|
{ action; } \
|
||||||
|
get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
|
||||||
|
|
||||||
|
#define GET_BITS(nbits) \
|
||||||
|
(((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
|
||||||
|
|
||||||
|
#define PEEK_BITS(nbits) \
|
||||||
|
(((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
|
||||||
|
|
||||||
|
#define DROP_BITS(nbits) \
|
||||||
|
(bits_left -= (nbits))
|
||||||
|
|
||||||
|
/* Load up the bit buffer to a depth of at least nbits */
|
||||||
|
EXTERN(boolean) jpeg_fill_bit_buffer
|
||||||
|
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
|
||||||
|
register int bits_left, int nbits));
|
||||||
|
|
||||||
|
/* Out-of-line case for Huffman code fetching */
|
||||||
|
EXTERN(int) jpeg_huff_decode
|
||||||
|
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
|
||||||
|
register int bits_left, d_derived_tbl * htbl, int min_bits));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure F.12: extend sign bit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||||
381
jdinput.c
Normal file
381
jdinput.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
* jdinput.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, 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 control logic for the JPEG decompressor.
|
||||||
|
* These routines are concerned with controlling the decompressor's input
|
||||||
|
* processing (marker reading and coefficient decoding). The actual input
|
||||||
|
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Private state */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_input_controller pub; /* public fields */
|
||||||
|
|
||||||
|
boolean inheaders; /* TRUE until first SOS is reached */
|
||||||
|
} my_input_controller;
|
||||||
|
|
||||||
|
typedef my_input_controller * my_inputctl_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines to calculate various quantities related to the size of the image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
initial_setup (j_decompress_ptr cinfo)
|
||||||
|
/* Called once, when first SOS marker is reached */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Make sure image isn't bigger than I can handle */
|
||||||
|
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
|
||||||
|
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
|
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
|
||||||
|
|
||||||
|
/* For now, precision must match compiled-in value... */
|
||||||
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
/* Check that number of components won't exceed internal array sizes */
|
||||||
|
if (cinfo->num_components > MAX_COMPONENTS)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||||
|
MAX_COMPONENTS);
|
||||||
|
|
||||||
|
/* Compute maximum sampling factors; check factor validity */
|
||||||
|
cinfo->max_h_samp_factor = 1;
|
||||||
|
cinfo->max_v_samp_factor = 1;
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
||||||
|
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_SAMPLING);
|
||||||
|
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||||
|
compptr->h_samp_factor);
|
||||||
|
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||||
|
compptr->v_samp_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
|
||||||
|
* In the full decompressor, this will be overridden by jdmaster.c;
|
||||||
|
* but in the transcoder, jdmaster.c is not used, so we must do it here.
|
||||||
|
*/
|
||||||
|
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||||
|
|
||||||
|
/* Compute dimensions of components */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
compptr->DCT_scaled_size = DCTSIZE;
|
||||||
|
/* Size in DCT blocks */
|
||||||
|
compptr->width_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||||
|
compptr->height_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||||
|
/* downsampled_width and downsampled_height will also be overridden by
|
||||||
|
* jdmaster.c if we are doing full decompression. The transcoder library
|
||||||
|
* doesn't use these values, but the calling application might.
|
||||||
|
*/
|
||||||
|
/* Size in samples */
|
||||||
|
compptr->downsampled_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) cinfo->max_h_samp_factor);
|
||||||
|
compptr->downsampled_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) cinfo->max_v_samp_factor);
|
||||||
|
/* Mark component needed, until color conversion says otherwise */
|
||||||
|
compptr->component_needed = TRUE;
|
||||||
|
/* Mark no quantization table yet saved for component */
|
||||||
|
compptr->quant_table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute number of fully interleaved MCU rows. */
|
||||||
|
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
|
||||||
|
/* Decide whether file contains multiple scans */
|
||||||
|
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
||||||
|
cinfo->inputctl->has_multiple_scans = TRUE;
|
||||||
|
else
|
||||||
|
cinfo->inputctl->has_multiple_scans = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
per_scan_setup (j_decompress_ptr cinfo)
|
||||||
|
/* Do computations that are needed before processing a JPEG scan */
|
||||||
|
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
|
||||||
|
{
|
||||||
|
int ci, mcublks, tmp;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
if (cinfo->comps_in_scan == 1) {
|
||||||
|
|
||||||
|
/* Noninterleaved (single-component) scan */
|
||||||
|
compptr = cinfo->cur_comp_info[0];
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||||
|
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||||
|
|
||||||
|
/* For noninterleaved scan, always one block per MCU */
|
||||||
|
compptr->MCU_width = 1;
|
||||||
|
compptr->MCU_height = 1;
|
||||||
|
compptr->MCU_blocks = 1;
|
||||||
|
compptr->MCU_sample_width = compptr->DCT_scaled_size;
|
||||||
|
compptr->last_col_width = 1;
|
||||||
|
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||||
|
* as the number of block rows present in the last iMCU row.
|
||||||
|
*/
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
cinfo->blocks_in_MCU = 1;
|
||||||
|
cinfo->MCU_membership[0] = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Interleaved (multi-component) scan */
|
||||||
|
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
|
||||||
|
MAX_COMPS_IN_SCAN);
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width,
|
||||||
|
(long) (cinfo->max_h_samp_factor*DCTSIZE));
|
||||||
|
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
|
||||||
|
cinfo->blocks_in_MCU = 0;
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Sampling factors give # of blocks of component in each MCU */
|
||||||
|
compptr->MCU_width = compptr->h_samp_factor;
|
||||||
|
compptr->MCU_height = compptr->v_samp_factor;
|
||||||
|
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||||
|
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
|
||||||
|
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||||
|
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_width;
|
||||||
|
compptr->last_col_width = tmp;
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_height;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
mcublks = compptr->MCU_blocks;
|
||||||
|
if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||||
|
while (mcublks-- > 0) {
|
||||||
|
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save away a copy of the Q-table referenced by each component present
|
||||||
|
* in the current scan, unless already saved during a prior scan.
|
||||||
|
*
|
||||||
|
* In a multiple-scan JPEG file, the encoder could assign different components
|
||||||
|
* the same Q-table slot number, but change table definitions between scans
|
||||||
|
* so that each component uses a different Q-table. (The IJG encoder is not
|
||||||
|
* currently capable of doing this, but other encoders might.) Since we want
|
||||||
|
* to be able to dequantize all the components at the end of the file, this
|
||||||
|
* means that we have to save away the table actually used for each component.
|
||||||
|
* We do this by copying the table at the start of the first scan containing
|
||||||
|
* the component.
|
||||||
|
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
|
||||||
|
* slot between scans of a component using that slot. If the encoder does so
|
||||||
|
* anyway, this decoder will simply use the Q-table values that were current
|
||||||
|
* at the start of the first scan for the component.
|
||||||
|
*
|
||||||
|
* The decompressor output side looks only at the saved quant tables,
|
||||||
|
* not at the current Q-table slots.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
latch_quant_tables (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int ci, qtblno;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JQUANT_TBL * qtbl;
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* No work if we already saved Q-table for this component */
|
||||||
|
if (compptr->quant_table != NULL)
|
||||||
|
continue;
|
||||||
|
/* Make sure specified quantization table is present */
|
||||||
|
qtblno = compptr->quant_tbl_no;
|
||||||
|
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||||
|
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||||
|
/* OK, save away the quantization table */
|
||||||
|
qtbl = (JQUANT_TBL *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(JQUANT_TBL));
|
||||||
|
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
|
||||||
|
compptr->quant_table = qtbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the input modules to read a scan of compressed data.
|
||||||
|
* The first call to this is done by jdmaster.c after initializing
|
||||||
|
* the entire decompressor (during jpeg_start_decompress).
|
||||||
|
* Subsequent calls come from consume_markers, below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_input_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
per_scan_setup(cinfo);
|
||||||
|
latch_quant_tables(cinfo);
|
||||||
|
(*cinfo->entropy->start_pass) (cinfo);
|
||||||
|
(*cinfo->coef->start_input_pass) (cinfo);
|
||||||
|
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up after inputting a compressed-data scan.
|
||||||
|
* This is called by the coefficient controller after it's read all
|
||||||
|
* the expected data of the scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
finish_input_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
cinfo->inputctl->consume_input = consume_markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read JPEG markers before, between, or after compressed-data scans.
|
||||||
|
* Change state as necessary when a new scan is reached.
|
||||||
|
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||||
|
*
|
||||||
|
* The consume_input method pointer points either here or to the
|
||||||
|
* coefficient controller's consume_data routine, depending on whether
|
||||||
|
* we are reading a compressed data segment or inter-segment markers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
consume_markers (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
|
||||||
|
return JPEG_REACHED_EOI;
|
||||||
|
|
||||||
|
val = (*cinfo->marker->read_markers) (cinfo);
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case JPEG_REACHED_SOS: /* Found SOS */
|
||||||
|
if (inputctl->inheaders) { /* 1st SOS */
|
||||||
|
initial_setup(cinfo);
|
||||||
|
inputctl->inheaders = FALSE;
|
||||||
|
/* Note: start_input_pass must be called by jdmaster.c
|
||||||
|
* before any more input can be consumed. jdapimin.c is
|
||||||
|
* responsible for enforcing this sequencing.
|
||||||
|
*/
|
||||||
|
} else { /* 2nd or later SOS marker */
|
||||||
|
if (! inputctl->pub.has_multiple_scans)
|
||||||
|
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
|
||||||
|
start_input_pass(cinfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JPEG_REACHED_EOI: /* Found EOI */
|
||||||
|
inputctl->pub.eoi_reached = TRUE;
|
||||||
|
if (inputctl->inheaders) { /* Tables-only datastream, apparently */
|
||||||
|
if (cinfo->marker->saw_SOF)
|
||||||
|
ERREXIT(cinfo, JERR_SOF_NO_SOS);
|
||||||
|
} else {
|
||||||
|
/* Prevent infinite loop in coef ctlr's decompress_data routine
|
||||||
|
* if user set output_scan_number larger than number of scans.
|
||||||
|
*/
|
||||||
|
if (cinfo->output_scan_number > cinfo->input_scan_number)
|
||||||
|
cinfo->output_scan_number = cinfo->input_scan_number;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JPEG_SUSPENDED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset state to begin a fresh datastream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
reset_input_controller (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||||
|
|
||||||
|
inputctl->pub.consume_input = consume_markers;
|
||||||
|
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||||
|
inputctl->pub.eoi_reached = FALSE;
|
||||||
|
inputctl->inheaders = TRUE;
|
||||||
|
/* Reset other modules */
|
||||||
|
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||||
|
(*cinfo->marker->reset_marker_reader) (cinfo);
|
||||||
|
/* Reset progression state -- would be cleaner if entropy decoder did this */
|
||||||
|
cinfo->coef_bits = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the input controller module.
|
||||||
|
* This is called only once, when the decompression object is created.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_input_controller (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl;
|
||||||
|
|
||||||
|
/* Create subobject in permanent pool */
|
||||||
|
inputctl = (my_inputctl_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
SIZEOF(my_input_controller));
|
||||||
|
cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
|
||||||
|
/* Initialize method pointers */
|
||||||
|
inputctl->pub.consume_input = consume_markers;
|
||||||
|
inputctl->pub.reset_input_controller = reset_input_controller;
|
||||||
|
inputctl->pub.start_input_pass = start_input_pass;
|
||||||
|
inputctl->pub.finish_input_pass = finish_input_pass;
|
||||||
|
/* Initialize state: can't use reset_input_controller since we don't
|
||||||
|
* want to try to reset other modules yet.
|
||||||
|
*/
|
||||||
|
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||||
|
inputctl->pub.eoi_reached = FALSE;
|
||||||
|
inputctl->inheaders = TRUE;
|
||||||
|
}
|
||||||
271
jdmain.c
271
jdmain.c
@@ -1,271 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 INCLUDES_ARE_ANSI
|
|
||||||
#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
|
|
||||||
|
|
||||||
#include "jversion.h" /* for version message */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PD version of getopt(3).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "egetopt.c"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This list defines the known output image formats
|
|
||||||
* (not all of which need be supported by a given version).
|
|
||||||
* You can change the default output format by defining DEFAULT_FMT;
|
|
||||||
* indeed, you had better do so if you undefine PPM_SUPPORTED.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FMT_GIF, /* GIF format */
|
|
||||||
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
|
|
||||||
FMT_RLE, /* RLE format */
|
|
||||||
FMT_TARGA, /* Targa format */
|
|
||||||
FMT_TIFF /* TIFF format */
|
|
||||||
} IMAGE_FORMATS;
|
|
||||||
|
|
||||||
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
|
|
||||||
#define DEFAULT_FMT FMT_PPM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static IMAGE_FORMATS requested_fmt;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This routine gets control after the input file header has been read.
|
|
||||||
* It must determine what output file format is to be written,
|
|
||||||
* and make any other decompression parameter changes that are desirable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
METHODDEF void
|
|
||||||
d_ui_method_selection (decompress_info_ptr cinfo)
|
|
||||||
{
|
|
||||||
/* if grayscale or CMYK input, force similar output; */
|
|
||||||
/* else leave the output colorspace as set by options. */
|
|
||||||
if (cinfo->jpeg_color_space == CS_GRAYSCALE)
|
|
||||||
cinfo->out_color_space = CS_GRAYSCALE;
|
|
||||||
else if (cinfo->jpeg_color_space == CS_CMYK)
|
|
||||||
cinfo->out_color_space = CS_CMYK;
|
|
||||||
|
|
||||||
/* select output file format */
|
|
||||||
/* Note: jselwxxx routine may make additional parameter changes,
|
|
||||||
* such as forcing color quantization if it's a colormapped format.
|
|
||||||
*/
|
|
||||||
switch (requested_fmt) {
|
|
||||||
#ifdef GIF_SUPPORTED
|
|
||||||
case FMT_GIF:
|
|
||||||
jselwgif(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef PPM_SUPPORTED
|
|
||||||
case FMT_PPM:
|
|
||||||
jselwppm(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef RLE_SUPPORTED
|
|
||||||
case FMT_RLE:
|
|
||||||
jselwrle(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef TARGA_SUPPORTED
|
|
||||||
case FMT_TARGA:
|
|
||||||
jselwtarga(cinfo);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
ERREXIT(cinfo->emethods, "Unsupported output file format");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
|
||||||
usage (char * progname)
|
|
||||||
/* complain about bad command line */
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s ", progname);
|
|
||||||
fprintf(stderr, "[-G] [-P] [-R] [-T] [-b] [-g] [-q colors] [-2] [-D] [-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 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;
|
|
||||||
|
|
||||||
/* Set up default JPEG parameters. */
|
|
||||||
j_d_defaults(&cinfo, TRUE);
|
|
||||||
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
|
||||||
|
|
||||||
/* Scan command line options, adjust parameters */
|
|
||||||
|
|
||||||
while ((c = egetopt(argc, argv, "GPRTbdgq:2D")) != EOF)
|
|
||||||
switch (c) {
|
|
||||||
case 'G': /* GIF output format. */
|
|
||||||
requested_fmt = FMT_GIF;
|
|
||||||
break;
|
|
||||||
case 'P': /* PPM output format. */
|
|
||||||
requested_fmt = FMT_PPM;
|
|
||||||
break;
|
|
||||||
case 'R': /* RLE output format. */
|
|
||||||
requested_fmt = FMT_RLE;
|
|
||||||
break;
|
|
||||||
case 'T': /* Targa output format. */
|
|
||||||
requested_fmt = FMT_TARGA;
|
|
||||||
break;
|
|
||||||
case 'b': /* Enable cross-block smoothing. */
|
|
||||||
cinfo.do_block_smoothing = TRUE;
|
|
||||||
break;
|
|
||||||
case 'd': /* Debugging. */
|
|
||||||
e_methods.trace_level++;
|
|
||||||
break;
|
|
||||||
case 'g': /* Force grayscale output. */
|
|
||||||
cinfo.out_color_space = CS_GRAYSCALE;
|
|
||||||
break;
|
|
||||||
case 'q': /* Do color quantization. */
|
|
||||||
{ int val;
|
|
||||||
if (optarg == NULL)
|
|
||||||
usage(argv[0]);
|
|
||||||
if (sscanf(optarg, "%d", &val) != 1)
|
|
||||||
usage(argv[0]);
|
|
||||||
cinfo.desired_number_of_colors = val;
|
|
||||||
}
|
|
||||||
cinfo.quantize_colors = TRUE;
|
|
||||||
break;
|
|
||||||
case '2': /* Use two-pass quantization. */
|
|
||||||
cinfo.two_pass_quantize = TRUE;
|
|
||||||
break;
|
|
||||||
case 'D': /* Suppress dithering in color quantization. */
|
|
||||||
cinfo.use_dithering = FALSE;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
usage(argv[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If -d appeared, print version identification */
|
|
||||||
if (e_methods.trace_level > 0)
|
|
||||||
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
|
|
||||||
JVERSION, JCOPYRIGHT);
|
|
||||||
|
|
||||||
/* Select the input and output files */
|
|
||||||
|
|
||||||
#ifdef TWO_FILE_COMMANDLINE
|
|
||||||
|
|
||||||
if (optind != argc-2) {
|
|
||||||
fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* not TWO_FILE_COMMANDLINE -- use Unix style */
|
|
||||||
|
|
||||||
cinfo.input_file = stdin; /* default input file */
|
|
||||||
cinfo.output_file = stdout; /* always the output file */
|
|
||||||
|
|
||||||
if (optind < argc-1) {
|
|
||||||
fprintf(stderr, "%s: only one input file\n", argv[0]);
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
if (optind < argc) {
|
|
||||||
if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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. */
|
|
||||||
j_d_free_defaults(&cinfo, TRUE);
|
|
||||||
#ifdef MEM_STATS
|
|
||||||
if (e_methods.trace_level > 0) /* Optional memory-usage statistics */
|
|
||||||
j_mem_stats();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* All done. */
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
512
jdmainct.c
Normal file
512
jdmainct.c
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
/*
|
||||||
|
* jdmainct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains the main buffer controller for decompression.
|
||||||
|
* The main buffer lies between the JPEG decompressor proper and the
|
||||||
|
* post-processor; it holds downsampled data in the JPEG colorspace.
|
||||||
|
*
|
||||||
|
* Note that this code is bypassed in raw-data mode, since the application
|
||||||
|
* supplies the equivalent of the main buffer in that case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the current system design, the main buffer need never be a full-image
|
||||||
|
* buffer; any full-height buffers will be found inside the coefficient or
|
||||||
|
* postprocessing controllers. Nonetheless, the main controller is not
|
||||||
|
* trivial. Its responsibility is to provide context rows for upsampling/
|
||||||
|
* rescaling, and doing this in an efficient fashion is a bit tricky.
|
||||||
|
*
|
||||||
|
* Postprocessor input data is counted in "row groups". A row group
|
||||||
|
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||||
|
* sample rows of each component. (We require DCT_scaled_size values to be
|
||||||
|
* chosen such that these numbers are integers. In practice DCT_scaled_size
|
||||||
|
* values will likely be powers of two, so we actually have the stronger
|
||||||
|
* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
|
||||||
|
* Upsampling will typically produce max_v_samp_factor pixel rows from each
|
||||||
|
* row group (times any additional scale factor that the upsampler is
|
||||||
|
* applying).
|
||||||
|
*
|
||||||
|
* The coefficient controller will deliver data to us one iMCU row at a time;
|
||||||
|
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
|
||||||
|
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
|
||||||
|
* to one row of MCUs when the image is fully interleaved.) Note that the
|
||||||
|
* number of sample rows varies across components, but the number of row
|
||||||
|
* groups does not. Some garbage sample rows may be included in the last iMCU
|
||||||
|
* row at the bottom of the image.
|
||||||
|
*
|
||||||
|
* Depending on the vertical scaling algorithm used, the upsampler may need
|
||||||
|
* access to the sample row(s) above and below its current input row group.
|
||||||
|
* The upsampler is required to set need_context_rows TRUE at global selection
|
||||||
|
* time if so. When need_context_rows is FALSE, this controller can simply
|
||||||
|
* obtain one iMCU row at a time from the coefficient controller and dole it
|
||||||
|
* out as row groups to the postprocessor.
|
||||||
|
*
|
||||||
|
* When need_context_rows is TRUE, this controller guarantees that the buffer
|
||||||
|
* passed to postprocessing contains at least one row group's worth of samples
|
||||||
|
* above and below the row group(s) being processed. Note that the context
|
||||||
|
* rows "above" the first passed row group appear at negative row offsets in
|
||||||
|
* the passed buffer. At the top and bottom of the image, the required
|
||||||
|
* context rows are manufactured by duplicating the first or last real sample
|
||||||
|
* row; this avoids having special cases in the upsampling inner loops.
|
||||||
|
*
|
||||||
|
* The amount of context is fixed at one row group just because that's a
|
||||||
|
* convenient number for this controller to work with. The existing
|
||||||
|
* upsamplers really only need one sample row of context. An upsampler
|
||||||
|
* supporting arbitrary output rescaling might wish for more than one row
|
||||||
|
* group of context when shrinking the image; tough, we don't handle that.
|
||||||
|
* (This is justified by the assumption that downsizing will be handled mostly
|
||||||
|
* by adjusting the DCT_scaled_size values, so that the actual scale factor at
|
||||||
|
* the upsample step needn't be much less than one.)
|
||||||
|
*
|
||||||
|
* To provide the desired context, we have to retain the last two row groups
|
||||||
|
* of one iMCU row while reading in the next iMCU row. (The last row group
|
||||||
|
* can't be processed until we have another row group for its below-context,
|
||||||
|
* and so we have to save the next-to-last group too for its above-context.)
|
||||||
|
* We could do this most simply by copying data around in our buffer, but
|
||||||
|
* that'd be very slow. We can avoid copying any data by creating a rather
|
||||||
|
* strange pointer structure. Here's how it works. We allocate a workspace
|
||||||
|
* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
|
||||||
|
* of row groups per iMCU row). We create two sets of redundant pointers to
|
||||||
|
* the workspace. Labeling the physical row groups 0 to M+1, the synthesized
|
||||||
|
* pointer lists look like this:
|
||||||
|
* M+1 M-1
|
||||||
|
* master pointer --> 0 master pointer --> 0
|
||||||
|
* 1 1
|
||||||
|
* ... ...
|
||||||
|
* M-3 M-3
|
||||||
|
* M-2 M
|
||||||
|
* M-1 M+1
|
||||||
|
* M M-2
|
||||||
|
* M+1 M-1
|
||||||
|
* 0 0
|
||||||
|
* We read alternate iMCU rows using each master pointer; thus the last two
|
||||||
|
* row groups of the previous iMCU row remain un-overwritten in the workspace.
|
||||||
|
* The pointer lists are set up so that the required context rows appear to
|
||||||
|
* be adjacent to the proper places when we pass the pointer lists to the
|
||||||
|
* upsampler.
|
||||||
|
*
|
||||||
|
* The above pictures describe the normal state of the pointer lists.
|
||||||
|
* At top and bottom of the image, we diddle the pointer lists to duplicate
|
||||||
|
* the first or last sample row as necessary (this is cheaper than copying
|
||||||
|
* sample rows around).
|
||||||
|
*
|
||||||
|
* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
|
||||||
|
* situation each iMCU row provides only one row group so the buffering logic
|
||||||
|
* must be different (eg, we must read two iMCU rows before we can emit the
|
||||||
|
* first row group). For now, we simply do not support providing context
|
||||||
|
* rows when min_DCT_scaled_size is 1. That combination seems unlikely to
|
||||||
|
* be worth providing --- if someone wants a 1/8th-size preview, they probably
|
||||||
|
* want it quick and dirty, so a context-free upsampler is sufficient.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_d_main_controller pub; /* public fields */
|
||||||
|
|
||||||
|
/* Pointer to allocated workspace (M or M+2 row groups). */
|
||||||
|
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
|
||||||
|
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
|
||||||
|
|
||||||
|
/* Remaining fields are only used in the context case. */
|
||||||
|
|
||||||
|
/* These are the master pointers to the funny-order pointer lists. */
|
||||||
|
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
|
||||||
|
|
||||||
|
int whichptr; /* indicates which pointer set is now in use */
|
||||||
|
int context_state; /* process_data state machine status */
|
||||||
|
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
|
||||||
|
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
|
||||||
|
} my_main_controller;
|
||||||
|
|
||||||
|
typedef my_main_controller * my_main_ptr;
|
||||||
|
|
||||||
|
/* context_state values: */
|
||||||
|
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
|
||||||
|
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
|
||||||
|
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(void) process_data_simple_main
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||||
|
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||||
|
METHODDEF(void) process_data_context_main
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||||
|
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
METHODDEF(void) process_data_crank_post
|
||||||
|
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||||
|
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
alloc_funny_pointers (j_decompress_ptr cinfo)
|
||||||
|
/* Allocate space for the funny pointer lists.
|
||||||
|
* This is done only once, not once per pass.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf;
|
||||||
|
|
||||||
|
/* Get top-level space for component array pointers.
|
||||||
|
* We alloc both arrays with one call to save a few cycles.
|
||||||
|
*/
|
||||||
|
main->xbuffer[0] = (JSAMPIMAGE)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
|
||||||
|
main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
/* Get space for pointer lists --- M+4 row groups in each list.
|
||||||
|
* We alloc both pointer lists with one call to save a few cycles.
|
||||||
|
*/
|
||||||
|
xbuf = (JSAMPARRAY)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
|
||||||
|
xbuf += rgroup; /* want one row group at negative offsets */
|
||||||
|
main->xbuffer[0][ci] = xbuf;
|
||||||
|
xbuf += rgroup * (M + 4);
|
||||||
|
main->xbuffer[1][ci] = xbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
make_funny_pointers (j_decompress_ptr cinfo)
|
||||||
|
/* Create the funny pointer lists discussed in the comments above.
|
||||||
|
* The actual workspace is already allocated (in main->buffer),
|
||||||
|
* and the space for the pointer lists is allocated too.
|
||||||
|
* This routine just fills in the curiously ordered lists.
|
||||||
|
* This will be repeated at the beginning of each pass.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY buf, xbuf0, xbuf1;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
xbuf0 = main->xbuffer[0][ci];
|
||||||
|
xbuf1 = main->xbuffer[1][ci];
|
||||||
|
/* First copy the workspace pointers as-is */
|
||||||
|
buf = main->buffer[ci];
|
||||||
|
for (i = 0; i < rgroup * (M + 2); i++) {
|
||||||
|
xbuf0[i] = xbuf1[i] = buf[i];
|
||||||
|
}
|
||||||
|
/* In the second list, put the last four row groups in swapped order */
|
||||||
|
for (i = 0; i < rgroup * 2; i++) {
|
||||||
|
xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
|
||||||
|
xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
|
||||||
|
}
|
||||||
|
/* The wraparound pointers at top and bottom will be filled later
|
||||||
|
* (see set_wraparound_pointers, below). Initially we want the "above"
|
||||||
|
* pointers to duplicate the first actual data line. This only needs
|
||||||
|
* to happen in xbuffer[0].
|
||||||
|
*/
|
||||||
|
for (i = 0; i < rgroup; i++) {
|
||||||
|
xbuf0[i - rgroup] = xbuf0[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
set_wraparound_pointers (j_decompress_ptr cinfo)
|
||||||
|
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
|
||||||
|
* This changes the pointer list state from top-of-image to the normal state.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf0, xbuf1;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
xbuf0 = main->xbuffer[0][ci];
|
||||||
|
xbuf1 = main->xbuffer[1][ci];
|
||||||
|
for (i = 0; i < rgroup; i++) {
|
||||||
|
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
|
||||||
|
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
|
||||||
|
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
|
||||||
|
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
set_bottom_pointers (j_decompress_ptr cinfo)
|
||||||
|
/* Change the pointer lists to duplicate the last sample row at the bottom
|
||||||
|
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
|
||||||
|
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup, iMCUheight, rows_left;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Count sample rows in one iMCU row and in one row group */
|
||||||
|
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
|
||||||
|
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
|
||||||
|
/* Count nondummy sample rows remaining for this component */
|
||||||
|
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
|
||||||
|
if (rows_left == 0) rows_left = iMCUheight;
|
||||||
|
/* Count nondummy row groups. Should get same answer for each component,
|
||||||
|
* so we need only do it once.
|
||||||
|
*/
|
||||||
|
if (ci == 0) {
|
||||||
|
main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
|
||||||
|
}
|
||||||
|
/* Duplicate the last real sample row rgroup*2 times; this pads out the
|
||||||
|
* last partial rowgroup and ensures at least one full rowgroup of context.
|
||||||
|
*/
|
||||||
|
xbuf = main->xbuffer[main->whichptr][ci];
|
||||||
|
for (i = 0; i < rgroup * 2; i++) {
|
||||||
|
xbuf[rows_left + i] = xbuf[rows_left-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
switch (pass_mode) {
|
||||||
|
case JBUF_PASS_THRU:
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
main->pub.process_data = process_data_context_main;
|
||||||
|
make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
|
||||||
|
main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
|
||||||
|
main->context_state = CTX_PREPARE_FOR_IMCU;
|
||||||
|
main->iMCU_row_ctr = 0;
|
||||||
|
} else {
|
||||||
|
/* Simple case with no context needed */
|
||||||
|
main->pub.process_data = process_data_simple_main;
|
||||||
|
}
|
||||||
|
main->buffer_full = FALSE; /* Mark buffer empty */
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
break;
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
case JBUF_CRANK_DEST:
|
||||||
|
/* For last pass of 2-pass quantization, just crank the postprocessor */
|
||||||
|
main->pub.process_data = process_data_crank_post;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* This handles the simple case where no context is required.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
process_data_simple_main (j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
JDIMENSION rowgroups_avail;
|
||||||
|
|
||||||
|
/* Read input data if we haven't filled the main buffer yet */
|
||||||
|
if (! main->buffer_full) {
|
||||||
|
if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
|
||||||
|
return; /* suspension forced, can do nothing more */
|
||||||
|
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
|
||||||
|
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
|
||||||
|
/* Note: at the bottom of the image, we may pass extra garbage row groups
|
||||||
|
* to the postprocessor. The postprocessor has to check for bottom
|
||||||
|
* of image anyway (at row resolution), so no point in us doing it too.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Feed the postprocessor */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, main->buffer,
|
||||||
|
&main->rowgroup_ctr, rowgroups_avail,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
|
||||||
|
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
|
||||||
|
if (main->rowgroup_ctr >= rowgroups_avail) {
|
||||||
|
main->buffer_full = FALSE;
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* This handles the case where context rows must be provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
process_data_context_main (j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
{
|
||||||
|
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
/* Read input data if we haven't filled the main buffer yet */
|
||||||
|
if (! main->buffer_full) {
|
||||||
|
if (! (*cinfo->coef->decompress_data) (cinfo,
|
||||||
|
main->xbuffer[main->whichptr]))
|
||||||
|
return; /* suspension forced, can do nothing more */
|
||||||
|
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||||
|
main->iMCU_row_ctr++; /* count rows received */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Postprocessor typically will not swallow all the input data it is handed
|
||||||
|
* in one call (due to filling the output buffer first). Must be prepared
|
||||||
|
* to exit and restart. This switch lets us keep track of how far we got.
|
||||||
|
* Note that each case falls through to the next on successful completion.
|
||||||
|
*/
|
||||||
|
switch (main->context_state) {
|
||||||
|
case CTX_POSTPONED_ROW:
|
||||||
|
/* Call postprocessor using previously set pointers for postponed row */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
|
||||||
|
&main->rowgroup_ctr, main->rowgroups_avail,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
if (main->rowgroup_ctr < main->rowgroups_avail)
|
||||||
|
return; /* Need to suspend */
|
||||||
|
main->context_state = CTX_PREPARE_FOR_IMCU;
|
||||||
|
if (*out_row_ctr >= out_rows_avail)
|
||||||
|
return; /* Postprocessor exactly filled output buf */
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case CTX_PREPARE_FOR_IMCU:
|
||||||
|
/* Prepare to process first M-1 row groups of this iMCU row */
|
||||||
|
main->rowgroup_ctr = 0;
|
||||||
|
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
|
||||||
|
/* Check for bottom of image: if so, tweak pointers to "duplicate"
|
||||||
|
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
|
||||||
|
*/
|
||||||
|
if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
|
||||||
|
set_bottom_pointers(cinfo);
|
||||||
|
main->context_state = CTX_PROCESS_IMCU;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case CTX_PROCESS_IMCU:
|
||||||
|
/* Call postprocessor using previously set pointers */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
|
||||||
|
&main->rowgroup_ctr, main->rowgroups_avail,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
if (main->rowgroup_ctr < main->rowgroups_avail)
|
||||||
|
return; /* Need to suspend */
|
||||||
|
/* After the first iMCU, change wraparound pointers to normal state */
|
||||||
|
if (main->iMCU_row_ctr == 1)
|
||||||
|
set_wraparound_pointers(cinfo);
|
||||||
|
/* Prepare to load new iMCU row using other xbuffer list */
|
||||||
|
main->whichptr ^= 1; /* 0=>1 or 1=>0 */
|
||||||
|
main->buffer_full = FALSE;
|
||||||
|
/* Still need to process last row group of this iMCU row, */
|
||||||
|
/* which is saved at index M+1 of the other xbuffer */
|
||||||
|
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
|
||||||
|
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
|
||||||
|
main->context_state = CTX_POSTPONED_ROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process some data.
|
||||||
|
* Final pass of two-pass quantization: just call the postprocessor.
|
||||||
|
* Source data will be the postprocessor controller's internal buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
process_data_crank_post (j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
{
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
|
||||||
|
(JDIMENSION *) NULL, (JDIMENSION) 0,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* QUANT_2PASS_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize main buffer controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_main_ptr main;
|
||||||
|
int ci, rgroup, ngroups;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
main = (my_main_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_main_controller));
|
||||||
|
cinfo->main = (struct jpeg_d_main_controller *) main;
|
||||||
|
main->pub.start_pass = start_pass_main;
|
||||||
|
|
||||||
|
if (need_full_buffer) /* shouldn't happen */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
|
||||||
|
/* Allocate the workspace.
|
||||||
|
* ngroups is the number of row groups we need.
|
||||||
|
*/
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
|
||||||
|
ngroups = cinfo->min_DCT_scaled_size + 2;
|
||||||
|
} else {
|
||||||
|
ngroups = cinfo->min_DCT_scaled_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
compptr->width_in_blocks * compptr->DCT_scaled_size,
|
||||||
|
(JDIMENSION) (rgroup * ngroups));
|
||||||
|
}
|
||||||
|
}
|
||||||
1360
jdmarker.c
Normal file
1360
jdmarker.c
Normal file
File diff suppressed because it is too large
Load Diff
675
jdmaster.c
675
jdmaster.c
@@ -1,180 +1,557 @@
|
|||||||
/*
|
/*
|
||||||
* jdmaster.c
|
* jdmaster.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* This file is part of the Independent JPEG Group's software.
|
* This file is part of the Independent JPEG Group's software.
|
||||||
* For conditions of distribution and use, see the accompanying README file.
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
*
|
*
|
||||||
* This file contains the main control for the JPEG decompressor.
|
* This file contains master control logic for the JPEG decompressor.
|
||||||
* The system-dependent (user interface) code should call jpeg_decompress()
|
* These routines are concerned with selecting the modules to be executed
|
||||||
* after doing appropriate setup of the decompress_info_struct parameter.
|
* and with determining the number of passes and the work to be done in each
|
||||||
|
* pass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
METHODDEF void
|
/* Private state */
|
||||||
d_per_scan_method_selection (decompress_info_ptr cinfo)
|
|
||||||
/* Central point for per-scan method selection */
|
typedef struct {
|
||||||
|
struct jpeg_decomp_master pub; /* public fields */
|
||||||
|
|
||||||
|
int pass_number; /* # of passes completed */
|
||||||
|
|
||||||
|
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
|
||||||
|
|
||||||
|
/* Saved references to initialized quantizer modules,
|
||||||
|
* in case we need to switch modes.
|
||||||
|
*/
|
||||||
|
struct jpeg_color_quantizer * quantizer_1pass;
|
||||||
|
struct jpeg_color_quantizer * quantizer_2pass;
|
||||||
|
} my_decomp_master;
|
||||||
|
|
||||||
|
typedef my_decomp_master * my_master_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine whether merged upsample/color conversion should be used.
|
||||||
|
* CRUCIAL: this must match the actual capabilities of jdmerge.c!
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
use_merged_upsample (j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
/* MCU disassembly */
|
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||||
jseldmcu(cinfo);
|
/* Merging is the equivalent of plain box-filter upsampling */
|
||||||
/* Un-subsampling of pixels */
|
if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
|
||||||
jselunsubsample(cinfo);
|
return FALSE;
|
||||||
|
/* jdmerge.c only supports YCC=>RGB color conversion */
|
||||||
|
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
|
||||||
|
cinfo->out_color_space != JCS_RGB ||
|
||||||
|
cinfo->out_color_components != RGB_PIXELSIZE)
|
||||||
|
return FALSE;
|
||||||
|
/* and it only handles 2h1v or 2h2v sampling ratios */
|
||||||
|
if (cinfo->comp_info[0].h_samp_factor != 2 ||
|
||||||
|
cinfo->comp_info[1].h_samp_factor != 1 ||
|
||||||
|
cinfo->comp_info[2].h_samp_factor != 1 ||
|
||||||
|
cinfo->comp_info[0].v_samp_factor > 2 ||
|
||||||
|
cinfo->comp_info[1].v_samp_factor != 1 ||
|
||||||
|
cinfo->comp_info[2].v_samp_factor != 1)
|
||||||
|
return FALSE;
|
||||||
|
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
|
||||||
|
if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||||
|
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||||
|
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
|
||||||
|
return FALSE;
|
||||||
|
/* ??? also need to test for upsample-time rescaling, when & if supported */
|
||||||
|
return TRUE; /* by golly, it'll work... */
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LOCAL void
|
/*
|
||||||
d_initial_method_selection (decompress_info_ptr cinfo)
|
* Compute output image dimensions and related values.
|
||||||
/* Central point for initial method selection (after reading file header) */
|
* NOTE: this is exported for possible use by application.
|
||||||
|
* Hence it mustn't do anything that can't be done twice.
|
||||||
|
* Also note that it may be called before the master module is initialized!
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
|
||||||
|
/* Do computations that are needed before master selection phase */
|
||||||
{
|
{
|
||||||
/* JPEG file scanning method selection is already done. */
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
/* So is output file format selection (both are done by user interface). */
|
int ci;
|
||||||
|
|
||||||
/* 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;
|
jpeg_component_info *compptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Compute maximum sampling factors; check factor validity */
|
/* Prevent application from calling me at wrong times */
|
||||||
cinfo->max_h_samp_factor = 1;
|
if (cinfo->global_state != DSTATE_READY)
|
||||||
cinfo->max_v_samp_factor = 1;
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
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);
|
|
||||||
|
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
|
||||||
|
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||||
|
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
|
||||||
|
/* Provide 1/8 scaling */
|
||||||
|
cinfo->output_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width, 8L);
|
||||||
|
cinfo->output_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height, 8L);
|
||||||
|
cinfo->min_DCT_scaled_size = 1;
|
||||||
|
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
|
||||||
|
/* Provide 1/4 scaling */
|
||||||
|
cinfo->output_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width, 4L);
|
||||||
|
cinfo->output_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height, 4L);
|
||||||
|
cinfo->min_DCT_scaled_size = 2;
|
||||||
|
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
|
||||||
|
/* Provide 1/2 scaling */
|
||||||
|
cinfo->output_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width, 2L);
|
||||||
|
cinfo->output_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height, 2L);
|
||||||
|
cinfo->min_DCT_scaled_size = 4;
|
||||||
|
} else {
|
||||||
|
/* Provide 1/1 scaling */
|
||||||
|
cinfo->output_width = cinfo->image_width;
|
||||||
|
cinfo->output_height = cinfo->image_height;
|
||||||
|
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||||
|
}
|
||||||
|
/* In selecting the actual DCT scaling for each component, we try to
|
||||||
|
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||||
|
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||||
|
* Note this code assumes that the supported DCT scalings are powers of 2.
|
||||||
|
*/
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
int ssize = cinfo->min_DCT_scaled_size;
|
||||||
|
while (ssize < DCTSIZE &&
|
||||||
|
(compptr->h_samp_factor * ssize * 2 <=
|
||||||
|
cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
|
||||||
|
(compptr->v_samp_factor * ssize * 2 <=
|
||||||
|
cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
|
||||||
|
ssize = ssize * 2;
|
||||||
|
}
|
||||||
|
compptr->DCT_scaled_size = ssize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute logical subsampled dimensions of components */
|
/* Recompute downsampled dimensions of components;
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
* application needs to know these if using raw downsampled data.
|
||||||
compptr = &cinfo->comp_info[ci];
|
*/
|
||||||
compptr->true_comp_width = (cinfo->image_width * compptr->h_samp_factor
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
+ cinfo->max_h_samp_factor - 1)
|
ci++, compptr++) {
|
||||||
/ cinfo->max_h_samp_factor;
|
/* Size in samples, after IDCT scaling */
|
||||||
compptr->true_comp_height = (cinfo->image_height * compptr->v_samp_factor
|
compptr->downsampled_width = (JDIMENSION)
|
||||||
+ cinfo->max_v_samp_factor - 1)
|
jdiv_round_up((long) cinfo->image_width *
|
||||||
/ cinfo->max_v_samp_factor;
|
(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
|
||||||
|
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||||
|
compptr->downsampled_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height *
|
||||||
|
(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
|
||||||
|
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !IDCT_SCALING_SUPPORTED */
|
||||||
|
|
||||||
|
/* Hardwire it to "no scaling" */
|
||||||
|
cinfo->output_width = cinfo->image_width;
|
||||||
|
cinfo->output_height = cinfo->image_height;
|
||||||
|
/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
|
||||||
|
* and has computed unscaled downsampled_width and downsampled_height.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* IDCT_SCALING_SUPPORTED */
|
||||||
|
|
||||||
|
/* Report number of components in selected colorspace. */
|
||||||
|
/* Probably this should be in the color conversion module... */
|
||||||
|
switch (cinfo->out_color_space) {
|
||||||
|
case JCS_GRAYSCALE:
|
||||||
|
cinfo->out_color_components = 1;
|
||||||
|
break;
|
||||||
|
case JCS_RGB:
|
||||||
|
#if RGB_PIXELSIZE != 3
|
||||||
|
cinfo->out_color_components = RGB_PIXELSIZE;
|
||||||
|
break;
|
||||||
|
#endif /* else share code with YCbCr */
|
||||||
|
case JCS_YCbCr:
|
||||||
|
cinfo->out_color_components = 3;
|
||||||
|
break;
|
||||||
|
case JCS_CMYK:
|
||||||
|
case JCS_YCCK:
|
||||||
|
cinfo->out_color_components = 4;
|
||||||
|
break;
|
||||||
|
default: /* else must be same colorspace as in file */
|
||||||
|
cinfo->out_color_components = cinfo->num_components;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cinfo->output_components = (cinfo->quantize_colors ? 1 :
|
||||||
|
cinfo->out_color_components);
|
||||||
|
|
||||||
|
/* See if upsampler will want to emit more than one row at a time */
|
||||||
|
if (use_merged_upsample(cinfo))
|
||||||
|
cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
|
||||||
|
else
|
||||||
|
cinfo->rec_outbuf_height = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Several decompression processes need to range-limit values to the range
|
||||||
|
* 0..MAXJSAMPLE; the input value may fall somewhat outside this range
|
||||||
|
* due to noise introduced by quantization, roundoff error, etc. These
|
||||||
|
* processes are inner loops and need to be as fast as possible. On most
|
||||||
|
* machines, particularly CPUs with pipelines or instruction prefetch,
|
||||||
|
* a (subscript-check-less) C table lookup
|
||||||
|
* x = sample_range_limit[x];
|
||||||
|
* is faster than explicit tests
|
||||||
|
* if (x < 0) x = 0;
|
||||||
|
* else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
|
||||||
|
* These processes all use a common table prepared by the routine below.
|
||||||
|
*
|
||||||
|
* For most steps we can mathematically guarantee that the initial value
|
||||||
|
* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
|
||||||
|
* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
|
||||||
|
* limiting step (just after the IDCT), a wildly out-of-range value is
|
||||||
|
* possible if the input data is corrupt. To avoid any chance of indexing
|
||||||
|
* off the end of memory and getting a bad-pointer trap, we perform the
|
||||||
|
* post-IDCT limiting thus:
|
||||||
|
* x = range_limit[x & MASK];
|
||||||
|
* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
|
||||||
|
* samples. Under normal circumstances this is more than enough range and
|
||||||
|
* a correct output will be generated; with bogus input data the mask will
|
||||||
|
* cause wraparound, and we will safely generate a bogus-but-in-range output.
|
||||||
|
* For the post-IDCT step, we want to convert the data from signed to unsigned
|
||||||
|
* representation by adding CENTERJSAMPLE at the same time that we limit it.
|
||||||
|
* So the post-IDCT limiting table ends up looking like this:
|
||||||
|
* CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
|
||||||
|
* MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
|
||||||
|
* 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
|
||||||
|
* 0,1,...,CENTERJSAMPLE-1
|
||||||
|
* Negative inputs select values from the upper half of the table after
|
||||||
|
* masking.
|
||||||
|
*
|
||||||
|
* We can save some space by overlapping the start of the post-IDCT table
|
||||||
|
* with the simpler range limiting table. The post-IDCT table begins at
|
||||||
|
* sample_range_limit + CENTERJSAMPLE.
|
||||||
|
*
|
||||||
|
* Note that the table is allocated in near data space on PCs; it's small
|
||||||
|
* enough and used often enough to justify this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
prepare_range_limit_table (j_decompress_ptr cinfo)
|
||||||
|
/* Allocate and fill in the sample_range_limit table */
|
||||||
|
{
|
||||||
|
JSAMPLE * table;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
table = (JSAMPLE *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
|
||||||
|
table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
|
||||||
|
cinfo->sample_range_limit = table;
|
||||||
|
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
|
||||||
|
MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
|
||||||
|
/* Main part of "simple" table: limit[x] = x */
|
||||||
|
for (i = 0; i <= MAXJSAMPLE; i++)
|
||||||
|
table[i] = (JSAMPLE) i;
|
||||||
|
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
|
||||||
|
/* End of simple table, rest of first half of post-IDCT table */
|
||||||
|
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
|
||||||
|
table[i] = MAXJSAMPLE;
|
||||||
|
/* Second half of post-IDCT table */
|
||||||
|
MEMZERO(table + (2 * (MAXJSAMPLE+1)),
|
||||||
|
(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
|
||||||
|
MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
|
||||||
|
cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Master selection of decompression modules.
|
||||||
|
* This is done once at jpeg_start_decompress time. We determine
|
||||||
|
* which modules will be used and give them appropriate initialization calls.
|
||||||
|
* We also initialize the decompressor input side to begin consuming data.
|
||||||
|
*
|
||||||
|
* Since jpeg_read_header has finished, we know what is in the SOF
|
||||||
|
* and (first) SOS markers. We also have all the application parameter
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
master_selection (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
|
boolean use_c_buffer;
|
||||||
|
long samplesperrow;
|
||||||
|
JDIMENSION jd_samplesperrow;
|
||||||
|
|
||||||
|
/* Initialize dimensions and other stuff */
|
||||||
|
jpeg_calc_output_dimensions(cinfo);
|
||||||
|
prepare_range_limit_table(cinfo);
|
||||||
|
|
||||||
|
/* Width of an output scanline must be representable as JDIMENSION. */
|
||||||
|
samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
|
||||||
|
jd_samplesperrow = (JDIMENSION) samplesperrow;
|
||||||
|
if ((long) jd_samplesperrow != samplesperrow)
|
||||||
|
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
||||||
|
|
||||||
|
/* Initialize my private state */
|
||||||
|
master->pass_number = 0;
|
||||||
|
master->using_merged_upsample = use_merged_upsample(cinfo);
|
||||||
|
|
||||||
|
/* Color quantizer selection */
|
||||||
|
master->quantizer_1pass = NULL;
|
||||||
|
master->quantizer_2pass = NULL;
|
||||||
|
/* No mode changes if not using buffered-image mode. */
|
||||||
|
if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
|
||||||
|
cinfo->enable_1pass_quant = FALSE;
|
||||||
|
cinfo->enable_external_quant = FALSE;
|
||||||
|
cinfo->enable_2pass_quant = FALSE;
|
||||||
|
}
|
||||||
|
if (cinfo->quantize_colors) {
|
||||||
|
if (cinfo->raw_data_out)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
/* 2-pass quantizer only works in 3-component color space. */
|
||||||
|
if (cinfo->out_color_components != 3) {
|
||||||
|
cinfo->enable_1pass_quant = TRUE;
|
||||||
|
cinfo->enable_external_quant = FALSE;
|
||||||
|
cinfo->enable_2pass_quant = FALSE;
|
||||||
|
cinfo->colormap = NULL;
|
||||||
|
} else if (cinfo->colormap != NULL) {
|
||||||
|
cinfo->enable_external_quant = TRUE;
|
||||||
|
} else if (cinfo->two_pass_quantize) {
|
||||||
|
cinfo->enable_2pass_quant = TRUE;
|
||||||
|
} else {
|
||||||
|
cinfo->enable_1pass_quant = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cinfo->enable_1pass_quant) {
|
||||||
|
#ifdef QUANT_1PASS_SUPPORTED
|
||||||
|
jinit_1pass_quantizer(cinfo);
|
||||||
|
master->quantizer_1pass = cinfo->cquantize;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use the 2-pass code to map to external colormaps. */
|
||||||
|
if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
jinit_2pass_quantizer(cinfo);
|
||||||
|
master->quantizer_2pass = cinfo->cquantize;
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* If both quantizers are initialized, the 2-pass one is left active;
|
||||||
|
* this is necessary for starting with quantization to an external map.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Post-processing: in particular, color conversion first */
|
||||||
|
if (! cinfo->raw_data_out) {
|
||||||
|
if (master->using_merged_upsample) {
|
||||||
|
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||||
|
jinit_merged_upsampler(cinfo); /* does color conversion too */
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
jinit_color_deconverter(cinfo);
|
||||||
|
jinit_upsampler(cinfo);
|
||||||
|
}
|
||||||
|
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||||
|
}
|
||||||
|
/* Inverse DCT */
|
||||||
|
jinit_inverse_dct(cinfo);
|
||||||
|
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
|
} else {
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||||
|
jinit_phuff_decoder(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
jinit_huff_decoder(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize principal buffer controllers. */
|
||||||
|
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
||||||
|
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||||
|
|
||||||
|
if (! cinfo->raw_data_out)
|
||||||
|
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
|
|
||||||
|
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||||
|
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Initialize input side of decompressor to consume first scan. */
|
||||||
|
(*cinfo->inputctl->start_input_pass) (cinfo);
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
|
/* If jpeg_start_decompress will read the whole file, initialize
|
||||||
|
* progress monitoring appropriately. The input step is counted
|
||||||
|
* as one pass.
|
||||||
|
*/
|
||||||
|
if (cinfo->progress != NULL && ! cinfo->buffered_image &&
|
||||||
|
cinfo->inputctl->has_multiple_scans) {
|
||||||
|
int nscans;
|
||||||
|
/* Estimate number of scans to set pass_limit. */
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
|
||||||
|
nscans = 2 + 3 * cinfo->num_components;
|
||||||
|
} else {
|
||||||
|
/* For a nonprogressive multiscan file, estimate 1 scan per component. */
|
||||||
|
nscans = cinfo->num_components;
|
||||||
|
}
|
||||||
|
cinfo->progress->pass_counter = 0L;
|
||||||
|
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
|
||||||
|
cinfo->progress->completed_passes = 0;
|
||||||
|
cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
|
||||||
|
/* Count the input pass as done */
|
||||||
|
master->pass_number++;
|
||||||
|
}
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-pass setup.
|
||||||
|
* This is called at the beginning of each output pass. We determine which
|
||||||
|
* modules will be active during this pass and give them appropriate
|
||||||
|
* start_pass calls. We also set is_dummy_pass to indicate whether this
|
||||||
|
* is a "real" output pass or a dummy pass for color quantization.
|
||||||
|
* (In the latter case, jdapistd.c will crank the pass to completion.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
prepare_for_output_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
|
|
||||||
|
if (master->pub.is_dummy_pass) {
|
||||||
|
#ifdef QUANT_2PASS_SUPPORTED
|
||||||
|
/* Final pass of 2-pass quantization */
|
||||||
|
master->pub.is_dummy_pass = FALSE;
|
||||||
|
(*cinfo->cquantize->start_pass) (cinfo, FALSE);
|
||||||
|
(*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||||
|
(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif /* QUANT_2PASS_SUPPORTED */
|
||||||
|
} else {
|
||||||
|
if (cinfo->quantize_colors && cinfo->colormap == NULL) {
|
||||||
|
/* Select new quantization method */
|
||||||
|
if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
|
||||||
|
cinfo->cquantize = master->quantizer_2pass;
|
||||||
|
master->pub.is_dummy_pass = TRUE;
|
||||||
|
} else if (cinfo->enable_1pass_quant) {
|
||||||
|
cinfo->cquantize = master->quantizer_1pass;
|
||||||
|
} else {
|
||||||
|
ERREXIT(cinfo, JERR_MODE_CHANGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*cinfo->idct->start_pass) (cinfo);
|
||||||
|
(*cinfo->coef->start_output_pass) (cinfo);
|
||||||
|
if (! cinfo->raw_data_out) {
|
||||||
|
if (! master->using_merged_upsample)
|
||||||
|
(*cinfo->cconvert->start_pass) (cinfo);
|
||||||
|
(*cinfo->upsample->start_pass) (cinfo);
|
||||||
|
if (cinfo->quantize_colors)
|
||||||
|
(*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
|
||||||
|
(*cinfo->post->start_pass) (cinfo,
|
||||||
|
(master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
|
||||||
|
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up progress monitor's pass info if present */
|
||||||
|
if (cinfo->progress != NULL) {
|
||||||
|
cinfo->progress->completed_passes = master->pass_number;
|
||||||
|
cinfo->progress->total_passes = master->pass_number +
|
||||||
|
(master->pub.is_dummy_pass ? 2 : 1);
|
||||||
|
/* In buffered-image mode, we assume one more output pass if EOI not
|
||||||
|
* yet reached, but no more passes if EOI has been reached.
|
||||||
|
*/
|
||||||
|
if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
|
||||||
|
cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the main entry point to the JPEG decompressor.
|
* Finish up at end of an output pass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
GLOBAL void
|
finish_output_pass (j_decompress_ptr cinfo)
|
||||||
jpeg_decompress (decompress_info_ptr cinfo)
|
|
||||||
{
|
{
|
||||||
short i;
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
|
|
||||||
/* Initialize pointers as needed to mark stuff unallocated. */
|
if (cinfo->quantize_colors)
|
||||||
cinfo->comp_info = NULL;
|
(*cinfo->cquantize->finish_pass) (cinfo);
|
||||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
master->pass_number++;
|
||||||
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;
|
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||||
}
|
|
||||||
|
/*
|
||||||
/* Read the JPEG file header markers; everything up through the first SOS
|
* Switch to a new external colormap between output passes.
|
||||||
* 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
|
GLOBAL(void)
|
||||||
* set at the same time, but could be set up by read_file_header itself.
|
jpeg_new_colormap (j_decompress_ptr cinfo)
|
||||||
*/
|
{
|
||||||
(*cinfo->methods->read_file_header) (cinfo);
|
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||||
if (! ((*cinfo->methods->read_scan_header) (cinfo)))
|
|
||||||
ERREXIT(cinfo->emethods, "Empty JPEG file");
|
/* Prevent application from calling me at wrong times */
|
||||||
|
if (cinfo->global_state != DSTATE_BUFIMAGE)
|
||||||
/* Give UI a chance to adjust decompression parameters and select */
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
/* output file format based on info from file header. */
|
|
||||||
(*cinfo->methods->d_ui_method_selection) (cinfo);
|
if (cinfo->quantize_colors && cinfo->enable_external_quant &&
|
||||||
|
cinfo->colormap != NULL) {
|
||||||
/* Now select methods for decompression steps. */
|
/* Select 2-pass quantizer for external colormap use */
|
||||||
initial_setup(cinfo);
|
cinfo->cquantize = master->quantizer_2pass;
|
||||||
d_initial_method_selection(cinfo);
|
/* Notify quantizer of colormap change */
|
||||||
|
(*cinfo->cquantize->new_color_map) (cinfo);
|
||||||
/* Initialize the output file & other modules as needed */
|
master->pub.is_dummy_pass = FALSE; /* just in case */
|
||||||
/* (color_quant and entropy_decoder are inited by pipeline controller) */
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_MODE_CHANGE);
|
||||||
(*cinfo->methods->output_init) (cinfo);
|
}
|
||||||
(*cinfo->methods->colorout_init) (cinfo);
|
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
/* And let the pipeline controller do the rest. */
|
|
||||||
(*cinfo->methods->d_pipeline_controller) (cinfo);
|
|
||||||
|
/*
|
||||||
/* Finish output file, release working storage, etc */
|
* Initialize master decompression control and select active modules.
|
||||||
(*cinfo->methods->colorout_term) (cinfo);
|
* This is performed at the start of jpeg_start_decompress.
|
||||||
(*cinfo->methods->output_term) (cinfo);
|
*/
|
||||||
(*cinfo->methods->read_file_trailer) (cinfo);
|
|
||||||
|
GLOBAL(void)
|
||||||
/* Release allocated storage for tables */
|
jinit_master_decompress (j_decompress_ptr cinfo)
|
||||||
#define FREE(ptr) if ((ptr) != NULL) \
|
{
|
||||||
(*cinfo->emethods->free_small) ((void *) ptr)
|
my_master_ptr master;
|
||||||
|
|
||||||
FREE(cinfo->comp_info);
|
master = (my_master_ptr)
|
||||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
FREE(cinfo->quant_tbl_ptrs[i]);
|
SIZEOF(my_decomp_master));
|
||||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
cinfo->master = (struct jpeg_decomp_master *) master;
|
||||||
FREE(cinfo->dc_huff_tbl_ptrs[i]);
|
master->pub.prepare_for_output_pass = prepare_for_output_pass;
|
||||||
FREE(cinfo->ac_huff_tbl_ptrs[i]);
|
master->pub.finish_output_pass = finish_output_pass;
|
||||||
}
|
|
||||||
|
master->pub.is_dummy_pass = FALSE;
|
||||||
/* My, that was easy, wasn't it? */
|
|
||||||
|
master_selection(cinfo);
|
||||||
}
|
}
|
||||||
|
|||||||
146
jdmcu.c
146
jdmcu.c
@@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user