CyanWorlds
13 years ago
209 changed files with 105056 additions and 112 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,134 @@ |
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
#
|
||||||
|
# Automake Makefile for the JPEG library
|
||||||
|
#
|
||||||
|
# This file is written by Bob Friesenhahn, Guido Vollbeding
|
||||||
|
#
|
||||||
|
|
||||||
|
# Sources to build library
|
||||||
|
LIBSOURCES = jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c \
|
||||||
|
jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \
|
||||||
|
jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c \
|
||||||
|
jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \
|
||||||
|
jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \
|
||||||
|
jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c \
|
||||||
|
jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c \
|
||||||
|
jquant2.c jutils.c jmemmgr.c @MEMORYMGR@.c
|
||||||
|
|
||||||
|
# System dependent sources
|
||||||
|
SYSDEPSOURCES = jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c
|
||||||
|
|
||||||
|
# Headers which are installed to support the library
|
||||||
|
INSTINCLUDES = jerror.h jmorecfg.h jpeglib.h
|
||||||
|
|
||||||
|
# Headers which are not installed
|
||||||
|
OTHERINCLUDES = cderror.h cdjpeg.h jdct.h jinclude.h jmemsys.h jpegint.h \
|
||||||
|
jversion.h transupp.h
|
||||||
|
|
||||||
|
# Manual pages (Automake uses 'MANS' for itself)
|
||||||
|
DISTMANS= cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 wrjpgcom.1
|
||||||
|
|
||||||
|
# Other documentation files
|
||||||
|
DOCS= README install.txt usage.txt wizard.txt example.c libjpeg.txt \
|
||||||
|
structure.txt coderules.txt filelist.txt change.log
|
||||||
|
|
||||||
|
# Makefiles for various systems
|
||||||
|
MKFILES= configure Makefile.in makefile.ansi makefile.unix makefile.bcc \
|
||||||
|
makefile.mc6 makefile.dj makefile.wat makefile.vc makejdsw.vc6 \
|
||||||
|
makeadsw.vc6 makejdep.vc6 makejdsp.vc6 makejmak.vc6 makecdep.vc6 \
|
||||||
|
makecdsp.vc6 makecmak.vc6 makeddep.vc6 makeddsp.vc6 makedmak.vc6 \
|
||||||
|
maketdep.vc6 maketdsp.vc6 maketmak.vc6 makerdep.vc6 makerdsp.vc6 \
|
||||||
|
makermak.vc6 makewdep.vc6 makewdsp.vc6 makewmak.vc6 makejsln.v10 \
|
||||||
|
makeasln.v10 makejvcx.v10 makejfil.v10 makecvcx.v10 makecfil.v10 \
|
||||||
|
makedvcx.v10 makedfil.v10 maketvcx.v10 maketfil.v10 makervcx.v10 \
|
||||||
|
makerfil.v10 makewvcx.v10 makewfil.v10 makeproj.mac makcjpeg.st \
|
||||||
|
makdjpeg.st makljpeg.st maktjpeg.st makefile.manx makefile.sas \
|
||||||
|
makefile.mms makefile.vms makvms.opt
|
||||||
|
|
||||||
|
# Configuration files
|
||||||
|
CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \
|
||||||
|
jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \
|
||||||
|
jconfig.vms
|
||||||
|
|
||||||
|
# Support scripts for configure
|
||||||
|
CONFIGUREFILES= config.guess config.sub install-sh ltmain.sh depcomp missing
|
||||||
|
|
||||||
|
# Miscellaneous support files
|
||||||
|
OTHERFILES= jconfig.txt ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm \
|
||||||
|
libjpeg.map
|
||||||
|
|
||||||
|
# Test support files
|
||||||
|
TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \
|
||||||
|
testimgp.jpg
|
||||||
|
|
||||||
|
# libtool libraries to build
|
||||||
|
lib_LTLIBRARIES = libjpeg.la
|
||||||
|
|
||||||
|
# Library sources for libjpeg.la
|
||||||
|
libjpeg_la_SOURCES = $(LIBSOURCES)
|
||||||
|
|
||||||
|
# LDFLAGS for libjpeg.la
|
||||||
|
libjpeg_la_LDFLAGS = -no-undefined \
|
||||||
|
-version-info $(JPEG_LIB_VERSION)
|
||||||
|
|
||||||
|
if HAVE_LD_VERSION_SCRIPT |
||||||
|
libjpeg_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libjpeg.map
|
||||||
|
endif |
||||||
|
|
||||||
|
# Executables to build
|
||||||
|
bin_PROGRAMS = cjpeg djpeg jpegtran rdjpgcom wrjpgcom
|
||||||
|
|
||||||
|
# Executable sources & libs
|
||||||
|
cjpeg_SOURCES = cjpeg.c rdppm.c rdgif.c rdtarga.c rdrle.c rdbmp.c \
|
||||||
|
rdswitch.c cdjpeg.c
|
||||||
|
cjpeg_LDADD = libjpeg.la
|
||||||
|
djpeg_SOURCES = djpeg.c wrppm.c wrgif.c wrtarga.c wrrle.c wrbmp.c \
|
||||||
|
rdcolmap.c cdjpeg.c
|
||||||
|
djpeg_LDADD = libjpeg.la
|
||||||
|
jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c
|
||||||
|
jpegtran_LDADD = libjpeg.la
|
||||||
|
rdjpgcom_SOURCES = rdjpgcom.c
|
||||||
|
wrjpgcom_SOURCES = wrjpgcom.c
|
||||||
|
|
||||||
|
# Manual pages to install
|
||||||
|
man_MANS = $(DISTMANS)
|
||||||
|
|
||||||
|
# Headers to install
|
||||||
|
include_HEADERS = $(INSTINCLUDES)
|
||||||
|
|
||||||
|
# Other distributed headers
|
||||||
|
noinst_HEADERS = $(OTHERINCLUDES)
|
||||||
|
|
||||||
|
# Other distributed files
|
||||||
|
EXTRA_DIST = $(DOCS) $(DISTMANS) $(MKFILES) $(CONFIGFILES) $(SYSDEPSOURCES) \
|
||||||
|
$(OTHERFILES) $(TESTFILES)
|
||||||
|
|
||||||
|
# Files to be cleaned
|
||||||
|
CLEANFILES = testout.ppm testout.bmp testout.jpg testoutp.ppm testoutp.jpg \
|
||||||
|
testoutt.jpg
|
||||||
|
|
||||||
|
# Install jconfig.h
|
||||||
|
install-data-local: |
||||||
|
$(mkinstalldirs) $(DESTDIR)$(includedir)
|
||||||
|
$(INSTALL_HEADER) jconfig.h $(DESTDIR)$(includedir)/jconfig.h
|
||||||
|
|
||||||
|
# Uninstall jconfig.h
|
||||||
|
uninstall-local: |
||||||
|
rm -f $(DESTDIR)$(includedir)/jconfig.h
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test: check-local |
||||||
|
check-local: |
||||||
|
rm -f testout*
|
||||||
|
./djpeg -dct int -ppm -outfile testout.ppm $(srcdir)/testorig.jpg
|
||||||
|
./djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(srcdir)/testorig.jpg
|
||||||
|
./cjpeg -dct int -outfile testout.jpg $(srcdir)/testimg.ppm
|
||||||
|
./djpeg -dct int -ppm -outfile testoutp.ppm $(srcdir)/testprog.jpg
|
||||||
|
./cjpeg -dct int -progressive -opt -outfile testoutp.jpg $(srcdir)/testimg.ppm
|
||||||
|
./jpegtran -outfile testoutt.jpg $(srcdir)/testprog.jpg
|
||||||
|
cmp $(srcdir)/testimg.ppm testout.ppm
|
||||||
|
cmp $(srcdir)/testimg.bmp testout.bmp
|
||||||
|
cmp $(srcdir)/testimg.jpg testout.jpg
|
||||||
|
cmp $(srcdir)/testimg.ppm testoutp.ppm
|
||||||
|
cmp $(srcdir)/testimgp.jpg testoutp.jpg
|
||||||
|
cmp $(srcdir)/testorig.jpg testoutt.jpg
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,326 @@ |
|||||||
|
The Independent JPEG Group's JPEG software |
||||||
|
========================================== |
||||||
|
|
||||||
|
README for release 8c of 16-Jan-2011 |
||||||
|
==================================== |
||||||
|
|
||||||
|
This distribution contains the eighth public release of the Independent JPEG |
||||||
|
Group's free JPEG software. You are welcome to redistribute this software and |
||||||
|
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. |
||||||
|
|
||||||
|
This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, |
||||||
|
Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, |
||||||
|
Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, |
||||||
|
and other members of the Independent JPEG Group. |
||||||
|
|
||||||
|
IJG is not affiliated with the official ISO JPEG standards committee. |
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION ROADMAP |
||||||
|
===================== |
||||||
|
|
||||||
|
This file contains the following sections: |
||||||
|
|
||||||
|
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. |
||||||
|
ACKNOWLEDGMENTS Special thanks. |
||||||
|
FILE FORMAT WARS Software *not* to get. |
||||||
|
TO DO Plans for future IJG releases. |
||||||
|
|
||||||
|
Other documentation files in the distribution are: |
||||||
|
|
||||||
|
User documentation: |
||||||
|
install.txt How to configure and install the IJG software. |
||||||
|
usage.txt Usage instructions for cjpeg, djpeg, jpegtran, |
||||||
|
rdjpgcom, and wrjpgcom. |
||||||
|
*.1 Unix-style man pages for programs (same info as usage.txt). |
||||||
|
wizard.txt Advanced usage instructions for JPEG wizards only. |
||||||
|
change.log Version-to-version change highlights. |
||||||
|
Programmer and internal documentation: |
||||||
|
libjpeg.txt How to use the JPEG library in your own programs. |
||||||
|
example.c Sample code for calling the JPEG library. |
||||||
|
structure.txt Overview of the JPEG library's internal structure. |
||||||
|
filelist.txt Road map of IJG files. |
||||||
|
coderules.txt Coding style rules --- please read if you contribute code. |
||||||
|
|
||||||
|
Please read at least the files install.txt and usage.txt. Some 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. |
||||||
|
|
||||||
|
|
||||||
|
OVERVIEW |
||||||
|
======== |
||||||
|
|
||||||
|
This package contains C software to implement JPEG image encoding, decoding, |
||||||
|
and transcoding. JPEG (pronounced "jay-peg") is a standardized compression |
||||||
|
method for full-color and gray-scale images. |
||||||
|
|
||||||
|
This software implements JPEG baseline, extended-sequential, and progressive |
||||||
|
compression processes. Provision is made for supporting all variants of these |
||||||
|
processes, although some uncommon parameter settings aren't implemented yet. |
||||||
|
We have made no provision for supporting the hierarchical or lossless |
||||||
|
processes defined in the standard. |
||||||
|
|
||||||
|
We provide a set of library routines for reading and writing JPEG image files, |
||||||
|
plus two sample applications "cjpeg" and "djpeg", which use the library to |
||||||
|
perform conversion between JPEG and some other popular image file formats. |
||||||
|
The library is intended to be reused in other applications. |
||||||
|
|
||||||
|
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 |
||||||
|
flexibility, while also making it fast enough to be useful. In particular, |
||||||
|
the software is not intended to be read as a tutorial on JPEG. (See the |
||||||
|
REFERENCES section for introductory material.) 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. |
||||||
|
No royalty is required, but we do ask for an acknowledgement in product |
||||||
|
documentation, as described under LEGAL ISSUES. |
||||||
|
|
||||||
|
|
||||||
|
LEGAL ISSUES |
||||||
|
============ |
||||||
|
|
||||||
|
In plain English: |
||||||
|
|
||||||
|
1. We don't promise that this software works. (But if you find any bugs, |
||||||
|
please let us know!) |
||||||
|
2. You can use this software for whatever you want. You don't have to pay us. |
||||||
|
3. You may not pretend that you wrote this software. If you use it in a |
||||||
|
program, you must acknowledge somewhere in your documentation that |
||||||
|
you've used the IJG code. |
||||||
|
|
||||||
|
In legalese: |
||||||
|
|
||||||
|
The authors make NO WARRANTY or representation, either express or implied, |
||||||
|
with respect to this software, its quality, accuracy, merchantability, or |
||||||
|
fitness for a particular purpose. This software is provided "AS IS", and you, |
||||||
|
its user, assume the entire risk as to its quality and accuracy. |
||||||
|
|
||||||
|
This software is copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding. |
||||||
|
All Rights Reserved except as specified below. |
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute this |
||||||
|
software (or portions thereof) for any purpose, without fee, subject to these |
||||||
|
conditions: |
||||||
|
(1) If any part of the source code for this software is distributed, then this |
||||||
|
README file must be included, with this copyright and no-warranty notice |
||||||
|
unaltered; and any additions, deletions, or changes to the original files |
||||||
|
must be clearly indicated in accompanying documentation. |
||||||
|
(2) If only executable code is distributed, then the accompanying |
||||||
|
documentation must state that "this software is based in part on the work of |
||||||
|
the Independent JPEG Group". |
||||||
|
(3) Permission for use of this software is granted only if the user accepts |
||||||
|
full responsibility for any undesirable consequences; the authors accept |
||||||
|
NO LIABILITY for damages of any kind. |
||||||
|
|
||||||
|
These conditions apply to any software derived from or based on the IJG code, |
||||||
|
not just to the unmodified library. If you use our work, you ought to |
||||||
|
acknowledge us. |
||||||
|
|
||||||
|
Permission is NOT granted for the use of any IJG author's name or company name |
||||||
|
in advertising or publicity relating to this software or products derived from |
||||||
|
it. This software may be referred to only as "the Independent JPEG Group's |
||||||
|
software". |
||||||
|
|
||||||
|
We specifically permit and encourage the use of this software as the basis of |
||||||
|
commercial products, provided that all warranty or liability claims are |
||||||
|
assumed by the product vendor. |
||||||
|
|
||||||
|
|
||||||
|
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, |
||||||
|
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. |
||||||
|
ansi2knr.c is NOT covered by the above copyright and conditions, but instead |
||||||
|
by the usual distribution terms of the Free Software Foundation; principally, |
||||||
|
that you must include source code if you redistribute it. (See the file |
||||||
|
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part |
||||||
|
of any program generated from the IJG code, this does not limit you more than |
||||||
|
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, |
||||||
|
ltmain.sh). Another support script, install-sh, is copyright by X Consortium |
||||||
|
but is also freely distributable. |
||||||
|
|
||||||
|
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 |
||||||
|
"The Graphics Interchange Format(c) is the Copyright property of |
||||||
|
CompuServe Incorporated. GIF(sm) is a Service Mark property of |
||||||
|
CompuServe Incorporated." |
||||||
|
|
||||||
|
|
||||||
|
REFERENCES |
||||||
|
========== |
||||||
|
|
||||||
|
We 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 http://www.ijg.org/files/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 currently available 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). |
||||||
|
Although this is by far the most detailed and comprehensive exposition of |
||||||
|
JPEG publicly available, we point out that it is still missing an explanation |
||||||
|
of the most essential properties and algorithms of the underlying DCT |
||||||
|
technology. |
||||||
|
If you think that you know about DCT-based JPEG after reading this book, |
||||||
|
then you are in delusion. The real fundamentals and corresponding potential |
||||||
|
of DCT-based JPEG are not publicly known so far, and that is the reason for |
||||||
|
all the mistaken developments taking place in the image coding domain. |
||||||
|
|
||||||
|
The original JPEG 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. |
||||||
|
IJG JPEG 8 introduces an implementation of the JPEG SmartScale extension |
||||||
|
which is specified in a contributed document at ITU and ISO with title "ITU-T |
||||||
|
JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced Image Coding", April |
||||||
|
2006, Geneva, Switzerland. The latest version of the document is Revision 3. |
||||||
|
|
||||||
|
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. JFIF 1.02 has been adopted as an Ecma International Technical Report |
||||||
|
and thus received a formal publication status. It is available as a free |
||||||
|
download in PDF format from |
||||||
|
http://www.ecma-international.org/publications/techreports/E-TR-098.htm. |
||||||
|
A PostScript version of the JFIF document is available at |
||||||
|
http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at |
||||||
|
http://www.ijg.org/files/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 |
||||||
|
http://www.ijg.org/files/. 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. |
||||||
|
|
||||||
|
|
||||||
|
ARCHIVE LOCATIONS |
||||||
|
================= |
||||||
|
|
||||||
|
The "official" archive site for this software is www.ijg.org. |
||||||
|
The most recent released version can always be found there in |
||||||
|
directory "files". This particular version will be archived as |
||||||
|
http://www.ijg.org/files/jpegsrc.v8c.tar.gz, and in Windows-compatible |
||||||
|
"zip" archive format as http://www.ijg.org/files/jpegsr8c.zip. |
||||||
|
|
||||||
|
The JPEG FAQ (Frequently Asked Questions) article is a source of some |
||||||
|
general information about JPEG. |
||||||
|
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 |
||||||
|
|
||||||
|
|
||||||
|
ACKNOWLEDGMENTS |
||||||
|
=============== |
||||||
|
|
||||||
|
Thank to Juergen Bruder for providing me with a copy of the common DCT |
||||||
|
algorithm article, only to find out that I had come to the same result |
||||||
|
in a more direct and comprehensible way with a more generative approach. |
||||||
|
|
||||||
|
Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the |
||||||
|
ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. |
||||||
|
|
||||||
|
Thank to Thomas Wiegand and Gary Sullivan for inviting me to the |
||||||
|
Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. |
||||||
|
|
||||||
|
Thank to John Korejwa and Massimo Ballerini for inviting me to |
||||||
|
fruitful consultations in Boston, MA and Milan, Italy. |
||||||
|
|
||||||
|
Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther |
||||||
|
Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel |
||||||
|
for corresponding business development. |
||||||
|
|
||||||
|
Thank to Nico Zschach and Dirk Stelling of the technical support team |
||||||
|
at the Digital Images company in Halle for providing me with extra |
||||||
|
equipment for configuration tests. |
||||||
|
|
||||||
|
Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful |
||||||
|
communication about JPEG configuration in Sigma Photo Pro software. |
||||||
|
|
||||||
|
Thank to Andrew Finkenstadt for hosting the ijg.org site. |
||||||
|
|
||||||
|
Last but not least special thank to Thomas G. Lane for the original |
||||||
|
design and development of this singular software package. |
||||||
|
|
||||||
|
|
||||||
|
FILE FORMAT WARS |
||||||
|
================ |
||||||
|
|
||||||
|
The ISO JPEG standards committee actually promotes different formats like |
||||||
|
"JPEG 2000" or "JPEG XR" which are incompatible with original DCT-based |
||||||
|
JPEG and which are based on faulty technologies. IJG therefore does not |
||||||
|
and will not support such momentary mistakes (see REFERENCES). |
||||||
|
We have little or no sympathy for the promotion of these formats. Indeed, |
||||||
|
one of the original reasons for developing this free software was to help |
||||||
|
force convergence on common, interoperable format standards for JPEG files. |
||||||
|
Don't use an incompatible file format! |
||||||
|
(In any case, our decoder will remain capable of reading existing JPEG |
||||||
|
image files indefinitely.) |
||||||
|
|
||||||
|
|
||||||
|
TO DO |
||||||
|
===== |
||||||
|
|
||||||
|
Version 8 is the first release of a new generation JPEG standard |
||||||
|
to overcome the limitations of the original JPEG specification. |
||||||
|
More features are being prepared for coming releases... |
||||||
|
|
||||||
|
Please send bug reports, offers of help, etc. to jpeg-info@uc.ag. |
@ -0,0 +1,5 @@ |
|||||||
|
This is a slightly modified version of the jpeg library. A new color space |
||||||
|
is added, "JCS_RGBA", for reading from/writing to jpeg files using the format |
||||||
|
expected by the CyanWorlds.com Engine. This code does not pretend to provide |
||||||
|
more RGBA support than needed for the CyanWorlds.com Engine. |
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -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>. |
@ -0,0 +1,739 @@ |
|||||||
|
/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ |
||||||
|
|
||||||
|
/*$Id: ansi2knr.c,v 1.14 2003/09/06 05:36:56 eggert Exp $*/ |
||||||
|
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */ |
||||||
|
|
||||||
|
/*
|
||||||
|
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, |
||||||
|
or, if there is no file named COPYLEFT, a file named COPYING. 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* Usage: |
||||||
|
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]] |
||||||
|
* --filename provides the file name for the #line directive in the output, |
||||||
|
* overriding input_file (if present). |
||||||
|
* If no input_file is supplied, input is read from stdin. |
||||||
|
* 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 and/or preprocessor directives), except that a line |
||||||
|
* consisting of only |
||||||
|
* identifier1(identifier2) |
||||||
|
* will not be considered a function definition unless identifier2 is |
||||||
|
* the word "void", and a line consisting of |
||||||
|
* identifier1(identifier2, <<arbitrary>>) |
||||||
|
* will not be considered a function definition. |
||||||
|
* ansi2knr 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, comments, and preprocessor directives, 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 function headers. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 2000-04-12 backs out Eggert's changes because of bugs: |
||||||
|
- concatlits didn't declare the type of its bufend argument; |
||||||
|
- concatlits didn't recognize when it was inside a comment; |
||||||
|
- scanstring could scan backward past the beginning of the string; when |
||||||
|
- the check for \ + newline in scanstring was unnecessary. |
||||||
|
|
||||||
|
2000-03-05 Paul Eggert <eggert@twinsun.com> |
||||||
|
|
||||||
|
Add support for concatenated string literals. |
||||||
|
* ansi2knr.c (concatlits): New decl. |
||||||
|
(main): Invoke concatlits to concatenate string literals. |
||||||
|
(scanstring): Handle backslash-newline correctly. Work with |
||||||
|
character constants. Fix bug when scanning backwards through |
||||||
|
backslash-quote. Check for unterminated strings. |
||||||
|
(convert1): Parse character constants, too. |
||||||
|
(appendline, concatlits): New functions. |
||||||
|
* ansi2knr.1: Document this. |
||||||
|
|
||||||
|
lpd 1999-08-17 added code to allow preprocessor directives |
||||||
|
wherever comments are allowed |
||||||
|
lpd 1999-04-12 added minor fixes from Pavel Roskin |
||||||
|
<pavel_roskin@geocities.com> for clean compilation with |
||||||
|
gcc -W -Wall |
||||||
|
lpd 1999-03-22 added hack to recognize lines consisting of |
||||||
|
identifier1(identifier2, xxx) as *not* being procedures |
||||||
|
lpd 1999-02-03 made indentation of preprocessor commands consistent |
||||||
|
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an |
||||||
|
endless loop; quoted strings within an argument list |
||||||
|
confused the parser |
||||||
|
lpd 1999-01-24 added a check for write errors on the output, |
||||||
|
suggested by Jim Meyering <meyering@ascend.com> |
||||||
|
lpd 1998-11-09 added further hack to recognize identifier(void) |
||||||
|
as being a procedure |
||||||
|
lpd 1998-10-23 added hack to recognize lines consisting of |
||||||
|
identifier1(identifier2) as *not* being procedures |
||||||
|
lpd 1997-12-08 made input_file optional; only closes input and/or |
||||||
|
output file if not stdin or stdout respectively; prints |
||||||
|
usage message on stderr rather than stdout; adds |
||||||
|
--filename switch (changes suggested by |
||||||
|
<ceder@lysator.liu.se>) |
||||||
|
lpd 1996-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 1996-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 1995-06-22 removed #ifndefs whose sole purpose was to define |
||||||
|
undefined preprocessor symbols as 0; changed all #ifdefs |
||||||
|
for configuration symbols to #ifs |
||||||
|
lpd 1995-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 1994-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 1994-10-10 removed CONFIG_BROKETS conditional |
||||||
|
lpd 1994-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 1989-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 <ctype.h> |
||||||
|
|
||||||
|
#if HAVE_CONFIG_H |
||||||
|
|
||||||
|
/*
|
||||||
|
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). |
||||||
|
This will define HAVE_CONFIG_H and so, activate the following lines. |
||||||
|
*/ |
||||||
|
|
||||||
|
# if STDC_HEADERS || HAVE_STRING_H |
||||||
|
# include <string.h> |
||||||
|
# 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 |
||||||
|
|
||||||
|
/* Define NULL (for *very* old compilers). */ |
||||||
|
#ifndef NULL |
||||||
|
# define NULL (0) |
||||||
|
#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 *ppdirforward(); |
||||||
|
char *ppdirbackward(); |
||||||
|
char *skipspace(); |
||||||
|
char *scanstring(); |
||||||
|
int writeblanks(); |
||||||
|
int test1(); |
||||||
|
int convert1(); |
||||||
|
|
||||||
|
/* The main program */ |
||||||
|
int |
||||||
|
main(argc, argv) |
||||||
|
int argc; |
||||||
|
char *argv[]; |
||||||
|
{ FILE *in = stdin; |
||||||
|
FILE *out = stdout; |
||||||
|
char *filename = 0; |
||||||
|
char *program_name = argv[0]; |
||||||
|
char *output_name = 0; |
||||||
|
#define bufsize 5000 /* arbitrary size */ |
||||||
|
char *buf; |
||||||
|
char *line; |
||||||
|
char *more; |
||||||
|
char *usage = |
||||||
|
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n"; |
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
int output_error; |
||||||
|
|
||||||
|
while ( argc > 1 && argv[1][0] == '-' ) { |
||||||
|
if ( !strcmp(argv[1], "--varargs") ) { |
||||||
|
convert_varargs = 1; |
||||||
|
argc--; |
||||||
|
argv++; |
||||||
|
continue; |
||||||
|
} |
||||||
|
if ( !strcmp(argv[1], "--filename") && argc > 2 ) { |
||||||
|
filename = argv[2]; |
||||||
|
argc -= 2; |
||||||
|
argv += 2; |
||||||
|
continue; |
||||||
|
} |
||||||
|
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name, |
||||||
|
argv[1]); |
||||||
|
fprintf(stderr, usage); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
switch ( argc ) |
||||||
|
{ |
||||||
|
default: |
||||||
|
fprintf(stderr, usage); |
||||||
|
exit(0); |
||||||
|
case 3: |
||||||
|
output_name = argv[2]; |
||||||
|
out = fopen(output_name, "w"); |
||||||
|
if ( out == NULL ) { |
||||||
|
fprintf(stderr, "%s: Cannot open output file %s\n", |
||||||
|
program_name, output_name); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
/* falls through */ |
||||||
|
case 2: |
||||||
|
in = fopen(argv[1], "r"); |
||||||
|
if ( in == NULL ) { |
||||||
|
fprintf(stderr, "%s: Cannot open input file %s\n", |
||||||
|
program_name, argv[1]); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
if ( filename == 0 ) |
||||||
|
filename = argv[1]; |
||||||
|
/* falls through */ |
||||||
|
case 1: |
||||||
|
break; |
||||||
|
} |
||||||
|
if ( filename ) |
||||||
|
fprintf(out, "#line 1 \"%s\"\n", filename); |
||||||
|
buf = malloc(bufsize); |
||||||
|
if ( buf == NULL ) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Unable to allocate read buffer!\n"); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
line = buf; |
||||||
|
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) |
||||||
|
{ |
||||||
|
test: line += strlen(line); |
||||||
|
switch ( test1(buf) ) |
||||||
|
{ |
||||||
|
case 2: /* a function header */ |
||||||
|
convert1(buf, out, 1, convert_varargs); |
||||||
|
break; |
||||||
|
case 1: /* a function */ |
||||||
|
/* 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(ppdirforward(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; |
||||||
|
case -1: /* maybe the start of a function */ |
||||||
|
if ( line != buf + (bufsize - 1) ) /* overflow check */ |
||||||
|
continue; |
||||||
|
/* falls through */ |
||||||
|
default: /* not a function */ |
||||||
|
wl: fputs(buf, out); |
||||||
|
break; |
||||||
|
} |
||||||
|
line = buf; |
||||||
|
} |
||||||
|
if ( line != buf ) |
||||||
|
fputs(buf, out); |
||||||
|
free(buf); |
||||||
|
if ( output_name ) { |
||||||
|
output_error = ferror(out); |
||||||
|
output_error |= fclose(out); |
||||||
|
} else { /* out == stdout */ |
||||||
|
fflush(out); |
||||||
|
output_error = ferror(out); |
||||||
|
} |
||||||
|
if ( output_error ) { |
||||||
|
fprintf(stderr, "%s: error writing to %s\n", program_name, |
||||||
|
(output_name ? output_name : "stdout")); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
if ( in != stdin ) |
||||||
|
fclose(in); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip forward or backward over one or more preprocessor directives. |
||||||
|
*/ |
||||||
|
char * |
||||||
|
ppdirforward(p) |
||||||
|
char *p; |
||||||
|
{ |
||||||
|
for (; *p == '#'; ++p) { |
||||||
|
for (; *p != '\r' && *p != '\n'; ++p) |
||||||
|
if (*p == 0) |
||||||
|
return p; |
||||||
|
if (*p == '\r' && p[1] == '\n') |
||||||
|
++p; |
||||||
|
} |
||||||
|
return p; |
||||||
|
} |
||||||
|
char * |
||||||
|
ppdirbackward(p, limit) |
||||||
|
char *p; |
||||||
|
char *limit; |
||||||
|
{ |
||||||
|
char *np = p; |
||||||
|
|
||||||
|
for (;; p = --np) { |
||||||
|
if (*np == '\n' && np[-1] == '\r') |
||||||
|
--np; |
||||||
|
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np) |
||||||
|
if (np[-1] == 0) |
||||||
|
return np; |
||||||
|
if (*np != '#') |
||||||
|
return p; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip over whitespace, comments, and preprocessor directives, |
||||||
|
* in either direction. |
||||||
|
*/ |
||||||
|
char * |
||||||
|
skipspace(p, dir) |
||||||
|
char *p; |
||||||
|
int dir; /* 1 for forward, -1 for backward */ |
||||||
|
{ |
||||||
|
for ( ; ; ) { |
||||||
|
while ( is_space(*p) ) |
||||||
|
p += dir; |
||||||
|
if ( !(*p == '/' && p[dir] == '*') ) |
||||||
|
break; |
||||||
|
p += dir; p += dir; |
||||||
|
while ( !(*p == '*' && p[dir] == '/') ) { |
||||||
|
if ( *p == 0 ) |
||||||
|
return p; /* multi-line comment?? */ |
||||||
|
p += dir; |
||||||
|
} |
||||||
|
p += dir; p += dir; |
||||||
|
} |
||||||
|
return p; |
||||||
|
} |
||||||
|
|
||||||
|
/* Scan over a quoted string, in either direction. */ |
||||||
|
char * |
||||||
|
scanstring(p, dir) |
||||||
|
char *p; |
||||||
|
int dir; |
||||||
|
{ |
||||||
|
for (p += dir; ; p += dir) |
||||||
|
if (*p == '"' && p[-dir] != '\\') |
||||||
|
return p + dir; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Write blanks over part of a string. |
||||||
|
* Don't overwrite end-of-line characters. |
||||||
|
*/ |
||||||
|
int |
||||||
|
writeblanks(start, end) |
||||||
|
char *start; |
||||||
|
char *end; |
||||||
|
{ char *p; |
||||||
|
for ( p = start; p < end; p++ ) |
||||||
|
if ( *p != '\r' && *p != '\n' ) |
||||||
|
*p = ' '; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Test whether the string in buf is a function definition. |
||||||
|
* The string may contain and/or end with a newline. |
||||||
|
* Return as follows: |
||||||
|
* 0 - definitely not a function definition; |
||||||
|
* 1 - definitely a function definition; |
||||||
|
* 2 - definitely a function prototype (NOT USED); |
||||||
|
* -1 - may be the beginning of a function definition, |
||||||
|
* 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 |
||||||
|
test1(buf) |
||||||
|
char *buf; |
||||||
|
{ char *p = buf; |
||||||
|
char *bend; |
||||||
|
char *endfn; |
||||||
|
int contin; |
||||||
|
|
||||||
|
if ( !isidfirstchar(*p) ) |
||||||
|
return 0; /* no name at left margin */ |
||||||
|
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1); |
||||||
|
switch ( *bend ) |
||||||
|
{ |
||||||
|
case ';': contin = 0 /*2*/; break; |
||||||
|
case ')': contin = 1; break; |
||||||
|
case '{': return 0; /* not a function */ |
||||||
|
case '}': return 0; /* not a function */ |
||||||
|
default: contin = -1; |
||||||
|
} |
||||||
|
while ( isidchar(*p) ) |
||||||
|
p++; |
||||||
|
endfn = p; |
||||||
|
p = skipspace(p, 1); |
||||||
|
if ( *p++ != '(' ) |
||||||
|
return 0; /* not a function */ |
||||||
|
p = skipspace(p, 1); |
||||||
|
if ( *p == ')' ) |
||||||
|
return 0; /* no parameters */ |
||||||
|
/* Check that the apparent function name isn't a keyword. */ |
||||||
|
/* We only need to check for keywords that could be followed */ |
||||||
|
/* by a left parenthesis (which, unfortunately, is most of them). */ |
||||||
|
{ static char *words[] = |
||||||
|
{ "asm", "auto", "case", "char", "const", "double", |
||||||
|
"extern", "float", "for", "if", "int", "long", |
||||||
|
"register", "return", "short", "signed", "sizeof", |
||||||
|
"static", "switch", "typedef", "unsigned", |
||||||
|
"void", "volatile", "while", 0 |
||||||
|
}; |
||||||
|
char **key = words; |
||||||
|
char *kp; |
||||||
|
unsigned len = endfn - buf; |
||||||
|
|
||||||
|
while ( (kp = *key) != 0 ) |
||||||
|
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) ) |
||||||
|
return 0; /* name is a keyword */ |
||||||
|
key++; |
||||||
|
} |
||||||
|
} |
||||||
|
{ |
||||||
|
char *id = p; |
||||||
|
int len; |
||||||
|
/*
|
||||||
|
* Check for identifier1(identifier2) and not |
||||||
|
* identifier1(void), or identifier1(identifier2, xxxx). |
||||||
|
*/ |
||||||
|
|
||||||
|
while ( isidchar(*p) ) |
||||||
|
p++; |
||||||
|
len = p - id; |
||||||
|
p = skipspace(p, 1); |
||||||
|
if (*p == ',' || |
||||||
|
(*p == ')' && (len != 4 || strncmp(id, "void", 4))) |
||||||
|
) |
||||||
|
return 0; /* not a function */ |
||||||
|
} |
||||||
|
/*
|
||||||
|
* If the last significant character was a ), we need to count |
||||||
|
* parentheses, because it might be part of a formal parameter |
||||||
|
* that is a procedure. |
||||||
|
*/ |
||||||
|
if (contin > 0) { |
||||||
|
int level = 0; |
||||||
|
|
||||||
|
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1)) |
||||||
|
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0); |
||||||
|
if (level > 0) |
||||||
|
contin = -1; |
||||||
|
} |
||||||
|
return contin; |
||||||
|
} |
||||||
|
|
||||||
|
/* Convert a recognized function definition or header to K&R syntax. */ |
||||||
|
int |
||||||
|
convert1(buf, out, header, convert_varargs) |
||||||
|
char *buf; |
||||||
|
FILE *out; |
||||||
|
int header; /* Boolean */ |
||||||
|
int convert_varargs; /* Boolean */ |
||||||
|
{ char *endfn; |
||||||
|
char *p; |
||||||
|
/*
|
||||||
|
* The breaks table contains pointers to the beginning and end |
||||||
|
* of each argument. |
||||||
|
*/ |
||||||
|
char **breaks; |
||||||
|
unsigned num_breaks = 2; /* for testing */ |
||||||
|
char **btop; |
||||||
|
char **bp; |
||||||
|
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; |
||||||
|
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); |
||||||
|
if ( breaks == NULL ) |
||||||
|
{ /* Couldn't allocate break table, give up */ |
||||||
|
fprintf(stderr, "Unable to allocate break table!\n"); |
||||||
|
fputs(buf, out); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
btop = breaks + num_breaks * 2 - 2; |
||||||
|
bp = breaks; |
||||||
|
/* Parse the argument list */ |
||||||
|
do |
||||||
|
{ int level = 0; |
||||||
|
char *lp = NULL; |
||||||
|
char *rp = NULL; |
||||||
|
char *end = NULL; |
||||||
|
|
||||||
|
if ( bp >= btop ) |
||||||
|
{ /* Filled up break table. */ |
||||||
|
/* Allocate a bigger one and start over. */ |
||||||
|
free((char *)breaks); |
||||||
|
num_breaks <<= 1; |
||||||
|
goto top; |
||||||
|
} |
||||||
|
*bp++ = p; |
||||||
|
/* Find the end of the argument */ |
||||||
|
for ( ; end == NULL; p++ ) |
||||||
|
{ switch(*p) |
||||||
|
{ |
||||||
|
case ',': |
||||||
|
if ( !level ) end = p; |
||||||
|
break; |
||||||
|
case '(': |
||||||
|
if ( !level ) lp = p; |
||||||
|
level++; |
||||||
|
break; |
||||||
|
case ')': |
||||||
|
if ( --level < 0 ) end = p; |
||||||
|
else rp = p; |
||||||
|
break; |
||||||
|
case '/': |
||||||
|
if (p[1] == '*') |
||||||
|
p = skipspace(p, 1) - 1; |
||||||
|
break; |
||||||
|
case '"': |
||||||
|
p = scanstring(p, 1) - 1; |
||||||
|
break; |
||||||
|
default: |
||||||
|
; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Erase any embedded prototype parameters. */ |
||||||
|
if ( lp && rp ) |
||||||
|
writeblanks(lp + 1, rp); |
||||||
|
p--; /* back up over terminator */ |
||||||
|
/* Find the name being declared. */ |
||||||
|
/* This is complicated because of procedure and */ |
||||||
|
/* array modifiers. */ |
||||||
|
for ( ; ; ) |
||||||
|
{ p = skipspace(p - 1, -1); |
||||||
|
switch ( *p ) |
||||||
|
{ |
||||||
|
case ']': /* skip array dimension(s) */ |
||||||
|
case ')': /* skip procedure args OR name */ |
||||||
|
{ int level = 1; |
||||||
|
while ( level ) |
||||||
|
switch ( *--p ) |
||||||
|
{ |
||||||
|
case ']': case ')': |
||||||
|
level++; |
||||||
|
break; |
||||||
|
case '[': case '(': |
||||||
|
level--; |
||||||
|
break; |
||||||
|
case '/': |
||||||
|
if (p > buf && p[-1] == '*') |
||||||
|
p = skipspace(p, -1) + 1; |
||||||
|
break; |
||||||
|
case '"': |
||||||
|
p = scanstring(p, -1) + 1; |
||||||
|
break; |
||||||
|
default: ; |
||||||
|
} |
||||||
|
} |
||||||
|
if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) |
||||||
|
{ /* We found the name being declared */ |
||||||
|
while ( !isidfirstchar(*p) ) |
||||||
|
p = skipspace(p, 1) + 1; |
||||||
|
goto found; |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
goto found; |
||||||
|
} |
||||||
|
} |
||||||
|
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) |
||||||
|
{ if ( convert_varargs ) |
||||||
|
{ *bp++ = "va_alist"; |
||||||
|
vararg = p-2; |
||||||
|
} |
||||||
|
else |
||||||
|
{ p++; |
||||||
|
if ( bp == breaks + 1 ) /* sole argument */ |
||||||
|
writeblanks(breaks[0], p); |
||||||
|
else |
||||||
|
writeblanks(bp[-1] - 1, p); |
||||||
|
bp--; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ while ( isidchar(*p) ) p--; |
||||||
|
*bp++ = p+1; |
||||||
|
} |
||||||
|
p = end; |
||||||
|
} |
||||||
|
while ( *p++ == ',' ); |
||||||
|
*bp = p; |
||||||
|
/* Make a special check for 'void' arglist */ |
||||||
|
if ( bp == breaks+2 ) |
||||||
|
{ p = skipspace(breaks[0], 1); |
||||||
|
if ( !strncmp(p, "void", 4) ) |
||||||
|
{ p = skipspace(p+4, 1); |
||||||
|
if ( p == breaks[2] - 1 ) |
||||||
|
{ bp = breaks; /* yup, pretend arglist is empty */ |
||||||
|
writeblanks(breaks[0], p + 1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/* Put out the function name and left parenthesis. */ |
||||||
|
p = buf; |
||||||
|
while ( p != endfn ) putc(*p, out), p++; |
||||||
|
/* Put out the declaration. */ |
||||||
|
if ( header ) |
||||||
|
{ fputs(");", out); |
||||||
|
for ( p = breaks[0]; *p; p++ ) |
||||||
|
if ( *p == '\r' || *p == '\n' ) |
||||||
|
putc(*p, out); |
||||||
|
} |
||||||
|
else |
||||||
|
{ for ( ap = breaks+1; ap < bp; ap += 2 ) |
||||||
|
{ p = *ap; |
||||||
|
while ( isidchar(*p) ) |
||||||
|
putc(*p, out), p++; |
||||||
|
if ( ap < bp - 1 ) |
||||||
|
fputs(", ", out); |
||||||
|
} |
||||||
|
fputs(") ", out); |
||||||
|
/* Put out the argument declarations */ |
||||||
|
for ( ap = breaks+2; ap <= bp; ap += 2 ) |
||||||
|
(*ap)[-1] = ';'; |
||||||
|
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); |
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,134 @@ |
|||||||
|
/*
|
||||||
|
* cderror.h |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane. |
||||||
|
* Modified 2009 by Guido Vollbeding. |
||||||
|
* 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_EMPTY, "Empty BMP image") |
||||||
|
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 |
@ -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; |
||||||
|
} |
@ -0,0 +1,187 @@ |
|||||||
|
/*
|
||||||
|
* 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_quality_ratings SetQRates |
||||||
|
#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, |
||||||
|
boolean force_baseline)); |
||||||
|
EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); |
||||||
|
EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, |
||||||
|
boolean force_baseline)); |
||||||
|
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 |
@ -0,0 +1,326 @@ |
|||||||
|
CHANGE LOG for Independent JPEG Group's JPEG software |
||||||
|
|
||||||
|
|
||||||
|
Version 8c 16-Jan-2011 |
||||||
|
----------------------- |
||||||
|
|
||||||
|
Add option to compression library and cjpeg (-block N) to use |
||||||
|
different DCT block size. |
||||||
|
All N from 1 to 16 are possible. Default is 8 (baseline format). |
||||||
|
Larger values produce higher compression, |
||||||
|
smaller values produce higher quality. |
||||||
|
SmartScale capable decoder (introduced with IJG JPEG 8) required. |
||||||
|
|
||||||
|
|
||||||
|
Version 8b 16-May-2010 |
||||||
|
----------------------- |
||||||
|
|
||||||
|
Repair problem in new memory source manager with corrupt JPEG data. |
||||||
|
Thank to Ted Campbell and Samuel Chun for the report. |
||||||
|
|
||||||
|
Repair problem in Makefile.am test target. |
||||||
|
Thank to anonymous user for the report. |
||||||
|
|
||||||
|
Support MinGW installation with automatic configure. |
||||||
|
Thank to Volker Grabsch for the suggestion. |
||||||
|
|
||||||
|
|
||||||
|
Version 8a 28-Feb-2010 |
||||||
|
----------------------- |
||||||
|
|
||||||
|
Writing tables-only datastreams via jpeg_write_tables works again. |
||||||
|
|
||||||
|
Support 32-bit BMPs (RGB image with Alpha channel) for read in cjpeg. |
||||||
|
Thank to Brett Blackham for the suggestion. |
||||||
|
|
||||||
|
Improve accuracy in floating point IDCT calculation. |
||||||
|
Thank to Robert Hooke for the hint. |
||||||
|
|
||||||
|
|
||||||
|
Version 8 10-Jan-2010 |
||||||
|
---------------------- |
||||||
|
|
||||||
|
jpegtran now supports the same -scale option as djpeg for "lossless" resize. |
||||||
|
An implementation of the JPEG SmartScale extension is required for this |
||||||
|
feature. A (draft) specification of the JPEG SmartScale extension is |
||||||
|
available as a contributed document at ITU and ISO. Revision 2 or later |
||||||
|
of the document is required (latest document version is Revision 3). |
||||||
|
The SmartScale extension will enable more features beside lossless resize |
||||||
|
in future implementations, as described in the document (new compression |
||||||
|
options). |
||||||
|
|
||||||
|
Add sanity check in BMP reader module to avoid cjpeg crash for empty input |
||||||
|
image (thank to Isaev Ildar of ISP RAS, Moscow, RU for reporting this error). |
||||||
|
|
||||||
|
Add data source and destination managers for read from and write to |
||||||
|
memory buffers. New API functions jpeg_mem_src and jpeg_mem_dest. |
||||||
|
Thank to Roberto Boni from Italy for the suggestion. |
||||||
|
|
||||||
|
|
||||||
|
Version 7 27-Jun-2009 |
||||||
|
---------------------- |
||||||
|
|
||||||
|
New scaled DCTs implemented. |
||||||
|
djpeg now supports scalings N/8 with all N from 1 to 16. |
||||||
|
cjpeg now supports scalings 8/N with all N from 1 to 16. |
||||||
|
Scaled DCTs with size larger than 8 are now also used for resolving the |
||||||
|
common 2x2 chroma subsampling case without additional spatial resampling. |
||||||
|
Separate spatial resampling for those kind of files is now only necessary |
||||||
|
for N>8 scaling cases. |
||||||
|
Furthermore, separate scaled DCT functions are provided for direct resolving |
||||||
|
of the common asymmetric subsampling cases (2x1 and 1x2) without additional |
||||||
|
spatial resampling. |
||||||
|
|
||||||
|
cjpeg -quality option has been extended for support of separate quality |
||||||
|
settings for luminance and chrominance (or in general, for every provided |
||||||
|
quantization table slot). |
||||||
|
New API function jpeg_default_qtables() and q_scale_factor array in library. |
||||||
|
|
||||||
|
Added -nosmooth option to cjpeg, complementary to djpeg. |
||||||
|
New variable "do_fancy_downsampling" in library, complement to fancy |
||||||
|
upsampling. Fancy upsampling now uses direct DCT scaling with sizes |
||||||
|
larger than 8. The old method is not reversible and has been removed. |
||||||
|
|
||||||
|
Support arithmetic entropy encoding and decoding. |
||||||
|
Added files jaricom.c, jcarith.c, jdarith.c. |
||||||
|
|
||||||
|
Straighten the file structure: |
||||||
|
Removed files jidctred.c, jcphuff.c, jchuff.h, jdphuff.c, jdhuff.h. |
||||||
|
|
||||||
|
jpegtran has a new "lossless" cropping feature. |
||||||
|
|
||||||
|
Implement -perfect option in jpegtran, new API function |
||||||
|
jtransform_perfect_transform() in transupp. (DP 204_perfect.dpatch) |
||||||
|
|
||||||
|
Better error messages for jpegtran fopen failure. |
||||||
|
(DP 203_jpegtran_errmsg.dpatch) |
||||||
|
|
||||||
|
Fix byte order issue with 16bit PPM/PGM files in rdppm.c/wrppm.c: |
||||||
|
according to Netpbm, the de facto standard implementation of the PNM formats, |
||||||
|
the most significant byte is first. (DP 203_rdppm.dpatch) |
||||||
|
|
||||||
|
Add -raw option to rdjpgcom not to mangle the output. |
||||||
|
(DP 205_rdjpgcom_raw.dpatch) |
||||||
|
|
||||||
|
Make rdjpgcom locale aware. (DP 201_rdjpgcom_locale.dpatch) |
||||||
|
|
||||||
|
Add extern "C" to jpeglib.h. |
||||||
|
This avoids the need to put extern "C" { ... } around #include "jpeglib.h" |
||||||
|
in your C++ application. Defining the symbol DONT_USE_EXTERN_C in the |
||||||
|
configuration prevents this. (DP 202_jpeglib.h_c++.dpatch) |
||||||
|
|
||||||
|
|
||||||
|
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. |
@ -0,0 +1,339 @@ |
|||||||
|
.TH CJPEG 1 "14 November 2010" |
||||||
|
.SH NAME |
||||||
|
cjpeg \- compress an image file to a JPEG file |
||||||
|
.SH SYNOPSIS |
||||||
|
.B cjpeg |
||||||
|
[ |
||||||
|
.I options |
||||||
|
] |
||||||
|
[ |
||||||
|
.I filename |
||||||
|
] |
||||||
|
.LP |
||||||
|
.SH DESCRIPTION |
||||||
|
.LP |
||||||
|
.B cjpeg |
||||||
|
compresses the named image file, or the standard input if no file is |
||||||
|
named, and produces a JPEG/JFIF file on the standard output. |
||||||
|
The currently supported input file formats are: PPM (PBMPLUS color |
||||||
|
format), PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster |
||||||
|
Toolkit format). (RLE is supported only if the URT library is available.) |
||||||
|
.SH OPTIONS |
||||||
|
All switch names may be abbreviated; for example, |
||||||
|
.B \-grayscale |
||||||
|
may be written |
||||||
|
.B \-gray |
||||||
|
or |
||||||
|
.BR \-gr . |
||||||
|
Most of the "basic" switches can be abbreviated to as little as one letter. |
||||||
|
Upper and lower case are equivalent (thus |
||||||
|
.B \-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 |
||||||
|
.BI \-quality " N[,...]" |
||||||
|
Scale quantization tables to adjust image quality. Quality is 0 (worst) to |
||||||
|
100 (best); default is 75. (See below for more info.) |
||||||
|
.TP |
||||||
|
.B \-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 |
||||||
|
encoding parameters are used. |
||||||
|
.B \-optimize |
||||||
|
usually makes the JPEG file a little smaller, but |
||||||
|
.B cjpeg |
||||||
|
runs somewhat slower and needs much more memory. Image quality and speed of |
||||||
|
decompression are unaffected by |
||||||
|
.BR \-optimize . |
||||||
|
.TP |
||||||
|
.B \-progressive |
||||||
|
Create progressive JPEG file (see below). |
||||||
|
.TP |
||||||
|
.BI \-scale " M/N" |
||||||
|
Scale the output image by a factor M/N. Currently supported scale factors are |
||||||
|
M/N with all N from 1 to 16, where M is the destination DCT size, which is 8 |
||||||
|
by default (see |
||||||
|
.BI \-block " N" |
||||||
|
switch below). |
||||||
|
.TP |
||||||
|
.B \-targa |
||||||
|
Input file is Targa format. Targa files that contain an "identification" |
||||||
|
field will not be automatically recognized by |
||||||
|
.BR cjpeg ; |
||||||
|
for such files you must specify |
||||||
|
.B \-targa |
||||||
|
to make |
||||||
|
.B cjpeg |
||||||
|
treat the input as Targa format. |
||||||
|
For most Targa files, you won't need this switch. |
||||||
|
.PP |
||||||
|
The |
||||||
|
.B \-quality |
||||||
|
switch lets you trade off compressed file size against quality of the |
||||||
|
reconstructed image: the higher the quality setting, the larger the JPEG file, |
||||||
|
and the closer the output image will be to the original input. Normally you |
||||||
|
want to use the lowest quality setting (smallest file) that decompresses into |
||||||
|
something visually indistinguishable from the original image. For this |
||||||
|
purpose the quality setting should be between 50 and 95; the default of 75 is |
||||||
|
often about right. If you see defects at |
||||||
|
.B \-quality |
||||||
|
75, then go up 5 or 10 counts at a time until you are happy with the output |
||||||
|
image. (The optimal setting will vary from one image to another.) |
||||||
|
.PP |
||||||
|
.B \-quality |
||||||
|
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 |
||||||
|
as roundoff error). This setting is mainly of interest for experimental |
||||||
|
purposes. Quality values above about 95 are |
||||||
|
.B not |
||||||
|
recommended for normal use; the compressed file size goes up dramatically for |
||||||
|
hardly any gain in output image quality. |
||||||
|
.PP |
||||||
|
In the other direction, quality values below 50 will produce very small files |
||||||
|
of low image quality. Settings around 5 to 10 might be useful in preparing an |
||||||
|
index of a large image library, for example. Try |
||||||
|
.B \-quality |
||||||
|
2 (or so) for some amusing Cubist effects. (Note: quality |
||||||
|
values below about 25 generate 2-byte quantization tables, which are |
||||||
|
considered optional in the JPEG standard. |
||||||
|
.B cjpeg |
||||||
|
emits a warning message when you give such a quality value, because some |
||||||
|
other JPEG programs may be unable to decode the resulting file. Use |
||||||
|
.B \-baseline |
||||||
|
if you need to ensure compatibility at low quality values.) |
||||||
|
.PP |
||||||
|
The |
||||||
|
.B \-quality |
||||||
|
option has been extended in IJG version 7 for support of separate quality |
||||||
|
settings for luminance and chrominance (or in general, for every provided |
||||||
|
quantization table slot). This feature is useful for high-quality |
||||||
|
applications which cannot accept the damage of color data by coarse |
||||||
|
subsampling settings. You can now easily reduce the color data amount more |
||||||
|
smoothly with finer control without separate subsampling. The resulting file |
||||||
|
is fully compliant with standard JPEG decoders. |
||||||
|
Note that the |
||||||
|
.B \-quality |
||||||
|
ratings refer to the quantization table slots, and that the last value is |
||||||
|
replicated if there are more q-table slots than parameters. The default |
||||||
|
q-table slots are 0 for luminance and 1 for chrominance with default tables as |
||||||
|
given in the JPEG standard. This is compatible with the old behaviour in case |
||||||
|
that only one parameter is given, which is then used for both luminance and |
||||||
|
chrominance (slots 0 and 1). More or custom quantization tables can be set |
||||||
|
with |
||||||
|
.B \-qtables |
||||||
|
and assigned to components with |
||||||
|
.B \-qslots |
||||||
|
parameter (see the "wizard" switches below). |
||||||
|
.B Caution: |
||||||
|
You must explicitly add |
||||||
|
.BI \-sample " 1x1" |
||||||
|
for efficient separate color |
||||||
|
quality selection, since the default value used by library is 2x2! |
||||||
|
.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. |
||||||
|
.PP |
||||||
|
Switches for advanced users: |
||||||
|
.TP |
||||||
|
.BI \-block " N" |
||||||
|
Set DCT block size. All N from 1 to 16 are possible. |
||||||
|
Default is 8 (baseline format). |
||||||
|
Larger values produce higher compression, |
||||||
|
smaller values produce higher quality |
||||||
|
(exact DCT stage possible with 1 or 2; with the default quality of 75 and |
||||||
|
default Luminance qtable the DCT+Quantization stage is lossless for N=1). |
||||||
|
CAUTION: An implementation of the JPEG SmartScale extension is required for |
||||||
|
this feature. SmartScale enabled JPEG is not yet widely implemented, so |
||||||
|
many decoders will be unable to view a SmartScale extended JPEG file at all. |
||||||
|
.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 |
||||||
|
.B \-nosmooth |
||||||
|
Don't use high-quality downsampling. |
||||||
|
.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 \-arithmetic |
||||||
|
Use arithmetic coding. |
||||||
|
.B Caution: |
||||||
|
arithmetic coded JPEG is not yet widely implemented, so many decoders will be |
||||||
|
unable to view an arithmetic coded JPEG file at all. |
||||||
|
.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.txt. |
||||||
|
.SH EXAMPLES |
||||||
|
.LP |
||||||
|
This example compresses the PPM file foo.ppm with a quality factor of |
||||||
|
60 and saves the output as foo.jpg: |
||||||
|
.IP |
||||||
|
.B cjpeg \-quality |
||||||
|
.I 60 foo.ppm |
||||||
|
.B > |
||||||
|
.I foo.jpg |
||||||
|
.SH HINTS |
||||||
|
Color GIF files are not the ideal input for JPEG; JPEG is really intended for |
||||||
|
compressing full-color (24-bit) images. In particular, don't try to convert |
||||||
|
cartoons, line drawings, and other images that have only a few distinct |
||||||
|
colors. GIF works great on these, JPEG does not. If you want to convert a |
||||||
|
GIF to JPEG, you should experiment with |
||||||
|
.BR cjpeg 's |
||||||
|
.B \-quality |
||||||
|
and |
||||||
|
.B \-smooth |
||||||
|
options to get a satisfactory conversion. |
||||||
|
.B \-smooth 10 |
||||||
|
or so is often helpful. |
||||||
|
.PP |
||||||
|
Avoid running an image through a series of JPEG compression/decompression |
||||||
|
cycles. Image quality loss will accumulate; after ten or so cycles the image |
||||||
|
may be noticeably worse than it was after one cycle. It's best to use a |
||||||
|
lossless format while manipulating an image, then convert to JPEG format when |
||||||
|
you are ready to file the image away. |
||||||
|
.PP |
||||||
|
The |
||||||
|
.B \-optimize |
||||||
|
option to |
||||||
|
.B cjpeg |
||||||
|
is worth using when you are making a "final" version for posting or archiving. |
||||||
|
It's also a win when you are using low quality settings to make very small |
||||||
|
JPEG files; the percentage improvement is often a lot more than it is on |
||||||
|
larger files. (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 |
||||||
|
.BR djpeg (1), |
||||||
|
.BR jpegtran (1), |
||||||
|
.BR rdjpgcom (1), |
||||||
|
.BR wrjpgcom (1) |
||||||
|
.br |
||||||
|
.BR ppm (5), |
||||||
|
.BR pgm (5) |
||||||
|
.br |
||||||
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard", |
||||||
|
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. |
||||||
|
.SH AUTHOR |
||||||
|
Independent JPEG Group |
||||||
|
.SH BUGS |
||||||
|
GIF input files are no longer supported, to avoid the Unisys LZW patent. |
||||||
|
(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 |
||||||
|
The |
||||||
|
.B \-targa |
||||||
|
switch is not a bug, it's a feature. (It would be a bug if the Targa format |
||||||
|
designers had not been clueless.) |
@ -0,0 +1,639 @@ |
|||||||
|
/*
|
||||||
|
* cjpeg.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane. |
||||||
|
* Modified 2003-2010 by Guido Vollbeding. |
||||||
|
* This file is part of the Independent JPEG Group's software. |
||||||
|
* For conditions of distribution and use, see the accompanying README file. |
||||||
|
* |
||||||
|
* This file contains a command-line user interface for the JPEG compressor. |
||||||
|
* It should work on any system with Unix- or MS-DOS-style command lines. |
||||||
|
* |
||||||
|
* Two different command line styles are permitted, depending on the |
||||||
|
* compile-time switch TWO_FILE_COMMANDLINE: |
||||||
|
* cjpeg [options] inputfile outputfile |
||||||
|
* cjpeg [options] [inputfile] |
||||||
|
* In the second style, output is always to standard output, which you'd |
||||||
|
* normally redirect to a file or pipe to some other program. Input is |
||||||
|
* either from a named file or from standard input (typically redirected). |
||||||
|
* The second style is convenient on Unix but is unhelpful on systems that |
||||||
|
* don't support pipes. Also, you MUST use the first style if your system |
||||||
|
* doesn't do binary I/O to stdin/stdout. |
||||||
|
* To simplify script writing, the "-outfile" switch is provided. The syntax |
||||||
|
* cjpeg [options] -outfile outputfile inputfile |
||||||
|
* works regardless of which command line style is used. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ |
||||||
|
#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 DCT_SCALING_SUPPORTED |
||||||
|
fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\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_SCALING_SUPPORTED |
||||||
|
fprintf(stderr, " -block N DCT block size (1..16; default is 8)\n"); |
||||||
|
#endif |
||||||
|
#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, " -nosmooth Don't use high-quality downsampling\n"); |
||||||
|
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); |
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED |
||||||
|
fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); |
||||||
|
#endif |
||||||
|
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); |
||||||
|
fprintf(stderr, " -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); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
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; |
||||||
|
boolean force_baseline; |
||||||
|
boolean simple_progressive; |
||||||
|
char * qualityarg = NULL; /* saves -quality parm if any */ |
||||||
|
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. */ |
||||||
|
|
||||||
|
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", 2)) { |
||||||
|
/* Force baseline-compatible output (8-bit quantizer values). */ |
||||||
|
force_baseline = TRUE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "block", 2)) { |
||||||
|
/* Set DCT block size. */ |
||||||
|
#if defined(DCT_SCALING_SUPPORTED) && defined(JPEG_LIB_VERSION_MAJOR) && \ |
||||||
|
(JPEG_LIB_VERSION_MAJOR > 8 || (JPEG_LIB_VERSION_MAJOR == 8 && \
|
||||||
|
defined(JPEG_LIB_VERSION_MINOR) && JPEG_LIB_VERSION_MINOR >= 3)) |
||||||
|
int val; |
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1) |
||||||
|
usage(); |
||||||
|
if (val < 1 || val > 16) |
||||||
|
usage(); |
||||||
|
cinfo->block_size = val; |
||||||
|
#else |
||||||
|
fprintf(stderr, "%s: sorry, block size setting not supported\n", |
||||||
|
progname); |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
#endif |
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) { |
||||||
|
/* Select DCT algorithm. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (keymatch(argv[argn], "int", 1)) { |
||||||
|
cinfo->dct_method = JDCT_ISLOW; |
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) { |
||||||
|
cinfo->dct_method = JDCT_IFAST; |
||||||
|
} else if (keymatch(argv[argn], "float", 2)) { |
||||||
|
cinfo->dct_method = JDCT_FLOAT; |
||||||
|
} else |
||||||
|
usage(); |
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { |
||||||
|
/* Enable debug printouts. */ |
||||||
|
/* On first -d, print version identification */ |
||||||
|
static boolean printed_version = FALSE; |
||||||
|
|
||||||
|
if (! printed_version) { |
||||||
|
fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n", |
||||||
|
JVERSION, JCOPYRIGHT); |
||||||
|
printed_version = TRUE; |
||||||
|
} |
||||||
|
cinfo->err->trace_level++; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { |
||||||
|
/* Force a monochrome JPEG file to be generated. */ |
||||||
|
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); |
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) { |
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */ |
||||||
|
long lval; |
||||||
|
char ch = 'x'; |
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) |
||||||
|
usage(); |
||||||
|
if (ch == 'm' || ch == 'M') |
||||||
|
lval *= 1000L; |
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "nosmooth", 3)) { |
||||||
|
/* Suppress fancy downsampling */ |
||||||
|
cinfo->do_fancy_downsampling = FALSE; |
||||||
|
|
||||||
|
} 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 ratings (quantization table scaling factors). */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
qualityarg = argv[argn]; |
||||||
|
|
||||||
|
} 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, "scale", 4)) { |
||||||
|
/* Scale the 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, "scans", 4)) { |
||||||
|
/* 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. */ |
||||||
|
if (qualityarg != NULL) /* process -quality if it was present */ |
||||||
|
if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) |
||||||
|
usage(); |
||||||
|
|
||||||
|
if (qtablefile != NULL) /* process -qtables if it was present */ |
||||||
|
if (! read_quant_tables(cinfo, qtablefile, 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 */ |
||||||
|
} |
@ -0,0 +1,402 @@ |
|||||||
|
/*
|
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.txt for explanations */\n\n"); |
||||||
|
#ifdef HAVE_PROTOTYPES |
||||||
|
fprintf(outfile, "#define HAVE_PROTOTYPES\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef HAVE_PROTOTYPES\n"); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_UNSIGNED_CHAR |
||||||
|
fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n"); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_UNSIGNED_SHORT |
||||||
|
fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n"); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_VOID |
||||||
|
fprintf(outfile, "/* #define void char */\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#define void char\n"); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_CONST |
||||||
|
fprintf(outfile, "/* #define const */\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#define const\n"); |
||||||
|
#endif |
||||||
|
if (is_char_signed((int) signed_char_check)) |
||||||
|
fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n"); |
||||||
|
else |
||||||
|
fprintf(outfile, "#define CHAR_IS_UNSIGNED\n"); |
||||||
|
#ifdef HAVE_STDDEF_H |
||||||
|
fprintf(outfile, "#define HAVE_STDDEF_H\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef HAVE_STDDEF_H\n"); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_STDLIB_H |
||||||
|
fprintf(outfile, "#define HAVE_STDLIB_H\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef HAVE_STDLIB_H\n"); |
||||||
|
#endif |
||||||
|
#ifdef NEED_BSD_STRINGS |
||||||
|
fprintf(outfile, "#define NEED_BSD_STRINGS\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef NEED_BSD_STRINGS\n"); |
||||||
|
#endif |
||||||
|
#ifdef NEED_SYS_TYPES_H |
||||||
|
fprintf(outfile, "#define NEED_SYS_TYPES_H\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef NEED_SYS_TYPES_H\n"); |
||||||
|
#endif |
||||||
|
fprintf(outfile, "#undef NEED_FAR_POINTERS\n"); |
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n"); |
||||||
|
#endif |
||||||
|
#ifdef INCOMPLETE_TYPES_BROKEN |
||||||
|
fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n"); |
||||||
|
#else |
||||||
|
fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n"); |
||||||
|
#endif |
||||||
|
fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n"); |
||||||
|
if (is_shifting_signed(-0x7F7E80B1L)) |
||||||
|
fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n"); |
||||||
|
else |
||||||
|
fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n"); |
||||||
|
fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n"); |
||||||
|
fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n"); |
||||||
|
fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n"); |
||||||
|
fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n"); |
||||||
|
fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n"); |
||||||
|
fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n"); |
||||||
|
fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n"); |
||||||
|
fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n"); |
||||||
|
fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n"); |
||||||
|
fprintf(outfile, "#undef DONT_USE_B_MODE\n"); |
||||||
|
fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n"); |
||||||
|
fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n"); |
||||||
|
|
||||||
|
/* Close the jconfig.h file */ |
||||||
|
fclose(outfile); |
||||||
|
|
||||||
|
/* User report */ |
||||||
|
printf("Configuration check for Independent JPEG Group's software done.\n"); |
||||||
|
printf("\nI have written the jconfig.h file for you.\n\n"); |
||||||
|
#ifdef HAVE_PROTOTYPES |
||||||
|
printf("You should use makefile.ansi as the starting point for your Makefile.\n"); |
||||||
|
#else |
||||||
|
printf("You should use makefile.unix as the starting point for your Makefile.\n"); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef NEED_SPECIAL_INCLUDE |
||||||
|
printf("\nYou'll need to change jconfig.h to include the system include file\n"); |
||||||
|
printf("that you found type size_t in, or add a direct definition of type\n"); |
||||||
|
printf("size_t if that's what you used. Just add it to the end.\n"); |
||||||
|
#endif |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -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.txt). |
||||||
|
|
||||||
|
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. |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,318 @@ |
|||||||
|
# IJG auto-configuration source file. |
||||||
|
# Process this file with autoconf to produce a configure script. |
||||||
|
|
||||||
|
# |
||||||
|
# Configure script for IJG libjpeg |
||||||
|
# |
||||||
|
|
||||||
|
AC_INIT([libjpeg], [8.3.0]) |
||||||
|
|
||||||
|
# Directory where autotools helper scripts lives. |
||||||
|
AC_CONFIG_AUX_DIR([.]) |
||||||
|
|
||||||
|
# Generate configuration headers. |
||||||
|
AC_CONFIG_HEADERS([jconfig.h:jconfig.cfg]) |
||||||
|
|
||||||
|
# Hack: disable autoheader so that it doesn't overwrite our cfg template. |
||||||
|
AUTOHEADER="echo autoheader ignored" |
||||||
|
|
||||||
|
# Check system type |
||||||
|
AC_CANONICAL_TARGET |
||||||
|
|
||||||
|
# Initialize Automake |
||||||
|
# Don't require all the GNU mandated files |
||||||
|
AM_INIT_AUTOMAKE([-Wall -Werror ansi2knr no-dist foreign]) |
||||||
|
|
||||||
|
# Make --enable-silent-rules the default. |
||||||
|
# To get verbose build output you may configure |
||||||
|
# with --disable-silent-rules or use "make V=1". |
||||||
|
AM_SILENT_RULES([yes]) |
||||||
|
|
||||||
|
# This is required when using the de-ANSI-fication feature. |
||||||
|
AM_C_PROTOTYPES |
||||||
|
|
||||||
|
# Add configure option --enable-maintainer-mode which enables |
||||||
|
# dependency checking and generation useful to package maintainers. |
||||||
|
# This is made an option to avoid confusing end users. |
||||||
|
AM_MAINTAINER_MODE |
||||||
|
|
||||||
|
# Check for programs |
||||||
|
AC_PROG_CC |
||||||
|
AC_PROG_CC_STDC |
||||||
|
AC_PROG_CPP |
||||||
|
AC_PROG_INSTALL |
||||||
|
AC_PROG_MAKE_SET |
||||||
|
AC_PROG_LN_S |
||||||
|
|
||||||
|
# Check if LD supports linker scripts, |
||||||
|
# and define automake conditional HAVE_LD_VERSION_SCRIPT if so. |
||||||
|
AC_ARG_ENABLE([ld-version-script], |
||||||
|
AS_HELP_STRING([--enable-ld-version-script], |
||||||
|
[enable linker version script (default is enabled when possible)]), |
||||||
|
[have_ld_version_script=$enableval], []) |
||||||
|
if test -z "$have_ld_version_script"; then |
||||||
|
AC_MSG_CHECKING([if LD -Wl,--version-script works]) |
||||||
|
save_LDFLAGS="$LDFLAGS" |
||||||
|
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" |
||||||
|
cat > conftest.map <<EOF |
||||||
|
VERS_1 { |
||||||
|
global: sym; |
||||||
|
}; |
||||||
|
|
||||||
|
VERS_2 { |
||||||
|
global: sym; |
||||||
|
} VERS_1; |
||||||
|
EOF |
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], |
||||||
|
[have_ld_version_script=yes], [have_ld_version_script=no]) |
||||||
|
rm -f conftest.map |
||||||
|
LDFLAGS="$save_LDFLAGS" |
||||||
|
AC_MSG_RESULT($have_ld_version_script) |
||||||
|
fi |
||||||
|
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") |
||||||
|
|
||||||
|
# See if compiler supports prototypes. |
||||||
|
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],[1],[Compiler supports function 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 |
||||||
|
|
||||||
|
# Check header files |
||||||
|
AC_CHECK_HEADERS(stddef.h stdlib.h locale.h) |
||||||
|
AC_CHECK_HEADER(string.h, , AC_DEFINE([NEED_BSD_STRINGS],[1],[Compiler has <strings.h> rather than standard <string.h>.])) |
||||||
|
|
||||||
|
# See whether type size_t is defined in any ANSI-standard places; |
||||||
|
# if not, perhaps it is defined in <sys/types.h>. |
||||||
|
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],[1],[Need to include <sys/types.h> in order to obtain size_t.]) |
||||||
|
AC_EGREP_CPP(size_t, [#include <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 |
||||||
|
|
||||||
|
# Check compiler characteristics |
||||||
|
AC_MSG_CHECKING(for type unsigned char) |
||||||
|
AC_TRY_COMPILE(, [ unsigned char un_char; ], |
||||||
|
[AC_MSG_RESULT(yes) |
||||||
|
AC_DEFINE([HAVE_UNSIGNED_CHAR],[1],[Compiler supports '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],[1],[Compiler supports '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],[Define 'void' as 'char' for archaic compilers that don't understand it.])]) |
||||||
|
AC_C_CONST |
||||||
|
|
||||||
|
# Check for non-broken inline under various spellings |
||||||
|
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],[How to obtain function inlining.]) |
||||||
|
|
||||||
|
# We cannot check for bogus warnings, but at least we can check for errors |
||||||
|
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],[1],[Compiler does not support pointers to unspecified structures.])]) |
||||||
|
|
||||||
|
# Test whether global names are unique to at least 15 chars |
||||||
|
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],[1],[Linker requires that global names be unique in first 15 characters.])]) |
||||||
|
|
||||||
|
# Run-time checks |
||||||
|
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); |
||||||
|
int main() { |
||||||
|
exit(is_char_signed((int) signed_char_check)); |
||||||
|
}], [AC_MSG_RESULT(no) |
||||||
|
AC_DEFINE([CHAR_IS_UNSIGNED],[1],[Characters are 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 */ |
||||||
|
} |
||||||
|
int main() { |
||||||
|
exit(is_shifting_signed(-0x7F7E80B1L)); |
||||||
|
}], [AC_MSG_RESULT(no) |
||||||
|
AC_DEFINE([RIGHT_SHIFT_IS_UNSIGNED],[1],[Broken compiler shifts signed values as an unsigned shift.])], 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> |
||||||
|
int main() { |
||||||
|
if (fopen("conftestdata", "wb") != NULL) |
||||||
|
exit(0); |
||||||
|
exit(1); |
||||||
|
}], AC_MSG_RESULT(yes), [AC_MSG_RESULT(no) |
||||||
|
AC_DEFINE([DONT_USE_B_MODE],[1],[Don't open files in binary mode.])], |
||||||
|
AC_MSG_RESULT(Assuming that it does.)) |
||||||
|
|
||||||
|
# Configure libtool |
||||||
|
AC_LIBTOOL_WIN32_DLL |
||||||
|
AC_PROG_LIBTOOL |
||||||
|
|
||||||
|
# Select memory manager depending on user input. |
||||||
|
# If no "-enable-maxmem", use jmemnobs |
||||||
|
MEMORYMGR='jmemnobs' |
||||||
|
MAXMEM="no" |
||||||
|
AC_ARG_ENABLE(maxmem, |
||||||
|
[ --enable-maxmem[=N] enable use of temp files, set max mem usage to N MB], |
||||||
|
MAXMEM="$enableval") |
||||||
|
dnl [# support --with-maxmem for backwards compatibility with IJG V5.] |
||||||
|
dnl 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}], [Maximum data space library will allocate.]) |
||||||
|
AC_MSG_CHECKING([for 'tmpfile()']) |
||||||
|
AC_TRY_LINK([#include <stdio.h>], [ FILE * tfile = tmpfile(); ], |
||||||
|
[AC_MSG_RESULT(yes) |
||||||
|
MEMORYMGR='jmemansi'], |
||||||
|
[AC_MSG_RESULT(no) |
||||||
|
dnl if tmpfile is not present, must use jmemname. |
||||||
|
MEMORYMGR='jmemname' |
||||||
|
|
||||||
|
# Test for the need to remove temporary files using a signal handler (for cjpeg/djpeg) |
||||||
|
AC_DEFINE([NEED_SIGNAL_CATCHER],[1],[Need signal handler to clean up temporary files.]) |
||||||
|
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],[1],[The mktemp() function is not available.])])]) |
||||||
|
fi |
||||||
|
AC_SUBST(MEMORYMGR) |
||||||
|
|
||||||
|
# Extract the library version IDs from jpeglib.h. |
||||||
|
AC_MSG_CHECKING([libjpeg version number]) |
||||||
|
[JPEG_LIB_VERSION_MAJOR=`sed -e '/^#define JPEG_LIB_VERSION_MAJOR/!d' -e 's/^[^0-9]*\([0-9][0-9]*\).*$/\1/' $srcdir/jpeglib.h`] |
||||||
|
[JPEG_LIB_VERSION_MINOR=`sed -e '/^#define JPEG_LIB_VERSION_MINOR/!d' -e 's/^[^0-9]*\([0-9][0-9]*\).*$/\1/' $srcdir/jpeglib.h`] |
||||||
|
[JPEG_LIB_VERSION="`expr $JPEG_LIB_VERSION_MAJOR + $JPEG_LIB_VERSION_MINOR`:0:$JPEG_LIB_VERSION_MINOR"] |
||||||
|
AC_MSG_RESULT([$JPEG_LIB_VERSION]) |
||||||
|
AC_SUBST([JPEG_LIB_VERSION]) |
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile]) |
||||||
|
AC_OUTPUT |
@ -0,0 +1,630 @@ |
|||||||
|
#! /bin/sh |
||||||
|
# depcomp - compile a program generating dependencies as side-effects |
||||||
|
|
||||||
|
scriptversion=2009-04-28.21; # UTC |
||||||
|
|
||||||
|
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free |
||||||
|
# Software Foundation, Inc. |
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2, or (at your option) |
||||||
|
# any later version. |
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you |
||||||
|
# distribute this file as part of a program that contains a |
||||||
|
# configuration script generated by Autoconf, you may include it under |
||||||
|
# the same distribution terms that you use for the rest of that program. |
||||||
|
|
||||||
|
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. |
||||||
|
|
||||||
|
case $1 in |
||||||
|
'') |
||||||
|
echo "$0: No command. Try \`$0 --help' for more information." 1>&2 |
||||||
|
exit 1; |
||||||
|
;; |
||||||
|
-h | --h*) |
||||||
|
cat <<\EOF |
||||||
|
Usage: depcomp [--help] [--version] PROGRAM [ARGS] |
||||||
|
|
||||||
|
Run PROGRAMS ARGS to compile a file, generating dependencies |
||||||
|
as side-effects. |
||||||
|
|
||||||
|
Environment variables: |
||||||
|
depmode Dependency tracking mode. |
||||||
|
source Source file read by `PROGRAMS ARGS'. |
||||||
|
object Object file output by `PROGRAMS ARGS'. |
||||||
|
DEPDIR directory where to store dependencies. |
||||||
|
depfile Dependency file to output. |
||||||
|
tmpdepfile Temporary file to use when outputing dependencies. |
||||||
|
libtool Whether libtool is used (yes/no). |
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>. |
||||||
|
EOF |
||||||
|
exit $? |
||||||
|
;; |
||||||
|
-v | --v*) |
||||||
|
echo "depcomp $scriptversion" |
||||||
|
exit $? |
||||||
|
;; |
||||||
|
esac |
||||||
|
|
||||||
|
if test -z "$depmode" || test -z "$source" || test -z "$object"; then |
||||||
|
echo "depcomp: Variables source, object and depmode must be set" 1>&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. |
||||||
|
depfile=${depfile-`echo "$object" | |
||||||
|
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} |
||||||
|
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} |
||||||
|
|
||||||
|
rm -f "$tmpdepfile" |
||||||
|
|
||||||
|
# Some modes work just like other modes, but use different flags. We |
||||||
|
# parameterize here, but still list the modes in the big case below, |
||||||
|
# to make depend.m4 easier to write. Note that we *cannot* use a case |
||||||
|
# here, because this file can only contain one case statement. |
||||||
|
if test "$depmode" = hp; then |
||||||
|
# HP compiler uses -M and no extra arg. |
||||||
|
gccflag=-M |
||||||
|
depmode=gcc |
||||||
|
fi |
||||||
|
|
||||||
|
if test "$depmode" = dashXmstdout; then |
||||||
|
# This is just like dashmstdout with a different argument. |
||||||
|
dashmflag=-xM |
||||||
|
depmode=dashmstdout |
||||||
|
fi |
||||||
|
|
||||||
|
cygpath_u="cygpath -u -f -" |
||||||
|
if test "$depmode" = msvcmsys; then |
||||||
|
# This is just like msvisualcpp but w/o cygpath translation. |
||||||
|
# Just convert the backslash-escaped backslashes to single forward |
||||||
|
# slashes to satisfy depend.m4 |
||||||
|
cygpath_u="sed s,\\\\\\\\,/,g" |
||||||
|
depmode=msvisualcpp |
||||||
|
fi |
||||||
|
|
||||||
|
case "$depmode" in |
||||||
|
gcc3) |
||||||
|
## gcc 3 implements dependency tracking that does exactly what |
||||||
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like |
||||||
|
## it if -MD -MP comes after the -MF stuff. Hmm. |
||||||
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon |
||||||
|
## the command line argument order; so add the flags where they |
||||||
|
## appear in depend2.am. Note that the slowdown incurred here |
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this. |
||||||
|
for arg |
||||||
|
do |
||||||
|
case $arg in |
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; |
||||||
|
*) set fnord "$@" "$arg" ;; |
||||||
|
esac |
||||||
|
shift # fnord |
||||||
|
shift # $arg |
||||||
|
done |
||||||
|
"$@" |
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
mv "$tmpdepfile" "$depfile" |
||||||
|
;; |
||||||
|
|
||||||
|
gcc) |
||||||
|
## There are various ways to get dependency output from gcc. Here's |
||||||
|
## why we pick this rather obscure method: |
||||||
|
## - Don't want to use -MD because we'd like the dependencies to end |
||||||
|
## up in a subdir. Having to rename by hand is ugly. |
||||||
|
## (We might end up doing this anyway to support other compilers.) |
||||||
|
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like |
||||||
|
## -MM, not -M (despite what the docs say). |
||||||
|
## - Using -M directly means running the compiler twice (even worse |
||||||
|
## than renaming). |
||||||
|
if test -z "$gccflag"; then |
||||||
|
gccflag=-MD, |
||||||
|
fi |
||||||
|
"$@" -Wp,"$gccflag$tmpdepfile" |
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
rm -f "$depfile" |
||||||
|
echo "$object : \\" > "$depfile" |
||||||
|
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz |
||||||
|
## The second -e expression handles DOS-style file names with drive letters. |
||||||
|
sed -e 's/^[^:]*: / /' \ |
||||||
|
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" |
||||||
|
## This next piece of magic avoids the `deleted header file' problem. |
||||||
|
## The problem is that when a header file which appears in a .P file |
||||||
|
## is deleted, the dependency causes make to die (because there is |
||||||
|
## typically no way to rebuild the header). We avoid this by adding |
||||||
|
## dummy dependencies for each header file. Too bad gcc doesn't do |
||||||
|
## this for us directly. |
||||||
|
tr ' ' ' |
||||||
|
' < "$tmpdepfile" | |
||||||
|
## Some versions of gcc put a space before the `:'. On the theory |
||||||
|
## that the space means something, we add a space to the output as |
||||||
|
## well. |
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation |
||||||
|
## correctly. Breaking it into two sed invocations is a workaround. |
||||||
|
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
hp) |
||||||
|
# This case exists only to let depend.m4 do its work. It works by |
||||||
|
# looking at the text of this script. This case will never be run, |
||||||
|
# since it is checked for above. |
||||||
|
exit 1 |
||||||
|
;; |
||||||
|
|
||||||
|
sgi) |
||||||
|
if test "$libtool" = yes; then |
||||||
|
"$@" "-Wp,-MDupdate,$tmpdepfile" |
||||||
|
else |
||||||
|
"$@" -MDupdate "$tmpdepfile" |
||||||
|
fi |
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
rm -f "$depfile" |
||||||
|
|
||||||
|
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files |
||||||
|
echo "$object : \\" > "$depfile" |
||||||
|
|
||||||
|
# Clip off the initial element (the dependent). Don't try to be |
||||||
|
# clever and replace this with sed code, as IRIX sed won't handle |
||||||
|
# lines with more than a fixed number of characters (4096 in |
||||||
|
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; |
||||||
|
# the IRIX cc adds comments like `#:fec' to the end of the |
||||||
|
# dependency line. |
||||||
|
tr ' ' ' |
||||||
|
' < "$tmpdepfile" \ |
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ |
||||||
|
tr ' |
||||||
|
' ' ' >> "$depfile" |
||||||
|
echo >> "$depfile" |
||||||
|
|
||||||
|
# The second pass generates a dummy entry for each header file. |
||||||
|
tr ' ' ' |
||||||
|
' < "$tmpdepfile" \ |
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ |
||||||
|
>> "$depfile" |
||||||
|
else |
||||||
|
# The sourcefile does not contain any dependencies, so just |
||||||
|
# store a dummy comment line, to avoid errors with the Makefile |
||||||
|
# "include basename.Plo" scheme. |
||||||
|
echo "#dummy" > "$depfile" |
||||||
|
fi |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
aix) |
||||||
|
# The C for AIX Compiler uses -M and outputs the dependencies |
||||||
|
# in a .u file. In older versions, this file always lives in the |
||||||
|
# current directory. Also, the AIX compiler puts `$object:' at the |
||||||
|
# start of each line; $object doesn't have directory information. |
||||||
|
# Version 6 uses the directory in both cases. |
||||||
|
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` |
||||||
|
test "x$dir" = "x$object" && dir= |
||||||
|
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` |
||||||
|
if test "$libtool" = yes; then |
||||||
|
tmpdepfile1=$dir$base.u |
||||||
|
tmpdepfile2=$base.u |
||||||
|
tmpdepfile3=$dir.libs/$base.u |
||||||
|
"$@" -Wc,-M |
||||||
|
else |
||||||
|
tmpdepfile1=$dir$base.u |
||||||
|
tmpdepfile2=$dir$base.u |
||||||
|
tmpdepfile3=$dir$base.u |
||||||
|
"$@" -M |
||||||
|
fi |
||||||
|
stat=$? |
||||||
|
|
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" |
||||||
|
do |
||||||
|
test -f "$tmpdepfile" && break |
||||||
|
done |
||||||
|
if test -f "$tmpdepfile"; then |
||||||
|
# Each line is of the form `foo.o: dependent.h'. |
||||||
|
# Do two passes, one to just change these to |
||||||
|
# `$object: dependent.h' and one to simply `dependent.h:'. |
||||||
|
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" |
||||||
|
# That's a tab and a space in the []. |
||||||
|
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" |
||||||
|
else |
||||||
|
# The sourcefile does not contain any dependencies, so just |
||||||
|
# store a dummy comment line, to avoid errors with the Makefile |
||||||
|
# "include basename.Plo" scheme. |
||||||
|
echo "#dummy" > "$depfile" |
||||||
|
fi |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
icc) |
||||||
|
# Intel's C compiler understands `-MD -MF file'. However on |
||||||
|
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c |
||||||
|
# ICC 7.0 will fill foo.d with something like |
||||||
|
# foo.o: sub/foo.c |
||||||
|
# foo.o: sub/foo.h |
||||||
|
# which is wrong. We want: |
||||||
|
# sub/foo.o: sub/foo.c |
||||||
|
# sub/foo.o: sub/foo.h |
||||||
|
# sub/foo.c: |
||||||
|
# sub/foo.h: |
||||||
|
# ICC 7.1 will output |
||||||
|
# foo.o: sub/foo.c sub/foo.h |
||||||
|
# and will wrap long lines using \ : |
||||||
|
# foo.o: sub/foo.c ... \ |
||||||
|
# sub/foo.h ... \ |
||||||
|
# ... |
||||||
|
|
||||||
|
"$@" -MD -MF "$tmpdepfile" |
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
rm -f "$depfile" |
||||||
|
# Each line is of the form `foo.o: dependent.h', |
||||||
|
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. |
||||||
|
# Do two passes, one to just change these to |
||||||
|
# `$object: dependent.h' and one to simply `dependent.h:'. |
||||||
|
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" |
||||||
|
# Some versions of the HPUX 10.20 sed can't process this invocation |
||||||
|
# correctly. Breaking it into two sed invocations is a workaround. |
||||||
|
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | |
||||||
|
sed -e 's/$/ :/' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
hp2) |
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64 |
||||||
|
# compilers, which have integrated preprocessors. The correct option |
||||||
|
# to use with these is +Maked; it writes dependencies to a file named |
||||||
|
# 'foo.d', which lands next to the object file, wherever that |
||||||
|
# happens to be. |
||||||
|
# Much of this is similar to the tru64 case; see comments there. |
||||||
|
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` |
||||||
|
test "x$dir" = "x$object" && dir= |
||||||
|
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` |
||||||
|
if test "$libtool" = yes; then |
||||||
|
tmpdepfile1=$dir$base.d |
||||||
|
tmpdepfile2=$dir.libs/$base.d |
||||||
|
"$@" -Wc,+Maked |
||||||
|
else |
||||||
|
tmpdepfile1=$dir$base.d |
||||||
|
tmpdepfile2=$dir$base.d |
||||||
|
"$@" +Maked |
||||||
|
fi |
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" |
||||||
|
do |
||||||
|
test -f "$tmpdepfile" && break |
||||||
|
done |
||||||
|
if test -f "$tmpdepfile"; then |
||||||
|
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" |
||||||
|
# Add `dependent.h:' lines. |
||||||
|
sed -ne '2,${ |
||||||
|
s/^ *// |
||||||
|
s/ \\*$// |
||||||
|
s/$/:/ |
||||||
|
p |
||||||
|
}' "$tmpdepfile" >> "$depfile" |
||||||
|
else |
||||||
|
echo "#dummy" > "$depfile" |
||||||
|
fi |
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2" |
||||||
|
;; |
||||||
|
|
||||||
|
tru64) |
||||||
|
# The Tru64 compiler uses -MD to generate dependencies as a side |
||||||
|
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. |
||||||
|
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put |
||||||
|
# dependencies in `foo.d' instead, so we check for that too. |
||||||
|
# Subdirectories are respected. |
||||||
|
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` |
||||||
|
test "x$dir" = "x$object" && dir= |
||||||
|
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` |
||||||
|
|
||||||
|
if test "$libtool" = yes; then |
||||||
|
# With Tru64 cc, shared objects can also be used to make a |
||||||
|
# static library. This mechanism is used in libtool 1.4 series to |
||||||
|
# handle both shared and static libraries in a single compilation. |
||||||
|
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. |
||||||
|
# |
||||||
|
# With libtool 1.5 this exception was removed, and libtool now |
||||||
|
# generates 2 separate objects for the 2 libraries. These two |
||||||
|
# compilations output dependencies in $dir.libs/$base.o.d and |
||||||
|
# in $dir$base.o.d. We have to check for both files, because |
||||||
|
# one of the two compilations can be disabled. We should prefer |
||||||
|
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is |
||||||
|
# automatically cleaned when .libs/ is deleted, while ignoring |
||||||
|
# the former would cause a distcleancheck panic. |
||||||
|
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 |
||||||
|
tmpdepfile2=$dir$base.o.d # libtool 1.5 |
||||||
|
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 |
||||||
|
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 |
||||||
|
"$@" -Wc,-MD |
||||||
|
else |
||||||
|
tmpdepfile1=$dir$base.o.d |
||||||
|
tmpdepfile2=$dir$base.d |
||||||
|
tmpdepfile3=$dir$base.d |
||||||
|
tmpdepfile4=$dir$base.d |
||||||
|
"$@" -MD |
||||||
|
fi |
||||||
|
|
||||||
|
stat=$? |
||||||
|
if test $stat -eq 0; then : |
||||||
|
else |
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" |
||||||
|
exit $stat |
||||||
|
fi |
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" |
||||||
|
do |
||||||
|
test -f "$tmpdepfile" && break |
||||||
|
done |
||||||
|
if test -f "$tmpdepfile"; then |
||||||
|
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" |
||||||
|
# That's a tab and a space in the []. |
||||||
|
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" |
||||||
|
else |
||||||
|
echo "#dummy" > "$depfile" |
||||||
|
fi |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
#nosideeffect) |
||||||
|
# This comment above is used by automake to tell side-effect |
||||||
|
# dependency tracking mechanisms from slower ones. |
||||||
|
|
||||||
|
dashmstdout) |
||||||
|
# Important note: in order to support this mode, a compiler *must* |
||||||
|
# always write the preprocessed file to stdout, regardless of -o. |
||||||
|
"$@" || exit $? |
||||||
|
|
||||||
|
# Remove the call to Libtool. |
||||||
|
if test "$libtool" = yes; then |
||||||
|
while test "X$1" != 'X--mode=compile'; do |
||||||
|
shift |
||||||
|
done |
||||||
|
shift |
||||||
|
fi |
||||||
|
|
||||||
|
# Remove `-o $object'. |
||||||
|
IFS=" " |
||||||
|
for arg |
||||||
|
do |
||||||
|
case $arg in |
||||||
|
-o) |
||||||
|
shift |
||||||
|
;; |
||||||
|
$object) |
||||||
|
shift |
||||||
|
;; |
||||||
|
*) |
||||||
|
set fnord "$@" "$arg" |
||||||
|
shift # fnord |
||||||
|
shift # $arg |
||||||
|
;; |
||||||
|
esac |
||||||
|
done |
||||||
|
|
||||||
|
test -z "$dashmflag" && dashmflag=-M |
||||||
|
# Require at least two characters before searching for `:' |
||||||
|
# in the target name. This is to cope with DOS-style filenames: |
||||||
|
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. |
||||||
|
"$@" $dashmflag | |
||||||
|
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" |
||||||
|
rm -f "$depfile" |
||||||
|
cat < "$tmpdepfile" > "$depfile" |
||||||
|
tr ' ' ' |
||||||
|
' < "$tmpdepfile" | \ |
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation |
||||||
|
## correctly. Breaking it into two sed invocations is a workaround. |
||||||
|
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
dashXmstdout) |
||||||
|
# This case only exists to satisfy depend.m4. It is never actually |
||||||
|
# run, as this mode is specially recognized in the preamble. |
||||||
|
exit 1 |
||||||
|
;; |
||||||
|
|
||||||
|
makedepend) |
||||||
|
"$@" || exit $? |
||||||
|
# Remove any Libtool call |
||||||
|
if test "$libtool" = yes; then |
||||||
|
while test "X$1" != 'X--mode=compile'; do |
||||||
|
shift |
||||||
|
done |
||||||
|
shift |
||||||
|
fi |
||||||
|
# X makedepend |
||||||
|
shift |
||||||
|
cleared=no eat=no |
||||||
|
for arg |
||||||
|
do |
||||||
|
case $cleared in |
||||||
|
no) |
||||||
|
set ""; shift |
||||||
|
cleared=yes ;; |
||||||
|
esac |
||||||
|
if test $eat = yes; then |
||||||
|
eat=no |
||||||
|
continue |
||||||
|
fi |
||||||
|
case "$arg" in |
||||||
|
-D*|-I*) |
||||||
|
set fnord "$@" "$arg"; shift ;; |
||||||
|
# Strip any option that makedepend may not understand. Remove |
||||||
|
# the object too, otherwise makedepend will parse it as a source file. |
||||||
|
-arch) |
||||||
|
eat=yes ;; |
||||||
|
-*|$object) |
||||||
|
;; |
||||||
|
*) |
||||||
|
set fnord "$@" "$arg"; shift ;; |
||||||
|
esac |
||||||
|
done |
||||||
|
obj_suffix=`echo "$object" | sed 's/^.*\././'` |
||||||
|
touch "$tmpdepfile" |
||||||
|
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" |
||||||
|
rm -f "$depfile" |
||||||
|
cat < "$tmpdepfile" > "$depfile" |
||||||
|
sed '1,2d' "$tmpdepfile" | tr ' ' ' |
||||||
|
' | \ |
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation |
||||||
|
## correctly. Breaking it into two sed invocations is a workaround. |
||||||
|
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile".bak |
||||||
|
;; |
||||||
|
|
||||||
|
cpp) |
||||||
|
# Important note: in order to support this mode, a compiler *must* |
||||||
|
# always write the preprocessed file to stdout. |
||||||
|
"$@" || exit $? |
||||||
|
|
||||||
|
# Remove the call to Libtool. |
||||||
|
if test "$libtool" = yes; then |
||||||
|
while test "X$1" != 'X--mode=compile'; do |
||||||
|
shift |
||||||
|
done |
||||||
|
shift |
||||||
|
fi |
||||||
|
|
||||||
|
# Remove `-o $object'. |
||||||
|
IFS=" " |
||||||
|
for arg |
||||||
|
do |
||||||
|
case $arg in |
||||||
|
-o) |
||||||
|
shift |
||||||
|
;; |
||||||
|
$object) |
||||||
|
shift |
||||||
|
;; |
||||||
|
*) |
||||||
|
set fnord "$@" "$arg" |
||||||
|
shift # fnord |
||||||
|
shift # $arg |
||||||
|
;; |
||||||
|
esac |
||||||
|
done |
||||||
|
|
||||||
|
"$@" -E | |
||||||
|
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ |
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | |
||||||
|
sed '$ s: \\$::' > "$tmpdepfile" |
||||||
|
rm -f "$depfile" |
||||||
|
echo "$object : \\" > "$depfile" |
||||||
|
cat < "$tmpdepfile" >> "$depfile" |
||||||
|
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
msvisualcpp) |
||||||
|
# Important note: in order to support this mode, a compiler *must* |
||||||
|
# always write the preprocessed file to stdout. |
||||||
|
"$@" || exit $? |
||||||
|
|
||||||
|
# Remove the call to Libtool. |
||||||
|
if test "$libtool" = yes; then |
||||||
|
while test "X$1" != 'X--mode=compile'; do |
||||||
|
shift |
||||||
|
done |
||||||
|
shift |
||||||
|
fi |
||||||
|
|
||||||
|
IFS=" " |
||||||
|
for arg |
||||||
|
do |
||||||
|
case "$arg" in |
||||||
|
-o) |
||||||
|
shift |
||||||
|
;; |
||||||
|
$object) |
||||||
|
shift |
||||||
|
;; |
||||||
|
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") |
||||||
|
set fnord "$@" |
||||||
|
shift |
||||||
|
shift |
||||||
|
;; |
||||||
|
*) |
||||||
|
set fnord "$@" "$arg" |
||||||
|
shift |
||||||
|
shift |
||||||
|
;; |
||||||
|
esac |
||||||
|
done |
||||||
|
"$@" -E 2>/dev/null | |
||||||
|
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" |
||||||
|
rm -f "$depfile" |
||||||
|
echo "$object : \\" > "$depfile" |
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" |
||||||
|
echo " " >> "$depfile" |
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" |
||||||
|
rm -f "$tmpdepfile" |
||||||
|
;; |
||||||
|
|
||||||
|
msvcmsys) |
||||||
|
# This case exists only to let depend.m4 do its work. It works by |
||||||
|
# looking at the text of this script. This case will never be run, |
||||||
|
# since it is checked for above. |
||||||
|
exit 1 |
||||||
|
;; |
||||||
|
|
||||||
|
none) |
||||||
|
exec "$@" |
||||||
|
;; |
||||||
|
|
||||||
|
*) |
||||||
|
echo "Unknown depmode $depmode" 1>&2 |
||||||
|
exit 1 |
||||||
|
;; |
||||||
|
esac |
||||||
|
|
||||||
|
exit 0 |
||||||
|
|
||||||
|
# Local Variables: |
||||||
|
# mode: shell-script |
||||||
|
# sh-indentation: 2 |
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp) |
||||||
|
# time-stamp-start: "scriptversion=" |
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H" |
||||||
|
# time-stamp-time-zone: "UTC" |
||||||
|
# time-stamp-end: "; # UTC" |
||||||
|
# End: |
@ -0,0 +1,252 @@ |
|||||||
|
.TH DJPEG 1 "3 October 2009" |
||||||
|
.SH NAME |
||||||
|
djpeg \- decompress a JPEG file to an image file |
||||||
|
.SH SYNOPSIS |
||||||
|
.B djpeg |
||||||
|
[ |
||||||
|
.I options |
||||||
|
] |
||||||
|
[ |
||||||
|
.I filename |
||||||
|
] |
||||||
|
.LP |
||||||
|
.SH DESCRIPTION |
||||||
|
.LP |
||||||
|
.B djpeg |
||||||
|
decompresses the named JPEG file, or the standard input if no file is named, |
||||||
|
and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP, |
||||||
|
GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected. |
||||||
|
(RLE is supported only if the URT library is available.) |
||||||
|
.SH OPTIONS |
||||||
|
All switch names may be abbreviated; for example, |
||||||
|
.B \-grayscale |
||||||
|
may be written |
||||||
|
.B \-gray |
||||||
|
or |
||||||
|
.BR \-gr . |
||||||
|
Most of the "basic" switches can be abbreviated to as little as one letter. |
||||||
|
Upper and lower case are equivalent (thus |
||||||
|
.B \-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 |
||||||
|
.BI \-colors " N" |
||||||
|
Reduce image to at most N colors. This reduces the number of colors used in |
||||||
|
the output image, so that it can be displayed on a colormapped display or |
||||||
|
stored in a colormapped file format. For example, if you have an 8-bit |
||||||
|
display, you'd need to reduce to 256 or fewer colors. |
||||||
|
.TP |
||||||
|
.BI \-quantize " N" |
||||||
|
Same as |
||||||
|
.BR \-colors . |
||||||
|
.B \-colors |
||||||
|
is the recommended name, |
||||||
|
.B \-quantize |
||||||
|
is provided only for backwards compatibility. |
||||||
|
.TP |
||||||
|
.B \-fast |
||||||
|
Select recommended processing options for fast, low quality output. (The |
||||||
|
default options are chosen for highest quality output.) Currently, this is |
||||||
|
equivalent to \fB\-dct fast \-nosmooth \-onepass \-dither ordered\fR. |
||||||
|
.TP |
||||||
|
.B \-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 supported scale factors are |
||||||
|
M/N with all M from 1 to 16, where N is the source DCT size, which is 8 for |
||||||
|
baseline JPEG. If the /N part is omitted, then M specifies the DCT scaled |
||||||
|
size to be applied on the given input. For baseline JPEG this is equivalent |
||||||
|
to M/8 scaling, since the source DCT size for baseline JPEG is 8. |
||||||
|
Scaling is handy if the image is larger than your screen; also, |
||||||
|
.B djpeg |
||||||
|
runs much faster when scaling down the output. |
||||||
|
.TP |
||||||
|
.B \-bmp |
||||||
|
Select BMP output format (Windows flavor). 8-bit colormapped format is |
||||||
|
emitted if |
||||||
|
.B \-colors |
||||||
|
or |
||||||
|
.B \-grayscale |
||||||
|
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color |
||||||
|
format is emitted. |
||||||
|
.TP |
||||||
|
.B \-gif |
||||||
|
Select GIF output format. Since GIF does not support more than 256 colors, |
||||||
|
.B \-colors 256 |
||||||
|
is assumed (unless you specify a smaller number of colors). |
||||||
|
.TP |
||||||
|
.B \-os2 |
||||||
|
Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is |
||||||
|
emitted if |
||||||
|
.B \-colors |
||||||
|
or |
||||||
|
.B \-grayscale |
||||||
|
is specified, or if the JPEG file is gray-scale; otherwise, 24-bit full-color |
||||||
|
format is emitted. |
||||||
|
.TP |
||||||
|
.B \-pnm |
||||||
|
Select PBMPLUS (PPM/PGM) output format (this is the default format). |
||||||
|
PGM is emitted if the JPEG file is gray-scale or if |
||||||
|
.B \-grayscale |
||||||
|
is specified; otherwise PPM is emitted. |
||||||
|
.TP |
||||||
|
.B \-rle |
||||||
|
Select RLE output format. (Requires URT library.) |
||||||
|
.TP |
||||||
|
.B \-targa |
||||||
|
Select Targa output format. Gray-scale format is emitted if the JPEG file is |
||||||
|
gray-scale or if |
||||||
|
.B \-grayscale |
||||||
|
is specified; otherwise, colormapped format is emitted if |
||||||
|
.B \-colors |
||||||
|
is specified; otherwise, 24-bit full-color format is emitted. |
||||||
|
.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 |
||||||
|
.B \-dither fs |
||||||
|
Use Floyd-Steinberg dithering in color quantization. |
||||||
|
.TP |
||||||
|
.B \-dither ordered |
||||||
|
Use ordered dithering in color quantization. |
||||||
|
.TP |
||||||
|
.B \-dither none |
||||||
|
Do not use dithering in color quantization. |
||||||
|
By default, Floyd-Steinberg dithering is applied when quantizing colors; this |
||||||
|
is slow but usually produces the best results. Ordered dither is a compromise |
||||||
|
between speed and quality; no dithering is fast but usually looks awful. Note |
||||||
|
that these switches have no effect unless color quantization is being done. |
||||||
|
Ordered dither is only available in |
||||||
|
.B \-onepass |
||||||
|
mode. |
||||||
|
.TP |
||||||
|
.BI \-map " file" |
||||||
|
Quantize to the colors used in the specified image file. This is useful for |
||||||
|
producing multiple files with identical color maps, or for forcing a |
||||||
|
predefined set of colors to be used. The |
||||||
|
.I file |
||||||
|
must be a GIF or PPM file. This option overrides |
||||||
|
.B \-colors |
||||||
|
and |
||||||
|
.BR \-onepass . |
||||||
|
.TP |
||||||
|
.B \-nosmooth |
||||||
|
Don't use high-quality upsampling. |
||||||
|
.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 |
||||||
|
.BR \-v 's |
||||||
|
give more output. Also, version information is printed at startup. |
||||||
|
.TP |
||||||
|
.B \-debug |
||||||
|
Same as |
||||||
|
.BR \-verbose . |
||||||
|
.SH EXAMPLES |
||||||
|
.LP |
||||||
|
This example decompresses the JPEG file foo.jpg, quantizes it to |
||||||
|
256 colors, and saves the output in 8-bit BMP format in foo.bmp: |
||||||
|
.IP |
||||||
|
.B djpeg \-colors 256 \-bmp |
||||||
|
.I foo.jpg |
||||||
|
.B > |
||||||
|
.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 |
||||||
|
.BR cjpeg (1), |
||||||
|
.BR jpegtran (1), |
||||||
|
.BR rdjpgcom (1), |
||||||
|
.BR wrjpgcom (1) |
||||||
|
.br |
||||||
|
.BR ppm (5), |
||||||
|
.BR pgm (5) |
||||||
|
.br |
||||||
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard", |
||||||
|
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. |
||||||
|
.SH AUTHOR |
||||||
|
Independent JPEG Group |
||||||
|
.SH BUGS |
||||||
|
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. |
@ -0,0 +1,617 @@ |
|||||||
|
/*
|
||||||
|
* djpeg.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane. |
||||||
|
* Modified 2009 by Guido Vollbeding. |
||||||
|
* This file is part of the Independent JPEG Group's software. |
||||||
|
* For conditions of distribution and use, see the accompanying README file. |
||||||
|
* |
||||||
|
* This file contains a command-line user interface for the JPEG decompressor. |
||||||
|
* It should work on any system with Unix- or MS-DOS-style command lines. |
||||||
|
* |
||||||
|
* Two different command line styles are permitted, depending on the |
||||||
|
* compile-time switch TWO_FILE_COMMANDLINE: |
||||||
|
* djpeg [options] inputfile outputfile |
||||||
|
* djpeg [options] [inputfile] |
||||||
|
* In the second style, output is always to standard output, which you'd |
||||||
|
* normally redirect to a file or pipe to some other program. Input is |
||||||
|
* either from a named file or from standard input (typically redirected). |
||||||
|
* The second style is convenient on Unix but is unhelpful on systems that |
||||||
|
* don't support pipes. Also, you MUST use the first style if your system |
||||||
|
* doesn't do binary I/O to stdin/stdout. |
||||||
|
* To simplify script writing, the "-outfile" switch is provided. The syntax |
||||||
|
* djpeg [options] -outfile outputfile inputfile |
||||||
|
* works regardless of which command line style is used. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ |
||||||
|
#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); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int) |
||||||
|
parse_switches (j_decompress_ptr cinfo, int argc, char **argv, |
||||||
|
int last_file_arg_seen, boolean for_real) |
||||||
|
/* Parse optional switches.
|
||||||
|
* Returns argv[] index of first file-name argument (== argc if none). |
||||||
|
* Any file names with indexes <= last_file_arg_seen are ignored; |
||||||
|
* they have presumably been processed in a previous iteration. |
||||||
|
* (Pass 0 for last_file_arg_seen on the first or only iteration.) |
||||||
|
* for_real is FALSE on the first (dummy) pass; we may skip any expensive |
||||||
|
* processing. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
int argn; |
||||||
|
char * arg; |
||||||
|
|
||||||
|
/* Set up default JPEG parameters. */ |
||||||
|
requested_fmt = DEFAULT_FMT; /* set default output file format */ |
||||||
|
outfilename = NULL; |
||||||
|
cinfo->err->trace_level = 0; |
||||||
|
|
||||||
|
/* Scan command line options, adjust parameters */ |
||||||
|
|
||||||
|
for (argn = 1; argn < argc; argn++) { |
||||||
|
arg = argv[argn]; |
||||||
|
if (*arg != '-') { |
||||||
|
/* Not a switch, must be a file name argument */ |
||||||
|
if (argn <= last_file_arg_seen) { |
||||||
|
outfilename = NULL; /* -outfile applies to just one input file */ |
||||||
|
continue; /* ignore this name if previously processed */ |
||||||
|
} |
||||||
|
break; /* else done parsing switches */ |
||||||
|
} |
||||||
|
arg++; /* advance past switch marker character */ |
||||||
|
|
||||||
|
if (keymatch(arg, "bmp", 1)) { |
||||||
|
/* BMP output format. */ |
||||||
|
requested_fmt = FMT_BMP; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || |
||||||
|
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { |
||||||
|
/* Do color quantization. */ |
||||||
|
int val; |
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (sscanf(argv[argn], "%d", &val) != 1) |
||||||
|
usage(); |
||||||
|
cinfo->desired_number_of_colors = val; |
||||||
|
cinfo->quantize_colors = TRUE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "dct", 2)) { |
||||||
|
/* Select IDCT algorithm. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (keymatch(argv[argn], "int", 1)) { |
||||||
|
cinfo->dct_method = JDCT_ISLOW; |
||||||
|
} else if (keymatch(argv[argn], "fast", 2)) { |
||||||
|
cinfo->dct_method = JDCT_IFAST; |
||||||
|
} else if (keymatch(argv[argn], "float", 2)) { |
||||||
|
cinfo->dct_method = JDCT_FLOAT; |
||||||
|
} else |
||||||
|
usage(); |
||||||
|
|
||||||
|
} else if (keymatch(arg, "dither", 2)) { |
||||||
|
/* Select dithering algorithm. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (keymatch(argv[argn], "fs", 2)) { |
||||||
|
cinfo->dither_mode = JDITHER_FS; |
||||||
|
} else if (keymatch(argv[argn], "none", 2)) { |
||||||
|
cinfo->dither_mode = JDITHER_NONE; |
||||||
|
} else if (keymatch(argv[argn], "ordered", 2)) { |
||||||
|
cinfo->dither_mode = JDITHER_ORDERED; |
||||||
|
} else |
||||||
|
usage(); |
||||||
|
|
||||||
|
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { |
||||||
|
/* Enable debug printouts. */ |
||||||
|
/* On first -d, print version identification */ |
||||||
|
static boolean printed_version = FALSE; |
||||||
|
|
||||||
|
if (! printed_version) { |
||||||
|
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", |
||||||
|
JVERSION, JCOPYRIGHT); |
||||||
|
printed_version = TRUE; |
||||||
|
} |
||||||
|
cinfo->err->trace_level++; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "fast", 1)) { |
||||||
|
/* Select recommended processing options for quick-and-dirty output. */ |
||||||
|
cinfo->two_pass_quantize = FALSE; |
||||||
|
cinfo->dither_mode = JDITHER_ORDERED; |
||||||
|
if (! cinfo->quantize_colors) /* don't override an earlier -colors */ |
||||||
|
cinfo->desired_number_of_colors = 216; |
||||||
|
cinfo->dct_method = JDCT_FASTEST; |
||||||
|
cinfo->do_fancy_upsampling = FALSE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "gif", 1)) { |
||||||
|
/* GIF output format. */ |
||||||
|
requested_fmt = FMT_GIF; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { |
||||||
|
/* Force monochrome output. */ |
||||||
|
cinfo->out_color_space = JCS_GRAYSCALE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "map", 3)) { |
||||||
|
/* Quantize to a color map taken from an input file. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (for_real) { /* too expensive to do twice! */ |
||||||
|
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ |
||||||
|
FILE * mapfile; |
||||||
|
|
||||||
|
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { |
||||||
|
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
read_color_map(cinfo, mapfile); |
||||||
|
fclose(mapfile); |
||||||
|
cinfo->quantize_colors = TRUE; |
||||||
|
#else |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
} else if (keymatch(arg, "maxmemory", 3)) { |
||||||
|
/* Maximum memory in Kb (or Mb with 'm'). */ |
||||||
|
long lval; |
||||||
|
char ch = 'x'; |
||||||
|
|
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) |
||||||
|
usage(); |
||||||
|
if (ch == 'm' || ch == 'M') |
||||||
|
lval *= 1000L; |
||||||
|
cinfo->mem->max_memory_to_use = lval * 1000L; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "nosmooth", 3)) { |
||||||
|
/* Suppress fancy upsampling */ |
||||||
|
cinfo->do_fancy_upsampling = FALSE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "onepass", 3)) { |
||||||
|
/* Use fast one-pass quantization. */ |
||||||
|
cinfo->two_pass_quantize = FALSE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "os2", 3)) { |
||||||
|
/* BMP output format (OS/2 flavor). */ |
||||||
|
requested_fmt = FMT_OS2; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "outfile", 4)) { |
||||||
|
/* Set output file name. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
outfilename = argv[argn]; /* save it away for later use */ |
||||||
|
|
||||||
|
} else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { |
||||||
|
/* PPM/PGM output format. */ |
||||||
|
requested_fmt = FMT_PPM; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "rle", 1)) { |
||||||
|
/* RLE output format. */ |
||||||
|
requested_fmt = FMT_RLE; |
||||||
|
|
||||||
|
} else if (keymatch(arg, "scale", 1)) { |
||||||
|
/* Scale the output image by a fraction M/N. */ |
||||||
|
if (++argn >= argc) /* advance to next argument */ |
||||||
|
usage(); |
||||||
|
if (sscanf(argv[argn], "%d/%d", |
||||||
|
&cinfo->scale_num, &cinfo->scale_denom) < 1) |
||||||
|
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 */ |
||||||
|
} |
@ -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.txt. |
||||||
|
* |
||||||
|
* 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.txt. |
||||||
|
* |
||||||
|
* 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.txt 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.txt 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.txt 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.txt. |
||||||
|
*/ |
@ -0,0 +1,215 @@ |
|||||||
|
IJG JPEG LIBRARY: FILE LIST |
||||||
|
|
||||||
|
Copyright (C) 1994-2009, Thomas G. Lane, Guido Vollbeding. |
||||||
|
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. |
||||||
|
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. |
||||||
|
jcarith.c Arithmetic entropy coding. |
||||||
|
jcmarker.c JPEG marker writing. |
||||||
|
jdatadst.c Data destination managers for memory and 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. |
||||||
|
jdarith.c Arithmetic entropy decoding. |
||||||
|
jddctmgr.c IDCT manager (IDCT implementation selection & control). |
||||||
|
jidctint.c Inverse DCT using slow-but-accurate integer method. |
||||||
|
jidctfst.c Inverse DCT using faster, less accurate integer method. |
||||||
|
jidctflt.c Inverse DCT using floating-point arithmetic. |
||||||
|
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 managers for memory and stdio input. |
||||||
|
|
||||||
|
Support files for both compression and decompression: |
||||||
|
|
||||||
|
jaricom.c Tables for common use in arithmetic entropy encoding and |
||||||
|
decoding routines. |
||||||
|
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.txt 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. |
||||||
|
*.txt 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.txt for more info): |
||||||
|
|
||||||
|
configure Unix shell script to perform automatic configuration. |
||||||
|
configure.ac Source file for use with Autoconf to generate configure. |
||||||
|
ltmain.sh Support scripts for configure (from GNU libtool). |
||||||
|
config.guess |
||||||
|
config.sub |
||||||
|
depcomp |
||||||
|
missing |
||||||
|
install-sh Install shell script for those Unix systems lacking one. |
||||||
|
Makefile.in Makefile input for configure. |
||||||
|
Makefile.am Source file for use with Automake to generate Makefile.in. |
||||||
|
ckconfig.c Program to generate jconfig.h on non-Unix systems. |
||||||
|
jconfig.txt Template for making jconfig.h by hand. |
||||||
|
mak*.* Sample makefiles for particular systems. |
||||||
|
jconfig.* Sample jconfig.h for particular systems. |
||||||
|
libjpeg.map Script to generate shared library with versioned symbols. |
||||||
|
aclocal.m4 M4 macro definitions for use with Autoconf. |
||||||
|
ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of |
||||||
|
L. Peter Deutsch and Aladdin Enterprises). |
||||||
|
|
||||||
|
Test files (see install.txt for test procedure): |
||||||
|
|
||||||
|
test*.* Source and comparison files for confidence test. |
||||||
|
These are binary image files, NOT text files. |
@ -0,0 +1,520 @@ |
|||||||
|
#!/bin/sh |
||||||
|
# install - install a program, script, or datafile |
||||||
|
|
||||||
|
scriptversion=2009-04-28.21; # UTC |
||||||
|
|
||||||
|
# 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. |
||||||
|
|
||||||
|
nl=' |
||||||
|
' |
||||||
|
IFS=" "" $nl" |
||||||
|
|
||||||
|
# set DOITPROG to echo to test this script |
||||||
|
|
||||||
|
# Don't use :- since 4.3BSD and earlier shells don't like it. |
||||||
|
doit=${DOITPROG-} |
||||||
|
if test -z "$doit"; then |
||||||
|
doit_exec=exec |
||||||
|
else |
||||||
|
doit_exec=$doit |
||||||
|
fi |
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path; |
||||||
|
# or use environment vars. |
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp} |
||||||
|
chmodprog=${CHMODPROG-chmod} |
||||||
|
chownprog=${CHOWNPROG-chown} |
||||||
|
cmpprog=${CMPPROG-cmp} |
||||||
|
cpprog=${CPPROG-cp} |
||||||
|
mkdirprog=${MKDIRPROG-mkdir} |
||||||
|
mvprog=${MVPROG-mv} |
||||||
|
rmprog=${RMPROG-rm} |
||||||
|
stripprog=${STRIPPROG-strip} |
||||||
|
|
||||||
|
posix_glob='?' |
||||||
|
initialize_posix_glob=' |
||||||
|
test "$posix_glob" != "?" || { |
||||||
|
if (set -f) 2>/dev/null; then |
||||||
|
posix_glob= |
||||||
|
else |
||||||
|
posix_glob=: |
||||||
|
fi |
||||||
|
} |
||||||
|
' |
||||||
|
|
||||||
|
posix_mkdir= |
||||||
|
|
||||||
|
# Desired mode of installed file. |
||||||
|
mode=0755 |
||||||
|
|
||||||
|
chgrpcmd= |
||||||
|
chmodcmd=$chmodprog |
||||||
|
chowncmd= |
||||||
|
mvcmd=$mvprog |
||||||
|
rmcmd="$rmprog -f" |
||||||
|
stripcmd= |
||||||
|
|
||||||
|
src= |
||||||
|
dst= |
||||||
|
dir_arg= |
||||||
|
dst_arg= |
||||||
|
|
||||||
|
copy_on_change=false |
||||||
|
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: |
||||||
|
--help display this help and exit. |
||||||
|
--version display version info and exit. |
||||||
|
|
||||||
|
-c (ignored) |
||||||
|
-C install only if different (preserve the last data modification time) |
||||||
|
-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. |
||||||
|
|
||||||
|
Environment variables override the default commands: |
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG |
||||||
|
RMPROG STRIPPROG |
||||||
|
" |
||||||
|
|
||||||
|
while test $# -ne 0; do |
||||||
|
case $1 in |
||||||
|
-c) ;; |
||||||
|
|
||||||
|
-C) copy_on_change=true;; |
||||||
|
|
||||||
|
-d) dir_arg=true;; |
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2" |
||||||
|
shift;; |
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;; |
||||||
|
|
||||||
|
-m) mode=$2 |
||||||
|
case $mode in |
||||||
|
*' '* | *' '* | *' |
||||||
|
'* | *'*'* | *'?'* | *'['*) |
||||||
|
echo "$0: invalid mode: $mode" >&2 |
||||||
|
exit 1;; |
||||||
|
esac |
||||||
|
shift;; |
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2" |
||||||
|
shift;; |
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;; |
||||||
|
|
||||||
|
-t) dst_arg=$2 |
||||||
|
shift;; |
||||||
|
|
||||||
|
-T) no_target_directory=true;; |
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;; |
||||||
|
|
||||||
|
--) shift |
||||||
|
break;; |
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2 |
||||||
|
exit 1;; |
||||||
|
|
||||||
|
*) break;; |
||||||
|
esac |
||||||
|
shift |
||||||
|
done |
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then |
||||||
|
# When -d is used, all remaining arguments are directories to create. |
||||||
|
# When -t is used, the destination is already specified. |
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@. |
||||||
|
for arg |
||||||
|
do |
||||||
|
if test -n "$dst_arg"; then |
||||||
|
# $@ is not empty: it contains at least $arg. |
||||||
|
set fnord "$@" "$dst_arg" |
||||||
|
shift # fnord |
||||||
|
fi |
||||||
|
shift # arg |
||||||
|
dst_arg=$arg |
||||||
|
done |
||||||
|
fi |
||||||
|
|
||||||
|
if test $# -eq 0; 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 |
||||||
|
|
||||||
|
if test -z "$dir_arg"; then |
||||||
|
trap '(exit $?); exit' 1 2 13 15 |
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes. |
||||||
|
# However, 'strip' requires both read and write access to temps. |
||||||
|
case $mode in |
||||||
|
# Optimize common cases. |
||||||
|
*644) cp_umask=133;; |
||||||
|
*755) cp_umask=22;; |
||||||
|
|
||||||
|
*[0-7]) |
||||||
|
if test -z "$stripcmd"; then |
||||||
|
u_plus_rw= |
||||||
|
else |
||||||
|
u_plus_rw='% 200' |
||||||
|
fi |
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; |
||||||
|
*) |
||||||
|
if test -z "$stripcmd"; then |
||||||
|
u_plus_rw= |
||||||
|
else |
||||||
|
u_plus_rw=,u+rw |
||||||
|
fi |
||||||
|
cp_umask=$mode$u_plus_rw;; |
||||||
|
esac |
||||||
|
fi |
||||||
|
|
||||||
|
for src |
||||||
|
do |
||||||
|
# Protect names starting with `-'. |
||||||
|
case $src in |
||||||
|
-*) src=./$src;; |
||||||
|
esac |
||||||
|
|
||||||
|
if test -n "$dir_arg"; then |
||||||
|
dst=$src |
||||||
|
dstdir=$dst |
||||||
|
test -d "$dstdir" |
||||||
|
dstdir_status=$? |
||||||
|
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 "$dst_arg"; then |
||||||
|
echo "$0: no destination specified." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
dst=$dst_arg |
||||||
|
# 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: $dst_arg: Is a directory" >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
dstdir=$dst |
||||||
|
dst=$dstdir/`basename "$src"` |
||||||
|
dstdir_status=0 |
||||||
|
else |
||||||
|
# Prefer dirname, but fall back on a substitute if dirname fails. |
||||||
|
dstdir=` |
||||||
|
(dirname "$dst") 2>/dev/null || |
||||||
|
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ |
||||||
|
X"$dst" : 'X\(//\)[^/]' \| \ |
||||||
|
X"$dst" : 'X\(//\)$' \| \ |
||||||
|
X"$dst" : 'X\(/\)' \| . 2>/dev/null || |
||||||
|
echo X"$dst" | |
||||||
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ |
||||||
|
s//\1/ |
||||||
|
q |
||||||
|
} |
||||||
|
/^X\(\/\/\)[^/].*/{ |
||||||
|
s//\1/ |
||||||
|
q |
||||||
|
} |
||||||
|
/^X\(\/\/\)$/{ |
||||||
|
s//\1/ |
||||||
|
q |
||||||
|
} |
||||||
|
/^X\(\/\).*/{ |
||||||
|
s//\1/ |
||||||
|
q |
||||||
|
} |
||||||
|
s/.*/./; q' |
||||||
|
` |
||||||
|
|
||||||
|
test -d "$dstdir" |
||||||
|
dstdir_status=$? |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
obsolete_mkdir_used=false |
||||||
|
|
||||||
|
if test $dstdir_status != 0; then |
||||||
|
case $posix_mkdir in |
||||||
|
'') |
||||||
|
# Create intermediate dirs using mode 755 as modified by the umask. |
||||||
|
# This is like FreeBSD 'install' as of 1997-10-28. |
||||||
|
umask=`umask` |
||||||
|
case $stripcmd.$umask in |
||||||
|
# Optimize common cases. |
||||||
|
*[2367][2367]) mkdir_umask=$umask;; |
||||||
|
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; |
||||||
|
|
||||||
|
*[0-7]) |
||||||
|
mkdir_umask=`expr $umask + 22 \ |
||||||
|
- $umask % 100 % 40 + $umask % 20 \ |
||||||
|
- $umask % 10 % 4 + $umask % 2 |
||||||
|
`;; |
||||||
|
*) mkdir_umask=$umask,go-w;; |
||||||
|
esac |
||||||
|
|
||||||
|
# With -d, create the new directory with the user-specified mode. |
||||||
|
# Otherwise, rely on $mkdir_umask. |
||||||
|
if test -n "$dir_arg"; then |
||||||
|
mkdir_mode=-m$mode |
||||||
|
else |
||||||
|
mkdir_mode= |
||||||
|
fi |
||||||
|
|
||||||
|
posix_mkdir=false |
||||||
|
case $umask in |
||||||
|
*[123567][0-7][0-7]) |
||||||
|
# POSIX mkdir -p sets u+wx bits regardless of umask, which |
||||||
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0. |
||||||
|
;; |
||||||
|
*) |
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ |
||||||
|
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 |
||||||
|
|
||||||
|
if (umask $mkdir_umask && |
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 |
||||||
|
then |
||||||
|
if test -z "$dir_arg" || { |
||||||
|
# Check for POSIX incompatibilities with -m. |
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or |
||||||
|
# other-writeable bit of parent directory when it shouldn't. |
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory. |
||||||
|
ls_ld_tmpdir=`ls -ld "$tmpdir"` |
||||||
|
case $ls_ld_tmpdir in |
||||||
|
d????-?r-*) different_mode=700;; |
||||||
|
d????-?--*) different_mode=755;; |
||||||
|
*) false;; |
||||||
|
esac && |
||||||
|
$mkdirprog -m$different_mode -p -- "$tmpdir" && { |
||||||
|
ls_ld_tmpdir_1=`ls -ld "$tmpdir"` |
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" |
||||||
|
} |
||||||
|
} |
||||||
|
then posix_mkdir=: |
||||||
|
fi |
||||||
|
rmdir "$tmpdir/d" "$tmpdir" |
||||||
|
else |
||||||
|
# Remove any dirs left behind by ancient mkdir implementations. |
||||||
|
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null |
||||||
|
fi |
||||||
|
trap '' 0;; |
||||||
|
esac;; |
||||||
|
esac |
||||||
|
|
||||||
|
if |
||||||
|
$posix_mkdir && ( |
||||||
|
umask $mkdir_umask && |
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" |
||||||
|
) |
||||||
|
then : |
||||||
|
else |
||||||
|
|
||||||
|
# The umask is ridiculous, or mkdir does not conform to POSIX, |
||||||
|
# or it failed possibly due to a race condition. Create the |
||||||
|
# directory the slow way, step by step, checking for races as we go. |
||||||
|
|
||||||
|
case $dstdir in |
||||||
|
/*) prefix='/';; |
||||||
|
-*) prefix='./';; |
||||||
|
*) prefix='';; |
||||||
|
esac |
||||||
|
|
||||||
|
eval "$initialize_posix_glob" |
||||||
|
|
||||||
|
oIFS=$IFS |
||||||
|
IFS=/ |
||||||
|
$posix_glob set -f |
||||||
|
set fnord $dstdir |
||||||
|
shift |
||||||
|
$posix_glob set +f |
||||||
|
IFS=$oIFS |
||||||
|
|
||||||
|
prefixes= |
||||||
|
|
||||||
|
for d |
||||||
|
do |
||||||
|
test -z "$d" && continue |
||||||
|
|
||||||
|
prefix=$prefix$d |
||||||
|
if test -d "$prefix"; then |
||||||
|
prefixes= |
||||||
|
else |
||||||
|
if $posix_mkdir; then |
||||||
|
(umask=$mkdir_umask && |
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break |
||||||
|
# Don't fail if two instances are running concurrently. |
||||||
|
test -d "$prefix" || exit 1 |
||||||
|
else |
||||||
|
case $prefix in |
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; |
||||||
|
*) qprefix=$prefix;; |
||||||
|
esac |
||||||
|
prefixes="$prefixes '$qprefix'" |
||||||
|
fi |
||||||
|
fi |
||||||
|
prefix=$prefix/ |
||||||
|
done |
||||||
|
|
||||||
|
if test -n "$prefixes"; then |
||||||
|
# Don't fail if two instances are running concurrently. |
||||||
|
(umask $mkdir_umask && |
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") || |
||||||
|
test -d "$dstdir" || exit 1 |
||||||
|
obsolete_mkdir_used=true |
||||||
|
fi |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
if test -n "$dir_arg"; then |
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } && |
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && |
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || |
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 |
||||||
|
else |
||||||
|
|
||||||
|
# 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 |
||||||
|
|
||||||
|
# Copy the file name to the temp name. |
||||||
|
(umask $cp_umask && $doit_exec $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 $mode "$dsttmp"; } && |
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file. |
||||||
|
if $copy_on_change && |
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && |
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && |
||||||
|
|
||||||
|
eval "$initialize_posix_glob" && |
||||||
|
$posix_glob set -f && |
||||||
|
set X $old && old=:$2:$4:$5:$6 && |
||||||
|
set X $new && new=:$2:$4:$5:$6 && |
||||||
|
$posix_glob set +f && |
||||||
|
|
||||||
|
test "$old" = "$new" && |
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 |
||||||
|
then |
||||||
|
rm -f "$dsttmp" |
||||||
|
else |
||||||
|
# Rename the file to the real destination. |
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 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. |
||||||
|
{ |
||||||
|
test ! -f "$dst" || |
||||||
|
$doit $rmcmd -f "$dst" 2>/dev/null || |
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && |
||||||
|
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } |
||||||
|
} || |
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2 |
||||||
|
(exit 1); exit 1 |
||||||
|
} |
||||||
|
} && |
||||||
|
|
||||||
|
# Now rename the file to the real destination. |
||||||
|
$doit $mvcmd "$dsttmp" "$dst" |
||||||
|
} |
||||||
|
fi || exit 1 |
||||||
|
|
||||||
|
trap '' 0 |
||||||
|
fi |
||||||
|
done |
||||||
|
|
||||||
|
# Local variables: |
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp) |
||||||
|
# time-stamp-start: "scriptversion=" |
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H" |
||||||
|
# time-stamp-time-zone: "UTC" |
||||||
|
# time-stamp-end: "; # UTC" |
||||||
|
# End: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,153 @@ |
|||||||
|
/*
|
||||||
|
* jaricom.c |
||||||
|
* |
||||||
|
* Developed 1997-2009 by Guido Vollbeding. |
||||||
|
* 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 probability estimation tables for common use in |
||||||
|
* arithmetic entropy encoding and decoding routines. |
||||||
|
* |
||||||
|
* This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1 |
||||||
|
* and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec |
||||||
|
* (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82). |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
/* The following #define specifies the packing of the four components
|
||||||
|
* into the compact INT32 representation. |
||||||
|
* Note that this formula must match the actual arithmetic encoder |
||||||
|
* and decoder implementation. The implementation has to be changed |
||||||
|
* if this formula is changed. |
||||||
|
* The current organization is leaned on Markus Kuhn's JBIG |
||||||
|
* implementation (jbig_tab.c). |
||||||
|
*/ |
||||||
|
|
||||||
|
#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) |
||||||
|
|
||||||
|
const INT32 jpeg_aritab[113+1] = { |
||||||
|
/*
|
||||||
|
* Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS |
||||||
|
*/ |
||||||
|
V( 0, 0x5a1d, 1, 1, 1 ), |
||||||
|
V( 1, 0x2586, 14, 2, 0 ), |
||||||
|
V( 2, 0x1114, 16, 3, 0 ), |
||||||
|
V( 3, 0x080b, 18, 4, 0 ), |
||||||
|
V( 4, 0x03d8, 20, 5, 0 ), |
||||||
|
V( 5, 0x01da, 23, 6, 0 ), |
||||||
|
V( 6, 0x00e5, 25, 7, 0 ), |
||||||
|
V( 7, 0x006f, 28, 8, 0 ), |
||||||
|
V( 8, 0x0036, 30, 9, 0 ), |
||||||
|
V( 9, 0x001a, 33, 10, 0 ), |
||||||
|
V( 10, 0x000d, 35, 11, 0 ), |
||||||
|
V( 11, 0x0006, 9, 12, 0 ), |
||||||
|
V( 12, 0x0003, 10, 13, 0 ), |
||||||
|
V( 13, 0x0001, 12, 13, 0 ), |
||||||
|
V( 14, 0x5a7f, 15, 15, 1 ), |
||||||
|
V( 15, 0x3f25, 36, 16, 0 ), |
||||||
|
V( 16, 0x2cf2, 38, 17, 0 ), |
||||||
|
V( 17, 0x207c, 39, 18, 0 ), |
||||||
|
V( 18, 0x17b9, 40, 19, 0 ), |
||||||
|
V( 19, 0x1182, 42, 20, 0 ), |
||||||
|
V( 20, 0x0cef, 43, 21, 0 ), |
||||||
|
V( 21, 0x09a1, 45, 22, 0 ), |
||||||
|
V( 22, 0x072f, 46, 23, 0 ), |
||||||
|
V( 23, 0x055c, 48, 24, 0 ), |
||||||
|
V( 24, 0x0406, 49, 25, 0 ), |
||||||
|
V( 25, 0x0303, 51, 26, 0 ), |
||||||
|
V( 26, 0x0240, 52, 27, 0 ), |
||||||
|
V( 27, 0x01b1, 54, 28, 0 ), |
||||||
|
V( 28, 0x0144, 56, 29, 0 ), |
||||||
|
V( 29, 0x00f5, 57, 30, 0 ), |
||||||
|
V( 30, 0x00b7, 59, 31, 0 ), |
||||||
|
V( 31, 0x008a, 60, 32, 0 ), |
||||||
|
V( 32, 0x0068, 62, 33, 0 ), |
||||||
|
V( 33, 0x004e, 63, 34, 0 ), |
||||||
|
V( 34, 0x003b, 32, 35, 0 ), |
||||||
|
V( 35, 0x002c, 33, 9, 0 ), |
||||||
|
V( 36, 0x5ae1, 37, 37, 1 ), |
||||||
|
V( 37, 0x484c, 64, 38, 0 ), |
||||||
|
V( 38, 0x3a0d, 65, 39, 0 ), |
||||||
|
V( 39, 0x2ef1, 67, 40, 0 ), |
||||||
|
V( 40, 0x261f, 68, 41, 0 ), |
||||||
|
V( 41, 0x1f33, 69, 42, 0 ), |
||||||
|
V( 42, 0x19a8, 70, 43, 0 ), |
||||||
|
V( 43, 0x1518, 72, 44, 0 ), |
||||||
|
V( 44, 0x1177, 73, 45, 0 ), |
||||||
|
V( 45, 0x0e74, 74, 46, 0 ), |
||||||
|
V( 46, 0x0bfb, 75, 47, 0 ), |
||||||
|
V( 47, 0x09f8, 77, 48, 0 ), |
||||||
|
V( 48, 0x0861, 78, 49, 0 ), |
||||||
|
V( 49, 0x0706, 79, 50, 0 ), |
||||||
|
V( 50, 0x05cd, 48, 51, 0 ), |
||||||
|
V( 51, 0x04de, 50, 52, 0 ), |
||||||
|
V( 52, 0x040f, 50, 53, 0 ), |
||||||
|
V( 53, 0x0363, 51, 54, 0 ), |
||||||
|
V( 54, 0x02d4, 52, 55, 0 ), |
||||||
|
V( 55, 0x025c, 53, 56, 0 ), |
||||||
|
V( 56, 0x01f8, 54, 57, 0 ), |
||||||
|
V( 57, 0x01a4, 55, 58, 0 ), |
||||||
|
V( 58, 0x0160, 56, 59, 0 ), |
||||||
|
V( 59, 0x0125, 57, 60, 0 ), |
||||||
|
V( 60, 0x00f6, 58, 61, 0 ), |
||||||
|
V( 61, 0x00cb, 59, 62, 0 ), |
||||||
|
V( 62, 0x00ab, 61, 63, 0 ), |
||||||
|
V( 63, 0x008f, 61, 32, 0 ), |
||||||
|
V( 64, 0x5b12, 65, 65, 1 ), |
||||||
|
V( 65, 0x4d04, 80, 66, 0 ), |
||||||
|
V( 66, 0x412c, 81, 67, 0 ), |
||||||
|
V( 67, 0x37d8, 82, 68, 0 ), |
||||||
|
V( 68, 0x2fe8, 83, 69, 0 ), |
||||||
|
V( 69, 0x293c, 84, 70, 0 ), |
||||||
|
V( 70, 0x2379, 86, 71, 0 ), |
||||||
|
V( 71, 0x1edf, 87, 72, 0 ), |
||||||
|
V( 72, 0x1aa9, 87, 73, 0 ), |
||||||
|
V( 73, 0x174e, 72, 74, 0 ), |
||||||
|
V( 74, 0x1424, 72, 75, 0 ), |
||||||
|
V( 75, 0x119c, 74, 76, 0 ), |
||||||
|
V( 76, 0x0f6b, 74, 77, 0 ), |
||||||
|
V( 77, 0x0d51, 75, 78, 0 ), |
||||||
|
V( 78, 0x0bb6, 77, 79, 0 ), |
||||||
|
V( 79, 0x0a40, 77, 48, 0 ), |
||||||
|
V( 80, 0x5832, 80, 81, 1 ), |
||||||
|
V( 81, 0x4d1c, 88, 82, 0 ), |
||||||
|
V( 82, 0x438e, 89, 83, 0 ), |
||||||
|
V( 83, 0x3bdd, 90, 84, 0 ), |
||||||
|
V( 84, 0x34ee, 91, 85, 0 ), |
||||||
|
V( 85, 0x2eae, 92, 86, 0 ), |
||||||
|
V( 86, 0x299a, 93, 87, 0 ), |
||||||
|
V( 87, 0x2516, 86, 71, 0 ), |
||||||
|
V( 88, 0x5570, 88, 89, 1 ), |
||||||
|
V( 89, 0x4ca9, 95, 90, 0 ), |
||||||
|
V( 90, 0x44d9, 96, 91, 0 ), |
||||||
|
V( 91, 0x3e22, 97, 92, 0 ), |
||||||
|
V( 92, 0x3824, 99, 93, 0 ), |
||||||
|
V( 93, 0x32b4, 99, 94, 0 ), |
||||||
|
V( 94, 0x2e17, 93, 86, 0 ), |
||||||
|
V( 95, 0x56a8, 95, 96, 1 ), |
||||||
|
V( 96, 0x4f46, 101, 97, 0 ), |
||||||
|
V( 97, 0x47e5, 102, 98, 0 ), |
||||||
|
V( 98, 0x41cf, 103, 99, 0 ), |
||||||
|
V( 99, 0x3c3d, 104, 100, 0 ), |
||||||
|
V( 100, 0x375e, 99, 93, 0 ), |
||||||
|
V( 101, 0x5231, 105, 102, 0 ), |
||||||
|
V( 102, 0x4c0f, 106, 103, 0 ), |
||||||
|
V( 103, 0x4639, 107, 104, 0 ), |
||||||
|
V( 104, 0x415e, 103, 99, 0 ), |
||||||
|
V( 105, 0x5627, 105, 106, 1 ), |
||||||
|
V( 106, 0x50e7, 108, 107, 0 ), |
||||||
|
V( 107, 0x4b85, 109, 103, 0 ), |
||||||
|
V( 108, 0x5597, 110, 109, 0 ), |
||||||
|
V( 109, 0x504f, 111, 107, 0 ), |
||||||
|
V( 110, 0x5a10, 110, 111, 1 ), |
||||||
|
V( 111, 0x5522, 112, 109, 0 ), |
||||||
|
V( 112, 0x59eb, 112, 111, 1 ), |
||||||
|
/*
|
||||||
|
* This last entry is used for fixed probability estimate of 0.5 |
||||||
|
* as recommended in Section 10.3 Table 5 of ITU-T Rec. T.851. |
||||||
|
*/ |
||||||
|
V( 113, 0x5a1d, 113, 113, 0 ) |
||||||
|
}; |
@ -0,0 +1,288 @@ |
|||||||
|
/*
|
||||||
|
* jcapimin.c |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1998, Thomas G. Lane. |
||||||
|
* Modified 2003-2010 by Guido Vollbeding. |
||||||
|
* 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; |
||||||
|
cinfo->q_scale_factor[i] = 100; |
||||||
|
} |
||||||
|
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) { |
||||||
|
cinfo->dc_huff_tbl_ptrs[i] = NULL; |
||||||
|
cinfo->ac_huff_tbl_ptrs[i] = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/* Must do it here for emit_dqt in case jpeg_write_tables is used */ |
||||||
|
cinfo->block_size = DCTSIZE; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
|
||||||
|
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(). |
||||||
|
*/ |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -0,0 +1,934 @@ |
|||||||
|
/*
|
||||||
|
* jcarith.c |
||||||
|
* |
||||||
|
* Developed 1997-2009 by Guido Vollbeding. |
||||||
|
* 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 portable arithmetic entropy encoding routines for JPEG |
||||||
|
* (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). |
||||||
|
* |
||||||
|
* Both sequential and progressive modes are supported in this single module. |
||||||
|
* |
||||||
|
* Suspension is not currently supported in this module. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Expanded entropy encoder object for arithmetic encoding. */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_entropy_encoder pub; /* public fields */ |
||||||
|
|
||||||
|
INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */ |
||||||
|
INT32 a; /* A register, normalized size of coding interval */ |
||||||
|
INT32 sc; /* counter for stacked 0xFF values which might overflow */ |
||||||
|
INT32 zc; /* counter for pending 0x00 output values which might *
|
||||||
|
* be discarded at the end ("Pacman" termination) */ |
||||||
|
int ct; /* bit shift counter, determines when next byte will be written */ |
||||||
|
int buffer; /* buffer for most recent output byte != 0xFF */ |
||||||
|
|
||||||
|
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ |
||||||
|
int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ |
||||||
|
|
||||||
|
unsigned int restarts_to_go; /* MCUs left in this restart interval */ |
||||||
|
int next_restart_num; /* next restart number to write (0-7) */ |
||||||
|
|
||||||
|
/* Pointers to statistics areas (these workspaces have image lifespan) */ |
||||||
|
unsigned char * dc_stats[NUM_ARITH_TBLS]; |
||||||
|
unsigned char * ac_stats[NUM_ARITH_TBLS]; |
||||||
|
|
||||||
|
/* Statistics bin for coding with fixed probability 0.5 */ |
||||||
|
unsigned char fixed_bin[4]; |
||||||
|
} arith_entropy_encoder; |
||||||
|
|
||||||
|
typedef arith_entropy_encoder * arith_entropy_ptr; |
||||||
|
|
||||||
|
/* The following two definitions specify the allocation chunk size
|
||||||
|
* for the statistics area. |
||||||
|
* According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least |
||||||
|
* 49 statistics bins for DC, and 245 statistics bins for AC coding. |
||||||
|
* |
||||||
|
* We use a compact representation with 1 byte per statistics bin, |
||||||
|
* thus the numbers directly represent byte sizes. |
||||||
|
* This 1 byte per statistics bin contains the meaning of the MPS |
||||||
|
* (more probable symbol) in the highest bit (mask 0x80), and the |
||||||
|
* index into the probability estimation state machine table |
||||||
|
* in the lower bits (mask 0x7F). |
||||||
|
*/ |
||||||
|
|
||||||
|
#define DC_STAT_BINS 64 |
||||||
|
#define AC_STAT_BINS 256 |
||||||
|
|
||||||
|
/* NOTE: Uncomment the following #define if you want to use the
|
||||||
|
* given formula for calculating the AC conditioning parameter Kx |
||||||
|
* for spectral selection progressive coding in section G.1.3.2 |
||||||
|
* of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4). |
||||||
|
* Although the spec and P&M authors claim that this "has proven |
||||||
|
* to give good results for 8 bit precision samples", I'm not |
||||||
|
* convinced yet that this is really beneficial. |
||||||
|
* Early tests gave only very marginal compression enhancements |
||||||
|
* (a few - around 5 or so - bytes even for very large files), |
||||||
|
* which would turn out rather negative if we'd suppress the |
||||||
|
* DAC (Define Arithmetic Conditioning) marker segments for |
||||||
|
* the default parameters in the future. |
||||||
|
* Note that currently the marker writing module emits 12-byte |
||||||
|
* DAC segments for a full-component scan in a color image. |
||||||
|
* This is not worth worrying about IMHO. However, since the |
||||||
|
* spec defines the default values to be used if the tables |
||||||
|
* are omitted (unlike Huffman tables, which are required |
||||||
|
* anyway), one might optimize this behaviour in the future, |
||||||
|
* and then it would be disadvantageous to use custom tables if |
||||||
|
* they don't provide sufficient gain to exceed the DAC size. |
||||||
|
* |
||||||
|
* On the other hand, I'd consider it as a reasonable result |
||||||
|
* that the conditioning has no significant influence on the |
||||||
|
* compression performance. This means that the basic |
||||||
|
* statistical model is already rather stable. |
||||||
|
* |
||||||
|
* Thus, at the moment, we use the default conditioning values |
||||||
|
* anyway, and do not use the custom formula. |
||||||
|
* |
||||||
|
#define CALCULATE_SPECTRAL_CONDITIONING |
||||||
|
*/ |
||||||
|
|
||||||
|
/* 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 |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
emit_byte (int val, j_compress_ptr cinfo) |
||||||
|
/* Write next output byte; we do not support suspension in this module. */ |
||||||
|
{ |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up at the end of an arithmetic-compressed scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
finish_pass (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
INT32 temp; |
||||||
|
|
||||||
|
/* Section D.1.8: Termination of encoding */ |
||||||
|
|
||||||
|
/* Find the e->c in the coding interval with the largest
|
||||||
|
* number of trailing zero bits */ |
||||||
|
if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c) |
||||||
|
e->c = temp + 0x8000L; |
||||||
|
else |
||||||
|
e->c = temp; |
||||||
|
/* Send remaining bytes to output */ |
||||||
|
e->c <<= e->ct; |
||||||
|
if (e->c & 0xF8000000L) { |
||||||
|
/* One final overflow has to be handled */ |
||||||
|
if (e->buffer >= 0) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
emit_byte(e->buffer + 1, cinfo); |
||||||
|
if (e->buffer + 1 == 0xFF) |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
} |
||||||
|
e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ |
||||||
|
e->sc = 0; |
||||||
|
} else { |
||||||
|
if (e->buffer == 0) |
||||||
|
++e->zc; |
||||||
|
else if (e->buffer >= 0) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
emit_byte(e->buffer, cinfo); |
||||||
|
} |
||||||
|
if (e->sc) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
do { |
||||||
|
emit_byte(0xFF, cinfo); |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
} while (--e->sc); |
||||||
|
} |
||||||
|
} |
||||||
|
/* Output final bytes only if they are not 0x00 */ |
||||||
|
if (e->c & 0x7FFF800L) { |
||||||
|
if (e->zc) /* output final pending zero bytes */ |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
emit_byte((e->c >> 19) & 0xFF, cinfo); |
||||||
|
if (((e->c >> 19) & 0xFF) == 0xFF) |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
if (e->c & 0x7F800L) { |
||||||
|
emit_byte((e->c >> 11) & 0xFF, cinfo); |
||||||
|
if (((e->c >> 11) & 0xFF) == 0xFF) |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The core arithmetic encoding routine (common in JPEG and JBIG). |
||||||
|
* This needs to go as fast as possible. |
||||||
|
* Machine-dependent optimization facilities |
||||||
|
* are not utilized in this portable implementation. |
||||||
|
* However, this code should be fairly efficient and |
||||||
|
* may be a good base for further optimizations anyway. |
||||||
|
* |
||||||
|
* Parameter 'val' to be encoded may be 0 or 1 (binary decision). |
||||||
|
* |
||||||
|
* Note: I've added full "Pacman" termination support to the |
||||||
|
* byte output routines, which is equivalent to the optional |
||||||
|
* Discard_final_zeros procedure (Figure D.15) in the spec. |
||||||
|
* Thus, we always produce the shortest possible output |
||||||
|
* stream compliant to the spec (no trailing zero bytes, |
||||||
|
* except for FF stuffing). |
||||||
|
* |
||||||
|
* I've also introduced a new scheme for accessing |
||||||
|
* the probability estimation state machine table, |
||||||
|
* derived from Markus Kuhn's JBIG implementation. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
|
||||||
|
{ |
||||||
|
register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
register unsigned char nl, nm; |
||||||
|
register INT32 qe, temp; |
||||||
|
register int sv; |
||||||
|
|
||||||
|
/* Fetch values from our compact representation of Table D.2:
|
||||||
|
* Qe values and probability estimation state machine |
||||||
|
*/ |
||||||
|
sv = *st; |
||||||
|
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ |
||||||
|
nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ |
||||||
|
nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ |
||||||
|
|
||||||
|
/* Encode & estimation procedures per sections D.1.4 & D.1.5 */ |
||||||
|
e->a -= qe; |
||||||
|
if (val != (sv >> 7)) { |
||||||
|
/* Encode the less probable symbol */ |
||||||
|
if (e->a >= qe) { |
||||||
|
/* If the interval size (qe) for the less probable symbol (LPS)
|
||||||
|
* is larger than the interval size for the MPS, then exchange |
||||||
|
* the two symbols for coding efficiency, otherwise code the LPS |
||||||
|
* as usual: */ |
||||||
|
e->c += e->a; |
||||||
|
e->a = qe; |
||||||
|
} |
||||||
|
*st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ |
||||||
|
} else { |
||||||
|
/* Encode the more probable symbol */ |
||||||
|
if (e->a >= 0x8000L) |
||||||
|
return; /* A >= 0x8000 -> ready, no renormalization required */ |
||||||
|
if (e->a < qe) { |
||||||
|
/* If the interval size (qe) for the less probable symbol (LPS)
|
||||||
|
* is larger than the interval size for the MPS, then exchange |
||||||
|
* the two symbols for coding efficiency: */ |
||||||
|
e->c += e->a; |
||||||
|
e->a = qe; |
||||||
|
} |
||||||
|
*st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ |
||||||
|
} |
||||||
|
|
||||||
|
/* Renormalization & data output per section D.1.6 */ |
||||||
|
do { |
||||||
|
e->a <<= 1; |
||||||
|
e->c <<= 1; |
||||||
|
if (--e->ct == 0) { |
||||||
|
/* Another byte is ready for output */ |
||||||
|
temp = e->c >> 19; |
||||||
|
if (temp > 0xFF) { |
||||||
|
/* Handle overflow over all stacked 0xFF bytes */ |
||||||
|
if (e->buffer >= 0) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
emit_byte(e->buffer + 1, cinfo); |
||||||
|
if (e->buffer + 1 == 0xFF) |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
} |
||||||
|
e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ |
||||||
|
e->sc = 0; |
||||||
|
/* Note: The 3 spacer bits in the C register guarantee
|
||||||
|
* that the new buffer byte can't be 0xFF here |
||||||
|
* (see page 160 in the P&M JPEG book). */ |
||||||
|
e->buffer = temp & 0xFF; /* new output byte, might overflow later */ |
||||||
|
} else if (temp == 0xFF) { |
||||||
|
++e->sc; /* stack 0xFF byte (which might overflow later) */ |
||||||
|
} else { |
||||||
|
/* Output all stacked 0xFF bytes, they will not overflow any more */ |
||||||
|
if (e->buffer == 0) |
||||||
|
++e->zc; |
||||||
|
else if (e->buffer >= 0) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
emit_byte(e->buffer, cinfo); |
||||||
|
} |
||||||
|
if (e->sc) { |
||||||
|
if (e->zc) |
||||||
|
do emit_byte(0x00, cinfo); |
||||||
|
while (--e->zc); |
||||||
|
do { |
||||||
|
emit_byte(0xFF, cinfo); |
||||||
|
emit_byte(0x00, cinfo); |
||||||
|
} while (--e->sc); |
||||||
|
} |
||||||
|
e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ |
||||||
|
} |
||||||
|
e->c &= 0x7FFFFL; |
||||||
|
e->ct += 8; |
||||||
|
} |
||||||
|
} while (e->a < 0x8000L); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit a restart marker & resynchronize predictions. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
emit_restart (j_compress_ptr cinfo, int restart_num) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
int ci; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
|
||||||
|
finish_pass(cinfo); |
||||||
|
|
||||||
|
emit_byte(0xFF, cinfo); |
||||||
|
emit_byte(JPEG_RST0 + restart_num, cinfo); |
||||||
|
|
||||||
|
/* Re-initialize statistics areas */ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
/* DC needs no table for refinement scan */ |
||||||
|
if (cinfo->Ss == 0 && cinfo->Ah == 0) { |
||||||
|
MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); |
||||||
|
/* Reset DC predictions to 0 */ |
||||||
|
entropy->last_dc_val[ci] = 0; |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
} |
||||||
|
/* AC needs no table when not present */ |
||||||
|
if (cinfo->Se) { |
||||||
|
MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Reset arithmetic encoding variables */ |
||||||
|
entropy->c = 0; |
||||||
|
entropy->a = 0x10000L; |
||||||
|
entropy->sc = 0; |
||||||
|
entropy->zc = 0; |
||||||
|
entropy->ct = 11; |
||||||
|
entropy->buffer = -1; /* empty */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int blkn, ci, tbl; |
||||||
|
int v, v2, m; |
||||||
|
ISHIFT_TEMPS |
||||||
|
|
||||||
|
/* Emit restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) { |
||||||
|
emit_restart(cinfo, entropy->next_restart_num); |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num++; |
||||||
|
entropy->next_restart_num &= 7; |
||||||
|
} |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
/* Encode the MCU data blocks */ |
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { |
||||||
|
block = MCU_data[blkn]; |
||||||
|
ci = cinfo->MCU_membership[blkn]; |
||||||
|
tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; |
||||||
|
|
||||||
|
/* Compute the DC value after the required point transform by Al.
|
||||||
|
* This is simply an arithmetic right shift. |
||||||
|
*/ |
||||||
|
m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al); |
||||||
|
|
||||||
|
/* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ |
||||||
|
|
||||||
|
/* Table F.4: Point to statistics bin S0 for DC coefficient coding */ |
||||||
|
st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; |
||||||
|
|
||||||
|
/* Figure F.4: Encode_DC_DIFF */ |
||||||
|
if ((v = m - entropy->last_dc_val[ci]) == 0) { |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
} else { |
||||||
|
entropy->last_dc_val[ci] = m; |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
/* Figure F.6: Encoding nonzero value v */ |
||||||
|
/* Figure F.7: Encoding the sign of v */ |
||||||
|
if (v > 0) { |
||||||
|
arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ |
||||||
|
st += 2; /* Table F.4: SP = S0 + 2 */ |
||||||
|
entropy->dc_context[ci] = 4; /* small positive diff category */ |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ |
||||||
|
st += 3; /* Table F.4: SN = S0 + 3 */ |
||||||
|
entropy->dc_context[ci] = 8; /* small negative diff category */ |
||||||
|
} |
||||||
|
/* Figure F.8: Encoding the magnitude category of v */ |
||||||
|
m = 0; |
||||||
|
if (v -= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m = 1; |
||||||
|
v2 = v; |
||||||
|
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ |
||||||
|
while (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */ |
||||||
|
if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] += 8; /* large diff category */ |
||||||
|
/* Figure F.9: Encoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
arith_encode(cinfo, st, (m & v) ? 1 : 0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int tbl, k, ke; |
||||||
|
int v, v2, m; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Emit restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) { |
||||||
|
emit_restart(cinfo, entropy->next_restart_num); |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num++; |
||||||
|
entropy->next_restart_num &= 7; |
||||||
|
} |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* Encode the MCU data block */ |
||||||
|
block = MCU_data[0]; |
||||||
|
tbl = cinfo->cur_comp_info[0]->ac_tbl_no; |
||||||
|
|
||||||
|
/* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ |
||||||
|
|
||||||
|
/* Establish EOB (end-of-block) index */ |
||||||
|
for (ke = cinfo->Se; ke > 0; ke--) |
||||||
|
/* 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 ((v = (*block)[natural_order[ke]]) >= 0) { |
||||||
|
if (v >>= cinfo->Al) break; |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
if (v >>= cinfo->Al) break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Figure F.5: Encode_AC_Coefficients */ |
||||||
|
for (k = cinfo->Ss; k <= ke; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
arith_encode(cinfo, st, 0); /* EOB decision */ |
||||||
|
for (;;) { |
||||||
|
if ((v = (*block)[natural_order[k]]) >= 0) { |
||||||
|
if (v >>= cinfo->Al) { |
||||||
|
arith_encode(cinfo, st + 1, 1); |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 0); |
||||||
|
break; |
||||||
|
} |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
if (v >>= cinfo->Al) { |
||||||
|
arith_encode(cinfo, st + 1, 1); |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 1); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st + 1, 0); st += 3; k++; |
||||||
|
} |
||||||
|
st += 2; |
||||||
|
/* Figure F.8: Encoding the magnitude category of v */ |
||||||
|
m = 0; |
||||||
|
if (v -= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m = 1; |
||||||
|
v2 = v; |
||||||
|
if (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st = entropy->ac_stats[tbl] + |
||||||
|
(k <= cinfo->arith_ac_K[tbl] ? 189 : 217); |
||||||
|
while (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
/* Figure F.9: Encoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
arith_encode(cinfo, st, (m & v) ? 1 : 0); |
||||||
|
} |
||||||
|
/* Encode EOB decision only if k <= cinfo->Se */ |
||||||
|
if (k <= cinfo->Se) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for DC successive approximation refinement scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
unsigned char *st; |
||||||
|
int Al, blkn; |
||||||
|
|
||||||
|
/* Emit restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) { |
||||||
|
emit_restart(cinfo, entropy->next_restart_num); |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num++; |
||||||
|
entropy->next_restart_num &= 7; |
||||||
|
} |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
st = entropy->fixed_bin; /* use fixed probability estimation */ |
||||||
|
Al = cinfo->Al; |
||||||
|
|
||||||
|
/* Encode the MCU data blocks */ |
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { |
||||||
|
/* We simply emit the Al'th bit of the DC coefficient value. */ |
||||||
|
arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1); |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU encoding for AC successive approximation refinement scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int tbl, k, ke, kex; |
||||||
|
int v; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Emit restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) { |
||||||
|
emit_restart(cinfo, entropy->next_restart_num); |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num++; |
||||||
|
entropy->next_restart_num &= 7; |
||||||
|
} |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* Encode the MCU data block */ |
||||||
|
block = MCU_data[0]; |
||||||
|
tbl = cinfo->cur_comp_info[0]->ac_tbl_no; |
||||||
|
|
||||||
|
/* Section G.1.3.3: Encoding of AC coefficients */ |
||||||
|
|
||||||
|
/* Establish EOB (end-of-block) index */ |
||||||
|
for (ke = cinfo->Se; ke > 0; ke--) |
||||||
|
/* 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 ((v = (*block)[natural_order[ke]]) >= 0) { |
||||||
|
if (v >>= cinfo->Al) break; |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
if (v >>= cinfo->Al) break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Establish EOBx (previous stage end-of-block) index */ |
||||||
|
for (kex = ke; kex > 0; kex--) |
||||||
|
if ((v = (*block)[natural_order[kex]]) >= 0) { |
||||||
|
if (v >>= cinfo->Ah) break; |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
if (v >>= cinfo->Ah) break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Figure G.10: Encode_AC_Coefficients_SA */ |
||||||
|
for (k = cinfo->Ss; k <= ke; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
if (k > kex) |
||||||
|
arith_encode(cinfo, st, 0); /* EOB decision */ |
||||||
|
for (;;) { |
||||||
|
if ((v = (*block)[natural_order[k]]) >= 0) { |
||||||
|
if (v >>= cinfo->Al) { |
||||||
|
if (v >> 1) /* previously nonzero coef */ |
||||||
|
arith_encode(cinfo, st + 2, (v & 1)); |
||||||
|
else { /* newly nonzero coef */ |
||||||
|
arith_encode(cinfo, st + 1, 1); |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 0); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
if (v >>= cinfo->Al) { |
||||||
|
if (v >> 1) /* previously nonzero coef */ |
||||||
|
arith_encode(cinfo, st + 2, (v & 1)); |
||||||
|
else { /* newly nonzero coef */ |
||||||
|
arith_encode(cinfo, st + 1, 1); |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 1); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st + 1, 0); st += 3; k++; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Encode EOB decision only if k <= cinfo->Se */ |
||||||
|
if (k <= cinfo->Se) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode and output one MCU's worth of arithmetic-compressed coefficients. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int blkn, ci, tbl, k, ke; |
||||||
|
int v, v2, m; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Emit restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) { |
||||||
|
emit_restart(cinfo, entropy->next_restart_num); |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num++; |
||||||
|
entropy->next_restart_num &= 7; |
||||||
|
} |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* 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]; |
||||||
|
|
||||||
|
/* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ |
||||||
|
|
||||||
|
tbl = compptr->dc_tbl_no; |
||||||
|
|
||||||
|
/* Table F.4: Point to statistics bin S0 for DC coefficient coding */ |
||||||
|
st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; |
||||||
|
|
||||||
|
/* Figure F.4: Encode_DC_DIFF */ |
||||||
|
if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) { |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
} else { |
||||||
|
entropy->last_dc_val[ci] = (*block)[0]; |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
/* Figure F.6: Encoding nonzero value v */ |
||||||
|
/* Figure F.7: Encoding the sign of v */ |
||||||
|
if (v > 0) { |
||||||
|
arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ |
||||||
|
st += 2; /* Table F.4: SP = S0 + 2 */ |
||||||
|
entropy->dc_context[ci] = 4; /* small positive diff category */ |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ |
||||||
|
st += 3; /* Table F.4: SN = S0 + 3 */ |
||||||
|
entropy->dc_context[ci] = 8; /* small negative diff category */ |
||||||
|
} |
||||||
|
/* Figure F.8: Encoding the magnitude category of v */ |
||||||
|
m = 0; |
||||||
|
if (v -= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m = 1; |
||||||
|
v2 = v; |
||||||
|
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ |
||||||
|
while (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */ |
||||||
|
if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] += 8; /* large diff category */ |
||||||
|
/* Figure F.9: Encoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
arith_encode(cinfo, st, (m & v) ? 1 : 0); |
||||||
|
} |
||||||
|
|
||||||
|
/* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ |
||||||
|
|
||||||
|
tbl = compptr->ac_tbl_no; |
||||||
|
|
||||||
|
/* Establish EOB (end-of-block) index */ |
||||||
|
for (ke = cinfo->lim_Se; ke > 0; ke--) |
||||||
|
if ((*block)[natural_order[ke]]) break; |
||||||
|
|
||||||
|
/* Figure F.5: Encode_AC_Coefficients */ |
||||||
|
for (k = 1; k <= ke; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
arith_encode(cinfo, st, 0); /* EOB decision */ |
||||||
|
while ((v = (*block)[natural_order[k]]) == 0) { |
||||||
|
arith_encode(cinfo, st + 1, 0); st += 3; k++; |
||||||
|
} |
||||||
|
arith_encode(cinfo, st + 1, 1); |
||||||
|
/* Figure F.6: Encoding nonzero value v */ |
||||||
|
/* Figure F.7: Encoding the sign of v */ |
||||||
|
if (v > 0) { |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 0); |
||||||
|
} else { |
||||||
|
v = -v; |
||||||
|
arith_encode(cinfo, entropy->fixed_bin, 1); |
||||||
|
} |
||||||
|
st += 2; |
||||||
|
/* Figure F.8: Encoding the magnitude category of v */ |
||||||
|
m = 0; |
||||||
|
if (v -= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m = 1; |
||||||
|
v2 = v; |
||||||
|
if (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st = entropy->ac_stats[tbl] + |
||||||
|
(k <= cinfo->arith_ac_K[tbl] ? 189 : 217); |
||||||
|
while (v2 >>= 1) { |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
m <<= 1; |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
arith_encode(cinfo, st, 0); |
||||||
|
/* Figure F.9: Encoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
arith_encode(cinfo, st, (m & v) ? 1 : 0); |
||||||
|
} |
||||||
|
/* Encode EOB decision only if k <= cinfo->lim_Se */ |
||||||
|
if (k <= cinfo->lim_Se) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
arith_encode(cinfo, st, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an arithmetic-compressed scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
start_pass (j_compress_ptr cinfo, boolean gather_statistics) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
int ci, tbl; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
|
||||||
|
if (gather_statistics) |
||||||
|
/* Make sure to avoid that in the master control logic!
|
||||||
|
* We are fully adaptive here and need no extra |
||||||
|
* statistics gathering pass! |
||||||
|
*/ |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
|
||||||
|
/* We assume jcmaster.c already validated the progressive scan parameters. */ |
||||||
|
|
||||||
|
/* Select execution routines */ |
||||||
|
if (cinfo->progressive_mode) { |
||||||
|
if (cinfo->Ah == 0) { |
||||||
|
if (cinfo->Ss == 0) |
||||||
|
entropy->pub.encode_mcu = encode_mcu_DC_first; |
||||||
|
else |
||||||
|
entropy->pub.encode_mcu = encode_mcu_AC_first; |
||||||
|
} else { |
||||||
|
if (cinfo->Ss == 0) |
||||||
|
entropy->pub.encode_mcu = encode_mcu_DC_refine; |
||||||
|
else |
||||||
|
entropy->pub.encode_mcu = encode_mcu_AC_refine; |
||||||
|
} |
||||||
|
} else |
||||||
|
entropy->pub.encode_mcu = encode_mcu; |
||||||
|
|
||||||
|
/* Allocate & initialize requested statistics areas */ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
/* DC needs no table for refinement scan */ |
||||||
|
if (cinfo->Ss == 0 && cinfo->Ah == 0) { |
||||||
|
tbl = compptr->dc_tbl_no; |
||||||
|
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) |
||||||
|
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); |
||||||
|
if (entropy->dc_stats[tbl] == NULL) |
||||||
|
entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) |
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); |
||||||
|
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); |
||||||
|
/* Initialize DC predictions to 0 */ |
||||||
|
entropy->last_dc_val[ci] = 0; |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
} |
||||||
|
/* AC needs no table when not present */ |
||||||
|
if (cinfo->Se) { |
||||||
|
tbl = compptr->ac_tbl_no; |
||||||
|
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) |
||||||
|
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); |
||||||
|
if (entropy->ac_stats[tbl] == NULL) |
||||||
|
entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) |
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); |
||||||
|
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); |
||||||
|
#ifdef CALCULATE_SPECTRAL_CONDITIONING |
||||||
|
if (cinfo->progressive_mode) |
||||||
|
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ |
||||||
|
cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); |
||||||
|
#endif |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Initialize arithmetic encoding variables */ |
||||||
|
entropy->c = 0; |
||||||
|
entropy->a = 0x10000L; |
||||||
|
entropy->sc = 0; |
||||||
|
entropy->zc = 0; |
||||||
|
entropy->ct = 11; |
||||||
|
entropy->buffer = -1; /* empty */ |
||||||
|
|
||||||
|
/* Initialize restart stuff */ |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
entropy->next_restart_num = 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for arithmetic entropy encoding. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_arith_encoder (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy; |
||||||
|
int i; |
||||||
|
|
||||||
|
entropy = (arith_entropy_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(arith_entropy_encoder)); |
||||||
|
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; |
||||||
|
entropy->pub.start_pass = start_pass; |
||||||
|
entropy->pub.finish_pass = finish_pass; |
||||||
|
|
||||||
|
/* Mark tables unallocated */ |
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++) { |
||||||
|
entropy->dc_stats[i] = NULL; |
||||||
|
entropy->ac_stats[i] = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/* Initialize index for fixed probability estimation */ |
||||||
|
entropy->fixed_bin[0] = 113; |
||||||
|
} |
@ -0,0 +1,453 @@ |
|||||||
|
/*
|
||||||
|
* 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; |
||||||
|
forward_DCT_ptr forward_DCT; |
||||||
|
|
||||||
|
/* 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]; |
||||||
|
forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; |
||||||
|
blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width |
||||||
|
: compptr->last_col_width; |
||||||
|
xpos = MCU_col_num * compptr->MCU_sample_width; |
||||||
|
ypos = yoffset * compptr->DCT_v_scaled_size; |
||||||
|
/* 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) { |
||||||
|
(*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 += compptr->DCT_v_scaled_size; |
||||||
|
} |
||||||
|
} |
||||||
|
/* 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; |
||||||
|
forward_DCT_ptr forward_DCT; |
||||||
|
|
||||||
|
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; |
||||||
|
forward_DCT = cinfo->fdct->forward_DCT[ci]; |
||||||
|
/* 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]; |
||||||
|
(*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, |
||||||
|
(JDIMENSION) (block_row * compptr->DCT_v_scaled_size), |
||||||
|
(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 */ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,574 @@ |
|||||||
|
/*
|
||||||
|
* jccolor.c |
||||||
|
* |
||||||
|
* 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. |
||||||
|
* |
||||||
|
* This file contains input colorspace conversion routines. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* 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 **************/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are |
||||||
|
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. |
||||||
|
* The conversion equations to be implemented are therefore |
||||||
|
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B |
||||||
|
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define SCALEBITS 16 /* speediest right-shift on some machines */ |
||||||
|
#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) |
||||||
|
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) |
||||||
|
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) |
||||||
|
|
||||||
|
/* We allocate one big table and divide it up into eight parts, instead of
|
||||||
|
* doing eight alloc_small requests. This lets us use a single table base |
||||||
|
* address, which can be held in a register in the inner loops on many |
||||||
|
* machines (more than can hold all eight addresses, anyway). |
||||||
|
*/ |
||||||
|
|
||||||
|
#define R_Y_OFF 0 /* offset to R => Y section */ |
||||||
|
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ |
||||||
|
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ |
||||||
|
#define R_CB_OFF (3*(MAXJSAMPLE+1)) |
||||||
|
#define G_CB_OFF (4*(MAXJSAMPLE+1)) |
||||||
|
#define B_CB_OFF (5*(MAXJSAMPLE+1)) |
||||||
|
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ |
||||||
|
#define G_CR_OFF (6*(MAXJSAMPLE+1)) |
||||||
|
#define B_CR_OFF (7*(MAXJSAMPLE+1)) |
||||||
|
#define TABLE_SIZE (8*(MAXJSAMPLE+1)) |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for RGB->YCC colorspace conversion. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
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
|
||||||
|
* 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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
rgba_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 += RGBA_PIXELSIZE; |
||||||
|
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||||
|
* must be too; we do not need an explicit range-limiting operation. |
||||||
|
* Hence the value being shifted is never negative, and we don't |
||||||
|
* need the general RIGHT_SHIFT macro. |
||||||
|
*/ |
||||||
|
/* Y */ |
||||||
|
outptr0[col] = (JSAMPLE) |
||||||
|
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) |
||||||
|
>> SCALEBITS); |
||||||
|
/* Cb */ |
||||||
|
outptr1[col] = (JSAMPLE) |
||||||
|
((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) |
||||||
|
>> SCALEBITS); |
||||||
|
/* Cr */ |
||||||
|
outptr2[col] = (JSAMPLE) |
||||||
|
((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) |
||||||
|
>> SCALEBITS); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**************** Cases other than RGB -> YCbCr **************/ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
rgba_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 += RGBA_PIXELSIZE; |
||||||
|
/* Y */ |
||||||
|
outptr[col] = (JSAMPLE) |
||||||
|
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) |
||||||
|
>> SCALEBITS); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
rgba_rgb_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 += RGBA_PIXELSIZE; |
||||||
|
outptr0[col] = r; |
||||||
|
outptr1[col] = g; |
||||||
|
outptr2[col] = b; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace. |
||||||
|
* This version handles Adobe-style CMYK->YCCK conversion, |
||||||
|
* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same |
||||||
|
* conversion as above, while passing K (black) unchanged. |
||||||
|
* We assume rgb_ycc_start has been called. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
cmyk_ycck_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, outptr3; |
||||||
|
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]; |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace. |
||||||
|
* This version handles grayscale output with no conversion. |
||||||
|
* The source can be either plain grayscale or YCbCr (since Y == gray). |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
grayscale_convert (j_compress_ptr cinfo, |
||||||
|
JSAMPARRAY input_buf, JSAMPIMAGE output_buf, |
||||||
|
JDIMENSION output_row, int num_rows) |
||||||
|
{ |
||||||
|
register JSAMPROW inptr; |
||||||
|
register JSAMPROW outptr; |
||||||
|
register JDIMENSION col; |
||||||
|
JDIMENSION num_cols = cinfo->image_width; |
||||||
|
int instride = cinfo->input_components; |
||||||
|
|
||||||
|
while (--num_rows >= 0) { |
||||||
|
inptr = *input_buf++; |
||||||
|
outptr = output_buf[0][output_row]; |
||||||
|
output_row++; |
||||||
|
for (col = 0; col < num_cols; col++) { |
||||||
|
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ |
||||||
|
inptr += instride; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the JPEG colorspace. |
||||||
|
* This version handles multi-component colorspaces without conversion. |
||||||
|
* We assume input_components == num_components. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
null_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; |
||||||
|
register int ci; |
||||||
|
int nc = cinfo->num_components; |
||||||
|
JDIMENSION num_cols = cinfo->image_width; |
||||||
|
|
||||||
|
while (--num_rows >= 0) { |
||||||
|
/* It seems fastest to make a separate pass for each component. */ |
||||||
|
for (ci = 0; ci < nc; ci++) { |
||||||
|
inptr = *input_buf; |
||||||
|
outptr = output_buf[ci][output_row]; |
||||||
|
for (col = 0; col < num_cols; col++) { |
||||||
|
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ |
||||||
|
inptr += nc; |
||||||
|
} |
||||||
|
} |
||||||
|
input_buf++; |
||||||
|
output_row++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empty method for start_pass. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
null_method (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
/* no work needed */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for input colorspace conversion. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_color_converter (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_cconvert_ptr cconvert; |
||||||
|
|
||||||
|
cconvert = (my_cconvert_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(my_color_converter)); |
||||||
|
cinfo->cconvert = (struct jpeg_color_converter *) cconvert; |
||||||
|
/* set start_pass to null method until we find out differently */ |
||||||
|
cconvert->pub.start_pass = null_method; |
||||||
|
|
||||||
|
/* Make sure input_components agrees with in_color_space */ |
||||||
|
switch (cinfo->in_color_space) { |
||||||
|
case JCS_GRAYSCALE: |
||||||
|
if (cinfo->input_components != 1) |
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_RGB: |
||||||
|
#if RGB_PIXELSIZE != 3 |
||||||
|
if (cinfo->input_components != RGB_PIXELSIZE) |
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); |
||||||
|
break; |
||||||
|
#endif /* else share code with YCbCr */ |
||||||
|
|
||||||
|
case JCS_YCbCr: |
||||||
|
if (cinfo->input_components != 3) |
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_RGBA: |
||||||
|
case JCS_CMYK: |
||||||
|
case JCS_YCCK: |
||||||
|
if (cinfo->input_components != 4) |
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
default: /* JCS_UNKNOWN can be anything */ |
||||||
|
if (cinfo->input_components < 1) |
||||||
|
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Check num_components, set conversion method based on requested space */ |
||||||
|
switch (cinfo->jpeg_color_space) { |
||||||
|
case JCS_GRAYSCALE: |
||||||
|
if (cinfo->num_components != 1) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
if (cinfo->in_color_space == JCS_GRAYSCALE) |
||||||
|
cconvert->pub.color_convert = grayscale_convert; |
||||||
|
else if (cinfo->in_color_space == JCS_RGB) { |
||||||
|
cconvert->pub.start_pass = rgb_ycc_start; |
||||||
|
cconvert->pub.color_convert = rgb_gray_convert; |
||||||
|
} else if (cinfo->in_color_space == JCS_RGBA) { |
||||||
|
cconvert->pub.start_pass = rgb_ycc_start; |
||||||
|
cconvert->pub.color_convert = rgba_gray_convert; |
||||||
|
} else if (cinfo->in_color_space == JCS_YCbCr) |
||||||
|
cconvert->pub.color_convert = grayscale_convert; |
||||||
|
else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_RGB: |
||||||
|
if (cinfo->num_components != 3) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
else if (cinfo->in_color_space == JCS_RGBA) |
||||||
|
cconvert->pub.color_convert = rgba_rgb_convert; |
||||||
|
else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_YCbCr: |
||||||
|
if (cinfo->num_components != 3) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
if (cinfo->in_color_space == JCS_RGB) { |
||||||
|
cconvert->pub.start_pass = rgb_ycc_start; |
||||||
|
cconvert->pub.color_convert = rgb_ycc_convert; |
||||||
|
} else if (cinfo->in_color_space == JCS_RGBA) { |
||||||
|
cconvert->pub.start_pass = rgb_ycc_start; |
||||||
|
cconvert->pub.color_convert = rgba_ycc_convert; |
||||||
|
} else if (cinfo->in_color_space == JCS_YCbCr) |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_CMYK: |
||||||
|
if (cinfo->num_components != 4) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
if (cinfo->in_color_space == JCS_CMYK) |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_YCCK: |
||||||
|
if (cinfo->num_components != 4) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
if (cinfo->in_color_space == JCS_CMYK) { |
||||||
|
cconvert->pub.start_pass = rgb_ycc_start; |
||||||
|
cconvert->pub.color_convert = cmyk_ycck_convert; |
||||||
|
} else if (cinfo->in_color_space == JCS_YCCK) |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
default: /* allow null conversion of JCS_UNKNOWN */ |
||||||
|
if (cinfo->jpeg_color_space != cinfo->in_color_space || |
||||||
|
cinfo->num_components != cinfo->input_components) |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,482 @@ |
|||||||
|
/*
|
||||||
|
* 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. |
||||||
|
* |
||||||
|
* 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[MAX_COMPONENTS]; |
||||||
|
|
||||||
|
/* 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[MAX_COMPONENTS]; |
||||||
|
FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; |
||||||
|
#endif |
||||||
|
} my_fdct_controller; |
||||||
|
|
||||||
|
typedef my_fdct_controller * my_fdct_ptr; |
||||||
|
|
||||||
|
|
||||||
|
/* The current scaled-DCT routines require ISLOW-style divisor 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 DCT_SCALING_SUPPORTED |
||||||
|
#define PROVIDE_ISLOW_TABLES |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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. */ |
||||||
|
{ |
||||||
|
/* This routine is heavily used, so it's worth coding it tightly. */ |
||||||
|
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; |
||||||
|
forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; |
||||||
|
DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; |
||||||
|
DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ |
||||||
|
JDIMENSION bi; |
||||||
|
|
||||||
|
sample_data += start_row; /* fold in the vertical offset once */ |
||||||
|
|
||||||
|
for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { |
||||||
|
/* Perform the DCT */ |
||||||
|
(*do_dct) (workspace, sample_data, start_col); |
||||||
|
|
||||||
|
/* Quantize/descale the coefficients, and store into coef_blocks[] */ |
||||||
|
{ register DCTELEM temp, qval; |
||||||
|
register int i; |
||||||
|
register JCOEFPTR output_ptr = coef_blocks[bi]; |
||||||
|
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) { |
||||||
|
qval = divisors[i]; |
||||||
|
temp = workspace[i]; |
||||||
|
/* Divide the coefficient value by qval, ensuring proper rounding.
|
||||||
|
* Since C does not specify the direction of rounding for negative |
||||||
|
* quotients, we have to force the dividend positive for portability. |
||||||
|
* |
||||||
|
* In most files, at least half of the output values will be zero |
||||||
|
* (at default quantization settings, more like three-quarters...) |
||||||
|
* so we should ensure that this case is fast. On many machines, |
||||||
|
* a comparison is enough cheaper than a divide to make a special test |
||||||
|
* a win. Since both inputs will be nonnegative, we need only test |
||||||
|
* for a < b to discover whether a/b is 0. |
||||||
|
* If your machine's division is fast enough, define FAST_DIVIDE. |
||||||
|
*/ |
||||||
|
#ifdef FAST_DIVIDE |
||||||
|
#define DIVIDE_BY(a,b) a /= b |
||||||
|
#else |
||||||
|
#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 |
||||||
|
#endif |
||||||
|
if (temp < 0) { |
||||||
|
temp = -temp; |
||||||
|
temp += qval>>1; /* for rounding */ |
||||||
|
DIVIDE_BY(temp, qval); |
||||||
|
temp = -temp; |
||||||
|
} else { |
||||||
|
temp += qval>>1; /* for rounding */ |
||||||
|
DIVIDE_BY(temp, qval); |
||||||
|
} |
||||||
|
output_ptr[i] = (JCOEF) temp; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#ifdef DCT_FLOAT_SUPPORTED |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JSAMPARRAY sample_data, JBLOCKROW coef_blocks, |
||||||
|
JDIMENSION start_row, JDIMENSION start_col, |
||||||
|
JDIMENSION num_blocks) |
||||||
|
/* This version is used for floating-point DCT implementations. */ |
||||||
|
{ |
||||||
|
/* This routine is heavily used, so it's worth coding it tightly. */ |
||||||
|
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; |
||||||
|
float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; |
||||||
|
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; |
||||||
|
FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ |
||||||
|
JDIMENSION bi; |
||||||
|
|
||||||
|
sample_data += start_row; /* fold in the vertical offset once */ |
||||||
|
|
||||||
|
for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { |
||||||
|
/* Perform the DCT */ |
||||||
|
(*do_dct) (workspace, sample_data, start_col); |
||||||
|
|
||||||
|
/* Quantize/descale the coefficients, and store into coef_blocks[] */ |
||||||
|
{ register FAST_FLOAT temp; |
||||||
|
register int i; |
||||||
|
register JCOEFPTR output_ptr = coef_blocks[bi]; |
||||||
|
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) { |
||||||
|
/* Apply the quantization and scaling factor */ |
||||||
|
temp = workspace[i] * divisors[i]; |
||||||
|
/* Round to nearest integer.
|
||||||
|
* Since C does not specify the direction of rounding for negative |
||||||
|
* quotients, we have to force the dividend positive for portability. |
||||||
|
* The maximum coefficient size is +-16K (for 12-bit data), so this |
||||||
|
* code should work for either 16-bit or 32-bit ints. |
||||||
|
*/ |
||||||
|
output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* DCT_FLOAT_SUPPORTED */ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize 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; |
||||||
|
int method = 0; |
||||||
|
JQUANT_TBL * qtbl; |
||||||
|
DCTELEM * dtbl; |
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
/* Select the proper DCT routine for this component's scaling */ |
||||||
|
switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { |
||||||
|
#ifdef DCT_SCALING_SUPPORTED |
||||||
|
case ((1 << 8) + 1): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_1x1; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 2): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_2x2; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((3 << 8) + 3): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_3x3; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 4): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_4x4; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((5 << 8) + 5): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_5x5; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 6): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_6x6; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((7 << 8) + 7): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_7x7; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((9 << 8) + 9): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_9x9; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((10 << 8) + 10): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_10x10; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((11 << 8) + 11): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_11x11; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((12 << 8) + 12): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_12x12; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((13 << 8) + 13): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_13x13; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((14 << 8) + 14): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_14x14; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((15 << 8) + 15): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_15x15; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((16 << 8) + 16): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_16x16; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((16 << 8) + 8): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_16x8; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((14 << 8) + 7): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_14x7; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((12 << 8) + 6): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_12x6; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((10 << 8) + 5): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_10x5; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((8 << 8) + 4): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_8x4; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 3): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_6x3; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 2): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_4x2; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 1): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_2x1; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((8 << 8) + 16): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_8x16; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((7 << 8) + 14): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_7x14; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 12): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_6x12; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((5 << 8) + 10): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_5x10; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 8): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_4x8; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((3 << 8) + 6): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_3x6; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 4): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_2x4; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((1 << 8) + 2): |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_1x2; |
||||||
|
method = JDCT_ISLOW; /* jfdctint uses islow-style table */ |
||||||
|
break; |
||||||
|
#endif |
||||||
|
case ((DCTSIZE << 8) + DCTSIZE): |
||||||
|
switch (cinfo->dct_method) { |
||||||
|
#ifdef DCT_ISLOW_SUPPORTED |
||||||
|
case JDCT_ISLOW: |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_islow; |
||||||
|
method = JDCT_ISLOW; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_IFAST_SUPPORTED |
||||||
|
case JDCT_IFAST: |
||||||
|
fdct->do_dct[ci] = jpeg_fdct_ifast; |
||||||
|
method = JDCT_IFAST; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_FLOAT_SUPPORTED |
||||||
|
case JDCT_FLOAT: |
||||||
|
fdct->do_float_dct[ci] = jpeg_fdct_float; |
||||||
|
method = JDCT_FLOAT; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
default: |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
break; |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
ERREXIT2(cinfo, JERR_BAD_DCTSIZE, |
||||||
|
compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); |
||||||
|
break; |
||||||
|
} |
||||||
|
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 (method) { |
||||||
|
#ifdef PROVIDE_ISLOW_TABLES |
||||||
|
case JDCT_ISLOW: |
||||||
|
/* For LL&M IDCT method, divisors are equal to raw quantization
|
||||||
|
* coefficients multiplied by 8 (to counteract scaling). |
||||||
|
*/ |
||||||
|
if (fdct->divisors[qtblno] == NULL) { |
||||||
|
fdct->divisors[qtblno] = (DCTELEM *) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
DCTSIZE2 * SIZEOF(DCTELEM)); |
||||||
|
} |
||||||
|
dtbl = fdct->divisors[qtblno]; |
||||||
|
for (i = 0; i < DCTSIZE2; i++) { |
||||||
|
dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; |
||||||
|
} |
||||||
|
fdct->pub.forward_DCT[ci] = forward_DCT; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_IFAST_SUPPORTED |
||||||
|
case JDCT_IFAST: |
||||||
|
{ |
||||||
|
/* For AA&N IDCT method, divisors are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where |
||||||
|
* scalefactor[0] = 1 |
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 |
||||||
|
* We apply a further scale factor of 8. |
||||||
|
*/ |
||||||
|
#define CONST_BITS 14 |
||||||
|
static const INT16 aanscales[DCTSIZE2] = { |
||||||
|
/* precomputed values scaled up by 14 bits */ |
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, |
||||||
|
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, |
||||||
|
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, |
||||||
|
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, |
||||||
|
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, |
||||||
|
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, |
||||||
|
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, |
||||||
|
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 |
||||||
|
}; |
||||||
|
SHIFT_TEMPS |
||||||
|
|
||||||
|
if (fdct->divisors[qtblno] == NULL) { |
||||||
|
fdct->divisors[qtblno] = (DCTELEM *) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
DCTSIZE2 * SIZEOF(DCTELEM)); |
||||||
|
} |
||||||
|
dtbl = fdct->divisors[qtblno]; |
||||||
|
for (i = 0; i < DCTSIZE2; i++) { |
||||||
|
dtbl[i] = (DCTELEM) |
||||||
|
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], |
||||||
|
(INT32) aanscales[i]), |
||||||
|
CONST_BITS-3); |
||||||
|
} |
||||||
|
} |
||||||
|
fdct->pub.forward_DCT[ci] = forward_DCT; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_FLOAT_SUPPORTED |
||||||
|
case JDCT_FLOAT: |
||||||
|
{ |
||||||
|
/* For float AA&N IDCT method, divisors are equal to quantization
|
||||||
|
* coefficients scaled by scalefactor[row]*scalefactor[col], where |
||||||
|
* scalefactor[0] = 1 |
||||||
|
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 |
||||||
|
* We apply a further scale factor of 8. |
||||||
|
* What's actually stored is 1/divisor so that the inner loop can |
||||||
|
* use a multiplication rather than a division. |
||||||
|
*/ |
||||||
|
FAST_FLOAT * fdtbl; |
||||||
|
int row, col; |
||||||
|
static const double aanscalefactor[DCTSIZE] = { |
||||||
|
1.0, 1.387039845, 1.306562965, 1.175875602, |
||||||
|
1.0, 0.785694958, 0.541196100, 0.275899379 |
||||||
|
}; |
||||||
|
|
||||||
|
if (fdct->float_divisors[qtblno] == NULL) { |
||||||
|
fdct->float_divisors[qtblno] = (FAST_FLOAT *) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
DCTSIZE2 * SIZEOF(FAST_FLOAT)); |
||||||
|
} |
||||||
|
fdtbl = fdct->float_divisors[qtblno]; |
||||||
|
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++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
fdct->pub.forward_DCT[ci] = forward_DCT_float; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
default: |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize FDCT manager. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_forward_dct (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_fdct_ptr fdct; |
||||||
|
int i; |
||||||
|
|
||||||
|
fdct = (my_fdct_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(my_fdct_controller)); |
||||||
|
cinfo->fdct = (struct jpeg_forward_dct *) fdct; |
||||||
|
fdct->pub.start_pass = start_pass_fdctmgr; |
||||||
|
|
||||||
|
/* 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 |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@ |
|||||||
|
/*
|
||||||
|
* 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) |
||||||
|
jinit_arith_encoder(cinfo); |
||||||
|
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); |
||||||
|
} |
@ -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 < (JDIMENSION) cinfo->min_DCT_v_scaled_size) |
||||||
|
(*cinfo->prep->pre_process_data) (cinfo, |
||||||
|
input_buf, in_row_ctr, in_rows_avail, |
||||||
|
main->buffer, &main->rowgroup_ctr, |
||||||
|
(JDIMENSION) cinfo->min_DCT_v_scaled_size); |
||||||
|
|
||||||
|
/* 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 != (JDIMENSION) cinfo->min_DCT_v_scaled_size) |
||||||
|
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 * compptr->DCT_h_scaled_size, |
||||||
|
(JDIMENSION) jround_up((long) compptr->height_in_blocks, |
||||||
|
(long) compptr->v_samp_factor) * DCTSIZE, |
||||||
|
(JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); |
||||||
|
} |
||||||
|
#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 * compptr->DCT_h_scaled_size, |
||||||
|
(JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,682 @@ |
|||||||
|
/*
|
||||||
|
* jcmarker.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane. |
||||||
|
* Modified 2003-2010 by Guido Vollbeding. |
||||||
|
* 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 <= cinfo->lim_Se; i++) { |
||||||
|
if (qtbl->quantval[cinfo->natural_order[i]] > 255) |
||||||
|
prec = 1; |
||||||
|
} |
||||||
|
|
||||||
|
if (! qtbl->sent_table) { |
||||||
|
emit_marker(cinfo, M_DQT); |
||||||
|
|
||||||
|
emit_2bytes(cinfo, |
||||||
|
prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); |
||||||
|
|
||||||
|
emit_byte(cinfo, index + (prec<<4)); |
||||||
|
|
||||||
|
for (i = 0; i <= cinfo->lim_Se; i++) { |
||||||
|
/* The table entries must be emitted in zigzag order. */ |
||||||
|
unsigned int qval = qtbl->quantval[cinfo->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 needs no table for refinement scan */ |
||||||
|
if (cinfo->Ss == 0 && cinfo->Ah == 0) |
||||||
|
dc_in_use[compptr->dc_tbl_no] = 1; |
||||||
|
/* AC needs no table when not present */ |
||||||
|
if (cinfo->Se) |
||||||
|
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]; |
||||||
|
|
||||||
|
if (length) { |
||||||
|
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->jpeg_height > 65535L || |
||||||
|
(long) cinfo->jpeg_width > 65535L) |
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); |
||||||
|
|
||||||
|
emit_byte(cinfo, cinfo->data_precision); |
||||||
|
emit_2bytes(cinfo, (int) cinfo->jpeg_height); |
||||||
|
emit_2bytes(cinfo, (int) cinfo->jpeg_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); |
||||||
|
|
||||||
|
/* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* DC needs no table for refinement scan */ |
||||||
|
td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; |
||||||
|
/* AC needs no table when not present */ |
||||||
|
ta = cinfo->Se ? compptr->ac_tbl_no : 0; |
||||||
|
|
||||||
|
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_pseudo_sos (j_compress_ptr cinfo) |
||||||
|
/* Emit a pseudo SOS marker */ |
||||||
|
{ |
||||||
|
emit_marker(cinfo, M_SOS); |
||||||
|
|
||||||
|
emit_2bytes(cinfo, 2 + 1 + 3); /* length */ |
||||||
|
|
||||||
|
emit_byte(cinfo, 0); /* Ns */ |
||||||
|
|
||||||
|
emit_byte(cinfo, 0); /* Ss */ |
||||||
|
emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ |
||||||
|
emit_byte(cinfo, 0); /* Ah/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, and a conditional pseudo SOS marker. |
||||||
|
* 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 || cinfo->block_size != DCTSIZE) { |
||||||
|
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) { |
||||||
|
if (cinfo->progressive_mode) |
||||||
|
emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ |
||||||
|
else |
||||||
|
emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ |
||||||
|
} 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 */ |
||||||
|
} |
||||||
|
|
||||||
|
/* Check to emit pseudo SOS marker */ |
||||||
|
if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) |
||||||
|
emit_pseudo_sos(cinfo); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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]; |
||||||
|
/* DC needs no table for refinement scan */ |
||||||
|
if (cinfo->Ss == 0 && cinfo->Ah == 0) |
||||||
|
emit_dht(cinfo, compptr->dc_tbl_no, FALSE); |
||||||
|
/* AC needs no table when not present */ |
||||||
|
if (cinfo->Se) |
||||||
|
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; |
||||||
|
} |
@ -0,0 +1,858 @@ |
|||||||
|
/*
|
||||||
|
* jcmaster.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane. |
||||||
|
* Modified 2003-2011 by Guido Vollbeding. |
||||||
|
* 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 master control logic for the JPEG compressor. |
||||||
|
* These routines are concerned with parameter validation, initial setup, |
||||||
|
* 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 "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Private state */ |
||||||
|
|
||||||
|
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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute JPEG image dimensions and related values. |
||||||
|
* NOTE: this is exported for possible use by application. |
||||||
|
* Hence it mustn't do anything that can't be done twice. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo) |
||||||
|
/* Do computations that are needed before master selection phase */ |
||||||
|
{ |
||||||
|
#ifdef DCT_SCALING_SUPPORTED |
||||||
|
|
||||||
|
/* Sanity check on input image dimensions to prevent overflow in
|
||||||
|
* following calculation. |
||||||
|
* We do check jpeg_width and jpeg_height in initial_setup below, |
||||||
|
* but image_width and image_height can come from arbitrary data, |
||||||
|
* and we need some space for multiplication by block_size. |
||||||
|
*/ |
||||||
|
if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) |
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); |
||||||
|
|
||||||
|
/* Compute actual JPEG image dimensions and DCT scaling choices. */ |
||||||
|
if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/1 scaling */ |
||||||
|
cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; |
||||||
|
cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; |
||||||
|
cinfo->min_DCT_h_scaled_size = 1; |
||||||
|
cinfo->min_DCT_v_scaled_size = 1; |
||||||
|
} else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/2 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 2; |
||||||
|
cinfo->min_DCT_v_scaled_size = 2; |
||||||
|
} else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/3 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 3; |
||||||
|
cinfo->min_DCT_v_scaled_size = 3; |
||||||
|
} else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/4 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 4; |
||||||
|
cinfo->min_DCT_v_scaled_size = 4; |
||||||
|
} else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/5 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 5; |
||||||
|
cinfo->min_DCT_v_scaled_size = 5; |
||||||
|
} else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/6 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 6; |
||||||
|
cinfo->min_DCT_v_scaled_size = 6; |
||||||
|
} else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/7 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 7; |
||||||
|
cinfo->min_DCT_v_scaled_size = 7; |
||||||
|
} else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/8 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 8; |
||||||
|
cinfo->min_DCT_v_scaled_size = 8; |
||||||
|
} else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/9 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 9; |
||||||
|
cinfo->min_DCT_v_scaled_size = 9; |
||||||
|
} else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/10 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 10; |
||||||
|
cinfo->min_DCT_v_scaled_size = 10; |
||||||
|
} else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/11 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 11; |
||||||
|
cinfo->min_DCT_v_scaled_size = 11; |
||||||
|
} else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/12 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 12; |
||||||
|
cinfo->min_DCT_v_scaled_size = 12; |
||||||
|
} else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/13 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 13; |
||||||
|
cinfo->min_DCT_v_scaled_size = 13; |
||||||
|
} else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/14 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 14; |
||||||
|
cinfo->min_DCT_v_scaled_size = 14; |
||||||
|
} else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { |
||||||
|
/* Provide block_size/15 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 15; |
||||||
|
cinfo->min_DCT_v_scaled_size = 15; |
||||||
|
} else { |
||||||
|
/* Provide block_size/16 scaling */ |
||||||
|
cinfo->jpeg_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); |
||||||
|
cinfo->jpeg_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); |
||||||
|
cinfo->min_DCT_h_scaled_size = 16; |
||||||
|
cinfo->min_DCT_v_scaled_size = 16; |
||||||
|
} |
||||||
|
|
||||||
|
#else /* !DCT_SCALING_SUPPORTED */ |
||||||
|
|
||||||
|
/* Hardwire it to "no scaling" */ |
||||||
|
cinfo->jpeg_width = cinfo->image_width; |
||||||
|
cinfo->jpeg_height = cinfo->image_height; |
||||||
|
cinfo->min_DCT_h_scaled_size = DCTSIZE; |
||||||
|
cinfo->min_DCT_v_scaled_size = DCTSIZE; |
||||||
|
|
||||||
|
#endif /* DCT_SCALING_SUPPORTED */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
jpeg_calc_trans_dimensions (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) |
||||||
|
ERREXIT2(cinfo, JERR_BAD_DCTSIZE, |
||||||
|
cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); |
||||||
|
|
||||||
|
cinfo->block_size = cinfo->min_DCT_h_scaled_size; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
initial_setup (j_compress_ptr cinfo, boolean transcode_only) |
||||||
|
/* Do computations that are needed before master selection phase */ |
||||||
|
{ |
||||||
|
int ci, ssize; |
||||||
|
jpeg_component_info *compptr; |
||||||
|
long samplesperrow; |
||||||
|
JDIMENSION jd_samplesperrow; |
||||||
|
|
||||||
|
if (transcode_only) |
||||||
|
jpeg_calc_trans_dimensions(cinfo); |
||||||
|
else |
||||||
|
jpeg_calc_jpeg_dimensions(cinfo); |
||||||
|
|
||||||
|
/* Sanity check on block_size */ |
||||||
|
if (cinfo->block_size < 1 || cinfo->block_size > 16) |
||||||
|
ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); |
||||||
|
|
||||||
|
/* Derive natural_order from block_size */ |
||||||
|
switch (cinfo->block_size) { |
||||||
|
case 2: cinfo->natural_order = jpeg_natural_order2; break; |
||||||
|
case 3: cinfo->natural_order = jpeg_natural_order3; break; |
||||||
|
case 4: cinfo->natural_order = jpeg_natural_order4; break; |
||||||
|
case 5: cinfo->natural_order = jpeg_natural_order5; break; |
||||||
|
case 6: cinfo->natural_order = jpeg_natural_order6; break; |
||||||
|
case 7: cinfo->natural_order = jpeg_natural_order7; break; |
||||||
|
default: cinfo->natural_order = jpeg_natural_order; break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Derive lim_Se from block_size */ |
||||||
|
cinfo->lim_Se = cinfo->block_size < DCTSIZE ? |
||||||
|
cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; |
||||||
|
|
||||||
|
/* Sanity check on image dimensions */ |
||||||
|
if (cinfo->jpeg_height <= 0 || cinfo->jpeg_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->jpeg_height > (long) JPEG_MAX_DIMENSION || |
||||||
|
(long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) |
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); |
||||||
|
|
||||||
|
/* Width of an input scanline must be representable as JDIMENSION. */ |
||||||
|
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; |
||||||
|
jd_samplesperrow = (JDIMENSION) samplesperrow; |
||||||
|
if ((long) jd_samplesperrow != samplesperrow) |
||||||
|
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); |
||||||
|
|
||||||
|
/* For now, precision must match compiled-in value... */ |
||||||
|
if (cinfo->data_precision != BITS_IN_JSAMPLE) |
||||||
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); |
||||||
|
|
||||||
|
/* Check that number of components won't exceed internal array sizes */ |
||||||
|
if (cinfo->num_components > MAX_COMPONENTS) |
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, |
||||||
|
MAX_COMPONENTS); |
||||||
|
|
||||||
|
/* Compute maximum sampling factors; check factor validity */ |
||||||
|
cinfo->max_h_samp_factor = 1; |
||||||
|
cinfo->max_v_samp_factor = 1; |
||||||
|
for (ci = 0, 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); |
||||||
|
} |
||||||
|
|
||||||
|
/* Compute dimensions of components */ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
/* Fill in the correct component_index value; don't rely on application */ |
||||||
|
compptr->component_index = ci; |
||||||
|
/* In selecting the actual DCT scaling for each component, we try to
|
||||||
|
* scale down the chroma components via DCT scaling rather than downsampling. |
||||||
|
* This saves time if the downsampler gets to use 1:1 scaling. |
||||||
|
* Note this code adapts subsampling ratios which are powers of 2. |
||||||
|
*/ |
||||||
|
ssize = 1; |
||||||
|
#ifdef DCT_SCALING_SUPPORTED |
||||||
|
while (cinfo->min_DCT_h_scaled_size * ssize <= |
||||||
|
(cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && |
||||||
|
(cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { |
||||||
|
ssize = ssize * 2; |
||||||
|
} |
||||||
|
#endif |
||||||
|
compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; |
||||||
|
ssize = 1; |
||||||
|
#ifdef DCT_SCALING_SUPPORTED |
||||||
|
while (cinfo->min_DCT_v_scaled_size * ssize <= |
||||||
|
(cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && |
||||||
|
(cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { |
||||||
|
ssize = ssize * 2; |
||||||
|
} |
||||||
|
#endif |
||||||
|
compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; |
||||||
|
|
||||||
|
/* We don't support DCT ratios larger than 2. */ |
||||||
|
if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) |
||||||
|
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; |
||||||
|
else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) |
||||||
|
compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; |
||||||
|
|
||||||
|
/* Size in DCT blocks */ |
||||||
|
compptr->width_in_blocks = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, |
||||||
|
(long) (cinfo->max_h_samp_factor * cinfo->block_size)); |
||||||
|
compptr->height_in_blocks = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
/* Size in samples */ |
||||||
|
compptr->downsampled_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->jpeg_width * |
||||||
|
(long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), |
||||||
|
(long) (cinfo->max_h_samp_factor * cinfo->block_size)); |
||||||
|
compptr->downsampled_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->jpeg_height * |
||||||
|
(long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
/* 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->jpeg_height, |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
reduce_script (j_compress_ptr cinfo) |
||||||
|
/* Adapt scan script for use with reduced block size;
|
||||||
|
* assume that script has been validated before. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
jpeg_scan_info * scanptr; |
||||||
|
int idxout, idxin; |
||||||
|
|
||||||
|
/* Circumvent const declaration for this function */ |
||||||
|
scanptr = (jpeg_scan_info *) cinfo->scan_info; |
||||||
|
idxout = 0; |
||||||
|
|
||||||
|
for (idxin = 0; idxin < cinfo->num_scans; idxin++) { |
||||||
|
/* After skipping, idxout becomes smaller than idxin */ |
||||||
|
if (idxin != idxout) |
||||||
|
/* Copy rest of data;
|
||||||
|
* note we stay in given chunk of allocated memory. |
||||||
|
*/ |
||||||
|
scanptr[idxout] = scanptr[idxin]; |
||||||
|
if (scanptr[idxout].Ss > cinfo->lim_Se) |
||||||
|
/* Entire scan out of range - skip this entry */ |
||||||
|
continue; |
||||||
|
if (scanptr[idxout].Se > cinfo->lim_Se) |
||||||
|
/* Limit scan to end of block */ |
||||||
|
scanptr[idxout].Se = cinfo->lim_Se; |
||||||
|
idxout++; |
||||||
|
} |
||||||
|
|
||||||
|
cinfo->num_scans = idxout; |
||||||
|
} |
||||||
|
|
||||||
|
#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]]; |
||||||
|
} |
||||||
|
if (cinfo->progressive_mode) { |
||||||
|
cinfo->Ss = scanptr->Ss; |
||||||
|
cinfo->Se = scanptr->Se; |
||||||
|
cinfo->Ah = scanptr->Ah; |
||||||
|
cinfo->Al = scanptr->Al; |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
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 = cinfo->block_size * cinfo->block_size - 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 = compptr->DCT_h_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->jpeg_width, |
||||||
|
(long) (cinfo->max_h_samp_factor * cinfo->block_size)); |
||||||
|
cinfo->MCU_rows_in_scan = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->jpeg_height, |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
|
||||||
|
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_h_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 > 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-pass setup. |
||||||
|
* This is called at the beginning of each pass. We determine which modules |
||||||
|
* will be active during this pass and give them appropriate start_pass calls. |
||||||
|
* We also set is_last_pass to indicate whether any more passes will be |
||||||
|
* required. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
prepare_for_pass (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master; |
||||||
|
|
||||||
|
switch (master->pass_type) { |
||||||
|
case main_pass: |
||||||
|
/* 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->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); |
||||||
|
} |
||||||
|
|
||||||
|
master->pub.is_last_pass = (master->pass_number == master->total_passes-1); |
||||||
|
|
||||||
|
/* Set up progress monitor's pass info if present */ |
||||||
|
if (cinfo->progress != NULL) { |
||||||
|
cinfo->progress->completed_passes = master->pass_number; |
||||||
|
cinfo->progress->total_passes = master->total_passes; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special start-of-pass hook. |
||||||
|
* This is called by jpeg_write_scanlines if call_pass_startup is TRUE. |
||||||
|
* In single-pass processing, we need this hook because we don't want to |
||||||
|
* write frame/scan headers during jpeg_start_compress; we want to let the |
||||||
|
* application write COM markers etc. between jpeg_start_compress and the |
||||||
|
* jpeg_write_scanlines loop. |
||||||
|
* In multi-pass processing, this routine is not used. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
pass_startup (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ |
||||||
|
|
||||||
|
(*cinfo->marker->write_frame_header) (cinfo); |
||||||
|
(*cinfo->marker->write_scan_header) (cinfo); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up at end of pass. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
finish_pass_master (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
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, transcode_only); |
||||||
|
|
||||||
|
if (cinfo->scan_info != NULL) { |
||||||
|
#ifdef C_MULTISCAN_FILES_SUPPORTED |
||||||
|
validate_script(cinfo); |
||||||
|
if (cinfo->block_size < DCTSIZE) |
||||||
|
reduce_script(cinfo); |
||||||
|
#else |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
#endif |
||||||
|
} else { |
||||||
|
cinfo->progressive_mode = FALSE; |
||||||
|
cinfo->num_scans = 1; |
||||||
|
} |
||||||
|
|
||||||
|
if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && |
||||||
|
!cinfo->arith_code) /* TEMPORARY HACK ??? */ |
||||||
|
/* assume default tables no good for progressive or downscale mode */ |
||||||
|
cinfo->optimize_coding = TRUE; |
||||||
|
|
||||||
|
/* 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; |
||||||
|
} |
@ -0,0 +1,106 @@ |
|||||||
|
/*
|
||||||
|
* 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. |
||||||
|
* |
||||||
|
* 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; |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS or OS/2. */ |
||||||
|
/* see jconfig.txt 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 |
||||||
|
#ifdef __MSDOS__ |
||||||
|
#define NEED_FAR_POINTERS /* for small or medium memory model */ |
||||||
|
#endif |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN /* this assumes you have -w-stu in CFLAGS */ |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#ifdef __MSDOS__ |
||||||
|
#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ |
||||||
|
#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ |
||||||
|
#define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE |
||||||
|
#define USE_SETMODE /* Borland has setmode() */ |
||||||
|
#ifdef __MSDOS__ |
||||||
|
#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ |
||||||
|
#endif |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,53 @@ |
|||||||
|
/* jconfig.cfg --- source file edited by configure script */ |
||||||
|
/* see jconfig.txt 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 HAVE_LOCALE_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, on Windows systems. */ |
||||||
|
#ifdef _WIN32 |
||||||
|
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ |
||||||
|
typedef unsigned char boolean; |
||||||
|
#endif |
||||||
|
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
#undef INLINE |
||||||
|
/* These are for configuring the JPEG memory manager. */ |
||||||
|
#undef DEFAULT_MAX_MEM |
||||||
|
#undef NO_MKTEMP |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE |
||||||
|
#undef NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
|
||||||
|
/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ |
||||||
|
#undef PROGRESS_REPORT |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,38 @@ |
|||||||
|
/* jconfig.dj --- jconfig.h for DJGPP (Delorie's GNU C port) on MS-DOS. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */ |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE /* optional */ |
||||||
|
#define USE_SETMODE /* Needed to make one-file style work in DJGPP */ |
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,43 @@ |
|||||||
|
/* jconfig.mac --- jconfig.h for CodeWarrior on Apple Macintosh */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */ |
||||||
|
|
||||||
|
#define ALIGN_TYPE long /* Needed for 680x0 Macs */ |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define USE_CCOMMAND /* Command line reader for Macintosh */ |
||||||
|
#define TWO_FILE_COMMANDLINE /* Binary I/O thru stdin/stdout doesn't work */ |
||||||
|
|
||||||
|
#undef NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,43 @@ |
|||||||
|
/* jconfig.manx --- jconfig.h for Amiga systems using Manx Aztec C ver 5.x. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ |
||||||
|
|
||||||
|
#define SHORTxSHORT_32 /* produces better DCT code with Aztec C */ |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE |
||||||
|
#define NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#define signal_catcher _abort /* hack for Aztec C naming requirements */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,52 @@ |
|||||||
|
/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#define NEED_FAR_POINTERS /* for small or medium memory model */ |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ |
||||||
|
|
||||||
|
#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ |
||||||
|
|
||||||
|
#define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ |
||||||
|
|
||||||
|
#define NEED_FHEAPMIN /* far heap management routines are broken */ |
||||||
|
|
||||||
|
#define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ |
||||||
|
/* Note: the above define is known to improve the code with Microsoft C 6.00A. |
||||||
|
* I do not know whether it is good for later compiler versions. |
||||||
|
* Please report any info on this point to jpeg-info@uc.ag. |
||||||
|
*/ |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE |
||||||
|
#define USE_SETMODE /* Microsoft has setmode() */ |
||||||
|
#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,43 @@ |
|||||||
|
/* jconfig.sas --- jconfig.h for Amiga systems using SAS C 6.0 and up. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ |
||||||
|
|
||||||
|
#define NO_MKTEMP /* SAS C doesn't have mktemp() */ |
||||||
|
|
||||||
|
#define SHORTxSHORT_32 /* produces better DCT code with SAS C */ |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE |
||||||
|
#define NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,42 @@ |
|||||||
|
/* jconfig.st --- jconfig.h for Atari ST/STE/TT using Pure C or Turbo C. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */ |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#define ALIGN_TYPE long /* apparently double is a weird size? */ |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE /* optional -- undef if you like Unix style */ |
||||||
|
/* Note: if you undef TWO_FILE_COMMANDLINE, you may need to define |
||||||
|
* USE_SETMODE. Some Atari compilers require it, some do not. |
||||||
|
*/ |
||||||
|
#define NEED_SIGNAL_CATCHER /* needed if you use jmemname.c */ |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,164 @@ |
|||||||
|
/* |
||||||
|
* jconfig.txt |
||||||
|
* |
||||||
|
* 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.txt) |
||||||
|
*/ |
||||||
|
#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 |
||||||
|
|
||||||
|
/* Define "boolean" as unsigned char, not int, on Windows systems. |
||||||
|
*/ |
||||||
|
#ifdef _WIN32 |
||||||
|
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ |
||||||
|
typedef unsigned char boolean; |
||||||
|
#endif |
||||||
|
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* 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 */ |
@ -0,0 +1,45 @@ |
|||||||
|
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ |
||||||
|
/* see jconfig.txt 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 */ |
||||||
|
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ |
||||||
|
typedef unsigned char boolean; |
||||||
|
#endif |
||||||
|
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ |
||||||
|
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE /* optional */ |
||||||
|
#define USE_SETMODE /* Microsoft has setmode() */ |
||||||
|
#undef NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,37 @@ |
|||||||
|
/* jconfig.vms --- jconfig.h for use on Digital VMS. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#undef CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#define TWO_FILE_COMMANDLINE /* Needed on VMS */ |
||||||
|
#undef NEED_SIGNAL_CATCHER |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,38 @@ |
|||||||
|
/* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */ |
||||||
|
/* see jconfig.txt for explanations */ |
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES |
||||||
|
#define HAVE_UNSIGNED_CHAR |
||||||
|
#define HAVE_UNSIGNED_SHORT |
||||||
|
/* #define void char */ |
||||||
|
/* #define const */ |
||||||
|
#define CHAR_IS_UNSIGNED |
||||||
|
#define HAVE_STDDEF_H |
||||||
|
#define HAVE_STDLIB_H |
||||||
|
#undef NEED_BSD_STRINGS |
||||||
|
#undef NEED_SYS_TYPES_H |
||||||
|
#undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ |
||||||
|
#undef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#undef INCOMPLETE_TYPES_BROKEN |
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS |
||||||
|
|
||||||
|
#undef RIGHT_SHIFT_IS_UNSIGNED |
||||||
|
|
||||||
|
#endif /* JPEG_INTERNALS */ |
||||||
|
|
||||||
|
#ifdef JPEG_CJPEG_DJPEG |
||||||
|
|
||||||
|
#define BMP_SUPPORTED /* BMP image file format */ |
||||||
|
#define GIF_SUPPORTED /* GIF image file format */ |
||||||
|
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ |
||||||
|
#undef RLE_SUPPORTED /* Utah RLE image file format */ |
||||||
|
#define TARGA_SUPPORTED /* Targa image file format */ |
||||||
|
|
||||||
|
#undef TWO_FILE_COMMANDLINE /* optional */ |
||||||
|
#define USE_SETMODE /* Needed to make one-file style work in Watcom */ |
||||||
|
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ |
||||||
|
#undef DONT_USE_B_MODE |
||||||
|
#undef PROGRESS_REPORT /* optional */ |
||||||
|
|
||||||
|
#endif /* JPEG_CJPEG_DJPEG */ |
@ -0,0 +1,633 @@ |
|||||||
|
/*
|
||||||
|
* jcparam.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane. |
||||||
|
* Modified 2003-2008 by Guido Vollbeding. |
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* 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 |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) |
||||||
|
/* Set or change the 'quality' (quantization) setting, using default tables
|
||||||
|
* and straight percentage-scaling quality scales. |
||||||
|
* This entry point allows different scalings for luminance and chrominance. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
/* Set up two quantization tables using the specified scaling */ |
||||||
|
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, |
||||||
|
cinfo->q_scale_factor[0], force_baseline); |
||||||
|
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, |
||||||
|
cinfo->q_scale_factor[1], force_baseline); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
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. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
/* 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->scale_num = 1; /* 1:1 scaling */ |
||||||
|
cinfo->scale_denom = 1; |
||||||
|
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; |
||||||
|
|
||||||
|
/* By default, apply fancy downsampling */ |
||||||
|
cinfo->do_fancy_downsampling = TRUE; |
||||||
|
|
||||||
|
/* 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: |
||||||
|
case JCS_RGBA: |
||||||
|
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 */ |
@ -0,0 +1,358 @@ |
|||||||
|
/*
|
||||||
|
* 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++) { |
||||||
|
numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_scaled_size; |
||||||
|
expand_bottom_edge(output_buf[ci], |
||||||
|
compptr->width_in_blocks * compptr->DCT_h_scaled_size, |
||||||
|
(int) (*out_row_group_ctr * numrows), |
||||||
|
(int) (out_row_groups_avail * numrows)); |
||||||
|
} |
||||||
|
*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 * |
||||||
|
cinfo->min_DCT_h_scaled_size * |
||||||
|
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 * |
||||||
|
cinfo->min_DCT_h_scaled_size * |
||||||
|
cinfo->max_h_samp_factor) / compptr->h_samp_factor), |
||||||
|
(JDIMENSION) cinfo->max_v_samp_factor); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,545 @@ |
|||||||
|
/*
|
||||||
|
* jcsample.c |
||||||
|
* |
||||||
|
* 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. |
||||||
|
* |
||||||
|
* This file contains downsampling routines. |
||||||
|
* |
||||||
|
* Downsampling input data is counted in "row groups". A row group |
||||||
|
* is defined to be max_v_samp_factor pixel rows of each component, |
||||||
|
* from which the downsampler produces v_samp_factor sample rows. |
||||||
|
* A single row group is processed in each call to the downsampler module. |
||||||
|
* |
||||||
|
* The downsampler is responsible for edge-expansion of its output data |
||||||
|
* to fill an integral number of DCT blocks horizontally. The source buffer |
||||||
|
* may be modified if it is helpful for this purpose (the source buffer is |
||||||
|
* allocated wide enough to correspond to the desired output width). |
||||||
|
* The caller (the prep controller) is responsible for vertical padding. |
||||||
|
* |
||||||
|
* The downsampler may request "context rows" by setting need_context_rows |
||||||
|
* during startup. In this case, the input arrays will contain at least |
||||||
|
* one row group's worth of pixels above and below the passed-in data; |
||||||
|
* the caller will create dummy rows at image top and bottom by replicating |
||||||
|
* the first or last real pixel row. |
||||||
|
* |
||||||
|
* An excellent reference for image resampling is |
||||||
|
* Digital Image Warping, George Wolberg, 1990. |
||||||
|
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. |
||||||
|
* |
||||||
|
* The downsampling algorithm used here is a simple average of the source |
||||||
|
* pixels covered by the output pixel. The hi-falutin sampling literature |
||||||
|
* refers to this as a "box filter". In general the characteristics of a box |
||||||
|
* filter are not very good, but for the specific cases we normally use (1:1 |
||||||
|
* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not |
||||||
|
* nearly so bad. If you intend to use other sampling ratios, you'd be well |
||||||
|
* advised to improve this code. |
||||||
|
* |
||||||
|
* A simple input-smoothing capability is provided. This is mainly intended |
||||||
|
* for cleaning up color-dithered GIF input files (if you find it inadequate, |
||||||
|
* we suggest using an external filtering program such as pnmconvol). When |
||||||
|
* enabled, each input pixel P is replaced by a weighted sum of itself and its |
||||||
|
* eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, |
||||||
|
* where SF = (smoothing_factor / 1024). |
||||||
|
* Currently, smoothing is only supported for 2h2v sampling factors. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Pointer to routine to downsample a single component */ |
||||||
|
typedef JMETHOD(void, downsample1_ptr, |
||||||
|
(j_compress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data)); |
||||||
|
|
||||||
|
/* Private subobject */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_downsampler pub; /* public fields */ |
||||||
|
|
||||||
|
/* Downsampling method pointers, one per component */ |
||||||
|
downsample1_ptr methods[MAX_COMPONENTS]; |
||||||
|
|
||||||
|
/* Height of an output row group for each component. */ |
||||||
|
int rowgroup_height[MAX_COMPONENTS]; |
||||||
|
|
||||||
|
/* These arrays save pixel expansion factors so that int_downsample need not
|
||||||
|
* recompute them each time. They are unused for other downsampling methods. |
||||||
|
*/ |
||||||
|
UINT8 h_expand[MAX_COMPONENTS]; |
||||||
|
UINT8 v_expand[MAX_COMPONENTS]; |
||||||
|
} my_downsampler; |
||||||
|
|
||||||
|
typedef my_downsampler * my_downsample_ptr; |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a downsampling pass. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
start_pass_downsample (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
/* no work for now */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand a component horizontally from width input_cols to width output_cols, |
||||||
|
* by duplicating the rightmost samples. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
expand_right_edge (JSAMPARRAY image_data, int num_rows, |
||||||
|
JDIMENSION input_cols, JDIMENSION output_cols) |
||||||
|
{ |
||||||
|
register JSAMPROW ptr; |
||||||
|
register JSAMPLE pixval; |
||||||
|
register int count; |
||||||
|
int row; |
||||||
|
int numcols = (int) (output_cols - input_cols); |
||||||
|
|
||||||
|
if (numcols > 0) { |
||||||
|
for (row = 0; row < num_rows; row++) { |
||||||
|
ptr = image_data[row] + input_cols; |
||||||
|
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ |
||||||
|
for (count = numcols; count > 0; count--) |
||||||
|
*ptr++ = pixval; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do downsampling for a whole row group (all components). |
||||||
|
* |
||||||
|
* In this version we simply downsample each component independently. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
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 * downsample->rowgroup_height[ci]); |
||||||
|
(*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) |
||||||
|
{ |
||||||
|
my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; |
||||||
|
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; |
||||||
|
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ |
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
||||||
|
JSAMPROW inptr, outptr; |
||||||
|
INT32 outvalue; |
||||||
|
|
||||||
|
h_expand = downsample->h_expand[compptr->component_index]; |
||||||
|
v_expand = downsample->v_expand[compptr->component_index]; |
||||||
|
numpix = h_expand * v_expand; |
||||||
|
numpix2 = numpix/2; |
||||||
|
|
||||||
|
/* Expand input data enough to let all the output samples be generated
|
||||||
|
* by the standard loop. Special-casing padded output would be more |
||||||
|
* efficient. |
||||||
|
*/ |
||||||
|
expand_right_edge(input_data, cinfo->max_v_samp_factor, |
||||||
|
cinfo->image_width, output_cols * h_expand); |
||||||
|
|
||||||
|
inrow = outrow = 0; |
||||||
|
while (inrow < cinfo->max_v_samp_factor) { |
||||||
|
outptr = output_data[outrow]; |
||||||
|
for (outcol = 0, outcol_h = 0; outcol < output_cols; |
||||||
|
outcol++, outcol_h += h_expand) { |
||||||
|
outvalue = 0; |
||||||
|
for (v = 0; v < v_expand; v++) { |
||||||
|
inptr = input_data[inrow+v] + outcol_h; |
||||||
|
for (h = 0; h < h_expand; h++) { |
||||||
|
outvalue += (INT32) GETJSAMPLE(*inptr++); |
||||||
|
} |
||||||
|
} |
||||||
|
*outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); |
||||||
|
} |
||||||
|
inrow += v_expand; |
||||||
|
outrow++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Downsample pixel values of a single component. |
||||||
|
* This version handles the special case of a full-size component, |
||||||
|
* without smoothing. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data) |
||||||
|
{ |
||||||
|
/* Copy the data */ |
||||||
|
jcopy_sample_rows(input_data, 0, output_data, 0, |
||||||
|
cinfo->max_v_samp_factor, cinfo->image_width); |
||||||
|
/* Edge-expand */ |
||||||
|
expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, |
||||||
|
compptr->width_in_blocks * compptr->DCT_h_scaled_size); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) |
||||||
|
h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JSAMPARRAY input_data, JSAMPARRAY output_data) |
||||||
|
{ |
||||||
|
int inrow; |
||||||
|
JDIMENSION outcol; |
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
||||||
|
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 (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { |
||||||
|
outptr = output_data[inrow]; |
||||||
|
inptr = input_data[inrow]; |
||||||
|
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 * compptr->DCT_h_scaled_size; |
||||||
|
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 = outrow = 0; |
||||||
|
while (inrow < cinfo->max_v_samp_factor) { |
||||||
|
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; |
||||||
|
outrow++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED |
||||||
|
|
||||||
|
/*
|
||||||
|
* Downsample pixel values of a single component. |
||||||
|
* This version handles the standard case of 2:1 horizontal and 2:1 vertical, |
||||||
|
* with smoothing. 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 * compptr->DCT_h_scaled_size; |
||||||
|
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 = outrow = 0; |
||||||
|
while (inrow < cinfo->max_v_samp_factor) { |
||||||
|
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; |
||||||
|
outrow++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 inrow; |
||||||
|
JDIMENSION colctr; |
||||||
|
JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
||||||
|
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 (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { |
||||||
|
outptr = output_data[inrow]; |
||||||
|
inptr = input_data[inrow]; |
||||||
|
above_ptr = input_data[inrow-1]; |
||||||
|
below_ptr = input_data[inrow+1]; |
||||||
|
|
||||||
|
/* Special case for first column */ |
||||||
|
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + |
||||||
|
GETJSAMPLE(*inptr); |
||||||
|
membersum = GETJSAMPLE(*inptr++); |
||||||
|
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + |
||||||
|
GETJSAMPLE(*inptr); |
||||||
|
neighsum = colsum + (colsum - membersum) + nextcolsum; |
||||||
|
membersum = membersum * memberscale + neighsum * neighscale; |
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); |
||||||
|
lastcolsum = colsum; colsum = nextcolsum; |
||||||
|
|
||||||
|
for (colctr = output_cols - 2; colctr > 0; colctr--) { |
||||||
|
membersum = GETJSAMPLE(*inptr++); |
||||||
|
above_ptr++; below_ptr++; |
||||||
|
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + |
||||||
|
GETJSAMPLE(*inptr); |
||||||
|
neighsum = lastcolsum + (colsum - membersum) + nextcolsum; |
||||||
|
membersum = membersum * memberscale + neighsum * neighscale; |
||||||
|
*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); |
||||||
|
lastcolsum = colsum; colsum = nextcolsum; |
||||||
|
} |
||||||
|
|
||||||
|
/* Special case for last column */ |
||||||
|
membersum = GETJSAMPLE(*inptr); |
||||||
|
neighsum = lastcolsum + (colsum - membersum) + colsum; |
||||||
|
membersum = membersum * memberscale + neighsum * neighscale; |
||||||
|
*outptr = (JSAMPLE) ((membersum + 32768) >> 16); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* INPUT_SMOOTHING_SUPPORTED */ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for downsampling. |
||||||
|
* Note that we must select a routine for each component. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_downsampler (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_downsample_ptr downsample; |
||||||
|
int ci; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
boolean smoothok = TRUE; |
||||||
|
int h_in_group, v_in_group, h_out_group, v_out_group; |
||||||
|
|
||||||
|
downsample = (my_downsample_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(my_downsampler)); |
||||||
|
cinfo->downsample = (struct jpeg_downsampler *) downsample; |
||||||
|
downsample->pub.start_pass = start_pass_downsample; |
||||||
|
downsample->pub.downsample = sep_downsample; |
||||||
|
downsample->pub.need_context_rows = FALSE; |
||||||
|
|
||||||
|
if (cinfo->CCIR601_sampling) |
||||||
|
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); |
||||||
|
|
||||||
|
/* Verify we can handle the sampling factors, and set up method pointers */ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
/* Compute size of an "output group" for DCT scaling. This many samples
|
||||||
|
* are to be converted from max_h_samp_factor * max_v_samp_factor pixels. |
||||||
|
*/ |
||||||
|
h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / |
||||||
|
cinfo->min_DCT_h_scaled_size; |
||||||
|
v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_scaled_size; |
||||||
|
h_in_group = cinfo->max_h_samp_factor; |
||||||
|
v_in_group = cinfo->max_v_samp_factor; |
||||||
|
downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ |
||||||
|
if (h_in_group == h_out_group && v_in_group == v_out_group) { |
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED |
||||||
|
if (cinfo->smoothing_factor) { |
||||||
|
downsample->methods[ci] = fullsize_smooth_downsample; |
||||||
|
downsample->pub.need_context_rows = TRUE; |
||||||
|
} else |
||||||
|
#endif |
||||||
|
downsample->methods[ci] = fullsize_downsample; |
||||||
|
} else if (h_in_group == h_out_group * 2 && |
||||||
|
v_in_group == v_out_group) { |
||||||
|
smoothok = FALSE; |
||||||
|
downsample->methods[ci] = h2v1_downsample; |
||||||
|
} else if (h_in_group == h_out_group * 2 && |
||||||
|
v_in_group == v_out_group * 2) { |
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED |
||||||
|
if (cinfo->smoothing_factor) { |
||||||
|
downsample->methods[ci] = h2v2_smooth_downsample; |
||||||
|
downsample->pub.need_context_rows = TRUE; |
||||||
|
} else |
||||||
|
#endif |
||||||
|
downsample->methods[ci] = h2v2_downsample; |
||||||
|
} else if ((h_in_group % h_out_group) == 0 && |
||||||
|
(v_in_group % v_out_group) == 0) { |
||||||
|
smoothok = FALSE; |
||||||
|
downsample->methods[ci] = int_downsample; |
||||||
|
downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); |
||||||
|
downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); |
||||||
|
} else |
||||||
|
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef INPUT_SMOOTHING_SUPPORTED |
||||||
|
if (cinfo->smoothing_factor && !smoothok) |
||||||
|
TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); |
||||||
|
#endif |
||||||
|
} |
@ -0,0 +1,382 @@ |
|||||||
|
/*
|
||||||
|
* jctrans.c |
||||||
|
* |
||||||
|
* Copyright (C) 1995-1998, Thomas G. Lane. |
||||||
|
* Modified 2000-2009 by Guido Vollbeding. |
||||||
|
* 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; |
||||||
|
dstinfo->jpeg_width = srcinfo->output_width; |
||||||
|
dstinfo->jpeg_height = srcinfo->output_height; |
||||||
|
dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; |
||||||
|
dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; |
||||||
|
/* 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) |
||||||
|
{ |
||||||
|
/* 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) |
||||||
|
jinit_arith_encoder(cinfo); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,396 @@ |
|||||||
|
/*
|
||||||
|
* jdapimin.c |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1998, Thomas G. Lane. |
||||||
|
* Modified 2009 by Guido Vollbeding. |
||||||
|
* 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 = cinfo->block_size; /* 1:1 scaling */ |
||||||
|
cinfo->scale_denom = cinfo->block_size; |
||||||
|
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; |
||||||
|
} |
@ -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_v_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 */ |
@ -0,0 +1,772 @@ |
|||||||
|
/*
|
||||||
|
* jdarith.c |
||||||
|
* |
||||||
|
* Developed 1997-2009 by Guido Vollbeding. |
||||||
|
* 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 portable arithmetic entropy decoding routines for JPEG |
||||||
|
* (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). |
||||||
|
* |
||||||
|
* Both sequential and progressive modes are supported in this single module. |
||||||
|
* |
||||||
|
* Suspension is not currently supported in this module. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Expanded entropy decoder object for arithmetic decoding. */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_entropy_decoder pub; /* public fields */ |
||||||
|
|
||||||
|
INT32 c; /* C register, base of coding interval + input bit buffer */ |
||||||
|
INT32 a; /* A register, normalized size of coding interval */ |
||||||
|
int ct; /* bit shift counter, # of bits left in bit buffer part of C */ |
||||||
|
/* init: ct = -16 */ |
||||||
|
/* run: ct = 0..7 */ |
||||||
|
/* error: ct = -1 */ |
||||||
|
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ |
||||||
|
int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ |
||||||
|
|
||||||
|
unsigned int restarts_to_go; /* MCUs left in this restart interval */ |
||||||
|
|
||||||
|
/* Pointers to statistics areas (these workspaces have image lifespan) */ |
||||||
|
unsigned char * dc_stats[NUM_ARITH_TBLS]; |
||||||
|
unsigned char * ac_stats[NUM_ARITH_TBLS]; |
||||||
|
|
||||||
|
/* Statistics bin for coding with fixed probability 0.5 */ |
||||||
|
unsigned char fixed_bin[4]; |
||||||
|
} arith_entropy_decoder; |
||||||
|
|
||||||
|
typedef arith_entropy_decoder * arith_entropy_ptr; |
||||||
|
|
||||||
|
/* The following two definitions specify the allocation chunk size
|
||||||
|
* for the statistics area. |
||||||
|
* According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least |
||||||
|
* 49 statistics bins for DC, and 245 statistics bins for AC coding. |
||||||
|
* |
||||||
|
* We use a compact representation with 1 byte per statistics bin, |
||||||
|
* thus the numbers directly represent byte sizes. |
||||||
|
* This 1 byte per statistics bin contains the meaning of the MPS |
||||||
|
* (more probable symbol) in the highest bit (mask 0x80), and the |
||||||
|
* index into the probability estimation state machine table |
||||||
|
* in the lower bits (mask 0x7F). |
||||||
|
*/ |
||||||
|
|
||||||
|
#define DC_STAT_BINS 64 |
||||||
|
#define AC_STAT_BINS 256 |
||||||
|
|
||||||
|
|
||||||
|
LOCAL(int) |
||||||
|
get_byte (j_decompress_ptr cinfo) |
||||||
|
/* Read next input byte; we do not support suspension in this module. */ |
||||||
|
{ |
||||||
|
struct jpeg_source_mgr * src = cinfo->src; |
||||||
|
|
||||||
|
if (src->bytes_in_buffer == 0) |
||||||
|
if (! (*src->fill_input_buffer) (cinfo)) |
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND); |
||||||
|
src->bytes_in_buffer--; |
||||||
|
return GETJOCTET(*src->next_input_byte++); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The core arithmetic decoding routine (common in JPEG and JBIG). |
||||||
|
* This needs to go as fast as possible. |
||||||
|
* Machine-dependent optimization facilities |
||||||
|
* are not utilized in this portable implementation. |
||||||
|
* However, this code should be fairly efficient and |
||||||
|
* may be a good base for further optimizations anyway. |
||||||
|
* |
||||||
|
* Return value is 0 or 1 (binary decision). |
||||||
|
* |
||||||
|
* Note: I've changed the handling of the code base & bit |
||||||
|
* buffer register C compared to other implementations |
||||||
|
* based on the standards layout & procedures. |
||||||
|
* While it also contains both the actual base of the |
||||||
|
* coding interval (16 bits) and the next-bits buffer, |
||||||
|
* the cut-point between these two parts is floating |
||||||
|
* (instead of fixed) with the bit shift counter CT. |
||||||
|
* Thus, we also need only one (variable instead of |
||||||
|
* fixed size) shift for the LPS/MPS decision, and |
||||||
|
* we can get away with any renormalization update |
||||||
|
* of C (except for new data insertion, of course). |
||||||
|
* |
||||||
|
* I've also introduced a new scheme for accessing |
||||||
|
* the probability estimation state machine table, |
||||||
|
* derived from Markus Kuhn's JBIG implementation. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(int) |
||||||
|
arith_decode (j_decompress_ptr cinfo, unsigned char *st) |
||||||
|
{ |
||||||
|
register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
register unsigned char nl, nm; |
||||||
|
register INT32 qe, temp; |
||||||
|
register int sv, data; |
||||||
|
|
||||||
|
/* Renormalization & data input per section D.2.6 */ |
||||||
|
while (e->a < 0x8000L) { |
||||||
|
if (--e->ct < 0) { |
||||||
|
/* Need to fetch next data byte */ |
||||||
|
if (cinfo->unread_marker) |
||||||
|
data = 0; /* stuff zero data */ |
||||||
|
else { |
||||||
|
data = get_byte(cinfo); /* read next input byte */ |
||||||
|
if (data == 0xFF) { /* zero stuff or marker code */ |
||||||
|
do data = get_byte(cinfo); |
||||||
|
while (data == 0xFF); /* swallow extra 0xFF bytes */ |
||||||
|
if (data == 0) |
||||||
|
data = 0xFF; /* discard stuffed zero byte */ |
||||||
|
else { |
||||||
|
/* Note: Different from the Huffman decoder, hitting
|
||||||
|
* a marker while processing the compressed data |
||||||
|
* segment is legal in arithmetic coding. |
||||||
|
* The convention is to supply zero data |
||||||
|
* then until decoding is complete. |
||||||
|
*/ |
||||||
|
cinfo->unread_marker = data; |
||||||
|
data = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
e->c = (e->c << 8) | data; /* insert data into C register */ |
||||||
|
if ((e->ct += 8) < 0) /* update bit shift counter */ |
||||||
|
/* Need more initial bytes */ |
||||||
|
if (++e->ct == 0) |
||||||
|
/* Got 2 initial bytes -> re-init A and exit loop */ |
||||||
|
e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ |
||||||
|
} |
||||||
|
e->a <<= 1; |
||||||
|
} |
||||||
|
|
||||||
|
/* Fetch values from our compact representation of Table D.2:
|
||||||
|
* Qe values and probability estimation state machine |
||||||
|
*/ |
||||||
|
sv = *st; |
||||||
|
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ |
||||||
|
nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ |
||||||
|
nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ |
||||||
|
|
||||||
|
/* Decode & estimation procedures per sections D.2.4 & D.2.5 */ |
||||||
|
temp = e->a - qe; |
||||||
|
e->a = temp; |
||||||
|
temp <<= e->ct; |
||||||
|
if (e->c >= temp) { |
||||||
|
e->c -= temp; |
||||||
|
/* Conditional LPS (less probable symbol) exchange */ |
||||||
|
if (e->a < qe) { |
||||||
|
e->a = qe; |
||||||
|
*st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ |
||||||
|
} else { |
||||||
|
e->a = qe; |
||||||
|
*st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ |
||||||
|
sv ^= 0x80; /* Exchange LPS/MPS */ |
||||||
|
} |
||||||
|
} else if (e->a < 0x8000L) { |
||||||
|
/* Conditional MPS (more probable symbol) exchange */ |
||||||
|
if (e->a < qe) { |
||||||
|
*st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ |
||||||
|
sv ^= 0x80; /* Exchange LPS/MPS */ |
||||||
|
} else { |
||||||
|
*st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return sv >> 7; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for a restart marker & resynchronize decoder. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
process_restart (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
int ci; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
|
||||||
|
/* Advance past the RSTn marker */ |
||||||
|
if (! (*cinfo->marker->read_restart_marker) (cinfo)) |
||||||
|
ERREXIT(cinfo, JERR_CANT_SUSPEND); |
||||||
|
|
||||||
|
/* Re-initialize statistics areas */ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { |
||||||
|
MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); |
||||||
|
/* Reset DC predictions to 0 */ |
||||||
|
entropy->last_dc_val[ci] = 0; |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
} |
||||||
|
if ((! cinfo->progressive_mode && cinfo->lim_Se) || |
||||||
|
(cinfo->progressive_mode && cinfo->Ss)) { |
||||||
|
MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Reset arithmetic decoding variables */ |
||||||
|
entropy->c = 0; |
||||||
|
entropy->a = 0; |
||||||
|
entropy->ct = -16; /* force reading 2 initial bytes to fill C */ |
||||||
|
|
||||||
|
/* Reset restart counter */ |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arithmetic MCU decoding. |
||||||
|
* Each of these routines decodes and returns one MCU's worth of |
||||||
|
* arithmetic-compressed coefficients. |
||||||
|
* The coefficients are reordered from zigzag order into natural array order, |
||||||
|
* but are not dequantized. |
||||||
|
* |
||||||
|
* The i'th block of the MCU is stored into the block pointed to by |
||||||
|
* MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for DC initial scan (either spectral selection, |
||||||
|
* or first pass of successive approximation). |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int blkn, ci, tbl, sign; |
||||||
|
int v, m; |
||||||
|
|
||||||
|
/* Process restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) |
||||||
|
process_restart(cinfo); |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
if (entropy->ct == -1) return TRUE; /* if error do nothing */ |
||||||
|
|
||||||
|
/* Outer loop handles each block in the MCU */ |
||||||
|
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { |
||||||
|
block = MCU_data[blkn]; |
||||||
|
ci = cinfo->MCU_membership[blkn]; |
||||||
|
tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; |
||||||
|
|
||||||
|
/* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ |
||||||
|
|
||||||
|
/* Table F.4: Point to statistics bin S0 for DC coefficient coding */ |
||||||
|
st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; |
||||||
|
|
||||||
|
/* Figure F.19: Decode_DC_DIFF */ |
||||||
|
if (arith_decode(cinfo, st) == 0) |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
else { |
||||||
|
/* Figure F.21: Decoding nonzero value v */ |
||||||
|
/* Figure F.22: Decoding the sign of v */ |
||||||
|
sign = arith_decode(cinfo, st + 1); |
||||||
|
st += 2; st += sign; |
||||||
|
/* Figure F.23: Decoding the magnitude category of v */ |
||||||
|
if ((m = arith_decode(cinfo, st)) != 0) { |
||||||
|
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ |
||||||
|
while (arith_decode(cinfo, st)) { |
||||||
|
if ((m <<= 1) == 0x8000) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* magnitude overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */ |
||||||
|
if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ |
||||||
|
else |
||||||
|
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ |
||||||
|
v = m; |
||||||
|
/* Figure F.24: Decoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
if (arith_decode(cinfo, st)) v |= m; |
||||||
|
v += 1; if (sign) v = -v; |
||||||
|
entropy->last_dc_val[ci] += v; |
||||||
|
} |
||||||
|
|
||||||
|
/* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ |
||||||
|
(*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for AC initial scan (either spectral selection, |
||||||
|
* or first pass of successive approximation). |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int tbl, sign, k; |
||||||
|
int v, m; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Process restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) |
||||||
|
process_restart(cinfo); |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
if (entropy->ct == -1) return TRUE; /* if error do nothing */ |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* There is always only one block per MCU */ |
||||||
|
block = MCU_data[0]; |
||||||
|
tbl = cinfo->cur_comp_info[0]->ac_tbl_no; |
||||||
|
|
||||||
|
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ |
||||||
|
|
||||||
|
/* Figure F.20: Decode_AC_coefficients */ |
||||||
|
for (k = cinfo->Ss; k <= cinfo->Se; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
if (arith_decode(cinfo, st)) break; /* EOB flag */ |
||||||
|
while (arith_decode(cinfo, st + 1) == 0) { |
||||||
|
st += 3; k++; |
||||||
|
if (k > cinfo->Se) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* spectral overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Figure F.21: Decoding nonzero value v */ |
||||||
|
/* Figure F.22: Decoding the sign of v */ |
||||||
|
sign = arith_decode(cinfo, entropy->fixed_bin); |
||||||
|
st += 2; |
||||||
|
/* Figure F.23: Decoding the magnitude category of v */ |
||||||
|
if ((m = arith_decode(cinfo, st)) != 0) { |
||||||
|
if (arith_decode(cinfo, st)) { |
||||||
|
m <<= 1; |
||||||
|
st = entropy->ac_stats[tbl] + |
||||||
|
(k <= cinfo->arith_ac_K[tbl] ? 189 : 217); |
||||||
|
while (arith_decode(cinfo, st)) { |
||||||
|
if ((m <<= 1) == 0x8000) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* magnitude overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
v = m; |
||||||
|
/* Figure F.24: Decoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
if (arith_decode(cinfo, st)) v |= m; |
||||||
|
v += 1; if (sign) v = -v; |
||||||
|
/* Scale and output coefficient in natural (dezigzagged) order */ |
||||||
|
(*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for DC successive approximation refinement scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
unsigned char *st; |
||||||
|
int p1, blkn; |
||||||
|
|
||||||
|
/* Process restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) |
||||||
|
process_restart(cinfo); |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
st = entropy->fixed_bin; /* use fixed probability estimation */ |
||||||
|
p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ |
||||||
|
|
||||||
|
/* Outer loop handles each block in the MCU */ |
||||||
|
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { |
||||||
|
/* Encoded data is simply the next bit of the two's-complement DC value */ |
||||||
|
if (arith_decode(cinfo, st)) |
||||||
|
MCU_data[blkn][0][0] |= p1; |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for AC successive approximation refinement scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
JBLOCKROW block; |
||||||
|
JCOEFPTR thiscoef; |
||||||
|
unsigned char *st; |
||||||
|
int tbl, k, kex; |
||||||
|
int p1, m1; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Process restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) |
||||||
|
process_restart(cinfo); |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
if (entropy->ct == -1) return TRUE; /* if error do nothing */ |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* There is always only one block per MCU */ |
||||||
|
block = MCU_data[0]; |
||||||
|
tbl = cinfo->cur_comp_info[0]->ac_tbl_no; |
||||||
|
|
||||||
|
p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ |
||||||
|
m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ |
||||||
|
|
||||||
|
/* Establish EOBx (previous stage end-of-block) index */ |
||||||
|
for (kex = cinfo->Se; kex > 0; kex--) |
||||||
|
if ((*block)[natural_order[kex]]) break; |
||||||
|
|
||||||
|
for (k = cinfo->Ss; k <= cinfo->Se; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
if (k > kex) |
||||||
|
if (arith_decode(cinfo, st)) break; /* EOB flag */ |
||||||
|
for (;;) { |
||||||
|
thiscoef = *block + natural_order[k]; |
||||||
|
if (*thiscoef) { /* previously nonzero coef */ |
||||||
|
if (arith_decode(cinfo, st + 2)) { |
||||||
|
if (*thiscoef < 0) |
||||||
|
*thiscoef += m1; |
||||||
|
else |
||||||
|
*thiscoef += p1; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ |
||||||
|
if (arith_decode(cinfo, entropy->fixed_bin)) |
||||||
|
*thiscoef = m1; |
||||||
|
else |
||||||
|
*thiscoef = p1; |
||||||
|
break; |
||||||
|
} |
||||||
|
st += 3; k++; |
||||||
|
if (k > cinfo->Se) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* spectral overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode one MCU's worth of arithmetic-compressed coefficients. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
JBLOCKROW block; |
||||||
|
unsigned char *st; |
||||||
|
int blkn, ci, tbl, sign, k; |
||||||
|
int v, m; |
||||||
|
const int * natural_order; |
||||||
|
|
||||||
|
/* Process restart marker if needed */ |
||||||
|
if (cinfo->restart_interval) { |
||||||
|
if (entropy->restarts_to_go == 0) |
||||||
|
process_restart(cinfo); |
||||||
|
entropy->restarts_to_go--; |
||||||
|
} |
||||||
|
|
||||||
|
if (entropy->ct == -1) return TRUE; /* if error do nothing */ |
||||||
|
|
||||||
|
natural_order = cinfo->natural_order; |
||||||
|
|
||||||
|
/* Outer loop handles each block in the MCU */ |
||||||
|
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { |
||||||
|
block = MCU_data[blkn]; |
||||||
|
ci = cinfo->MCU_membership[blkn]; |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
|
||||||
|
/* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ |
||||||
|
|
||||||
|
tbl = compptr->dc_tbl_no; |
||||||
|
|
||||||
|
/* Table F.4: Point to statistics bin S0 for DC coefficient coding */ |
||||||
|
st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; |
||||||
|
|
||||||
|
/* Figure F.19: Decode_DC_DIFF */ |
||||||
|
if (arith_decode(cinfo, st) == 0) |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
else { |
||||||
|
/* Figure F.21: Decoding nonzero value v */ |
||||||
|
/* Figure F.22: Decoding the sign of v */ |
||||||
|
sign = arith_decode(cinfo, st + 1); |
||||||
|
st += 2; st += sign; |
||||||
|
/* Figure F.23: Decoding the magnitude category of v */ |
||||||
|
if ((m = arith_decode(cinfo, st)) != 0) { |
||||||
|
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ |
||||||
|
while (arith_decode(cinfo, st)) { |
||||||
|
if ((m <<= 1) == 0x8000) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* magnitude overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */ |
||||||
|
if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 0; /* zero diff category */ |
||||||
|
else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) |
||||||
|
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ |
||||||
|
else |
||||||
|
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ |
||||||
|
v = m; |
||||||
|
/* Figure F.24: Decoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
if (arith_decode(cinfo, st)) v |= m; |
||||||
|
v += 1; if (sign) v = -v; |
||||||
|
entropy->last_dc_val[ci] += v; |
||||||
|
} |
||||||
|
|
||||||
|
(*block)[0] = (JCOEF) entropy->last_dc_val[ci]; |
||||||
|
|
||||||
|
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ |
||||||
|
|
||||||
|
tbl = compptr->ac_tbl_no; |
||||||
|
|
||||||
|
/* Figure F.20: Decode_AC_coefficients */ |
||||||
|
for (k = 1; k <= cinfo->lim_Se; k++) { |
||||||
|
st = entropy->ac_stats[tbl] + 3 * (k - 1); |
||||||
|
if (arith_decode(cinfo, st)) break; /* EOB flag */ |
||||||
|
while (arith_decode(cinfo, st + 1) == 0) { |
||||||
|
st += 3; k++; |
||||||
|
if (k > cinfo->lim_Se) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* spectral overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Figure F.21: Decoding nonzero value v */ |
||||||
|
/* Figure F.22: Decoding the sign of v */ |
||||||
|
sign = arith_decode(cinfo, entropy->fixed_bin); |
||||||
|
st += 2; |
||||||
|
/* Figure F.23: Decoding the magnitude category of v */ |
||||||
|
if ((m = arith_decode(cinfo, st)) != 0) { |
||||||
|
if (arith_decode(cinfo, st)) { |
||||||
|
m <<= 1; |
||||||
|
st = entropy->ac_stats[tbl] + |
||||||
|
(k <= cinfo->arith_ac_K[tbl] ? 189 : 217); |
||||||
|
while (arith_decode(cinfo, st)) { |
||||||
|
if ((m <<= 1) == 0x8000) { |
||||||
|
WARNMS(cinfo, JWRN_ARITH_BAD_CODE); |
||||||
|
entropy->ct = -1; /* magnitude overflow */ |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
st += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
v = m; |
||||||
|
/* Figure F.24: Decoding the magnitude bit pattern of v */ |
||||||
|
st += 14; |
||||||
|
while (m >>= 1) |
||||||
|
if (arith_decode(cinfo, st)) v |= m; |
||||||
|
v += 1; if (sign) v = -v; |
||||||
|
(*block)[natural_order[k]] = (JCOEF) v; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an arithmetic-compressed scan. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
start_pass (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; |
||||||
|
int ci, tbl; |
||||||
|
jpeg_component_info * compptr; |
||||||
|
|
||||||
|
if (cinfo->progressive_mode) { |
||||||
|
/* Validate progressive scan parameters */ |
||||||
|
if (cinfo->Ss == 0) { |
||||||
|
if (cinfo->Se != 0) |
||||||
|
goto bad; |
||||||
|
} else { |
||||||
|
/* need not check Ss/Se < 0 since they came from unsigned bytes */ |
||||||
|
if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) |
||||||
|
goto bad; |
||||||
|
/* AC scans may have only one component */ |
||||||
|
if (cinfo->comps_in_scan != 1) |
||||||
|
goto bad; |
||||||
|
} |
||||||
|
if (cinfo->Ah != 0) { |
||||||
|
/* Successive approximation refinement scan: must have Al = Ah-1. */ |
||||||
|
if (cinfo->Ah-1 != cinfo->Al) |
||||||
|
goto bad; |
||||||
|
} |
||||||
|
if (cinfo->Al > 13) { /* need not check for < 0 */ |
||||||
|
bad: |
||||||
|
ERREXIT4(cinfo, JERR_BAD_PROGRESSION, |
||||||
|
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); |
||||||
|
} |
||||||
|
/* Update progression status, and verify that scan order is legal.
|
||||||
|
* Note that inter-scan inconsistencies are treated as warnings |
||||||
|
* not fatal errors ... not clear if this is right way to behave. |
||||||
|
*/ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; |
||||||
|
int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; |
||||||
|
if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ |
||||||
|
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); |
||||||
|
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { |
||||||
|
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; |
||||||
|
if (cinfo->Ah != expected) |
||||||
|
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); |
||||||
|
coef_bit_ptr[coefi] = cinfo->Al; |
||||||
|
} |
||||||
|
} |
||||||
|
/* Select MCU decoding routine */ |
||||||
|
if (cinfo->Ah == 0) { |
||||||
|
if (cinfo->Ss == 0) |
||||||
|
entropy->pub.decode_mcu = decode_mcu_DC_first; |
||||||
|
else |
||||||
|
entropy->pub.decode_mcu = decode_mcu_AC_first; |
||||||
|
} else { |
||||||
|
if (cinfo->Ss == 0) |
||||||
|
entropy->pub.decode_mcu = decode_mcu_DC_refine; |
||||||
|
else |
||||||
|
entropy->pub.decode_mcu = decode_mcu_AC_refine; |
||||||
|
} |
||||||
|
} else { |
||||||
|
/* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
|
||||||
|
* This ought to be an error condition, but we make it a warning. |
||||||
|
*/ |
||||||
|
if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || |
||||||
|
(cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) |
||||||
|
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); |
||||||
|
/* Select MCU decoding routine */ |
||||||
|
entropy->pub.decode_mcu = decode_mcu; |
||||||
|
} |
||||||
|
|
||||||
|
/* Allocate & initialize requested statistics areas */ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { |
||||||
|
tbl = compptr->dc_tbl_no; |
||||||
|
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) |
||||||
|
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); |
||||||
|
if (entropy->dc_stats[tbl] == NULL) |
||||||
|
entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) |
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); |
||||||
|
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); |
||||||
|
/* Initialize DC predictions to 0 */ |
||||||
|
entropy->last_dc_val[ci] = 0; |
||||||
|
entropy->dc_context[ci] = 0; |
||||||
|
} |
||||||
|
if ((! cinfo->progressive_mode && cinfo->lim_Se) || |
||||||
|
(cinfo->progressive_mode && cinfo->Ss)) { |
||||||
|
tbl = compptr->ac_tbl_no; |
||||||
|
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) |
||||||
|
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); |
||||||
|
if (entropy->ac_stats[tbl] == NULL) |
||||||
|
entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) |
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); |
||||||
|
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Initialize arithmetic decoding variables */ |
||||||
|
entropy->c = 0; |
||||||
|
entropy->a = 0; |
||||||
|
entropy->ct = -16; /* force reading 2 initial bytes to fill C */ |
||||||
|
|
||||||
|
/* Initialize restart counter */ |
||||||
|
entropy->restarts_to_go = cinfo->restart_interval; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for arithmetic entropy decoding. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_arith_decoder (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
arith_entropy_ptr entropy; |
||||||
|
int i; |
||||||
|
|
||||||
|
entropy = (arith_entropy_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(arith_entropy_decoder)); |
||||||
|
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; |
||||||
|
entropy->pub.start_pass = start_pass; |
||||||
|
|
||||||
|
/* Mark tables unallocated */ |
||||||
|
for (i = 0; i < NUM_ARITH_TBLS; i++) { |
||||||
|
entropy->dc_stats[i] = NULL; |
||||||
|
entropy->ac_stats[i] = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/* Initialize index for fixed probability estimation */ |
||||||
|
entropy->fixed_bin[0] = 113; |
||||||
|
|
||||||
|
if (cinfo->progressive_mode) { |
||||||
|
/* Create progression status table */ |
||||||
|
int *coef_bit_ptr, ci; |
||||||
|
cinfo->coef_bits = (int (*)[DCTSIZE2]) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
cinfo->num_components*DCTSIZE2*SIZEOF(int)); |
||||||
|
coef_bit_ptr = & cinfo->coef_bits[0][0]; |
||||||
|
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) |
||||||
|
*coef_bit_ptr++ = -1; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,267 @@ |
|||||||
|
/*
|
||||||
|
* jdatadst.c |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane. |
||||||
|
* Modified 2009 by Guido Vollbeding. |
||||||
|
* 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 memory or 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" |
||||||
|
|
||||||
|
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */ |
||||||
|
extern void * malloc JPP((size_t size)); |
||||||
|
extern void free JPP((void *ptr)); |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
/* 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 */ |
||||||
|
|
||||||
|
|
||||||
|
/* Expanded data destination object for memory output */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_destination_mgr pub; /* public fields */ |
||||||
|
|
||||||
|
unsigned char ** outbuffer; /* target buffer */ |
||||||
|
unsigned long * outsize; |
||||||
|
unsigned char * newbuffer; /* newly allocated buffer */ |
||||||
|
JOCTET * buffer; /* start of buffer */ |
||||||
|
size_t bufsize; |
||||||
|
} my_mem_destination_mgr; |
||||||
|
|
||||||
|
typedef my_mem_destination_mgr * my_mem_dest_ptr; |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
init_mem_destination (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
/* no work necessary here */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
empty_mem_output_buffer (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
size_t nextsize; |
||||||
|
JOCTET * nextbuffer; |
||||||
|
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; |
||||||
|
|
||||||
|
/* Try to allocate new buffer with double size */ |
||||||
|
nextsize = dest->bufsize * 2; |
||||||
|
nextbuffer = malloc(nextsize); |
||||||
|
|
||||||
|
if (nextbuffer == NULL) |
||||||
|
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); |
||||||
|
|
||||||
|
MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); |
||||||
|
|
||||||
|
if (dest->newbuffer != NULL) |
||||||
|
free(dest->newbuffer); |
||||||
|
|
||||||
|
dest->newbuffer = nextbuffer; |
||||||
|
|
||||||
|
dest->pub.next_output_byte = nextbuffer + dest->bufsize; |
||||||
|
dest->pub.free_in_buffer = dest->bufsize; |
||||||
|
|
||||||
|
dest->buffer = nextbuffer; |
||||||
|
dest->bufsize = nextsize; |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
term_mem_destination (j_compress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; |
||||||
|
|
||||||
|
*dest->outbuffer = dest->buffer; |
||||||
|
*dest->outsize = dest->bufsize - dest->pub.free_in_buffer; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for output to a memory buffer. |
||||||
|
* The caller may supply an own initial buffer with appropriate size. |
||||||
|
* Otherwise, or when the actual data output exceeds the given size, |
||||||
|
* the library adapts the buffer size as necessary. |
||||||
|
* The standard library functions malloc/free are used for allocating |
||||||
|
* larger memory, so the buffer is available to the application after |
||||||
|
* finishing compression, and then the application is responsible for |
||||||
|
* freeing the requested memory. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_mem_dest (j_compress_ptr cinfo, |
||||||
|
unsigned char ** outbuffer, unsigned long * outsize) |
||||||
|
{ |
||||||
|
my_mem_dest_ptr dest; |
||||||
|
|
||||||
|
if (outbuffer == NULL || outsize == NULL) /* sanity check */ |
||||||
|
ERREXIT(cinfo, JERR_BUFFER_SIZE); |
||||||
|
|
||||||
|
/* The destination object is made permanent so that multiple JPEG images
|
||||||
|
* can be written to the same buffer without re-executing jpeg_mem_dest. |
||||||
|
*/ |
||||||
|
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_mem_destination_mgr)); |
||||||
|
} |
||||||
|
|
||||||
|
dest = (my_mem_dest_ptr) cinfo->dest; |
||||||
|
dest->pub.init_destination = init_mem_destination; |
||||||
|
dest->pub.empty_output_buffer = empty_mem_output_buffer; |
||||||
|
dest->pub.term_destination = term_mem_destination; |
||||||
|
dest->outbuffer = outbuffer; |
||||||
|
dest->outsize = outsize; |
||||||
|
dest->newbuffer = NULL; |
||||||
|
|
||||||
|
if (*outbuffer == NULL || *outsize == 0) { |
||||||
|
/* Allocate initial buffer */ |
||||||
|
dest->newbuffer = *outbuffer = malloc(OUTPUT_BUF_SIZE); |
||||||
|
if (dest->newbuffer == NULL) |
||||||
|
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); |
||||||
|
*outsize = OUTPUT_BUF_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
dest->pub.next_output_byte = dest->buffer = *outbuffer; |
||||||
|
dest->pub.free_in_buffer = dest->bufsize = *outsize; |
||||||
|
} |
@ -0,0 +1,274 @@ |
|||||||
|
/*
|
||||||
|
* jdatasrc.c |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane. |
||||||
|
* Modified 2009-2010 by Guido Vollbeding. |
||||||
|
* 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 memory or 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; |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
init_mem_source (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
/* no work necessary here */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(boolean) |
||||||
|
fill_mem_input_buffer (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
static JOCTET mybuffer[4]; |
||||||
|
|
||||||
|
/* The whole JPEG data is expected to reside in the supplied memory
|
||||||
|
* buffer, so any request for more data beyond the given buffer size |
||||||
|
* is treated as an error. |
||||||
|
*/ |
||||||
|
WARNMS(cinfo, JWRN_JPEG_EOF); |
||||||
|
/* Insert a fake EOI marker */ |
||||||
|
mybuffer[0] = (JOCTET) 0xFF; |
||||||
|
mybuffer[1] = (JOCTET) JPEG_EOI; |
||||||
|
|
||||||
|
cinfo->src->next_input_byte = mybuffer; |
||||||
|
cinfo->src->bytes_in_buffer = 2; |
||||||
|
|
||||||
|
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) |
||||||
|
{ |
||||||
|
struct jpeg_source_mgr * src = 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->bytes_in_buffer) { |
||||||
|
num_bytes -= (long) src->bytes_in_buffer; |
||||||
|
(void) (*src->fill_input_buffer) (cinfo); |
||||||
|
/* note we assume that fill_input_buffer will never return FALSE,
|
||||||
|
* so suspension need not be handled. |
||||||
|
*/ |
||||||
|
} |
||||||
|
src->next_input_byte += (size_t) num_bytes; |
||||||
|
src->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 */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for input from a supplied memory buffer. |
||||||
|
* The buffer must contain the whole JPEG data. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_mem_src (j_decompress_ptr cinfo, |
||||||
|
unsigned char * inbuffer, unsigned long insize) |
||||||
|
{ |
||||||
|
struct jpeg_source_mgr * src; |
||||||
|
|
||||||
|
if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ |
||||||
|
ERREXIT(cinfo, JERR_INPUT_EMPTY); |
||||||
|
|
||||||
|
/* The source object is made permanent so that a series of JPEG images
|
||||||
|
* can be read from the same buffer by calling jpeg_mem_src only before |
||||||
|
* the first one. |
||||||
|
*/ |
||||||
|
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(struct jpeg_source_mgr)); |
||||||
|
} |
||||||
|
|
||||||
|
src = cinfo->src; |
||||||
|
src->init_source = init_mem_source; |
||||||
|
src->fill_input_buffer = fill_mem_input_buffer; |
||||||
|
src->skip_input_data = skip_input_data; |
||||||
|
src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ |
||||||
|
src->term_source = term_source; |
||||||
|
src->bytes_in_buffer = (size_t) insize; |
||||||
|
src->next_input_byte = (JOCTET *) inbuffer; |
||||||
|
} |
@ -0,0 +1,736 @@ |
|||||||
|
/*
|
||||||
|
* 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. |
||||||
|
* |
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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, xindex, yindex, yoffset, useful_width; |
||||||
|
JSAMPARRAY output_ptr; |
||||||
|
JDIMENSION start_col, output_col; |
||||||
|
jpeg_component_info *compptr; |
||||||
|
inverse_DCT_method_ptr inverse_DCT; |
||||||
|
|
||||||
|
/* Loop to process as much as one whole 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++) { |
||||||
|
/* 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; |
||||||
|
} |
||||||
|
/* Determine where data should go in output_buf and do the IDCT thing.
|
||||||
|
* We skip dummy blocks at the right and bottom edges (but blkn gets |
||||||
|
* incremented past them!). Note the inner loop relies on having |
||||||
|
* allocated the MCU_buffer[] blocks sequentially. |
||||||
|
*/ |
||||||
|
blkn = 0; /* index of current DCT block within MCU */ |
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { |
||||||
|
compptr = cinfo->cur_comp_info[ci]; |
||||||
|
/* Don't bother to IDCT an uninteresting component. */ |
||||||
|
if (! compptr->component_needed) { |
||||||
|
blkn += compptr->MCU_blocks; |
||||||
|
continue; |
||||||
|
} |
||||||
|
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; |
||||||
|
useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width |
||||||
|
: compptr->last_col_width; |
||||||
|
output_ptr = output_buf[compptr->component_index] + |
||||||
|
yoffset * compptr->DCT_v_scaled_size; |
||||||
|
start_col = MCU_col_num * compptr->MCU_sample_width; |
||||||
|
for (yindex = 0; yindex < compptr->MCU_height; yindex++) { |
||||||
|
if (cinfo->input_iMCU_row < last_iMCU_row || |
||||||
|
yoffset+yindex < compptr->last_row_height) { |
||||||
|
output_col = start_col; |
||||||
|
for (xindex = 0; xindex < useful_width; xindex++) { |
||||||
|
(*inverse_DCT) (cinfo, compptr, |
||||||
|
(JCOEFPTR) coef->MCU_buffer[blkn+xindex], |
||||||
|
output_ptr, output_col); |
||||||
|
output_col += compptr->DCT_h_scaled_size; |
||||||
|
} |
||||||
|
} |
||||||
|
blkn += compptr->MCU_width; |
||||||
|
output_ptr += compptr->DCT_v_scaled_size; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/* 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; |
||||||
|
|
||||||
|
/* 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++) { |
||||||
|
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 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_h_scaled_size; |
||||||
|
} |
||||||
|
output_ptr += compptr->DCT_v_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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
JBLOCK workspace; |
||||||
|
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) workspace, (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 && workspace[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; |
||||||
|
} |
||||||
|
workspace[1] = (JCOEF) pred; |
||||||
|
} |
||||||
|
/* AC10 */ |
||||||
|
if ((Al=coef_bits[2]) != 0 && workspace[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; |
||||||
|
} |
||||||
|
workspace[8] = (JCOEF) pred; |
||||||
|
} |
||||||
|
/* AC20 */ |
||||||
|
if ((Al=coef_bits[3]) != 0 && workspace[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; |
||||||
|
} |
||||||
|
workspace[16] = (JCOEF) pred; |
||||||
|
} |
||||||
|
/* AC11 */ |
||||||
|
if ((Al=coef_bits[4]) != 0 && workspace[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; |
||||||
|
} |
||||||
|
workspace[9] = (JCOEF) pred; |
||||||
|
} |
||||||
|
/* AC02 */ |
||||||
|
if ((Al=coef_bits[5]) != 0 && workspace[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; |
||||||
|
} |
||||||
|
workspace[2] = (JCOEF) pred; |
||||||
|
} |
||||||
|
/* OK, do the IDCT */ |
||||||
|
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace, |
||||||
|
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_h_scaled_size; |
||||||
|
} |
||||||
|
output_ptr += compptr->DCT_v_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 */ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,498 @@ |
|||||||
|
/*
|
||||||
|
* jdcolor.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 output colorspace conversion routines. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Private subobject */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_color_deconverter pub; /* public fields */ |
||||||
|
|
||||||
|
/* Private state for YCC->RGB conversion */ |
||||||
|
int * Cr_r_tab; /* => table for Cr to R conversion */ |
||||||
|
int * Cb_b_tab; /* => table for Cb to B conversion */ |
||||||
|
INT32 * Cr_g_tab; /* => table for Cr to G conversion */ |
||||||
|
INT32 * Cb_g_tab; /* => table for Cb to G conversion */ |
||||||
|
} my_color_deconverter; |
||||||
|
|
||||||
|
typedef my_color_deconverter * my_cconvert_ptr; |
||||||
|
|
||||||
|
|
||||||
|
/**************** YCbCr -> RGB conversion: most common case **************/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 tables for YCC->RGB colorspace conversion. |
||||||
|
*/ |
||||||
|
|
||||||
|
LOCAL(void) |
||||||
|
build_ycc_rgb_table (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert some rows of samples to the output colorspace. |
||||||
|
* |
||||||
|
* Note that we change from noninterleaved, one-plane-per-component format |
||||||
|
* to interleaved-pixel format. The output buffer is therefore three times |
||||||
|
* as wide as the input buffer. |
||||||
|
* A starting row offset is provided only for the input buffer. The caller |
||||||
|
* can easily adjust the passed output_buf value to accommodate any row |
||||||
|
* offset required on that side. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
ycc_rgb_convert (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; |
||||||
|
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]; |
||||||
|
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[RGB_RED] = range_limit[y + Crrtab[cr]]; |
||||||
|
outptr[RGB_GREEN] = range_limit[y + |
||||||
|
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], |
||||||
|
SCALEBITS))]; |
||||||
|
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; |
||||||
|
outptr += RGB_PIXELSIZE; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
ycc_rgba_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; |
||||||
|
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]; |
||||||
|
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[RGB_RED] = range_limit[y + Crrtab[cr]]; |
||||||
|
outptr[RGB_GREEN] = range_limit[y + |
||||||
|
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], |
||||||
|
SCALEBITS))]; |
||||||
|
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; |
||||||
|
outptr[RGBA_ALPHA] = MAXJSAMPLE; |
||||||
|
outptr += RGBA_PIXELSIZE; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**************** Cases other than YCbCr -> RGB **************/ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Color conversion for no colorspace change: just copy the data, |
||||||
|
* converting from separate-planes to interleaved representation. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
null_convert (j_decompress_ptr cinfo, |
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row, |
||||||
|
JSAMPARRAY output_buf, int num_rows) |
||||||
|
{ |
||||||
|
register JSAMPROW inptr, outptr; |
||||||
|
register JDIMENSION count; |
||||||
|
register int num_components = cinfo->num_components; |
||||||
|
JDIMENSION num_cols = cinfo->output_width; |
||||||
|
int ci; |
||||||
|
|
||||||
|
while (--num_rows >= 0) { |
||||||
|
for (ci = 0; ci < num_components; ci++) { |
||||||
|
inptr = input_buf[ci][input_row]; |
||||||
|
outptr = output_buf[0] + ci; |
||||||
|
for (count = num_cols; count > 0; count--) { |
||||||
|
*outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ |
||||||
|
outptr += num_components; |
||||||
|
} |
||||||
|
} |
||||||
|
input_row++; |
||||||
|
output_buf++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Color conversion for grayscale: just copy the data. |
||||||
|
* This also works for YCbCr -> grayscale conversion, in which |
||||||
|
* we just copy the Y (luminance) component and ignore chrominance. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
grayscale_convert (j_decompress_ptr cinfo, |
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row, |
||||||
|
JSAMPARRAY output_buf, int num_rows) |
||||||
|
{ |
||||||
|
jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, |
||||||
|
num_rows, cinfo->output_width); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) |
||||||
|
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]; |
||||||
|
outptr += RGB_PIXELSIZE; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
gray_rgba_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]; |
||||||
|
outptr[RGBA_ALPHA] = MAXJSAMPLE; |
||||||
|
outptr += RGBA_PIXELSIZE; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
rgb_rgba_convert (j_decompress_ptr cinfo, |
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row, |
||||||
|
JSAMPARRAY output_buf, int num_rows) |
||||||
|
{ |
||||||
|
register JSAMPROW inptr0, inptr1, inptr2, outptr; |
||||||
|
register JDIMENSION col; |
||||||
|
JDIMENSION num_cols = cinfo->output_width; |
||||||
|
|
||||||
|
while (--num_rows >= 0) { |
||||||
|
inptr0 = input_buf[0][input_row]; |
||||||
|
inptr1 = input_buf[1][input_row]; |
||||||
|
inptr2 = input_buf[2][input_row]; |
||||||
|
input_row++; |
||||||
|
outptr = *output_buf++; |
||||||
|
for (col = 0; col < num_cols; col++) { |
||||||
|
/* We can dispense with GETJSAMPLE() here */ |
||||||
|
outptr[RGB_RED] = inptr0[col]; |
||||||
|
outptr[RGB_GREEN] = inptr1[col]; |
||||||
|
outptr[RGB_BLUE] = inptr2[col]; |
||||||
|
outptr[RGBA_ALPHA] = MAXJSAMPLE; |
||||||
|
outptr += RGBA_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 */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for output colorspace conversion. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_color_deconverter (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_cconvert_ptr cconvert; |
||||||
|
int ci; |
||||||
|
|
||||||
|
cconvert = (my_cconvert_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(my_color_deconverter)); |
||||||
|
cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; |
||||||
|
cconvert->pub.start_pass = start_pass_dcolor; |
||||||
|
|
||||||
|
/* Make sure num_components agrees with jpeg_color_space */ |
||||||
|
switch (cinfo->jpeg_color_space) { |
||||||
|
case JCS_GRAYSCALE: |
||||||
|
if (cinfo->num_components != 1) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_RGB: |
||||||
|
case JCS_YCbCr: |
||||||
|
if (cinfo->num_components != 3) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_CMYK: |
||||||
|
case JCS_YCCK: |
||||||
|
if (cinfo->num_components != 4) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
break; |
||||||
|
|
||||||
|
default: /* JCS_UNKNOWN can be anything */ |
||||||
|
if (cinfo->num_components < 1) |
||||||
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Set out_color_components and conversion method based on requested space.
|
||||||
|
* Also clear the component_needed flags for any unused components, |
||||||
|
* so that earlier pipeline stages can avoid useless computation. |
||||||
|
*/ |
||||||
|
|
||||||
|
switch (cinfo->out_color_space) { |
||||||
|
case JCS_GRAYSCALE: |
||||||
|
cinfo->out_color_components = 1; |
||||||
|
if (cinfo->jpeg_color_space == JCS_GRAYSCALE || |
||||||
|
cinfo->jpeg_color_space == JCS_YCbCr) { |
||||||
|
cconvert->pub.color_convert = grayscale_convert; |
||||||
|
/* For color->grayscale conversion, only the Y (0) component is needed */ |
||||||
|
for (ci = 1; ci < cinfo->num_components; ci++) |
||||||
|
cinfo->comp_info[ci].component_needed = FALSE; |
||||||
|
} else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_RGB: |
||||||
|
cinfo->out_color_components = RGB_PIXELSIZE; |
||||||
|
if (cinfo->jpeg_color_space == JCS_YCbCr) { |
||||||
|
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; |
||||||
|
|
||||||
|
case JCS_RGBA: |
||||||
|
cinfo->out_color_components = 4; |
||||||
|
if (cinfo->jpeg_color_space == JCS_YCbCr) { |
||||||
|
cconvert->pub.color_convert = ycc_rgba_convert; |
||||||
|
build_ycc_rgb_table(cinfo); |
||||||
|
} else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { |
||||||
|
cconvert->pub.color_convert = gray_rgba_convert; |
||||||
|
} else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { |
||||||
|
cconvert->pub.color_convert = rgb_rgba_convert; |
||||||
|
} else if (cinfo->jpeg_color_space == JCS_RGB) { |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
} else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
case JCS_CMYK: |
||||||
|
cinfo->out_color_components = 4; |
||||||
|
if (cinfo->jpeg_color_space == JCS_YCCK) { |
||||||
|
cconvert->pub.color_convert = ycck_cmyk_convert; |
||||||
|
build_ycc_rgb_table(cinfo); |
||||||
|
} else if (cinfo->jpeg_color_space == JCS_CMYK) { |
||||||
|
cconvert->pub.color_convert = null_convert; |
||||||
|
} else |
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
/* Permit null conversion 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; |
||||||
|
} |
||||||
|
|
||||||
|
if (cinfo->quantize_colors) |
||||||
|
cinfo->output_components = 1; /* single colormapped output component */ |
||||||
|
else |
||||||
|
cinfo->output_components = cinfo->out_color_components; |
||||||
|
} |
@ -0,0 +1,393 @@ |
|||||||
|
/*
|
||||||
|
* 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. |
||||||
|
* |
||||||
|
* This include file contains common declarations for the forward and |
||||||
|
* inverse DCT modules. These declarations are private to the DCT managers |
||||||
|
* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. |
||||||
|
* The individual DCT algorithms are kept in separate files to ease
|
||||||
|
* machine-dependent tuning (e.g., assembly coding). |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A forward DCT routine is given a pointer to an input sample array and |
||||||
|
* 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 input data is to be fetched from 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 FDCT code.) |
||||||
|
* Note that the number of samples fetched by the FDCT routine is |
||||||
|
* DCT_h_scaled_size * DCT_v_scaled_size. |
||||||
|
* The DCT outputs are returned scaled up by a factor of 8; they therefore |
||||||
|
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This |
||||||
|
* convention improves accuracy in integer implementations and saves some |
||||||
|
* work in floating-point ones. |
||||||
|
* Quantization of the output coefficients is done by jcdctmgr.c. |
||||||
|
*/ |
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8 |
||||||
|
typedef int DCTELEM; /* 16 or 32 bits is fine */ |
||||||
|
#else |
||||||
|
typedef INT32 DCTELEM; /* must have 32 bits */ |
||||||
|
#endif |
||||||
|
|
||||||
|
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, |
||||||
|
JSAMPARRAY sample_data, |
||||||
|
JDIMENSION start_col)); |
||||||
|
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, |
||||||
|
JSAMPARRAY sample_data, |
||||||
|
JDIMENSION start_col)); |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_h_scaled_size * DCT_v_scaled_size. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ |
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine has its own ideas about the best dct_table element type. |
||||||
|
*/ |
||||||
|
|
||||||
|
typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ |
||||||
|
#if BITS_IN_JSAMPLE == 8 |
||||||
|
typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ |
||||||
|
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ |
||||||
|
#else |
||||||
|
typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ |
||||||
|
#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ |
||||||
|
#endif |
||||||
|
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine is responsible for range-limiting its results and |
||||||
|
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could |
||||||
|
* be quite far out of range if the input data is corrupt, so a bulletproof |
||||||
|
* range-limiting step is required. We use a mask-and-table-lookup method |
||||||
|
* to do the combined operations quickly. See the comments with |
||||||
|
* prepare_range_limit_table (in jdmaster.c) for more info. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) |
||||||
|
|
||||||
|
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ |
||||||
|
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */ |
||||||
|
|
||||||
|
#ifdef NEED_SHORT_EXTERNAL_NAMES |
||||||
|
#define jpeg_fdct_islow jFDislow |
||||||
|
#define jpeg_fdct_ifast jFDifast |
||||||
|
#define jpeg_fdct_float jFDfloat |
||||||
|
#define jpeg_fdct_7x7 jFD7x7 |
||||||
|
#define jpeg_fdct_6x6 jFD6x6 |
||||||
|
#define jpeg_fdct_5x5 jFD5x5 |
||||||
|
#define jpeg_fdct_4x4 jFD4x4 |
||||||
|
#define jpeg_fdct_3x3 jFD3x3 |
||||||
|
#define jpeg_fdct_2x2 jFD2x2 |
||||||
|
#define jpeg_fdct_1x1 jFD1x1 |
||||||
|
#define jpeg_fdct_9x9 jFD9x9 |
||||||
|
#define jpeg_fdct_10x10 jFD10x10 |
||||||
|
#define jpeg_fdct_11x11 jFD11x11 |
||||||
|
#define jpeg_fdct_12x12 jFD12x12 |
||||||
|
#define jpeg_fdct_13x13 jFD13x13 |
||||||
|
#define jpeg_fdct_14x14 jFD14x14 |
||||||
|
#define jpeg_fdct_15x15 jFD15x15 |
||||||
|
#define jpeg_fdct_16x16 jFD16x16 |
||||||
|
#define jpeg_fdct_16x8 jFD16x8 |
||||||
|
#define jpeg_fdct_14x7 jFD14x7 |
||||||
|
#define jpeg_fdct_12x6 jFD12x6 |
||||||
|
#define jpeg_fdct_10x5 jFD10x5 |
||||||
|
#define jpeg_fdct_8x4 jFD8x4 |
||||||
|
#define jpeg_fdct_6x3 jFD6x3 |
||||||
|
#define jpeg_fdct_4x2 jFD4x2 |
||||||
|
#define jpeg_fdct_2x1 jFD2x1 |
||||||
|
#define jpeg_fdct_8x16 jFD8x16 |
||||||
|
#define jpeg_fdct_7x14 jFD7x14 |
||||||
|
#define jpeg_fdct_6x12 jFD6x12 |
||||||
|
#define jpeg_fdct_5x10 jFD5x10 |
||||||
|
#define jpeg_fdct_4x8 jFD4x8 |
||||||
|
#define jpeg_fdct_3x6 jFD3x6 |
||||||
|
#define jpeg_fdct_2x4 jFD2x4 |
||||||
|
#define jpeg_fdct_1x2 jFD1x2 |
||||||
|
#define jpeg_idct_islow jRDislow |
||||||
|
#define jpeg_idct_ifast jRDifast |
||||||
|
#define jpeg_idct_float jRDfloat |
||||||
|
#define jpeg_idct_7x7 jRD7x7 |
||||||
|
#define jpeg_idct_6x6 jRD6x6 |
||||||
|
#define jpeg_idct_5x5 jRD5x5 |
||||||
|
#define jpeg_idct_4x4 jRD4x4 |
||||||
|
#define jpeg_idct_3x3 jRD3x3 |
||||||
|
#define jpeg_idct_2x2 jRD2x2 |
||||||
|
#define jpeg_idct_1x1 jRD1x1 |
||||||
|
#define jpeg_idct_9x9 jRD9x9 |
||||||
|
#define jpeg_idct_10x10 jRD10x10 |
||||||
|
#define jpeg_idct_11x11 jRD11x11 |
||||||
|
#define jpeg_idct_12x12 jRD12x12 |
||||||
|
#define jpeg_idct_13x13 jRD13x13 |
||||||
|
#define jpeg_idct_14x14 jRD14x14 |
||||||
|
#define jpeg_idct_15x15 jRD15x15 |
||||||
|
#define jpeg_idct_16x16 jRD16x16 |
||||||
|
#define jpeg_idct_16x8 jRD16x8 |
||||||
|
#define jpeg_idct_14x7 jRD14x7 |
||||||
|
#define jpeg_idct_12x6 jRD12x6 |
||||||
|
#define jpeg_idct_10x5 jRD10x5 |
||||||
|
#define jpeg_idct_8x4 jRD8x4 |
||||||
|
#define jpeg_idct_6x3 jRD6x3 |
||||||
|
#define jpeg_idct_4x2 jRD4x2 |
||||||
|
#define jpeg_idct_2x1 jRD2x1 |
||||||
|
#define jpeg_idct_8x16 jRD8x16 |
||||||
|
#define jpeg_idct_7x14 jRD7x14 |
||||||
|
#define jpeg_idct_6x12 jRD6x12 |
||||||
|
#define jpeg_idct_5x10 jRD5x10 |
||||||
|
#define jpeg_idct_4x8 jRD4x8 |
||||||
|
#define jpeg_idct_3x6 jRD3x8 |
||||||
|
#define jpeg_idct_2x4 jRD2x4 |
||||||
|
#define jpeg_idct_1x2 jRD1x2 |
||||||
|
#endif /* NEED_SHORT_EXTERNAL_NAMES */ |
||||||
|
|
||||||
|
/* Extern declarations for the forward and inverse DCT routines. */ |
||||||
|
|
||||||
|
EXTERN(void) jpeg_fdct_islow |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_ifast |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_float |
||||||
|
JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_7x7 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_6x6 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_5x5 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_4x4 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_3x3 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_2x2 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_1x1 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_9x9 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_10x10 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_11x11 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_12x12 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_13x13 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_14x14 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_15x15 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_16x16 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_16x8 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_14x7 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_12x6 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_10x5 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_8x4 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_6x3 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_4x2 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_2x1 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_8x16 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_7x14 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_6x12 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_5x10 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_4x8 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_3x6 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_2x4 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
EXTERN(void) jpeg_fdct_1x2 |
||||||
|
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); |
||||||
|
|
||||||
|
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_7x7 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_6x6 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_5x5 |
||||||
|
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_3x3 |
||||||
|
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_9x9 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_10x10 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_11x11 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_12x12 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_13x13 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_14x14 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_15x15 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_16x16 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_16x8 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_14x7 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_12x6 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_10x5 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_8x4 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_6x3 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_4x2 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_2x1 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_8x16 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_7x14 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_6x12 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_5x10 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_4x8 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_3x6 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_2x4 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
EXTERN(void) jpeg_idct_1x2 |
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, |
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for handling fixed-point arithmetic; these are used by many |
||||||
|
* but not all of the DCT/IDCT modules. |
||||||
|
* |
||||||
|
* All values are expected to be of type INT32. |
||||||
|
* Fractional constants are scaled left by CONST_BITS bits. |
||||||
|
* CONST_BITS is defined within each module using these macros, |
||||||
|
* and may differ from one module to the next. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define ONE ((INT32) 1) |
||||||
|
#define CONST_SCALE (ONE << CONST_BITS) |
||||||
|
|
||||||
|
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
|
||||||
|
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time, |
||||||
|
* thus causing a lot of useless floating-point operations at run time. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) |
||||||
|
|
||||||
|
/* Descale and correctly round an INT32 value that's scaled by N bits.
|
||||||
|
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding |
||||||
|
* the fudge factor is correct for either sign of X. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) |
||||||
|
|
||||||
|
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
|
||||||
|
* This macro is used only when the two inputs will actually be no more than |
||||||
|
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a |
||||||
|
* full 32x32 multiply. This provides a useful speedup on many machines. |
||||||
|
* Unfortunately there is no way to specify a 16x16->32 multiply portably |
||||||
|
* in C, but some C compilers will do the right thing if you provide the |
||||||
|
* correct combination of casts. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ |
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) |
||||||
|
#endif |
||||||
|
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ |
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef MULTIPLY16C16 /* default definition */ |
||||||
|
#define MULTIPLY16C16(var,const) ((var) * (const)) |
||||||
|
#endif |
||||||
|
|
||||||
|
/* Same except both inputs are variables. */ |
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ |
||||||
|
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef MULTIPLY16V16 /* default definition */ |
||||||
|
#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) |
||||||
|
#endif |
@ -0,0 +1,384 @@ |
|||||||
|
/*
|
||||||
|
* jddctmgr.c |
||||||
|
* |
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane. |
||||||
|
* Modified 2002-2010 by Guido Vollbeding. |
||||||
|
* This file is part of the Independent JPEG Group's software. |
||||||
|
* For conditions of distribution and use, see the accompanying README file. |
||||||
|
* |
||||||
|
* This file contains the inverse-DCT management logic. |
||||||
|
* This code selects a particular IDCT implementation to be used, |
||||||
|
* and it performs related housekeeping chores. No code in this file |
||||||
|
* is executed per IDCT step, only during 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; |
||||||
|
|
||||||
|
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_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { |
||||||
|
#ifdef IDCT_SCALING_SUPPORTED |
||||||
|
case ((1 << 8) + 1): |
||||||
|
method_ptr = jpeg_idct_1x1; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 2): |
||||||
|
method_ptr = jpeg_idct_2x2; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((3 << 8) + 3): |
||||||
|
method_ptr = jpeg_idct_3x3; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 4): |
||||||
|
method_ptr = jpeg_idct_4x4; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((5 << 8) + 5): |
||||||
|
method_ptr = jpeg_idct_5x5; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 6): |
||||||
|
method_ptr = jpeg_idct_6x6; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((7 << 8) + 7): |
||||||
|
method_ptr = jpeg_idct_7x7; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((9 << 8) + 9): |
||||||
|
method_ptr = jpeg_idct_9x9; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((10 << 8) + 10): |
||||||
|
method_ptr = jpeg_idct_10x10; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((11 << 8) + 11): |
||||||
|
method_ptr = jpeg_idct_11x11; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((12 << 8) + 12): |
||||||
|
method_ptr = jpeg_idct_12x12; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((13 << 8) + 13): |
||||||
|
method_ptr = jpeg_idct_13x13; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((14 << 8) + 14): |
||||||
|
method_ptr = jpeg_idct_14x14; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((15 << 8) + 15): |
||||||
|
method_ptr = jpeg_idct_15x15; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((16 << 8) + 16): |
||||||
|
method_ptr = jpeg_idct_16x16; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((16 << 8) + 8): |
||||||
|
method_ptr = jpeg_idct_16x8; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((14 << 8) + 7): |
||||||
|
method_ptr = jpeg_idct_14x7; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((12 << 8) + 6): |
||||||
|
method_ptr = jpeg_idct_12x6; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((10 << 8) + 5): |
||||||
|
method_ptr = jpeg_idct_10x5; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((8 << 8) + 4): |
||||||
|
method_ptr = jpeg_idct_8x4; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 3): |
||||||
|
method_ptr = jpeg_idct_6x3; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 2): |
||||||
|
method_ptr = jpeg_idct_4x2; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 1): |
||||||
|
method_ptr = jpeg_idct_2x1; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((8 << 8) + 16): |
||||||
|
method_ptr = jpeg_idct_8x16; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((7 << 8) + 14): |
||||||
|
method_ptr = jpeg_idct_7x14; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((6 << 8) + 12): |
||||||
|
method_ptr = jpeg_idct_6x12; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((5 << 8) + 10): |
||||||
|
method_ptr = jpeg_idct_5x10; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((4 << 8) + 8): |
||||||
|
method_ptr = jpeg_idct_4x8; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((3 << 8) + 6): |
||||||
|
method_ptr = jpeg_idct_3x6; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((2 << 8) + 4): |
||||||
|
method_ptr = jpeg_idct_2x4; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
case ((1 << 8) + 2): |
||||||
|
method_ptr = jpeg_idct_1x2; |
||||||
|
method = JDCT_ISLOW; /* jidctint uses islow-style table */ |
||||||
|
break; |
||||||
|
#endif |
||||||
|
case ((DCTSIZE << 8) + DCTSIZE): |
||||||
|
switch (cinfo->dct_method) { |
||||||
|
#ifdef DCT_ISLOW_SUPPORTED |
||||||
|
case JDCT_ISLOW: |
||||||
|
method_ptr = jpeg_idct_islow; |
||||||
|
method = JDCT_ISLOW; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_IFAST_SUPPORTED |
||||||
|
case JDCT_IFAST: |
||||||
|
method_ptr = jpeg_idct_ifast; |
||||||
|
method = JDCT_IFAST; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
#ifdef DCT_FLOAT_SUPPORTED |
||||||
|
case JDCT_FLOAT: |
||||||
|
method_ptr = jpeg_idct_float; |
||||||
|
method = JDCT_FLOAT; |
||||||
|
break; |
||||||
|
#endif |
||||||
|
default: |
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED); |
||||||
|
break; |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
ERREXIT2(cinfo, JERR_BAD_DCTSIZE, |
||||||
|
compptr->DCT_h_scaled_size, compptr->DCT_v_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 |
||||||
|
* We apply a further scale factor of 1/8. |
||||||
|
*/ |
||||||
|
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] * 0.125); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,661 @@ |
|||||||
|
/*
|
||||||
|
* jdinput.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane. |
||||||
|
* Modified 2002-2009 by Guido Vollbeding. |
||||||
|
* 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 jdarith.c. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Private state */ |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
struct jpeg_input_controller pub; /* public fields */ |
||||||
|
|
||||||
|
int inheaders; /* Nonzero 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute output image dimensions and related values. |
||||||
|
* NOTE: this is exported for possible use by application. |
||||||
|
* Hence it mustn't do anything that can't be done twice. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_core_output_dimensions (j_decompress_ptr cinfo) |
||||||
|
/* Do computations that are needed before master selection phase.
|
||||||
|
* This function is used for transcoding and full decompression. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
#ifdef IDCT_SCALING_SUPPORTED |
||||||
|
int ci; |
||||||
|
jpeg_component_info *compptr; |
||||||
|
|
||||||
|
/* Compute actual output image dimensions and DCT scaling choices. */ |
||||||
|
if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { |
||||||
|
/* Provide 1/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 1; |
||||||
|
cinfo->min_DCT_v_scaled_size = 1; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { |
||||||
|
/* Provide 2/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 2; |
||||||
|
cinfo->min_DCT_v_scaled_size = 2; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { |
||||||
|
/* Provide 3/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 3; |
||||||
|
cinfo->min_DCT_v_scaled_size = 3; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { |
||||||
|
/* Provide 4/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 4; |
||||||
|
cinfo->min_DCT_v_scaled_size = 4; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { |
||||||
|
/* Provide 5/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 5; |
||||||
|
cinfo->min_DCT_v_scaled_size = 5; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { |
||||||
|
/* Provide 6/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 6; |
||||||
|
cinfo->min_DCT_v_scaled_size = 6; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { |
||||||
|
/* Provide 7/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 7; |
||||||
|
cinfo->min_DCT_v_scaled_size = 7; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { |
||||||
|
/* Provide 8/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 8; |
||||||
|
cinfo->min_DCT_v_scaled_size = 8; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { |
||||||
|
/* Provide 9/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 9; |
||||||
|
cinfo->min_DCT_v_scaled_size = 9; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { |
||||||
|
/* Provide 10/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 10; |
||||||
|
cinfo->min_DCT_v_scaled_size = 10; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { |
||||||
|
/* Provide 11/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 11; |
||||||
|
cinfo->min_DCT_v_scaled_size = 11; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { |
||||||
|
/* Provide 12/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 12; |
||||||
|
cinfo->min_DCT_v_scaled_size = 12; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { |
||||||
|
/* Provide 13/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 13; |
||||||
|
cinfo->min_DCT_v_scaled_size = 13; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { |
||||||
|
/* Provide 14/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 14; |
||||||
|
cinfo->min_DCT_v_scaled_size = 14; |
||||||
|
} else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { |
||||||
|
/* Provide 15/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 15; |
||||||
|
cinfo->min_DCT_v_scaled_size = 15; |
||||||
|
} else { |
||||||
|
/* Provide 16/block_size scaling */ |
||||||
|
cinfo->output_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); |
||||||
|
cinfo->output_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); |
||||||
|
cinfo->min_DCT_h_scaled_size = 16; |
||||||
|
cinfo->min_DCT_v_scaled_size = 16; |
||||||
|
} |
||||||
|
|
||||||
|
/* Recompute dimensions of components */ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; |
||||||
|
compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; |
||||||
|
} |
||||||
|
|
||||||
|
#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,
|
||||||
|
* and has computed unscaled downsampled_width and downsampled_height. |
||||||
|
*/ |
||||||
|
|
||||||
|
#endif /* IDCT_SCALING_SUPPORTED */ |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
/* Derive block_size, natural_order, and lim_Se */ |
||||||
|
if (cinfo->is_baseline || (cinfo->progressive_mode && |
||||||
|
cinfo->comps_in_scan)) { /* no pseudo SOS marker */ |
||||||
|
cinfo->block_size = DCTSIZE; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
} else |
||||||
|
switch (cinfo->Se) { |
||||||
|
case (1*1-1): |
||||||
|
cinfo->block_size = 1; |
||||||
|
cinfo->natural_order = jpeg_natural_order; /* not needed */ |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (2*2-1): |
||||||
|
cinfo->block_size = 2; |
||||||
|
cinfo->natural_order = jpeg_natural_order2; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (3*3-1): |
||||||
|
cinfo->block_size = 3; |
||||||
|
cinfo->natural_order = jpeg_natural_order3; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (4*4-1): |
||||||
|
cinfo->block_size = 4; |
||||||
|
cinfo->natural_order = jpeg_natural_order4; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (5*5-1): |
||||||
|
cinfo->block_size = 5; |
||||||
|
cinfo->natural_order = jpeg_natural_order5; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (6*6-1): |
||||||
|
cinfo->block_size = 6; |
||||||
|
cinfo->natural_order = jpeg_natural_order6; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (7*7-1): |
||||||
|
cinfo->block_size = 7; |
||||||
|
cinfo->natural_order = jpeg_natural_order7; |
||||||
|
cinfo->lim_Se = cinfo->Se; |
||||||
|
break; |
||||||
|
case (8*8-1): |
||||||
|
cinfo->block_size = 8; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (9*9-1): |
||||||
|
cinfo->block_size = 9; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (10*10-1): |
||||||
|
cinfo->block_size = 10; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (11*11-1): |
||||||
|
cinfo->block_size = 11; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (12*12-1): |
||||||
|
cinfo->block_size = 12; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (13*13-1): |
||||||
|
cinfo->block_size = 13; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (14*14-1): |
||||||
|
cinfo->block_size = 14; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (15*15-1): |
||||||
|
cinfo->block_size = 15; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
case (16*16-1): |
||||||
|
cinfo->block_size = 16; |
||||||
|
cinfo->natural_order = jpeg_natural_order; |
||||||
|
cinfo->lim_Se = DCTSIZE2-1; |
||||||
|
break; |
||||||
|
default: |
||||||
|
ERREXIT4(cinfo, JERR_BAD_PROGRESSION, |
||||||
|
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
/* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size.
|
||||||
|
* In the full decompressor, |
||||||
|
* this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; |
||||||
|
* but in the transcoder, |
||||||
|
* jpeg_calc_output_dimensions is not used, so we must do it here. |
||||||
|
*/ |
||||||
|
cinfo->min_DCT_h_scaled_size = cinfo->block_size; |
||||||
|
cinfo->min_DCT_v_scaled_size = cinfo->block_size; |
||||||
|
|
||||||
|
/* Compute dimensions of components */ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
compptr->DCT_h_scaled_size = cinfo->block_size; |
||||||
|
compptr->DCT_v_scaled_size = cinfo->block_size; |
||||||
|
/* 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 * cinfo->block_size)); |
||||||
|
compptr->height_in_blocks = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
/* 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 * cinfo->block_size)); |
||||||
|
|
||||||
|
/* 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_h_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 * cinfo->block_size)); |
||||||
|
cinfo->MCU_rows_in_scan = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height, |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
|
||||||
|
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_h_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. |
||||||
|
* |
||||||
|
* Note: This function should NOT return a pseudo SOS marker (with zero |
||||||
|
* component number) to the caller. A pseudo marker received by |
||||||
|
* read_markers is processed and then skipped for other 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; |
||||||
|
|
||||||
|
for (;;) { /* Loop to pass pseudo SOS marker */ |
||||||
|
val = (*cinfo->marker->read_markers) (cinfo); |
||||||
|
|
||||||
|
switch (val) { |
||||||
|
case JPEG_REACHED_SOS: /* Found SOS */ |
||||||
|
if (inputctl->inheaders) { /* 1st SOS */ |
||||||
|
if (inputctl->inheaders == 1) |
||||||
|
initial_setup(cinfo); |
||||||
|
if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ |
||||||
|
inputctl->inheaders = 2; |
||||||
|
break; |
||||||
|
} |
||||||
|
inputctl->inheaders = 0; |
||||||
|
/* 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! */ |
||||||
|
if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ |
||||||
|
break; |
||||||
|
start_input_pass(cinfo); |
||||||
|
} |
||||||
|
return val; |
||||||
|
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; |
||||||
|
} |
||||||
|
return val; |
||||||
|
case JPEG_SUSPENDED: |
||||||
|
return val; |
||||||
|
default: |
||||||
|
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 = 1; |
||||||
|
/* 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 = 1; |
||||||
|
} |
@ -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_v_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_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_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_v_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_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_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_v_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_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_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_v_scaled_size; |
||||||
|
rgroup = iMCUheight / cinfo->min_DCT_v_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_v_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_v_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_v_scaled_size + 1); |
||||||
|
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_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_v_scaled_size < 2) /* unsupported, see comments above */ |
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL); |
||||||
|
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ |
||||||
|
ngroups = cinfo->min_DCT_v_scaled_size + 2; |
||||||
|
} else { |
||||||
|
ngroups = cinfo->min_DCT_v_scaled_size; |
||||||
|
} |
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / |
||||||
|
cinfo->min_DCT_v_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_h_scaled_size, |
||||||
|
(JDIMENSION) (rgroup * ngroups)); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,533 @@ |
|||||||
|
/*
|
||||||
|
* jdmaster.c |
||||||
|
* |
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane. |
||||||
|
* Modified 2002-2009 by Guido Vollbeding. |
||||||
|
* 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 master control logic for the JPEG decompressor. |
||||||
|
* These routines are concerned with selecting the modules to be executed |
||||||
|
* and with determining the number of passes and the work to be done in each |
||||||
|
* pass. |
||||||
|
*/ |
||||||
|
|
||||||
|
#define JPEG_INTERNALS |
||||||
|
#include "jinclude.h" |
||||||
|
#include "jpeglib.h" |
||||||
|
|
||||||
|
|
||||||
|
/* Private state */ |
||||||
|
|
||||||
|
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) |
||||||
|
{ |
||||||
|
#ifdef UPSAMPLE_MERGING_SUPPORTED |
||||||
|
/* Merging is the equivalent of plain box-filter upsampling */ |
||||||
|
if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) |
||||||
|
return FALSE; |
||||||
|
/* jdmerge.c only supports YCC=>RGB color conversion */ |
||||||
|
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || |
||||||
|
cinfo->out_color_space != JCS_RGB || |
||||||
|
cinfo->out_color_components != RGB_PIXELSIZE) |
||||||
|
return FALSE; |
||||||
|
/* and it only handles 2h1v or 2h2v sampling ratios */ |
||||||
|
if (cinfo->comp_info[0].h_samp_factor != 2 || |
||||||
|
cinfo->comp_info[1].h_samp_factor != 1 || |
||||||
|
cinfo->comp_info[2].h_samp_factor != 1 || |
||||||
|
cinfo->comp_info[0].v_samp_factor > 2 || |
||||||
|
cinfo->comp_info[1].v_samp_factor != 1 || |
||||||
|
cinfo->comp_info[2].v_samp_factor != 1) |
||||||
|
return FALSE; |
||||||
|
/* furthermore, it doesn't work if we've scaled the IDCTs differently */ |
||||||
|
if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || |
||||||
|
cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || |
||||||
|
cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || |
||||||
|
cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || |
||||||
|
cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || |
||||||
|
cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_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 |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute output image dimensions and related values. |
||||||
|
* 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.
|
||||||
|
* This function is used for full decompression. |
||||||
|
*/ |
||||||
|
{ |
||||||
|
#ifdef IDCT_SCALING_SUPPORTED |
||||||
|
int ci; |
||||||
|
jpeg_component_info *compptr; |
||||||
|
#endif |
||||||
|
|
||||||
|
/* Prevent application from calling me at wrong times */ |
||||||
|
if (cinfo->global_state != DSTATE_READY) |
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); |
||||||
|
|
||||||
|
/* Compute core output image dimensions and DCT scaling choices. */ |
||||||
|
jpeg_core_output_dimensions(cinfo); |
||||||
|
|
||||||
|
#ifdef IDCT_SCALING_SUPPORTED |
||||||
|
|
||||||
|
/* 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 adapts subsampling ratios which are powers of 2. |
||||||
|
*/ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
int ssize = 1; |
||||||
|
while (cinfo->min_DCT_h_scaled_size * ssize <= |
||||||
|
(cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && |
||||||
|
(cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { |
||||||
|
ssize = ssize * 2; |
||||||
|
} |
||||||
|
compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; |
||||||
|
ssize = 1; |
||||||
|
while (cinfo->min_DCT_v_scaled_size * ssize <= |
||||||
|
(cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && |
||||||
|
(cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { |
||||||
|
ssize = ssize * 2; |
||||||
|
} |
||||||
|
compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; |
||||||
|
|
||||||
|
/* We don't support IDCT ratios larger than 2. */ |
||||||
|
if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) |
||||||
|
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; |
||||||
|
else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) |
||||||
|
compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; |
||||||
|
} |
||||||
|
|
||||||
|
/* Recompute downsampled dimensions of components;
|
||||||
|
* application needs to know these if using raw downsampled data. |
||||||
|
*/ |
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
||||||
|
ci++, compptr++) { |
||||||
|
/* Size in samples, after IDCT scaling */ |
||||||
|
compptr->downsampled_width = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_width * |
||||||
|
(long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), |
||||||
|
(long) (cinfo->max_h_samp_factor * cinfo->block_size)); |
||||||
|
compptr->downsampled_height = (JDIMENSION) |
||||||
|
jdiv_round_up((long) cinfo->image_height * |
||||||
|
(long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), |
||||||
|
(long) (cinfo->max_v_samp_factor * cinfo->block_size)); |
||||||
|
} |
||||||
|
|
||||||
|
#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) |
||||||
|
jinit_arith_decoder(cinfo); |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up at end of an output pass. |
||||||
|
*/ |
||||||
|
|
||||||
|
METHODDEF(void) |
||||||
|
finish_output_pass (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master; |
||||||
|
|
||||||
|
if (cinfo->quantize_colors) |
||||||
|
(*cinfo->cquantize->finish_pass) (cinfo); |
||||||
|
master->pass_number++; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#ifdef D_MULTISCAN_FILES_SUPPORTED |
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to a new external colormap between output passes. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jpeg_new_colormap (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_master_ptr master = (my_master_ptr) cinfo->master; |
||||||
|
|
||||||
|
/* Prevent application from calling me at wrong times */ |
||||||
|
if (cinfo->global_state != DSTATE_BUFIMAGE) |
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); |
||||||
|
|
||||||
|
if (cinfo->quantize_colors && cinfo->enable_external_quant && |
||||||
|
cinfo->colormap != NULL) { |
||||||
|
/* Select 2-pass quantizer for external colormap use */ |
||||||
|
cinfo->cquantize = master->quantizer_2pass; |
||||||
|
/* Notify quantizer of colormap change */ |
||||||
|
(*cinfo->cquantize->new_color_map) (cinfo); |
||||||
|
master->pub.is_dummy_pass = FALSE; /* just in case */ |
||||||
|
} else |
||||||
|
ERREXIT(cinfo, JERR_MODE_CHANGE); |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */ |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize master decompression control and select active modules. |
||||||
|
* This is performed at the start of jpeg_start_decompress. |
||||||
|
*/ |
||||||
|
|
||||||
|
GLOBAL(void) |
||||||
|
jinit_master_decompress (j_decompress_ptr cinfo) |
||||||
|
{ |
||||||
|
my_master_ptr master; |
||||||
|
|
||||||
|
master = (my_master_ptr) |
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
||||||
|
SIZEOF(my_decomp_master)); |
||||||
|
cinfo->master = (struct jpeg_decomp_master *) master; |
||||||
|
master->pub.prepare_for_output_pass = prepare_for_output_pass; |
||||||
|
master->pub.finish_output_pass = finish_output_pass; |
||||||
|
|
||||||
|
master->pub.is_dummy_pass = FALSE; |
||||||
|
|
||||||
|
master_selection(cinfo); |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue