mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 04:51:19 +00:00
- Switched to IJG code for reading JPEG images. I have included a stripped-
down version of the library with the ZDoom source. (It actually uses less space than zlib now.) Unix users probably ought to use the system-supplied libjpeg instead. I modified Makefile.linux to hopefully do that. I'm sure Jim or someone will correct me if it doesn't actually work. SVN r293 (trunk)
This commit is contained in:
parent
21869a6c08
commit
ed12bdc0f4
42 changed files with 11261 additions and 623 deletions
|
@ -16,7 +16,7 @@ ifdef GC
|
||||||
endif
|
endif
|
||||||
CFLAGS += -MMD -DHAVE_FILELENGTH -D__forceinline=inline -Izlib -IFLAC `sdl-config --cflags`
|
CFLAGS += -MMD -DHAVE_FILELENGTH -D__forceinline=inline -Izlib -IFLAC `sdl-config --cflags`
|
||||||
CFLAGS += -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DNEED_STRUPR
|
CFLAGS += -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DNEED_STRUPR
|
||||||
LDFLAGS += -lFLAC++ -lFLAC -lz -lfmod `sdl-config --libs`
|
LDFLAGS += -lFLAC++ -lFLAC -lz -ljpeg -lfmod `sdl-config --libs`
|
||||||
NASMFLAGS += -f elf -DM_TARGET_LINUX
|
NASMFLAGS += -f elf -DM_TARGET_LINUX
|
||||||
|
|
||||||
SRCDIRS = src/ $(addprefix src/,g_doom/ g_heretic/ g_hexen/ g_raven/ g_shared/ g_strife/ oplsynth/ sound/ sdl/)
|
SRCDIRS = src/ $(addprefix src/,g_doom/ g_heretic/ g_hexen/ g_raven/ g_shared/ g_strife/ oplsynth/ sound/ sdl/)
|
||||||
|
|
|
@ -27,6 +27,7 @@ basetools: ccdv.exe
|
||||||
$(MAKE) -C tools/xlatcc
|
$(MAKE) -C tools/xlatcc
|
||||||
$(MAKE) -C wadsrc -f Makefile.mgw
|
$(MAKE) -C wadsrc -f Makefile.mgw
|
||||||
$(MAKE) -C flac -f Makefile.mgw
|
$(MAKE) -C flac -f Makefile.mgw
|
||||||
|
$(MAKE) -C jpeg-6b -f Makefile.mgw
|
||||||
|
|
||||||
cleanexe:
|
cleanexe:
|
||||||
@$(MAKE) -C . -f Makefile.mingw clean
|
@$(MAKE) -C . -f Makefile.mingw clean
|
||||||
|
@ -41,6 +42,7 @@ clean:
|
||||||
@$(MAKE) -C . -f Makefile.mingw clean
|
@$(MAKE) -C . -f Makefile.mingw clean
|
||||||
@$(MAKE) -C zlib -f Makefile.mgw clean
|
@$(MAKE) -C zlib -f Makefile.mgw clean
|
||||||
@$(MAKE) -C flac -f Makefile.mgw clean
|
@$(MAKE) -C flac -f Makefile.mgw clean
|
||||||
|
@$(MAKE) -C jpeg-6b -f Makefile.mgw clean
|
||||||
ifeq (msys,$(OSTYPE))
|
ifeq (msys,$(OSTYPE))
|
||||||
rm -f ccdv.exe
|
rm -f ccdv.exe
|
||||||
else
|
else
|
||||||
|
|
|
@ -25,8 +25,8 @@ RELEASEOBJDIR ?= releaseobj
|
||||||
CCDV = @ccdv
|
CCDV = @ccdv
|
||||||
RE2C = tools/re2c/re2c
|
RE2C = tools/re2c/re2c
|
||||||
|
|
||||||
CPPFLAGS = -DWIN32 -D_WIN32 -D_WINDOWS -DHAVE_STRUPR -DHAVE_FILELENGTH -DI_DO_NOT_LIKE_BIG_DOWNLOADS -D__forceinline=inline -MMD -Izlib -IFLAC -Isrc -Isrc/win32 -Isrc/g_doom -Isrc/g_heretic -I src/g_hexen -Isrc/g_raven -Isrc/g_strife -Isrc/g_shared -Isrc/oplsynth -Isrc/sound
|
CPPFLAGS = -DWIN32 -D_WIN32 -D_WINDOWS -DHAVE_STRUPR -DHAVE_FILELENGTH -DI_DO_NOT_LIKE_BIG_DOWNLOADS -D__forceinline=inline -MMD -Izlib -IFLAC -Ijpeg-6b -Isrc -Isrc/win32 -Isrc/g_doom -Isrc/g_heretic -I src/g_hexen -Isrc/g_raven -Isrc/g_strife -Isrc/g_shared -Isrc/oplsynth -Isrc/sound
|
||||||
LDFLAGS += flac/libflac.a zlib/libz.a -lfmod -lwsock32 -lwinmm -lddraw -ldsound -ldxguid -ldinput8 -lole32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lsetupapi -lws2_32 -Wl,--subsystem,windows
|
LDFLAGS += flac/libflac.a zlib/libz.a jpeg-6b/libjpeg.a -lfmod -lwsock32 -lwinmm -lddraw -ldsound -ldxguid -ldinput8 -lole32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lsetupapi -lws2_32 -Wl,--subsystem,windows
|
||||||
|
|
||||||
ifdef FMODDIR
|
ifdef FMODDIR
|
||||||
CPPFLAGS += -I$(FMODDIR)/api/inc
|
CPPFLAGS += -I$(FMODDIR)/api/inc
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
August 16, 2006
|
||||||
|
- Switched to IJG code for reading JPEG images. I have included a stripped-
|
||||||
|
down version of the library with the ZDoom source. (It actually uses less
|
||||||
|
space than zlib now.) Unix users probably ought to use the system-supplied
|
||||||
|
libjpeg instead. I modified Makefile.linux to hopefully do that. I'm sure
|
||||||
|
Jim or someone will correct me if it doesn't actually work.
|
||||||
|
|
||||||
August 14, 2006
|
August 14, 2006
|
||||||
- Added JPEG texture support, courtesy of Ken's Picture Library. I will
|
- Added JPEG texture support, courtesy of Ken's Picture Library. I will
|
||||||
probably switch to the IJG library once I pare it down. (Ken's code is 18K
|
probably switch to the IJG library once I pare it down. (Ken's code is 18K
|
||||||
|
|
63
jpeg-6b/Makefile.mgw
Normal file
63
jpeg-6b/Makefile.mgw
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Makefile for libjpeg, derived from zlib/Makefile.mgw.
|
||||||
|
|
||||||
|
STATICLIB = libjpeg.a
|
||||||
|
|
||||||
|
CCDV = @../ccdv
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = $(LOC) -O2 -Wall -fomit-frame-pointer
|
||||||
|
|
||||||
|
AS = $(CC)
|
||||||
|
ASFLAGS = $(LOC) -Wall
|
||||||
|
|
||||||
|
LD = $(CC)
|
||||||
|
LDFLAGS = $(LOC) -s
|
||||||
|
|
||||||
|
AR = ar
|
||||||
|
ARFLAGS = rcs
|
||||||
|
|
||||||
|
OBJS = jcomapi.o jdapimin.o jdapistd.o jdatasrc.o jdcoefct.o jdcolor.o \
|
||||||
|
jddctmgr.o jdhuff.o jdinput.o jdmainct.o jdmarker.o jdmaster.o \
|
||||||
|
jdmerge.o jdphuff.o jdpostct.o jdsample.o jerror.o jidctint.o \
|
||||||
|
jmemmgr.o jutils.o
|
||||||
|
|
||||||
|
all: $(STATICLIB)
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CCDV) $(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(STATICLIB): $(OBJS)
|
||||||
|
$(CCDV) $(AR) $(ARFLAGS) $@ $(OBJS)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
ifeq (msys,$(OSTYPE))
|
||||||
|
rm -f $(STATICLIB)
|
||||||
|
rm -f *.o
|
||||||
|
else
|
||||||
|
-del /q /f $(STATICLIB) 2>nul
|
||||||
|
-del /q /f *.o 2>nul
|
||||||
|
endif
|
||||||
|
|
||||||
|
jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h
|
||||||
|
jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||||
|
jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h
|
||||||
|
jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h
|
||||||
|
jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h
|
||||||
|
jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||||
|
jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||||
|
jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
385
jpeg-6b/README
Normal file
385
jpeg-6b/README
Normal file
|
@ -0,0 +1,385 @@
|
||||||
|
The Independent JPEG Group's JPEG software
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
README for release 6b of 27-Mar-1998
|
||||||
|
====================================
|
||||||
|
|
||||||
|
This distribution contains the sixth 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.
|
||||||
|
|
||||||
|
Serious users of this software (particularly those incorporating it into
|
||||||
|
larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
|
||||||
|
our electronic mailing list. Mailing list members are notified of updates
|
||||||
|
and have a chance to participate in technical discussions, etc.
|
||||||
|
|
||||||
|
This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
|
||||||
|
Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
|
||||||
|
Guido Vollbeding, 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.
|
||||||
|
RELATED SOFTWARE Other stuff you should get.
|
||||||
|
FILE FORMAT WARS Software *not* to get.
|
||||||
|
TO DO Plans for future IJG releases.
|
||||||
|
|
||||||
|
Other documentation files in the distribution are:
|
||||||
|
|
||||||
|
User documentation:
|
||||||
|
install.doc How to configure and install the IJG software.
|
||||||
|
usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
|
||||||
|
rdjpgcom, and wrjpgcom.
|
||||||
|
*.1 Unix-style man pages for programs (same info as usage.doc).
|
||||||
|
wizard.doc Advanced usage instructions for JPEG wizards only.
|
||||||
|
change.log Version-to-version change highlights.
|
||||||
|
Programmer and internal documentation:
|
||||||
|
libjpeg.doc How to use the JPEG library in your own programs.
|
||||||
|
example.c Sample code for calling the JPEG library.
|
||||||
|
structure.doc Overview of the JPEG library's internal structure.
|
||||||
|
filelist.doc Road map of IJG files.
|
||||||
|
coderules.doc Coding style rules --- please read if you contribute code.
|
||||||
|
|
||||||
|
Please read at least the files install.doc and usage.doc. Useful information
|
||||||
|
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
|
||||||
|
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
|
||||||
|
|
||||||
|
If you want to understand how the JPEG code works, we suggest reading one or
|
||||||
|
more of the REFERENCES, then looking at the documentation files (in roughly
|
||||||
|
the order listed) before diving into the code.
|
||||||
|
|
||||||
|
|
||||||
|
OVERVIEW
|
||||||
|
========
|
||||||
|
|
||||||
|
This package contains C software to implement JPEG image compression and
|
||||||
|
decompression. JPEG (pronounced "jay-peg") is a standardized compression
|
||||||
|
method for full-color and gray-scale images. JPEG is intended for compressing
|
||||||
|
"real-world" scenes; line drawings, cartoons and other non-realistic images
|
||||||
|
are not its strong suit. JPEG is lossy, meaning that the output image is not
|
||||||
|
exactly identical to the input image. Hence you must not use JPEG if you
|
||||||
|
have to have identical output bits. However, on typical photographic images,
|
||||||
|
very good compression levels can be obtained with no visible change, and
|
||||||
|
remarkably high compression levels are possible if you can tolerate a
|
||||||
|
low-quality image. For more details, see the references, or just experiment
|
||||||
|
with various compression settings.
|
||||||
|
|
||||||
|
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.
|
||||||
|
For legal reasons, we are not distributing code for the arithmetic-coding
|
||||||
|
variants of JPEG; see LEGAL ISSUES. 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-1998, Thomas G. Lane.
|
||||||
|
All Rights Reserved except as specified below.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute this
|
||||||
|
software (or portions thereof) for any purpose, without fee, subject to these
|
||||||
|
conditions:
|
||||||
|
(1) If any part of the source code for this software is distributed, then this
|
||||||
|
README file must be included, with this copyright and no-warranty notice
|
||||||
|
unaltered; and any additions, deletions, or changes to the original files
|
||||||
|
must be clearly indicated in accompanying documentation.
|
||||||
|
(2) If only executable code is distributed, then the accompanying
|
||||||
|
documentation must state that "this software is based in part on the work of
|
||||||
|
the Independent JPEG Group".
|
||||||
|
(3) Permission for use of this software is granted only if the user accepts
|
||||||
|
full responsibility for any undesirable consequences; the authors accept
|
||||||
|
NO LIABILITY for damages of any kind.
|
||||||
|
|
||||||
|
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,
|
||||||
|
ltconfig, ltmain.sh). Another support script, install-sh, is copyright
|
||||||
|
by M.I.T. but is also freely distributable.
|
||||||
|
|
||||||
|
It appears that the arithmetic coding option of the JPEG spec is covered by
|
||||||
|
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
|
||||||
|
legally be used without obtaining one or more licenses. For this reason,
|
||||||
|
support for arithmetic coding has been removed from the free JPEG software.
|
||||||
|
(Since arithmetic coding provides only a marginal gain over the unpatented
|
||||||
|
Huffman mode, it is unlikely that very many implementations will support it.)
|
||||||
|
So far as we are aware, there are no patent restrictions on the remaining
|
||||||
|
code.
|
||||||
|
|
||||||
|
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 highly recommend reading one or more of these references before trying to
|
||||||
|
understand the innards of the JPEG software.
|
||||||
|
|
||||||
|
The best short technical introduction to the JPEG compression algorithm is
|
||||||
|
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||||
|
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||||
|
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||||
|
applications of JPEG, and related topics.) If you don't have the CACM issue
|
||||||
|
handy, a PostScript file containing a revised version of Wallace's article is
|
||||||
|
available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
|
||||||
|
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
|
||||||
|
omits the sample images that appeared in CACM, but it includes corrections
|
||||||
|
and some added material. Note: the Wallace article is copyright ACM and IEEE,
|
||||||
|
and it may not be used for commercial purposes.
|
||||||
|
|
||||||
|
A somewhat less technical, more leisurely introduction to JPEG can be found in
|
||||||
|
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
|
||||||
|
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
|
||||||
|
good explanations and example C code for a multitude of compression methods
|
||||||
|
including JPEG. It is an excellent source if you are comfortable reading C
|
||||||
|
code but don't know much about data compression in general. The book's JPEG
|
||||||
|
sample code is far from industrial-strength, but when you are ready to look
|
||||||
|
at a full implementation, you've got one here...
|
||||||
|
|
||||||
|
The best full description of JPEG is the textbook "JPEG Still Image Data
|
||||||
|
Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
|
||||||
|
by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
|
||||||
|
The book includes the complete text of the ISO JPEG standards (DIS 10918-1
|
||||||
|
and draft DIS 10918-2). This is by far the most complete exposition of JPEG
|
||||||
|
in existence, and we highly recommend it.
|
||||||
|
|
||||||
|
The JPEG standard itself is not available electronically; you must order a
|
||||||
|
paper copy through ISO or ITU. (Unless you feel a need to own a certified
|
||||||
|
official copy, we recommend buying the Pennebaker and Mitchell book instead;
|
||||||
|
it's much cheaper and includes a great deal of useful explanatory material.)
|
||||||
|
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
|
||||||
|
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
|
||||||
|
doesn't take credit card orders, but Global does.) It's not cheap: as of
|
||||||
|
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
|
||||||
|
shipping/handling. The standard is divided into two parts, Part 1 being the
|
||||||
|
actual specification, while Part 2 covers compliance testing methods. Part 1
|
||||||
|
is titled "Digital Compression and Coding of Continuous-tone Still Images,
|
||||||
|
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
|
||||||
|
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
|
||||||
|
Continuous-tone Still Images, Part 2: Compliance testing" and has document
|
||||||
|
numbers ISO/IEC IS 10918-2, ITU-T T.83.
|
||||||
|
|
||||||
|
Some extensions to the original JPEG standard are defined in JPEG Part 3,
|
||||||
|
a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
|
||||||
|
currently does not support any Part 3 extensions.
|
||||||
|
|
||||||
|
The JPEG standard does not specify all details of an interchangeable file
|
||||||
|
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||||
|
1.02. A copy of the JFIF spec is available from:
|
||||||
|
Literature Department
|
||||||
|
C-Cube Microsystems, Inc.
|
||||||
|
1778 McCarthy Blvd.
|
||||||
|
Milpitas, CA 95035
|
||||||
|
phone (408) 944-6300, fax (408) 944-6314
|
||||||
|
A PostScript version of this document is available by FTP at
|
||||||
|
ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
|
||||||
|
version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
|
||||||
|
the figures.
|
||||||
|
|
||||||
|
The TIFF 6.0 file format specification can be obtained by FTP from
|
||||||
|
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
|
||||||
|
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
|
||||||
|
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
|
||||||
|
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
|
||||||
|
(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
|
||||||
|
from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
|
||||||
|
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
|
||||||
|
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
|
||||||
|
uses our library to implement TIFF/JPEG per the Note. libtiff is available
|
||||||
|
from ftp://ftp.sgi.com/graphics/tiff/.
|
||||||
|
|
||||||
|
|
||||||
|
ARCHIVE LOCATIONS
|
||||||
|
=================
|
||||||
|
|
||||||
|
The "official" archive site for this software is ftp.uu.net (Internet
|
||||||
|
address 192.48.96.9). The most recent released version can always be found
|
||||||
|
there in directory graphics/jpeg. This particular version will be archived
|
||||||
|
as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
|
||||||
|
direct Internet access, UUNET's archives are also available via UUCP; contact
|
||||||
|
help@uunet.uu.net for information on retrieving files that way.
|
||||||
|
|
||||||
|
Numerous Internet sites maintain copies of the UUNET files. However, only
|
||||||
|
ftp.uu.net is guaranteed to have the latest official version.
|
||||||
|
|
||||||
|
You can also obtain this software in DOS-compatible "zip" archive format from
|
||||||
|
the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
|
||||||
|
on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
|
||||||
|
"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
|
||||||
|
release.
|
||||||
|
|
||||||
|
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
|
||||||
|
general information about JPEG. It is updated constantly and therefore is
|
||||||
|
not included in this distribution. The FAQ is posted every two weeks to
|
||||||
|
Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
|
||||||
|
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
|
||||||
|
and other news.answers archive sites, including the official news.answers
|
||||||
|
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
|
||||||
|
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
|
||||||
|
with body
|
||||||
|
send usenet/news.answers/jpeg-faq/part1
|
||||||
|
send usenet/news.answers/jpeg-faq/part2
|
||||||
|
|
||||||
|
|
||||||
|
RELATED SOFTWARE
|
||||||
|
================
|
||||||
|
|
||||||
|
Numerous viewing and image manipulation programs now support JPEG. (Quite a
|
||||||
|
few of them use this library to do so.) The JPEG FAQ described above lists
|
||||||
|
some of the more popular free and shareware viewers, and tells where to
|
||||||
|
obtain them on Internet.
|
||||||
|
|
||||||
|
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
|
||||||
|
PBMPLUS software, which provides many useful operations on PPM-format image
|
||||||
|
files. In particular, it can convert PPM images to and from a wide range of
|
||||||
|
other formats, thus making cjpeg/djpeg considerably more useful. The latest
|
||||||
|
version is distributed by the NetPBM group, and is available from numerous
|
||||||
|
sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
|
||||||
|
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
|
||||||
|
you are likely to have difficulty making it work on any non-Unix machine.
|
||||||
|
|
||||||
|
A different free JPEG implementation, written by the PVRG group at Stanford,
|
||||||
|
is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
|
||||||
|
is designed for research and experimentation rather than production use;
|
||||||
|
it is slower, harder to use, and less portable than the IJG code, but it
|
||||||
|
is easier to read and modify. Also, the PVRG code supports lossless JPEG,
|
||||||
|
which we do not. (On the other hand, it doesn't do progressive JPEG.)
|
||||||
|
|
||||||
|
|
||||||
|
FILE FORMAT WARS
|
||||||
|
================
|
||||||
|
|
||||||
|
Some JPEG programs produce files that are not compatible with our library.
|
||||||
|
The root of the problem is that the ISO JPEG committee failed to specify a
|
||||||
|
concrete file format. Some vendors "filled in the blanks" on their own,
|
||||||
|
creating proprietary formats that no one else could read. (For example, none
|
||||||
|
of the early commercial JPEG implementations for the Macintosh were able to
|
||||||
|
exchange compressed files.)
|
||||||
|
|
||||||
|
The file format we have adopted is called JFIF (see REFERENCES). This format
|
||||||
|
has been agreed to by a number of major commercial JPEG vendors, and it has
|
||||||
|
become the de facto standard. JFIF is a minimal or "low end" representation.
|
||||||
|
We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
|
||||||
|
Technical Note #2) for "high end" applications that need to record a lot of
|
||||||
|
additional data about an image. TIFF/JPEG is fairly new and not yet widely
|
||||||
|
supported, unfortunately.
|
||||||
|
|
||||||
|
The upcoming JPEG Part 3 standard defines a file format called SPIFF.
|
||||||
|
SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
|
||||||
|
be able to read the most common variant of SPIFF. SPIFF has some technical
|
||||||
|
advantages over JFIF, but its major claim to fame is simply that it is an
|
||||||
|
official standard rather than an informal one. At this point it is unclear
|
||||||
|
whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
|
||||||
|
standard. IJG intends to support SPIFF once the standard is frozen, but we
|
||||||
|
have not decided whether it should become our default output format or not.
|
||||||
|
(In any case, our decoder will remain capable of reading JFIF indefinitely.)
|
||||||
|
|
||||||
|
Various proprietary file formats incorporating JPEG compression also exist.
|
||||||
|
We have little or no sympathy for the existence of these formats. Indeed,
|
||||||
|
one of the original reasons for developing this free software was to help
|
||||||
|
force convergence on common, open format standards for JPEG files. Don't
|
||||||
|
use a proprietary file format!
|
||||||
|
|
||||||
|
|
||||||
|
TO DO
|
||||||
|
=====
|
||||||
|
|
||||||
|
The major thrust for v7 will probably be improvement of visual quality.
|
||||||
|
The current method for scaling the quantization tables is known not to be
|
||||||
|
very good at low Q values. We also intend to investigate block boundary
|
||||||
|
smoothing, "poor man's variable quantization", and other means of improving
|
||||||
|
quality-vs-file-size performance without sacrificing compatibility.
|
||||||
|
|
||||||
|
In future versions, we are considering supporting some of the upcoming JPEG
|
||||||
|
Part 3 extensions --- principally, variable quantization and the SPIFF file
|
||||||
|
format.
|
||||||
|
|
||||||
|
As always, speeding things up is of great interest.
|
||||||
|
|
||||||
|
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
|
106
jpeg-6b/jcomapi.c
Normal file
106
jpeg-6b/jcomapi.c
Normal file
|
@ -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;
|
||||||
|
}
|
26
jpeg-6b/jconfig.h
Normal file
26
jpeg-6b/jconfig.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
|
||||||
|
/* see jconfig.doc for explanations */
|
||||||
|
|
||||||
|
#define HAVE_PROTOTYPES
|
||||||
|
#define HAVE_UNSIGNED_CHAR
|
||||||
|
#define HAVE_UNSIGNED_SHORT
|
||||||
|
/* #define void char */
|
||||||
|
/* #define const */
|
||||||
|
#undef CHAR_IS_UNSIGNED
|
||||||
|
#define HAVE_STDDEF_H
|
||||||
|
#define HAVE_STDLIB_H
|
||||||
|
#undef NEED_BSD_STRINGS
|
||||||
|
#undef NEED_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* 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 */
|
343
jpeg-6b/jdapimin.c
Normal file
343
jpeg-6b/jdapimin.c
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
/*
|
||||||
|
* jdapimin.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains application interface code for the decompression half
|
||||||
|
* of the JPEG library. These are the "minimum" API routines that may be
|
||||||
|
* needed in either the normal full-decompression case or the
|
||||||
|
* transcoding-only case.
|
||||||
|
*
|
||||||
|
* Most of the routines intended to be called directly by an application
|
||||||
|
* are in this file or in jdapistd.c. But also see jcomapi.c for routines
|
||||||
|
* shared by compression and decompression, and jdtrans.c for the transcoding
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization of a JPEG decompression object.
|
||||||
|
* The error manager must already be set up (in case memory manager fails).
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Guard against version mismatches between library and caller. */
|
||||||
|
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
|
||||||
|
if (version != JPEG_LIB_VERSION)
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||||
|
if (structsize != SIZEOF(struct jpeg_decompress_struct))
|
||||||
|
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
|
||||||
|
(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
|
||||||
|
|
||||||
|
/* For debugging purposes, we zero the whole master structure.
|
||||||
|
* But the application has already set the err pointer, and may have set
|
||||||
|
* client_data, so we have to save and restore those fields.
|
||||||
|
* Note: if application hasn't set client_data, tools like Purify may
|
||||||
|
* complain here.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr * err = cinfo->err;
|
||||||
|
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
|
||||||
|
MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
|
||||||
|
cinfo->err = err;
|
||||||
|
cinfo->client_data = client_data;
|
||||||
|
}
|
||||||
|
cinfo->is_decompressor = TRUE;
|
||||||
|
|
||||||
|
/* Initialize a memory manager instance for this object */
|
||||||
|
jinit_memory_mgr((j_common_ptr) cinfo);
|
||||||
|
|
||||||
|
/* Zero out pointers to permanent structures. */
|
||||||
|
cinfo->progress = NULL;
|
||||||
|
cinfo->src = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||||
|
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||||
|
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize marker processor so application can override methods
|
||||||
|
* for COM, APPn markers before calling jpeg_read_header.
|
||||||
|
*/
|
||||||
|
cinfo->marker_list = NULL;
|
||||||
|
jinit_marker_reader(cinfo);
|
||||||
|
|
||||||
|
/* And initialize the overall input controller. */
|
||||||
|
jinit_input_controller(cinfo);
|
||||||
|
|
||||||
|
/* OK, I'm ready */
|
||||||
|
cinfo->global_state = DSTATE_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destruction of a JPEG decompression object
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_destroy_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abort processing of a JPEG decompression operation,
|
||||||
|
* but don't destroy the object itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_abort_decompress (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set default decompression parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
default_decompress_parms (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Guess the input colorspace, and set output colorspace accordingly. */
|
||||||
|
/* (Wish JPEG committee had provided a real way to specify this...) */
|
||||||
|
/* Note application may override our guesses. */
|
||||||
|
switch (cinfo->num_components) {
|
||||||
|
case 1:
|
||||||
|
cinfo->jpeg_color_space = JCS_GRAYSCALE;
|
||||||
|
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (cinfo->saw_JFIF_marker) {
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
|
||||||
|
} else if (cinfo->saw_Adobe_marker) {
|
||||||
|
switch (cinfo->Adobe_transform) {
|
||||||
|
case 0:
|
||||||
|
cinfo->jpeg_color_space = JCS_RGB;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Saw no special markers, try to guess from the component IDs */
|
||||||
|
int cid0 = cinfo->comp_info[0].component_id;
|
||||||
|
int cid1 = cinfo->comp_info[1].component_id;
|
||||||
|
int cid2 = cinfo->comp_info[2].component_id;
|
||||||
|
|
||||||
|
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
|
||||||
|
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
|
||||||
|
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||||
|
else {
|
||||||
|
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Always guess RGB is proper output colorspace. */
|
||||||
|
cinfo->out_color_space = JCS_RGB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (cinfo->saw_Adobe_marker) {
|
||||||
|
switch (cinfo->Adobe_transform) {
|
||||||
|
case 0:
|
||||||
|
cinfo->jpeg_color_space = JCS_CMYK;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cinfo->jpeg_color_space = JCS_YCCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||||
|
cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No special markers, assume straight CMYK. */
|
||||||
|
cinfo->jpeg_color_space = JCS_CMYK;
|
||||||
|
}
|
||||||
|
cinfo->out_color_space = JCS_CMYK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cinfo->jpeg_color_space = JCS_UNKNOWN;
|
||||||
|
cinfo->out_color_space = JCS_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set defaults for other decompression parameters. */
|
||||||
|
cinfo->scale_num = 1; /* 1:1 scaling */
|
||||||
|
cinfo->scale_denom = 1;
|
||||||
|
cinfo->output_gamma = 1.0;
|
||||||
|
cinfo->dct_method = JDCT_DEFAULT;
|
||||||
|
cinfo->do_fancy_upsampling = TRUE;
|
||||||
|
cinfo->do_block_smoothing = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompression startup: read start of JPEG datastream to see what's there.
|
||||||
|
* Need only initialize JPEG object and supply a data source before calling.
|
||||||
|
*
|
||||||
|
* This routine will read as far as the first SOS marker (ie, actual start of
|
||||||
|
* compressed data), and will save all tables and parameters in the JPEG
|
||||||
|
* object. It will also initialize the decompression parameters to default
|
||||||
|
* values, and finally return JPEG_HEADER_OK. On return, the application may
|
||||||
|
* adjust the decompression parameters and then call jpeg_start_decompress.
|
||||||
|
* (Or, if the application only wanted to determine the image parameters,
|
||||||
|
* the data need not be decompressed. In that case, call jpeg_abort or
|
||||||
|
* jpeg_destroy to release any temporary space.)
|
||||||
|
* If an abbreviated (tables only) datastream is presented, the routine will
|
||||||
|
* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
|
||||||
|
* re-use the JPEG object to read the abbreviated image datastream(s).
|
||||||
|
* It is unnecessary (but OK) to call jpeg_abort in this case.
|
||||||
|
* The JPEG_SUSPENDED return code only occurs if the data source module
|
||||||
|
* requests suspension of the decompressor. In this case the application
|
||||||
|
* should load more source data and then re-call jpeg_read_header to resume
|
||||||
|
* processing.
|
||||||
|
* If a non-suspending data source is used and require_image is TRUE, then the
|
||||||
|
* return code need not be inspected since only JPEG_HEADER_OK is possible.
|
||||||
|
*
|
||||||
|
* 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_BUFPOST:
|
||||||
|
case DSTATE_STOPPING:
|
||||||
|
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
}
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
/* 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_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;
|
||||||
|
}
|
144
jpeg-6b/jdapistd.c
Normal file
144
jpeg-6b/jdapistd.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
/* Ready for application to drive output pass through
|
||||||
|
* jpeg_read_scanlines or jpeg_read_raw_data.
|
||||||
|
*/
|
||||||
|
cinfo->global_state = 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;
|
||||||
|
}
|
212
jpeg-6b/jdatasrc.c
Normal file
212
jpeg-6b/jdatasrc.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* jdatasrc.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains decompression data source routines for the case of
|
||||||
|
* reading JPEG data from a file (or any stdio stream). While these routines
|
||||||
|
* are sufficient for most applications, some will want to use a different
|
||||||
|
* source manager.
|
||||||
|
* IMPORTANT: we assume that fread() will correctly transcribe an array of
|
||||||
|
* JOCTETs from 8-bit-wide elements on external storage. If char is wider
|
||||||
|
* than 8 bits on your machine, you may need to do some tweaking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jerror.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Expanded data source object for stdio input */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_source_mgr pub; /* public fields */
|
||||||
|
|
||||||
|
FILE * infile; /* source stream */
|
||||||
|
JOCTET * buffer; /* start of buffer */
|
||||||
|
boolean start_of_file; /* have we gotten any data yet? */
|
||||||
|
} my_source_mgr;
|
||||||
|
|
||||||
|
typedef my_source_mgr * my_src_ptr;
|
||||||
|
|
||||||
|
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize source --- called by jpeg_read_header
|
||||||
|
* before any data is actually read.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
init_source (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
|
||||||
|
/* We reset the empty-input-file flag for each image,
|
||||||
|
* but we don't clear the input buffer.
|
||||||
|
* This is correct behavior for reading a series of images from one source.
|
||||||
|
*/
|
||||||
|
src->start_of_file = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill the input buffer --- called whenever buffer is emptied.
|
||||||
|
*
|
||||||
|
* In typical applications, this should read fresh data into the buffer
|
||||||
|
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
||||||
|
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||||
|
* indicating that the buffer has been reloaded. It is not necessary to
|
||||||
|
* fill the buffer entirely, only to obtain at least one more byte.
|
||||||
|
*
|
||||||
|
* There is no such thing as an EOF return. If the end of the file has been
|
||||||
|
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
||||||
|
* the buffer. In most cases, generating a warning message and inserting a
|
||||||
|
* fake EOI marker is the best course of action --- this will allow the
|
||||||
|
* decompressor to output however much of the image is there. However,
|
||||||
|
* the resulting error message is misleading if the real problem is an empty
|
||||||
|
* input file, so we handle that case specially.
|
||||||
|
*
|
||||||
|
* In applications that need to be able to suspend compression due to input
|
||||||
|
* not being available yet, a FALSE return indicates that no more data can be
|
||||||
|
* obtained right now, but more may be forthcoming later. In this situation,
|
||||||
|
* the decompressor will return to its caller (with an indication of the
|
||||||
|
* number of scanlines it has read, if any). The application should resume
|
||||||
|
* decompression after it has loaded more data into the input buffer. Note
|
||||||
|
* that there are substantial restrictions on the use of suspension --- see
|
||||||
|
* the documentation.
|
||||||
|
*
|
||||||
|
* When suspending, the decompressor will back up to a convenient restart point
|
||||||
|
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
|
||||||
|
* indicate where the restart point will be if the current call returns FALSE.
|
||||||
|
* Data beyond this point must be rescanned after resumption, so move it to
|
||||||
|
* the front of the buffer rather than discarding it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
fill_input_buffer (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
size_t nbytes;
|
||||||
|
|
||||||
|
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
|
||||||
|
|
||||||
|
if (nbytes <= 0) {
|
||||||
|
if (src->start_of_file) /* Treat empty input file as fatal error */
|
||||||
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||||
|
WARNMS(cinfo, JWRN_JPEG_EOF);
|
||||||
|
/* Insert a fake EOI marker */
|
||||||
|
src->buffer[0] = (JOCTET) 0xFF;
|
||||||
|
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||||
|
nbytes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->pub.next_input_byte = src->buffer;
|
||||||
|
src->pub.bytes_in_buffer = nbytes;
|
||||||
|
src->start_of_file = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip data --- used to skip over a potentially large amount of
|
||||||
|
* uninteresting data (such as an APPn marker).
|
||||||
|
*
|
||||||
|
* Writers of suspendable-input applications must note that skip_input_data
|
||||||
|
* is not granted the right to give a suspension return. If the skip extends
|
||||||
|
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||||
|
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||||
|
* Arranging for additional bytes to be discarded before reloading the input
|
||||||
|
* buffer is the application writer's problem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||||
|
{
|
||||||
|
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||||
|
|
||||||
|
/* Just a dumb implementation for now. Could use fseek() except
|
||||||
|
* it doesn't work on pipes. Not clear that being smart is worth
|
||||||
|
* any trouble anyway --- large skips are infrequent.
|
||||||
|
*/
|
||||||
|
if (num_bytes > 0) {
|
||||||
|
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||||
|
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||||
|
(void) fill_input_buffer(cinfo);
|
||||||
|
/* note we assume that fill_input_buffer will never return FALSE,
|
||||||
|
* so suspension need not be handled.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
src->pub.next_input_byte += (size_t) num_bytes;
|
||||||
|
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An additional method that can be provided by data source modules is the
|
||||||
|
* resync_to_restart method for error recovery in the presence of RST markers.
|
||||||
|
* For the moment, this source module just uses the default resync method
|
||||||
|
* provided by the JPEG library. That method assumes that no backtracking
|
||||||
|
* is possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminate source --- called by jpeg_finish_decompress
|
||||||
|
* after all data has been read. Often a no-op.
|
||||||
|
*
|
||||||
|
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||||
|
* application must deal with any cleanup that should happen even
|
||||||
|
* for error exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
term_source (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* no work necessary here */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for input from a stdio stream.
|
||||||
|
* The caller must have already opened the stream, and is responsible
|
||||||
|
* for closing it after finishing decompression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
|
||||||
|
{
|
||||||
|
my_src_ptr src;
|
||||||
|
|
||||||
|
/* The source object and input buffer are made permanent so that a series
|
||||||
|
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||||
|
* only before the first one. (If we discarded the buffer at the end of
|
||||||
|
* one image, we'd likely lose the start of the next one.)
|
||||||
|
* This makes it unsafe to use this manager and a different source
|
||||||
|
* manager serially with the same JPEG object. Caveat programmer.
|
||||||
|
*/
|
||||||
|
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||||
|
cinfo->src = (struct jpeg_source_mgr *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
SIZEOF(my_source_mgr));
|
||||||
|
src = (my_src_ptr) cinfo->src;
|
||||||
|
src->buffer = (JOCTET *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
INPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||||
|
}
|
||||||
|
|
||||||
|
src = (my_src_ptr) cinfo->src;
|
||||||
|
src->pub.init_source = init_source;
|
||||||
|
src->pub.fill_input_buffer = fill_input_buffer;
|
||||||
|
src->pub.skip_input_data = skip_input_data;
|
||||||
|
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||||
|
src->pub.term_source = term_source;
|
||||||
|
src->infile = infile;
|
||||||
|
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||||
|
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||||
|
}
|
409
jpeg-6b/jdcoefct.c
Normal file
409
jpeg-6b/jdcoefct.c
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
} 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
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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. */
|
||||||
|
MEMZERO((void *) 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_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_scaled_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blkn += compptr->MCU_width;
|
||||||
|
output_ptr += compptr->DCT_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_scaled_size;
|
||||||
|
}
|
||||||
|
output_ptr += compptr->DCT_scaled_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||||
|
return JPEG_ROW_COMPLETED;
|
||||||
|
return JPEG_SCAN_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
}
|
393
jpeg-6b/jdcolor.c
Normal file
393
jpeg-6b/jdcolor.c
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************** 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
cinfo->output_components = cinfo->out_color_components;
|
||||||
|
}
|
164
jpeg-6b/jdct.h
Normal file
164
jpeg-6b/jdct.h
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* 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 a work area of type DCTELEM[];
|
||||||
|
* the DCT is to be performed in-place in that buffer. Type DCTELEM is int
|
||||||
|
* for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
|
||||||
|
* implementations use an array of type FAST_FLOAT, instead.)
|
||||||
|
* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
|
||||||
|
* The DCT outputs are returned scaled up by a factor of 8; they therefore
|
||||||
|
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
|
||||||
|
* convention improves accuracy in integer implementations and saves some
|
||||||
|
* work in floating-point ones.
|
||||||
|
* Quantization of the output coefficients is done by jcdctmgr.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
typedef int DCTELEM; /* 16 or 32 bits is fine */
|
||||||
|
#else
|
||||||
|
typedef INT32 DCTELEM; /* must have 32 bits */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
|
||||||
|
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
|
||||||
|
* to an output sample array. The routine must dequantize the input data as
|
||||||
|
* well as perform the IDCT; for dequantization, it uses the multiplier table
|
||||||
|
* pointed to by compptr->dct_table. The output data is to be placed into the
|
||||||
|
* sample array starting at a specified column. (Any row offset needed will
|
||||||
|
* be applied to the array pointer before it is passed to the IDCT code.)
|
||||||
|
* Note that the number of samples emitted by the IDCT routine is
|
||||||
|
* DCT_scaled_size * DCT_scaled_size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine has its own ideas about the best dct_table element type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
|
||||||
|
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
|
||||||
|
#else
|
||||||
|
typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
|
||||||
|
#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
|
||||||
|
#endif
|
||||||
|
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each IDCT routine is responsible for range-limiting its results and
|
||||||
|
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
|
||||||
|
* be quite far out of range if the input data is corrupt, so a bulletproof
|
||||||
|
* range-limiting step is required. We use a mask-and-table-lookup method
|
||||||
|
* to do the combined operations quickly. See the comments with
|
||||||
|
* prepare_range_limit_table (in jdmaster.c) for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
|
||||||
|
|
||||||
|
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
|
||||||
|
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
/* Extern declarations for the forward and inverse DCT routines. */
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
|
||||||
|
EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
|
||||||
|
|
||||||
|
EXTERN(void) jpeg_idct_islow
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_ifast
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_float
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_4x4
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_2x2
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
EXTERN(void) jpeg_idct_1x1
|
||||||
|
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for handling fixed-point arithmetic; these are used by many
|
||||||
|
* but not all of the DCT/IDCT modules.
|
||||||
|
*
|
||||||
|
* All values are expected to be of type INT32.
|
||||||
|
* Fractional constants are scaled left by CONST_BITS bits.
|
||||||
|
* CONST_BITS is defined within each module using these macros,
|
||||||
|
* and may differ from one module to the next.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ONE ((INT32) 1)
|
||||||
|
#define CONST_SCALE (ONE << CONST_BITS)
|
||||||
|
|
||||||
|
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
|
||||||
|
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
|
||||||
|
* thus causing a lot of useless floating-point operations at run time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
|
||||||
|
|
||||||
|
/* Descale and correctly round an INT32 value that's scaled by N bits.
|
||||||
|
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
|
||||||
|
* the fudge factor is correct for either sign of X.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
|
||||||
|
|
||||||
|
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
|
||||||
|
* This macro is used only when the two inputs will actually be no more than
|
||||||
|
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
|
||||||
|
* full 32x32 multiply. This provides a useful speedup on many machines.
|
||||||
|
* Unfortunately there is no way to specify a 16x16->32 multiply portably
|
||||||
|
* in C, but some C compilers will do the right thing if you provide the
|
||||||
|
* correct combination of casts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
|
||||||
|
#endif
|
||||||
|
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
|
||||||
|
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MULTIPLY16C16 /* default definition */
|
||||||
|
#define MULTIPLY16C16(var,const) ((var) * (const))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Same except both inputs are variables. */
|
||||||
|
|
||||||
|
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||||
|
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MULTIPLY16V16 /* default definition */
|
||||||
|
#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
|
||||||
|
#endif
|
172
jpeg-6b/jddctmgr.c
Normal file
172
jpeg-6b/jddctmgr.c
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* jddctmgr.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* 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];
|
||||||
|
} 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
|
||||||
|
#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_scaled_size) {
|
||||||
|
case DCTSIZE:
|
||||||
|
switch (cinfo->dct_method) {
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
method_ptr = jpeg_idct_islow;
|
||||||
|
method = JDCT_ISLOW;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
idct->pub.inverse_DCT[ci] = method_ptr;
|
||||||
|
/* Create multiplier table from quant table.
|
||||||
|
* However, we can skip this if the component is uninteresting
|
||||||
|
* or if we already built the table. Also, if no quant table
|
||||||
|
* has yet been saved for the component, we leave the
|
||||||
|
* multiplier table all-zero; we'll be reading zeroes from the
|
||||||
|
* coefficient controller's buffer anyway.
|
||||||
|
*/
|
||||||
|
if (! compptr->component_needed || idct->cur_method[ci] == method)
|
||||||
|
continue;
|
||||||
|
qtbl = compptr->quant_table;
|
||||||
|
if (qtbl == NULL) /* happens if no data yet for component */
|
||||||
|
continue;
|
||||||
|
idct->cur_method[ci] = method;
|
||||||
|
switch (method) {
|
||||||
|
#ifdef PROVIDE_ISLOW_TABLES
|
||||||
|
case JDCT_ISLOW:
|
||||||
|
{
|
||||||
|
/* For LL&M IDCT method, multipliers are equal to raw quantization
|
||||||
|
* coefficients, but are stored as ints to ensure access efficiency.
|
||||||
|
*/
|
||||||
|
ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
|
||||||
|
for (i = 0; i < DCTSIZE2; i++) {
|
||||||
|
ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
651
jpeg-6b/jdhuff.c
Normal file
651
jpeg-6b/jdhuff.c
Normal file
|
@ -0,0 +1,651 @@
|
||||||
|
/*
|
||||||
|
* jdhuff.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 Huffman entropy decoding routines.
|
||||||
|
*
|
||||||
|
* Much of the complexity here has to do with supporting input suspension.
|
||||||
|
* If the data source module demands suspension, we want to be able to back
|
||||||
|
* up to the start of the current MCU. To do this, we copy state variables
|
||||||
|
* into local working storage, and update them back to the permanent
|
||||||
|
* storage only upon successful completion of an MCU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jdhuff.h" /* Declarations shared with jdphuff.c */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expanded entropy decoder object for Huffman decoding.
|
||||||
|
*
|
||||||
|
* The savable_state subrecord contains fields that change within an MCU,
|
||||||
|
* but must not be updated permanently until we complete the MCU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||||
|
} savable_state;
|
||||||
|
|
||||||
|
/* This macro is to work around compilers with missing or broken
|
||||||
|
* structure assignment. You'll need to fix this code if you have
|
||||||
|
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_ASSIGN
|
||||||
|
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||||
|
#else
|
||||||
|
#if MAX_COMPS_IN_SCAN == 4
|
||||||
|
#define ASSIGN_STATE(dest,src) \
|
||||||
|
((dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||||
|
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||||
|
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||||
|
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_entropy_decoder pub; /* public fields */
|
||||||
|
|
||||||
|
/* These fields are loaded into local variables at start of each MCU.
|
||||||
|
* In case of suspension, we exit WITHOUT updating them.
|
||||||
|
*/
|
||||||
|
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||||
|
savable_state saved; /* Other state at start of MCU */
|
||||||
|
|
||||||
|
/* These fields are NOT loaded into local working state. */
|
||||||
|
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||||
|
|
||||||
|
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||||
|
d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||||
|
d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||||
|
|
||||||
|
/* Precalculated info set up by start_pass for use in decode_mcu: */
|
||||||
|
|
||||||
|
/* Pointers to derived tables to be used for each block within an MCU */
|
||||||
|
d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
/* Whether we care about the DC and AC coefficient values for each block */
|
||||||
|
boolean dc_needed[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
boolean ac_needed[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
} huff_entropy_decoder;
|
||||||
|
|
||||||
|
typedef huff_entropy_decoder * huff_entropy_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a Huffman-compressed scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_huff_decoder (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||||
|
int ci, blkn, dctbl, actbl;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
/* 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 because
|
||||||
|
* there are some baseline files out there with all zeroes in these bytes.
|
||||||
|
*/
|
||||||
|
if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
|
||||||
|
cinfo->Ah != 0 || cinfo->Al != 0)
|
||||||
|
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
dctbl = compptr->dc_tbl_no;
|
||||||
|
actbl = compptr->ac_tbl_no;
|
||||||
|
/* Compute derived values for Huffman tables */
|
||||||
|
/* We may do this more than once for a table, but it's not expensive */
|
||||||
|
jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
|
||||||
|
& entropy->dc_derived_tbls[dctbl]);
|
||||||
|
jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
|
||||||
|
& entropy->ac_derived_tbls[actbl]);
|
||||||
|
/* Initialize DC predictions to 0 */
|
||||||
|
entropy->saved.last_dc_val[ci] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Precalculate decoding info for each block in an MCU of this scan */
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
ci = cinfo->MCU_membership[blkn];
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Precalculate which table to use for each block */
|
||||||
|
entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
|
||||||
|
entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
|
||||||
|
/* Decide whether we really care about the coefficient values */
|
||||||
|
if (compptr->component_needed) {
|
||||||
|
entropy->dc_needed[blkn] = TRUE;
|
||||||
|
/* we don't need the ACs if producing a 1/8th-size image */
|
||||||
|
entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1);
|
||||||
|
} else {
|
||||||
|
entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize bitread state variables */
|
||||||
|
entropy->bitstate.bits_left = 0;
|
||||||
|
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||||
|
entropy->pub.insufficient_data = FALSE;
|
||||||
|
|
||||||
|
/* Initialize restart counter */
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the derived values for a Huffman table.
|
||||||
|
* This routine also performs some validation checks on the table.
|
||||||
|
*
|
||||||
|
* Note this is also used by jdphuff.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||||
|
d_derived_tbl ** pdtbl)
|
||||||
|
{
|
||||||
|
JHUFF_TBL *htbl;
|
||||||
|
d_derived_tbl *dtbl;
|
||||||
|
int p, i, l, si, numsymbols;
|
||||||
|
int lookbits, ctr;
|
||||||
|
char huffsize[257];
|
||||||
|
unsigned int huffcode[257];
|
||||||
|
unsigned int code;
|
||||||
|
|
||||||
|
/* Note that huffsize[] and huffcode[] are filled in code-length order,
|
||||||
|
* paralleling the order of the symbols themselves in htbl->huffval[].
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Find the input Huffman table */
|
||||||
|
if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
|
||||||
|
htbl =
|
||||||
|
isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
|
||||||
|
if (htbl == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
|
||||||
|
|
||||||
|
/* Allocate a workspace if we haven't already done so. */
|
||||||
|
if (*pdtbl == NULL)
|
||||||
|
*pdtbl = (d_derived_tbl *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(d_derived_tbl));
|
||||||
|
dtbl = *pdtbl;
|
||||||
|
dtbl->pub = htbl; /* fill in back link */
|
||||||
|
|
||||||
|
/* Figure C.1: make table of Huffman code length for each symbol */
|
||||||
|
|
||||||
|
p = 0;
|
||||||
|
for (l = 1; l <= 16; l++) {
|
||||||
|
i = (int) htbl->bits[l];
|
||||||
|
if (i < 0 || p + i > 256) /* protect against table overrun */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||||
|
while (i--)
|
||||||
|
huffsize[p++] = (char) l;
|
||||||
|
}
|
||||||
|
huffsize[p] = 0;
|
||||||
|
numsymbols = p;
|
||||||
|
|
||||||
|
/* Figure C.2: generate the codes themselves */
|
||||||
|
/* We also validate that the counts represent a legal Huffman code tree. */
|
||||||
|
|
||||||
|
code = 0;
|
||||||
|
si = huffsize[0];
|
||||||
|
p = 0;
|
||||||
|
while (huffsize[p]) {
|
||||||
|
while (((int) huffsize[p]) == si) {
|
||||||
|
huffcode[p++] = code;
|
||||||
|
code++;
|
||||||
|
}
|
||||||
|
/* code is now 1 more than the last code used for codelength si; but
|
||||||
|
* it must still fit in si bits, since no code is allowed to be all ones.
|
||||||
|
*/
|
||||||
|
if (((INT32) code) >= (((INT32) 1) << si))
|
||||||
|
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||||
|
code <<= 1;
|
||||||
|
si++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure F.15: generate decoding tables for bit-sequential decoding */
|
||||||
|
|
||||||
|
p = 0;
|
||||||
|
for (l = 1; l <= 16; l++) {
|
||||||
|
if (htbl->bits[l]) {
|
||||||
|
/* valoffset[l] = huffval[] index of 1st symbol of code length l,
|
||||||
|
* minus the minimum code of length l
|
||||||
|
*/
|
||||||
|
dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
|
||||||
|
p += htbl->bits[l];
|
||||||
|
dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
|
||||||
|
} else {
|
||||||
|
dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
|
||||||
|
|
||||||
|
/* Compute lookahead tables to speed up decoding.
|
||||||
|
* First we set all the table entries to 0, indicating "too long";
|
||||||
|
* then we iterate through the Huffman codes that are short enough and
|
||||||
|
* fill in all the entries that correspond to bit sequences starting
|
||||||
|
* with that code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
|
||||||
|
|
||||||
|
p = 0;
|
||||||
|
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
|
||||||
|
for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
|
||||||
|
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
|
||||||
|
/* Generate left-justified code followed by all possible bit sequences */
|
||||||
|
lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
|
||||||
|
for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
|
||||||
|
dtbl->look_nbits[lookbits] = l;
|
||||||
|
dtbl->look_sym[lookbits] = htbl->huffval[p];
|
||||||
|
lookbits++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate symbols as being reasonable.
|
||||||
|
* For AC tables, we make no check, but accept all byte values 0..255.
|
||||||
|
* For DC tables, we require the symbols to be in range 0..15.
|
||||||
|
* (Tighter bounds could be applied depending on the data depth and mode,
|
||||||
|
* but this is sufficient to ensure safe decoding.)
|
||||||
|
*/
|
||||||
|
if (isDC) {
|
||||||
|
for (i = 0; i < numsymbols; i++) {
|
||||||
|
int sym = htbl->huffval[i];
|
||||||
|
if (sym < 0 || sym > 15)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Out-of-line code for bit fetching (shared with jdphuff.c).
|
||||||
|
* See jdhuff.h for info about usage.
|
||||||
|
* Note: current values of get_buffer and bits_left are passed as parameters,
|
||||||
|
* but are returned in the corresponding fields of the state struct.
|
||||||
|
*
|
||||||
|
* On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
|
||||||
|
* of get_buffer to be used. (On machines with wider words, an even larger
|
||||||
|
* buffer could be used.) However, on some machines 32-bit shifts are
|
||||||
|
* quite slow and take time proportional to the number of places shifted.
|
||||||
|
* (This is true with most PC compilers, for instance.) In this case it may
|
||||||
|
* be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
|
||||||
|
* average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SLOW_SHIFT_32
|
||||||
|
#define MIN_GET_BITS 15 /* minimum allowable value */
|
||||||
|
#else
|
||||||
|
#define MIN_GET_BITS (BIT_BUF_SIZE-7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
GLOBAL(boolean)
|
||||||
|
jpeg_fill_bit_buffer (bitread_working_state * state,
|
||||||
|
register bit_buf_type get_buffer, register int bits_left,
|
||||||
|
int nbits)
|
||||||
|
/* Load up the bit buffer to a depth of at least nbits */
|
||||||
|
{
|
||||||
|
/* Copy heavily used state fields into locals (hopefully registers) */
|
||||||
|
register const JOCTET * next_input_byte = state->next_input_byte;
|
||||||
|
register size_t bytes_in_buffer = state->bytes_in_buffer;
|
||||||
|
j_decompress_ptr cinfo = state->cinfo;
|
||||||
|
|
||||||
|
/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
|
||||||
|
/* (It is assumed that no request will be for more than that many bits.) */
|
||||||
|
/* We fail to do so only if we hit a marker or are forced to suspend. */
|
||||||
|
|
||||||
|
if (cinfo->unread_marker == 0) { /* cannot advance past a marker */
|
||||||
|
while (bits_left < MIN_GET_BITS) {
|
||||||
|
register int c;
|
||||||
|
|
||||||
|
/* Attempt to read a byte */
|
||||||
|
if (bytes_in_buffer == 0) {
|
||||||
|
if (! (*cinfo->src->fill_input_buffer) (cinfo))
|
||||||
|
return FALSE;
|
||||||
|
next_input_byte = cinfo->src->next_input_byte;
|
||||||
|
bytes_in_buffer = cinfo->src->bytes_in_buffer;
|
||||||
|
}
|
||||||
|
bytes_in_buffer--;
|
||||||
|
c = GETJOCTET(*next_input_byte++);
|
||||||
|
|
||||||
|
/* If it's 0xFF, check and discard stuffed zero byte */
|
||||||
|
if (c == 0xFF) {
|
||||||
|
/* Loop here to discard any padding FF's on terminating marker,
|
||||||
|
* so that we can save a valid unread_marker value. NOTE: we will
|
||||||
|
* accept multiple FF's followed by a 0 as meaning a single FF data
|
||||||
|
* byte. This data pattern is not valid according to the standard.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
if (bytes_in_buffer == 0) {
|
||||||
|
if (! (*cinfo->src->fill_input_buffer) (cinfo))
|
||||||
|
return FALSE;
|
||||||
|
next_input_byte = cinfo->src->next_input_byte;
|
||||||
|
bytes_in_buffer = cinfo->src->bytes_in_buffer;
|
||||||
|
}
|
||||||
|
bytes_in_buffer--;
|
||||||
|
c = GETJOCTET(*next_input_byte++);
|
||||||
|
} while (c == 0xFF);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
/* Found FF/00, which represents an FF data byte */
|
||||||
|
c = 0xFF;
|
||||||
|
} else {
|
||||||
|
/* Oops, it's actually a marker indicating end of compressed data.
|
||||||
|
* Save the marker code for later use.
|
||||||
|
* Fine point: it might appear that we should save the marker into
|
||||||
|
* bitread working state, not straight into permanent state. But
|
||||||
|
* once we have hit a marker, we cannot need to suspend within the
|
||||||
|
* current MCU, because we will read no more bytes from the data
|
||||||
|
* source. So it is OK to update permanent state right away.
|
||||||
|
*/
|
||||||
|
cinfo->unread_marker = c;
|
||||||
|
/* See if we need to insert some fake zero bits. */
|
||||||
|
goto no_more_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, load c into get_buffer */
|
||||||
|
get_buffer = (get_buffer << 8) | c;
|
||||||
|
bits_left += 8;
|
||||||
|
} /* end while */
|
||||||
|
} else {
|
||||||
|
no_more_bytes:
|
||||||
|
/* We get here if we've read the marker that terminates the compressed
|
||||||
|
* data segment. There should be enough bits in the buffer register
|
||||||
|
* to satisfy the request; if so, no problem.
|
||||||
|
*/
|
||||||
|
if (nbits > bits_left) {
|
||||||
|
/* Uh-oh. Report corrupted data to user and stuff zeroes into
|
||||||
|
* the data stream, so that we can produce some kind of image.
|
||||||
|
* We use a nonvolatile flag to ensure that only one warning message
|
||||||
|
* appears per data segment.
|
||||||
|
*/
|
||||||
|
if (! cinfo->entropy->insufficient_data) {
|
||||||
|
WARNMS(cinfo, JWRN_HIT_MARKER);
|
||||||
|
cinfo->entropy->insufficient_data = TRUE;
|
||||||
|
}
|
||||||
|
/* Fill the buffer with zero bits */
|
||||||
|
get_buffer <<= MIN_GET_BITS - bits_left;
|
||||||
|
bits_left = MIN_GET_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unload the local registers */
|
||||||
|
state->next_input_byte = next_input_byte;
|
||||||
|
state->bytes_in_buffer = bytes_in_buffer;
|
||||||
|
state->get_buffer = get_buffer;
|
||||||
|
state->bits_left = bits_left;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Out-of-line code for Huffman code decoding.
|
||||||
|
* See jdhuff.h for info about usage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(int)
|
||||||
|
jpeg_huff_decode (bitread_working_state * state,
|
||||||
|
register bit_buf_type get_buffer, register int bits_left,
|
||||||
|
d_derived_tbl * htbl, int min_bits)
|
||||||
|
{
|
||||||
|
register int l = min_bits;
|
||||||
|
register INT32 code;
|
||||||
|
|
||||||
|
/* HUFF_DECODE has determined that the code is at least min_bits */
|
||||||
|
/* bits long, so fetch that many bits in one swoop. */
|
||||||
|
|
||||||
|
CHECK_BIT_BUFFER(*state, l, return -1);
|
||||||
|
code = GET_BITS(l);
|
||||||
|
|
||||||
|
/* Collect the rest of the Huffman code one bit at a time. */
|
||||||
|
/* This is per Figure F.16 in the JPEG spec. */
|
||||||
|
|
||||||
|
while (code > htbl->maxcode[l]) {
|
||||||
|
code <<= 1;
|
||||||
|
CHECK_BIT_BUFFER(*state, 1, return -1);
|
||||||
|
code |= GET_BITS(1);
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unload the local registers */
|
||||||
|
state->get_buffer = get_buffer;
|
||||||
|
state->bits_left = bits_left;
|
||||||
|
|
||||||
|
/* With garbage input we may reach the sentinel value l = 17. */
|
||||||
|
|
||||||
|
if (l > 16) {
|
||||||
|
WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
|
||||||
|
return 0; /* fake a zero as the safest result */
|
||||||
|
}
|
||||||
|
|
||||||
|
return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure F.12: extend sign bit.
|
||||||
|
* On some machines, a shift and add will be faster than a table lookup.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef AVOID_TABLES
|
||||||
|
|
||||||
|
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
|
||||||
|
|
||||||
|
static const int extend_test[16] = /* entry n is 2**(n-1) */
|
||||||
|
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||||
|
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
||||||
|
|
||||||
|
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||||
|
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
|
||||||
|
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
|
||||||
|
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
|
||||||
|
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
|
||||||
|
|
||||||
|
#endif /* AVOID_TABLES */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for a restart marker & resynchronize decoder.
|
||||||
|
* Returns FALSE if must suspend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
process_restart (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
/* Throw away any unused bits remaining in bit buffer; */
|
||||||
|
/* include any full bytes in next_marker's count of discarded bytes */
|
||||||
|
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
|
||||||
|
entropy->bitstate.bits_left = 0;
|
||||||
|
|
||||||
|
/* Advance past the RSTn marker */
|
||||||
|
if (! (*cinfo->marker->read_restart_marker) (cinfo))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Re-initialize DC predictions to 0 */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||||
|
entropy->saved.last_dc_val[ci] = 0;
|
||||||
|
|
||||||
|
/* Reset restart counter */
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
|
||||||
|
/* Reset out-of-data flag, unless read_restart_marker left us smack up
|
||||||
|
* against a marker. In that case we will end up treating the next data
|
||||||
|
* segment as empty, and we can avoid producing bogus output pixels by
|
||||||
|
* leaving the flag set.
|
||||||
|
*/
|
||||||
|
if (cinfo->unread_marker == 0)
|
||||||
|
entropy->pub.insufficient_data = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode and return one MCU's worth of Huffman-compressed coefficients.
|
||||||
|
* The coefficients are reordered from zigzag order into natural array order,
|
||||||
|
* but are not dequantized.
|
||||||
|
*
|
||||||
|
* The i'th block of the MCU is stored into the block pointed to by
|
||||||
|
* MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
|
||||||
|
* (Wholesale zeroing is usually a little faster than retail...)
|
||||||
|
*
|
||||||
|
* Returns FALSE if data source requested suspension. In that case no
|
||||||
|
* changes have been made to permanent state. (Exception: some output
|
||||||
|
* coefficients may already have been assigned. This is harmless for
|
||||||
|
* this module, since we'll just re-assign them on the next call.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||||
|
int blkn;
|
||||||
|
BITREAD_STATE_VARS;
|
||||||
|
savable_state state;
|
||||||
|
|
||||||
|
/* Process restart marker if needed; may have to suspend */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
if (! process_restart(cinfo))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||||
|
* This way, we return uniform gray for the remainder of the segment.
|
||||||
|
*/
|
||||||
|
if (! entropy->pub.insufficient_data) {
|
||||||
|
|
||||||
|
/* Load up working state */
|
||||||
|
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||||
|
ASSIGN_STATE(state, entropy->saved);
|
||||||
|
|
||||||
|
/* Outer loop handles each block in the MCU */
|
||||||
|
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
JBLOCKROW block = MCU_data[blkn];
|
||||||
|
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
||||||
|
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
||||||
|
register int s, k, r;
|
||||||
|
|
||||||
|
/* Decode a single block's worth of coefficients */
|
||||||
|
|
||||||
|
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||||
|
HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
|
||||||
|
if (s) {
|
||||||
|
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||||
|
r = GET_BITS(s);
|
||||||
|
s = HUFF_EXTEND(r, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entropy->dc_needed[blkn]) {
|
||||||
|
/* Convert DC difference to actual value, update last_dc_val */
|
||||||
|
int ci = cinfo->MCU_membership[blkn];
|
||||||
|
s += state.last_dc_val[ci];
|
||||||
|
state.last_dc_val[ci] = s;
|
||||||
|
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||||
|
(*block)[0] = (JCOEF) s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entropy->ac_needed[blkn]) {
|
||||||
|
|
||||||
|
/* Section F.2.2.2: decode the AC coefficients */
|
||||||
|
/* Since zeroes are skipped, output area must be cleared beforehand */
|
||||||
|
for (k = 1; k < DCTSIZE2; k++) {
|
||||||
|
HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
|
||||||
|
|
||||||
|
r = s >> 4;
|
||||||
|
s &= 15;
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
k += r;
|
||||||
|
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||||
|
r = GET_BITS(s);
|
||||||
|
s = HUFF_EXTEND(r, s);
|
||||||
|
/* Output coefficient in natural (dezigzagged) order.
|
||||||
|
* Note: the extra entries in jpeg_natural_order[] will save us
|
||||||
|
* if k >= DCTSIZE2, which could happen if the data is corrupted.
|
||||||
|
*/
|
||||||
|
(*block)[jpeg_natural_order[k]] = (JCOEF) s;
|
||||||
|
} else {
|
||||||
|
if (r != 15)
|
||||||
|
break;
|
||||||
|
k += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Section F.2.2.2: decode the AC coefficients */
|
||||||
|
/* In this path we just discard the values */
|
||||||
|
for (k = 1; k < DCTSIZE2; k++) {
|
||||||
|
HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
|
||||||
|
|
||||||
|
r = s >> 4;
|
||||||
|
s &= 15;
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
k += r;
|
||||||
|
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||||
|
DROP_BITS(s);
|
||||||
|
} else {
|
||||||
|
if (r != 15)
|
||||||
|
break;
|
||||||
|
k += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed MCU, so update state */
|
||||||
|
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||||
|
ASSIGN_STATE(entropy->saved, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Account for restart interval (no-op if not using restarts) */
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for Huffman entropy decoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_huff_decoder (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
huff_entropy_ptr entropy;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
entropy = (huff_entropy_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(huff_entropy_decoder));
|
||||||
|
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||||
|
entropy->pub.start_pass = start_pass_huff_decoder;
|
||||||
|
entropy->pub.decode_mcu = decode_mcu;
|
||||||
|
|
||||||
|
/* Mark tables unallocated */
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
194
jpeg-6b/jdhuff.h
Normal file
194
jpeg-6b/jdhuff.h
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* jdhuff.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains declarations for Huffman entropy decoding routines
|
||||||
|
* that are shared between the sequential decoder (jdhuff.c) and the
|
||||||
|
* progressive decoder (jdphuff.c). No other modules need to see these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||||
|
|
||||||
|
/* Derived data constructed for each Huffman table */
|
||||||
|
|
||||||
|
#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Basic tables: (element [0] of each array is unused) */
|
||||||
|
INT32 maxcode[18]; /* largest code of length k (-1 if none) */
|
||||||
|
/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
|
||||||
|
INT32 valoffset[17]; /* huffval[] offset for codes of length k */
|
||||||
|
/* valoffset[k] = huffval[] index of 1st symbol of code length k, less
|
||||||
|
* the smallest code of length k; so given a code of length k, the
|
||||||
|
* corresponding symbol is huffval[code + valoffset[k]]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Link to public Huffman table (needed only in jpeg_huff_decode) */
|
||||||
|
JHUFF_TBL *pub;
|
||||||
|
|
||||||
|
/* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
|
||||||
|
* the input data stream. If the next Huffman code is no more
|
||||||
|
* than HUFF_LOOKAHEAD bits long, we can obtain its length and
|
||||||
|
* the corresponding symbol directly from these tables.
|
||||||
|
*/
|
||||||
|
int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
|
||||||
|
UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
|
||||||
|
} d_derived_tbl;
|
||||||
|
|
||||||
|
/* Expand a Huffman table definition into the derived format */
|
||||||
|
EXTERN(void) jpeg_make_d_derived_tbl
|
||||||
|
JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||||
|
d_derived_tbl ** pdtbl));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetching the next N bits from the input stream is a time-critical operation
|
||||||
|
* for the Huffman decoders. We implement it with a combination of inline
|
||||||
|
* macros and out-of-line subroutines. Note that N (the number of bits
|
||||||
|
* demanded at one time) never exceeds 15 for JPEG use.
|
||||||
|
*
|
||||||
|
* We read source bytes into get_buffer and dole out bits as needed.
|
||||||
|
* If get_buffer already contains enough bits, they are fetched in-line
|
||||||
|
* by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
|
||||||
|
* bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
|
||||||
|
* as full as possible (not just to the number of bits needed; this
|
||||||
|
* prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
|
||||||
|
* Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
|
||||||
|
* On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
|
||||||
|
* at least the requested number of bits --- dummy zeroes are inserted if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
|
||||||
|
#define BIT_BUF_SIZE 32 /* size of buffer in bits */
|
||||||
|
|
||||||
|
/* If long is > 32 bits on your machine, and shifting/masking longs is
|
||||||
|
* reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
|
||||||
|
* appropriately should be a win. Unfortunately we can't define the size
|
||||||
|
* with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
|
||||||
|
* because not all machines measure sizeof in 8-bit bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct { /* Bitreading state saved across MCUs */
|
||||||
|
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||||
|
int bits_left; /* # of unused bits in it */
|
||||||
|
} bitread_perm_state;
|
||||||
|
|
||||||
|
typedef struct { /* Bitreading working state within an MCU */
|
||||||
|
/* Current data source location */
|
||||||
|
/* We need a copy, rather than munging the original, in case of suspension */
|
||||||
|
const JOCTET * next_input_byte; /* => next byte to read from source */
|
||||||
|
size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
|
||||||
|
/* Bit input buffer --- note these values are kept in register variables,
|
||||||
|
* not in this struct, inside the inner loops.
|
||||||
|
*/
|
||||||
|
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||||
|
int bits_left; /* # of unused bits in it */
|
||||||
|
/* Pointer needed by jpeg_fill_bit_buffer. */
|
||||||
|
j_decompress_ptr cinfo; /* back link to decompress master record */
|
||||||
|
} bitread_working_state;
|
||||||
|
|
||||||
|
/* Macros to declare and load/save bitread local variables. */
|
||||||
|
#define BITREAD_STATE_VARS \
|
||||||
|
register bit_buf_type get_buffer; \
|
||||||
|
register int bits_left; \
|
||||||
|
bitread_working_state br_state
|
||||||
|
|
||||||
|
#define BITREAD_LOAD_STATE(cinfop,permstate) \
|
||||||
|
br_state.cinfo = cinfop; \
|
||||||
|
br_state.next_input_byte = cinfop->src->next_input_byte; \
|
||||||
|
br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
|
||||||
|
get_buffer = permstate.get_buffer; \
|
||||||
|
bits_left = permstate.bits_left;
|
||||||
|
|
||||||
|
#define BITREAD_SAVE_STATE(cinfop,permstate) \
|
||||||
|
cinfop->src->next_input_byte = br_state.next_input_byte; \
|
||||||
|
cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
|
||||||
|
permstate.get_buffer = get_buffer; \
|
||||||
|
permstate.bits_left = bits_left
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros provide the in-line portion of bit fetching.
|
||||||
|
* Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
|
||||||
|
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
|
||||||
|
* The variables get_buffer and bits_left are assumed to be locals,
|
||||||
|
* but the state struct might not be (jpeg_huff_decode needs this).
|
||||||
|
* CHECK_BIT_BUFFER(state,n,action);
|
||||||
|
* Ensure there are N bits in get_buffer; if suspend, take action.
|
||||||
|
* val = GET_BITS(n);
|
||||||
|
* Fetch next N bits.
|
||||||
|
* val = PEEK_BITS(n);
|
||||||
|
* Fetch next N bits without removing them from the buffer.
|
||||||
|
* DROP_BITS(n);
|
||||||
|
* Discard next N bits.
|
||||||
|
* The value N should be a simple variable, not an expression, because it
|
||||||
|
* is evaluated multiple times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CHECK_BIT_BUFFER(state,nbits,action) \
|
||||||
|
{ if (bits_left < (nbits)) { \
|
||||||
|
if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
|
||||||
|
{ action; } \
|
||||||
|
get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
|
||||||
|
|
||||||
|
#define GET_BITS(nbits) \
|
||||||
|
(((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
|
||||||
|
|
||||||
|
#define PEEK_BITS(nbits) \
|
||||||
|
(((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
|
||||||
|
|
||||||
|
#define DROP_BITS(nbits) \
|
||||||
|
(bits_left -= (nbits))
|
||||||
|
|
||||||
|
/* Load up the bit buffer to a depth of at least nbits */
|
||||||
|
EXTERN(boolean) jpeg_fill_bit_buffer
|
||||||
|
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
|
||||||
|
register int bits_left, int nbits));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code for extracting next Huffman-coded symbol from input bit stream.
|
||||||
|
* Again, this is time-critical and we make the main paths be macros.
|
||||||
|
*
|
||||||
|
* We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
|
||||||
|
* without looping. Usually, more than 95% of the Huffman codes will be 8
|
||||||
|
* or fewer bits long. The few overlength codes are handled with a loop,
|
||||||
|
* which need not be inline code.
|
||||||
|
*
|
||||||
|
* Notes about the HUFF_DECODE macro:
|
||||||
|
* 1. Near the end of the data segment, we may fail to get enough bits
|
||||||
|
* for a lookahead. In that case, we do it the hard way.
|
||||||
|
* 2. If the lookahead table contains no entry, the next code must be
|
||||||
|
* more than HUFF_LOOKAHEAD bits long.
|
||||||
|
* 3. jpeg_huff_decode returns -1 if forced to suspend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
|
||||||
|
{ register int nb, look; \
|
||||||
|
if (bits_left < HUFF_LOOKAHEAD) { \
|
||||||
|
if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
|
||||||
|
get_buffer = state.get_buffer; bits_left = state.bits_left; \
|
||||||
|
if (bits_left < HUFF_LOOKAHEAD) { \
|
||||||
|
nb = 1; goto slowlabel; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
look = PEEK_BITS(HUFF_LOOKAHEAD); \
|
||||||
|
if ((nb = htbl->look_nbits[look]) != 0) { \
|
||||||
|
DROP_BITS(nb); \
|
||||||
|
result = htbl->look_sym[look]; \
|
||||||
|
} else { \
|
||||||
|
nb = HUFF_LOOKAHEAD+1; \
|
||||||
|
slowlabel: \
|
||||||
|
if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
|
||||||
|
{ failaction; } \
|
||||||
|
get_buffer = state.get_buffer; bits_left = state.bits_left; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Out-of-line case for Huffman code fetching */
|
||||||
|
EXTERN(int) jpeg_huff_decode
|
||||||
|
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
|
||||||
|
register int bits_left, d_derived_tbl * htbl, int min_bits));
|
381
jpeg-6b/jdinput.c
Normal file
381
jpeg-6b/jdinput.c
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
/*
|
||||||
|
* jdinput.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains input control logic for the JPEG decompressor.
|
||||||
|
* These routines are concerned with controlling the decompressor's input
|
||||||
|
* processing (marker reading and coefficient decoding). The actual input
|
||||||
|
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Private state */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_input_controller pub; /* public fields */
|
||||||
|
|
||||||
|
boolean inheaders; /* TRUE until first SOS is reached */
|
||||||
|
} my_input_controller;
|
||||||
|
|
||||||
|
typedef my_input_controller * my_inputctl_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines to calculate various quantities related to the size of the image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
initial_setup (j_decompress_ptr cinfo)
|
||||||
|
/* Called once, when first SOS marker is reached */
|
||||||
|
{
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
/* Make sure image isn't bigger than I can handle */
|
||||||
|
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
|
||||||
|
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
|
||||||
|
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
|
||||||
|
|
||||||
|
/* For now, precision must match compiled-in value... */
|
||||||
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
/* Check that number of components won't exceed internal array sizes */
|
||||||
|
if (cinfo->num_components > MAX_COMPONENTS)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||||
|
MAX_COMPONENTS);
|
||||||
|
|
||||||
|
/* Compute maximum sampling factors; check factor validity */
|
||||||
|
cinfo->max_h_samp_factor = 1;
|
||||||
|
cinfo->max_v_samp_factor = 1;
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
||||||
|
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_SAMPLING);
|
||||||
|
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||||
|
compptr->h_samp_factor);
|
||||||
|
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||||
|
compptr->v_samp_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
|
||||||
|
* In the full decompressor, this will be overridden by jdmaster.c;
|
||||||
|
* but in the transcoder, jdmaster.c is not used, so we must do it here.
|
||||||
|
*/
|
||||||
|
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||||
|
|
||||||
|
/* Compute dimensions of components */
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
compptr->DCT_scaled_size = DCTSIZE;
|
||||||
|
/* Size in DCT blocks */
|
||||||
|
compptr->width_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||||
|
compptr->height_in_blocks = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||||
|
/* downsampled_width and downsampled_height will also be overridden by
|
||||||
|
* jdmaster.c if we are doing full decompression. The transcoder library
|
||||||
|
* doesn't use these values, but the calling application might.
|
||||||
|
*/
|
||||||
|
/* Size in samples */
|
||||||
|
compptr->downsampled_width = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||||
|
(long) cinfo->max_h_samp_factor);
|
||||||
|
compptr->downsampled_height = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||||
|
(long) cinfo->max_v_samp_factor);
|
||||||
|
/* Mark component needed, until color conversion says otherwise */
|
||||||
|
compptr->component_needed = TRUE;
|
||||||
|
/* Mark no quantization table yet saved for component */
|
||||||
|
compptr->quant_table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute number of fully interleaved MCU rows. */
|
||||||
|
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
|
||||||
|
/* Decide whether file contains multiple scans */
|
||||||
|
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
||||||
|
cinfo->inputctl->has_multiple_scans = TRUE;
|
||||||
|
else
|
||||||
|
cinfo->inputctl->has_multiple_scans = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
per_scan_setup (j_decompress_ptr cinfo)
|
||||||
|
/* Do computations that are needed before processing a JPEG scan */
|
||||||
|
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
|
||||||
|
{
|
||||||
|
int ci, mcublks, tmp;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
if (cinfo->comps_in_scan == 1) {
|
||||||
|
|
||||||
|
/* Noninterleaved (single-component) scan */
|
||||||
|
compptr = cinfo->cur_comp_info[0];
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||||
|
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||||
|
|
||||||
|
/* For noninterleaved scan, always one block per MCU */
|
||||||
|
compptr->MCU_width = 1;
|
||||||
|
compptr->MCU_height = 1;
|
||||||
|
compptr->MCU_blocks = 1;
|
||||||
|
compptr->MCU_sample_width = compptr->DCT_scaled_size;
|
||||||
|
compptr->last_col_width = 1;
|
||||||
|
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||||
|
* as the number of block rows present in the last iMCU row.
|
||||||
|
*/
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
|
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
cinfo->blocks_in_MCU = 1;
|
||||||
|
cinfo->MCU_membership[0] = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Interleaved (multi-component) scan */
|
||||||
|
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
|
||||||
|
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
|
||||||
|
MAX_COMPS_IN_SCAN);
|
||||||
|
|
||||||
|
/* Overall image size in MCUs */
|
||||||
|
cinfo->MCUs_per_row = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_width,
|
||||||
|
(long) (cinfo->max_h_samp_factor*DCTSIZE));
|
||||||
|
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||||
|
jdiv_round_up((long) cinfo->image_height,
|
||||||
|
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||||
|
|
||||||
|
cinfo->blocks_in_MCU = 0;
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Sampling factors give # of blocks of component in each MCU */
|
||||||
|
compptr->MCU_width = compptr->h_samp_factor;
|
||||||
|
compptr->MCU_height = compptr->v_samp_factor;
|
||||||
|
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||||
|
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
|
||||||
|
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||||
|
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_width;
|
||||||
|
compptr->last_col_width = tmp;
|
||||||
|
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||||
|
if (tmp == 0) tmp = compptr->MCU_height;
|
||||||
|
compptr->last_row_height = tmp;
|
||||||
|
/* Prepare array describing MCU composition */
|
||||||
|
mcublks = compptr->MCU_blocks;
|
||||||
|
if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||||
|
while (mcublks-- > 0) {
|
||||||
|
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save away a copy of the Q-table referenced by each component present
|
||||||
|
* in the current scan, unless already saved during a prior scan.
|
||||||
|
*
|
||||||
|
* In a multiple-scan JPEG file, the encoder could assign different components
|
||||||
|
* the same Q-table slot number, but change table definitions between scans
|
||||||
|
* so that each component uses a different Q-table. (The IJG encoder is not
|
||||||
|
* currently capable of doing this, but other encoders might.) Since we want
|
||||||
|
* to be able to dequantize all the components at the end of the file, this
|
||||||
|
* means that we have to save away the table actually used for each component.
|
||||||
|
* We do this by copying the table at the start of the first scan containing
|
||||||
|
* the component.
|
||||||
|
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
|
||||||
|
* slot between scans of a component using that slot. If the encoder does so
|
||||||
|
* anyway, this decoder will simply use the Q-table values that were current
|
||||||
|
* at the start of the first scan for the component.
|
||||||
|
*
|
||||||
|
* The decompressor output side looks only at the saved quant tables,
|
||||||
|
* not at the current Q-table slots.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
latch_quant_tables (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
int ci, qtblno;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JQUANT_TBL * qtbl;
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* No work if we already saved Q-table for this component */
|
||||||
|
if (compptr->quant_table != NULL)
|
||||||
|
continue;
|
||||||
|
/* Make sure specified quantization table is present */
|
||||||
|
qtblno = compptr->quant_tbl_no;
|
||||||
|
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||||
|
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||||
|
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||||
|
/* OK, save away the quantization table */
|
||||||
|
qtbl = (JQUANT_TBL *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(JQUANT_TBL));
|
||||||
|
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
|
||||||
|
compptr->quant_table = qtbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the input modules to read a scan of compressed data.
|
||||||
|
* The first call to this is done by jdmaster.c after initializing
|
||||||
|
* the entire decompressor (during jpeg_start_decompress).
|
||||||
|
* Subsequent calls come from consume_markers, below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_input_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
per_scan_setup(cinfo);
|
||||||
|
latch_quant_tables(cinfo);
|
||||||
|
(*cinfo->entropy->start_pass) (cinfo);
|
||||||
|
(*cinfo->coef->start_input_pass) (cinfo);
|
||||||
|
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish up after inputting a compressed-data scan.
|
||||||
|
* This is called by the coefficient controller after it's read all
|
||||||
|
* the expected data of the scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
finish_input_pass (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
cinfo->inputctl->consume_input = consume_markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read JPEG markers before, between, or after compressed-data scans.
|
||||||
|
* Change state as necessary when a new scan is reached.
|
||||||
|
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||||
|
*
|
||||||
|
* The consume_input method pointer points either here or to the
|
||||||
|
* coefficient controller's consume_data routine, depending on whether
|
||||||
|
* we are reading a compressed data segment or inter-segment markers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(int)
|
||||||
|
consume_markers (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
|
||||||
|
return JPEG_REACHED_EOI;
|
||||||
|
|
||||||
|
val = (*cinfo->marker->read_markers) (cinfo);
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case JPEG_REACHED_SOS: /* Found SOS */
|
||||||
|
if (inputctl->inheaders) { /* 1st SOS */
|
||||||
|
initial_setup(cinfo);
|
||||||
|
inputctl->inheaders = FALSE;
|
||||||
|
/* Note: start_input_pass must be called by jdmaster.c
|
||||||
|
* before any more input can be consumed. jdapimin.c is
|
||||||
|
* responsible for enforcing this sequencing.
|
||||||
|
*/
|
||||||
|
} else { /* 2nd or later SOS marker */
|
||||||
|
if (! inputctl->pub.has_multiple_scans)
|
||||||
|
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
|
||||||
|
start_input_pass(cinfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JPEG_REACHED_EOI: /* Found EOI */
|
||||||
|
inputctl->pub.eoi_reached = TRUE;
|
||||||
|
if (inputctl->inheaders) { /* Tables-only datastream, apparently */
|
||||||
|
if (cinfo->marker->saw_SOF)
|
||||||
|
ERREXIT(cinfo, JERR_SOF_NO_SOS);
|
||||||
|
} else {
|
||||||
|
/* Prevent infinite loop in coef ctlr's decompress_data routine
|
||||||
|
* if user set output_scan_number larger than number of scans.
|
||||||
|
*/
|
||||||
|
if (cinfo->output_scan_number > cinfo->input_scan_number)
|
||||||
|
cinfo->output_scan_number = cinfo->input_scan_number;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JPEG_SUSPENDED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset state to begin a fresh datastream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
reset_input_controller (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||||
|
|
||||||
|
inputctl->pub.consume_input = consume_markers;
|
||||||
|
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||||
|
inputctl->pub.eoi_reached = FALSE;
|
||||||
|
inputctl->inheaders = TRUE;
|
||||||
|
/* Reset other modules */
|
||||||
|
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||||
|
(*cinfo->marker->reset_marker_reader) (cinfo);
|
||||||
|
/* Reset progression state -- would be cleaner if entropy decoder did this */
|
||||||
|
cinfo->coef_bits = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the input controller module.
|
||||||
|
* This is called only once, when the decompression object is created.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_input_controller (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_inputctl_ptr inputctl;
|
||||||
|
|
||||||
|
/* Create subobject in permanent pool */
|
||||||
|
inputctl = (my_inputctl_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||||
|
SIZEOF(my_input_controller));
|
||||||
|
cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
|
||||||
|
/* Initialize method pointers */
|
||||||
|
inputctl->pub.consume_input = consume_markers;
|
||||||
|
inputctl->pub.reset_input_controller = reset_input_controller;
|
||||||
|
inputctl->pub.start_input_pass = start_input_pass;
|
||||||
|
inputctl->pub.finish_input_pass = finish_input_pass;
|
||||||
|
/* Initialize state: can't use reset_input_controller since we don't
|
||||||
|
* want to try to reset other modules yet.
|
||||||
|
*/
|
||||||
|
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||||
|
inputctl->pub.eoi_reached = FALSE;
|
||||||
|
inputctl->inheaders = TRUE;
|
||||||
|
}
|
480
jpeg-6b/jdmainct.c
Normal file
480
jpeg-6b/jdmainct.c
Normal file
|
@ -0,0 +1,480 @@
|
||||||
|
/*
|
||||||
|
* 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));
|
||||||
|
|
||||||
|
|
||||||
|
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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf;
|
||||||
|
|
||||||
|
/* Get top-level space for component array pointers.
|
||||||
|
* We alloc both arrays with one call to save a few cycles.
|
||||||
|
*/
|
||||||
|
mymain->xbuffer[0] = (JSAMPIMAGE)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
|
||||||
|
mymain->xbuffer[1] = mymain->xbuffer[0] + cinfo->num_components;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
/* Get space for pointer lists --- M+4 row groups in each list.
|
||||||
|
* We alloc both pointer lists with one call to save a few cycles.
|
||||||
|
*/
|
||||||
|
xbuf = (JSAMPARRAY)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
|
||||||
|
xbuf += rgroup; /* want one row group at negative offsets */
|
||||||
|
mymain->xbuffer[0][ci] = xbuf;
|
||||||
|
xbuf += rgroup * (M + 4);
|
||||||
|
mymain->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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY buf, xbuf0, xbuf1;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
xbuf0 = mymain->xbuffer[0][ci];
|
||||||
|
xbuf1 = mymain->xbuffer[1][ci];
|
||||||
|
/* First copy the workspace pointers as-is */
|
||||||
|
buf = mymain->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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup;
|
||||||
|
int M = cinfo->min_DCT_scaled_size;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf0, xbuf1;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
xbuf0 = mymain->xbuffer[0][ci];
|
||||||
|
xbuf1 = mymain->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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
int ci, i, rgroup, iMCUheight, rows_left;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
JSAMPARRAY xbuf;
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Count sample rows in one iMCU row and in one row group */
|
||||||
|
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
|
||||||
|
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
|
||||||
|
/* Count nondummy sample rows remaining for this component */
|
||||||
|
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
|
||||||
|
if (rows_left == 0) rows_left = iMCUheight;
|
||||||
|
/* Count nondummy row groups. Should get same answer for each component,
|
||||||
|
* so we need only do it once.
|
||||||
|
*/
|
||||||
|
if (ci == 0) {
|
||||||
|
mymain->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 = mymain->xbuffer[mymain->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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
switch (pass_mode) {
|
||||||
|
case JBUF_PASS_THRU:
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
mymain->pub.process_data = process_data_context_main;
|
||||||
|
make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
|
||||||
|
mymain->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
|
||||||
|
mymain->context_state = CTX_PREPARE_FOR_IMCU;
|
||||||
|
mymain->iMCU_row_ctr = 0;
|
||||||
|
} else {
|
||||||
|
/* Simple case with no context needed */
|
||||||
|
mymain->pub.process_data = process_data_simple_main;
|
||||||
|
}
|
||||||
|
mymain->buffer_full = FALSE; /* Mark buffer empty */
|
||||||
|
mymain->rowgroup_ctr = 0;
|
||||||
|
break;
|
||||||
|
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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
JDIMENSION rowgroups_avail;
|
||||||
|
|
||||||
|
/* Read input data if we haven't filled the main buffer yet */
|
||||||
|
if (! mymain->buffer_full) {
|
||||||
|
if (! (*cinfo->coef->decompress_data) (cinfo, mymain->buffer))
|
||||||
|
return; /* suspension forced, can do nothing more */
|
||||||
|
mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
|
||||||
|
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
|
||||||
|
/* Note: at the bottom of the image, we may pass extra garbage row groups
|
||||||
|
* to the postprocessor. The postprocessor has to check for bottom
|
||||||
|
* of image anyway (at row resolution), so no point in us doing it too.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Feed the postprocessor */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, mymain->buffer,
|
||||||
|
&mymain->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 (mymain->rowgroup_ctr >= rowgroups_avail) {
|
||||||
|
mymain->buffer_full = FALSE;
|
||||||
|
mymain->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 mymain = (my_main_ptr) cinfo->main;
|
||||||
|
|
||||||
|
/* Read input data if we haven't filled the main buffer yet */
|
||||||
|
if (! mymain->buffer_full) {
|
||||||
|
if (! (*cinfo->coef->decompress_data) (cinfo,
|
||||||
|
mymain->xbuffer[mymain->whichptr]))
|
||||||
|
return; /* suspension forced, can do nothing more */
|
||||||
|
mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||||
|
mymain->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 (mymain->context_state) {
|
||||||
|
case CTX_POSTPONED_ROW:
|
||||||
|
/* Call postprocessor using previously set pointers for postponed row */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr],
|
||||||
|
&mymain->rowgroup_ctr, mymain->rowgroups_avail,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
if (mymain->rowgroup_ctr < mymain->rowgroups_avail)
|
||||||
|
return; /* Need to suspend */
|
||||||
|
mymain->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 */
|
||||||
|
mymain->rowgroup_ctr = 0;
|
||||||
|
mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
|
||||||
|
/* Check for bottom of image: if so, tweak pointers to "duplicate"
|
||||||
|
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
|
||||||
|
*/
|
||||||
|
if (mymain->iMCU_row_ctr == cinfo->total_iMCU_rows)
|
||||||
|
set_bottom_pointers(cinfo);
|
||||||
|
mymain->context_state = CTX_PROCESS_IMCU;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case CTX_PROCESS_IMCU:
|
||||||
|
/* Call postprocessor using previously set pointers */
|
||||||
|
(*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr],
|
||||||
|
&mymain->rowgroup_ctr, mymain->rowgroups_avail,
|
||||||
|
output_buf, out_row_ctr, out_rows_avail);
|
||||||
|
if (mymain->rowgroup_ctr < mymain->rowgroups_avail)
|
||||||
|
return; /* Need to suspend */
|
||||||
|
/* After the first iMCU, change wraparound pointers to normal state */
|
||||||
|
if (mymain->iMCU_row_ctr == 1)
|
||||||
|
set_wraparound_pointers(cinfo);
|
||||||
|
/* Prepare to load new iMCU row using other xbuffer list */
|
||||||
|
mymain->whichptr ^= 1; /* 0=>1 or 1=>0 */
|
||||||
|
mymain->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 */
|
||||||
|
mymain->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
|
||||||
|
mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
|
||||||
|
mymain->context_state = CTX_POSTPONED_ROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize main buffer controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_main_ptr mymain;
|
||||||
|
int ci, rgroup, ngroups;
|
||||||
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
|
mymain = (my_main_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_main_controller));
|
||||||
|
cinfo->main = (struct jpeg_d_main_controller *) mymain;
|
||||||
|
mymain->pub.start_pass = start_pass_main;
|
||||||
|
|
||||||
|
if (need_full_buffer) /* shouldn't happen */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
|
||||||
|
/* Allocate the workspace.
|
||||||
|
* ngroups is the number of row groups we need.
|
||||||
|
*/
|
||||||
|
if (cinfo->upsample->need_context_rows) {
|
||||||
|
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
|
||||||
|
ngroups = cinfo->min_DCT_scaled_size + 2;
|
||||||
|
} else {
|
||||||
|
ngroups = cinfo->min_DCT_scaled_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||||
|
mymain->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
compptr->width_in_blocks * compptr->DCT_scaled_size,
|
||||||
|
(JDIMENSION) (rgroup * ngroups));
|
||||||
|
}
|
||||||
|
}
|
1307
jpeg-6b/jdmarker.c
Normal file
1307
jpeg-6b/jdmarker.c
Normal file
File diff suppressed because it is too large
Load diff
366
jpeg-6b/jdmaster.c
Normal file
366
jpeg-6b/jdmaster.c
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
/*
|
||||||
|
* jdmaster.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 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_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||||
|
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||||
|
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
|
||||||
|
return FALSE;
|
||||||
|
/* ??? also need to test for upsample-time rescaling, when & if supported */
|
||||||
|
return TRUE; /* by golly, it'll work... */
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
{
|
||||||
|
/* Prevent application from calling me at wrong times */
|
||||||
|
if (cinfo->global_state != DSTATE_READY)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
|
|
||||||
|
/* Hardwire it to "no scaling" */
|
||||||
|
cinfo->output_width = cinfo->image_width;
|
||||||
|
cinfo->output_height = cinfo->image_height;
|
||||||
|
/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
|
||||||
|
* and has computed unscaled downsampled_width and downsampled_height.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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->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;
|
||||||
|
|
||||||
|
/* Post-processing: in particular, color conversion first */
|
||||||
|
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, 0);
|
||||||
|
/* Inverse DCT */
|
||||||
|
jinit_inverse_dct(cinfo);
|
||||||
|
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||||
|
if (cinfo->arith_code) {
|
||||||
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
|
} else {
|
||||||
|
if (cinfo->progressive_mode) {
|
||||||
|
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||||
|
jinit_phuff_decoder(cinfo);
|
||||||
|
#else
|
||||||
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
jinit_huff_decoder(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize principal buffer controllers. */
|
||||||
|
use_c_buffer = cinfo->inputctl->has_multiple_scans;
|
||||||
|
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||||
|
|
||||||
|
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->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 = 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;
|
||||||
|
|
||||||
|
(*cinfo->idct->start_pass) (cinfo);
|
||||||
|
(*cinfo->coef->start_output_pass) (cinfo);
|
||||||
|
if (! master->using_merged_upsample)
|
||||||
|
(*cinfo->cconvert->start_pass) (cinfo);
|
||||||
|
(*cinfo->upsample->start_pass) (cinfo);
|
||||||
|
(*cinfo->post->start_pass) (cinfo, 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 + 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;
|
||||||
|
|
||||||
|
master->pass_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_selection(cinfo);
|
||||||
|
}
|
400
jpeg-6b/jdmerge.c
Normal file
400
jpeg-6b/jdmerge.c
Normal file
|
@ -0,0 +1,400 @@
|
||||||
|
/*
|
||||||
|
* jdmerge.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 code for merged upsampling/color conversion.
|
||||||
|
*
|
||||||
|
* This file combines functions from jdsample.c and jdcolor.c;
|
||||||
|
* read those files first to understand what's going on.
|
||||||
|
*
|
||||||
|
* When the chroma components are to be upsampled by simple replication
|
||||||
|
* (ie, box filtering), we can save some work in color conversion by
|
||||||
|
* calculating all the output pixels corresponding to a pair of chroma
|
||||||
|
* samples at one time. In the conversion equations
|
||||||
|
* R = Y + K1 * Cr
|
||||||
|
* G = Y + K2 * Cb + K3 * Cr
|
||||||
|
* B = Y + K4 * Cb
|
||||||
|
* only the Y term varies among the group of pixels corresponding to a pair
|
||||||
|
* of chroma samples, so the rest of the terms can be calculated just once.
|
||||||
|
* At typical sampling ratios, this eliminates half or three-quarters of the
|
||||||
|
* multiplications needed for color conversion.
|
||||||
|
*
|
||||||
|
* This file currently provides implementations for the following cases:
|
||||||
|
* YCbCr => RGB color conversion only.
|
||||||
|
* Sampling ratios of 2h1v or 2h2v.
|
||||||
|
* No scaling needed at upsample time.
|
||||||
|
* Corner-aligned (non-CCIR601) sampling alignment.
|
||||||
|
* Other special cases could be added, but in most applications these are
|
||||||
|
* the only common cases. (For uncommon cases we fall back on the more
|
||||||
|
* general code in jdsample.c and jdcolor.c.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_upsampler pub; /* public fields */
|
||||||
|
|
||||||
|
/* Pointer to routine to do actual upsampling/conversion of one row group */
|
||||||
|
JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
|
||||||
|
JSAMPARRAY output_buf));
|
||||||
|
|
||||||
|
/* Private state for YCC->RGB conversion */
|
||||||
|
int * Cr_r_tab; /* => table for Cr to R conversion */
|
||||||
|
int * Cb_b_tab; /* => table for Cb to B conversion */
|
||||||
|
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
|
||||||
|
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
|
||||||
|
|
||||||
|
/* For 2:1 vertical sampling, we produce two output rows at a time.
|
||||||
|
* We need a "spare" row buffer to hold the second output row if the
|
||||||
|
* application provides just a one-row buffer; we also use the spare
|
||||||
|
* to discard the dummy last row if the image height is odd.
|
||||||
|
*/
|
||||||
|
JSAMPROW spare_row;
|
||||||
|
boolean spare_full; /* T if spare buffer is occupied */
|
||||||
|
|
||||||
|
JDIMENSION out_row_width; /* samples per output row */
|
||||||
|
JDIMENSION rows_to_go; /* counts rows remaining in image */
|
||||||
|
} my_upsampler;
|
||||||
|
|
||||||
|
typedef my_upsampler * my_upsample_ptr;
|
||||||
|
|
||||||
|
#define SCALEBITS 16 /* speediest right-shift on some machines */
|
||||||
|
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
|
||||||
|
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize tables for YCC->RGB colorspace conversion.
|
||||||
|
* This is taken directly from jdcolor.c; see that file for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
build_ycc_rgb_table (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
int i;
|
||||||
|
INT32 x;
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
upsample->Cr_r_tab = (int *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||||
|
upsample->Cb_b_tab = (int *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||||
|
upsample->Cr_g_tab = (INT32 *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||||
|
upsample->Cb_g_tab = (INT32 *)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||||
|
|
||||||
|
for (i = 0, 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 */
|
||||||
|
upsample->Cr_r_tab[i] = (int)
|
||||||
|
RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
|
||||||
|
/* Cb=>B value is nearest int to 1.77200 * x */
|
||||||
|
upsample->Cb_b_tab[i] = (int)
|
||||||
|
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
|
||||||
|
/* Cr=>G value is scaled-up -0.71414 * x */
|
||||||
|
upsample->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 */
|
||||||
|
upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an upsampling pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_merged_upsample (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
|
||||||
|
/* Mark the spare buffer empty */
|
||||||
|
upsample->spare_full = FALSE;
|
||||||
|
/* Initialize total-height counter for detecting bottom of image */
|
||||||
|
upsample->rows_to_go = cinfo->output_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control routine to do upsampling (and color conversion).
|
||||||
|
*
|
||||||
|
* The control routine just handles the row buffering considerations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
merged_2v_upsample (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||||
|
JDIMENSION in_row_groups_avail,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
/* 2:1 vertical sampling case: may need a spare row. */
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
JSAMPROW work_ptrs[2];
|
||||||
|
JDIMENSION num_rows; /* number of rows returned to caller */
|
||||||
|
|
||||||
|
if (upsample->spare_full) {
|
||||||
|
/* If we have a spare row saved from a previous cycle, just return it. */
|
||||||
|
jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
|
||||||
|
1, upsample->out_row_width);
|
||||||
|
num_rows = 1;
|
||||||
|
upsample->spare_full = FALSE;
|
||||||
|
} else {
|
||||||
|
/* Figure number of rows to return to caller. */
|
||||||
|
num_rows = 2;
|
||||||
|
/* Not more than the distance to the end of the image. */
|
||||||
|
if (num_rows > upsample->rows_to_go)
|
||||||
|
num_rows = upsample->rows_to_go;
|
||||||
|
/* And not more than what the client can accept: */
|
||||||
|
out_rows_avail -= *out_row_ctr;
|
||||||
|
if (num_rows > out_rows_avail)
|
||||||
|
num_rows = out_rows_avail;
|
||||||
|
/* Create output pointer array for upsampler. */
|
||||||
|
work_ptrs[0] = output_buf[*out_row_ctr];
|
||||||
|
if (num_rows > 1) {
|
||||||
|
work_ptrs[1] = output_buf[*out_row_ctr + 1];
|
||||||
|
} else {
|
||||||
|
work_ptrs[1] = upsample->spare_row;
|
||||||
|
upsample->spare_full = TRUE;
|
||||||
|
}
|
||||||
|
/* Now do the upsampling. */
|
||||||
|
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust counts */
|
||||||
|
*out_row_ctr += num_rows;
|
||||||
|
upsample->rows_to_go -= num_rows;
|
||||||
|
/* When the buffer is emptied, declare this input row group consumed */
|
||||||
|
if (! upsample->spare_full)
|
||||||
|
(*in_row_group_ctr)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
merged_1v_upsample (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||||
|
JDIMENSION in_row_groups_avail,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
/* 1:1 vertical sampling case: much easier, never need a spare row. */
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
|
||||||
|
/* Just do the upsampling. */
|
||||||
|
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
|
||||||
|
output_buf + *out_row_ctr);
|
||||||
|
/* Adjust counts */
|
||||||
|
(*out_row_ctr)++;
|
||||||
|
(*in_row_group_ctr)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the routines invoked by the control routines to do
|
||||||
|
* the actual upsampling/conversion. One row group is processed per call.
|
||||||
|
*
|
||||||
|
* Note: since we may be writing directly into application-supplied buffers,
|
||||||
|
* we have to be honest about the output width; we can't assume the buffer
|
||||||
|
* has been rounded up to an even width.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v1_merged_upsample (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
|
||||||
|
JSAMPARRAY output_buf)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
register int y, cred, cgreen, cblue;
|
||||||
|
int cb, cr;
|
||||||
|
register JSAMPROW outptr;
|
||||||
|
JSAMPROW inptr0, inptr1, inptr2;
|
||||||
|
JDIMENSION col;
|
||||||
|
/* copy these pointers into registers if possible */
|
||||||
|
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||||
|
int * Crrtab = upsample->Cr_r_tab;
|
||||||
|
int * Cbbtab = upsample->Cb_b_tab;
|
||||||
|
INT32 * Crgtab = upsample->Cr_g_tab;
|
||||||
|
INT32 * Cbgtab = upsample->Cb_g_tab;
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
inptr0 = input_buf[0][in_row_group_ctr];
|
||||||
|
inptr1 = input_buf[1][in_row_group_ctr];
|
||||||
|
inptr2 = input_buf[2][in_row_group_ctr];
|
||||||
|
outptr = output_buf[0];
|
||||||
|
/* Loop for each pair of output pixels */
|
||||||
|
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||||
|
/* Do the chroma part of the calculation */
|
||||||
|
cb = GETJSAMPLE(*inptr1++);
|
||||||
|
cr = GETJSAMPLE(*inptr2++);
|
||||||
|
cred = Crrtab[cr];
|
||||||
|
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||||
|
cblue = Cbbtab[cb];
|
||||||
|
/* Fetch 2 Y values and emit 2 pixels */
|
||||||
|
y = GETJSAMPLE(*inptr0++);
|
||||||
|
outptr[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr += RGB_PIXELSIZE;
|
||||||
|
y = GETJSAMPLE(*inptr0++);
|
||||||
|
outptr[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr += RGB_PIXELSIZE;
|
||||||
|
}
|
||||||
|
/* If image width is odd, do the last output column separately */
|
||||||
|
if (cinfo->output_width & 1) {
|
||||||
|
cb = GETJSAMPLE(*inptr1);
|
||||||
|
cr = GETJSAMPLE(*inptr2);
|
||||||
|
cred = Crrtab[cr];
|
||||||
|
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||||
|
cblue = Cbbtab[cb];
|
||||||
|
y = GETJSAMPLE(*inptr0);
|
||||||
|
outptr[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v2_merged_upsample (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
|
||||||
|
JSAMPARRAY output_buf)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
register int y, cred, cgreen, cblue;
|
||||||
|
int cb, cr;
|
||||||
|
register JSAMPROW outptr0, outptr1;
|
||||||
|
JSAMPROW inptr00, inptr01, inptr1, inptr2;
|
||||||
|
JDIMENSION col;
|
||||||
|
/* copy these pointers into registers if possible */
|
||||||
|
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||||
|
int * Crrtab = upsample->Cr_r_tab;
|
||||||
|
int * Cbbtab = upsample->Cb_b_tab;
|
||||||
|
INT32 * Crgtab = upsample->Cr_g_tab;
|
||||||
|
INT32 * Cbgtab = upsample->Cb_g_tab;
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
inptr00 = input_buf[0][in_row_group_ctr*2];
|
||||||
|
inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
|
||||||
|
inptr1 = input_buf[1][in_row_group_ctr];
|
||||||
|
inptr2 = input_buf[2][in_row_group_ctr];
|
||||||
|
outptr0 = output_buf[0];
|
||||||
|
outptr1 = output_buf[1];
|
||||||
|
/* Loop for each group of output pixels */
|
||||||
|
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||||
|
/* Do the chroma part of the calculation */
|
||||||
|
cb = GETJSAMPLE(*inptr1++);
|
||||||
|
cr = GETJSAMPLE(*inptr2++);
|
||||||
|
cred = Crrtab[cr];
|
||||||
|
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||||
|
cblue = Cbbtab[cb];
|
||||||
|
/* Fetch 4 Y values and emit 4 pixels */
|
||||||
|
y = GETJSAMPLE(*inptr00++);
|
||||||
|
outptr0[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr0 += RGB_PIXELSIZE;
|
||||||
|
y = GETJSAMPLE(*inptr00++);
|
||||||
|
outptr0[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr0 += RGB_PIXELSIZE;
|
||||||
|
y = GETJSAMPLE(*inptr01++);
|
||||||
|
outptr1[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr1 += RGB_PIXELSIZE;
|
||||||
|
y = GETJSAMPLE(*inptr01++);
|
||||||
|
outptr1[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
outptr1 += RGB_PIXELSIZE;
|
||||||
|
}
|
||||||
|
/* If image width is odd, do the last output column separately */
|
||||||
|
if (cinfo->output_width & 1) {
|
||||||
|
cb = GETJSAMPLE(*inptr1);
|
||||||
|
cr = GETJSAMPLE(*inptr2);
|
||||||
|
cred = Crrtab[cr];
|
||||||
|
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||||
|
cblue = Cbbtab[cb];
|
||||||
|
y = GETJSAMPLE(*inptr00);
|
||||||
|
outptr0[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
y = GETJSAMPLE(*inptr01);
|
||||||
|
outptr1[RGB_RED] = range_limit[y + cred];
|
||||||
|
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||||
|
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for merged upsampling/color conversion.
|
||||||
|
*
|
||||||
|
* NB: this is called under the conditions determined by use_merged_upsample()
|
||||||
|
* in jdmaster.c. That routine MUST correspond to the actual capabilities
|
||||||
|
* of this module; no safety checks are made here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_merged_upsampler (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample;
|
||||||
|
|
||||||
|
upsample = (my_upsample_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_upsampler));
|
||||||
|
cinfo->upsample = (struct jpeg_upsampler *) upsample;
|
||||||
|
upsample->pub.start_pass = start_pass_merged_upsample;
|
||||||
|
upsample->pub.need_context_rows = FALSE;
|
||||||
|
|
||||||
|
upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
|
||||||
|
|
||||||
|
if (cinfo->max_v_samp_factor == 2) {
|
||||||
|
upsample->pub.upsample = merged_2v_upsample;
|
||||||
|
upsample->upmethod = h2v2_merged_upsample;
|
||||||
|
/* Allocate a spare row buffer */
|
||||||
|
upsample->spare_row = (JSAMPROW)
|
||||||
|
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
|
||||||
|
} else {
|
||||||
|
upsample->pub.upsample = merged_1v_upsample;
|
||||||
|
upsample->upmethod = h2v1_merged_upsample;
|
||||||
|
/* No spare row needed */
|
||||||
|
upsample->spare_row = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
build_ycc_rgb_table(cinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* UPSAMPLE_MERGING_SUPPORTED */
|
668
jpeg-6b/jdphuff.c
Normal file
668
jpeg-6b/jdphuff.c
Normal file
|
@ -0,0 +1,668 @@
|
||||||
|
/*
|
||||||
|
* jdphuff.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains Huffman entropy decoding routines for progressive JPEG.
|
||||||
|
*
|
||||||
|
* Much of the complexity here has to do with supporting input suspension.
|
||||||
|
* If the data source module demands suspension, we want to be able to back
|
||||||
|
* up to the start of the current MCU. To do this, we copy state variables
|
||||||
|
* into local working storage, and update them back to the permanent
|
||||||
|
* storage only upon successful completion of an MCU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expanded entropy decoder object for progressive Huffman decoding.
|
||||||
|
*
|
||||||
|
* The savable_state subrecord contains fields that change within an MCU,
|
||||||
|
* but must not be updated permanently until we complete the MCU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int EOBRUN; /* remaining EOBs in EOBRUN */
|
||||||
|
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||||
|
} savable_state;
|
||||||
|
|
||||||
|
/* This macro is to work around compilers with missing or broken
|
||||||
|
* structure assignment. You'll need to fix this code if you have
|
||||||
|
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_STRUCT_ASSIGN
|
||||||
|
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||||
|
#else
|
||||||
|
#if MAX_COMPS_IN_SCAN == 4
|
||||||
|
#define ASSIGN_STATE(dest,src) \
|
||||||
|
((dest).EOBRUN = (src).EOBRUN, \
|
||||||
|
(dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||||
|
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||||
|
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||||
|
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_entropy_decoder pub; /* public fields */
|
||||||
|
|
||||||
|
/* These fields are loaded into local variables at start of each MCU.
|
||||||
|
* In case of suspension, we exit WITHOUT updating them.
|
||||||
|
*/
|
||||||
|
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||||
|
savable_state saved; /* Other state at start of MCU */
|
||||||
|
|
||||||
|
/* These fields are NOT loaded into local working state. */
|
||||||
|
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||||
|
|
||||||
|
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||||
|
d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
|
||||||
|
|
||||||
|
d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
|
||||||
|
} phuff_entropy_decoder;
|
||||||
|
|
||||||
|
typedef phuff_entropy_decoder * phuff_entropy_ptr;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a Huffman-compressed scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_phuff_decoder (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
boolean is_DC_band, bad;
|
||||||
|
int ci, coefi, tbl;
|
||||||
|
int *coef_bit_ptr;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
is_DC_band = (cinfo->Ss == 0);
|
||||||
|
|
||||||
|
/* Validate scan parameters */
|
||||||
|
bad = FALSE;
|
||||||
|
if (is_DC_band) {
|
||||||
|
if (cinfo->Se != 0)
|
||||||
|
bad = TRUE;
|
||||||
|
} else {
|
||||||
|
/* need not check Ss/Se < 0 since they came from unsigned bytes */
|
||||||
|
if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
|
||||||
|
bad = TRUE;
|
||||||
|
/* AC scans may have only one component */
|
||||||
|
if (cinfo->comps_in_scan != 1)
|
||||||
|
bad = TRUE;
|
||||||
|
}
|
||||||
|
if (cinfo->Ah != 0) {
|
||||||
|
/* Successive approximation refinement scan: must have Al = Ah-1. */
|
||||||
|
if (cinfo->Al != cinfo->Ah-1)
|
||||||
|
bad = TRUE;
|
||||||
|
}
|
||||||
|
if (cinfo->Al > 13) /* need not check for < 0 */
|
||||||
|
bad = TRUE;
|
||||||
|
/* Arguably the maximum Al value should be less than 13 for 8-bit precision,
|
||||||
|
* but the spec doesn't say so, and we try to be liberal about what we
|
||||||
|
* accept. Note: large Al values could result in out-of-range DC
|
||||||
|
* coefficients during early scans, leading to bizarre displays due to
|
||||||
|
* overflows in the IDCT math. But we won't crash.
|
||||||
|
*/
|
||||||
|
if (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 cindex = cinfo->cur_comp_info[ci]->component_index;
|
||||||
|
coef_bit_ptr = & cinfo->coef_bits[cindex][0];
|
||||||
|
if (!is_DC_band && 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 (is_DC_band)
|
||||||
|
entropy->pub.decode_mcu = decode_mcu_DC_first;
|
||||||
|
else
|
||||||
|
entropy->pub.decode_mcu = decode_mcu_AC_first;
|
||||||
|
} else {
|
||||||
|
if (is_DC_band)
|
||||||
|
entropy->pub.decode_mcu = decode_mcu_DC_refine;
|
||||||
|
else
|
||||||
|
entropy->pub.decode_mcu = decode_mcu_AC_refine;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
|
compptr = cinfo->cur_comp_info[ci];
|
||||||
|
/* Make sure requested tables are present, and compute derived tables.
|
||||||
|
* We may build same derived table more than once, but it's not expensive.
|
||||||
|
*/
|
||||||
|
if (is_DC_band) {
|
||||||
|
if (cinfo->Ah == 0) { /* DC refinement needs no table */
|
||||||
|
tbl = compptr->dc_tbl_no;
|
||||||
|
jpeg_make_d_derived_tbl(cinfo, TRUE, tbl,
|
||||||
|
& entropy->derived_tbls[tbl]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tbl = compptr->ac_tbl_no;
|
||||||
|
jpeg_make_d_derived_tbl(cinfo, FALSE, tbl,
|
||||||
|
& entropy->derived_tbls[tbl]);
|
||||||
|
/* remember the single active table */
|
||||||
|
entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
|
||||||
|
}
|
||||||
|
/* Initialize DC predictions to 0 */
|
||||||
|
entropy->saved.last_dc_val[ci] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize bitread state variables */
|
||||||
|
entropy->bitstate.bits_left = 0;
|
||||||
|
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||||
|
entropy->pub.insufficient_data = FALSE;
|
||||||
|
|
||||||
|
/* Initialize private state variables */
|
||||||
|
entropy->saved.EOBRUN = 0;
|
||||||
|
|
||||||
|
/* Initialize restart counter */
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure F.12: extend sign bit.
|
||||||
|
* On some machines, a shift and add will be faster than a table lookup.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef AVOID_TABLES
|
||||||
|
|
||||||
|
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
|
||||||
|
|
||||||
|
static const int extend_test[16] = /* entry n is 2**(n-1) */
|
||||||
|
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||||
|
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
||||||
|
|
||||||
|
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||||
|
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
|
||||||
|
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
|
||||||
|
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
|
||||||
|
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
|
||||||
|
|
||||||
|
#endif /* AVOID_TABLES */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for a restart marker & resynchronize decoder.
|
||||||
|
* Returns FALSE if must suspend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL(boolean)
|
||||||
|
process_restart (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
int ci;
|
||||||
|
|
||||||
|
/* Throw away any unused bits remaining in bit buffer; */
|
||||||
|
/* include any full bytes in next_marker's count of discarded bytes */
|
||||||
|
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
|
||||||
|
entropy->bitstate.bits_left = 0;
|
||||||
|
|
||||||
|
/* Advance past the RSTn marker */
|
||||||
|
if (! (*cinfo->marker->read_restart_marker) (cinfo))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Re-initialize DC predictions to 0 */
|
||||||
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||||
|
entropy->saved.last_dc_val[ci] = 0;
|
||||||
|
/* Re-init EOB run count, too */
|
||||||
|
entropy->saved.EOBRUN = 0;
|
||||||
|
|
||||||
|
/* Reset restart counter */
|
||||||
|
entropy->restarts_to_go = cinfo->restart_interval;
|
||||||
|
|
||||||
|
/* Reset out-of-data flag, unless read_restart_marker left us smack up
|
||||||
|
* against a marker. In that case we will end up treating the next data
|
||||||
|
* segment as empty, and we can avoid producing bogus output pixels by
|
||||||
|
* leaving the flag set.
|
||||||
|
*/
|
||||||
|
if (cinfo->unread_marker == 0)
|
||||||
|
entropy->pub.insufficient_data = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Huffman MCU decoding.
|
||||||
|
* Each of these routines decodes and returns one MCU's worth of
|
||||||
|
* Huffman-compressed coefficients.
|
||||||
|
* The coefficients are reordered from zigzag order into natural array order,
|
||||||
|
* but are not dequantized.
|
||||||
|
*
|
||||||
|
* The i'th block of the MCU is stored into the block pointed to by
|
||||||
|
* MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
|
||||||
|
*
|
||||||
|
* We return FALSE if data source requested suspension. In that case no
|
||||||
|
* changes have been made to permanent state. (Exception: some output
|
||||||
|
* coefficients may already have been assigned. This is harmless for
|
||||||
|
* spectral selection, since we'll just re-assign them on the next call.
|
||||||
|
* Successive approximation AC refinement has to be more careful, however.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
register int s, r;
|
||||||
|
int blkn, ci;
|
||||||
|
JBLOCKROW block;
|
||||||
|
BITREAD_STATE_VARS;
|
||||||
|
savable_state state;
|
||||||
|
d_derived_tbl * tbl;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
|
||||||
|
/* Process restart marker if needed; may have to suspend */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
if (! process_restart(cinfo))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||||
|
* This way, we return uniform gray for the remainder of the segment.
|
||||||
|
*/
|
||||||
|
if (! entropy->pub.insufficient_data) {
|
||||||
|
|
||||||
|
/* Load up working state */
|
||||||
|
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||||
|
ASSIGN_STATE(state, entropy->saved);
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
tbl = entropy->derived_tbls[compptr->dc_tbl_no];
|
||||||
|
|
||||||
|
/* Decode a single block's worth of coefficients */
|
||||||
|
|
||||||
|
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||||
|
HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
|
||||||
|
if (s) {
|
||||||
|
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||||
|
r = GET_BITS(s);
|
||||||
|
s = HUFF_EXTEND(r, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert DC difference to actual value, update last_dc_val */
|
||||||
|
s += state.last_dc_val[ci];
|
||||||
|
state.last_dc_val[ci] = s;
|
||||||
|
/* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
|
||||||
|
(*block)[0] = (JCOEF) (s << Al);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed MCU, so update state */
|
||||||
|
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||||
|
ASSIGN_STATE(entropy->saved, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Account for restart interval (no-op if not using restarts) */
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
int Se = cinfo->Se;
|
||||||
|
int Al = cinfo->Al;
|
||||||
|
register int s, k, r;
|
||||||
|
unsigned int EOBRUN;
|
||||||
|
JBLOCKROW block;
|
||||||
|
BITREAD_STATE_VARS;
|
||||||
|
d_derived_tbl * tbl;
|
||||||
|
|
||||||
|
/* Process restart marker if needed; may have to suspend */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
if (! process_restart(cinfo))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||||
|
* This way, we return uniform gray for the remainder of the segment.
|
||||||
|
*/
|
||||||
|
if (! entropy->pub.insufficient_data) {
|
||||||
|
|
||||||
|
/* Load up working state.
|
||||||
|
* We can avoid loading/saving bitread state if in an EOB run.
|
||||||
|
*/
|
||||||
|
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
|
||||||
|
|
||||||
|
/* There is always only one block per MCU */
|
||||||
|
|
||||||
|
if (EOBRUN > 0) /* if it's a band of zeroes... */
|
||||||
|
EOBRUN--; /* ...process it now (we do nothing) */
|
||||||
|
else {
|
||||||
|
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||||
|
block = MCU_data[0];
|
||||||
|
tbl = entropy->ac_derived_tbl;
|
||||||
|
|
||||||
|
for (k = cinfo->Ss; k <= Se; k++) {
|
||||||
|
HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
|
||||||
|
r = s >> 4;
|
||||||
|
s &= 15;
|
||||||
|
if (s) {
|
||||||
|
k += r;
|
||||||
|
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||||
|
r = GET_BITS(s);
|
||||||
|
s = HUFF_EXTEND(r, s);
|
||||||
|
/* Scale and output coefficient in natural (dezigzagged) order */
|
||||||
|
(*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
|
||||||
|
} else {
|
||||||
|
if (r == 15) { /* ZRL */
|
||||||
|
k += 15; /* skip 15 zeroes in band */
|
||||||
|
} else { /* EOBr, run length is 2^r + appended bits */
|
||||||
|
EOBRUN = 1 << r;
|
||||||
|
if (r) { /* EOBr, r > 0 */
|
||||||
|
CHECK_BIT_BUFFER(br_state, r, return FALSE);
|
||||||
|
r = GET_BITS(r);
|
||||||
|
EOBRUN += r;
|
||||||
|
}
|
||||||
|
EOBRUN--; /* this band is processed at this moment */
|
||||||
|
break; /* force end-of-band */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed MCU, so update state */
|
||||||
|
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Account for restart interval (no-op if not using restarts) */
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for DC successive approximation refinement scan.
|
||||||
|
* Note: we assume such scans can be multi-component, although the spec
|
||||||
|
* is not very clear on the point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
|
||||||
|
int blkn;
|
||||||
|
JBLOCKROW block;
|
||||||
|
BITREAD_STATE_VARS;
|
||||||
|
|
||||||
|
/* Process restart marker if needed; may have to suspend */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
if (! process_restart(cinfo))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not worth the cycles to check insufficient_data here,
|
||||||
|
* since we will not change the data anyway if we read zeroes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Load up working state */
|
||||||
|
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||||
|
|
||||||
|
/* Outer loop handles each block in the MCU */
|
||||||
|
|
||||||
|
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||||
|
block = MCU_data[blkn];
|
||||||
|
|
||||||
|
/* Encoded data is simply the next bit of the two's-complement DC value */
|
||||||
|
CHECK_BIT_BUFFER(br_state, 1, return FALSE);
|
||||||
|
if (GET_BITS(1))
|
||||||
|
(*block)[0] |= p1;
|
||||||
|
/* Note: since we use |=, repeating the assignment later is safe */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed MCU, so update state */
|
||||||
|
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||||
|
|
||||||
|
/* Account for restart interval (no-op if not using restarts) */
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU decoding for AC successive approximation refinement scan.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(boolean)
|
||||||
|
decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||||
|
int Se = cinfo->Se;
|
||||||
|
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
|
||||||
|
int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
|
||||||
|
register int s, k, r;
|
||||||
|
unsigned int EOBRUN;
|
||||||
|
JBLOCKROW block;
|
||||||
|
JCOEFPTR thiscoef;
|
||||||
|
BITREAD_STATE_VARS;
|
||||||
|
d_derived_tbl * tbl;
|
||||||
|
int num_newnz;
|
||||||
|
int newnz_pos[DCTSIZE2];
|
||||||
|
|
||||||
|
/* Process restart marker if needed; may have to suspend */
|
||||||
|
if (cinfo->restart_interval) {
|
||||||
|
if (entropy->restarts_to_go == 0)
|
||||||
|
if (! process_restart(cinfo))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've run out of data, don't modify the MCU.
|
||||||
|
*/
|
||||||
|
if (! entropy->pub.insufficient_data) {
|
||||||
|
|
||||||
|
/* Load up working state */
|
||||||
|
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||||
|
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
|
||||||
|
|
||||||
|
/* There is always only one block per MCU */
|
||||||
|
block = MCU_data[0];
|
||||||
|
tbl = entropy->ac_derived_tbl;
|
||||||
|
|
||||||
|
/* If we are forced to suspend, we must undo the assignments to any newly
|
||||||
|
* nonzero coefficients in the block, because otherwise we'd get confused
|
||||||
|
* next time about which coefficients were already nonzero.
|
||||||
|
* But we need not undo addition of bits to already-nonzero coefficients;
|
||||||
|
* instead, we can test the current bit to see if we already did it.
|
||||||
|
*/
|
||||||
|
num_newnz = 0;
|
||||||
|
|
||||||
|
/* initialize coefficient loop counter to start of band */
|
||||||
|
k = cinfo->Ss;
|
||||||
|
|
||||||
|
if (EOBRUN == 0) {
|
||||||
|
for (; k <= Se; k++) {
|
||||||
|
HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
|
||||||
|
r = s >> 4;
|
||||||
|
s &= 15;
|
||||||
|
if (s) {
|
||||||
|
if (s != 1) /* size of new coef should always be 1 */
|
||||||
|
WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
|
||||||
|
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
|
||||||
|
if (GET_BITS(1))
|
||||||
|
s = p1; /* newly nonzero coef is positive */
|
||||||
|
else
|
||||||
|
s = m1; /* newly nonzero coef is negative */
|
||||||
|
} else {
|
||||||
|
if (r != 15) {
|
||||||
|
EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */
|
||||||
|
if (r) {
|
||||||
|
CHECK_BIT_BUFFER(br_state, r, goto undoit);
|
||||||
|
r = GET_BITS(r);
|
||||||
|
EOBRUN += r;
|
||||||
|
}
|
||||||
|
break; /* rest of block is handled by EOB logic */
|
||||||
|
}
|
||||||
|
/* note s = 0 for processing ZRL */
|
||||||
|
}
|
||||||
|
/* Advance over already-nonzero coefs and r still-zero coefs,
|
||||||
|
* appending correction bits to the nonzeroes. A correction bit is 1
|
||||||
|
* if the absolute value of the coefficient must be increased.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
thiscoef = *block + jpeg_natural_order[k];
|
||||||
|
if (*thiscoef != 0) {
|
||||||
|
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
|
||||||
|
if (GET_BITS(1)) {
|
||||||
|
if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
|
||||||
|
if (*thiscoef >= 0)
|
||||||
|
*thiscoef += p1;
|
||||||
|
else
|
||||||
|
*thiscoef += m1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (--r < 0)
|
||||||
|
break; /* reached target zero coefficient */
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
} while (k <= Se);
|
||||||
|
if (s) {
|
||||||
|
int pos = jpeg_natural_order[k];
|
||||||
|
/* Output newly nonzero coefficient */
|
||||||
|
(*block)[pos] = (JCOEF) s;
|
||||||
|
/* Remember its position in case we have to suspend */
|
||||||
|
newnz_pos[num_newnz++] = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EOBRUN > 0) {
|
||||||
|
/* Scan any remaining coefficient positions after the end-of-band
|
||||||
|
* (the last newly nonzero coefficient, if any). Append a correction
|
||||||
|
* bit to each already-nonzero coefficient. A correction bit is 1
|
||||||
|
* if the absolute value of the coefficient must be increased.
|
||||||
|
*/
|
||||||
|
for (; k <= Se; k++) {
|
||||||
|
thiscoef = *block + jpeg_natural_order[k];
|
||||||
|
if (*thiscoef != 0) {
|
||||||
|
CHECK_BIT_BUFFER(br_state, 1, goto undoit);
|
||||||
|
if (GET_BITS(1)) {
|
||||||
|
if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
|
||||||
|
if (*thiscoef >= 0)
|
||||||
|
*thiscoef += p1;
|
||||||
|
else
|
||||||
|
*thiscoef += m1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Count one block completed in EOB run */
|
||||||
|
EOBRUN--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed MCU, so update state */
|
||||||
|
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||||
|
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Account for restart interval (no-op if not using restarts) */
|
||||||
|
entropy->restarts_to_go--;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
undoit:
|
||||||
|
/* Re-zero any output coefficients that we made newly nonzero */
|
||||||
|
while (num_newnz > 0)
|
||||||
|
(*block)[newnz_pos[--num_newnz]] = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for progressive Huffman entropy decoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_phuff_decoder (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
phuff_entropy_ptr entropy;
|
||||||
|
int *coef_bit_ptr;
|
||||||
|
int ci, i;
|
||||||
|
|
||||||
|
entropy = (phuff_entropy_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(phuff_entropy_decoder));
|
||||||
|
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||||
|
entropy->pub.start_pass = start_pass_phuff_decoder;
|
||||||
|
|
||||||
|
/* Mark derived tables unallocated */
|
||||||
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
|
entropy->derived_tbls[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create progression status table */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* D_PROGRESSIVE_SUPPORTED */
|
70
jpeg-6b/jdpostct.c
Normal file
70
jpeg-6b/jdpostct.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* jdpostct.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 decompression postprocessing controller.
|
||||||
|
* This controller manages the upsampling, color conversion, and color
|
||||||
|
* quantization/reduction steps; specifically, it controls the buffering
|
||||||
|
* between upsample/color conversion and color quantization/reduction.
|
||||||
|
*
|
||||||
|
* If no color quantization/reduction is required, then this module has no
|
||||||
|
* work to do, and it just hands off to the upsample/color conversion code.
|
||||||
|
* An integrated upsample/convert/quantize process would replace this module
|
||||||
|
* entirely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Private buffer controller object */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_d_post_controller pub; /* public fields */
|
||||||
|
} my_post_controller;
|
||||||
|
|
||||||
|
typedef my_post_controller * my_post_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for a processing pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||||
|
{
|
||||||
|
my_post_ptr post = (my_post_ptr) cinfo->post;
|
||||||
|
|
||||||
|
switch (pass_mode) {
|
||||||
|
case JBUF_PASS_THRU:
|
||||||
|
/* For single-pass processing without color quantization,
|
||||||
|
* I have no work to do; just call the upsampler directly.
|
||||||
|
*/
|
||||||
|
post->pub.post_process_data = cinfo->upsample->upsample;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize postprocessing controller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||||
|
{
|
||||||
|
my_post_ptr post;
|
||||||
|
|
||||||
|
post = (my_post_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_post_controller));
|
||||||
|
cinfo->post = (struct jpeg_d_post_controller *) post;
|
||||||
|
post->pub.start_pass = start_pass_dpost;
|
||||||
|
}
|
478
jpeg-6b/jdsample.c
Normal file
478
jpeg-6b/jdsample.c
Normal file
|
@ -0,0 +1,478 @@
|
||||||
|
/*
|
||||||
|
* jdsample.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 upsampling routines.
|
||||||
|
*
|
||||||
|
* Upsampling input data is counted in "row groups". A row group
|
||||||
|
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||||
|
* sample rows of each component. Upsampling will normally produce
|
||||||
|
* max_v_samp_factor pixel rows from each row group (but this could vary
|
||||||
|
* if the upsampler is applying a scale factor of its own).
|
||||||
|
*
|
||||||
|
* An excellent reference for image resampling is
|
||||||
|
* Digital Image Warping, George Wolberg, 1990.
|
||||||
|
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Pointer to routine to upsample a single component */
|
||||||
|
typedef JMETHOD(void, upsample1_ptr,
|
||||||
|
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||||
|
|
||||||
|
/* Private subobject */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_upsampler pub; /* public fields */
|
||||||
|
|
||||||
|
/* Color conversion buffer. When using separate upsampling and color
|
||||||
|
* conversion steps, this buffer holds one upsampled row group until it
|
||||||
|
* has been color converted and output.
|
||||||
|
* Note: we do not allocate any storage for component(s) which are full-size,
|
||||||
|
* ie do not need rescaling. The corresponding entry of color_buf[] is
|
||||||
|
* simply set to point to the input data array, thereby avoiding copying.
|
||||||
|
*/
|
||||||
|
JSAMPARRAY color_buf[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
/* Per-component upsampling method pointers */
|
||||||
|
upsample1_ptr methods[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
int next_row_out; /* counts rows emitted from color_buf */
|
||||||
|
JDIMENSION rows_to_go; /* counts rows remaining in image */
|
||||||
|
|
||||||
|
/* Height of an input row group for each component. */
|
||||||
|
int rowgroup_height[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
/* These arrays save pixel expansion factors so that int_expand need not
|
||||||
|
* recompute them each time. They are unused for other upsampling methods.
|
||||||
|
*/
|
||||||
|
UINT8 h_expand[MAX_COMPONENTS];
|
||||||
|
UINT8 v_expand[MAX_COMPONENTS];
|
||||||
|
} my_upsampler;
|
||||||
|
|
||||||
|
typedef my_upsampler * my_upsample_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize for an upsampling pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
start_pass_upsample (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
|
||||||
|
/* Mark the conversion buffer empty */
|
||||||
|
upsample->next_row_out = cinfo->max_v_samp_factor;
|
||||||
|
/* Initialize total-height counter for detecting bottom of image */
|
||||||
|
upsample->rows_to_go = cinfo->output_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control routine to do upsampling (and color conversion).
|
||||||
|
*
|
||||||
|
* In this version we upsample each component independently.
|
||||||
|
* We upsample one row group into the conversion buffer, then apply
|
||||||
|
* color conversion a row at a time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
sep_upsample (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||||
|
JDIMENSION in_row_groups_avail,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
JDIMENSION num_rows;
|
||||||
|
|
||||||
|
/* Fill the conversion buffer, if it's empty */
|
||||||
|
if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Invoke per-component upsample method. Notice we pass a POINTER
|
||||||
|
* to color_buf[ci], so that fullsize_upsample can change it.
|
||||||
|
*/
|
||||||
|
(*upsample->methods[ci]) (cinfo, compptr,
|
||||||
|
input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
|
||||||
|
upsample->color_buf + ci);
|
||||||
|
}
|
||||||
|
upsample->next_row_out = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color-convert and emit rows */
|
||||||
|
|
||||||
|
/* How many we have in the buffer: */
|
||||||
|
num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
|
||||||
|
/* Not more than the distance to the end of the image. Need this test
|
||||||
|
* in case the image height is not a multiple of max_v_samp_factor:
|
||||||
|
*/
|
||||||
|
if (num_rows > upsample->rows_to_go)
|
||||||
|
num_rows = upsample->rows_to_go;
|
||||||
|
/* And not more than what the client can accept: */
|
||||||
|
out_rows_avail -= *out_row_ctr;
|
||||||
|
if (num_rows > out_rows_avail)
|
||||||
|
num_rows = out_rows_avail;
|
||||||
|
|
||||||
|
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
|
||||||
|
(JDIMENSION) upsample->next_row_out,
|
||||||
|
output_buf + *out_row_ctr,
|
||||||
|
(int) num_rows);
|
||||||
|
|
||||||
|
/* Adjust counts */
|
||||||
|
*out_row_ctr += num_rows;
|
||||||
|
upsample->rows_to_go -= num_rows;
|
||||||
|
upsample->next_row_out += num_rows;
|
||||||
|
/* When the buffer is emptied, declare this input row group consumed */
|
||||||
|
if (upsample->next_row_out >= cinfo->max_v_samp_factor)
|
||||||
|
(*in_row_group_ctr)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the routines invoked by sep_upsample to upsample pixel values
|
||||||
|
* of a single component. One row group is processed per call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For full-size components, we just make color_buf[ci] point at the
|
||||||
|
* input buffer, and thus avoid copying any data. Note that this is
|
||||||
|
* safe only because sep_upsample doesn't declare the input row group
|
||||||
|
* "consumed" until we are done color converting and emitting it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
*output_data_ptr = input_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a no-op version used for "uninteresting" components.
|
||||||
|
* These components will not be referenced by color conversion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
*output_data_ptr = NULL; /* safety check */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This version handles any integral sampling ratios.
|
||||||
|
* This is not used for typical JPEG files, so it need not be fast.
|
||||||
|
* Nor, for that matter, is it particularly accurate: the algorithm is
|
||||||
|
* simple replication of the input pixel onto the corresponding output
|
||||||
|
* pixels. The hi-falutin sampling literature refers to this as a
|
||||||
|
* "box filter". A box filter tends to introduce visible artifacts,
|
||||||
|
* so if you are actually going to use 3:1 or 4:1 sampling ratios
|
||||||
|
* you would be well advised to improve this code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||||
|
JSAMPARRAY output_data = *output_data_ptr;
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JSAMPLE invalue;
|
||||||
|
register int h;
|
||||||
|
JSAMPROW outend;
|
||||||
|
int h_expand, v_expand;
|
||||||
|
int inrow, outrow;
|
||||||
|
|
||||||
|
h_expand = upsample->h_expand[compptr->component_index];
|
||||||
|
v_expand = upsample->v_expand[compptr->component_index];
|
||||||
|
|
||||||
|
inrow = outrow = 0;
|
||||||
|
while (outrow < cinfo->max_v_samp_factor) {
|
||||||
|
/* Generate one output row with proper horizontal expansion */
|
||||||
|
inptr = input_data[inrow];
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
outend = outptr + cinfo->output_width;
|
||||||
|
while (outptr < outend) {
|
||||||
|
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||||
|
for (h = h_expand; h > 0; h--) {
|
||||||
|
*outptr++ = invalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Generate any additional output rows by duplicating the first one */
|
||||||
|
if (v_expand > 1) {
|
||||||
|
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
|
||||||
|
v_expand-1, cinfo->output_width);
|
||||||
|
}
|
||||||
|
inrow++;
|
||||||
|
outrow += v_expand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
|
||||||
|
* It's still a box filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
JSAMPARRAY output_data = *output_data_ptr;
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JSAMPLE invalue;
|
||||||
|
JSAMPROW outend;
|
||||||
|
int inrow;
|
||||||
|
|
||||||
|
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
|
||||||
|
inptr = input_data[inrow];
|
||||||
|
outptr = output_data[inrow];
|
||||||
|
outend = outptr + cinfo->output_width;
|
||||||
|
while (outptr < outend) {
|
||||||
|
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||||
|
*outptr++ = invalue;
|
||||||
|
*outptr++ = invalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
|
||||||
|
* It's still a box filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
JSAMPARRAY output_data = *output_data_ptr;
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JSAMPLE invalue;
|
||||||
|
JSAMPROW outend;
|
||||||
|
int inrow, outrow;
|
||||||
|
|
||||||
|
inrow = outrow = 0;
|
||||||
|
while (outrow < cinfo->max_v_samp_factor) {
|
||||||
|
inptr = input_data[inrow];
|
||||||
|
outptr = output_data[outrow];
|
||||||
|
outend = outptr + cinfo->output_width;
|
||||||
|
while (outptr < outend) {
|
||||||
|
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||||
|
*outptr++ = invalue;
|
||||||
|
*outptr++ = invalue;
|
||||||
|
}
|
||||||
|
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
|
||||||
|
1, cinfo->output_width);
|
||||||
|
inrow++;
|
||||||
|
outrow += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
|
||||||
|
*
|
||||||
|
* The upsampling algorithm is linear interpolation between pixel centers,
|
||||||
|
* also known as a "triangle filter". This is a good compromise between
|
||||||
|
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
|
||||||
|
* of the way between input pixel centers.
|
||||||
|
*
|
||||||
|
* A note about the "bias" calculations: when rounding fractional values to
|
||||||
|
* integer, we do not want to always round 0.5 up to the next integer.
|
||||||
|
* If we did that, we'd introduce a noticeable bias towards larger values.
|
||||||
|
* Instead, this code is arranged so that 0.5 will be rounded up or down at
|
||||||
|
* alternate pixel locations (a simple ordered dither pattern).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
JSAMPARRAY output_data = *output_data_ptr;
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register int invalue;
|
||||||
|
register JDIMENSION colctr;
|
||||||
|
int inrow;
|
||||||
|
|
||||||
|
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
|
||||||
|
inptr = input_data[inrow];
|
||||||
|
outptr = output_data[inrow];
|
||||||
|
/* Special case for first column */
|
||||||
|
invalue = GETJSAMPLE(*inptr++);
|
||||||
|
*outptr++ = (JSAMPLE) invalue;
|
||||||
|
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||||
|
|
||||||
|
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
|
||||||
|
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
|
||||||
|
invalue = GETJSAMPLE(*inptr++) * 3;
|
||||||
|
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
|
||||||
|
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special case for last column */
|
||||||
|
invalue = GETJSAMPLE(*inptr);
|
||||||
|
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
|
||||||
|
*outptr++ = (JSAMPLE) invalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
|
||||||
|
* Again a triangle filter; see comments for h2v1 case, above.
|
||||||
|
*
|
||||||
|
* It is OK for us to reference the adjacent input rows because we demanded
|
||||||
|
* context from the main buffer controller (see initialization code).
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||||
|
{
|
||||||
|
JSAMPARRAY output_data = *output_data_ptr;
|
||||||
|
register JSAMPROW inptr0, inptr1, outptr;
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
register int thiscolsum, lastcolsum, nextcolsum;
|
||||||
|
#else
|
||||||
|
register INT32 thiscolsum, lastcolsum, nextcolsum;
|
||||||
|
#endif
|
||||||
|
register JDIMENSION colctr;
|
||||||
|
int inrow, outrow, v;
|
||||||
|
|
||||||
|
inrow = outrow = 0;
|
||||||
|
while (outrow < cinfo->max_v_samp_factor) {
|
||||||
|
for (v = 0; v < 2; v++) {
|
||||||
|
/* inptr0 points to nearest input row, inptr1 points to next nearest */
|
||||||
|
inptr0 = input_data[inrow];
|
||||||
|
if (v == 0) /* next nearest is row above */
|
||||||
|
inptr1 = input_data[inrow-1];
|
||||||
|
else /* next nearest is row below */
|
||||||
|
inptr1 = input_data[inrow+1];
|
||||||
|
outptr = output_data[outrow++];
|
||||||
|
|
||||||
|
/* Special case for first column */
|
||||||
|
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||||
|
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||||
|
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||||
|
|
||||||
|
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
|
||||||
|
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
|
||||||
|
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
|
||||||
|
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||||
|
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special case for last column */
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
|
||||||
|
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
|
||||||
|
}
|
||||||
|
inrow++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module initialization routine for upsampling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_upsampler (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_upsample_ptr upsample;
|
||||||
|
int ci;
|
||||||
|
jpeg_component_info * compptr;
|
||||||
|
boolean need_buffer, do_fancy;
|
||||||
|
int h_in_group, v_in_group, h_out_group, v_out_group;
|
||||||
|
|
||||||
|
upsample = (my_upsample_ptr)
|
||||||
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
SIZEOF(my_upsampler));
|
||||||
|
cinfo->upsample = (struct jpeg_upsampler *) upsample;
|
||||||
|
upsample->pub.start_pass = start_pass_upsample;
|
||||||
|
upsample->pub.upsample = sep_upsample;
|
||||||
|
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
|
||||||
|
|
||||||
|
if (cinfo->CCIR601_sampling) /* this isn't supported */
|
||||||
|
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
|
||||||
|
|
||||||
|
/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
|
||||||
|
* so don't ask for it.
|
||||||
|
*/
|
||||||
|
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
|
||||||
|
|
||||||
|
/* Verify we can handle the sampling factors, select per-component methods,
|
||||||
|
* and create storage as needed.
|
||||||
|
*/
|
||||||
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
|
ci++, compptr++) {
|
||||||
|
/* Compute size of an "input group" after IDCT scaling. This many samples
|
||||||
|
* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
|
||||||
|
*/
|
||||||
|
h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size;
|
||||||
|
v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||||
|
cinfo->min_DCT_scaled_size;
|
||||||
|
h_out_group = cinfo->max_h_samp_factor;
|
||||||
|
v_out_group = cinfo->max_v_samp_factor;
|
||||||
|
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
|
||||||
|
need_buffer = TRUE;
|
||||||
|
if (! compptr->component_needed) {
|
||||||
|
/* Don't bother to upsample an uninteresting component. */
|
||||||
|
upsample->methods[ci] = noop_upsample;
|
||||||
|
need_buffer = FALSE;
|
||||||
|
} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
|
||||||
|
/* Fullsize components can be processed without any work. */
|
||||||
|
upsample->methods[ci] = fullsize_upsample;
|
||||||
|
need_buffer = FALSE;
|
||||||
|
} else if (h_in_group * 2 == h_out_group &&
|
||||||
|
v_in_group == v_out_group) {
|
||||||
|
/* Special cases for 2h1v upsampling */
|
||||||
|
if (do_fancy && compptr->downsampled_width > 2)
|
||||||
|
upsample->methods[ci] = h2v1_fancy_upsample;
|
||||||
|
else
|
||||||
|
upsample->methods[ci] = h2v1_upsample;
|
||||||
|
} else if (h_in_group * 2 == h_out_group &&
|
||||||
|
v_in_group * 2 == v_out_group) {
|
||||||
|
/* Special cases for 2h2v upsampling */
|
||||||
|
if (do_fancy && compptr->downsampled_width > 2) {
|
||||||
|
upsample->methods[ci] = h2v2_fancy_upsample;
|
||||||
|
upsample->pub.need_context_rows = TRUE;
|
||||||
|
} else
|
||||||
|
upsample->methods[ci] = h2v2_upsample;
|
||||||
|
} else if ((h_out_group % h_in_group) == 0 &&
|
||||||
|
(v_out_group % v_in_group) == 0) {
|
||||||
|
/* Generic integral-factors upsampling method */
|
||||||
|
upsample->methods[ci] = int_upsample;
|
||||||
|
upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
|
||||||
|
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
|
||||||
|
} else
|
||||||
|
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
|
||||||
|
if (need_buffer) {
|
||||||
|
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
|
||||||
|
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||||
|
(JDIMENSION) jround_up((long) cinfo->output_width,
|
||||||
|
(long) cinfo->max_h_samp_factor),
|
||||||
|
(JDIMENSION) cinfo->max_v_samp_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
261
jpeg-6b/jerror.c
Normal file
261
jpeg-6b/jerror.c
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
/*
|
||||||
|
* jerror.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains simple error-reporting and trace-message routines.
|
||||||
|
* These are suitable for Unix-like systems and others where writing to
|
||||||
|
* stderr is the right thing to do. Many applications will want to replace
|
||||||
|
* some or all of these routines.
|
||||||
|
*
|
||||||
|
* If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
|
||||||
|
* you get a Windows-specific hack to display error messages in a dialog box.
|
||||||
|
* It ain't much, but it beats dropping error messages into the bit bucket,
|
||||||
|
* which is what happens to output to stderr under most Windows C compilers.
|
||||||
|
*
|
||||||
|
* These routines are used by both the compression and decompression code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jversion.h"
|
||||||
|
#include "jerror.h"
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_MESSAGEBOX
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||||
|
#define EXIT_FAILURE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the message string table.
|
||||||
|
* We do this from the master message list in jerror.h by re-reading
|
||||||
|
* jerror.h with a suitable definition for macro JMESSAGE.
|
||||||
|
* The message table is made an external symbol just in case any applications
|
||||||
|
* want to refer to it directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) string ,
|
||||||
|
|
||||||
|
const char * const jpeg_std_message_table[] = {
|
||||||
|
#include "jerror.h"
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Error exit handler: must not return to caller.
|
||||||
|
*
|
||||||
|
* Applications may override this if they want to get control back after
|
||||||
|
* an error. Typically one would longjmp somewhere instead of exiting.
|
||||||
|
* The setjmp buffer can be made a private field within an expanded error
|
||||||
|
* handler object. Note that the info needed to generate an error message
|
||||||
|
* is stored in the error object, so you can generate the message now or
|
||||||
|
* later, at your convenience.
|
||||||
|
* You should make sure that the JPEG object is cleaned up (with jpeg_abort
|
||||||
|
* or jpeg_destroy) at some point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
error_exit (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
/* Always display the message */
|
||||||
|
(*cinfo->err->output_message) (cinfo);
|
||||||
|
|
||||||
|
/* Let the memory manager delete any temp files before we die */
|
||||||
|
jpeg_destroy(cinfo);
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual output of an error or trace message.
|
||||||
|
* Applications may override this method to send JPEG messages somewhere
|
||||||
|
* other than stderr.
|
||||||
|
*
|
||||||
|
* On Windows, printing to stderr is generally completely useless,
|
||||||
|
* so we provide optional code to produce an error-dialog popup.
|
||||||
|
* Most Windows applications will still prefer to override this routine,
|
||||||
|
* but if they don't, it'll do something at least marginally useful.
|
||||||
|
*
|
||||||
|
* NOTE: to use the library in an environment that doesn't support the
|
||||||
|
* C stdio library, you may have to delete the call to fprintf() entirely,
|
||||||
|
* not just not use this routine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
output_message (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
char buffer[JMSG_LENGTH_MAX];
|
||||||
|
|
||||||
|
/* Create the message */
|
||||||
|
(*cinfo->err->format_message) (cinfo, buffer);
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_MESSAGEBOX
|
||||||
|
/* Display it in a message dialog box */
|
||||||
|
MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
|
||||||
|
MB_OK | MB_ICONERROR);
|
||||||
|
#else
|
||||||
|
/* Send it to stderr, adding a newline */
|
||||||
|
fprintf(stderr, "%s\n", buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decide whether to emit a trace or warning message.
|
||||||
|
* msg_level is one of:
|
||||||
|
* -1: recoverable corrupt-data warning, may want to abort.
|
||||||
|
* 0: important advisory messages (always display to user).
|
||||||
|
* 1: first level of tracing detail.
|
||||||
|
* 2,3,...: successively more detailed tracing messages.
|
||||||
|
* An application might override this method if it wanted to abort on warnings
|
||||||
|
* or change the policy about which messages to display.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
emit_message (j_common_ptr cinfo, int msg_level)
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr * err = cinfo->err;
|
||||||
|
|
||||||
|
if (msg_level < 0) {
|
||||||
|
/* It's a warning message. Since corrupt files may generate many warnings,
|
||||||
|
* the policy implemented here is to show only the first warning,
|
||||||
|
* unless trace_level >= 3.
|
||||||
|
*/
|
||||||
|
if (err->num_warnings == 0 || err->trace_level >= 3)
|
||||||
|
(*err->output_message) (cinfo);
|
||||||
|
/* Always count warnings in num_warnings. */
|
||||||
|
err->num_warnings++;
|
||||||
|
} else {
|
||||||
|
/* It's a trace message. Show it if trace_level >= msg_level. */
|
||||||
|
if (err->trace_level >= msg_level)
|
||||||
|
(*err->output_message) (cinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a message string for the most recent JPEG error or message.
|
||||||
|
* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
|
||||||
|
* characters. Note that no '\n' character is added to the string.
|
||||||
|
* Few applications should need to override this method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
format_message (j_common_ptr cinfo, char * buffer)
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr * err = cinfo->err;
|
||||||
|
int msg_code = err->msg_code;
|
||||||
|
const char * msgtext = NULL;
|
||||||
|
const char * msgptr;
|
||||||
|
char ch;
|
||||||
|
boolean isstring;
|
||||||
|
|
||||||
|
/* Look up message string in proper table */
|
||||||
|
if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
|
||||||
|
msgtext = err->jpeg_message_table[msg_code];
|
||||||
|
} else if (err->addon_message_table != NULL &&
|
||||||
|
msg_code >= err->first_addon_message &&
|
||||||
|
msg_code <= err->last_addon_message) {
|
||||||
|
msgtext = err->addon_message_table[msg_code - err->first_addon_message];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Defend against bogus message number */
|
||||||
|
if (msgtext == NULL) {
|
||||||
|
err->msg_parm.i[0] = msg_code;
|
||||||
|
msgtext = err->jpeg_message_table[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for string parameter, as indicated by %s in the message text */
|
||||||
|
isstring = FALSE;
|
||||||
|
msgptr = msgtext;
|
||||||
|
while ((ch = *msgptr++) != '\0') {
|
||||||
|
if (ch == '%') {
|
||||||
|
if (*msgptr == 's') isstring = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format the message into the passed buffer */
|
||||||
|
#if _MSC_VER >= 1400
|
||||||
|
if (isstring)
|
||||||
|
sprintf_s(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
|
||||||
|
else
|
||||||
|
sprintf_s(buffer, JMSG_LENGTH_MAX, msgtext,
|
||||||
|
err->msg_parm.i[0], err->msg_parm.i[1],
|
||||||
|
err->msg_parm.i[2], err->msg_parm.i[3],
|
||||||
|
err->msg_parm.i[4], err->msg_parm.i[5],
|
||||||
|
err->msg_parm.i[6], err->msg_parm.i[7]);
|
||||||
|
#else
|
||||||
|
if (isstring)
|
||||||
|
sprintf(buffer, msgtext, err->msg_parm.s);
|
||||||
|
else
|
||||||
|
sprintf(buffer, msgtext,
|
||||||
|
err->msg_parm.i[0], err->msg_parm.i[1],
|
||||||
|
err->msg_parm.i[2], err->msg_parm.i[3],
|
||||||
|
err->msg_parm.i[4], err->msg_parm.i[5],
|
||||||
|
err->msg_parm.i[6], err->msg_parm.i[7]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset error state variables at start of a new image.
|
||||||
|
* This is called during compression startup to reset trace/error
|
||||||
|
* processing to default state, without losing any application-specific
|
||||||
|
* method pointers. An application might possibly want to override
|
||||||
|
* this method if it has additional error processing state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
reset_error_mgr (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
cinfo->err->num_warnings = 0;
|
||||||
|
/* trace_level is not reset since it is an application-supplied parameter */
|
||||||
|
cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the standard error-handling methods in a jpeg_error_mgr object.
|
||||||
|
* Typical call is:
|
||||||
|
* struct jpeg_compress_struct cinfo;
|
||||||
|
* struct jpeg_error_mgr err;
|
||||||
|
*
|
||||||
|
* cinfo.err = jpeg_std_error(&err);
|
||||||
|
* after which the application may override some of the methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(struct jpeg_error_mgr *)
|
||||||
|
jpeg_std_error (struct jpeg_error_mgr * err)
|
||||||
|
{
|
||||||
|
err->error_exit = error_exit;
|
||||||
|
err->emit_message = emit_message;
|
||||||
|
err->output_message = output_message;
|
||||||
|
err->format_message = format_message;
|
||||||
|
err->reset_error_mgr = reset_error_mgr;
|
||||||
|
|
||||||
|
err->trace_level = 0; /* default = no tracing */
|
||||||
|
err->num_warnings = 0; /* no warnings emitted yet */
|
||||||
|
err->msg_code = 0; /* may be useful as a flag for "no error" */
|
||||||
|
|
||||||
|
/* Initialize message table pointers */
|
||||||
|
err->jpeg_message_table = jpeg_std_message_table;
|
||||||
|
err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
|
||||||
|
|
||||||
|
err->addon_message_table = NULL;
|
||||||
|
err->first_addon_message = 0; /* for safety */
|
||||||
|
err->last_addon_message = 0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
290
jpeg-6b/jerror.h
Normal file
290
jpeg-6b/jerror.h
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
* jerror.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file defines the error and message codes for the JPEG library.
|
||||||
|
* Edit this file to add new codes, or to translate the message strings to
|
||||||
|
* some other language.
|
||||||
|
* A set of error-reporting macros are defined too. Some applications using
|
||||||
|
* the JPEG library may wish to include this file to get the error codes
|
||||||
|
* and/or the macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To define the enum list of message codes, include this file without
|
||||||
|
* defining 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 JERROR_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 /* JERROR_H */
|
||||||
|
#endif /* JMESSAGE */
|
||||||
|
|
||||||
|
#ifdef JMAKE_ENUM_LIST
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
|
||||||
|
#define JMESSAGE(code,string) code ,
|
||||||
|
|
||||||
|
#endif /* JMAKE_ENUM_LIST */
|
||||||
|
|
||||||
|
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
|
||||||
|
|
||||||
|
/* For maintenance convenience, list is alphabetical by message code name */
|
||||||
|
JMESSAGE(JERR_ARITH_NOTIMPL,
|
||||||
|
"Sorry, there are legal restrictions on arithmetic coding")
|
||||||
|
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
|
||||||
|
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
|
||||||
|
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||||
|
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
|
||||||
|
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||||
|
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
|
||||||
|
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
|
||||||
|
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
|
||||||
|
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
|
||||||
|
JMESSAGE(JERR_BAD_LIB_VERSION,
|
||||||
|
"Wrong JPEG library version: library is %d, caller expects %d")
|
||||||
|
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
|
||||||
|
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
|
||||||
|
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||||
|
JMESSAGE(JERR_BAD_PROGRESSION,
|
||||||
|
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||||
|
JMESSAGE(JERR_BAD_PROG_SCRIPT,
|
||||||
|
"Invalid progressive parameters at scan script entry %d")
|
||||||
|
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
|
||||||
|
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||||
|
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||||
|
JMESSAGE(JERR_BAD_STRUCT_SIZE,
|
||||||
|
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
|
||||||
|
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
|
||||||
|
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
|
||||||
|
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
|
||||||
|
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
|
||||||
|
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
|
||||||
|
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
|
||||||
|
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
|
||||||
|
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
|
||||||
|
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
|
||||||
|
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
|
||||||
|
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
|
||||||
|
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
|
||||||
|
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
|
||||||
|
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
|
||||||
|
JMESSAGE(JERR_FILE_READ, "Input file read error")
|
||||||
|
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
|
||||||
|
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
|
||||||
|
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
|
||||||
|
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
|
||||||
|
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
|
||||||
|
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
|
||||||
|
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
|
||||||
|
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
|
||||||
|
"Cannot transcode due to multiple use of quantization table %d")
|
||||||
|
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
|
||||||
|
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
|
||||||
|
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
|
||||||
|
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
|
||||||
|
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
|
||||||
|
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
|
||||||
|
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
|
||||||
|
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
|
||||||
|
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
|
||||||
|
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
|
||||||
|
JMESSAGE(JERR_QUANT_COMPONENTS,
|
||||||
|
"Cannot quantize more than %d color components")
|
||||||
|
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
|
||||||
|
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
|
||||||
|
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
|
||||||
|
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
|
||||||
|
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
|
||||||
|
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
|
||||||
|
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
|
||||||
|
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
|
||||||
|
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
|
||||||
|
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
|
||||||
|
JMESSAGE(JERR_TFILE_WRITE,
|
||||||
|
"Write failed on temporary file --- out of disk space?")
|
||||||
|
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
|
||||||
|
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
|
||||||
|
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
|
||||||
|
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
|
||||||
|
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
|
||||||
|
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
|
||||||
|
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
|
||||||
|
JMESSAGE(JMSG_VERSION, JVERSION)
|
||||||
|
JMESSAGE(JTRC_16BIT_TABLES,
|
||||||
|
"Caution: quantization tables are too coarse for baseline JPEG")
|
||||||
|
JMESSAGE(JTRC_ADOBE,
|
||||||
|
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
|
||||||
|
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
|
||||||
|
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
|
||||||
|
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
|
||||||
|
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
|
||||||
|
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
|
||||||
|
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
|
||||||
|
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
|
||||||
|
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
|
||||||
|
JMESSAGE(JTRC_EOI, "End Of Image")
|
||||||
|
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
|
||||||
|
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
|
||||||
|
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
|
||||||
|
"Warning: thumbnail image size does not match data length %u")
|
||||||
|
JMESSAGE(JTRC_JFIF_EXTENSION,
|
||||||
|
"JFIF extension marker: type 0x%02x, length %u")
|
||||||
|
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
|
||||||
|
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
|
||||||
|
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
|
||||||
|
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
|
||||||
|
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
|
||||||
|
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
|
||||||
|
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
|
||||||
|
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
|
||||||
|
JMESSAGE(JTRC_RST, "RST%d")
|
||||||
|
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
|
||||||
|
"Smoothing not supported with nonstandard sampling ratios")
|
||||||
|
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
|
||||||
|
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
|
||||||
|
JMESSAGE(JTRC_SOI, "Start of Image")
|
||||||
|
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
|
||||||
|
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
|
||||||
|
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
|
||||||
|
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
|
||||||
|
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
|
||||||
|
JMESSAGE(JTRC_THUMB_JPEG,
|
||||||
|
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
|
||||||
|
JMESSAGE(JTRC_THUMB_PALETTE,
|
||||||
|
"JFIF extension marker: palette thumbnail image, length %u")
|
||||||
|
JMESSAGE(JTRC_THUMB_RGB,
|
||||||
|
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||||
|
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||||
|
"Unrecognized component IDs %d %d %d, assuming YCbCr")
|
||||||
|
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
|
||||||
|
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||||
|
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
||||||
|
JMESSAGE(JWRN_BOGUS_PROGRESSION,
|
||||||
|
"Inconsistent progression sequence for component %d coefficient %d")
|
||||||
|
JMESSAGE(JWRN_EXTRANEOUS_DATA,
|
||||||
|
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
|
||||||
|
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
|
||||||
|
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
|
||||||
|
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
|
||||||
|
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
|
||||||
|
JMESSAGE(JWRN_MUST_RESYNC,
|
||||||
|
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
|
||||||
|
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
|
||||||
|
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
|
||||||
|
|
||||||
|
#ifdef JMAKE_ENUM_LIST
|
||||||
|
|
||||||
|
JMSG_LASTMSGCODE
|
||||||
|
} J_MESSAGE_CODE;
|
||||||
|
|
||||||
|
#undef JMAKE_ENUM_LIST
|
||||||
|
#endif /* JMAKE_ENUM_LIST */
|
||||||
|
|
||||||
|
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
|
||||||
|
#undef JMESSAGE
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JERROR_H
|
||||||
|
#define JERROR_H
|
||||||
|
|
||||||
|
/* Macros to simplify using the error and trace message stuff */
|
||||||
|
/* The first parameter is either type of cinfo pointer */
|
||||||
|
|
||||||
|
/* Fatal errors (print message and exit) */
|
||||||
|
#define ERREXIT(cinfo,code) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
#define ERREXIT1(cinfo,code,p1) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
#define ERREXIT2(cinfo,code,p1,p2) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
#define ERREXIT3(cinfo,code,p1,p2,p3) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||||
|
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||||
|
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||||
|
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
#define ERREXITS(cinfo,code,str) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||||
|
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||||
|
|
||||||
|
#define MAKESTMT(stuff) do { stuff } while (0)
|
||||||
|
|
||||||
|
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
|
||||||
|
#define WARNMS(cinfo,code) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||||
|
#define WARNMS1(cinfo,code,p1) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||||
|
#define WARNMS2(cinfo,code,p1,p2) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||||
|
|
||||||
|
/* Informational/debugging messages */
|
||||||
|
#define TRACEMS(cinfo,lvl,code) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||||
|
#define TRACEMS1(cinfo,lvl,code,p1) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||||
|
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||||
|
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||||
|
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
|
||||||
|
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||||
|
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
|
||||||
|
(cinfo)->err->msg_code = (code); \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||||
|
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
|
||||||
|
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||||
|
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||||
|
(cinfo)->err->msg_code = (code); \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||||
|
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
|
||||||
|
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||||
|
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||||
|
_mp[4] = (p5); \
|
||||||
|
(cinfo)->err->msg_code = (code); \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||||
|
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
|
||||||
|
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||||
|
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||||
|
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
|
||||||
|
(cinfo)->err->msg_code = (code); \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||||
|
#define TRACEMSS(cinfo,lvl,code,str) \
|
||||||
|
((cinfo)->err->msg_code = (code), \
|
||||||
|
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||||
|
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||||
|
|
||||||
|
#endif /* JERROR_H */
|
389
jpeg-6b/jidctint.c
Normal file
389
jpeg-6b/jidctint.c
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
/*
|
||||||
|
* jidctint.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains a slow-but-accurate integer implementation of the
|
||||||
|
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
|
||||||
|
* must also perform dequantization of the input coefficients.
|
||||||
|
*
|
||||||
|
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
|
||||||
|
* on each row (or vice versa, but it's more convenient to emit a row at
|
||||||
|
* a time). Direct algorithms are also available, but they are much more
|
||||||
|
* complex and seem not to be any faster when reduced to code.
|
||||||
|
*
|
||||||
|
* This implementation is based on an algorithm described in
|
||||||
|
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
|
||||||
|
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
|
||||||
|
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
|
||||||
|
* The primary algorithm described there uses 11 multiplies and 29 adds.
|
||||||
|
* We use their alternate method with 12 multiplies and 32 adds.
|
||||||
|
* The advantage of this method is that no data path contains more than one
|
||||||
|
* multiplication; this allows a very simple and accurate implementation in
|
||||||
|
* scaled fixed-point arithmetic, with a minimal number of shifts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||||
|
|
||||||
|
#ifdef DCT_ISLOW_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This module is specialized to the case DCTSIZE = 8.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if DCTSIZE != 8
|
||||||
|
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The poop on this scaling stuff is as follows:
|
||||||
|
*
|
||||||
|
* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
|
||||||
|
* larger than the true IDCT outputs. The final outputs are therefore
|
||||||
|
* a factor of N larger than desired; since N=8 this can be cured by
|
||||||
|
* a simple right shift at the end of the algorithm. The advantage of
|
||||||
|
* this arrangement is that we save two multiplications per 1-D IDCT,
|
||||||
|
* because the y0 and y4 inputs need not be divided by sqrt(N).
|
||||||
|
*
|
||||||
|
* We have to do addition and subtraction of the integer inputs, which
|
||||||
|
* is no problem, and multiplication by fractional constants, which is
|
||||||
|
* a problem to do in integer arithmetic. We multiply all the constants
|
||||||
|
* by CONST_SCALE and convert them to integer constants (thus retaining
|
||||||
|
* CONST_BITS bits of precision in the constants). After doing a
|
||||||
|
* multiplication we have to divide the product by CONST_SCALE, with proper
|
||||||
|
* rounding, to produce the correct output. This division can be done
|
||||||
|
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
|
||||||
|
* as long as possible so that partial sums can be added together with
|
||||||
|
* full fractional precision.
|
||||||
|
*
|
||||||
|
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
|
||||||
|
* they are represented to better-than-integral precision. These outputs
|
||||||
|
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
|
||||||
|
* with the recommended scaling. (To scale up 12-bit sample data further, an
|
||||||
|
* intermediate INT32 array would be needed.)
|
||||||
|
*
|
||||||
|
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
|
||||||
|
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
|
||||||
|
* shows that the values given below are the most effective.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
#define CONST_BITS 13
|
||||||
|
#define PASS1_BITS 2
|
||||||
|
#else
|
||||||
|
#define CONST_BITS 13
|
||||||
|
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
|
||||||
|
* causing a lot of useless floating-point operations at run time.
|
||||||
|
* To get around this we use the following pre-calculated constants.
|
||||||
|
* If you change CONST_BITS you may want to add appropriate values.
|
||||||
|
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if CONST_BITS == 13
|
||||||
|
#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
|
||||||
|
#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
|
||||||
|
#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
|
||||||
|
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
|
||||||
|
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
|
||||||
|
#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
|
||||||
|
#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
|
||||||
|
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
|
||||||
|
#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
|
||||||
|
#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
|
||||||
|
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
|
||||||
|
#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
|
||||||
|
#else
|
||||||
|
#define FIX_0_298631336 FIX(0.298631336)
|
||||||
|
#define FIX_0_390180644 FIX(0.390180644)
|
||||||
|
#define FIX_0_541196100 FIX(0.541196100)
|
||||||
|
#define FIX_0_765366865 FIX(0.765366865)
|
||||||
|
#define FIX_0_899976223 FIX(0.899976223)
|
||||||
|
#define FIX_1_175875602 FIX(1.175875602)
|
||||||
|
#define FIX_1_501321110 FIX(1.501321110)
|
||||||
|
#define FIX_1_847759065 FIX(1.847759065)
|
||||||
|
#define FIX_1_961570560 FIX(1.961570560)
|
||||||
|
#define FIX_2_053119869 FIX(2.053119869)
|
||||||
|
#define FIX_2_562915447 FIX(2.562915447)
|
||||||
|
#define FIX_3_072711026 FIX(3.072711026)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
|
||||||
|
* For 8-bit samples with the recommended scaling, all the variable
|
||||||
|
* and constant values involved are no more than 16 bits wide, so a
|
||||||
|
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
|
||||||
|
* For 12-bit samples, a full 32-bit multiplication will be needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
|
||||||
|
#else
|
||||||
|
#define MULTIPLY(var,const) ((var) * (const))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Dequantize a coefficient by multiplying it by the multiplier-table
|
||||||
|
* entry; produce an int result. In this module, both inputs and result
|
||||||
|
* are 16 bits or less, so either int or short multiply will work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform dequantization and inverse DCT on one block of coefficients.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION output_col)
|
||||||
|
{
|
||||||
|
INT32 tmp0, tmp1, tmp2, tmp3;
|
||||||
|
INT32 tmp10, tmp11, tmp12, tmp13;
|
||||||
|
INT32 z1, z2, z3, z4, z5;
|
||||||
|
JCOEFPTR inptr;
|
||||||
|
ISLOW_MULT_TYPE * quantptr;
|
||||||
|
int * wsptr;
|
||||||
|
JSAMPROW outptr;
|
||||||
|
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
|
||||||
|
int ctr;
|
||||||
|
int workspace[DCTSIZE2]; /* buffers data between passes */
|
||||||
|
SHIFT_TEMPS
|
||||||
|
|
||||||
|
/* Pass 1: process columns from input, store into work array. */
|
||||||
|
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
|
||||||
|
/* furthermore, we scale the results by 2**PASS1_BITS. */
|
||||||
|
|
||||||
|
inptr = coef_block;
|
||||||
|
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
|
||||||
|
wsptr = workspace;
|
||||||
|
for (ctr = DCTSIZE; ctr > 0; ctr--) {
|
||||||
|
/* Due to quantization, we will usually find that many of the input
|
||||||
|
* coefficients are zero, especially the AC terms. We can exploit this
|
||||||
|
* by short-circuiting the IDCT calculation for any column in which all
|
||||||
|
* the AC terms are zero. In that case each output is equal to the
|
||||||
|
* DC coefficient (with scale factor as needed).
|
||||||
|
* With typical images and quantization tables, half or more of the
|
||||||
|
* column DCT calculations can be simplified this way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
|
||||||
|
inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
|
||||||
|
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
|
||||||
|
inptr[DCTSIZE*7] == 0) {
|
||||||
|
/* AC terms all zero */
|
||||||
|
int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
|
||||||
|
|
||||||
|
wsptr[DCTSIZE*0] = dcval;
|
||||||
|
wsptr[DCTSIZE*1] = dcval;
|
||||||
|
wsptr[DCTSIZE*2] = dcval;
|
||||||
|
wsptr[DCTSIZE*3] = dcval;
|
||||||
|
wsptr[DCTSIZE*4] = dcval;
|
||||||
|
wsptr[DCTSIZE*5] = dcval;
|
||||||
|
wsptr[DCTSIZE*6] = dcval;
|
||||||
|
wsptr[DCTSIZE*7] = dcval;
|
||||||
|
|
||||||
|
inptr++; /* advance pointers to next column */
|
||||||
|
quantptr++;
|
||||||
|
wsptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Even part: reverse the even part of the forward DCT. */
|
||||||
|
/* The rotator is sqrt(2)*c(-6). */
|
||||||
|
|
||||||
|
z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
|
||||||
|
z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
|
||||||
|
|
||||||
|
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
|
||||||
|
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
|
||||||
|
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
|
||||||
|
|
||||||
|
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
|
||||||
|
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
|
||||||
|
|
||||||
|
tmp0 = (z2 + z3) << CONST_BITS;
|
||||||
|
tmp1 = (z2 - z3) << CONST_BITS;
|
||||||
|
|
||||||
|
tmp10 = tmp0 + tmp3;
|
||||||
|
tmp13 = tmp0 - tmp3;
|
||||||
|
tmp11 = tmp1 + tmp2;
|
||||||
|
tmp12 = tmp1 - tmp2;
|
||||||
|
|
||||||
|
/* Odd part per figure 8; the matrix is unitary and hence its
|
||||||
|
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
|
||||||
|
tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
|
||||||
|
tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
|
||||||
|
tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
|
||||||
|
|
||||||
|
z1 = tmp0 + tmp3;
|
||||||
|
z2 = tmp1 + tmp2;
|
||||||
|
z3 = tmp0 + tmp2;
|
||||||
|
z4 = tmp1 + tmp3;
|
||||||
|
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
|
||||||
|
|
||||||
|
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
|
||||||
|
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
|
||||||
|
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
|
||||||
|
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
|
||||||
|
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
|
||||||
|
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
|
||||||
|
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
|
||||||
|
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
|
||||||
|
|
||||||
|
z3 += z5;
|
||||||
|
z4 += z5;
|
||||||
|
|
||||||
|
tmp0 += z1 + z3;
|
||||||
|
tmp1 += z2 + z4;
|
||||||
|
tmp2 += z2 + z3;
|
||||||
|
tmp3 += z1 + z4;
|
||||||
|
|
||||||
|
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
|
||||||
|
|
||||||
|
wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
|
||||||
|
wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
|
||||||
|
|
||||||
|
inptr++; /* advance pointers to next column */
|
||||||
|
quantptr++;
|
||||||
|
wsptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass 2: process rows from work array, store into output array. */
|
||||||
|
/* Note that we must descale the results by a factor of 8 == 2**3, */
|
||||||
|
/* and also undo the PASS1_BITS scaling. */
|
||||||
|
|
||||||
|
wsptr = workspace;
|
||||||
|
for (ctr = 0; ctr < DCTSIZE; ctr++) {
|
||||||
|
outptr = output_buf[ctr] + output_col;
|
||||||
|
/* Rows of zeroes can be exploited in the same way as we did with columns.
|
||||||
|
* However, the column calculation has created many nonzero AC terms, so
|
||||||
|
* the simplification applies less often (typically 5% to 10% of the time).
|
||||||
|
* On machines with very fast multiplication, it's possible that the
|
||||||
|
* test takes more time than it's worth. In that case this section
|
||||||
|
* may be commented out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_ZERO_ROW_TEST
|
||||||
|
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
|
||||||
|
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
|
||||||
|
/* AC terms all zero */
|
||||||
|
JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
|
||||||
|
outptr[0] = dcval;
|
||||||
|
outptr[1] = dcval;
|
||||||
|
outptr[2] = dcval;
|
||||||
|
outptr[3] = dcval;
|
||||||
|
outptr[4] = dcval;
|
||||||
|
outptr[5] = dcval;
|
||||||
|
outptr[6] = dcval;
|
||||||
|
outptr[7] = dcval;
|
||||||
|
|
||||||
|
wsptr += DCTSIZE; /* advance pointer to next row */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Even part: reverse the even part of the forward DCT. */
|
||||||
|
/* The rotator is sqrt(2)*c(-6). */
|
||||||
|
|
||||||
|
z2 = (INT32) wsptr[2];
|
||||||
|
z3 = (INT32) wsptr[6];
|
||||||
|
|
||||||
|
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
|
||||||
|
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
|
||||||
|
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
|
||||||
|
|
||||||
|
tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
|
||||||
|
tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
|
||||||
|
|
||||||
|
tmp10 = tmp0 + tmp3;
|
||||||
|
tmp13 = tmp0 - tmp3;
|
||||||
|
tmp11 = tmp1 + tmp2;
|
||||||
|
tmp12 = tmp1 - tmp2;
|
||||||
|
|
||||||
|
/* Odd part per figure 8; the matrix is unitary and hence its
|
||||||
|
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tmp0 = (INT32) wsptr[7];
|
||||||
|
tmp1 = (INT32) wsptr[5];
|
||||||
|
tmp2 = (INT32) wsptr[3];
|
||||||
|
tmp3 = (INT32) wsptr[1];
|
||||||
|
|
||||||
|
z1 = tmp0 + tmp3;
|
||||||
|
z2 = tmp1 + tmp2;
|
||||||
|
z3 = tmp0 + tmp2;
|
||||||
|
z4 = tmp1 + tmp3;
|
||||||
|
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
|
||||||
|
|
||||||
|
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
|
||||||
|
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
|
||||||
|
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
|
||||||
|
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
|
||||||
|
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
|
||||||
|
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
|
||||||
|
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
|
||||||
|
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
|
||||||
|
|
||||||
|
z3 += z5;
|
||||||
|
z4 += z5;
|
||||||
|
|
||||||
|
tmp0 += z1 + z3;
|
||||||
|
tmp1 += z2 + z4;
|
||||||
|
tmp2 += z2 + z3;
|
||||||
|
tmp3 += z1 + z4;
|
||||||
|
|
||||||
|
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
|
||||||
|
|
||||||
|
outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
|
||||||
|
CONST_BITS+PASS1_BITS+3)
|
||||||
|
& RANGE_MASK];
|
||||||
|
|
||||||
|
wsptr += DCTSIZE; /* advance pointer to next row */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DCT_ISLOW_SUPPORTED */
|
91
jpeg-6b/jinclude.h
Normal file
91
jpeg-6b/jinclude.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* jinclude.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file exists to provide a single place to fix any problems with
|
||||||
|
* including the wrong system include files. (Common problems are taken
|
||||||
|
* care of by the standard jconfig symbols, but on really weird systems
|
||||||
|
* you may have to edit this file.)
|
||||||
|
*
|
||||||
|
* NOTE: this file is NOT intended to be included by applications using the
|
||||||
|
* JPEG library. Most applications need only include jpeglib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Include auto-config file to find out which system include files we need. */
|
||||||
|
|
||||||
|
#include "jconfig.h" /* auto configuration options */
|
||||||
|
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need the NULL macro and size_t typedef.
|
||||||
|
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
|
||||||
|
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
|
||||||
|
* pull in <sys/types.h> as well.
|
||||||
|
* Note that the core JPEG library does not require <stdio.h>;
|
||||||
|
* only the default error handler and data source/destination modules do.
|
||||||
|
* But we must pull it in because of the references to FILE in jpeglib.h.
|
||||||
|
* You can remove those references if you want to compile without <stdio.h>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_STDDEF_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need memory copying and zeroing functions, plus strncpy().
|
||||||
|
* ANSI and System V implementations declare these in <string.h>.
|
||||||
|
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||||
|
* Some systems may declare memset and memcpy in <memory.h>.
|
||||||
|
*
|
||||||
|
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||||
|
* Change the casts in these macros if not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef NEED_BSD_STRINGS
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
|
||||||
|
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
|
||||||
|
|
||||||
|
#else /* not BSD, assume ANSI/SysV string lib */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
|
||||||
|
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||||
|
* type returned by sizeof(). However, it seems there are some irrational
|
||||||
|
* implementations out there, in which sizeof() returns an int even though
|
||||||
|
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||||
|
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The modules that use fread() and fwrite() always invoke them through
|
||||||
|
* these macros. On some systems you may need to twiddle the argument casts.
|
||||||
|
* CAUTION: argument order is different from underlying functions!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JFREAD(file,buf,sizeofbuf) \
|
||||||
|
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||||
|
#define JFWRITE(file,buf,sizeofbuf) \
|
||||||
|
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
652
jpeg-6b/jmemmgr.c
Normal file
652
jpeg-6b/jmemmgr.c
Normal file
|
@ -0,0 +1,652 @@
|
||||||
|
/*
|
||||||
|
* jmemmgr.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 the JPEG system-independent memory management
|
||||||
|
* routines. This code is usable across a wide variety of machines; most
|
||||||
|
* of the system dependencies have been isolated in a separate file.
|
||||||
|
* The major functions provided here are:
|
||||||
|
* * pool-based allocation and freeing of memory;
|
||||||
|
* * policy decisions about how to divide available memory among the
|
||||||
|
* virtual arrays;
|
||||||
|
* * control logic for swapping virtual arrays between main memory and
|
||||||
|
* backing storage.
|
||||||
|
* The separate system-dependent file provides the actual backing-storage
|
||||||
|
* access code, and it contains the policy decision about how much total
|
||||||
|
* main memory to use.
|
||||||
|
* This file is system-dependent in the sense that some of its functions
|
||||||
|
* are unnecessary in some systems. For example, if there is enough virtual
|
||||||
|
* memory so that backing storage will never be used, much of the virtual
|
||||||
|
* array control logic could be removed. (Of course, if you have that much
|
||||||
|
* memory then you shouldn't care about a little bit of unused code...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some important notes:
|
||||||
|
* The allocation routines provided here must never return NULL.
|
||||||
|
* They should exit to error_exit if unsuccessful.
|
||||||
|
*
|
||||||
|
* It's not a good idea to try to merge the sarray and barray routines,
|
||||||
|
* even though they are textually almost the same, because samples are
|
||||||
|
* usually stored as bytes while coefficients are shorts or ints. Thus,
|
||||||
|
* in machines where byte pointers have a different representation from
|
||||||
|
* word pointers, the resulting machine code could not be the same.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Many machines require storage alignment: longs must start on 4-byte
|
||||||
|
* boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc()
|
||||||
|
* always returns pointers that are multiples of the worst-case alignment
|
||||||
|
* requirement, and we had better do so too.
|
||||||
|
* There isn't any really portable way to determine the worst-case alignment
|
||||||
|
* requirement. This module assumes that the alignment requirement is
|
||||||
|
* multiples of sizeof(ALIGN_TYPE).
|
||||||
|
* By default, we define ALIGN_TYPE as double. This is necessary on some
|
||||||
|
* workstations (where doubles really do need 8-byte alignment) and will work
|
||||||
|
* fine on nearly everything. If your machine has lesser alignment needs,
|
||||||
|
* you can save a few bytes by making ALIGN_TYPE smaller.
|
||||||
|
* The only place I know of where this will NOT work is certain Macintosh
|
||||||
|
* 680x0 compilers that define double as a 10-byte IEEE extended float.
|
||||||
|
* Doing 10-byte alignment is counterproductive because longwords won't be
|
||||||
|
* aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have
|
||||||
|
* such a compiler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ALIGN_TYPE /* so can override from jconfig.h */
|
||||||
|
#define ALIGN_TYPE double
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We allocate objects from "pools", where each pool is gotten with a single
|
||||||
|
* request to jpeg_get_small() or jpeg_get_large(). There is no per-object
|
||||||
|
* overhead within a pool, except for alignment padding. Each pool has a
|
||||||
|
* header with a link to the next pool of the same class.
|
||||||
|
* Small and large pool headers are identical except that the latter's
|
||||||
|
* link pointer must be FAR on 80x86 machines.
|
||||||
|
* Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
|
||||||
|
* field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
|
||||||
|
* of the alignment requirement of ALIGN_TYPE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef union small_pool_struct * small_pool_ptr;
|
||||||
|
|
||||||
|
typedef union small_pool_struct {
|
||||||
|
struct {
|
||||||
|
small_pool_ptr next; /* next in list of pools */
|
||||||
|
size_t bytes_used; /* how many bytes already used within pool */
|
||||||
|
size_t bytes_left; /* bytes still available in this pool */
|
||||||
|
} hdr;
|
||||||
|
ALIGN_TYPE dummy; /* included in union to ensure alignment */
|
||||||
|
} small_pool_hdr;
|
||||||
|
|
||||||
|
typedef union large_pool_struct * large_pool_ptr;
|
||||||
|
|
||||||
|
typedef union large_pool_struct {
|
||||||
|
struct {
|
||||||
|
large_pool_ptr next; /* next in list of pools */
|
||||||
|
size_t bytes_used; /* how many bytes already used within pool */
|
||||||
|
size_t bytes_left; /* bytes still available in this pool */
|
||||||
|
} hdr;
|
||||||
|
ALIGN_TYPE dummy; /* included in union to ensure alignment */
|
||||||
|
} large_pool_hdr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here is the full definition of a memory manager object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct jpeg_memory_mgr pub; /* public fields */
|
||||||
|
|
||||||
|
/* Each pool identifier (lifetime class) names a linked list of pools. */
|
||||||
|
small_pool_ptr small_list[JPOOL_NUMPOOLS];
|
||||||
|
large_pool_ptr large_list[JPOOL_NUMPOOLS];
|
||||||
|
|
||||||
|
/* Since we only have one lifetime class of virtual arrays, only one
|
||||||
|
* linked list is necessary (for each datatype). Note that the virtual
|
||||||
|
* array control blocks being linked together are actually stored somewhere
|
||||||
|
* in the small-pool list.
|
||||||
|
*/
|
||||||
|
jvirt_barray_ptr virt_barray_list;
|
||||||
|
|
||||||
|
/* alloc_sarray and alloc_barray set this value for use by virtual
|
||||||
|
* array routines.
|
||||||
|
*/
|
||||||
|
JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
|
||||||
|
} my_memory_mgr;
|
||||||
|
|
||||||
|
typedef my_memory_mgr * my_mem_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The control blocks for virtual arrays.
|
||||||
|
* Note that these blocks are allocated in the "small" pool area.
|
||||||
|
* System-dependent info for the associated backing store (if any) is hidden
|
||||||
|
* inside the backing_store_info struct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct jvirt_barray_control {
|
||||||
|
JBLOCKARRAY mem_buffer; /* => the in-memory buffer */
|
||||||
|
JDIMENSION rows_in_array; /* total virtual array height */
|
||||||
|
JDIMENSION blocksperrow; /* width of array (and of memory buffer) */
|
||||||
|
JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */
|
||||||
|
JDIMENSION rows_in_mem; /* height of memory buffer */
|
||||||
|
JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
|
||||||
|
JDIMENSION cur_start_row; /* first logical row # in the buffer */
|
||||||
|
JDIMENSION first_undef_row; /* row # of first uninitialized row */
|
||||||
|
boolean pre_zero; /* pre-zero mode requested? */
|
||||||
|
boolean dirty; /* do current buffer contents need written? */
|
||||||
|
jvirt_barray_ptr next; /* link to next virtual barray control block */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LOCAL(void)
|
||||||
|
out_of_memory (j_common_ptr cinfo, int which)
|
||||||
|
/* Report an out-of-memory error and stop execution */
|
||||||
|
{
|
||||||
|
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocation of "small" objects.
|
||||||
|
*
|
||||||
|
* For these, we use pooled storage. When a new pool must be created,
|
||||||
|
* we try to get enough space for the current request plus a "slop" factor,
|
||||||
|
* where the slop will be the amount of leftover space in the new pool.
|
||||||
|
* The speed vs. space tradeoff is largely determined by the slop values.
|
||||||
|
* A different slop value is provided for each pool class (lifetime),
|
||||||
|
* and we also distinguish the first pool of a class from later ones.
|
||||||
|
* NOTE: the values given work fairly well on both 16- and 32-bit-int
|
||||||
|
* machines, but may be too small if longs are 64 bits or more.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
|
||||||
|
{
|
||||||
|
1600, /* first PERMANENT pool */
|
||||||
|
16000 /* first IMAGE pool */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
|
||||||
|
{
|
||||||
|
0, /* additional PERMANENT pools */
|
||||||
|
5000 /* additional IMAGE pools */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(void *)
|
||||||
|
alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
|
||||||
|
/* Allocate a "small" object */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
small_pool_ptr hdr_ptr, prev_hdr_ptr;
|
||||||
|
char * data_ptr;
|
||||||
|
size_t odd_bytes, min_request, slop;
|
||||||
|
|
||||||
|
/* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
|
||||||
|
odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
|
||||||
|
if (odd_bytes > 0)
|
||||||
|
sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
|
||||||
|
|
||||||
|
/* See if space is available in any existing pool */
|
||||||
|
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
|
||||||
|
prev_hdr_ptr = NULL;
|
||||||
|
hdr_ptr = mem->small_list[pool_id];
|
||||||
|
while (hdr_ptr != NULL) {
|
||||||
|
if (hdr_ptr->hdr.bytes_left >= sizeofobject)
|
||||||
|
break; /* found pool with enough space */
|
||||||
|
prev_hdr_ptr = hdr_ptr;
|
||||||
|
hdr_ptr = hdr_ptr->hdr.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Time to make a new pool? */
|
||||||
|
if (hdr_ptr == NULL) {
|
||||||
|
/* min_request is what we need now, slop is what will be leftover */
|
||||||
|
min_request = sizeofobject + SIZEOF(small_pool_hdr);
|
||||||
|
if (prev_hdr_ptr == NULL) /* first pool in class? */
|
||||||
|
slop = first_pool_slop[pool_id];
|
||||||
|
else
|
||||||
|
slop = extra_pool_slop[pool_id];
|
||||||
|
/* Try to get space, if fail reduce slop and try again */
|
||||||
|
for (;;) {
|
||||||
|
hdr_ptr = (small_pool_ptr) malloc(min_request + slop);
|
||||||
|
if (hdr_ptr != NULL)
|
||||||
|
break;
|
||||||
|
slop /= 2;
|
||||||
|
if (slop < MIN_SLOP) /* give up when it gets real small */
|
||||||
|
out_of_memory(cinfo, 2); /* jpeg_get_small failed */
|
||||||
|
}
|
||||||
|
/* Success, initialize the new pool header and add to end of list */
|
||||||
|
hdr_ptr->hdr.next = NULL;
|
||||||
|
hdr_ptr->hdr.bytes_used = 0;
|
||||||
|
hdr_ptr->hdr.bytes_left = sizeofobject + slop;
|
||||||
|
if (prev_hdr_ptr == NULL) /* first pool in class? */
|
||||||
|
mem->small_list[pool_id] = hdr_ptr;
|
||||||
|
else
|
||||||
|
prev_hdr_ptr->hdr.next = hdr_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, allocate the object from the current pool */
|
||||||
|
data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
|
||||||
|
data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
|
||||||
|
hdr_ptr->hdr.bytes_used += sizeofobject;
|
||||||
|
hdr_ptr->hdr.bytes_left -= sizeofobject;
|
||||||
|
|
||||||
|
return (void *) data_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocation of "large" objects.
|
||||||
|
*
|
||||||
|
* The external semantics of these are the same as "small" objects,
|
||||||
|
* except that FAR pointers are used on 80x86. However the pool
|
||||||
|
* management heuristics are quite different. We assume that each
|
||||||
|
* request is large enough that it may as well be passed directly to
|
||||||
|
* jpeg_get_large; the pool management just links everything together
|
||||||
|
* so that we can free it all on demand.
|
||||||
|
* Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
|
||||||
|
* structures. The routines that create these structures (see below)
|
||||||
|
* deliberately bunch rows together to ensure a large request size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void *)
|
||||||
|
alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
|
||||||
|
/* Allocate a "large" object */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
large_pool_ptr hdr_ptr;
|
||||||
|
size_t odd_bytes;
|
||||||
|
|
||||||
|
/* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
|
||||||
|
odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
|
||||||
|
if (odd_bytes > 0)
|
||||||
|
sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
|
||||||
|
|
||||||
|
/* Always make a new pool */
|
||||||
|
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
|
||||||
|
|
||||||
|
hdr_ptr = (large_pool_ptr) malloc(sizeofobject + SIZEOF(large_pool_hdr));
|
||||||
|
if (hdr_ptr == NULL)
|
||||||
|
out_of_memory(cinfo, 4); /* jpeg_get_large failed */
|
||||||
|
|
||||||
|
/* Success, initialize the new pool header and add to list */
|
||||||
|
hdr_ptr->hdr.next = mem->large_list[pool_id];
|
||||||
|
/* We maintain space counts in each pool header for statistical purposes,
|
||||||
|
* even though they are not needed for allocation.
|
||||||
|
*/
|
||||||
|
hdr_ptr->hdr.bytes_used = sizeofobject;
|
||||||
|
hdr_ptr->hdr.bytes_left = 0;
|
||||||
|
mem->large_list[pool_id] = hdr_ptr;
|
||||||
|
|
||||||
|
return (void *) (hdr_ptr + 1); /* point to first data byte in pool */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creation of 2-D sample arrays.
|
||||||
|
* The pointers are in near heap, the samples themselves in FAR heap.
|
||||||
|
*
|
||||||
|
* To minimize allocation overhead and to allow I/O of large contiguous
|
||||||
|
* blocks, we allocate the sample rows in groups of as many rows as possible
|
||||||
|
* without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
|
||||||
|
* NB: the virtual array control routines, later in this file, know about
|
||||||
|
* this chunking of rows. The rowsperchunk value is left in the mem manager
|
||||||
|
* object so that it can be saved away if this sarray is the workspace for
|
||||||
|
* a virtual array.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(JSAMPARRAY)
|
||||||
|
alloc_sarray (j_common_ptr cinfo, int pool_id,
|
||||||
|
JDIMENSION samplesperrow, JDIMENSION numrows)
|
||||||
|
/* Allocate a 2-D sample array */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
JSAMPARRAY result;
|
||||||
|
JSAMPROW workspace;
|
||||||
|
JDIMENSION i;
|
||||||
|
|
||||||
|
/* Calculate max # of rows allowed in one allocation chunk */
|
||||||
|
mem->last_rowsperchunk = numrows;
|
||||||
|
|
||||||
|
/* Get space for row pointers (small object) */
|
||||||
|
result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
|
||||||
|
(size_t) (numrows * SIZEOF(JSAMPROW)));
|
||||||
|
|
||||||
|
/* Get the rows themselves (large objects) */
|
||||||
|
workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
|
||||||
|
(size_t) ((size_t) numrows * (size_t) samplesperrow
|
||||||
|
* SIZEOF(JSAMPLE)));
|
||||||
|
for (i = 0; i < numrows; i++) {
|
||||||
|
result[i] = workspace;
|
||||||
|
workspace += samplesperrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creation of 2-D coefficient-block arrays.
|
||||||
|
* This is essentially the same as the code for sample arrays, above.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(JBLOCKARRAY)
|
||||||
|
alloc_barray (j_common_ptr cinfo, int pool_id,
|
||||||
|
JDIMENSION blocksperrow, JDIMENSION numrows)
|
||||||
|
/* Allocate a 2-D coefficient-block array */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
JBLOCKARRAY result;
|
||||||
|
JBLOCKROW workspace;
|
||||||
|
JDIMENSION i;
|
||||||
|
|
||||||
|
/* Calculate max # of rows allowed in one allocation chunk */
|
||||||
|
mem->last_rowsperchunk = numrows;
|
||||||
|
|
||||||
|
/* Get space for row pointers (small object) */
|
||||||
|
result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
|
||||||
|
(size_t) (numrows * SIZEOF(JBLOCKROW)));
|
||||||
|
|
||||||
|
/* Get the rows themselves (large objects) */
|
||||||
|
workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
|
||||||
|
(size_t) ((size_t) numrows * (size_t) blocksperrow
|
||||||
|
* SIZEOF(JBLOCK)));
|
||||||
|
for (i = 0; i < numrows; i++) {
|
||||||
|
result[i] = workspace;
|
||||||
|
workspace += blocksperrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* About virtual array management:
|
||||||
|
*
|
||||||
|
* The above "normal" array routines are only used to allocate strip buffers
|
||||||
|
* (as wide as the image, but just a few rows high). Full-image-sized buffers
|
||||||
|
* are handled as "virtual" arrays. The array is still accessed a strip at a
|
||||||
|
* time, but the memory manager must save the whole array for repeated
|
||||||
|
* accesses. The intended implementation is that there is a strip buffer in
|
||||||
|
* memory (as high as is possible given the desired memory limit), plus a
|
||||||
|
* backing file that holds the rest of the array.
|
||||||
|
*
|
||||||
|
* The request_virt_array routines are told the total size of the image and
|
||||||
|
* the maximum number of rows that will be accessed at once. The in-memory
|
||||||
|
* buffer must be at least as large as the maxaccess value.
|
||||||
|
*
|
||||||
|
* The request routines create control blocks but not the in-memory buffers.
|
||||||
|
* That is postponed until realize_virt_arrays is called. At that time the
|
||||||
|
* total amount of space needed is known (approximately, anyway), so free
|
||||||
|
* memory can be divided up fairly.
|
||||||
|
*
|
||||||
|
* The access_virt_array routines are responsible for making a specific strip
|
||||||
|
* area accessible (after reading or writing the backing file, if necessary).
|
||||||
|
* Note that the access routines are told whether the caller intends to modify
|
||||||
|
* the accessed strip; during a read-only pass this saves having to rewrite
|
||||||
|
* data to disk. The access routines are also responsible for pre-zeroing
|
||||||
|
* any newly accessed rows, if pre-zeroing was requested.
|
||||||
|
*
|
||||||
|
* In current usage, the access requests are usually for nonoverlapping
|
||||||
|
* strips; that is, successive access start_row numbers differ by exactly
|
||||||
|
* num_rows = maxaccess. This means we can get good performance with simple
|
||||||
|
* buffer dump/reload logic, by making the in-memory buffer be a multiple
|
||||||
|
* of the access height; then there will never be accesses across bufferload
|
||||||
|
* boundaries. The code will still work with overlapping access requests,
|
||||||
|
* but it doesn't handle bufferload overlaps very efficiently.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(jvirt_barray_ptr)
|
||||||
|
request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
|
||||||
|
JDIMENSION blocksperrow, JDIMENSION numrows,
|
||||||
|
JDIMENSION maxaccess)
|
||||||
|
/* Request a virtual 2-D coefficient-block array */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
jvirt_barray_ptr result;
|
||||||
|
|
||||||
|
/* Only IMAGE-lifetime virtual arrays are currently supported */
|
||||||
|
if (pool_id != JPOOL_IMAGE)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
|
||||||
|
|
||||||
|
/* get control block */
|
||||||
|
result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
|
||||||
|
SIZEOF(struct jvirt_barray_control));
|
||||||
|
|
||||||
|
result->mem_buffer = NULL; /* marks array not yet realized */
|
||||||
|
result->rows_in_array = numrows;
|
||||||
|
result->blocksperrow = blocksperrow;
|
||||||
|
result->maxaccess = maxaccess;
|
||||||
|
result->pre_zero = pre_zero;
|
||||||
|
result->next = mem->virt_barray_list; /* add to list of virtual arrays */
|
||||||
|
mem->virt_barray_list = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
realize_virt_arrays (j_common_ptr cinfo)
|
||||||
|
/* Allocate the in-memory buffers for any unrealized virtual arrays */
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
long space_per_minheight;
|
||||||
|
long minheights;
|
||||||
|
jvirt_barray_ptr bptr;
|
||||||
|
|
||||||
|
/* Compute the minimum space needed (maxaccess rows in each buffer)
|
||||||
|
* and the maximum space needed (full image height in each buffer).
|
||||||
|
* These may be of use to the system-dependent jpeg_mem_available routine.
|
||||||
|
*/
|
||||||
|
space_per_minheight = 0;
|
||||||
|
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
|
||||||
|
if (bptr->mem_buffer == NULL) { /* if not realized yet */
|
||||||
|
space_per_minheight += (long) bptr->maxaccess *
|
||||||
|
(long) bptr->blocksperrow * SIZEOF(JBLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space_per_minheight <= 0)
|
||||||
|
return; /* no unrealized arrays, no work */
|
||||||
|
|
||||||
|
/* Allocate the in-memory buffers and initialize backing store as needed. */
|
||||||
|
|
||||||
|
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
|
||||||
|
if (bptr->mem_buffer == NULL) { /* if not realized yet */
|
||||||
|
minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
|
||||||
|
bptr->rows_in_mem = bptr->rows_in_array;
|
||||||
|
bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
|
||||||
|
bptr->blocksperrow, bptr->rows_in_mem);
|
||||||
|
bptr->rowsperchunk = mem->last_rowsperchunk;
|
||||||
|
bptr->cur_start_row = 0;
|
||||||
|
bptr->first_undef_row = 0;
|
||||||
|
bptr->dirty = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
METHODDEF(JBLOCKARRAY)
|
||||||
|
access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
|
||||||
|
JDIMENSION start_row, JDIMENSION num_rows,
|
||||||
|
boolean writable)
|
||||||
|
/* Access the part of a virtual block array starting at start_row */
|
||||||
|
/* and extending for num_rows rows. writable is true if */
|
||||||
|
/* caller intends to modify the accessed area. */
|
||||||
|
{
|
||||||
|
JDIMENSION end_row = start_row + num_rows;
|
||||||
|
JDIMENSION undef_row;
|
||||||
|
|
||||||
|
/* debugging check */
|
||||||
|
if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
|
||||||
|
ptr->mem_buffer == NULL)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
|
||||||
|
|
||||||
|
/* Make the desired part of the virtual array accessible */
|
||||||
|
if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row+ptr->rows_in_mem)
|
||||||
|
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
|
||||||
|
|
||||||
|
/* Ensure the accessed part of the array is defined; prezero if needed.
|
||||||
|
* To improve locality of access, we only prezero the part of the array
|
||||||
|
* that the caller is about to access, not the entire in-memory array.
|
||||||
|
*/
|
||||||
|
if (ptr->first_undef_row < end_row) {
|
||||||
|
if (ptr->first_undef_row < start_row) {
|
||||||
|
if (writable) /* writer skipped over a section of array */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
|
||||||
|
undef_row = start_row; /* but reader is allowed to read ahead */
|
||||||
|
} else {
|
||||||
|
undef_row = ptr->first_undef_row;
|
||||||
|
}
|
||||||
|
if (writable)
|
||||||
|
ptr->first_undef_row = end_row;
|
||||||
|
if (ptr->pre_zero) {
|
||||||
|
size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
|
||||||
|
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
|
||||||
|
end_row -= ptr->cur_start_row;
|
||||||
|
while (undef_row < end_row) {
|
||||||
|
MEMZERO((void *) ptr->mem_buffer[undef_row], bytesperrow);
|
||||||
|
undef_row++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (! writable) /* reader looking at undefined data */
|
||||||
|
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Flag the buffer dirty if caller will write in it */
|
||||||
|
if (writable)
|
||||||
|
ptr->dirty = TRUE;
|
||||||
|
/* Return address of proper part of the buffer */
|
||||||
|
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release all objects belonging to a specified pool.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
free_pool (j_common_ptr cinfo, int pool_id)
|
||||||
|
{
|
||||||
|
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||||
|
small_pool_ptr shdr_ptr;
|
||||||
|
large_pool_ptr lhdr_ptr;
|
||||||
|
|
||||||
|
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
|
||||||
|
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
|
||||||
|
|
||||||
|
/* Release large objects */
|
||||||
|
lhdr_ptr = mem->large_list[pool_id];
|
||||||
|
mem->large_list[pool_id] = NULL;
|
||||||
|
|
||||||
|
while (lhdr_ptr != NULL) {
|
||||||
|
large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
|
||||||
|
free(lhdr_ptr);
|
||||||
|
lhdr_ptr = next_lhdr_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release small objects */
|
||||||
|
shdr_ptr = mem->small_list[pool_id];
|
||||||
|
mem->small_list[pool_id] = NULL;
|
||||||
|
|
||||||
|
while (shdr_ptr != NULL) {
|
||||||
|
small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
|
||||||
|
free(shdr_ptr);
|
||||||
|
shdr_ptr = next_shdr_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Close up shop entirely.
|
||||||
|
* Note that this cannot be called unless cinfo->mem is non-NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
METHODDEF(void)
|
||||||
|
self_destruct (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
int pool;
|
||||||
|
|
||||||
|
/* Close all backing store, release all memory.
|
||||||
|
* Releasing pools in reverse order might help avoid fragmentation
|
||||||
|
* with some (brain-damaged) malloc libraries.
|
||||||
|
*/
|
||||||
|
for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
|
||||||
|
free_pool(cinfo, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the memory manager control block too. */
|
||||||
|
free(cinfo->mem);
|
||||||
|
cinfo->mem = NULL; /* ensures I will be called only once */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory manager initialization.
|
||||||
|
* When this is called, only the error manager pointer is valid in cinfo!
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jinit_memory_mgr (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
my_mem_ptr mem;
|
||||||
|
int pool;
|
||||||
|
|
||||||
|
cinfo->mem = NULL; /* for safety if init fails */
|
||||||
|
|
||||||
|
/* Check for configuration errors.
|
||||||
|
* SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
|
||||||
|
* doesn't reflect any real hardware alignment requirement.
|
||||||
|
* The test is a little tricky: for X>0, X and X-1 have no one-bits
|
||||||
|
* in common if and only if X is a power of 2, ie has only one one-bit.
|
||||||
|
* Some compilers may give an "unreachable code" warning here; ignore it.
|
||||||
|
*/
|
||||||
|
if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
|
||||||
|
ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
|
||||||
|
|
||||||
|
/* Attempt to allocate memory manager's control block */
|
||||||
|
mem = (my_mem_ptr) malloc(SIZEOF(my_memory_mgr));
|
||||||
|
|
||||||
|
if (mem == NULL) {
|
||||||
|
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, fill in the method pointers */
|
||||||
|
mem->pub.alloc_small = alloc_small;
|
||||||
|
mem->pub.alloc_large = alloc_large;
|
||||||
|
mem->pub.alloc_sarray = alloc_sarray;
|
||||||
|
mem->pub.alloc_barray = alloc_barray;
|
||||||
|
mem->pub.request_virt_barray = request_virt_barray;
|
||||||
|
mem->pub.realize_virt_arrays = realize_virt_arrays;
|
||||||
|
mem->pub.access_virt_barray = access_virt_barray;
|
||||||
|
mem->pub.free_pool = free_pool;
|
||||||
|
mem->pub.self_destruct = self_destruct;
|
||||||
|
|
||||||
|
/* Initialize working state */
|
||||||
|
for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
|
||||||
|
mem->small_list[pool] = NULL;
|
||||||
|
mem->large_list[pool] = NULL;
|
||||||
|
}
|
||||||
|
mem->virt_barray_list = NULL;
|
||||||
|
|
||||||
|
/* Declare ourselves open for business */
|
||||||
|
cinfo->mem = & mem->pub;
|
||||||
|
}
|
330
jpeg-6b/jmorecfg.h
Normal file
330
jpeg-6b/jmorecfg.h
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* jmorecfg.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains additional configuration options that customize the
|
||||||
|
* JPEG software for special applications or support machine-dependent
|
||||||
|
* optimizations. Most users will not need to touch this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define BITS_IN_JSAMPLE as either
|
||||||
|
* 8 for 8-bit sample values (the usual setting)
|
||||||
|
* 12 for 12-bit sample values
|
||||||
|
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
|
||||||
|
* JPEG standard, and the IJG code does not support anything else!
|
||||||
|
* We do not support run-time selection of data precision, sorry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of components (color channels) allowed in JPEG image.
|
||||||
|
* To meet the letter of the JPEG spec, set this to 255. However, darn
|
||||||
|
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
|
||||||
|
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
|
||||||
|
* really short on memory. (Each allowed component costs a hundred or so
|
||||||
|
* bytes of storage, whether actually used in an image or not.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_COMPONENTS 10 /* maximum number of image components */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic data types.
|
||||||
|
* You may need to change these if you have a machine with unusual data
|
||||||
|
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
|
||||||
|
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
|
||||||
|
* but it had better be at least 16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Representation of a single sample (pixel element value).
|
||||||
|
* We frequently allocate large arrays of these, so it's important to keep
|
||||||
|
* them small. But if you have memory to burn and access to char or short
|
||||||
|
* arrays is very slow on your hardware, you might want to change these.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 8
|
||||||
|
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
||||||
|
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_CHAR
|
||||||
|
|
||||||
|
typedef unsigned char JSAMPLE;
|
||||||
|
#define GETJSAMPLE(value) ((int) (value))
|
||||||
|
|
||||||
|
#else /* not HAVE_UNSIGNED_CHAR */
|
||||||
|
|
||||||
|
typedef char JSAMPLE;
|
||||||
|
#ifdef CHAR_IS_UNSIGNED
|
||||||
|
#define GETJSAMPLE(value) ((int) (value))
|
||||||
|
#else
|
||||||
|
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
|
||||||
|
#endif /* CHAR_IS_UNSIGNED */
|
||||||
|
|
||||||
|
#endif /* HAVE_UNSIGNED_CHAR */
|
||||||
|
|
||||||
|
#define MAXJSAMPLE 255
|
||||||
|
#define CENTERJSAMPLE 128
|
||||||
|
|
||||||
|
#endif /* BITS_IN_JSAMPLE == 8 */
|
||||||
|
|
||||||
|
|
||||||
|
#if BITS_IN_JSAMPLE == 12
|
||||||
|
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
|
||||||
|
* On nearly all machines "short" will do nicely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef short JSAMPLE;
|
||||||
|
#define GETJSAMPLE(value) ((int) (value))
|
||||||
|
|
||||||
|
#define MAXJSAMPLE 4095
|
||||||
|
#define CENTERJSAMPLE 2048
|
||||||
|
|
||||||
|
#endif /* BITS_IN_JSAMPLE == 12 */
|
||||||
|
|
||||||
|
|
||||||
|
/* Representation of a DCT frequency coefficient.
|
||||||
|
* This should be a signed value of at least 16 bits; "short" is usually OK.
|
||||||
|
* Again, we allocate large arrays of these, but you can change to int
|
||||||
|
* if you have memory to burn and "short" is really slow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef short JCOEF;
|
||||||
|
|
||||||
|
|
||||||
|
/* Compressed datastreams are represented as arrays of JOCTET.
|
||||||
|
* These must be EXACTLY 8 bits wide, at least once they are written to
|
||||||
|
* external storage. Note that when using the stdio data source/destination
|
||||||
|
* managers, this is also the data type passed to fread/fwrite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_CHAR
|
||||||
|
|
||||||
|
typedef unsigned char JOCTET;
|
||||||
|
#define GETJOCTET(value) (value)
|
||||||
|
|
||||||
|
#else /* not HAVE_UNSIGNED_CHAR */
|
||||||
|
|
||||||
|
typedef char JOCTET;
|
||||||
|
#ifdef CHAR_IS_UNSIGNED
|
||||||
|
#define GETJOCTET(value) (value)
|
||||||
|
#else
|
||||||
|
#define GETJOCTET(value) ((value) & 0xFF)
|
||||||
|
#endif /* CHAR_IS_UNSIGNED */
|
||||||
|
|
||||||
|
#endif /* HAVE_UNSIGNED_CHAR */
|
||||||
|
|
||||||
|
|
||||||
|
/* These typedefs are used for various table entries and so forth.
|
||||||
|
* They must be at least as wide as specified; but making them too big
|
||||||
|
* won't cost a huge amount of memory, so we don't provide special
|
||||||
|
* extraction code like we did for JSAMPLE. (In other words, these
|
||||||
|
* typedefs live at a different point on the speed/space tradeoff curve.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* UINT8 must hold at least the values 0..255. */
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_CHAR
|
||||||
|
typedef unsigned char UINT8;
|
||||||
|
#else /* not HAVE_UNSIGNED_CHAR */
|
||||||
|
#ifdef CHAR_IS_UNSIGNED
|
||||||
|
typedef char UINT8;
|
||||||
|
#else /* not CHAR_IS_UNSIGNED */
|
||||||
|
typedef short UINT8;
|
||||||
|
#endif /* CHAR_IS_UNSIGNED */
|
||||||
|
#endif /* HAVE_UNSIGNED_CHAR */
|
||||||
|
|
||||||
|
/* UINT16 must hold at least the values 0..65535. */
|
||||||
|
|
||||||
|
#ifdef HAVE_UNSIGNED_SHORT
|
||||||
|
typedef unsigned short UINT16;
|
||||||
|
#else /* not HAVE_UNSIGNED_SHORT */
|
||||||
|
typedef unsigned int UINT16;
|
||||||
|
#endif /* HAVE_UNSIGNED_SHORT */
|
||||||
|
|
||||||
|
/* INT16 must hold at least the values -32768..32767. */
|
||||||
|
|
||||||
|
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
|
||||||
|
typedef short INT16;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* INT32 must hold at least signed 32-bit values. */
|
||||||
|
|
||||||
|
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
|
||||||
|
typedef long INT32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Datatype used for image dimensions. The JPEG standard only supports
|
||||||
|
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
|
||||||
|
* "unsigned int" is sufficient on all machines. However, if you need to
|
||||||
|
* handle larger images and you don't mind deviating from the spec, you
|
||||||
|
* can change this datatype.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef unsigned int JDIMENSION;
|
||||||
|
|
||||||
|
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
|
||||||
|
|
||||||
|
|
||||||
|
/* These macros are used in all function definitions and extern declarations.
|
||||||
|
* You could modify them if you need to change function linkage conventions;
|
||||||
|
* in particular, you'll need to do that to make the library a Windows DLL.
|
||||||
|
* Another application is to make all functions global for use with debuggers
|
||||||
|
* or code profilers that require it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a function called through method pointers: */
|
||||||
|
#define METHODDEF(type) static type
|
||||||
|
/* a function used only in its module: */
|
||||||
|
#define LOCAL(type) static type
|
||||||
|
/* a function referenced thru EXTERNs: */
|
||||||
|
#define GLOBAL(type) type
|
||||||
|
/* a reference to a GLOBAL function: */
|
||||||
|
#define EXTERN(type) extern type
|
||||||
|
|
||||||
|
|
||||||
|
/* This macro is used to declare a "method", that is, a function pointer.
|
||||||
|
* We want to supply prototype parameters if the compiler can cope.
|
||||||
|
* Note that the arglist parameter must be parenthesized!
|
||||||
|
* Again, you can customize this if you need special linkage keywords.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
|
||||||
|
#else
|
||||||
|
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
|
||||||
|
* in standard header files. Or you may have conflicts with application-
|
||||||
|
* specific header files that you want to include together with these files.
|
||||||
|
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_BOOLEAN
|
||||||
|
typedef int boolean;
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE /* in case these macros already exist */
|
||||||
|
#define FALSE 0 /* values of boolean */
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining options affect code selection within the JPEG library,
|
||||||
|
* but they don't need to be visible to most applications using the library.
|
||||||
|
* To minimize application namespace pollution, the symbols won't be
|
||||||
|
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
#define JPEG_INTERNAL_OPTIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNAL_OPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These defines indicate whether to include various optional functions.
|
||||||
|
* Undefining some of these symbols will produce a smaller but less capable
|
||||||
|
* library. Note that you can leave certain source files out of the
|
||||||
|
* compilation/linking process if you've #undef'd the corresponding symbols.
|
||||||
|
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
|
||||||
|
|
||||||
|
/* Capability options common to encoder and decoder: */
|
||||||
|
|
||||||
|
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
|
||||||
|
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
|
||||||
|
|
||||||
|
/* Decoder capability options: */
|
||||||
|
|
||||||
|
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||||
|
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||||
|
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||||
|
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
|
||||||
|
|
||||||
|
/* more capability options later, no doubt */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ordering of RGB data in scanlines passed to or from the application.
|
||||||
|
* If your application wants to deal with data in the order B,G,R, just
|
||||||
|
* change these macros. You can also deal with formats such as R,G,B,X
|
||||||
|
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
|
||||||
|
* the offsets will also change the order in which colormap data is organized.
|
||||||
|
* RESTRICTIONS:
|
||||||
|
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
|
||||||
|
* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
|
||||||
|
* useful if you are using JPEG color spaces other than YCbCr or grayscale.
|
||||||
|
* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
|
||||||
|
* is not 3 (they don't understand about dummy color components!). So you
|
||||||
|
* can't use color quantization if you change that value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
|
||||||
|
#define RGB_GREEN 1 /* Offset of Green */
|
||||||
|
#define RGB_BLUE 2 /* Offset of Blue */
|
||||||
|
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
|
||||||
|
|
||||||
|
|
||||||
|
/* Definitions for speed-related optimizations. */
|
||||||
|
|
||||||
|
|
||||||
|
/* If your compiler supports inline functions, define INLINE
|
||||||
|
* as the inline keyword; otherwise define it as empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INLINE
|
||||||
|
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
|
||||||
|
#define INLINE __inline__
|
||||||
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define INLINE __inline
|
||||||
|
#endif
|
||||||
|
#ifndef INLINE
|
||||||
|
#define INLINE /* default is to define it as empty */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
|
||||||
|
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
|
||||||
|
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MULTIPLIER
|
||||||
|
#define MULTIPLIER int /* type for fastest integer multiply */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* FAST_FLOAT should be either float or double, whichever is done faster
|
||||||
|
* by your compiler. (Note that this type is only used in the floating point
|
||||||
|
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
|
||||||
|
* Typically, float is faster in ANSI C compilers, while double is faster in
|
||||||
|
* pre-ANSI compilers (because they insist on converting to double anyway).
|
||||||
|
* The code below therefore chooses float if we have ANSI-style prototypes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FAST_FLOAT
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
#define FAST_FLOAT float
|
||||||
|
#else
|
||||||
|
#define FAST_FLOAT double
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* JPEG_INTERNAL_OPTIONS */
|
284
jpeg-6b/jpeg-6b.vcproj
Normal file
284
jpeg-6b/jpeg-6b.vcproj
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="jpeg-6b"
|
||||||
|
ProjectGUID="{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}"
|
||||||
|
RootNamespace="jpeg6b"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
OmitFramePointers="true"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
CallingConvention="1"
|
||||||
|
CompileAs="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jcomapi.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdapimin.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdapistd.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdatasrc.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdcoefct.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdcolor.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jddctmgr.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdhuff.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdinput.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdmainct.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdmarker.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdmaster.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdmerge.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdphuff.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdpostct.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdsample.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jerror.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jidctint.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jmemmgr.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jutils.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jconfig.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdct.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jdhuff.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jerror.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jinclude.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jmorecfg.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jpegint.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jpeglib.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jversion.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath=".\readme-zdoom.txt"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
261
jpeg-6b/jpegint.h
Normal file
261
jpeg-6b/jpegint.h
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
/*
|
||||||
|
* jpegint.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file provides common declarations for the various JPEG modules.
|
||||||
|
* These declarations are considered internal to the JPEG library; most
|
||||||
|
* applications using the library shouldn't need to include this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations for both compression & decompression */
|
||||||
|
|
||||||
|
typedef enum { /* Operating modes for buffer controllers */
|
||||||
|
JBUF_PASS_THRU, /* Plain stripwise operation */
|
||||||
|
/* Remaining modes require a full-image buffer to have been created */
|
||||||
|
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
|
||||||
|
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
|
||||||
|
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
|
||||||
|
} J_BUF_MODE;
|
||||||
|
|
||||||
|
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
|
||||||
|
#define CSTATE_START 100 /* after create_compress */
|
||||||
|
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
|
||||||
|
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
|
||||||
|
#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
|
||||||
|
#define DSTATE_START 200 /* after create_decompress */
|
||||||
|
#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
|
||||||
|
#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
|
||||||
|
#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
|
||||||
|
#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
|
||||||
|
#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
|
||||||
|
//#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
|
||||||
|
//#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
|
||||||
|
#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
|
||||||
|
#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
|
||||||
|
#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations for decompression modules */
|
||||||
|
|
||||||
|
/* Master control module */
|
||||||
|
struct jpeg_decomp_master {
|
||||||
|
JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Input control module */
|
||||||
|
struct jpeg_input_controller {
|
||||||
|
JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* State variables made visible to other modules */
|
||||||
|
boolean has_multiple_scans; /* True if file has multiple scans */
|
||||||
|
boolean eoi_reached; /* True when EOI has been consumed */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Main buffer control (downsampled-data buffer) */
|
||||||
|
struct jpeg_d_main_controller {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||||
|
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail));
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Coefficient buffer control */
|
||||||
|
struct jpeg_d_coef_controller {
|
||||||
|
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE output_buf));
|
||||||
|
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||||
|
jvirt_barray_ptr *coef_arrays;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Decompression postprocessing (color quantization buffer control) */
|
||||||
|
struct jpeg_d_post_controller {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||||
|
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION *in_row_group_ctr,
|
||||||
|
JDIMENSION in_row_groups_avail,
|
||||||
|
JSAMPARRAY output_buf,
|
||||||
|
JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail));
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Marker reading & parsing */
|
||||||
|
struct jpeg_marker_reader {
|
||||||
|
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
|
||||||
|
/* Read markers until SOS or EOI.
|
||||||
|
* Returns same codes as are defined for jpeg_consume_input:
|
||||||
|
* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||||
|
*/
|
||||||
|
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
|
||||||
|
/* Read a restart marker --- exported for use by entropy decoder only */
|
||||||
|
jpeg_marker_parser_method read_restart_marker;
|
||||||
|
|
||||||
|
/* State of marker reader --- nominally internal, but applications
|
||||||
|
* supplying COM or APPn handlers might like to know the state.
|
||||||
|
*/
|
||||||
|
boolean saw_SOI; /* found SOI? */
|
||||||
|
boolean saw_SOF; /* found SOF? */
|
||||||
|
int next_restart_num; /* next restart number expected (0-7) */
|
||||||
|
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Entropy decoding */
|
||||||
|
struct jpeg_entropy_decoder {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
|
||||||
|
JBLOCKROW *MCU_data));
|
||||||
|
|
||||||
|
/* This is here to share code between baseline and progressive decoders; */
|
||||||
|
/* other modules probably should not use it */
|
||||||
|
boolean insufficient_data; /* set TRUE after emitting warning */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Inverse DCT (also performs dequantization) */
|
||||||
|
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||||
|
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||||
|
JCOEFPTR coef_block,
|
||||||
|
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||||
|
|
||||||
|
struct jpeg_inverse_dct {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||||
|
/* It is useful to allow each component to have a separate IDCT method. */
|
||||||
|
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Upsampling (note that upsampler must also call color converter) */
|
||||||
|
struct jpeg_upsampler {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf,
|
||||||
|
JDIMENSION *in_row_group_ctr,
|
||||||
|
JDIMENSION in_row_groups_avail,
|
||||||
|
JSAMPARRAY output_buf,
|
||||||
|
JDIMENSION *out_row_ctr,
|
||||||
|
JDIMENSION out_rows_avail));
|
||||||
|
|
||||||
|
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Colorspace conversion */
|
||||||
|
struct jpeg_color_deconverter {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||||
|
JSAMPARRAY output_buf, int num_rows));
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Color quantization or color precision reduction */
|
||||||
|
struct jpeg_color_quantizer {
|
||||||
|
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
|
||||||
|
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
|
||||||
|
int num_rows));
|
||||||
|
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Miscellaneous useful macros */
|
||||||
|
|
||||||
|
#undef MAX
|
||||||
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#undef MIN
|
||||||
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
|
|
||||||
|
/* We assume that right shift corresponds to signed division by 2 with
|
||||||
|
* rounding towards minus infinity. This is correct for typical "arithmetic
|
||||||
|
* shift" instructions that shift in copies of the sign bit. But some
|
||||||
|
* C compilers implement >> with an unsigned shift. For these machines you
|
||||||
|
* must define RIGHT_SHIFT_IS_UNSIGNED.
|
||||||
|
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
|
||||||
|
* It is only applied with constant shift counts. SHIFT_TEMPS must be
|
||||||
|
* included in the variables of any routine using RIGHT_SHIFT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||||
|
#define SHIFT_TEMPS INT32 shift_temp;
|
||||||
|
#define RIGHT_SHIFT(x,shft) \
|
||||||
|
((shift_temp = (x)) < 0 ? \
|
||||||
|
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
|
||||||
|
(shift_temp >> (shft)))
|
||||||
|
#else
|
||||||
|
#define SHIFT_TEMPS
|
||||||
|
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Compression module initialization routines */
|
||||||
|
EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||||
|
boolean transcode_only));
|
||||||
|
EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||||
|
/* Decompression module initialization routines */
|
||||||
|
EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||||
|
boolean need_full_buffer));
|
||||||
|
EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||||
|
/* Memory manager initialization */
|
||||||
|
EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||||
|
|
||||||
|
/* Utility routines in jutils.c */
|
||||||
|
static INLINE long jdiv_round_up (long a, long b)
|
||||||
|
/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
|
||||||
|
/* Assumes a >= 0, b > 0 */
|
||||||
|
{
|
||||||
|
return (a + b - 1L) / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE long jround_up (long a, long b)
|
||||||
|
/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
|
||||||
|
/* Assumes a >= 0, b > 0 */
|
||||||
|
{
|
||||||
|
a += b - 1L;
|
||||||
|
return a - (a % b);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN(long) jround_up JPP((long a, long b));
|
||||||
|
EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
|
||||||
|
JSAMPARRAY output_array, int dest_row,
|
||||||
|
int num_rows, JDIMENSION num_cols));
|
||||||
|
|
||||||
|
/* Constant tables in jutils.c */
|
||||||
|
#if 0 /* This table is not actually needed in v6a */
|
||||||
|
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
|
||||||
|
#endif
|
||||||
|
extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
|
941
jpeg-6b/jpeglib.h
Normal file
941
jpeg-6b/jpeglib.h
Normal file
|
@ -0,0 +1,941 @@
|
||||||
|
/*
|
||||||
|
* jpeglib.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file defines the application interface for the JPEG library.
|
||||||
|
* Most applications using the library need only include this file,
|
||||||
|
* and perhaps jerror.h if they want to know the exact error codes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JPEGLIB_H
|
||||||
|
#define JPEGLIB_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First we include the configuration files that record how this
|
||||||
|
* installation of the JPEG library is set up. jconfig.h can be
|
||||||
|
* generated automatically for many systems. jmorecfg.h contains
|
||||||
|
* manual configuration options that most people need not worry about.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
|
||||||
|
#include "jconfig.h" /* widely used configuration options */
|
||||||
|
#endif
|
||||||
|
#include "jmorecfg.h" /* seldom changed options */
|
||||||
|
|
||||||
|
|
||||||
|
/* Version ID for the JPEG library.
|
||||||
|
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_LIB_VERSION 62 /* Version 6b */
|
||||||
|
|
||||||
|
|
||||||
|
/* Various constants determining the sizes of things.
|
||||||
|
* All of these are specified by the JPEG standard, so don't change them
|
||||||
|
* if you want to be compatible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
|
||||||
|
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
|
||||||
|
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
|
||||||
|
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
|
||||||
|
#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
|
||||||
|
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
|
||||||
|
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
|
||||||
|
/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
|
||||||
|
* the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
|
||||||
|
* If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
|
||||||
|
* to handle it. We even let you do this from the jconfig.h file. However,
|
||||||
|
* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
|
||||||
|
* sometimes emits noncompliant files doesn't mean you should too.
|
||||||
|
*/
|
||||||
|
#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */
|
||||||
|
#ifndef D_MAX_BLOCKS_IN_MCU
|
||||||
|
#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structures for images (arrays of samples and of DCT coefficients).
|
||||||
|
* On 80x86 machines, the image arrays are too big for near pointers,
|
||||||
|
* but the pointer arrays can fit in near memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */
|
||||||
|
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
|
||||||
|
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
|
||||||
|
|
||||||
|
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
|
||||||
|
typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */
|
||||||
|
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
|
||||||
|
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
|
||||||
|
|
||||||
|
typedef JCOEF *JCOEFPTR; /* useful in a couple of places */
|
||||||
|
|
||||||
|
|
||||||
|
/* Types for JPEG compression parameters and working tables. */
|
||||||
|
|
||||||
|
|
||||||
|
/* DCT coefficient quantization tables. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* This array gives the coefficient quantizers in natural array order
|
||||||
|
* (not the zigzag order in which they are stored in a JPEG DQT marker).
|
||||||
|
* CAUTION: IJG versions prior to v6a kept this array in zigzag order.
|
||||||
|
*/
|
||||||
|
UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
|
||||||
|
/* This field is used only during compression. It's initialized FALSE when
|
||||||
|
* the table is created, and set TRUE when it's been output to the file.
|
||||||
|
* You could suppress output of a table by setting this to TRUE.
|
||||||
|
* (See jpeg_suppress_tables for an example.)
|
||||||
|
*/
|
||||||
|
boolean sent_table; /* TRUE when table has been output */
|
||||||
|
} JQUANT_TBL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Huffman coding tables. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* These two fields directly represent the contents of a JPEG DHT marker */
|
||||||
|
UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
|
||||||
|
/* length k bits; bits[0] is unused */
|
||||||
|
UINT8 huffval[256]; /* The symbols, in order of incr code length */
|
||||||
|
/* This field is used only during compression. It's initialized FALSE when
|
||||||
|
* the table is created, and set TRUE when it's been output to the file.
|
||||||
|
* You could suppress output of a table by setting this to TRUE.
|
||||||
|
* (See jpeg_suppress_tables for an example.)
|
||||||
|
*/
|
||||||
|
boolean sent_table; /* TRUE when table has been output */
|
||||||
|
} JHUFF_TBL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Basic info about one component (color channel). */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* These values are fixed over the whole image. */
|
||||||
|
/* For compression, they must be supplied by parameter setup; */
|
||||||
|
/* for decompression, they are read from the SOF marker. */
|
||||||
|
int component_id; /* identifier for this component (0..255) */
|
||||||
|
int component_index; /* its index in SOF or cinfo->comp_info[] */
|
||||||
|
int h_samp_factor; /* horizontal sampling factor (1..4) */
|
||||||
|
int v_samp_factor; /* vertical sampling factor (1..4) */
|
||||||
|
int quant_tbl_no; /* quantization table selector (0..3) */
|
||||||
|
/* These values may vary between scans. */
|
||||||
|
/* For compression, they must be supplied by parameter setup; */
|
||||||
|
/* for decompression, they are read from the SOS marker. */
|
||||||
|
/* The decompressor output side may not use these variables. */
|
||||||
|
int dc_tbl_no; /* DC entropy table selector (0..3) */
|
||||||
|
int ac_tbl_no; /* AC entropy table selector (0..3) */
|
||||||
|
|
||||||
|
/* Remaining fields should be treated as private by applications. */
|
||||||
|
|
||||||
|
/* These values are computed during compression or decompression startup: */
|
||||||
|
/* Component's size in DCT blocks.
|
||||||
|
* Any dummy blocks added to complete an MCU are not counted; therefore
|
||||||
|
* these values do not depend on whether a scan is interleaved or not.
|
||||||
|
*/
|
||||||
|
JDIMENSION width_in_blocks;
|
||||||
|
JDIMENSION height_in_blocks;
|
||||||
|
/* Size of a DCT block in samples. Always DCTSIZE for compression.
|
||||||
|
* For decompression this is the size of the output from one DCT block,
|
||||||
|
* reflecting any scaling we choose to apply during the IDCT step.
|
||||||
|
* Values of 1,2,4,8 are likely to be supported. Note that different
|
||||||
|
* components may receive different IDCT scalings.
|
||||||
|
*/
|
||||||
|
int DCT_scaled_size;
|
||||||
|
/* The downsampled dimensions are the component's actual, unpadded number
|
||||||
|
* of samples at the main buffer (preprocessing/compression interface), thus
|
||||||
|
* downsampled_width = ceil(image_width * Hi/Hmax)
|
||||||
|
* and similarly for height. For decompression, IDCT scaling is included, so
|
||||||
|
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
|
||||||
|
*/
|
||||||
|
JDIMENSION downsampled_width; /* actual width in samples */
|
||||||
|
JDIMENSION downsampled_height; /* actual height in samples */
|
||||||
|
/* This flag is used only for decompression. In cases where some of the
|
||||||
|
* components will be ignored (eg grayscale output from YCbCr image),
|
||||||
|
* we can skip most computations for the unused components.
|
||||||
|
*/
|
||||||
|
boolean component_needed; /* do we need the value of this component? */
|
||||||
|
|
||||||
|
/* These values are computed before starting a scan of the component. */
|
||||||
|
/* The decompressor output side may not use these variables. */
|
||||||
|
int MCU_width; /* number of blocks per MCU, horizontally */
|
||||||
|
int MCU_height; /* number of blocks per MCU, vertically */
|
||||||
|
int MCU_blocks; /* MCU_width * MCU_height */
|
||||||
|
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
|
||||||
|
int last_col_width; /* # of non-dummy blocks across in last MCU */
|
||||||
|
int last_row_height; /* # of non-dummy blocks down in last MCU */
|
||||||
|
|
||||||
|
/* Saved quantization table for component; NULL if none yet saved.
|
||||||
|
* See jdinput.c comments about the need for this information.
|
||||||
|
* This field is currently used only for decompression.
|
||||||
|
*/
|
||||||
|
JQUANT_TBL * quant_table;
|
||||||
|
|
||||||
|
/* Private per-component storage for DCT or IDCT subsystem. */
|
||||||
|
void * dct_table;
|
||||||
|
} jpeg_component_info;
|
||||||
|
|
||||||
|
|
||||||
|
/* The script for encoding a multiple-scan file is an array of these: */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int comps_in_scan; /* number of components encoded in this scan */
|
||||||
|
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
|
||||||
|
int Ss, Se; /* progressive JPEG spectral selection parms */
|
||||||
|
int Ah, Al; /* progressive JPEG successive approx. parms */
|
||||||
|
} jpeg_scan_info;
|
||||||
|
|
||||||
|
/* The decompressor can save APPn and COM markers in a list of these: */
|
||||||
|
|
||||||
|
typedef struct jpeg_marker_struct * jpeg_saved_marker_ptr;
|
||||||
|
|
||||||
|
struct jpeg_marker_struct {
|
||||||
|
jpeg_saved_marker_ptr next; /* next in list, or NULL */
|
||||||
|
UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
|
||||||
|
unsigned int original_length; /* # bytes of data in the file */
|
||||||
|
unsigned int data_length; /* # bytes of data saved at data[] */
|
||||||
|
JOCTET * data; /* the data contained in the marker */
|
||||||
|
/* the marker length word is not counted in data_length or original_length */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Known color spaces. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
JCS_UNKNOWN, /* error/unspecified */
|
||||||
|
JCS_GRAYSCALE, /* monochrome */
|
||||||
|
JCS_RGB, /* red/green/blue */
|
||||||
|
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
|
||||||
|
JCS_CMYK, /* C/M/Y/K */
|
||||||
|
JCS_YCCK /* Y/Cb/Cr/K */
|
||||||
|
} J_COLOR_SPACE;
|
||||||
|
|
||||||
|
/* DCT/IDCT algorithm options. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
JDCT_ISLOW, /* slow but accurate integer algorithm */
|
||||||
|
JDCT_IFAST, /* faster, less accurate integer method */
|
||||||
|
JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
|
||||||
|
} J_DCT_METHOD;
|
||||||
|
|
||||||
|
#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
|
||||||
|
#define JDCT_DEFAULT JDCT_ISLOW
|
||||||
|
#endif
|
||||||
|
#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
|
||||||
|
#define JDCT_FASTEST JDCT_IFAST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Dithering options for decompression. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
JDITHER_NONE, /* no dithering */
|
||||||
|
JDITHER_ORDERED, /* simple ordered dither */
|
||||||
|
JDITHER_FS /* Floyd-Steinberg error diffusion dither */
|
||||||
|
} J_DITHER_MODE;
|
||||||
|
|
||||||
|
|
||||||
|
/* Common fields between JPEG compression and decompression master structs. */
|
||||||
|
|
||||||
|
#define jpeg_common_fields \
|
||||||
|
struct jpeg_error_mgr * err; /* Error handler module */\
|
||||||
|
struct jpeg_memory_mgr * mem; /* Memory manager module */\
|
||||||
|
struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
|
||||||
|
void * client_data; /* Available for use by application */\
|
||||||
|
boolean is_decompressor; /* So common code can tell which is which */\
|
||||||
|
int global_state /* For checking call sequence validity */
|
||||||
|
|
||||||
|
/* Routines that are to be used by both halves of the library are declared
|
||||||
|
* to receive a pointer to this structure. There are no actual instances of
|
||||||
|
* jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
|
||||||
|
*/
|
||||||
|
struct jpeg_common_struct {
|
||||||
|
jpeg_common_fields; /* Fields common to both master struct types */
|
||||||
|
/* Additional fields follow in an actual jpeg_compress_struct or
|
||||||
|
* jpeg_decompress_struct. All three structs must agree on these
|
||||||
|
* initial fields! (This would be a lot cleaner in C++.)
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct jpeg_common_struct * j_common_ptr;
|
||||||
|
typedef struct jpeg_compress_struct * j_compress_ptr;
|
||||||
|
typedef struct jpeg_decompress_struct * j_decompress_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* Master record for a compression instance */
|
||||||
|
|
||||||
|
struct jpeg_compress_struct {
|
||||||
|
jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
|
||||||
|
|
||||||
|
/* Destination for compressed data */
|
||||||
|
struct jpeg_destination_mgr * dest;
|
||||||
|
|
||||||
|
/* Description of source image --- these fields must be filled in by
|
||||||
|
* outer application before starting compression. in_color_space must
|
||||||
|
* be correct before you can even call jpeg_set_defaults().
|
||||||
|
*/
|
||||||
|
|
||||||
|
JDIMENSION image_width; /* input image width */
|
||||||
|
JDIMENSION image_height; /* input image height */
|
||||||
|
int input_components; /* # of color components in input image */
|
||||||
|
J_COLOR_SPACE in_color_space; /* colorspace of input image */
|
||||||
|
|
||||||
|
double input_gamma; /* image gamma of input image */
|
||||||
|
|
||||||
|
/* Compression parameters --- these fields must be set before calling
|
||||||
|
* jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
|
||||||
|
* initialize everything to reasonable defaults, then changing anything
|
||||||
|
* the application specifically wants to change. That way you won't get
|
||||||
|
* burnt when new parameters are added. Also note that there are several
|
||||||
|
* helper routines to simplify changing parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int data_precision; /* bits of precision in image data */
|
||||||
|
|
||||||
|
int num_components; /* # of color components in JPEG image */
|
||||||
|
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
|
||||||
|
|
||||||
|
jpeg_component_info * comp_info;
|
||||||
|
/* comp_info[i] describes component that appears i'th in SOF */
|
||||||
|
|
||||||
|
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
|
||||||
|
/* ptrs to coefficient quantization tables, or NULL if not defined */
|
||||||
|
|
||||||
|
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||||
|
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||||
|
/* ptrs to Huffman coding tables, or NULL if not defined */
|
||||||
|
|
||||||
|
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
|
||||||
|
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
|
||||||
|
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
|
||||||
|
|
||||||
|
int num_scans; /* # of entries in scan_info array */
|
||||||
|
const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
|
||||||
|
/* The default value of scan_info is NULL, which causes a single-scan
|
||||||
|
* sequential JPEG file to be emitted. To create a multi-scan file,
|
||||||
|
* set num_scans and scan_info to point to an array of scan definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
boolean raw_data_in; /* TRUE=caller supplies downsampled data */
|
||||||
|
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
|
||||||
|
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
|
||||||
|
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
|
||||||
|
int smoothing_factor; /* 1..100, or 0 for no input smoothing */
|
||||||
|
J_DCT_METHOD dct_method; /* DCT algorithm selector */
|
||||||
|
|
||||||
|
/* The restart interval can be specified in absolute MCUs by setting
|
||||||
|
* restart_interval, or in MCU rows by setting restart_in_rows
|
||||||
|
* (in which case the correct restart_interval will be figured
|
||||||
|
* for each scan).
|
||||||
|
*/
|
||||||
|
unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
|
||||||
|
int restart_in_rows; /* if > 0, MCU rows per restart interval */
|
||||||
|
|
||||||
|
/* Parameters controlling emission of special markers. */
|
||||||
|
|
||||||
|
boolean write_JFIF_header; /* should a JFIF marker be written? */
|
||||||
|
UINT8 JFIF_major_version; /* What to write for the JFIF version number */
|
||||||
|
UINT8 JFIF_minor_version;
|
||||||
|
/* These three values are not used by the JPEG code, merely copied */
|
||||||
|
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
|
||||||
|
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
|
||||||
|
/* ratio is defined by X_density/Y_density even when density_unit=0. */
|
||||||
|
UINT8 density_unit; /* JFIF code for pixel size units */
|
||||||
|
UINT16 X_density; /* Horizontal pixel density */
|
||||||
|
UINT16 Y_density; /* Vertical pixel density */
|
||||||
|
boolean write_Adobe_marker; /* should an Adobe marker be written? */
|
||||||
|
|
||||||
|
/* State variable: index of next scanline to be written to
|
||||||
|
* jpeg_write_scanlines(). Application may use this to control its
|
||||||
|
* processing loop, e.g., "while (next_scanline < image_height)".
|
||||||
|
*/
|
||||||
|
|
||||||
|
JDIMENSION next_scanline; /* 0 .. image_height-1 */
|
||||||
|
|
||||||
|
/* Remaining fields are known throughout compressor, but generally
|
||||||
|
* should not be touched by a surrounding application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These fields are computed during compression startup
|
||||||
|
*/
|
||||||
|
boolean progressive_mode; /* TRUE if scan script uses progressive mode */
|
||||||
|
int max_h_samp_factor; /* largest h_samp_factor */
|
||||||
|
int max_v_samp_factor; /* largest v_samp_factor */
|
||||||
|
|
||||||
|
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
|
||||||
|
/* The coefficient controller receives data in units of MCU rows as defined
|
||||||
|
* for fully interleaved scans (whether the JPEG file is interleaved or not).
|
||||||
|
* There are v_samp_factor * DCTSIZE sample rows of each component in an
|
||||||
|
* "iMCU" (interleaved MCU) row.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These fields are valid during any one scan.
|
||||||
|
* They describe the components and MCUs actually appearing in the scan.
|
||||||
|
*/
|
||||||
|
int comps_in_scan; /* # of JPEG components in this scan */
|
||||||
|
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
|
||||||
|
/* *cur_comp_info[i] describes component that appears i'th in SOS */
|
||||||
|
|
||||||
|
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
|
||||||
|
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||||
|
|
||||||
|
int blocks_in_MCU; /* # of DCT blocks per MCU */
|
||||||
|
int MCU_membership[C_MAX_BLOCKS_IN_MCU];
|
||||||
|
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||||
|
/* i'th block in an MCU */
|
||||||
|
|
||||||
|
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Links to compression subobjects (methods and private variables of modules)
|
||||||
|
*/
|
||||||
|
struct jpeg_comp_master * master;
|
||||||
|
struct jpeg_c_main_controller * main;
|
||||||
|
struct jpeg_c_prep_controller * prep;
|
||||||
|
struct jpeg_c_coef_controller * coef;
|
||||||
|
struct jpeg_marker_writer * marker;
|
||||||
|
struct jpeg_color_converter * cconvert;
|
||||||
|
struct jpeg_downsampler * downsample;
|
||||||
|
struct jpeg_forward_dct * fdct;
|
||||||
|
struct jpeg_entropy_encoder * entropy;
|
||||||
|
jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
|
||||||
|
int script_space_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Master record for a decompression instance */
|
||||||
|
|
||||||
|
struct jpeg_decompress_struct {
|
||||||
|
jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
|
||||||
|
|
||||||
|
/* Source of compressed data */
|
||||||
|
struct jpeg_source_mgr * src;
|
||||||
|
|
||||||
|
/* Basic description of image --- filled in by jpeg_read_header(). */
|
||||||
|
/* Application may inspect these values to decide how to process image. */
|
||||||
|
|
||||||
|
JDIMENSION image_width; /* nominal image width (from SOF marker) */
|
||||||
|
JDIMENSION image_height; /* nominal image height */
|
||||||
|
int num_components; /* # of color components in JPEG image */
|
||||||
|
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
|
||||||
|
|
||||||
|
/* Decompression processing parameters --- these fields must be set before
|
||||||
|
* calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
|
||||||
|
* them to default values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
J_COLOR_SPACE out_color_space; /* colorspace for output */
|
||||||
|
|
||||||
|
unsigned int scale_num, scale_denom; /* fraction by which to scale image */
|
||||||
|
|
||||||
|
double output_gamma; /* image gamma wanted in output */
|
||||||
|
|
||||||
|
J_DCT_METHOD dct_method; /* IDCT algorithm selector */
|
||||||
|
boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
|
||||||
|
boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
|
||||||
|
|
||||||
|
/* Description of actual output image that will be returned to application.
|
||||||
|
* These fields are computed by jpeg_start_decompress().
|
||||||
|
* You can also use jpeg_calc_output_dimensions() to determine these values
|
||||||
|
* in advance of calling jpeg_start_decompress().
|
||||||
|
*/
|
||||||
|
|
||||||
|
JDIMENSION output_width; /* scaled image width */
|
||||||
|
JDIMENSION output_height; /* scaled image height */
|
||||||
|
int out_color_components; /* # of color components in out_color_space */
|
||||||
|
int output_components; /* # of color components returned */
|
||||||
|
/* output_components is 1 (a colormap index) when quantizing colors;
|
||||||
|
* otherwise it equals out_color_components.
|
||||||
|
*/
|
||||||
|
int rec_outbuf_height; /* min recommended height of scanline buffer */
|
||||||
|
/* If the buffer passed to jpeg_read_scanlines() is less than this many rows
|
||||||
|
* high, space and time will be wasted due to unnecessary data copying.
|
||||||
|
* Usually rec_outbuf_height will be 1 or 2, at most 4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* State variables: these variables indicate the progress of decompression.
|
||||||
|
* The application may examine these but must not modify them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Row index of next scanline to be read from jpeg_read_scanlines().
|
||||||
|
* Application may use this to control its processing loop, e.g.,
|
||||||
|
* "while (output_scanline < output_height)".
|
||||||
|
*/
|
||||||
|
JDIMENSION output_scanline; /* 0 .. output_height-1 */
|
||||||
|
|
||||||
|
/* Current input scan number and number of iMCU rows completed in scan.
|
||||||
|
* These indicate the progress of the decompressor input side.
|
||||||
|
*/
|
||||||
|
int input_scan_number; /* Number of SOS markers seen so far */
|
||||||
|
JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
|
||||||
|
|
||||||
|
/* The "output scan number" is the notional scan being displayed by the
|
||||||
|
* output side. The decompressor will not allow output scan/row number
|
||||||
|
* to get ahead of input scan/row, but it can fall arbitrarily far behind.
|
||||||
|
*/
|
||||||
|
int output_scan_number; /* Nominal scan number being displayed */
|
||||||
|
JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
|
||||||
|
|
||||||
|
/* Current progression status. coef_bits[c][i] indicates the precision
|
||||||
|
* with which component c's DCT coefficient i (in zigzag order) is known.
|
||||||
|
* It is -1 when no data has yet been received, otherwise it is the point
|
||||||
|
* transform (shift) value for the most recent scan of the coefficient
|
||||||
|
* (thus, 0 at completion of the progression).
|
||||||
|
* This pointer is NULL when reading a non-progressive file.
|
||||||
|
*/
|
||||||
|
int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
|
||||||
|
|
||||||
|
/* Internal JPEG parameters --- the application usually need not look at
|
||||||
|
* these fields. Note that the decompressor output side may not use
|
||||||
|
* any parameters that can change between scans.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Quantization and Huffman tables are carried forward across input
|
||||||
|
* datastreams when processing abbreviated JPEG datastreams.
|
||||||
|
*/
|
||||||
|
|
||||||
|
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
|
||||||
|
/* ptrs to coefficient quantization tables, or NULL if not defined */
|
||||||
|
|
||||||
|
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||||
|
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
|
||||||
|
/* ptrs to Huffman coding tables, or NULL if not defined */
|
||||||
|
|
||||||
|
/* These parameters are never carried across datastreams, since they
|
||||||
|
* are given in SOF/SOS markers or defined to be reset by SOI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int data_precision; /* bits of precision in image data */
|
||||||
|
|
||||||
|
jpeg_component_info * comp_info;
|
||||||
|
/* comp_info[i] describes component that appears i'th in SOF */
|
||||||
|
|
||||||
|
boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
|
||||||
|
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
|
||||||
|
|
||||||
|
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
|
||||||
|
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
|
||||||
|
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
|
||||||
|
|
||||||
|
unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
|
||||||
|
|
||||||
|
/* These fields record data obtained from optional markers recognized by
|
||||||
|
* the JPEG library.
|
||||||
|
*/
|
||||||
|
boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
|
||||||
|
/* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
|
||||||
|
UINT8 JFIF_major_version; /* JFIF version number */
|
||||||
|
UINT8 JFIF_minor_version;
|
||||||
|
UINT8 density_unit; /* JFIF code for pixel size units */
|
||||||
|
UINT16 X_density; /* Horizontal pixel density */
|
||||||
|
UINT16 Y_density; /* Vertical pixel density */
|
||||||
|
boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
|
||||||
|
UINT8 Adobe_transform; /* Color transform code from Adobe marker */
|
||||||
|
|
||||||
|
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
|
||||||
|
|
||||||
|
/* Aside from the specific data retained from APPn markers known to the
|
||||||
|
* library, the uninterpreted contents of any or all APPn and COM markers
|
||||||
|
* can be saved in a list for examination by the application.
|
||||||
|
*/
|
||||||
|
jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
|
||||||
|
|
||||||
|
/* Remaining fields are known throughout decompressor, but generally
|
||||||
|
* should not be touched by a surrounding application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These fields are computed during decompression startup
|
||||||
|
*/
|
||||||
|
int max_h_samp_factor; /* largest h_samp_factor */
|
||||||
|
int max_v_samp_factor; /* largest v_samp_factor */
|
||||||
|
|
||||||
|
int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
|
||||||
|
|
||||||
|
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
|
||||||
|
/* The coefficient controller's input and output progress is measured in
|
||||||
|
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
|
||||||
|
* in fully interleaved JPEG scans, but are used whether the scan is
|
||||||
|
* interleaved or not. We define an iMCU row as v_samp_factor DCT block
|
||||||
|
* rows of each component. Therefore, the IDCT output contains
|
||||||
|
* v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.
|
||||||
|
*/
|
||||||
|
|
||||||
|
JSAMPLE * sample_range_limit; /* table for fast range-limiting */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These fields are valid during any one scan.
|
||||||
|
* They describe the components and MCUs actually appearing in the scan.
|
||||||
|
* Note that the decompressor output side must not use these fields.
|
||||||
|
*/
|
||||||
|
int comps_in_scan; /* # of JPEG components in this scan */
|
||||||
|
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
|
||||||
|
/* *cur_comp_info[i] describes component that appears i'th in SOS */
|
||||||
|
|
||||||
|
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
|
||||||
|
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||||
|
|
||||||
|
int blocks_in_MCU; /* # of DCT blocks per MCU */
|
||||||
|
int MCU_membership[D_MAX_BLOCKS_IN_MCU];
|
||||||
|
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||||
|
/* i'th block in an MCU */
|
||||||
|
|
||||||
|
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
|
||||||
|
|
||||||
|
/* This field is shared between entropy decoder and marker parser.
|
||||||
|
* It is either zero or the code of a JPEG marker that has been
|
||||||
|
* read from the data source, but has not yet been processed.
|
||||||
|
*/
|
||||||
|
int unread_marker;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Links to decompression subobjects (methods, private variables of modules)
|
||||||
|
*/
|
||||||
|
struct jpeg_decomp_master * master;
|
||||||
|
struct jpeg_d_main_controller * main;
|
||||||
|
struct jpeg_d_coef_controller * coef;
|
||||||
|
struct jpeg_d_post_controller * post;
|
||||||
|
struct jpeg_input_controller * inputctl;
|
||||||
|
struct jpeg_marker_reader * marker;
|
||||||
|
struct jpeg_entropy_decoder * entropy;
|
||||||
|
struct jpeg_inverse_dct * idct;
|
||||||
|
struct jpeg_upsampler * upsample;
|
||||||
|
struct jpeg_color_deconverter * cconvert;
|
||||||
|
struct jpeg_color_quantizer * cquantize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* "Object" declarations for JPEG modules that may be supplied or called
|
||||||
|
* directly by the surrounding application.
|
||||||
|
* As with all objects in the JPEG library, these structs only define the
|
||||||
|
* publicly visible methods and state variables of a module. Additional
|
||||||
|
* private fields may exist after the public ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Error handler object */
|
||||||
|
|
||||||
|
struct jpeg_error_mgr {
|
||||||
|
/* Error exit handler: does not return to caller */
|
||||||
|
JMETHOD(void, error_exit, (j_common_ptr cinfo));
|
||||||
|
/* Conditionally emit a trace or warning message */
|
||||||
|
JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
|
||||||
|
/* Routine that actually outputs a trace or error message */
|
||||||
|
JMETHOD(void, output_message, (j_common_ptr cinfo));
|
||||||
|
/* Format a message string for the most recent JPEG error or message */
|
||||||
|
JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
|
||||||
|
#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
|
||||||
|
/* Reset error state variables at start of a new image */
|
||||||
|
JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
|
||||||
|
|
||||||
|
/* The message ID code and any parameters are saved here.
|
||||||
|
* A message can have one string parameter or up to 8 int parameters.
|
||||||
|
*/
|
||||||
|
int msg_code;
|
||||||
|
#define JMSG_STR_PARM_MAX 80
|
||||||
|
union {
|
||||||
|
int i[8];
|
||||||
|
char s[JMSG_STR_PARM_MAX];
|
||||||
|
} msg_parm;
|
||||||
|
|
||||||
|
/* Standard state variables for error facility */
|
||||||
|
|
||||||
|
int trace_level; /* max msg_level that will be displayed */
|
||||||
|
|
||||||
|
/* For recoverable corrupt-data errors, we emit a warning message,
|
||||||
|
* but keep going unless emit_message chooses to abort. emit_message
|
||||||
|
* should count warnings in num_warnings. The surrounding application
|
||||||
|
* can check for bad data by seeing if num_warnings is nonzero at the
|
||||||
|
* end of processing.
|
||||||
|
*/
|
||||||
|
long num_warnings; /* number of corrupt-data warnings */
|
||||||
|
|
||||||
|
/* These fields point to the table(s) of error message strings.
|
||||||
|
* An application can change the table pointer to switch to a different
|
||||||
|
* message list (typically, to change the language in which errors are
|
||||||
|
* reported). Some applications may wish to add additional error codes
|
||||||
|
* that will be handled by the JPEG library error mechanism; the second
|
||||||
|
* table pointer is used for this purpose.
|
||||||
|
*
|
||||||
|
* First table includes all errors generated by JPEG library itself.
|
||||||
|
* Error code 0 is reserved for a "no such error string" message.
|
||||||
|
*/
|
||||||
|
const char * const * jpeg_message_table; /* Library errors */
|
||||||
|
int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
|
||||||
|
/* Second table can be added by application (see cjpeg/djpeg for example).
|
||||||
|
* It contains strings numbered first_addon_message..last_addon_message.
|
||||||
|
*/
|
||||||
|
const char * const * addon_message_table; /* Non-library errors */
|
||||||
|
int first_addon_message; /* code for first string in addon table */
|
||||||
|
int last_addon_message; /* code for last string in addon table */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Progress monitor object */
|
||||||
|
|
||||||
|
struct jpeg_progress_mgr {
|
||||||
|
JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
|
||||||
|
|
||||||
|
long pass_counter; /* work units completed in this pass */
|
||||||
|
long pass_limit; /* total number of work units in this pass */
|
||||||
|
int completed_passes; /* passes completed so far */
|
||||||
|
int total_passes; /* total number of passes expected */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Data destination object for compression */
|
||||||
|
|
||||||
|
struct jpeg_destination_mgr {
|
||||||
|
JOCTET * next_output_byte; /* => next byte to write in buffer */
|
||||||
|
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
|
||||||
|
|
||||||
|
JMETHOD(void, init_destination, (j_compress_ptr cinfo));
|
||||||
|
JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
|
||||||
|
JMETHOD(void, term_destination, (j_compress_ptr cinfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Data source object for decompression */
|
||||||
|
|
||||||
|
struct jpeg_source_mgr {
|
||||||
|
const JOCTET * next_input_byte; /* => next byte to read from buffer */
|
||||||
|
size_t bytes_in_buffer; /* # of bytes remaining in buffer */
|
||||||
|
|
||||||
|
JMETHOD(void, init_source, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
|
||||||
|
JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
|
||||||
|
JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
|
||||||
|
JMETHOD(void, term_source, (j_decompress_ptr cinfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Memory manager object.
|
||||||
|
* Allocates "small" objects (a few K total), "large" objects (tens of K),
|
||||||
|
* and "really big" objects (virtual arrays with backing store if needed).
|
||||||
|
* The memory manager does not allow individual objects to be freed; rather,
|
||||||
|
* each created object is assigned to a pool, and whole pools can be freed
|
||||||
|
* at once. This is faster and more convenient than remembering exactly what
|
||||||
|
* to free, especially where malloc()/free() are not too speedy.
|
||||||
|
* NB: alloc routines never return NULL. They exit to error_exit if not
|
||||||
|
* successful.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
|
||||||
|
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
|
||||||
|
#define JPOOL_NUMPOOLS 2
|
||||||
|
|
||||||
|
typedef struct jvirt_barray_control * jvirt_barray_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
struct jpeg_memory_mgr {
|
||||||
|
/* Method pointers */
|
||||||
|
JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
|
||||||
|
size_t sizeofobject));
|
||||||
|
JMETHOD(void *, alloc_large, (j_common_ptr cinfo, int pool_id,
|
||||||
|
size_t sizeofobject));
|
||||||
|
JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
|
||||||
|
JDIMENSION samplesperrow,
|
||||||
|
JDIMENSION numrows));
|
||||||
|
JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
|
||||||
|
JDIMENSION blocksperrow,
|
||||||
|
JDIMENSION numrows));
|
||||||
|
JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
|
||||||
|
int pool_id,
|
||||||
|
boolean pre_zero,
|
||||||
|
JDIMENSION blocksperrow,
|
||||||
|
JDIMENSION numrows,
|
||||||
|
JDIMENSION maxaccess));
|
||||||
|
JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
|
||||||
|
JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
|
||||||
|
jvirt_barray_ptr ptr,
|
||||||
|
JDIMENSION start_row,
|
||||||
|
JDIMENSION num_rows,
|
||||||
|
boolean writable));
|
||||||
|
JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
|
||||||
|
JMETHOD(void, self_destruct, (j_common_ptr cinfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Routine signature for application-supplied marker processing methods.
|
||||||
|
* Need not pass marker code since it is stored in cinfo->unread_marker.
|
||||||
|
*/
|
||||||
|
typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
|
||||||
|
/* Declarations for routines called by application.
|
||||||
|
* The JPP macro hides prototype parameters from compilers that can't cope.
|
||||||
|
* Note JPP requires double parentheses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_PROTOTYPES
|
||||||
|
#define JPP(arglist) arglist
|
||||||
|
#else
|
||||||
|
#define JPP(arglist) ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Default error-management setup */
|
||||||
|
EXTERN(struct jpeg_error_mgr *) jpeg_std_error
|
||||||
|
JPP((struct jpeg_error_mgr * err));
|
||||||
|
|
||||||
|
/* Initialization of JPEG compression objects.
|
||||||
|
* jpeg_create_compress() and jpeg_create_decompress() are the exported
|
||||||
|
* names that applications should call. These expand to calls on
|
||||||
|
* jpeg_CreateCompress and jpeg_CreateDecompress with additional information
|
||||||
|
* passed for version mismatch checking.
|
||||||
|
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
|
||||||
|
*/
|
||||||
|
#define jpeg_create_compress(cinfo) \
|
||||||
|
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
|
||||||
|
(size_t) sizeof(struct jpeg_compress_struct))
|
||||||
|
#define jpeg_create_decompress(cinfo) \
|
||||||
|
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
|
||||||
|
(size_t) sizeof(struct jpeg_decompress_struct))
|
||||||
|
EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
|
||||||
|
int version, size_t structsize));
|
||||||
|
EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
|
||||||
|
int version, size_t structsize));
|
||||||
|
/* Destruction of JPEG compression objects */
|
||||||
|
EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Standard data source and destination managers: stdio streams. */
|
||||||
|
/* Caller is responsible for opening the file before and closing after. */
|
||||||
|
EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
|
||||||
|
|
||||||
|
/* Default parameter setup for compression */
|
||||||
|
EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
|
||||||
|
/* Compression parameter setup aids */
|
||||||
|
EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
|
||||||
|
J_COLOR_SPACE colorspace));
|
||||||
|
EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
|
||||||
|
boolean force_baseline));
|
||||||
|
EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
|
||||||
|
int scale_factor,
|
||||||
|
boolean force_baseline));
|
||||||
|
EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
|
||||||
|
const unsigned int *basic_table,
|
||||||
|
int scale_factor,
|
||||||
|
boolean force_baseline));
|
||||||
|
EXTERN(int) jpeg_quality_scaling JPP((int quality));
|
||||||
|
EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
|
||||||
|
boolean suppress));
|
||||||
|
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
|
||||||
|
EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
|
||||||
|
|
||||||
|
/* Main entry points for compression */
|
||||||
|
EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
|
||||||
|
boolean write_all_tables));
|
||||||
|
EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
|
||||||
|
JSAMPARRAY scanlines,
|
||||||
|
JDIMENSION num_lines));
|
||||||
|
EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
|
||||||
|
EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
|
||||||
|
JSAMPIMAGE data,
|
||||||
|
JDIMENSION num_lines));
|
||||||
|
|
||||||
|
/* Write a special marker. See libjpeg.doc concerning safe usage. */
|
||||||
|
EXTERN(void) jpeg_write_marker
|
||||||
|
JPP((j_compress_ptr cinfo, int marker,
|
||||||
|
const JOCTET * dataptr, unsigned int datalen));
|
||||||
|
/* Same, but piecemeal. */
|
||||||
|
EXTERN(void) jpeg_write_m_header
|
||||||
|
JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
|
||||||
|
EXTERN(void) jpeg_write_m_byte
|
||||||
|
JPP((j_compress_ptr cinfo, int val));
|
||||||
|
|
||||||
|
/* Alternate compression function: just write an abbreviated table file */
|
||||||
|
EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Decompression startup: read start of JPEG datastream to see what's there */
|
||||||
|
EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
|
||||||
|
boolean require_image));
|
||||||
|
/* Return value is one of: */
|
||||||
|
#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
|
||||||
|
#define JPEG_HEADER_OK 1 /* Found valid image datastream */
|
||||||
|
#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
|
||||||
|
/* If you pass require_image = TRUE (normal case), you need not check for
|
||||||
|
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
|
||||||
|
* JPEG_SUSPENDED is only possible if you use a data source module that can
|
||||||
|
* give a suspension return (the stdio source module doesn't).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Main entry points for decompression */
|
||||||
|
EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
|
||||||
|
EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
|
||||||
|
JSAMPARRAY scanlines,
|
||||||
|
JDIMENSION max_lines));
|
||||||
|
EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Additional entry points for buffered-image mode. */
|
||||||
|
EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
|
||||||
|
/* Return value is one of: */
|
||||||
|
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
|
||||||
|
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
|
||||||
|
#define JPEG_REACHED_EOI 2 /* Reached end of image */
|
||||||
|
#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
|
||||||
|
#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
|
||||||
|
|
||||||
|
/* Precalculate output dimensions for current decompression parameters. */
|
||||||
|
EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Control saving of COM and APPn markers into marker_list. */
|
||||||
|
EXTERN(void) jpeg_save_markers
|
||||||
|
JPP((j_decompress_ptr cinfo, int marker_code,
|
||||||
|
unsigned int length_limit));
|
||||||
|
|
||||||
|
/* Install a special processing method for COM or APPn markers. */
|
||||||
|
EXTERN(void) jpeg_set_marker_processor
|
||||||
|
JPP((j_decompress_ptr cinfo, int marker_code,
|
||||||
|
jpeg_marker_parser_method routine));
|
||||||
|
|
||||||
|
/* If you choose to abort compression or decompression before completing
|
||||||
|
* jpeg_finish_(de)compress, then you need to clean up to release memory,
|
||||||
|
* temporary files, etc. You can just call jpeg_destroy_(de)compress
|
||||||
|
* if you're done with the JPEG object, but if you want to clean it up and
|
||||||
|
* reuse it, call this:
|
||||||
|
*/
|
||||||
|
EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
|
||||||
|
EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
|
||||||
|
|
||||||
|
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
|
||||||
|
* flavor of JPEG object. These may be more convenient in some places.
|
||||||
|
*/
|
||||||
|
EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
|
||||||
|
EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
|
||||||
|
|
||||||
|
/* Default restart-marker-resync procedure for use by data source modules */
|
||||||
|
EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
|
||||||
|
int desired));
|
||||||
|
|
||||||
|
|
||||||
|
/* These marker codes are exported since applications and data source modules
|
||||||
|
* are likely to want to use them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_RST0 0xD0 /* RST0 marker code */
|
||||||
|
#define JPEG_EOI 0xD9 /* EOI marker code */
|
||||||
|
#define JPEG_APP0 0xE0 /* APP0 marker code */
|
||||||
|
#define JPEG_COM 0xFE /* COM marker code */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The JPEG library modules define JPEG_INTERNALS before including this file.
|
||||||
|
* The internal structure declarations are read only when that is true.
|
||||||
|
* Applications using the library should not include jpegint.h, but may wish
|
||||||
|
* to include jerror.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JPEG_INTERNALS
|
||||||
|
#include "jpegint.h" /* fetch private declarations */
|
||||||
|
#include "jerror.h" /* fetch error codes too */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* JPEGLIB_H */
|
103
jpeg-6b/jutils.c
Normal file
103
jpeg-6b/jutils.c
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* jutils.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 tables and miscellaneous utility routines needed
|
||||||
|
* for both compression and decompression.
|
||||||
|
* Note we prefix all global names with "j" to minimize conflicts with
|
||||||
|
* a surrounding application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JPEG_INTERNALS
|
||||||
|
#include "jinclude.h"
|
||||||
|
#include "jpeglib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
|
||||||
|
* of a DCT block read in natural order (left to right, top to bottom).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0 /* This table is not actually needed in v6a */
|
||||||
|
|
||||||
|
const int jpeg_zigzag_order[DCTSIZE2] = {
|
||||||
|
0, 1, 5, 6, 14, 15, 27, 28,
|
||||||
|
2, 4, 7, 13, 16, 26, 29, 42,
|
||||||
|
3, 8, 12, 17, 25, 30, 41, 43,
|
||||||
|
9, 11, 18, 24, 31, 40, 44, 53,
|
||||||
|
10, 19, 23, 32, 39, 45, 52, 54,
|
||||||
|
20, 22, 33, 38, 46, 51, 55, 60,
|
||||||
|
21, 34, 37, 47, 50, 56, 59, 61,
|
||||||
|
35, 36, 48, 49, 57, 58, 62, 63
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jpeg_natural_order[i] is the natural-order position of the i'th element
|
||||||
|
* of zigzag order.
|
||||||
|
*
|
||||||
|
* When reading corrupted data, the Huffman decoders could attempt
|
||||||
|
* to reference an entry beyond the end of this array (if the decoded
|
||||||
|
* zero run length reaches past the end of the block). To prevent
|
||||||
|
* wild stores without adding an inner-loop test, we put some extra
|
||||||
|
* "63"s after the real entries. This will cause the extra coefficient
|
||||||
|
* to be stored in location 63 of the block, not somewhere random.
|
||||||
|
* The worst case would be a run-length of 15, which means we need 16
|
||||||
|
* fake entries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int jpeg_natural_order[DCTSIZE2+16] = {
|
||||||
|
0, 1, 8, 16, 9, 2, 3, 10,
|
||||||
|
17, 24, 32, 25, 18, 11, 4, 5,
|
||||||
|
12, 19, 26, 33, 40, 48, 41, 34,
|
||||||
|
27, 20, 13, 6, 7, 14, 21, 28,
|
||||||
|
35, 42, 49, 56, 57, 50, 43, 36,
|
||||||
|
29, 22, 15, 23, 30, 37, 44, 51,
|
||||||
|
58, 59, 52, 45, 38, 31, 39, 46,
|
||||||
|
53, 60, 61, 54, 47, 55, 62, 63,
|
||||||
|
63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
|
||||||
|
63, 63, 63, 63, 63, 63, 63, 63
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arithmetic utilities
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
|
||||||
|
* and coefficient-block arrays. This won't work on 80x86 because the arrays
|
||||||
|
* are FAR and we're assuming a small-pointer memory model. However, some
|
||||||
|
* DOS compilers provide far-pointer versions of memcpy() and memset() even
|
||||||
|
* in the small-model libraries. These will be used if USE_FMEM is defined.
|
||||||
|
* Otherwise, the routines below do it the hard way. (The performance cost
|
||||||
|
* is not all that great, because these routines aren't very heavily used.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL(void)
|
||||||
|
jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
|
||||||
|
JSAMPARRAY output_array, int dest_row,
|
||||||
|
int num_rows, JDIMENSION num_cols)
|
||||||
|
/* Copy some rows of samples from one place to another.
|
||||||
|
* num_rows rows are copied from input_array[source_row++]
|
||||||
|
* to output_array[dest_row++]; these areas may overlap for duplication.
|
||||||
|
* The source and destination arrays must be at least as wide as num_cols.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
register JSAMPROW inptr, outptr;
|
||||||
|
register JDIMENSION count;
|
||||||
|
register int row;
|
||||||
|
|
||||||
|
input_array += source_row;
|
||||||
|
output_array += dest_row;
|
||||||
|
|
||||||
|
for (row = num_rows; row > 0; row--) {
|
||||||
|
inptr = *input_array++;
|
||||||
|
outptr = *output_array++;
|
||||||
|
for (count = num_cols; count > 0; count--)
|
||||||
|
*outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
|
||||||
|
}
|
||||||
|
}
|
14
jpeg-6b/jversion.h
Normal file
14
jpeg-6b/jversion.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* jversion.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* This file is part of the Independent JPEG Group's software.
|
||||||
|
* For conditions of distribution and use, see the accompanying README file.
|
||||||
|
*
|
||||||
|
* This file contains software version identification.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define JVERSION "6b 27-Mar-1998"
|
||||||
|
|
||||||
|
#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane"
|
27
jpeg-6b/readme-zdoom.txt
Normal file
27
jpeg-6b/readme-zdoom.txt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
This is a stripped version of the Independant JPEG Group's library,
|
||||||
|
available at <http://www.ijg.org/>. The following features have been
|
||||||
|
removed to decrease source code size:
|
||||||
|
|
||||||
|
* All encoding code.
|
||||||
|
* All sample applications.
|
||||||
|
* Most documentation.
|
||||||
|
* Unix configure scripts.
|
||||||
|
* Multiple Makefiles.
|
||||||
|
* Multiple memory managers.
|
||||||
|
* Disk-based backing store. If you don't have enough memory to decode
|
||||||
|
a JPEG file, you probably can't play ZDoom either.
|
||||||
|
* Fast integer DCT routines.
|
||||||
|
* Floating point DCT routines.
|
||||||
|
* Arithmetic coding, due to its patented status. (It is not normally
|
||||||
|
built in the standard version of the library, either.)
|
||||||
|
* Far pointers. Who cares about 16-bit x86? Not me.
|
||||||
|
* IDCT scaling.
|
||||||
|
* Block smoothing.
|
||||||
|
* Color quantization. Looking it up in the RGB32k table is good enough
|
||||||
|
for me.
|
||||||
|
* Transcoding routines.
|
||||||
|
* Buffered image output.
|
||||||
|
* Raw data output.
|
||||||
|
|
||||||
|
A Unix build of ZDoom should just use the system libjpeg instead of
|
||||||
|
this code.
|
571
src/kplib.cpp
571
src/kplib.cpp
|
@ -1,571 +0,0 @@
|
||||||
/**************************************************************************************************
|
|
||||||
KPLIB.C: Ken's Picture LIBrary written by Ken Silverman
|
|
||||||
Copyright (c) 1998-2005 Ken Silverman
|
|
||||||
Ken Silverman's official web site: http://www.advsys.net/ken
|
|
||||||
|
|
||||||
This source file includes routines for decompression of the following picture formats:
|
|
||||||
JPG,PNG,GIF,PCX,TGA,BMP,CEL
|
|
||||||
It also includes code to handle ZIP decompression.
|
|
||||||
|
|
||||||
Brief history:
|
|
||||||
1998?: Wrote KPEG, a JPEG viewer for DOS
|
|
||||||
2000: Wrote KPNG, a PNG viewer for DOS
|
|
||||||
2001: Combined KPEG&KPNG, ported to Visual C, and made it into a nice library called KPLIB.C
|
|
||||||
2002: Added support for: TGA,GIF,CEL,ZIP
|
|
||||||
2003: Added support for: BMP
|
|
||||||
05/18/2004: Added support for 8/24 bit PCX
|
|
||||||
|
|
||||||
I offer this code to the community for the benefit of Jonathon Fowler's Duke3D port.
|
|
||||||
|
|
||||||
-Ken S.
|
|
||||||
**************************************************************************************************/
|
|
||||||
// [RH] Removed everything but JPEG support.
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "m_swap.h"
|
|
||||||
#include "m_fixed.h"
|
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__DOS__)
|
|
||||||
#include <unistd.h>
|
|
||||||
static __inline unsigned long _lrotl (unsigned long i, int sh)
|
|
||||||
{ return((i>>(-sh))|(i<<sh)); }
|
|
||||||
#define _fileno fileno
|
|
||||||
#else
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(max)
|
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#if !defined(min)
|
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define _inline inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//use GCC-specific extension to force symbol name to be something in particular to override underscoring.
|
|
||||||
|
|
||||||
static int bytesperline, xres, yres, globxoffs, globyoffs;
|
|
||||||
static unsigned char *frameplace;
|
|
||||||
|
|
||||||
static const int pow2mask[32] =
|
|
||||||
{
|
|
||||||
0x00000000,0x00000001,0x00000003,0x00000007,
|
|
||||||
0x0000000f,0x0000001f,0x0000003f,0x0000007f,
|
|
||||||
0x000000ff,0x000001ff,0x000003ff,0x000007ff,
|
|
||||||
0x00000fff,0x00001fff,0x00003fff,0x00007fff,
|
|
||||||
0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
|
|
||||||
0x000fffff,0x001fffff,0x003fffff,0x007fffff,
|
|
||||||
0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff,
|
|
||||||
0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,
|
|
||||||
};
|
|
||||||
|
|
||||||
//Initialized tables (can't be in union)
|
|
||||||
//jpg: png:
|
|
||||||
// crmul 16384 abstab10 4096
|
|
||||||
// cbmul 16384 hxbit 472
|
|
||||||
// dct 4608 pow2mask 128*
|
|
||||||
// colclip 4096
|
|
||||||
// colclipup8 4096
|
|
||||||
// colclipup16 4096
|
|
||||||
// unzig 256
|
|
||||||
// pow2mask 128*
|
|
||||||
// dcflagor 64
|
|
||||||
|
|
||||||
int palcol[256], paleng;
|
|
||||||
unsigned char coltype, bitdepth;
|
|
||||||
|
|
||||||
//============================ KPEGILIB begins ===============================
|
|
||||||
|
|
||||||
//11/01/2000: This code was originally from KPEG.C
|
|
||||||
// All non 32-bit color drawing was removed
|
|
||||||
// "Motion" JPG code was removed
|
|
||||||
// A lot of parameters were added to kpeg() for library usage
|
|
||||||
static int clipxdim, clipydim;
|
|
||||||
|
|
||||||
static int hufquickcnt[8];
|
|
||||||
static int hufmaxatbit[8][20], hufvalatbit[8][20], hufcnt[8];
|
|
||||||
static unsigned char hufnumatbit[8][20], huftable[8][256];
|
|
||||||
static unsigned char gnumcomponents, dcflagor[64];
|
|
||||||
static int gcompid[4], gcomphsamp[4], gcompvsamp[4], gcompquantab[4];
|
|
||||||
static int lcompid[4], lcompdc[4], lcompac[4];
|
|
||||||
static int lcomphsamp[4], lcompvsamp[4], lcomphvsamp[4], lcompquantab[4];
|
|
||||||
static int lcomphsampmask[4], lcomphsampshift[4], lcompvsampshift[4];
|
|
||||||
static int quantab[4][64], dct[19][64], lastdc[4], unzig[64];
|
|
||||||
static const unsigned char pow2char[8] = {1,2,4,8,16,32,64,128};
|
|
||||||
|
|
||||||
#define SQRT2 23726566 //(sqrt(2))<<24
|
|
||||||
#define C182 31000253 //(cos(PI/8)*2)<<24
|
|
||||||
#define C18S22 43840978 //(cos(PI/8)*sqrt(2)*2)<<24
|
|
||||||
#define C38S22 18159528 //(cos(PI*3/8)*sqrt(2)*2)<<24
|
|
||||||
static const int cosqr16[8] = //cosqr16[i] = ((cos(PI*i/16)*sqrt(2))<<24);
|
|
||||||
{23726566,23270667,21920489,19727919,16777216,13181774,9079764,4628823};
|
|
||||||
|
|
||||||
// [RH] Moved the bigger tables into a dynamically allocated struct so that
|
|
||||||
// they don't waste space if a JPEG is never loaded.
|
|
||||||
struct kpegtables
|
|
||||||
{
|
|
||||||
int hufquickval[8][1024], hufquickbits[8][1024];
|
|
||||||
int colclip[1024], colclipup8[1024], colclipup16[1024];
|
|
||||||
int crmul[4096], cbmul[4096];
|
|
||||||
};
|
|
||||||
static kpegtables *kpeg;
|
|
||||||
|
|
||||||
static void initkpeg ()
|
|
||||||
{
|
|
||||||
int i, x, y;
|
|
||||||
|
|
||||||
kpeg = new kpegtables;
|
|
||||||
|
|
||||||
x = 0; //Back & forth diagonal pattern (aligning bytes for best compression)
|
|
||||||
for(i=0;i<16;i+=2)
|
|
||||||
{
|
|
||||||
for(y=7;y>=0;y--)
|
|
||||||
if ((unsigned)(i-y) < (unsigned)8) unzig[x++] = (y<<3)+i-y;
|
|
||||||
for(y=0;y<8;y++)
|
|
||||||
if ((unsigned)(i+1-y) < (unsigned)8) unzig[x++] = (y<<3)+i+1-y;
|
|
||||||
}
|
|
||||||
for(i=63;i>=0;i--) dcflagor[i] = (unsigned char)(1<<(unzig[i]>>3));
|
|
||||||
|
|
||||||
for(i=0;i<128;i++) kpeg->colclip[i] = i+128;
|
|
||||||
for(i=128;i<512;i++) kpeg->colclip[i] = 255;
|
|
||||||
for(i=512;i<896;i++) kpeg->colclip[i] = 0;
|
|
||||||
for(i=896;i<1024;i++) kpeg->colclip[i] = i-896;
|
|
||||||
for(i=0;i<1024;i++)
|
|
||||||
{
|
|
||||||
kpeg->colclipup8[i] = (kpeg->colclip[i]<<8);
|
|
||||||
kpeg->colclipup16[i] = (kpeg->colclip[i]<<16)+0xff000000; //Hack: set alphas to 255
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<2048;i++)
|
|
||||||
{
|
|
||||||
kpeg->crmul[(i<<1)+0] = (i-1024)*1470104; //1.402*1048576
|
|
||||||
kpeg->crmul[(i<<1)+1] = (i-1024)*-748830; //-0.71414*1048576
|
|
||||||
kpeg->cbmul[(i<<1)+0] = (i-1024)*-360857; //-0.34414*1048576
|
|
||||||
kpeg->cbmul[(i<<1)+1] = (i-1024)*1858077; //1.772*1048576
|
|
||||||
}
|
|
||||||
|
|
||||||
memset((void *)&dct[16][0],0,64*2*sizeof(dct[0][0]));
|
|
||||||
memset((void *)&dct[18][0],0xa0,64*sizeof(dct[0][0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void huffgetval (int index, int curbits, int num, int *daval, int *dabits)
|
|
||||||
{
|
|
||||||
int b, v, pow2, *hmax;
|
|
||||||
|
|
||||||
hmax = &hufmaxatbit[index][0];
|
|
||||||
pow2 = pow2mask[curbits-1]+1;
|
|
||||||
if (num&pow2) v = 1; else v = 0;
|
|
||||||
for(b=1;b<=16;b++)
|
|
||||||
{
|
|
||||||
if (v < hmax[b])
|
|
||||||
{
|
|
||||||
*dabits = b;
|
|
||||||
*daval = huftable[index][hufvalatbit[index][b]+v];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pow2 >>= 1; v <<= 1;
|
|
||||||
if (num&pow2) v++;
|
|
||||||
}
|
|
||||||
*dabits = 16;
|
|
||||||
*daval = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kpegrend (const char *kfilebuf, int kfilength,
|
|
||||||
unsigned char *daframeplace, int dabytesperline, int daxres, int dayres,
|
|
||||||
int daglobxoffs, int daglobyoffs)
|
|
||||||
{
|
|
||||||
int i, j, v, leng, xdim = 0, ydim = 0, index, prec, restartinterval;
|
|
||||||
int restartcnt, num, curbits, x, y, z, dctcnt, c, cc, daval, dabits;
|
|
||||||
int xx, yy, zz, xxx, yyy, r, g, b, t0, t1, t2, t3, t4, t5, t6, t7;
|
|
||||||
int yv, cr = 0, cb = 0, *dc, *dc2, xxxend, yyyend;
|
|
||||||
int *hqval, *hqbits, hqcnt, *quanptr;
|
|
||||||
unsigned char ch, marker, numbits, lnumcomponents, dcflag, *p;
|
|
||||||
const unsigned char *kfileptr;
|
|
||||||
|
|
||||||
if (kpeg == NULL) { initkpeg(); }
|
|
||||||
|
|
||||||
kfileptr = (unsigned char *)kfilebuf;
|
|
||||||
|
|
||||||
if (*(unsigned short *)kfileptr == 0xd8ff) kfileptr += 2;
|
|
||||||
else return(-1); //"%s is not a JPEG file\n",filename
|
|
||||||
|
|
||||||
restartinterval = 0;
|
|
||||||
for(i=0;i<4;i++) lastdc[i] = 0;
|
|
||||||
for(i=0;i<8;i++) hufcnt[i] = 0;
|
|
||||||
|
|
||||||
coltype = 0; bitdepth = 8; //For PNGOUT
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; if (ch != 255) continue;
|
|
||||||
marker = *kfileptr++;
|
|
||||||
leng = ((int)kfileptr[0]<<8)+(int)kfileptr[1]-2;
|
|
||||||
kfileptr += 2;
|
|
||||||
switch(marker)
|
|
||||||
{
|
|
||||||
case 0xc0: case 0xc1: case 0xc2:
|
|
||||||
//processit!
|
|
||||||
numbits = *kfileptr++;
|
|
||||||
|
|
||||||
ydim = ((int)kfileptr[0]<<8)+(int)kfileptr[1];
|
|
||||||
xdim = ((int)kfileptr[2]<<8)+(int)kfileptr[3];
|
|
||||||
//printf("%s: %ld / %ld = %ld\n",filename,xdim*ydim*3,kfilength,(xdim*ydim*3)/kfilength);
|
|
||||||
|
|
||||||
frameplace = daframeplace;
|
|
||||||
bytesperline = dabytesperline;
|
|
||||||
xres = daxres;
|
|
||||||
yres = dayres;
|
|
||||||
globxoffs = daglobxoffs;
|
|
||||||
globyoffs = daglobyoffs;
|
|
||||||
|
|
||||||
gnumcomponents = kfileptr[4];
|
|
||||||
kfileptr += 5;
|
|
||||||
for(z=0;z<gnumcomponents;z++)
|
|
||||||
{
|
|
||||||
gcompid[z] = kfileptr[0];
|
|
||||||
gcomphsamp[z] = (kfileptr[1]>>4);
|
|
||||||
gcompvsamp[z] = (kfileptr[1]&15);
|
|
||||||
gcompquantab[z] = kfileptr[2];
|
|
||||||
kfileptr += 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0xc4: //Huffman table
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; leng--;
|
|
||||||
if (ch >= 16) { index = ch-12; }
|
|
||||||
else { index = ch; }
|
|
||||||
memcpy((void *)&hufnumatbit[index][1],(void *)kfileptr,16); kfileptr += 16;
|
|
||||||
leng -= 16;
|
|
||||||
|
|
||||||
v = 0; hufcnt[index] = 0;
|
|
||||||
hufquickcnt[index] = 0; c = 0;
|
|
||||||
for(b=1;b<=16;b++)
|
|
||||||
{
|
|
||||||
hufmaxatbit[index][b] = v+hufnumatbit[index][b];
|
|
||||||
hufvalatbit[index][b] = hufcnt[index]-v;
|
|
||||||
memcpy((void *)&huftable[index][hufcnt[index]],(void *)kfileptr,(int)hufnumatbit[index][b]);
|
|
||||||
if (b <= 10)
|
|
||||||
for(c=0;c<hufnumatbit[index][b];c++)
|
|
||||||
for(j=(1<<(10-b));j>0;j--)
|
|
||||||
{
|
|
||||||
kpeg->hufquickval[index][hufquickcnt[index]] = huftable[index][hufcnt[index]+c];
|
|
||||||
kpeg->hufquickbits[index][hufquickcnt[index]] = b;
|
|
||||||
hufquickcnt[index]++;
|
|
||||||
}
|
|
||||||
kfileptr += hufnumatbit[index][b];
|
|
||||||
leng -= hufnumatbit[index][b];
|
|
||||||
hufcnt[index] += hufnumatbit[index][b];
|
|
||||||
v = ((v+hufnumatbit[index][b])<<1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (leng > 0);
|
|
||||||
break;
|
|
||||||
case 0xdb:
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; leng--;
|
|
||||||
index = (ch&15);
|
|
||||||
prec = (ch>>4);
|
|
||||||
for(z=0;z<64;z++)
|
|
||||||
{
|
|
||||||
v = (int)(*kfileptr++);
|
|
||||||
if (prec) v = (v<<8)+((int)(*kfileptr++));
|
|
||||||
v <<= 19;
|
|
||||||
if (unzig[z]&7) v = MulScale24(v,cosqr16[unzig[z]&7]);
|
|
||||||
if (unzig[z]>>3) v = MulScale24(v,cosqr16[unzig[z]>>3]);
|
|
||||||
if (index) v >>= 6;
|
|
||||||
quantab[index][unzig[z]] = v;
|
|
||||||
}
|
|
||||||
leng -= 64;
|
|
||||||
if (prec) leng -= 64;
|
|
||||||
} while (leng > 0);
|
|
||||||
break;
|
|
||||||
case 0xdd:
|
|
||||||
restartinterval = (((int)kfileptr[0])<<8)+((int)kfileptr[1]);
|
|
||||||
kfileptr += leng;
|
|
||||||
break;
|
|
||||||
case 0xda: case 0xd9:
|
|
||||||
if ((xdim <= 0) || (ydim <= 0)) return(-1);
|
|
||||||
|
|
||||||
lnumcomponents = *kfileptr++;
|
|
||||||
if (lnumcomponents > 1) coltype = 2;
|
|
||||||
for(z=0;z<lnumcomponents;z++)
|
|
||||||
{
|
|
||||||
lcompid[z] = kfileptr[0];
|
|
||||||
lcompdc[z] = (kfileptr[1]>>4);
|
|
||||||
lcompac[z] = (kfileptr[1]&15);
|
|
||||||
kfileptr += 2;
|
|
||||||
for(zz=0;zz<gnumcomponents;zz++)
|
|
||||||
if (lcompid[z] == gcompid[zz])
|
|
||||||
{
|
|
||||||
lcomphsamp[z] = gcomphsamp[zz];
|
|
||||||
lcompvsamp[z] = gcompvsamp[zz];
|
|
||||||
lcomphvsamp[z] = lcomphsamp[z]*lcompvsamp[z];
|
|
||||||
lcompquantab[z] = gcompquantab[zz];
|
|
||||||
|
|
||||||
for(i=0;i<8;i++)
|
|
||||||
if (pow2mask[i]+1 == lcomphsamp[z])
|
|
||||||
{
|
|
||||||
lcomphsampmask[z] = pow2mask[i];
|
|
||||||
lcomphsampshift[z] = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<8;i++)
|
|
||||||
if (pow2mask[i]+1 == lcompvsamp[z])
|
|
||||||
{
|
|
||||||
lcompvsampshift[z] = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Ss = kfileptr[0];
|
|
||||||
//Se = kfileptr[1];
|
|
||||||
//Ah = (kfileptr[2]>>4);
|
|
||||||
//Al = (kfileptr[2]&15);
|
|
||||||
kfileptr += 3;
|
|
||||||
|
|
||||||
if ((hufcnt[0] == 0) || (hufcnt[4] == 0)) return(-1);
|
|
||||||
|
|
||||||
clipxdim = min(xdim+globxoffs,xres);
|
|
||||||
clipydim = min(ydim+globyoffs,yres);
|
|
||||||
|
|
||||||
xx = max(globxoffs,0); xxx = min(globxoffs+xdim,xres);
|
|
||||||
yy = max(globyoffs,0); yyy = min(globyoffs+ydim,yres);
|
|
||||||
if ((xx >= xres) || (yy >= yres) || (xxx <= 0) || (yyy <= 0)) return(0);
|
|
||||||
|
|
||||||
restartcnt = restartinterval; marker = 0xd0;
|
|
||||||
num = 0; curbits = 0; x = 0; y = 0;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (kfileptr-(unsigned char *)kfilebuf >= kfilength)
|
|
||||||
lnumcomponents = 0; //rest of file is missing!
|
|
||||||
|
|
||||||
dctcnt = 0;
|
|
||||||
for(c=0;c<lnumcomponents;c++)
|
|
||||||
{
|
|
||||||
hqval = &kpeg->hufquickval[lcompac[c]+4][0];
|
|
||||||
hqbits = &kpeg->hufquickbits[lcompac[c]+4][0];
|
|
||||||
hqcnt = hufquickcnt[lcompac[c]+4];
|
|
||||||
quanptr = &quantab[lcompquantab[c]][0];
|
|
||||||
for(cc=lcomphvsamp[c];cc>0;cc--)
|
|
||||||
{
|
|
||||||
dc = &dct[dctcnt][0];
|
|
||||||
|
|
||||||
//Get DC
|
|
||||||
while (curbits < 16) //Getbits
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; if (ch == 255) kfileptr++;
|
|
||||||
num = (num<<8)+((int)ch); curbits += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = ((num>>(curbits-10))&1023);
|
|
||||||
if (i < hufquickcnt[lcompdc[c]])
|
|
||||||
{ dabits = kpeg->hufquickbits[lcompdc[c]][i]; daval = kpeg->hufquickval[lcompdc[c]][i]; }
|
|
||||||
else
|
|
||||||
huffgetval(lcompdc[c],curbits,num,&daval,&dabits);
|
|
||||||
|
|
||||||
curbits -= dabits;
|
|
||||||
if (daval)
|
|
||||||
{
|
|
||||||
while (curbits < 16) //Getbits
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; if (ch == 255) kfileptr++;
|
|
||||||
num = (num<<8)+((int)ch); curbits += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = ((unsigned)num >> (curbits-daval)) & pow2mask[daval];
|
|
||||||
if (v <= pow2mask[daval-1]) v -= pow2mask[daval];
|
|
||||||
lastdc[c] += v;
|
|
||||||
curbits -= daval;
|
|
||||||
}
|
|
||||||
dc[0] = lastdc[c]*quanptr[0];
|
|
||||||
|
|
||||||
//Get AC
|
|
||||||
memset((void *)&dc[1],0,63*4);
|
|
||||||
dcflag = 1;
|
|
||||||
for(z=1;z<64;z++)
|
|
||||||
{
|
|
||||||
while (curbits < 16) //Getbits
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; if (ch == 255) kfileptr++;
|
|
||||||
num = (num<<8)+((int)ch); curbits += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = ((num>>(curbits-10))&1023);
|
|
||||||
if (i < hqcnt)
|
|
||||||
{ daval = hqval[i]; curbits -= hqbits[i]; }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
huffgetval(lcompac[c]+4,curbits,num,&daval,&dabits);
|
|
||||||
curbits -= dabits;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!daval) break;
|
|
||||||
z += (daval>>4); if (z >= 64) break;
|
|
||||||
daval &= 15;
|
|
||||||
|
|
||||||
while (curbits < 16) //Getbits
|
|
||||||
{
|
|
||||||
ch = *kfileptr++; if (ch == 255) kfileptr++;
|
|
||||||
num = (num<<8)+((int)ch); curbits += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = ((unsigned)num >> (curbits-daval)) & pow2mask[daval];
|
|
||||||
if (v <= pow2mask[daval-1]) v -= pow2mask[daval];
|
|
||||||
dcflag |= dcflagor[z];
|
|
||||||
dc[unzig[z]] = v*quanptr[unzig[z]];
|
|
||||||
curbits -= daval;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(z=0;z<8;z++,dc+=8)
|
|
||||||
{
|
|
||||||
if (!(dcflag&pow2char[z])) continue;
|
|
||||||
t3 = dc[2] + dc[6];
|
|
||||||
t2 = (MulScale32(dc[2]-dc[6],SQRT2<<6)<<2) - t3;
|
|
||||||
t4 = dc[0] + dc[4]; t5 = dc[0] - dc[4];
|
|
||||||
t0 = t4+t3; t3 = t4-t3; t1 = t5+t2; t2 = t5-t2;
|
|
||||||
t4 = (MulScale32(dc[5]-dc[3]+dc[1]-dc[7],C182<<6)<<2);
|
|
||||||
t7 = dc[1] + dc[7] + dc[5] + dc[3];
|
|
||||||
t6 = (MulScale32(dc[3]-dc[5],C18S22<<5)<<3) + t4 - t7;
|
|
||||||
t5 = (MulScale32(dc[1]+dc[7]-dc[5]-dc[3],SQRT2<<6)<<2) - t6;
|
|
||||||
t4 = (MulScale32(dc[1]-dc[7],C38S22<<6)<<2) - t4 + t5;
|
|
||||||
dc[0] = t0+t7; dc[7] = t0-t7; dc[1] = t1+t6; dc[6] = t1-t6;
|
|
||||||
dc[2] = t2+t5; dc[5] = t2-t5; dc[4] = t3+t4; dc[3] = t3-t4;
|
|
||||||
}
|
|
||||||
dc = &dct[dctcnt][0];
|
|
||||||
for(z=7;z>=0;z--,dc++)
|
|
||||||
{
|
|
||||||
t3 = dc[2<<3] + dc[6<<3];
|
|
||||||
t2 = (MulScale32(dc[2<<3]-dc[6<<3],SQRT2<<6)<<2) - t3;
|
|
||||||
t4 = dc[0<<3] + dc[4<<3]; t5 = dc[0<<3] - dc[4<<3];
|
|
||||||
t0 = t4+t3; t3 = t4-t3; t1 = t5+t2; t2 = t5-t2;
|
|
||||||
t4 = (MulScale32(dc[5<<3]-dc[3<<3]+dc[1<<3]-dc[7<<3],C182<<6)<<2);
|
|
||||||
t7 = dc[1<<3] + dc[7<<3] + dc[5<<3] + dc[3<<3];
|
|
||||||
t6 = (MulScale32(dc[3<<3]-dc[5<<3],C18S22<<5)<<3) + t4 - t7;
|
|
||||||
t5 = (MulScale32(dc[1<<3]+dc[7<<3]-dc[5<<3]-dc[3<<3],SQRT2<<6)<<2) - t6;
|
|
||||||
t4 = (MulScale32(dc[1<<3]-dc[7<<3],C38S22<<6)<<2) - t4 + t5;
|
|
||||||
dc[0<<3] = t0+t7; dc[7<<3] = t0-t7; dc[1<<3] = t1+t6; dc[6<<3] = t1-t6;
|
|
||||||
dc[2<<3] = t2+t5; dc[5<<3] = t2-t5; dc[4<<3] = t3+t4; dc[3<<3] = t3-t4;
|
|
||||||
}
|
|
||||||
|
|
||||||
dctcnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dctcnt = 0; dc = &dct[18][0]; dc2 = &dct[16][0];
|
|
||||||
r = g = b = 0; cc = 0;
|
|
||||||
for(yy=0;yy<(lcompvsamp[0]<<3);yy+=8)
|
|
||||||
for(xx=0;xx<(lcomphsamp[0]<<3);xx+=8,dctcnt++)
|
|
||||||
{
|
|
||||||
yyy = y+yy+globyoffs; if ((unsigned)yyy >= (unsigned)clipydim) continue;
|
|
||||||
xxx = x+xx+globxoffs; if ((unsigned)xxx >= (unsigned)clipxdim) continue;
|
|
||||||
p = yyy*bytesperline + xxx*4 + frameplace;
|
|
||||||
if (lnumcomponents > 0) dc = &dct[dctcnt][0];
|
|
||||||
if (lnumcomponents > 1) dc2 = &dct[lcomphvsamp[0]][((yy>>lcompvsampshift[0])<<3)+(xx>>lcomphsampshift[0])];
|
|
||||||
xxxend = min(clipxdim-(x+xx+globxoffs),8);
|
|
||||||
yyyend = min(clipydim-(y+yy+globyoffs),8);
|
|
||||||
if ((lcomphsamp[0] == 1) && (xxxend == 8))
|
|
||||||
{
|
|
||||||
for(yyy=0;yyy<yyyend;yyy++)
|
|
||||||
{
|
|
||||||
for(xxx=0;xxx<8;xxx++)
|
|
||||||
{
|
|
||||||
yv = dc[xxx];
|
|
||||||
cr = (dc2[xxx+64]>>13)&~1;
|
|
||||||
cb = (dc2[xxx]>>13)&~1;
|
|
||||||
((int *)p)[xxx] = kpeg->colclipup16[(unsigned)(yv+kpeg->crmul[cr+2048])>>22]+
|
|
||||||
kpeg->colclipup8[(unsigned)(yv+kpeg->crmul[cr+2049]+kpeg->cbmul[cb+2048])>>22]+
|
|
||||||
kpeg->colclip[(unsigned)(yv+kpeg->cbmul[cb+2049])>>22];
|
|
||||||
}
|
|
||||||
p += bytesperline;
|
|
||||||
dc += 8;
|
|
||||||
if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((lcomphsamp[0] == 2) && (xxxend == 8))
|
|
||||||
{
|
|
||||||
for(yyy=0;yyy<yyyend;yyy++)
|
|
||||||
{
|
|
||||||
for(xxx=0;xxx<8;xxx+=2)
|
|
||||||
{
|
|
||||||
yv = dc[xxx];
|
|
||||||
cr = (dc2[(xxx>>1)+64]>>13)&~1;
|
|
||||||
cb = (dc2[(xxx>>1)]>>13)&~1;
|
|
||||||
i = kpeg->crmul[cr+2049]+kpeg->cbmul[cb+2048];
|
|
||||||
cr = kpeg->crmul[cr+2048];
|
|
||||||
cb = kpeg->cbmul[cb+2049];
|
|
||||||
((int *)p)[xxx] = kpeg->colclipup16[(unsigned)(yv+cr)>>22]+
|
|
||||||
kpeg->colclipup8[(unsigned)(yv+i)>>22]+
|
|
||||||
kpeg->colclip[(unsigned)(yv+cb)>>22];
|
|
||||||
yv = dc[xxx+1];
|
|
||||||
((int *)p)[xxx+1] = kpeg->colclipup16[(unsigned)(yv+cr)>>22]+
|
|
||||||
kpeg->colclipup8[(unsigned)(yv+i)>>22]+
|
|
||||||
kpeg->colclip[(unsigned)(yv+cb)>>22];
|
|
||||||
}
|
|
||||||
p += bytesperline;
|
|
||||||
dc += 8;
|
|
||||||
if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(yyy=0;yyy<yyyend;yyy++)
|
|
||||||
{
|
|
||||||
i = 0; j = 1;
|
|
||||||
for(xxx=0;xxx<xxxend;xxx++)
|
|
||||||
{
|
|
||||||
yv = dc[xxx];
|
|
||||||
j--;
|
|
||||||
if (!j)
|
|
||||||
{
|
|
||||||
j = lcomphsamp[0];
|
|
||||||
cr = (dc2[i+64]>>13)&~1;
|
|
||||||
cb = (dc2[i]>>13)&~1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
((int *)p)[xxx] = kpeg->colclipup16[(unsigned)(yv+kpeg->crmul[cr+2048])>>22]+
|
|
||||||
kpeg->colclipup8[(unsigned)(yv+kpeg->crmul[cr+2049]+kpeg->cbmul[cb+2048])>>22]+
|
|
||||||
kpeg->colclip[(unsigned)(yv+kpeg->cbmul[cb+2049])>>22];
|
|
||||||
}
|
|
||||||
p += bytesperline;
|
|
||||||
dc += 8;
|
|
||||||
if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lnumcomponents) //do only when not EOF...
|
|
||||||
{
|
|
||||||
restartcnt--;
|
|
||||||
if (!restartcnt)
|
|
||||||
{
|
|
||||||
kfileptr += 1-(curbits>>3); curbits = 0;
|
|
||||||
if ((kfileptr[-2] != 255) || (kfileptr[-1] != marker)) kfileptr--;
|
|
||||||
marker++; if (marker >= 0xd8) marker = 0xd0;
|
|
||||||
restartcnt = restartinterval;
|
|
||||||
for(i=0;i<4;i++) lastdc[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
x += (lcomphsamp[0]<<3);
|
|
||||||
if (x >= xdim) { x = 0; y += (lcompvsamp[0]<<3); if (y >= ydim) return(0); }
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
kfileptr += leng;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (kfileptr-(unsigned char *)kfilebuf < kfilength);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================== KPEGILIB ends ==============================
|
|
204
src/r_data.cpp
204
src/r_data.cpp
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
// Emacs style mode select -*- C++ -*-
|
// Emacs style mode select -*- C++ -*-
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -35,6 +36,11 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <jpeglib.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "m_alloc.h"
|
#include "m_alloc.h"
|
||||||
|
@ -57,6 +63,7 @@
|
||||||
|
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
#include "v_text.h"
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
@ -1806,7 +1813,18 @@ void FIMGZTexture::MakeTexture ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BYTE FPNGTexture::GrayMap[256];
|
static BYTE GrayMap[256];
|
||||||
|
|
||||||
|
static void InitGrayMap()
|
||||||
|
{
|
||||||
|
if (GrayMap[0] == GrayMap[255])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
GrayMap[i] = ColorMatcher.Pick (i, i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
||||||
BYTE depth, BYTE colortype, BYTE interlace)
|
BYTE depth, BYTE colortype, BYTE interlace)
|
||||||
|
@ -1901,13 +1919,7 @@ FPNGTexture::FPNGTexture (int lumpnum, int width, int height,
|
||||||
case 0: // Grayscale
|
case 0: // Grayscale
|
||||||
if (!bAlphaTexture)
|
if (!bAlphaTexture)
|
||||||
{
|
{
|
||||||
if (GrayMap[0] == GrayMap[255])
|
InitGrayMap();
|
||||||
{ // Initialize the GrayMap
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
GrayMap[i] = ColorMatcher.Pick (i, i, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (colortype == 0 && havetRNS && trans[0] != 0)
|
if (colortype == 0 && havetRNS && trans[0] != 0)
|
||||||
{
|
{
|
||||||
bMasked = true;
|
bMasked = true;
|
||||||
|
@ -2126,9 +2138,81 @@ void FPNGTexture::MakeTexture ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int kpegrend (const char *kfilebuf, int kfilength,
|
struct FLumpSourceMgr : public jpeg_source_mgr
|
||||||
unsigned char *daframeplace, int dabytesperline, int daxres, int dayres,
|
{
|
||||||
int daglobxoffs, int daglobyoffs);
|
FWadLump &Lump;
|
||||||
|
JOCTET Buffer[4096];
|
||||||
|
bool StartOfFile;
|
||||||
|
|
||||||
|
FLumpSourceMgr (FWadLump &lump, j_decompress_ptr cinfo)
|
||||||
|
: Lump (lump)
|
||||||
|
{
|
||||||
|
cinfo->src = this;
|
||||||
|
init_source = InitSource;
|
||||||
|
fill_input_buffer = FillInputBuffer;
|
||||||
|
skip_input_data = SkipInputData;
|
||||||
|
resync_to_restart = jpeg_resync_to_restart;
|
||||||
|
term_source = TermSource;
|
||||||
|
bytes_in_buffer = 0;
|
||||||
|
next_input_byte = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitSource (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
((FLumpSourceMgr *)(cinfo->src))->StartOfFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean FillInputBuffer (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src);
|
||||||
|
long nbytes = me->Lump.Read (me->Buffer, sizeof(me->Buffer));
|
||||||
|
|
||||||
|
if (nbytes <= 0)
|
||||||
|
{
|
||||||
|
me->Buffer[0] = (JOCTET)0xFF;
|
||||||
|
me->Buffer[1] = (JOCTET)JPEG_EOI;
|
||||||
|
nbytes = 2;
|
||||||
|
}
|
||||||
|
me->next_input_byte = me->Buffer;
|
||||||
|
me->bytes_in_buffer = nbytes;
|
||||||
|
me->StartOfFile = false;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SkipInputData (j_decompress_ptr cinfo, long num_bytes)
|
||||||
|
{
|
||||||
|
FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src);
|
||||||
|
if (num_bytes <= (long)me->bytes_in_buffer)
|
||||||
|
{
|
||||||
|
me->bytes_in_buffer -= num_bytes;
|
||||||
|
me->next_input_byte += num_bytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_bytes -= (long)me->bytes_in_buffer;
|
||||||
|
me->Lump.Seek (num_bytes, SEEK_CUR);
|
||||||
|
FillInputBuffer (cinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TermSource (j_decompress_ptr cinfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void JPEG_ErrorExit (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
(*cinfo->err->output_message) (cinfo);
|
||||||
|
throw -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void JPEG_OutputMessage (j_common_ptr cinfo)
|
||||||
|
{
|
||||||
|
char buffer[JMSG_LENGTH_MAX];
|
||||||
|
|
||||||
|
(*cinfo->err->format_message) (cinfo, buffer);
|
||||||
|
Printf (TEXTCOLOR_ORANGE "JPEG failure: %s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
|
FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
|
||||||
: SourceLump(lumpnum), Pixels(0)
|
: SourceLump(lumpnum), Pixels(0)
|
||||||
|
@ -2200,36 +2284,94 @@ const BYTE *FJPEGTexture::GetPixels ()
|
||||||
|
|
||||||
void FJPEGTexture::MakeTexture ()
|
void FJPEGTexture::MakeTexture ()
|
||||||
{
|
{
|
||||||
FMemLump lump = Wads.ReadLump (SourceLump);
|
FWadLump lump = Wads.OpenLumpNum (SourceLump);
|
||||||
BYTE *rgb = new BYTE[Width * Height * 4];
|
JSAMPLE *buff = NULL;
|
||||||
|
|
||||||
|
jpeg_decompress_struct cinfo;
|
||||||
|
jpeg_error_mgr jerr;
|
||||||
|
|
||||||
Pixels = new BYTE[Width * Height];
|
Pixels = new BYTE[Width * Height];
|
||||||
if (kpegrend ((char *)lump.GetMem(), Wads.LumpLength (SourceLump), rgb, Width * 4, Width, Height, 0, 0) < 0)
|
|
||||||
{ // Failed to read the JPEG
|
|
||||||
memset (Pixels, 0xBA, Width * Height);
|
memset (Pixels, 0xBA, Width * Height);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BYTE *in, *out;
|
|
||||||
int x, y, pitch, backstep;
|
|
||||||
|
|
||||||
in = rgb;
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
out = Pixels;
|
cinfo.err->output_message = JPEG_OutputMessage;
|
||||||
|
cinfo.err->error_exit = JPEG_ErrorExit;
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FLumpSourceMgr sourcemgr(lump, &cinfo);
|
||||||
|
jpeg_read_header(&cinfo, TRUE);
|
||||||
|
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
|
||||||
|
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
|
||||||
|
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
|
||||||
|
{
|
||||||
|
Printf (TEXTCOLOR_ORANGE "Unsupported color format\n", Name);
|
||||||
|
throw -1;
|
||||||
|
}
|
||||||
|
if (cinfo.out_color_space == JCS_GRAYSCALE)
|
||||||
|
{
|
||||||
|
InitGrayMap();
|
||||||
|
}
|
||||||
|
|
||||||
// Convert from source format to paletted, column-major.
|
jpeg_start_decompress(&cinfo);
|
||||||
pitch = Width * 4;
|
|
||||||
backstep = Height * pitch - 4;
|
int y = 0;
|
||||||
for (x = Width; x > 0; --x)
|
buff = new BYTE[cinfo.output_width * cinfo.output_components];
|
||||||
|
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height)
|
||||||
{
|
{
|
||||||
for (y = Height; y > 0; --y)
|
int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1);
|
||||||
|
BYTE *in = buff;
|
||||||
|
BYTE *out = Pixels + y;
|
||||||
|
switch (cinfo.out_color_space)
|
||||||
{
|
{
|
||||||
*out++ = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3];
|
case JCS_RGB:
|
||||||
in += pitch;
|
for (int x = Width; x > 0; --x)
|
||||||
|
{
|
||||||
|
*out = RGB32k[in[0]>>3][in[1]>>3][in[2]>>3];
|
||||||
|
out += Height;
|
||||||
|
in += 3;
|
||||||
}
|
}
|
||||||
in -= backstep;
|
break;
|
||||||
|
|
||||||
|
case JCS_GRAYSCALE:
|
||||||
|
for (int x = Width; x > 0; --x)
|
||||||
|
{
|
||||||
|
*out = GrayMap[in[0]];
|
||||||
|
out += Height;
|
||||||
|
in += 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JCS_CMYK:
|
||||||
|
// What are you doing using a CMYK image? :)
|
||||||
|
for (int x = Width; x > 0; --x)
|
||||||
|
{
|
||||||
|
// To be precise, these calculations should use 255, but
|
||||||
|
// 256 is much faster and virtually indistinguishable.
|
||||||
|
int r = in[3] - (((256-in[0])*in[3]) >> 8);
|
||||||
|
int g = in[3] - (((256-in[1])*in[3]) >> 8);
|
||||||
|
int b = in[3] - (((256-in[2])*in[3]) >> 8);
|
||||||
|
*out = RGB32k[r >> 3][g >> 3][b >> 3];
|
||||||
|
out += Height;
|
||||||
|
in += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
}
|
||||||
|
catch (int)
|
||||||
|
{
|
||||||
|
Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
}
|
||||||
|
if (buff != NULL)
|
||||||
|
{
|
||||||
|
delete[] buff;
|
||||||
}
|
}
|
||||||
delete[] rgb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FBuildTexture::FBuildTexture (int tilenum, const BYTE *pixels, int width, int height, int left, int top)
|
FBuildTexture::FBuildTexture (int tilenum, const BYTE *pixels, int width, int height, int left, int top)
|
||||||
|
|
|
@ -206,8 +206,6 @@ protected:
|
||||||
int PaletteSize;
|
int PaletteSize;
|
||||||
DWORD StartOfIDAT;
|
DWORD StartOfIDAT;
|
||||||
|
|
||||||
static BYTE GrayMap[256];
|
|
||||||
|
|
||||||
void MakeTexture ();
|
void MakeTexture ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
21
zdoom.sln
21
zdoom.sln
|
@ -2,11 +2,12 @@ Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
# Visual Studio 2005
|
# Visual Studio 2005
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zdoom", "zdoom.vcproj", "{8049475B-5C87-46F9-9358-635218A4EF18}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zdoom", "zdoom.vcproj", "{8049475B-5C87-46F9-9358-635218A4EF18}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466} = {AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}
|
||||||
{1D179D4B-F008-431B-8C72-111F8372584F} = {1D179D4B-F008-431B-8C72-111F8372584F}
|
{1D179D4B-F008-431B-8C72-111F8372584F} = {1D179D4B-F008-431B-8C72-111F8372584F}
|
||||||
{F9D9E7D4-E1A2-4866-9E85-B1B14137EE63} = {F9D9E7D4-E1A2-4866-9E85-B1B14137EE63}
|
|
||||||
{6077B7D6-349F-4077-B552-3BC302EF5859} = {6077B7D6-349F-4077-B552-3BC302EF5859}
|
|
||||||
{667D2EE7-C357-49E2-9BAB-0A4A45F0F76E} = {667D2EE7-C357-49E2-9BAB-0A4A45F0F76E}
|
|
||||||
{873F2EEA-24DF-454C-B245-CB9738BA993E} = {873F2EEA-24DF-454C-B245-CB9738BA993E}
|
{873F2EEA-24DF-454C-B245-CB9738BA993E} = {873F2EEA-24DF-454C-B245-CB9738BA993E}
|
||||||
|
{667D2EE7-C357-49E2-9BAB-0A4A45F0F76E} = {667D2EE7-C357-49E2-9BAB-0A4A45F0F76E}
|
||||||
|
{6077B7D6-349F-4077-B552-3BC302EF5859} = {6077B7D6-349F-4077-B552-3BC302EF5859}
|
||||||
|
{F9D9E7D4-E1A2-4866-9E85-B1B14137EE63} = {F9D9E7D4-E1A2-4866-9E85-B1B14137EE63}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcproj", "{F9D9E7D4-E1A2-4866-9E85-B1B14137EE63}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcproj", "{F9D9E7D4-E1A2-4866-9E85-B1B14137EE63}"
|
||||||
|
@ -19,9 +20,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "re2c", "tools\re2c\re2c.vcp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wadsrc", "wadsrc\wadsrc.vcproj", "{1D179D4B-F008-431B-8C72-111F8372584F}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wadsrc", "wadsrc\wadsrc.vcproj", "{1D179D4B-F008-431B-8C72-111F8372584F}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{24A19C02-F041-4AB0-A1A1-02E1E88EDBD3} = {24A19C02-F041-4AB0-A1A1-02E1E88EDBD3}
|
|
||||||
{AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8} = {AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8}
|
|
||||||
{3FFA68B3-9449-4B03-ADEE-194C3638623B} = {3FFA68B3-9449-4B03-ADEE-194C3638623B}
|
{3FFA68B3-9449-4B03-ADEE-194C3638623B} = {3FFA68B3-9449-4B03-ADEE-194C3638623B}
|
||||||
|
{AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8} = {AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8}
|
||||||
|
{24A19C02-F041-4AB0-A1A1-02E1E88EDBD3} = {24A19C02-F041-4AB0-A1A1-02E1E88EDBD3}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makewad", "tools\makewad\makewad.vcproj", "{24A19C02-F041-4AB0-A1A1-02E1E88EDBD3}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makewad", "tools\makewad\makewad.vcproj", "{24A19C02-F041-4AB0-A1A1-02E1E88EDBD3}"
|
||||||
|
@ -33,12 +34,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xlatcc", "tools\xlatcc\xlat
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dehsupp", "tools\dehsupp\dehsupp.vcproj", "{AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dehsupp", "tools\dehsupp\dehsupp.vcproj", "{AC64EE8F-F019-4A3E-BCAF-BD1FD072B9C8}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{0F80ACBF-460E-44F0-B28E-B3272D1774A7} = {0F80ACBF-460E-44F0-B28E-B3272D1774A7}
|
|
||||||
{667D2EE7-C357-49E2-9BAB-0A4A45F0F76E} = {667D2EE7-C357-49E2-9BAB-0A4A45F0F76E}
|
{667D2EE7-C357-49E2-9BAB-0A4A45F0F76E} = {667D2EE7-C357-49E2-9BAB-0A4A45F0F76E}
|
||||||
|
{0F80ACBF-460E-44F0-B28E-B3272D1774A7} = {0F80ACBF-460E-44F0-B28E-B3272D1774A7}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "updaterevision", "tools\updaterevision\updaterevision.vcproj", "{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "updaterevision", "tools\updaterevision\updaterevision.vcproj", "{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg-6b", "jpeg-6b\jpeg-6b.vcproj", "{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -127,6 +130,12 @@ Global
|
||||||
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|Win32.Build.0 = Release|Win32
|
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|Win32.Build.0 = Release|Win32
|
||||||
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|x64.ActiveCfg = Release|Win32
|
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|x64.ActiveCfg = Release|Win32
|
||||||
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|x64.Build.0 = Release|Win32
|
{6077B7D6-349F-4077-B552-3BC302EF5859}.Release|x64.Build.0 = Release|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Debug|x64.ActiveCfg = Debug|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{AC3F5340-40CB-4C3A-8AA7-CB7158DB4466}.Release|x64.ActiveCfg = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
AdditionalIncludeDirectories="src\win32,src\sound,src,zlib,src\g_shared,src\g_doom,src\g_raven,src\g_heretic,src\g_hexen,src\g_strife;flac"
|
AdditionalIncludeDirectories="src\win32,src\sound,src,zlib,src\g_shared,src\g_doom,src\g_raven,src\g_heretic,src\g_hexen,src\g_strife;flac;jpeg-6b"
|
||||||
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH"
|
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,USEASM,HAVE_STRUPR,HAVE_FILELENGTH"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
|
@ -284,7 +284,7 @@
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac"
|
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;flac;jpeg-6b"
|
||||||
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH"
|
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,USEASM,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
|
@ -1924,10 +1924,6 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\src\kplib.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\lumpconfigfile.cpp"
|
RelativePath=".\src\lumpconfigfile.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue