Re-add relevant files and tests from libjpeg v6b
This commit is contained in:
30
Makefile.am
30
Makefile.am
@@ -31,7 +31,7 @@ endif
|
||||
|
||||
TSTHDRS = rrutil.h rrtimer.h
|
||||
|
||||
noinst_PROGRAMS = jpgtest jpegut cjpeg djpeg
|
||||
noinst_PROGRAMS = jpgtest jpegut cjpeg djpeg jpegtran rdjpgcom wrjpgcom
|
||||
|
||||
jpgtest_SOURCES = $(TSTHDRS) jpgtest.cxx bmp.h bmp.c
|
||||
|
||||
@@ -56,3 +56,31 @@ djpeg_LDADD = $(top_srcdir)/libjpeg.la
|
||||
|
||||
djpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \
|
||||
-DTARGA_SUPPORTED
|
||||
|
||||
jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c
|
||||
|
||||
jpegtran_LDADD = $(top_srcdir)/libjpeg.la
|
||||
|
||||
rdjpgcom_SOURCES = wrjpgcom.c
|
||||
|
||||
rdjpgcom_LDADD = $(top_srcdir)/libjpeg.la
|
||||
|
||||
wrjpgcom_SOURCES = wrjpgcom.c
|
||||
|
||||
wrjpgcom_LDADD = $(top_srcdir)/libjpeg.la
|
||||
|
||||
test: cjpeg djpeg jpegtran
|
||||
$(RM) testout*
|
||||
$(top_srcdir)/jpegut
|
||||
$(top_srcdir)/djpeg -dct int -ppm -outfile testout.ppm $(top_srcdir)/testorig.jpg
|
||||
$(top_srcdir)/djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(top_srcdir)/testorig.jpg
|
||||
$(top_srcdir)/cjpeg -dct int -outfile testout.jpg $(top_srcdir)/testimg.ppm
|
||||
$(top_srcdir)/djpeg -dct int -ppm -outfile testoutp.ppm $(top_srcdir)/testprog.jpg
|
||||
$(top_srcdir)/cjpeg -dct int -progressive -opt -outfile testoutp.jpg $(top_srcdir)/testimg.ppm
|
||||
$(top_srcdir)/jpegtran -outfile testoutt.jpg $(top_srcdir)/testprog.jpg
|
||||
cmp $(top_srcdir)/testimg.ppm testout.ppm
|
||||
cmp $(top_srcdir)/testimg.bmp testout.bmp
|
||||
cmp $(top_srcdir)/testimg.jpg testout.jpg
|
||||
cmp $(top_srcdir)/testimg.ppm testoutp.ppm
|
||||
cmp $(top_srcdir)/testimgp.jpg testoutp.jpg
|
||||
cmp $(top_srcdir)/testorig.jpg testoutt.jpg
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
This directory includes a copy of the Independent JPEG Group's JPEG
|
||||
library (see the README file for more information). Not all the files
|
||||
from the original distribution have been included into the TigerVNC
|
||||
codebase. To obtain the original library, please see the README file,
|
||||
section "ARCHIVE LOCATIONS".
|
||||
217
change.log
Normal file
217
change.log
Normal file
@@ -0,0 +1,217 @@
|
||||
CHANGE LOG for Independent JPEG Group's JPEG software
|
||||
|
||||
|
||||
Version 6b 27-Mar-1998
|
||||
-----------------------
|
||||
|
||||
jpegtran has new features for lossless image transformations (rotation
|
||||
and flipping) as well as "lossless" reduction to grayscale.
|
||||
|
||||
jpegtran now copies comments by default; it has a -copy switch to enable
|
||||
copying all APPn blocks as well, or to suppress comments. (Formerly it
|
||||
always suppressed comments and APPn blocks.) jpegtran now also preserves
|
||||
JFIF version and resolution information.
|
||||
|
||||
New decompressor library feature: COM and APPn markers found in the input
|
||||
file can be saved in memory for later use by the application. (Before,
|
||||
you had to code this up yourself with a custom marker processor.)
|
||||
|
||||
There is an unused field "void * client_data" now in compress and decompress
|
||||
parameter structs; this may be useful in some applications.
|
||||
|
||||
JFIF version number information is now saved by the decoder and accepted by
|
||||
the encoder. jpegtran uses this to copy the source file's version number,
|
||||
to ensure "jpegtran -copy all" won't create bogus files that contain JFXX
|
||||
extensions but claim to be version 1.01. Applications that generate their
|
||||
own JFXX extension markers also (finally) have a supported way to cause the
|
||||
encoder to emit JFIF version number 1.02.
|
||||
|
||||
djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather
|
||||
than as unknown APP0 markers.
|
||||
|
||||
In -verbose mode, djpeg and rdjpgcom will try to print the contents of
|
||||
APP12 markers as text. Some digital cameras store useful text information
|
||||
in APP12 markers.
|
||||
|
||||
Handling of truncated data streams is more robust: blocks beyond the one in
|
||||
which the error occurs will be output as uniform gray, or left unchanged
|
||||
if decoding a progressive JPEG. The appearance no longer depends on the
|
||||
Huffman tables being used.
|
||||
|
||||
Huffman tables are checked for validity much more carefully than before.
|
||||
|
||||
To avoid the Unisys LZW patent, djpeg's GIF output capability has been
|
||||
changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
|
||||
has been removed altogether. We're not happy about it either, but there
|
||||
seems to be no good alternative.
|
||||
|
||||
The configure script now supports building libjpeg as a shared library
|
||||
on many flavors of Unix (all the ones that GNU libtool knows how to
|
||||
build shared libraries for). Use "./configure --enable-shared" to
|
||||
try this out.
|
||||
|
||||
New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio.
|
||||
Also, a jconfig file and a build script for Metrowerks CodeWarrior
|
||||
on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there
|
||||
are miscellaneous other minor improvements in the makefiles.
|
||||
|
||||
jmemmac.c now knows how to create temporary files following Mac System 7
|
||||
conventions.
|
||||
|
||||
djpeg's -map switch is now able to read raw-format PPM files reliably.
|
||||
|
||||
cjpeg -progressive -restart no longer generates any unnecessary DRI markers.
|
||||
|
||||
Multiple calls to jpeg_simple_progression for a single JPEG object
|
||||
no longer leak memory.
|
||||
|
||||
|
||||
Version 6a 7-Feb-96
|
||||
--------------------
|
||||
|
||||
Library initialization sequence modified to detect version mismatches
|
||||
and struct field packing mismatches between library and calling application.
|
||||
This change requires applications to be recompiled, but does not require
|
||||
any application source code change.
|
||||
|
||||
All routine declarations changed to the style "GLOBAL(type) name ...",
|
||||
that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the
|
||||
routine's return type as an argument. This makes it possible to add
|
||||
Microsoft-style linkage keywords to all the routines by changing just
|
||||
these macros. Note that any application code that was using these macros
|
||||
will have to be changed.
|
||||
|
||||
DCT coefficient quantization tables are now stored in normal array order
|
||||
rather than zigzag order. Application code that calls jpeg_add_quant_table,
|
||||
or otherwise manipulates quantization tables directly, will need to be
|
||||
changed. If you need to make such code work with either older or newer
|
||||
versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is
|
||||
recommended.
|
||||
|
||||
djpeg's trace capability now dumps DQT tables in natural order, not zigzag
|
||||
order. This allows the trace output to be made into a "-qtables" file
|
||||
more easily.
|
||||
|
||||
New system-dependent memory manager module for use on Apple Macintosh.
|
||||
|
||||
Fix bug in cjpeg's -smooth option: last one or two scanlines would be
|
||||
duplicates of the prior line unless the image height mod 16 was 1 or 2.
|
||||
|
||||
Repair minor problems in VMS, BCC, MC6 makefiles.
|
||||
|
||||
New configure script based on latest GNU Autoconf.
|
||||
|
||||
Correct the list of include files needed by MetroWerks C for ccommand().
|
||||
|
||||
Numerous small documentation updates.
|
||||
|
||||
|
||||
Version 6 2-Aug-95
|
||||
-------------------
|
||||
|
||||
Progressive JPEG support: library can read and write full progressive JPEG
|
||||
files. A "buffered image" mode supports incremental decoding for on-the-fly
|
||||
display of progressive images. Simply recompiling an existing IJG-v5-based
|
||||
decoder with v6 should allow it to read progressive files, though of course
|
||||
without any special progressive display.
|
||||
|
||||
New "jpegtran" application performs lossless transcoding between different
|
||||
JPEG formats; primarily, it can be used to convert baseline to progressive
|
||||
JPEG and vice versa. In support of jpegtran, the library now allows lossless
|
||||
reading and writing of JPEG files as DCT coefficient arrays. This ability
|
||||
may be of use in other applications.
|
||||
|
||||
Notes for programmers:
|
||||
* We changed jpeg_start_decompress() to be able to suspend; this makes all
|
||||
decoding modes available to suspending-input applications. However,
|
||||
existing applications that use suspending input will need to be changed
|
||||
to check the return value from jpeg_start_decompress(). You don't need to
|
||||
do anything if you don't use a suspending data source.
|
||||
* We changed the interface to the virtual array routines: access_virt_array
|
||||
routines now take a count of the number of rows to access this time. The
|
||||
last parameter to request_virt_array routines is now interpreted as the
|
||||
maximum number of rows that may be accessed at once, but not necessarily
|
||||
the height of every access.
|
||||
|
||||
|
||||
Version 5b 15-Mar-95
|
||||
---------------------
|
||||
|
||||
Correct bugs with grayscale images having v_samp_factor > 1.
|
||||
|
||||
jpeg_write_raw_data() now supports output suspension.
|
||||
|
||||
Correct bugs in "configure" script for case of compiling in
|
||||
a directory other than the one containing the source files.
|
||||
|
||||
Repair bug in jquant1.c: sometimes didn't use as many colors as it could.
|
||||
|
||||
Borland C makefile and jconfig file work under either MS-DOS or OS/2.
|
||||
|
||||
Miscellaneous improvements to documentation.
|
||||
|
||||
|
||||
Version 5a 7-Dec-94
|
||||
--------------------
|
||||
|
||||
Changed color conversion roundoff behavior so that grayscale values are
|
||||
represented exactly. (This causes test image files to change.)
|
||||
|
||||
Make ordered dither use 16x16 instead of 4x4 pattern for a small quality
|
||||
improvement.
|
||||
|
||||
New configure script based on latest GNU Autoconf.
|
||||
Fix configure script to handle CFLAGS correctly.
|
||||
Rename *.auto files to *.cfg, so that configure script still works if
|
||||
file names have been truncated for DOS.
|
||||
|
||||
Fix bug in rdbmp.c: didn't allow for extra data between header and image.
|
||||
|
||||
Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data.
|
||||
|
||||
Fix several bugs in rdrle.c.
|
||||
|
||||
NEED_SHORT_EXTERNAL_NAMES option was broken.
|
||||
|
||||
Revise jerror.h/jerror.c for more flexibility in message table.
|
||||
|
||||
Repair oversight in jmemname.c NO_MKTEMP case: file could be there
|
||||
but unreadable.
|
||||
|
||||
|
||||
Version 5 24-Sep-94
|
||||
--------------------
|
||||
|
||||
Version 5 represents a nearly complete redesign and rewrite of the IJG
|
||||
software. Major user-visible changes include:
|
||||
* Automatic configuration simplifies installation for most Unix systems.
|
||||
* A range of speed vs. image quality tradeoffs are supported.
|
||||
This includes resizing of an image during decompression: scaling down
|
||||
by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
|
||||
* New programs rdjpgcom and wrjpgcom allow insertion and extraction
|
||||
of text comments in a JPEG file.
|
||||
|
||||
The application programmer's interface to the library has changed completely.
|
||||
Notable improvements include:
|
||||
* We have eliminated the use of callback routines for handling the
|
||||
uncompressed image data. The application now sees the library as a
|
||||
set of routines that it calls to read or write image data on a
|
||||
scanline-by-scanline basis.
|
||||
* The application image data is represented in a conventional interleaved-
|
||||
pixel format, rather than as a separate array for each color channel.
|
||||
This can save a copying step in many programs.
|
||||
* The handling of compressed data has been cleaned up: the application can
|
||||
supply routines to source or sink the compressed data. It is possible to
|
||||
suspend processing on source/sink buffer overrun, although this is not
|
||||
supported in all operating modes.
|
||||
* All static state has been eliminated from the library, so that multiple
|
||||
instances of compression or decompression can be active concurrently.
|
||||
* JPEG abbreviated datastream formats are supported, ie, quantization and
|
||||
Huffman tables can be stored separately from the image data.
|
||||
* And not only that, but the documentation of the library has improved
|
||||
considerably!
|
||||
|
||||
|
||||
The last widely used release before the version 5 rewrite was version 4A of
|
||||
18-Feb-93. Change logs before that point have been discarded, since they
|
||||
are not of much interest after the rewrite.
|
||||
118
coderules.doc
Normal file
118
coderules.doc
Normal file
@@ -0,0 +1,118 @@
|
||||
IJG JPEG LIBRARY: CODING RULES
|
||||
|
||||
Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
|
||||
Since numerous people will be contributing code and bug fixes, it's important
|
||||
to establish a common coding style. The goal of using similar coding styles
|
||||
is much more important than the details of just what that style is.
|
||||
|
||||
In general we follow the recommendations of "Recommended C Style and Coding
|
||||
Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
|
||||
Brader). This document is available in the IJG FTP archive (see
|
||||
jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
|
||||
|
||||
Block comments should be laid out thusly:
|
||||
|
||||
/*
|
||||
* Block comments in this style.
|
||||
*/
|
||||
|
||||
We indent statements in K&R style, e.g.,
|
||||
if (test) {
|
||||
then-part;
|
||||
} else {
|
||||
else-part;
|
||||
}
|
||||
with two spaces per indentation level. (This indentation convention is
|
||||
handled automatically by GNU Emacs and many other text editors.)
|
||||
|
||||
Multi-word names should be written in lower case with underscores, e.g.,
|
||||
multi_word_name (not multiWordName). Preprocessor symbols and enum constants
|
||||
are similar but upper case (MULTI_WORD_NAME). Names should be unique within
|
||||
the first fifteen characters. (On some older systems, global names must be
|
||||
unique within six characters. We accommodate this without cluttering the
|
||||
source code by using macros to substitute shorter names.)
|
||||
|
||||
We use function prototypes everywhere; we rely on automatic source code
|
||||
transformation to feed prototype-less C compilers. Transformation is done
|
||||
by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript).
|
||||
ansi2knr is not very bright, so it imposes a format requirement on function
|
||||
declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
|
||||
should be written in the following style:
|
||||
|
||||
LOCAL(int *)
|
||||
function_name (int a, char *b)
|
||||
{
|
||||
code...
|
||||
}
|
||||
|
||||
Note that each function definition must begin with GLOBAL(type), LOCAL(type),
|
||||
or METHODDEF(type). These macros expand to "static type" or just "type" as
|
||||
appropriate. They provide a readable indication of the routine's usage and
|
||||
can readily be changed for special needs. (For instance, special linkage
|
||||
keywords can be inserted for use in Windows DLLs.)
|
||||
|
||||
ansi2knr does not transform method declarations (function pointers in
|
||||
structs). We handle these with a macro JMETHOD, defined as
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
|
||||
#else
|
||||
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
|
||||
#endif
|
||||
which is used like this:
|
||||
struct function_pointers {
|
||||
JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp));
|
||||
JMETHOD(void, term_entropy_encoder, (void));
|
||||
};
|
||||
Note the set of parentheses surrounding the parameter list.
|
||||
|
||||
A similar solution is used for forward and external function declarations
|
||||
(see the EXTERN and JPP macros).
|
||||
|
||||
If the code is to work on non-ANSI compilers, we cannot rely on a prototype
|
||||
declaration to coerce actual parameters into the right types. Therefore, use
|
||||
explicit casts on actual parameters whenever the actual parameter type is not
|
||||
identical to the formal parameter. Beware of implicit conversions to "int".
|
||||
|
||||
It seems there are some non-ANSI compilers in which the sizeof() operator
|
||||
is defined to return int, yet size_t is defined as long. Needless to say,
|
||||
this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
|
||||
so that the result is guaranteed to be of type size_t.
|
||||
|
||||
|
||||
The JPEG library is intended to be used within larger programs. Furthermore,
|
||||
we want it to be reentrant so that it can be used by applications that process
|
||||
multiple images concurrently. The following rules support these requirements:
|
||||
|
||||
1. Avoid direct use of file I/O, "malloc", error report printouts, etc;
|
||||
pass these through the common routines provided.
|
||||
|
||||
2. Minimize global namespace pollution. Functions should be declared static
|
||||
wherever possible. (Note that our method-based calling conventions help this
|
||||
a lot: in many modules only the initialization function will ever need to be
|
||||
called directly, so only that function need be externally visible.) All
|
||||
global function names should begin with "jpeg_", and should have an
|
||||
abbreviated name (unique in the first six characters) substituted by macro
|
||||
when NEED_SHORT_EXTERNAL_NAMES is set.
|
||||
|
||||
3. Don't use global variables; anything that must be used in another module
|
||||
should be in the common data structures.
|
||||
|
||||
4. Don't use static variables except for read-only constant tables. Variables
|
||||
that should be private to a module can be placed into private structures (see
|
||||
the system architecture document, structure.doc).
|
||||
|
||||
5. Source file names should begin with "j" for files that are part of the
|
||||
library proper; source files that are not part of the library, such as cjpeg.c
|
||||
and djpeg.c, do not begin with "j". Keep source file names to eight
|
||||
characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep
|
||||
compression and decompression code in separate source files --- some
|
||||
applications may want only one half of the library.
|
||||
|
||||
Note: these rules (particularly #4) are not followed religiously in the
|
||||
modules that are used in cjpeg/djpeg but are not part of the JPEG library
|
||||
proper. Those modules are not really intended to be used in other
|
||||
applications.
|
||||
433
example.c
Normal file
433
example.c
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* example.c
|
||||
*
|
||||
* This file illustrates how to use the IJG code as a subroutine library
|
||||
* to read or write JPEG image files. You should look at this code in
|
||||
* conjunction with the documentation file libjpeg.doc.
|
||||
*
|
||||
* This code will not do anything useful as-is, but it may be helpful as a
|
||||
* skeleton for constructing routines that call the JPEG library.
|
||||
*
|
||||
* We present these routines in the same coding style used in the JPEG code
|
||||
* (ANSI function definitions, etc); but you are of course free to code your
|
||||
* routines in a different style if you prefer.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Include file for users of JPEG library.
|
||||
* You will need to have included system headers that define at least
|
||||
* the typedefs FILE and size_t before you can include jpeglib.h.
|
||||
* (stdio.h is sufficient on ANSI-conforming systems.)
|
||||
* You may also wish to include "jerror.h".
|
||||
*/
|
||||
|
||||
#include "jpeglib.h"
|
||||
|
||||
/*
|
||||
* <setjmp.h> is used for the optional error recovery mechanism shown in
|
||||
* the second part of the example.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
|
||||
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
|
||||
|
||||
/* This half of the example shows how to feed data into the JPEG compressor.
|
||||
* We present a minimal version that does not worry about refinements such
|
||||
* as error recovery (the JPEG code will just exit() if it gets an error).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* IMAGE DATA FORMATS:
|
||||
*
|
||||
* The standard input image format is a rectangular array of pixels, with
|
||||
* each pixel having the same number of "component" values (color channels).
|
||||
* Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
|
||||
* If you are working with color data, then the color values for each pixel
|
||||
* must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
|
||||
* RGB color.
|
||||
*
|
||||
* For this example, we'll assume that this data structure matches the way
|
||||
* our application has stored the image in memory, so we can just pass a
|
||||
* pointer to our image buffer. In particular, let's say that the image is
|
||||
* RGB color and is described by:
|
||||
*/
|
||||
|
||||
extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
|
||||
extern int image_height; /* Number of rows in image */
|
||||
extern int image_width; /* Number of columns in image */
|
||||
|
||||
|
||||
/*
|
||||
* Sample routine for JPEG compression. We assume that the target file name
|
||||
* and a compression quality factor are passed in.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
write_JPEG_file (char * filename, int quality)
|
||||
{
|
||||
/* This struct contains the JPEG compression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
* It is possible to have several such structures, representing multiple
|
||||
* compression/decompression processes, in existence at once. We refer
|
||||
* to any one struct (and its associated working data) as a "JPEG object".
|
||||
*/
|
||||
struct jpeg_compress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler. It is declared separately
|
||||
* because applications often want to supply a specialized error handler
|
||||
* (see the second half of this file for an example). But here we just
|
||||
* take the easy way out and use the standard error handler, which will
|
||||
* print a message on stderr and call exit() if compression fails.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct jpeg_error_mgr jerr;
|
||||
/* More stuff */
|
||||
FILE * outfile; /* target file */
|
||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||
int row_stride; /* physical row width in image buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG compression object */
|
||||
|
||||
/* We have to set up the error handler first, in case the initialization
|
||||
* step fails. (Unlikely, but it could happen if you are out of memory.)
|
||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||
* address which we place into the link field in cinfo.
|
||||
*/
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg_create_compress(&cinfo);
|
||||
|
||||
/* Step 2: specify data destination (eg, a file) */
|
||||
/* Note: steps 2 and 3 can be done in either order. */
|
||||
|
||||
/* Here we use the library-supplied code to send compressed data to a
|
||||
* stdio stream. You can also write your own code to do something else.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to write binary files.
|
||||
*/
|
||||
if ((outfile = fopen(filename, "wb")) == NULL) {
|
||||
fprintf(stderr, "can't open %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
jpeg_stdio_dest(&cinfo, outfile);
|
||||
|
||||
/* Step 3: set parameters for compression */
|
||||
|
||||
/* First we supply a description of the input image.
|
||||
* Four fields of the cinfo struct must be filled in:
|
||||
*/
|
||||
cinfo.image_width = image_width; /* image width and height, in pixels */
|
||||
cinfo.image_height = image_height;
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||
/* Now use the library's routine to set default compression parameters.
|
||||
* (You must set at least cinfo.in_color_space before calling this,
|
||||
* since the defaults depend on the source color space.)
|
||||
*/
|
||||
jpeg_set_defaults(&cinfo);
|
||||
/* Now you can set any non-default parameters you wish to.
|
||||
* Here we just illustrate the use of quality (quantization table) scaling:
|
||||
*/
|
||||
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
||||
|
||||
/* Step 4: Start compressor */
|
||||
|
||||
/* TRUE ensures that we will write a complete interchange-JPEG file.
|
||||
* Pass TRUE unless you are very sure of what you're doing.
|
||||
*/
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
/* Step 5: while (scan lines remain to be written) */
|
||||
/* jpeg_write_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though.
|
||||
*/
|
||||
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could pass
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
|
||||
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
/* After finish_compress, we can close the output file. */
|
||||
fclose(outfile);
|
||||
|
||||
/* Step 7: release JPEG compression object */
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
/* And we're done! */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SOME FINE POINTS:
|
||||
*
|
||||
* In the above loop, we ignored the return value of jpeg_write_scanlines,
|
||||
* which is the number of scanlines actually written. We could get away
|
||||
* with this because we were only relying on the value of cinfo.next_scanline,
|
||||
* which will be incremented correctly. If you maintain additional loop
|
||||
* variables then you should be careful to increment them properly.
|
||||
* Actually, for output to a stdio stream you needn't worry, because
|
||||
* then jpeg_write_scanlines will write all the lines passed (or else exit
|
||||
* with a fatal error). Partial writes can only occur if you use a data
|
||||
* destination module that can demand suspension of the compressor.
|
||||
* (If you don't know what that's for, you don't need it.)
|
||||
*
|
||||
* If the compressor requires full-image buffers (for entropy-coding
|
||||
* optimization or a multi-scan JPEG file), it will create temporary
|
||||
* files for anything that doesn't fit within the maximum-memory setting.
|
||||
* (Note that temp files are NOT needed if you use the default parameters.)
|
||||
* On some systems you may need to set up a signal handler to ensure that
|
||||
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
||||
*
|
||||
* Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
|
||||
* files to be compatible with everyone else's. If you cannot readily read
|
||||
* your data in that order, you'll need an intermediate array to hold the
|
||||
* image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
|
||||
* source data using the JPEG code's internal virtual-array mechanisms.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
|
||||
|
||||
/* This half of the example shows how to read data from the JPEG decompressor.
|
||||
* It's a bit more refined than the above, in that we show:
|
||||
* (a) how to modify the JPEG library's standard error-reporting behavior;
|
||||
* (b) how to allocate workspace using the library's memory manager.
|
||||
*
|
||||
* Just to make this example a little different from the first one, we'll
|
||||
* assume that we do not intend to put the whole image into an in-memory
|
||||
* buffer, but to send it line-by-line someplace else. We need a one-
|
||||
* scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
|
||||
* memory manager allocate it for us. This approach is actually quite useful
|
||||
* because we don't need to remember to deallocate the buffer separately: it
|
||||
* will go away automatically when the JPEG object is cleaned up.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* ERROR HANDLING:
|
||||
*
|
||||
* The JPEG library's standard error handler (jerror.c) is divided into
|
||||
* several "methods" which you can override individually. This lets you
|
||||
* adjust the behavior without duplicating a lot of code, which you might
|
||||
* have to update with each future release.
|
||||
*
|
||||
* Our example here shows how to override the "error_exit" method so that
|
||||
* control is returned to the library's caller when a fatal error occurs,
|
||||
* rather than calling exit() as the standard error_exit method does.
|
||||
*
|
||||
* We use C's setjmp/longjmp facility to return control. This means that the
|
||||
* routine which calls the JPEG library must first execute a setjmp() call to
|
||||
* establish the return point. We want the replacement error_exit to do a
|
||||
* longjmp(). But we need to make the setjmp buffer accessible to the
|
||||
* error_exit routine. To do this, we make a private extension of the
|
||||
* standard JPEG error handler object. (If we were using C++, we'd say we
|
||||
* were making a subclass of the regular error handler.)
|
||||
*
|
||||
* Here's the extended error handler struct:
|
||||
*/
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr * my_error_ptr;
|
||||
|
||||
/*
|
||||
* Here's the routine that will replace the standard error_exit method:
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sample routine for JPEG decompression. We assume that the source file name
|
||||
* is passed in. We want to return 1 on success, 0 on error.
|
||||
*/
|
||||
|
||||
|
||||
GLOBAL(int)
|
||||
read_JPEG_file (char * filename)
|
||||
{
|
||||
/* This struct contains the JPEG decompression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
*/
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* We use our private extension JPEG error handler.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct my_error_mgr jerr;
|
||||
/* More stuff */
|
||||
FILE * infile; /* source file */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
|
||||
/* In this example we want to open the input file before doing anything else,
|
||||
* so that the setjmp() error recovery below can assume the file is open.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to read binary files.
|
||||
*/
|
||||
|
||||
if ((infile = fopen(filename, "rb")) == NULL) {
|
||||
fprintf(stderr, "can't open %s\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
/* If we get here, the JPEG code has signaled an error.
|
||||
* We need to clean up the JPEG object, close the input file, and return.
|
||||
*/
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
|
||||
jpeg_stdio_src(&cinfo, infile);
|
||||
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
|
||||
(void) jpeg_read_header(&cinfo, TRUE);
|
||||
/* We can ignore the return value from jpeg_read_header since
|
||||
* (a) suspension is not possible with the stdio data source, and
|
||||
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||
* See libjpeg.doc for more info.
|
||||
*/
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
/* Step 5: Start decompressor */
|
||||
|
||||
(void) jpeg_start_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
/* We may need to do some setup of our own at this point before reading
|
||||
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||
* output image dimensions available, as well as the output colormap
|
||||
* if we asked for color quantization.
|
||||
* In this example, we need to make an output work buffer of the right size.
|
||||
*/
|
||||
/* JSAMPLEs per row in output buffer */
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
/* Make a one-row-high sample array that will go away when done with image */
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
/* Step 6: while (scan lines remain to be read) */
|
||||
/* jpeg_read_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.output_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
*/
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
put_scanline_someplace(buffer[0], row_stride);
|
||||
}
|
||||
|
||||
/* Step 7: Finish decompression */
|
||||
|
||||
(void) jpeg_finish_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
/* After finish_decompress, we can close the input file.
|
||||
* Here we postpone it until after no more JPEG errors are possible,
|
||||
* so as to simplify the setjmp error logic above. (Actually, I don't
|
||||
* think that jpeg_destroy can do an error exit, but why assume anything...)
|
||||
*/
|
||||
fclose(infile);
|
||||
|
||||
/* At this point you may want to check to see whether any corrupt-data
|
||||
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
||||
*/
|
||||
|
||||
/* And we're done! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SOME FINE POINTS:
|
||||
*
|
||||
* In the above code, we ignored the return value of jpeg_read_scanlines,
|
||||
* which is the number of scanlines actually read. We could get away with
|
||||
* this because we asked for only one line at a time and we weren't using
|
||||
* a suspending data source. See libjpeg.doc for more info.
|
||||
*
|
||||
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
|
||||
* we should have done it beforehand to ensure that the space would be
|
||||
* counted against the JPEG max_memory setting. In some systems the above
|
||||
* code would risk an out-of-memory error. However, in general we don't
|
||||
* know the output image dimensions before jpeg_start_decompress(), unless we
|
||||
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
|
||||
*
|
||||
* Scanlines are returned in the same order as they appear in the JPEG file,
|
||||
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
|
||||
* you can use one of the virtual arrays provided by the JPEG memory manager
|
||||
* to invert the data. See wrbmp.c for an example.
|
||||
*
|
||||
* As with compression, some operating modes may require temporary files.
|
||||
* On some systems you may need to set up a signal handler to ensure that
|
||||
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
||||
*/
|
||||
210
filelist.doc
Normal file
210
filelist.doc
Normal file
@@ -0,0 +1,210 @@
|
||||
IJG JPEG LIBRARY: FILE LIST
|
||||
|
||||
Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
This file is part of the Independent JPEG Group's software.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
|
||||
Here is a road map to the files in the IJG JPEG distribution. The
|
||||
distribution includes the JPEG library proper, plus two application
|
||||
programs ("cjpeg" and "djpeg") which use the library to convert JPEG
|
||||
files to and from some other popular image formats. A third application
|
||||
"jpegtran" uses the library to do lossless conversion between different
|
||||
variants of JPEG. There are also two stand-alone applications,
|
||||
"rdjpgcom" and "wrjpgcom".
|
||||
|
||||
|
||||
THE JPEG LIBRARY
|
||||
================
|
||||
|
||||
Include files:
|
||||
|
||||
jpeglib.h JPEG library's exported data and function declarations.
|
||||
jconfig.h Configuration declarations. Note: this file is not present
|
||||
in the distribution; it is generated during installation.
|
||||
jmorecfg.h Additional configuration declarations; need not be changed
|
||||
for a standard installation.
|
||||
jerror.h Declares JPEG library's error and trace message codes.
|
||||
jinclude.h Central include file used by all IJG .c files to reference
|
||||
system include files.
|
||||
jpegint.h JPEG library's internal data structures.
|
||||
jchuff.h Private declarations for Huffman encoder modules.
|
||||
jdhuff.h Private declarations for Huffman decoder modules.
|
||||
jdct.h Private declarations for forward & reverse DCT subsystems.
|
||||
jmemsys.h Private declarations for memory management subsystem.
|
||||
jversion.h Version information.
|
||||
|
||||
Applications using the library should include jpeglib.h (which in turn
|
||||
includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included
|
||||
if the application needs to reference individual JPEG error codes. The
|
||||
other include files are intended for internal use and would not normally
|
||||
be included by an application program. (cjpeg/djpeg/etc do use jinclude.h,
|
||||
since its function is to improve portability of the whole IJG distribution.
|
||||
Most other applications will directly include the system include files they
|
||||
want, and hence won't need jinclude.h.)
|
||||
|
||||
|
||||
C source code files:
|
||||
|
||||
These files contain most of the functions intended to be called directly by
|
||||
an application program:
|
||||
|
||||
jcapimin.c Application program interface: core routines for compression.
|
||||
jcapistd.c Application program interface: standard compression.
|
||||
jdapimin.c Application program interface: core routines for decompression.
|
||||
jdapistd.c Application program interface: standard decompression.
|
||||
jcomapi.c Application program interface routines common to compression
|
||||
and decompression.
|
||||
jcparam.c Compression parameter setting helper routines.
|
||||
jctrans.c API and library routines for transcoding compression.
|
||||
jdtrans.c API and library routines for transcoding decompression.
|
||||
|
||||
Compression side of the library:
|
||||
|
||||
jcinit.c Initialization: determines which other modules to use.
|
||||
jcmaster.c Master control: setup and inter-pass sequencing logic.
|
||||
jcmainct.c Main buffer controller (preprocessor => JPEG compressor).
|
||||
jcprepct.c Preprocessor buffer controller.
|
||||
jccoefct.c Buffer controller for DCT coefficient buffer.
|
||||
jccolor.c Color space conversion.
|
||||
jcsample.c Downsampling.
|
||||
jcdctmgr.c DCT manager (DCT implementation selection & control).
|
||||
jfdctint.c Forward DCT using slow-but-accurate integer method.
|
||||
jfdctfst.c Forward DCT using faster, less accurate integer method.
|
||||
jfdctflt.c Forward DCT using floating-point arithmetic.
|
||||
jchuff.c Huffman entropy coding for sequential JPEG.
|
||||
jcphuff.c Huffman entropy coding for progressive JPEG.
|
||||
jcmarker.c JPEG marker writing.
|
||||
jdatadst.c Data destination manager for stdio output.
|
||||
|
||||
Decompression side of the library:
|
||||
|
||||
jdmaster.c Master control: determines which other modules to use.
|
||||
jdinput.c Input controller: controls input processing modules.
|
||||
jdmainct.c Main buffer controller (JPEG decompressor => postprocessor).
|
||||
jdcoefct.c Buffer controller for DCT coefficient buffer.
|
||||
jdpostct.c Postprocessor buffer controller.
|
||||
jdmarker.c JPEG marker reading.
|
||||
jdhuff.c Huffman entropy decoding for sequential JPEG.
|
||||
jdphuff.c Huffman entropy decoding for progressive JPEG.
|
||||
jddctmgr.c IDCT manager (IDCT implementation selection & control).
|
||||
jidctint.c Inverse DCT using slow-but-accurate integer method.
|
||||
jidctfst.c Inverse DCT using faster, less accurate integer method.
|
||||
jidctflt.c Inverse DCT using floating-point arithmetic.
|
||||
jidctred.c Inverse DCTs with reduced-size outputs.
|
||||
jdsample.c Upsampling.
|
||||
jdcolor.c Color space conversion.
|
||||
jdmerge.c Merged upsampling/color conversion (faster, lower quality).
|
||||
jquant1.c One-pass color quantization using a fixed-spacing colormap.
|
||||
jquant2.c Two-pass color quantization using a custom-generated colormap.
|
||||
Also handles one-pass quantization to an externally given map.
|
||||
jdatasrc.c Data source manager for stdio input.
|
||||
|
||||
Support files for both compression and decompression:
|
||||
|
||||
jerror.c Standard error handling routines (application replaceable).
|
||||
jmemmgr.c System-independent (more or less) memory management code.
|
||||
jutils.c Miscellaneous utility routines.
|
||||
|
||||
jmemmgr.c relies on a system-dependent memory management module. The IJG
|
||||
distribution includes the following implementations of the system-dependent
|
||||
module:
|
||||
|
||||
jmemnobs.c "No backing store": assumes adequate virtual memory exists.
|
||||
jmemansi.c Makes temporary files with ANSI-standard routine tmpfile().
|
||||
jmemname.c Makes temporary files with program-generated file names.
|
||||
jmemdos.c Custom implementation for MS-DOS (16-bit environment only):
|
||||
can use extended and expanded memory as well as temp files.
|
||||
jmemmac.c Custom implementation for Apple Macintosh.
|
||||
|
||||
Exactly one of the system-dependent modules should be configured into an
|
||||
installed JPEG library (see install.doc for hints about which one to use).
|
||||
On unusual systems you may find it worthwhile to make a special
|
||||
system-dependent memory manager.
|
||||
|
||||
|
||||
Non-C source code files:
|
||||
|
||||
jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in
|
||||
MS-DOS-specific configurations of the JPEG library.
|
||||
|
||||
|
||||
CJPEG/DJPEG/JPEGTRAN
|
||||
====================
|
||||
|
||||
Include files:
|
||||
|
||||
cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules.
|
||||
cderror.h Additional error and trace message codes for cjpeg et al.
|
||||
transupp.h Declarations for jpegtran support routines in transupp.c.
|
||||
|
||||
C source code files:
|
||||
|
||||
cjpeg.c Main program for cjpeg.
|
||||
djpeg.c Main program for djpeg.
|
||||
jpegtran.c Main program for jpegtran.
|
||||
cdjpeg.c Utility routines used by all three programs.
|
||||
rdcolmap.c Code to read a colormap file for djpeg's "-map" switch.
|
||||
rdswitch.c Code to process some of cjpeg's more complex switches.
|
||||
Also used by jpegtran.
|
||||
transupp.c Support code for jpegtran: lossless image manipulations.
|
||||
|
||||
Image file reader modules for cjpeg:
|
||||
|
||||
rdbmp.c BMP file input.
|
||||
rdgif.c GIF file input (now just a stub).
|
||||
rdppm.c PPM/PGM file input.
|
||||
rdrle.c Utah RLE file input.
|
||||
rdtarga.c Targa file input.
|
||||
|
||||
Image file writer modules for djpeg:
|
||||
|
||||
wrbmp.c BMP file output.
|
||||
wrgif.c GIF file output (a mere shadow of its former self).
|
||||
wrppm.c PPM/PGM file output.
|
||||
wrrle.c Utah RLE file output.
|
||||
wrtarga.c Targa file output.
|
||||
|
||||
|
||||
RDJPGCOM/WRJPGCOM
|
||||
=================
|
||||
|
||||
C source code files:
|
||||
|
||||
rdjpgcom.c Stand-alone rdjpgcom application.
|
||||
wrjpgcom.c Stand-alone wrjpgcom application.
|
||||
|
||||
These programs do not depend on the IJG library. They do use
|
||||
jconfig.h and jinclude.h, only to improve portability.
|
||||
|
||||
|
||||
ADDITIONAL FILES
|
||||
================
|
||||
|
||||
Documentation (see README for a guide to the documentation files):
|
||||
|
||||
README Master documentation file.
|
||||
*.doc Other documentation files.
|
||||
*.1 Documentation in Unix man page format.
|
||||
change.log Version-to-version change highlights.
|
||||
example.c Sample code for calling JPEG library.
|
||||
|
||||
Configuration/installation files and programs (see install.doc for more info):
|
||||
|
||||
configure Unix shell script to perform automatic configuration.
|
||||
ltconfig Support scripts for configure (from GNU libtool).
|
||||
ltmain.sh
|
||||
config.guess
|
||||
config.sub
|
||||
install-sh Install shell script for those Unix systems lacking one.
|
||||
ckconfig.c Program to generate jconfig.h on non-Unix systems.
|
||||
jconfig.doc Template for making jconfig.h by hand.
|
||||
makefile.* Sample makefiles for particular systems.
|
||||
jconfig.* Sample jconfig.h for particular systems.
|
||||
ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of
|
||||
L. Peter Deutsch and Aladdin Enterprises).
|
||||
|
||||
Test files (see install.doc for test procedure):
|
||||
|
||||
test*.* Source and comparison files for confidence test.
|
||||
These are binary image files, NOT text files.
|
||||
1063
install.doc
Normal file
1063
install.doc
Normal file
File diff suppressed because it is too large
Load Diff
238
jpegtran.1
Normal file
238
jpegtran.1
Normal file
@@ -0,0 +1,238 @@
|
||||
.TH JPEGTRAN 1 "3 August 1997"
|
||||
.SH NAME
|
||||
jpegtran \- lossless transformation of JPEG files
|
||||
.SH SYNOPSIS
|
||||
.B jpegtran
|
||||
[
|
||||
.I options
|
||||
]
|
||||
[
|
||||
.I filename
|
||||
]
|
||||
.LP
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
.B jpegtran
|
||||
performs various useful transformations of JPEG files.
|
||||
It can translate the coded representation from one variant of JPEG to another,
|
||||
for example from baseline JPEG to progressive JPEG or vice versa. It can also
|
||||
perform some rearrangements of the image data, for example turning an image
|
||||
from landscape to portrait format by rotation.
|
||||
.PP
|
||||
.B jpegtran
|
||||
works by rearranging the compressed data (DCT coefficients), without
|
||||
ever fully decoding the image. Therefore, its transformations are lossless:
|
||||
there is no image degradation at all, which would not be true if you used
|
||||
.B djpeg
|
||||
followed by
|
||||
.B cjpeg
|
||||
to accomplish the same conversion. But by the same token,
|
||||
.B jpegtran
|
||||
cannot perform lossy operations such as changing the image quality.
|
||||
.PP
|
||||
.B jpegtran
|
||||
reads the named JPEG/JFIF file, or the standard input if no file is
|
||||
named, and produces a JPEG/JFIF file on the standard output.
|
||||
.SH OPTIONS
|
||||
All switch names may be abbreviated; for example,
|
||||
.B \-optimize
|
||||
may be written
|
||||
.B \-opt
|
||||
or
|
||||
.BR \-o .
|
||||
Upper and lower case are equivalent.
|
||||
British spellings are also accepted (e.g.,
|
||||
.BR \-optimise ),
|
||||
though for brevity these are not mentioned below.
|
||||
.PP
|
||||
To specify the coded JPEG representation used in the output file,
|
||||
.B jpegtran
|
||||
accepts a subset of the switches recognized by
|
||||
.BR cjpeg :
|
||||
.TP
|
||||
.B \-optimize
|
||||
Perform optimization of entropy encoding parameters.
|
||||
.TP
|
||||
.B \-progressive
|
||||
Create progressive JPEG file.
|
||||
.TP
|
||||
.BI \-restart " N"
|
||||
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
|
||||
attached to the number.
|
||||
.TP
|
||||
.BI \-scans " file"
|
||||
Use the scan script given in the specified text file.
|
||||
.PP
|
||||
See
|
||||
.BR cjpeg (1)
|
||||
for more details about these switches.
|
||||
If you specify none of these switches, you get a plain baseline-JPEG output
|
||||
file. The quality setting and so forth are determined by the input file.
|
||||
.PP
|
||||
The image can be losslessly transformed by giving one of these switches:
|
||||
.TP
|
||||
.B \-flip horizontal
|
||||
Mirror image horizontally (left-right).
|
||||
.TP
|
||||
.B \-flip vertical
|
||||
Mirror image vertically (top-bottom).
|
||||
.TP
|
||||
.B \-rotate 90
|
||||
Rotate image 90 degrees clockwise.
|
||||
.TP
|
||||
.B \-rotate 180
|
||||
Rotate image 180 degrees.
|
||||
.TP
|
||||
.B \-rotate 270
|
||||
Rotate image 270 degrees clockwise (or 90 ccw).
|
||||
.TP
|
||||
.B \-transpose
|
||||
Transpose image (across UL-to-LR axis).
|
||||
.TP
|
||||
.B \-transverse
|
||||
Transverse transpose (across UR-to-LL axis).
|
||||
.PP
|
||||
The transpose transformation has no restrictions regarding image dimensions.
|
||||
The other transformations operate rather oddly if the image dimensions are not
|
||||
a multiple of the iMCU size (usually 8 or 16 pixels), because they can only
|
||||
transform complete blocks of DCT coefficient data in the desired way.
|
||||
.PP
|
||||
.BR jpegtran 's
|
||||
default behavior when transforming an odd-size image is designed
|
||||
to preserve exact reversibility and mathematical consistency of the
|
||||
transformation set. As stated, transpose is able to flip the entire image
|
||||
area. Horizontal mirroring leaves any partial iMCU column at the right edge
|
||||
untouched, but is able to flip all rows of the image. Similarly, vertical
|
||||
mirroring leaves any partial iMCU row at the bottom edge untouched, but is
|
||||
able to flip all columns. The other transforms can be built up as sequences
|
||||
of transpose and flip operations; for consistency, their actions on edge
|
||||
pixels are defined to be the same as the end result of the corresponding
|
||||
transpose-and-flip sequence.
|
||||
.PP
|
||||
For practical use, you may prefer to discard any untransformable edge pixels
|
||||
rather than having a strange-looking strip along the right and/or bottom edges
|
||||
of a transformed image. To do this, add the
|
||||
.B \-trim
|
||||
switch:
|
||||
.TP
|
||||
.B \-trim
|
||||
Drop non-transformable edge blocks.
|
||||
.PP
|
||||
Obviously, a transformation with
|
||||
.B \-trim
|
||||
is not reversible, so strictly speaking
|
||||
.B jpegtran
|
||||
with this switch is not lossless. Also, the expected mathematical
|
||||
equivalences between the transformations no longer hold. For example,
|
||||
.B \-rot 270 -trim
|
||||
trims only the bottom edge, but
|
||||
.B \-rot 90 -trim
|
||||
followed by
|
||||
.B \-rot 180 -trim
|
||||
trims both edges.
|
||||
.PP
|
||||
Another not-strictly-lossless transformation switch is:
|
||||
.TP
|
||||
.B \-grayscale
|
||||
Force grayscale output.
|
||||
.PP
|
||||
This option discards the chrominance channels if the input image is YCbCr
|
||||
(ie, a standard color JPEG), resulting in a grayscale JPEG file. The
|
||||
luminance channel is preserved exactly, so this is a better method of reducing
|
||||
to grayscale than decompression, conversion, and recompression. This switch
|
||||
is particularly handy for fixing a monochrome picture that was mistakenly
|
||||
encoded as a color JPEG. (In such a case, the space savings from getting rid
|
||||
of the near-empty chroma channels won't be large; but the decoding time for
|
||||
a grayscale JPEG is substantially less than that for a color JPEG.)
|
||||
.PP
|
||||
.B jpegtran
|
||||
also recognizes these switches that control what to do with "extra" markers,
|
||||
such as comment blocks:
|
||||
.TP
|
||||
.B \-copy none
|
||||
Copy no extra markers from source file. This setting suppresses all
|
||||
comments and other excess baggage present in the source file.
|
||||
.TP
|
||||
.B \-copy comments
|
||||
Copy only comment markers. This setting copies comments from the source file,
|
||||
but discards any other inessential data.
|
||||
.TP
|
||||
.B \-copy all
|
||||
Copy all extra markers. This setting preserves miscellaneous markers
|
||||
found in the source file, such as JFIF thumbnails and Photoshop settings.
|
||||
In some files these extra markers can be sizable.
|
||||
.PP
|
||||
The default behavior is
|
||||
.BR "\-copy comments" .
|
||||
(Note: in IJG releases v6 and v6a,
|
||||
.B jpegtran
|
||||
always did the equivalent of
|
||||
.BR "\-copy none" .)
|
||||
.PP
|
||||
Additional switches recognized by jpegtran are:
|
||||
.TP
|
||||
.BI \-maxmemory " N"
|
||||
Set limit for amount of memory to use in processing large images. Value is
|
||||
in thousands of bytes, or millions of bytes if "M" is attached to the
|
||||
number. For example,
|
||||
.B \-max 4m
|
||||
selects 4000000 bytes. If more space is needed, temporary files will be used.
|
||||
.TP
|
||||
.BI \-outfile " name"
|
||||
Send output image to the named file, not to standard output.
|
||||
.TP
|
||||
.B \-verbose
|
||||
Enable debug printout. More
|
||||
.BR \-v 's
|
||||
give more output. Also, version information is printed at startup.
|
||||
.TP
|
||||
.B \-debug
|
||||
Same as
|
||||
.BR \-verbose .
|
||||
.SH EXAMPLES
|
||||
.LP
|
||||
This example converts a baseline JPEG file to progressive form:
|
||||
.IP
|
||||
.B jpegtran \-progressive
|
||||
.I foo.jpg
|
||||
.B >
|
||||
.I fooprog.jpg
|
||||
.PP
|
||||
This example rotates an image 90 degrees clockwise, discarding any
|
||||
unrotatable edge pixels:
|
||||
.IP
|
||||
.B jpegtran \-rot 90 -trim
|
||||
.I foo.jpg
|
||||
.B >
|
||||
.I foo90.jpg
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B JPEGMEM
|
||||
If this environment variable is set, its value is the default memory limit.
|
||||
The value is specified as described for the
|
||||
.B \-maxmemory
|
||||
switch.
|
||||
.B JPEGMEM
|
||||
overrides the default value specified when the program was compiled, and
|
||||
itself is overridden by an explicit
|
||||
.BR \-maxmemory .
|
||||
.SH SEE ALSO
|
||||
.BR cjpeg (1),
|
||||
.BR djpeg (1),
|
||||
.BR rdjpgcom (1),
|
||||
.BR wrjpgcom (1)
|
||||
.br
|
||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||
Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44.
|
||||
.SH AUTHOR
|
||||
Independent JPEG Group
|
||||
.SH BUGS
|
||||
Arithmetic coding is not supported for legal reasons.
|
||||
.PP
|
||||
The transform options can't transform odd-size images perfectly. Use
|
||||
.B \-trim
|
||||
if you don't like the results without it.
|
||||
.PP
|
||||
The entire image is read into memory and then written out again, even in
|
||||
cases where this isn't really necessary. Expect swapping on large images,
|
||||
especially when using the more complex transform options.
|
||||
504
jpegtran.c
Normal file
504
jpegtran.c
Normal file
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
* jpegtran.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 a command-line user interface for JPEG transcoding.
|
||||
* It is very similar to cjpeg.c, but provides lossless transcoding between
|
||||
* different JPEG file formats. It also provides some lossless and sort-of-
|
||||
* lossless transformations of JPEG data.
|
||||
*/
|
||||
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
#include "transupp.h" /* Support routines for jpegtran */
|
||||
#include "jversion.h" /* for version message */
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Argument-parsing code.
|
||||
* The switch parser is designed to be useful with DOS-style command line
|
||||
* syntax, ie, intermixed switches and file names, where only the switches
|
||||
* to the left of a given file name affect processing of that file.
|
||||
* The main program in this file doesn't actually use this capability...
|
||||
*/
|
||||
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
static char * outfilename; /* for -outfile switch */
|
||||
static JCOPY_OPTION copyoption; /* -copy switch */
|
||||
static jpeg_transform_info transformoption; /* image transformation options */
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "usage: %s [switches] ", progname);
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, "[inputfile]\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -copy none Copy no extra markers from source file\n");
|
||||
fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
|
||||
fprintf(stderr, " -copy all Copy all extra markers\n");
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
|
||||
#endif
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
fprintf(stderr, " -progressive Create progressive JPEG file\n");
|
||||
#endif
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
fprintf(stderr, "Switches for modifying the image:\n");
|
||||
fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
|
||||
fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
|
||||
fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
|
||||
fprintf(stderr, " -transpose Transpose image\n");
|
||||
fprintf(stderr, " -transverse Transverse transpose image\n");
|
||||
fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
fprintf(stderr, "Switches for advanced users:\n");
|
||||
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
|
||||
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||
fprintf(stderr, "Switches for wizards:\n");
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||
#endif
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
select_transform (JXFORM_CODE transform)
|
||||
/* Silly little routine to detect multiple transform options,
|
||||
* which we can't handle.
|
||||
*/
|
||||
{
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (transformoption.transform == JXFORM_NONE ||
|
||||
transformoption.transform == transform) {
|
||||
transformoption.transform = transform;
|
||||
} else {
|
||||
fprintf(stderr, "%s: can only do one image transformation at a time\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LOCAL(int)
|
||||
parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
int last_file_arg_seen, boolean for_real)
|
||||
/* Parse optional switches.
|
||||
* Returns argv[] index of first file-name argument (== argc if none).
|
||||
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||
* they have presumably been processed in a previous iteration.
|
||||
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||
* processing.
|
||||
*/
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
boolean simple_progressive;
|
||||
char * scansarg = NULL; /* saves -scans parm if any */
|
||||
|
||||
/* Set up default JPEG parameters. */
|
||||
simple_progressive = FALSE;
|
||||
outfilename = NULL;
|
||||
copyoption = JCOPYOPT_DEFAULT;
|
||||
transformoption.transform = JXFORM_NONE;
|
||||
transformoption.trim = FALSE;
|
||||
transformoption.force_grayscale = FALSE;
|
||||
cinfo->err->trace_level = 0;
|
||||
|
||||
/* Scan command line options, adjust parameters */
|
||||
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (*arg != '-') {
|
||||
/* Not a switch, must be a file name argument */
|
||||
if (argn <= last_file_arg_seen) {
|
||||
outfilename = NULL; /* -outfile applies to just one input file */
|
||||
continue; /* ignore this name if previously processed */
|
||||
}
|
||||
break; /* else done parsing switches */
|
||||
}
|
||||
arg++; /* advance past switch marker character */
|
||||
|
||||
if (keymatch(arg, "arithmetic", 1)) {
|
||||
/* Use arithmetic coding. */
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
cinfo->arith_code = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "copy", 1)) {
|
||||
/* Select which extra markers to copy. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "none", 1)) {
|
||||
copyoption = JCOPYOPT_NONE;
|
||||
} else if (keymatch(argv[argn], "comments", 1)) {
|
||||
copyoption = JCOPYOPT_COMMENTS;
|
||||
} else if (keymatch(argv[argn], "all", 1)) {
|
||||
copyoption = JCOPYOPT_ALL;
|
||||
} else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||
/* Enable debug printouts. */
|
||||
/* On first -d, print version identification */
|
||||
static boolean printed_version = FALSE;
|
||||
|
||||
if (! printed_version) {
|
||||
fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
|
||||
JVERSION, JCOPYRIGHT);
|
||||
printed_version = TRUE;
|
||||
}
|
||||
cinfo->err->trace_level++;
|
||||
|
||||
} else if (keymatch(arg, "flip", 1)) {
|
||||
/* Mirror left-right or top-bottom. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "horizontal", 1))
|
||||
select_transform(JXFORM_FLIP_H);
|
||||
else if (keymatch(argv[argn], "vertical", 1))
|
||||
select_transform(JXFORM_FLIP_V);
|
||||
else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
|
||||
/* Force to grayscale. */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
transformoption.force_grayscale = TRUE;
|
||||
#else
|
||||
select_transform(JXFORM_NONE); /* force an error */
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||
long lval;
|
||||
char ch = 'x';
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||
usage();
|
||||
if (ch == 'm' || ch == 'M')
|
||||
lval *= 1000L;
|
||||
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||
|
||||
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
|
||||
/* Enable entropy parm optimization. */
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
cinfo->optimize_coding = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "outfile", 4)) {
|
||||
/* Set output file name. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
outfilename = argv[argn]; /* save it away for later use */
|
||||
|
||||
} else if (keymatch(arg, "progressive", 1)) {
|
||||
/* Select simple progressive mode. */
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
simple_progressive = TRUE;
|
||||
/* We must postpone execution until num_components is known. */
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "restart", 1)) {
|
||||
/* Restart interval in MCU rows (or in MCUs with 'b'). */
|
||||
long lval;
|
||||
char ch = 'x';
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||
usage();
|
||||
if (lval < 0 || lval > 65535L)
|
||||
usage();
|
||||
if (ch == 'b' || ch == 'B') {
|
||||
cinfo->restart_interval = (unsigned int) lval;
|
||||
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
|
||||
} else {
|
||||
cinfo->restart_in_rows = (int) lval;
|
||||
/* restart_interval will be computed during startup */
|
||||
}
|
||||
|
||||
} else if (keymatch(arg, "rotate", 2)) {
|
||||
/* Rotate 90, 180, or 270 degrees (measured clockwise). */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "90", 2))
|
||||
select_transform(JXFORM_ROT_90);
|
||||
else if (keymatch(argv[argn], "180", 3))
|
||||
select_transform(JXFORM_ROT_180);
|
||||
else if (keymatch(argv[argn], "270", 3))
|
||||
select_transform(JXFORM_ROT_270);
|
||||
else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "scans", 1)) {
|
||||
/* Set scan script. */
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
scansarg = argv[argn];
|
||||
/* We must postpone reading the file in case -progressive appears. */
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "transpose", 1)) {
|
||||
/* Transpose (across UL-to-LR axis). */
|
||||
select_transform(JXFORM_TRANSPOSE);
|
||||
|
||||
} else if (keymatch(arg, "transverse", 6)) {
|
||||
/* Transverse transpose (across UR-to-LL axis). */
|
||||
select_transform(JXFORM_TRANSVERSE);
|
||||
|
||||
} else if (keymatch(arg, "trim", 3)) {
|
||||
/* Trim off any partial edge MCUs that the transform can't handle. */
|
||||
transformoption.trim = TRUE;
|
||||
|
||||
} else {
|
||||
usage(); /* bogus switch */
|
||||
}
|
||||
}
|
||||
|
||||
/* Post-switch-scanning cleanup */
|
||||
|
||||
if (for_real) {
|
||||
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
if (simple_progressive) /* process -progressive; -scans can override */
|
||||
jpeg_simple_progression(cinfo);
|
||||
#endif
|
||||
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (scansarg != NULL) /* process -scans if it was present */
|
||||
if (! read_scan_script(cinfo, scansarg))
|
||||
usage();
|
||||
#endif
|
||||
}
|
||||
|
||||
return argn; /* return index of next arg (file name) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct jpeg_decompress_struct srcinfo;
|
||||
struct jpeg_compress_struct dstinfo;
|
||||
struct jpeg_error_mgr jsrcerr, jdsterr;
|
||||
#ifdef PROGRESS_REPORT
|
||||
struct cdjpeg_progress_mgr progress;
|
||||
#endif
|
||||
jvirt_barray_ptr * src_coef_arrays;
|
||||
jvirt_barray_ptr * dst_coef_arrays;
|
||||
int file_index;
|
||||
FILE * input_file;
|
||||
FILE * output_file;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "jpegtran"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Initialize the JPEG decompression object with default error handling. */
|
||||
srcinfo.err = jpeg_std_error(&jsrcerr);
|
||||
jpeg_create_decompress(&srcinfo);
|
||||
/* Initialize the JPEG compression object with default error handling. */
|
||||
dstinfo.err = jpeg_std_error(&jdsterr);
|
||||
jpeg_create_compress(&dstinfo);
|
||||
|
||||
/* Now safe to enable signal catcher.
|
||||
* Note: we assume only the decompression object will have virtual arrays.
|
||||
*/
|
||||
#ifdef NEED_SIGNAL_CATCHER
|
||||
enable_signal_catcher((j_common_ptr) &srcinfo);
|
||||
#endif
|
||||
|
||||
/* Scan command line to find file names.
|
||||
* It is convenient to use just one switch-parsing routine, but the switch
|
||||
* values read here are mostly ignored; we will rescan the switches after
|
||||
* opening the input file. Also note that most of the switches affect the
|
||||
* destination JPEG object, so we parse into that and then copy over what
|
||||
* needs to affects the source too.
|
||||
*/
|
||||
|
||||
file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
|
||||
jsrcerr.trace_level = jdsterr.trace_level;
|
||||
srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
|
||||
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
/* Must have either -outfile switch or explicit output file name */
|
||||
if (outfilename == NULL) {
|
||||
if (file_index != argc-2) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
outfilename = argv[file_index+1];
|
||||
} else {
|
||||
if (file_index != argc-1) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Unix style: expect zero or one file name */
|
||||
if (file_index < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", progname);
|
||||
usage();
|
||||
}
|
||||
#endif /* TWO_FILE_COMMANDLINE */
|
||||
|
||||
/* Open the input file. */
|
||||
if (file_index < argc) {
|
||||
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default input file is stdin */
|
||||
input_file = read_stdin();
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
if (outfilename != NULL) {
|
||||
if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default output file is stdout */
|
||||
output_file = write_stdout();
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
start_progress_monitor((j_common_ptr) &dstinfo, &progress);
|
||||
#endif
|
||||
|
||||
/* Specify data source for decompression */
|
||||
jpeg_stdio_src(&srcinfo, input_file);
|
||||
|
||||
/* Enable saving of extra markers that we want to copy */
|
||||
jcopy_markers_setup(&srcinfo, copyoption);
|
||||
|
||||
/* Read file header */
|
||||
(void) jpeg_read_header(&srcinfo, TRUE);
|
||||
|
||||
/* Any space needed by a transform option must be requested before
|
||||
* jpeg_read_coefficients so that memory allocation will be done right.
|
||||
*/
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
jtransform_request_workspace(&srcinfo, &transformoption);
|
||||
#endif
|
||||
|
||||
/* Read source file as DCT coefficients */
|
||||
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
|
||||
|
||||
/* Initialize destination compression parameters from source values */
|
||||
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
|
||||
|
||||
/* Adjust destination parameters if required by transform options;
|
||||
* also find out which set of coefficient arrays will hold the output.
|
||||
*/
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
#else
|
||||
dst_coef_arrays = src_coef_arrays;
|
||||
#endif
|
||||
|
||||
/* Adjust default compression parameters by re-parsing the options */
|
||||
file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
|
||||
|
||||
/* Specify data destination for compression */
|
||||
jpeg_stdio_dest(&dstinfo, output_file);
|
||||
|
||||
/* Start compressor (note no image data is actually written here) */
|
||||
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
|
||||
|
||||
/* Copy to the output file any extra markers that we want to preserve */
|
||||
jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
|
||||
|
||||
/* Execute image transformation, if any */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
jtransform_execute_transformation(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
#endif
|
||||
|
||||
/* Finish compression and release memory */
|
||||
jpeg_finish_compress(&dstinfo);
|
||||
jpeg_destroy_compress(&dstinfo);
|
||||
(void) jpeg_finish_decompress(&srcinfo);
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
|
||||
/* Close files, if we opened them */
|
||||
if (input_file != stdin)
|
||||
fclose(input_file);
|
||||
if (output_file != stdout)
|
||||
fclose(output_file);
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
end_progress_monitor((j_common_ptr) &dstinfo);
|
||||
#endif
|
||||
|
||||
/* All done. */
|
||||
exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
3006
libjpeg.doc
Normal file
3006
libjpeg.doc
Normal file
File diff suppressed because it is too large
Load Diff
319
makefile.cfg
319
makefile.cfg
@@ -1,319 +0,0 @@
|
||||
# Makefile for Independent JPEG Group's software
|
||||
|
||||
# makefile.cfg is edited by configure to produce a custom Makefile.
|
||||
|
||||
# Read installation instructions before saying "make" !!
|
||||
|
||||
# For compiling with source and object files in different directories.
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
# Where to install the programs and man pages.
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
binprefix =
|
||||
manprefix =
|
||||
manext = 1
|
||||
mandir = $(prefix)/man/man$(manext)
|
||||
|
||||
# The name of your C compiler:
|
||||
CC= @CC@
|
||||
|
||||
# You may need to adjust these cc options:
|
||||
CFLAGS= @CFLAGS@ @CPPFLAGS@ @INCLUDEFLAGS@
|
||||
# Generally, we recommend defining any configuration symbols in jconfig.h,
|
||||
# NOT via -D switches here.
|
||||
# However, any special defines for ansi2knr.c may be included here:
|
||||
ANSI2KNRFLAGS= @ANSI2KNRFLAGS@
|
||||
|
||||
# Link-time cc options:
|
||||
LDFLAGS= @LDFLAGS@
|
||||
|
||||
# To link any special libraries, add the necessary -l commands here.
|
||||
LDLIBS= @LIBS@
|
||||
|
||||
# If using GNU libtool, LIBTOOL references it; if not, LIBTOOL is empty.
|
||||
LIBTOOL = @LIBTOOL@
|
||||
# $(O) expands to "lo" if using libtool, plain "o" if not.
|
||||
# Similarly, $(A) expands to "la" or "a".
|
||||
O = @O@
|
||||
A = @A@
|
||||
|
||||
# Library version ID; libtool uses this for the shared library version number.
|
||||
# Note: we suggest this match the macro of the same name in jpeglib.h.
|
||||
JPEG_LIB_VERSION = @JPEG_LIB_VERSION@
|
||||
|
||||
# Put here the object file name for the correct system-dependent memory
|
||||
# manager file. For Unix this is usually jmemnobs.o, but you may want
|
||||
# to use jmemansi.o or jmemname.o if you have limited swap space.
|
||||
SYSDEPMEM= @MEMORYMGR@
|
||||
|
||||
# miscellaneous OS-dependent stuff
|
||||
SHELL= /bin/sh
|
||||
# linker
|
||||
LN= @LN@
|
||||
# file deletion command
|
||||
RM= rm -f
|
||||
# directory creation command
|
||||
MKDIR= mkdir
|
||||
# library (.a) file creation command
|
||||
AR= ar rc
|
||||
# second step in .a creation (use "touch" if not needed)
|
||||
AR2= @RANLIB@
|
||||
# installation program
|
||||
INSTALL= @INSTALL@
|
||||
INSTALL_PROGRAM= @INSTALL_PROGRAM@
|
||||
INSTALL_LIB= @INSTALL_LIB@
|
||||
INSTALL_DATA= @INSTALL_DATA@
|
||||
|
||||
# End of configurable options.
|
||||
|
||||
|
||||
# source files: JPEG library proper
|
||||
LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \
|
||||
jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \
|
||||
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \
|
||||
jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \
|
||||
jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \
|
||||
jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \
|
||||
jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \
|
||||
jquant2.c jutils.c jmemmgr.c
|
||||
# memmgr back ends: compile only one of these into a working library
|
||||
SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c
|
||||
# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom
|
||||
APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \
|
||||
rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \
|
||||
rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c
|
||||
SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES)
|
||||
# files included by source files
|
||||
INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \
|
||||
jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h
|
||||
# documentation, test, and support files
|
||||
DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \
|
||||
wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \
|
||||
coderules.doc filelist.doc change.log
|
||||
MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \
|
||||
makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \
|
||||
makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \
|
||||
maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \
|
||||
makvms.opt
|
||||
CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \
|
||||
jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \
|
||||
jconfig.vms
|
||||
CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh
|
||||
OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm
|
||||
TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \
|
||||
testimgp.jpg
|
||||
DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \
|
||||
$(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES)
|
||||
# library object files common to compression and decompression
|
||||
COMOBJECTS= jcomapi.$(O) jutils.$(O) jerror.$(O) jmemmgr.$(O) $(SYSDEPMEM)
|
||||
# compression library object files
|
||||
CLIBOBJECTS= jcapimin.$(O) jcapistd.$(O) jctrans.$(O) jcparam.$(O) \
|
||||
jdatadst.$(O) jcinit.$(O) jcmaster.$(O) jcmarker.$(O) jcmainct.$(O) \
|
||||
jcprepct.$(O) jccoefct.$(O) jccolor.$(O) jcsample.$(O) jchuff.$(O) \
|
||||
jcphuff.$(O) jcdctmgr.$(O) jfdctfst.$(O) jfdctflt.$(O) \
|
||||
jfdctint.$(O)
|
||||
# decompression library object files
|
||||
DLIBOBJECTS= jdapimin.$(O) jdapistd.$(O) jdtrans.$(O) jdatasrc.$(O) \
|
||||
jdmaster.$(O) jdinput.$(O) jdmarker.$(O) jdhuff.$(O) jdphuff.$(O) \
|
||||
jdmainct.$(O) jdcoefct.$(O) jdpostct.$(O) jddctmgr.$(O) \
|
||||
jidctfst.$(O) jidctflt.$(O) jidctint.$(O) jidctred.$(O) \
|
||||
jdsample.$(O) jdcolor.$(O) jquant1.$(O) jquant2.$(O) jdmerge.$(O)
|
||||
# These objectfiles are included in libjpeg.a
|
||||
LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS)
|
||||
# object files for sample applications (excluding library files)
|
||||
COBJECTS= cjpeg.$(O) rdppm.$(O) rdgif.$(O) rdtarga.$(O) rdrle.$(O) \
|
||||
rdbmp.$(O) rdswitch.$(O) cdjpeg.$(O)
|
||||
DOBJECTS= djpeg.$(O) wrppm.$(O) wrgif.$(O) wrtarga.$(O) wrrle.$(O) \
|
||||
wrbmp.$(O) rdcolmap.$(O) cdjpeg.$(O)
|
||||
TROBJECTS= jpegtran.$(O) rdswitch.$(O) cdjpeg.$(O) transupp.$(O)
|
||||
|
||||
|
||||
all: @A2K_DEPS@ libjpeg.$(A)
|
||||
|
||||
# Special compilation rules to support ansi2knr and libtool.
|
||||
.SUFFIXES: .lo .la
|
||||
|
||||
# How to compile with libtool.
|
||||
@COM_LT@.c.lo:
|
||||
@COM_LT@ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$*.c
|
||||
|
||||
# How to use ansi2knr, when not using libtool.
|
||||
@COM_A2K@.c.o:
|
||||
@COM_A2K@ ./ansi2knr $(srcdir)/$*.c knr/$*.c
|
||||
@COM_A2K@ $(CC) $(CFLAGS) -c knr/$*.c
|
||||
@COM_A2K@ $(RM) knr/$*.c
|
||||
|
||||
# How to use ansi2knr AND libtool.
|
||||
@COM_A2K@.c.lo:
|
||||
@COM_A2K@ ./ansi2knr $(srcdir)/$*.c knr/$*.c
|
||||
@COM_A2K@ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c knr/$*.c
|
||||
@COM_A2K@ $(RM) knr/$*.c
|
||||
|
||||
ansi2knr: ansi2knr.c
|
||||
$(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr $(srcdir)/ansi2knr.c
|
||||
$(MKDIR) knr
|
||||
|
||||
# the library:
|
||||
|
||||
# without libtool:
|
||||
libjpeg.a: @A2K_DEPS@ $(LIBOBJECTS)
|
||||
$(RM) libjpeg.a
|
||||
$(AR) libjpeg.a $(LIBOBJECTS)
|
||||
$(AR2) libjpeg.a
|
||||
|
||||
# with libtool:
|
||||
libjpeg.la: @A2K_DEPS@ $(LIBOBJECTS)
|
||||
$(LIBTOOL) --mode=link $(CC) -o libjpeg.la $(LIBOBJECTS) \
|
||||
-rpath $(libdir) -version-info $(JPEG_LIB_VERSION)
|
||||
|
||||
# sample programs:
|
||||
|
||||
cjpeg: $(COBJECTS) libjpeg.$(A)
|
||||
$(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.$(A) $(LDLIBS)
|
||||
|
||||
djpeg: $(DOBJECTS) libjpeg.$(A)
|
||||
$(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.$(A) $(LDLIBS)
|
||||
|
||||
jpegtran: $(TROBJECTS) libjpeg.$(A)
|
||||
$(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.$(A) $(LDLIBS)
|
||||
|
||||
rdjpgcom: rdjpgcom.$(O)
|
||||
$(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.$(O) $(LDLIBS)
|
||||
|
||||
wrjpgcom: wrjpgcom.$(O)
|
||||
$(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.$(O) $(LDLIBS)
|
||||
|
||||
# Installation rules:
|
||||
|
||||
install: cjpeg djpeg jpegtran rdjpgcom wrjpgcom @FORCE_INSTALL_LIB@
|
||||
$(INSTALL_PROGRAM) cjpeg $(bindir)/$(binprefix)cjpeg
|
||||
$(INSTALL_PROGRAM) djpeg $(bindir)/$(binprefix)djpeg
|
||||
$(INSTALL_PROGRAM) jpegtran $(bindir)/$(binprefix)jpegtran
|
||||
$(INSTALL_PROGRAM) rdjpgcom $(bindir)/$(binprefix)rdjpgcom
|
||||
$(INSTALL_PROGRAM) wrjpgcom $(bindir)/$(binprefix)wrjpgcom
|
||||
$(INSTALL_DATA) $(srcdir)/cjpeg.1 $(mandir)/$(manprefix)cjpeg.$(manext)
|
||||
$(INSTALL_DATA) $(srcdir)/djpeg.1 $(mandir)/$(manprefix)djpeg.$(manext)
|
||||
$(INSTALL_DATA) $(srcdir)/jpegtran.1 $(mandir)/$(manprefix)jpegtran.$(manext)
|
||||
$(INSTALL_DATA) $(srcdir)/rdjpgcom.1 $(mandir)/$(manprefix)rdjpgcom.$(manext)
|
||||
$(INSTALL_DATA) $(srcdir)/wrjpgcom.1 $(mandir)/$(manprefix)wrjpgcom.$(manext)
|
||||
|
||||
install-lib: libjpeg.$(A) install-headers
|
||||
$(INSTALL_LIB) libjpeg.$(A) $(libdir)/$(binprefix)libjpeg.$(A)
|
||||
|
||||
install-headers: jconfig.h
|
||||
$(INSTALL_DATA) jconfig.h $(includedir)/jconfig.h
|
||||
$(INSTALL_DATA) $(srcdir)/jpeglib.h $(includedir)/jpeglib.h
|
||||
$(INSTALL_DATA) $(srcdir)/jmorecfg.h $(includedir)/jmorecfg.h
|
||||
$(INSTALL_DATA) $(srcdir)/jerror.h $(includedir)/jerror.h
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.lo libjpeg.a libjpeg.la
|
||||
$(RM) cjpeg djpeg jpegtran rdjpgcom wrjpgcom
|
||||
$(RM) ansi2knr core testout* config.log config.status
|
||||
$(RM) -r knr .libs _libs
|
||||
|
||||
distclean: clean
|
||||
$(RM) Makefile jconfig.h libtool config.cache
|
||||
|
||||
test: cjpeg djpeg jpegtran
|
||||
$(RM) testout*
|
||||
./djpeg -dct int -ppm -outfile testout.ppm $(srcdir)/testorig.jpg
|
||||
./djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(srcdir)/testorig.jpg
|
||||
./cjpeg -dct int -outfile testout.jpg $(srcdir)/testimg.ppm
|
||||
./djpeg -dct int -ppm -outfile testoutp.ppm $(srcdir)/testprog.jpg
|
||||
./cjpeg -dct int -progressive -opt -outfile testoutp.jpg $(srcdir)/testimg.ppm
|
||||
./jpegtran -outfile testoutt.jpg $(srcdir)/testprog.jpg
|
||||
cmp $(srcdir)/testimg.ppm testout.ppm
|
||||
cmp $(srcdir)/testimg.bmp testout.bmp
|
||||
cmp $(srcdir)/testimg.jpg testout.jpg
|
||||
cmp $(srcdir)/testimg.ppm testoutp.ppm
|
||||
cmp $(srcdir)/testimgp.jpg testoutp.jpg
|
||||
cmp $(srcdir)/testorig.jpg testoutt.jpg
|
||||
|
||||
check: test
|
||||
|
||||
# Mistake catcher:
|
||||
|
||||
jconfig.h: jconfig.doc
|
||||
echo You must prepare a system-dependent jconfig.h file.
|
||||
echo Please read the installation directions in install.doc.
|
||||
exit 1
|
||||
|
||||
# GNU Make likes to know which target names are not really files to be made:
|
||||
.PHONY: all install install-lib install-headers clean distclean test check
|
||||
|
||||
|
||||
jcapimin.$(O): jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcapistd.$(O): jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jccoefct.$(O): jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jccolor.$(O): jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcdctmgr.$(O): jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jchuff.$(O): jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h
|
||||
jcinit.$(O): jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcmainct.$(O): jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcmarker.$(O): jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcmaster.$(O): jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcomapi.$(O): jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcparam.$(O): jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcphuff.$(O): jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h
|
||||
jcprepct.$(O): jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jcsample.$(O): jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jctrans.$(O): jctrans.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
|
||||
jdatadst.$(O): jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.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
|
||||
jdtrans.$(O): jdtrans.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
|
||||
jfdctflt.$(O): jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jfdctfst.$(O): jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jfdctint.$(O): jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jidctflt.$(O): jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jidctfst.$(O): jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jidctint.$(O): jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jidctred.$(O): jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jquant1.$(O): jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jquant2.$(O): jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.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 jmemsys.h
|
||||
jmemansi.$(O): jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h
|
||||
jmemname.$(O): jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h
|
||||
jmemnobs.$(O): jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h
|
||||
jmemdos.$(O): jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h
|
||||
jmemmac.$(O): jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h
|
||||
cjpeg.$(O): cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h
|
||||
djpeg.$(O): djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h
|
||||
jpegtran.$(O): jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h
|
||||
rdjpgcom.$(O): rdjpgcom.c jinclude.h jconfig.h
|
||||
wrjpgcom.$(O): wrjpgcom.c jinclude.h jconfig.h
|
||||
cdjpeg.$(O): cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdcolmap.$(O): rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdswitch.$(O): rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
transupp.$(O): transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h
|
||||
rdppm.$(O): rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
wrppm.$(O): wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdgif.$(O): rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
wrgif.$(O): wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdtarga.$(O): rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
wrtarga.$(O): wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdbmp.$(O): rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
wrbmp.$(O): wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
rdrle.$(O): rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
wrrle.$(O): wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h
|
||||
54
rdjpgcom.1
Normal file
54
rdjpgcom.1
Normal file
@@ -0,0 +1,54 @@
|
||||
.TH RDJPGCOM 1 "11 October 1997"
|
||||
.SH NAME
|
||||
rdjpgcom \- display text comments from a JPEG file
|
||||
.SH SYNOPSIS
|
||||
.B rdjpgcom
|
||||
[
|
||||
.B \-verbose
|
||||
]
|
||||
[
|
||||
.I filename
|
||||
]
|
||||
.LP
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
.B rdjpgcom
|
||||
reads the named JPEG/JFIF file, or the standard input if no file is named,
|
||||
and prints any text comments found in the file on the standard output.
|
||||
.PP
|
||||
The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file.
|
||||
Although the standard doesn't actually define what COM blocks are for, they
|
||||
are widely used to hold user-supplied text strings. This lets you add
|
||||
annotations, titles, index terms, etc to your JPEG files, and later retrieve
|
||||
them as text. COM blocks do not interfere with the image stored in the JPEG
|
||||
file. The maximum size of a COM block is 64K, but you can have as many of
|
||||
them as you like in one JPEG file.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-verbose
|
||||
Causes
|
||||
.B rdjpgcom
|
||||
to also display the JPEG image dimensions.
|
||||
.PP
|
||||
Switch names may be abbreviated, and are not case sensitive.
|
||||
.SH HINTS
|
||||
.B rdjpgcom
|
||||
does not depend on the IJG JPEG library. Its source code is intended as an
|
||||
illustration of the minimum amount of code required to parse a JPEG file
|
||||
header correctly.
|
||||
.PP
|
||||
In
|
||||
.B \-verbose
|
||||
mode,
|
||||
.B rdjpgcom
|
||||
will also attempt to print the contents of any "APP12" markers as text.
|
||||
Some digital cameras produce APP12 markers containing useful textual
|
||||
information. If you like, you can modify the source code to print
|
||||
other APPn marker types as well.
|
||||
.SH SEE ALSO
|
||||
.BR cjpeg (1),
|
||||
.BR djpeg (1),
|
||||
.BR jpegtran (1),
|
||||
.BR wrjpgcom (1)
|
||||
.SH AUTHOR
|
||||
Independent JPEG Group
|
||||
496
rdjpgcom.c
Normal file
496
rdjpgcom.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
* rdjpgcom.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 a very simple stand-alone application that displays
|
||||
* the text in COM (comment) markers in a JFIF file.
|
||||
* This may be useful as an example of the minimum logic needed to parse
|
||||
* JPEG markers.
|
||||
*/
|
||||
|
||||
#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
|
||||
#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
|
||||
|
||||
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||
#ifdef USE_SETMODE
|
||||
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||
#include <io.h> /* to declare setmode() */
|
||||
#endif
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#else
|
||||
#ifdef VMS /* VMS is very nonstandard */
|
||||
#define READ_BINARY "rb", "ctx=stm"
|
||||
#else /* standard ANSI-compliant case */
|
||||
#define READ_BINARY "rb"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
#ifdef VMS
|
||||
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
|
||||
#else
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These macros are used to read the input file.
|
||||
* To reuse this code in another application, you might need to change these.
|
||||
*/
|
||||
|
||||
static FILE * infile; /* input JPEG file */
|
||||
|
||||
/* Return next input byte, or EOF if no more */
|
||||
#define NEXTBYTE() getc(infile)
|
||||
|
||||
|
||||
/* Error exit handler */
|
||||
#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
|
||||
|
||||
|
||||
/* Read one byte, testing for EOF */
|
||||
static int
|
||||
read_1_byte (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = NEXTBYTE();
|
||||
if (c == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Read 2 bytes, convert to unsigned int */
|
||||
/* All 2-byte quantities in JPEG markers are MSB first */
|
||||
static unsigned int
|
||||
read_2_bytes (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
if (c1 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
c2 = NEXTBYTE();
|
||||
if (c2 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return (((unsigned int) c1) << 8) + ((unsigned int) c2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||||
* code byte (which is not an FF). Here are the marker codes of interest
|
||||
* in this program. (See jdmarker.c for a more complete list.)
|
||||
*/
|
||||
|
||||
#define M_SOF0 0xC0 /* Start Of Frame N */
|
||||
#define M_SOF1 0xC1 /* N indicates which compression process */
|
||||
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
|
||||
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
|
||||
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
|
||||
#define M_APP0 0xE0 /* Application-specific marker, type N */
|
||||
#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
|
||||
#define M_COM 0xFE /* COMment */
|
||||
|
||||
|
||||
/*
|
||||
* Find the next JPEG marker and return its marker code.
|
||||
* We expect at least one FF byte, possibly more if the compressor used FFs
|
||||
* to pad the file.
|
||||
* There could also be non-FF garbage between markers. The treatment of such
|
||||
* garbage is unspecified; we choose to skip over it but emit a warning msg.
|
||||
* NB: this routine must not be used after seeing SOS marker, since it will
|
||||
* not deal correctly with FF/00 sequences in the compressed image data...
|
||||
*/
|
||||
|
||||
static int
|
||||
next_marker (void)
|
||||
{
|
||||
int c;
|
||||
int discarded_bytes = 0;
|
||||
|
||||
/* Find 0xFF byte; count and skip any non-FFs. */
|
||||
c = read_1_byte();
|
||||
while (c != 0xFF) {
|
||||
discarded_bytes++;
|
||||
c = read_1_byte();
|
||||
}
|
||||
/* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
|
||||
* are legal as pad bytes, so don't count them in discarded_bytes.
|
||||
*/
|
||||
do {
|
||||
c = read_1_byte();
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (discarded_bytes != 0) {
|
||||
fprintf(stderr, "Warning: garbage data found in JPEG file\n");
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the initial marker, which should be SOI.
|
||||
* For a JFIF file, the first two bytes of the file should be literally
|
||||
* 0xFF M_SOI. To be more general, we could use next_marker, but if the
|
||||
* input file weren't actually JPEG at all, next_marker might read the whole
|
||||
* file and then return a misleading error message...
|
||||
*/
|
||||
|
||||
static int
|
||||
first_marker (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
c2 = NEXTBYTE();
|
||||
if (c1 != 0xFF || c2 != M_SOI)
|
||||
ERREXIT("Not a JPEG file");
|
||||
return c2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Most types of marker are followed by a variable-length parameter segment.
|
||||
* This routine skips over the parameters for any marker we don't otherwise
|
||||
* want to process.
|
||||
* Note that we MUST skip the parameter segment explicitly in order not to
|
||||
* be fooled by 0xFF bytes that might appear within the parameter segment;
|
||||
* such bytes do NOT introduce new markers.
|
||||
*/
|
||||
|
||||
static void
|
||||
skip_variable (void)
|
||||
/* Skip over an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Skip over the remaining bytes */
|
||||
while (length > 0) {
|
||||
(void) read_1_byte();
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a COM marker.
|
||||
* We want to print out the marker contents as legible text;
|
||||
* we must guard against non-text junk and varying newline representations.
|
||||
*/
|
||||
|
||||
static void
|
||||
process_COM (void)
|
||||
{
|
||||
unsigned int length;
|
||||
int ch;
|
||||
int lastch = 0;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
|
||||
while (length > 0) {
|
||||
ch = read_1_byte();
|
||||
/* Emit the character in a readable form.
|
||||
* Nonprintables are converted to \nnn form,
|
||||
* while \ is converted to \\.
|
||||
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
|
||||
*/
|
||||
if (ch == '\r') {
|
||||
printf("\n");
|
||||
} else if (ch == '\n') {
|
||||
if (lastch != '\r')
|
||||
printf("\n");
|
||||
} else if (ch == '\\') {
|
||||
printf("\\\\");
|
||||
} else if (isprint(ch)) {
|
||||
putc(ch, stdout);
|
||||
} else {
|
||||
printf("\\%03o", ch);
|
||||
}
|
||||
lastch = ch;
|
||||
length--;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a SOFn marker.
|
||||
* This code is only needed if you want to know the image dimensions...
|
||||
*/
|
||||
|
||||
static void
|
||||
process_SOFn (int marker)
|
||||
{
|
||||
unsigned int length;
|
||||
unsigned int image_height, image_width;
|
||||
int data_precision, num_components;
|
||||
const char * process;
|
||||
int ci;
|
||||
|
||||
length = read_2_bytes(); /* usual parameter length count */
|
||||
|
||||
data_precision = read_1_byte();
|
||||
image_height = read_2_bytes();
|
||||
image_width = read_2_bytes();
|
||||
num_components = read_1_byte();
|
||||
|
||||
switch (marker) {
|
||||
case M_SOF0: process = "Baseline"; break;
|
||||
case M_SOF1: process = "Extended sequential"; break;
|
||||
case M_SOF2: process = "Progressive"; break;
|
||||
case M_SOF3: process = "Lossless"; break;
|
||||
case M_SOF5: process = "Differential sequential"; break;
|
||||
case M_SOF6: process = "Differential progressive"; break;
|
||||
case M_SOF7: process = "Differential lossless"; break;
|
||||
case M_SOF9: process = "Extended sequential, arithmetic coding"; break;
|
||||
case M_SOF10: process = "Progressive, arithmetic coding"; break;
|
||||
case M_SOF11: process = "Lossless, arithmetic coding"; break;
|
||||
case M_SOF13: process = "Differential sequential, arithmetic coding"; break;
|
||||
case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
|
||||
case M_SOF15: process = "Differential lossless, arithmetic coding"; break;
|
||||
default: process = "Unknown"; break;
|
||||
}
|
||||
|
||||
printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
|
||||
image_width, image_height, num_components, data_precision);
|
||||
printf("JPEG process: %s\n", process);
|
||||
|
||||
if (length != (unsigned int) (8 + num_components * 3))
|
||||
ERREXIT("Bogus SOF marker length");
|
||||
|
||||
for (ci = 0; ci < num_components; ci++) {
|
||||
(void) read_1_byte(); /* Component ID code */
|
||||
(void) read_1_byte(); /* H, V sampling factors */
|
||||
(void) read_1_byte(); /* Quantization table number */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the marker stream until SOS or EOI is seen;
|
||||
* display any COM markers.
|
||||
* While the companion program wrjpgcom will always insert COM markers before
|
||||
* SOFn, other implementations might not, so we scan to SOS before stopping.
|
||||
* If we were only interested in the image dimensions, we would stop at SOFn.
|
||||
* (Conversely, if we only cared about COM markers, there would be no need
|
||||
* for special code to handle SOFn; we could treat it like other markers.)
|
||||
*/
|
||||
|
||||
static int
|
||||
scan_JPEG_header (int verbose)
|
||||
{
|
||||
int marker;
|
||||
|
||||
/* Expect SOI at start of file */
|
||||
if (first_marker() != M_SOI)
|
||||
ERREXIT("Expected SOI marker first");
|
||||
|
||||
/* Scan miscellaneous markers until we reach SOS. */
|
||||
for (;;) {
|
||||
marker = next_marker();
|
||||
switch (marker) {
|
||||
/* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
|
||||
* treated as SOFn. C4 in particular is actually DHT.
|
||||
*/
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
case M_SOF5: /* Differential sequential, Huffman */
|
||||
case M_SOF6: /* Differential progressive, Huffman */
|
||||
case M_SOF7: /* Differential lossless, Huffman */
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
case M_SOF13: /* Differential sequential, arithmetic */
|
||||
case M_SOF14: /* Differential progressive, arithmetic */
|
||||
case M_SOF15: /* Differential lossless, arithmetic */
|
||||
if (verbose)
|
||||
process_SOFn(marker);
|
||||
else
|
||||
skip_variable();
|
||||
break;
|
||||
|
||||
case M_SOS: /* stop before hitting compressed data */
|
||||
return marker;
|
||||
|
||||
case M_EOI: /* in case it's a tables-only JPEG stream */
|
||||
return marker;
|
||||
|
||||
case M_COM:
|
||||
process_COM();
|
||||
break;
|
||||
|
||||
case M_APP12:
|
||||
/* Some digital camera makers put useful textual information into
|
||||
* APP12 markers, so we print those out too when in -verbose mode.
|
||||
*/
|
||||
if (verbose) {
|
||||
printf("APP12 contains:\n");
|
||||
process_COM();
|
||||
} else
|
||||
skip_variable();
|
||||
break;
|
||||
|
||||
default: /* Anything else just gets skipped */
|
||||
skip_variable(); /* we assume it has a parameter count... */
|
||||
break;
|
||||
}
|
||||
} /* end loop */
|
||||
}
|
||||
|
||||
|
||||
/* Command line parsing code */
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n");
|
||||
|
||||
fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname);
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -verbose Also display dimensions of JPEG image\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
keymatch (char * arg, const char * keyword, int minchars)
|
||||
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
|
||||
/* keyword is the constant keyword (must be lower case already), */
|
||||
/* minchars is length of minimum legal abbreviation. */
|
||||
{
|
||||
register int ca, ck;
|
||||
register int nmatched = 0;
|
||||
|
||||
while ((ca = *arg++) != '\0') {
|
||||
if ((ck = *keyword++) == '\0')
|
||||
return 0; /* arg longer than keyword, no good */
|
||||
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||
ca = tolower(ca);
|
||||
if (ca != ck)
|
||||
return 0; /* no good */
|
||||
nmatched++; /* count matched characters */
|
||||
}
|
||||
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||
if (nmatched < minchars)
|
||||
return 0;
|
||||
return 1; /* A-OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
int verbose = 0;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "rdjpgcom"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Parse switches, if any */
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (arg[0] != '-')
|
||||
break; /* not switch, must be file name */
|
||||
arg++; /* advance over '-' */
|
||||
if (keymatch(arg, "verbose", 1)) {
|
||||
verbose++;
|
||||
} else
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Open the input file. */
|
||||
/* Unix style: expect zero or one file name */
|
||||
if (argn < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", progname);
|
||||
usage();
|
||||
}
|
||||
if (argn < argc) {
|
||||
if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default input file is stdin */
|
||||
#ifdef USE_SETMODE /* need to hack file mode? */
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
#endif
|
||||
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
|
||||
if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdin\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
infile = stdin;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Scan the JPEG headers. */
|
||||
(void) scan_JPEG_header(verbose);
|
||||
|
||||
/* All done. */
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
387
rdrle.c
Normal file
387
rdrle.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* rdrle.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 routines to read input images in Utah RLE format.
|
||||
* The Utah Raster Toolkit library is required (version 3.1 or later).
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume input from
|
||||
* an ordinary stdio stream. They further assume that reading begins
|
||||
* at the start of the file; start_input may need work if the
|
||||
* user interface has already read some data (e.g., to determine that
|
||||
* the file is indeed RLE format).
|
||||
*
|
||||
* Based on code contributed by Mike Lijewski,
|
||||
* with updates from Robert Hutchinson.
|
||||
*/
|
||||
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
|
||||
#ifdef RLE_SUPPORTED
|
||||
|
||||
/* rle.h is provided by the Utah Raster Toolkit. */
|
||||
|
||||
#include <rle.h>
|
||||
|
||||
/*
|
||||
* We assume that JSAMPLE has the same representation as rle_pixel,
|
||||
* to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE != 8
|
||||
Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We support the following types of RLE files:
|
||||
*
|
||||
* GRAYSCALE - 8 bits, no colormap
|
||||
* MAPPEDGRAY - 8 bits, 1 channel colomap
|
||||
* PSEUDOCOLOR - 8 bits, 3 channel colormap
|
||||
* TRUECOLOR - 24 bits, 3 channel colormap
|
||||
* DIRECTCOLOR - 24 bits, no colormap
|
||||
*
|
||||
* For now, we ignore any alpha channel in the image.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{ GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
|
||||
|
||||
|
||||
/*
|
||||
* Since RLE stores scanlines bottom-to-top, we have to invert the image
|
||||
* to conform to JPEG's top-to-bottom order. To do this, we read the
|
||||
* incoming image into a virtual array on the first get_pixel_rows call,
|
||||
* then fetch the required row from the virtual array on subsequent calls.
|
||||
*/
|
||||
|
||||
typedef struct _rle_source_struct * rle_source_ptr;
|
||||
|
||||
typedef struct _rle_source_struct {
|
||||
struct cjpeg_source_struct pub; /* public fields */
|
||||
|
||||
rle_kind visual; /* actual type of input file */
|
||||
jvirt_sarray_ptr image; /* virtual array to hold the image */
|
||||
JDIMENSION row; /* current row # in the virtual array */
|
||||
rle_hdr header; /* Input file information */
|
||||
rle_pixel** rle_row; /* holds a row returned by rle_getrow() */
|
||||
|
||||
} rle_source_struct;
|
||||
|
||||
|
||||
/*
|
||||
* Read the file header; return image size and component count.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
||||
{
|
||||
rle_source_ptr source = (rle_source_ptr) sinfo;
|
||||
JDIMENSION width, height;
|
||||
#ifdef PROGRESS_REPORT
|
||||
cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
|
||||
#endif
|
||||
|
||||
/* Use RLE library routine to get the header info */
|
||||
source->header = *rle_hdr_init(NULL);
|
||||
source->header.rle_file = source->pub.input_file;
|
||||
switch (rle_get_setup(&(source->header))) {
|
||||
case RLE_SUCCESS:
|
||||
/* A-OK */
|
||||
break;
|
||||
case RLE_NOT_RLE:
|
||||
ERREXIT(cinfo, JERR_RLE_NOT);
|
||||
break;
|
||||
case RLE_NO_SPACE:
|
||||
ERREXIT(cinfo, JERR_RLE_MEM);
|
||||
break;
|
||||
case RLE_EMPTY:
|
||||
ERREXIT(cinfo, JERR_RLE_EMPTY);
|
||||
break;
|
||||
case RLE_EOF:
|
||||
ERREXIT(cinfo, JERR_RLE_EOF);
|
||||
break;
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_RLE_BADERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Figure out what we have, set private vars and return values accordingly */
|
||||
|
||||
width = source->header.xmax - source->header.xmin + 1;
|
||||
height = source->header.ymax - source->header.ymin + 1;
|
||||
source->header.xmin = 0; /* realign horizontally */
|
||||
source->header.xmax = width-1;
|
||||
|
||||
cinfo->image_width = width;
|
||||
cinfo->image_height = height;
|
||||
cinfo->data_precision = 8; /* we can only handle 8 bit data */
|
||||
|
||||
if (source->header.ncolors == 1 && source->header.ncmap == 0) {
|
||||
source->visual = GRAYSCALE;
|
||||
TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
|
||||
} else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
|
||||
source->visual = MAPPEDGRAY;
|
||||
TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
|
||||
1 << source->header.cmaplen);
|
||||
} else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
|
||||
source->visual = PSEUDOCOLOR;
|
||||
TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
|
||||
1 << source->header.cmaplen);
|
||||
} else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
|
||||
source->visual = TRUECOLOR;
|
||||
TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
|
||||
1 << source->header.cmaplen);
|
||||
} else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
|
||||
source->visual = DIRECTCOLOR;
|
||||
TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
|
||||
|
||||
if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
|
||||
cinfo->in_color_space = JCS_GRAYSCALE;
|
||||
cinfo->input_components = 1;
|
||||
} else {
|
||||
cinfo->in_color_space = JCS_RGB;
|
||||
cinfo->input_components = 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* A place to hold each scanline while it's converted.
|
||||
* (GRAYSCALE scanlines don't need converting)
|
||||
*/
|
||||
if (source->visual != GRAYSCALE) {
|
||||
source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) width, (JDIMENSION) cinfo->input_components);
|
||||
}
|
||||
|
||||
/* request a virtual array to hold the image */
|
||||
source->image = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) (width * source->header.ncolors),
|
||||
(JDIMENSION) height, (JDIMENSION) 1);
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
/* count file input as separate pass */
|
||||
progress->total_extra_passes++;
|
||||
}
|
||||
#endif
|
||||
|
||||
source->pub.buffer_height = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
* Called only after load_image has read the image into the virtual array.
|
||||
* Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
||||
{
|
||||
rle_source_ptr source = (rle_source_ptr) sinfo;
|
||||
|
||||
source->row--;
|
||||
source->pub.buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one row of pixels.
|
||||
* Called only after load_image has read the image into the virtual array.
|
||||
* Used for PSEUDOCOLOR images.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
||||
{
|
||||
rle_source_ptr source = (rle_source_ptr) sinfo;
|
||||
JSAMPROW src_row, dest_row;
|
||||
JDIMENSION col;
|
||||
rle_map *colormap;
|
||||
int val;
|
||||
|
||||
colormap = source->header.cmap;
|
||||
dest_row = source->pub.buffer[0];
|
||||
source->row--;
|
||||
src_row = * (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
|
||||
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
val = GETJSAMPLE(*src_row++);
|
||||
*dest_row++ = (JSAMPLE) (colormap[val ] >> 8);
|
||||
*dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8);
|
||||
*dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load the image into a virtual array. We have to do this because RLE
|
||||
* files start at the lower left while the JPEG standard has them starting
|
||||
* in the upper left. This is called the first time we want to get a row
|
||||
* of input. What we do is load the RLE data into the array and then call
|
||||
* the appropriate routine to read one row from the array. Before returning,
|
||||
* we set source->pub.get_pixel_rows so that subsequent calls go straight to
|
||||
* the appropriate row-reading routine.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
||||
{
|
||||
rle_source_ptr source = (rle_source_ptr) sinfo;
|
||||
JDIMENSION row, col;
|
||||
JSAMPROW scanline, red_ptr, green_ptr, blue_ptr;
|
||||
rle_pixel **rle_row;
|
||||
rle_map *colormap;
|
||||
char channel;
|
||||
#ifdef PROGRESS_REPORT
|
||||
cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
|
||||
#endif
|
||||
|
||||
colormap = source->header.cmap;
|
||||
rle_row = source->rle_row;
|
||||
|
||||
/* Read the RLE data into our virtual array.
|
||||
* We assume here that (a) rle_pixel is represented the same as JSAMPLE,
|
||||
* and (b) we are not on a machine where FAR pointers differ from regular.
|
||||
*/
|
||||
RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_limit = cinfo->image_height;
|
||||
progress->pub.pass_counter = 0;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (source->visual) {
|
||||
|
||||
case GRAYSCALE:
|
||||
case PSEUDOCOLOR:
|
||||
for (row = 0; row < cinfo->image_height; row++) {
|
||||
rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
|
||||
rle_getrow(&source->header, rle_row);
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_counter++;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case MAPPEDGRAY:
|
||||
case TRUECOLOR:
|
||||
for (row = 0; row < cinfo->image_height; row++) {
|
||||
scanline = * (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
|
||||
rle_row = source->rle_row;
|
||||
rle_getrow(&source->header, rle_row);
|
||||
|
||||
for (col = 0; col < cinfo->image_width; col++) {
|
||||
for (channel = 0; channel < source->header.ncolors; channel++) {
|
||||
*scanline++ = (JSAMPLE)
|
||||
(colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_counter++;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DIRECTCOLOR:
|
||||
for (row = 0; row < cinfo->image_height; row++) {
|
||||
scanline = * (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
|
||||
rle_getrow(&source->header, rle_row);
|
||||
|
||||
red_ptr = rle_row[0];
|
||||
green_ptr = rle_row[1];
|
||||
blue_ptr = rle_row[2];
|
||||
|
||||
for (col = cinfo->image_width; col > 0; col--) {
|
||||
*scanline++ = *red_ptr++;
|
||||
*scanline++ = *green_ptr++;
|
||||
*scanline++ = *blue_ptr++;
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_counter++;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL)
|
||||
progress->completed_extra_passes++;
|
||||
#endif
|
||||
|
||||
/* Set up to call proper row-extraction routine in future */
|
||||
if (source->visual == PSEUDOCOLOR) {
|
||||
source->pub.buffer = source->rle_row;
|
||||
source->pub.get_pixel_rows = get_pseudocolor_row;
|
||||
} else {
|
||||
source->pub.get_pixel_rows = get_rle_row;
|
||||
}
|
||||
source->row = cinfo->image_height;
|
||||
|
||||
/* And fetch the topmost (bottommost) row */
|
||||
return (*source->pub.get_pixel_rows) (cinfo, sinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
||||
{
|
||||
/* no work */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The module selection routine for RLE format input.
|
||||
*/
|
||||
|
||||
GLOBAL(cjpeg_source_ptr)
|
||||
jinit_read_rle (j_compress_ptr cinfo)
|
||||
{
|
||||
rle_source_ptr source;
|
||||
|
||||
/* Create module interface object */
|
||||
source = (rle_source_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(rle_source_struct));
|
||||
/* Fill in method ptrs */
|
||||
source->pub.start_input = start_input_rle;
|
||||
source->pub.finish_input = finish_input_rle;
|
||||
source->pub.get_pixel_rows = load_image;
|
||||
|
||||
return (cjpeg_source_ptr) source;
|
||||
}
|
||||
|
||||
#endif /* RLE_SUPPORTED */
|
||||
948
structure.doc
Normal file
948
structure.doc
Normal file
@@ -0,0 +1,948 @@
|
||||
IJG JPEG LIBRARY: SYSTEM ARCHITECTURE
|
||||
|
||||
Copyright (C) 1991-1995, 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 an overview of the architecture of the IJG JPEG software;
|
||||
that is, the functions of the various modules in the system and the interfaces
|
||||
between modules. For more precise details about any data structure or calling
|
||||
convention, see the include files and comments in the source code.
|
||||
|
||||
We assume that the reader is already somewhat familiar with the JPEG standard.
|
||||
The README file includes references for learning about JPEG. The file
|
||||
libjpeg.doc describes the library from the viewpoint of an application
|
||||
programmer using the library; it's best to read that file before this one.
|
||||
Also, the file coderules.doc describes the coding style conventions we use.
|
||||
|
||||
In this document, JPEG-specific terminology follows the JPEG standard:
|
||||
A "component" means a color channel, e.g., Red or Luminance.
|
||||
A "sample" is a single component value (i.e., one number in the image data).
|
||||
A "coefficient" is a frequency coefficient (a DCT transform output number).
|
||||
A "block" is an 8x8 group of samples or coefficients.
|
||||
An "MCU" (minimum coded unit) is an interleaved set of blocks of size
|
||||
determined by the sampling factors, or a single block in a
|
||||
noninterleaved scan.
|
||||
We do not use the terms "pixel" and "sample" interchangeably. When we say
|
||||
pixel, we mean an element of the full-size image, while a sample is an element
|
||||
of the downsampled image. Thus the number of samples may vary across
|
||||
components while the number of pixels does not. (This terminology is not used
|
||||
rigorously throughout the code, but it is used in places where confusion would
|
||||
otherwise result.)
|
||||
|
||||
|
||||
*** System features ***
|
||||
|
||||
The IJG distribution contains two parts:
|
||||
* A subroutine library for JPEG compression and decompression.
|
||||
* cjpeg/djpeg, two sample applications that use the library to transform
|
||||
JFIF JPEG files to and from several other image formats.
|
||||
cjpeg/djpeg are of no great intellectual complexity: they merely add a simple
|
||||
command-line user interface and I/O routines for several uncompressed image
|
||||
formats. This document concentrates on the library itself.
|
||||
|
||||
We desire the library to be capable of supporting all JPEG baseline, extended
|
||||
sequential, and progressive DCT processes. Hierarchical processes are not
|
||||
supported.
|
||||
|
||||
The library does not support the lossless (spatial) JPEG process. Lossless
|
||||
JPEG shares little or no code with lossy JPEG, and would normally be used
|
||||
without the extensive pre- and post-processing provided by this library.
|
||||
We feel that lossless JPEG is better handled by a separate library.
|
||||
|
||||
Within these limits, any set of compression parameters allowed by the JPEG
|
||||
spec should be readable for decompression. (We can be more restrictive about
|
||||
what formats we can generate.) Although the system design allows for all
|
||||
parameter values, some uncommon settings are not yet implemented and may
|
||||
never be; nonintegral sampling ratios are the prime example. Furthermore,
|
||||
we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a
|
||||
run-time option, because most machines can store 8-bit pixels much more
|
||||
compactly than 12-bit.
|
||||
|
||||
For legal reasons, JPEG arithmetic coding is not currently supported, but
|
||||
extending the library to include it would be straightforward.
|
||||
|
||||
By itself, the library handles only interchange JPEG datastreams --- in
|
||||
particular the widely used JFIF file format. The library can be used by
|
||||
surrounding code to process interchange or abbreviated JPEG datastreams that
|
||||
are embedded in more complex file formats. (For example, libtiff uses this
|
||||
library to implement JPEG compression within the TIFF file format.)
|
||||
|
||||
The library includes a substantial amount of code that is not covered by the
|
||||
JPEG standard but is necessary for typical applications of JPEG. These
|
||||
functions preprocess the image before JPEG compression or postprocess it after
|
||||
decompression. They include colorspace conversion, downsampling/upsampling,
|
||||
and color quantization. This code can be omitted if not needed.
|
||||
|
||||
A wide range of quality vs. speed tradeoffs are possible in JPEG processing,
|
||||
and even more so in decompression postprocessing. The decompression library
|
||||
provides multiple implementations that cover most of the useful tradeoffs,
|
||||
ranging from very-high-quality down to fast-preview operation. On the
|
||||
compression side we have generally not provided low-quality choices, since
|
||||
compression is normally less time-critical. It should be understood that the
|
||||
low-quality modes may not meet the JPEG standard's accuracy requirements;
|
||||
nonetheless, they are useful for viewers.
|
||||
|
||||
|
||||
*** Portability issues ***
|
||||
|
||||
Portability is an essential requirement for the library. The key portability
|
||||
issues that show up at the level of system architecture are:
|
||||
|
||||
1. Memory usage. We want the code to be able to run on PC-class machines
|
||||
with limited memory. Images should therefore be processed sequentially (in
|
||||
strips), to avoid holding the whole image in memory at once. Where a
|
||||
full-image buffer is necessary, we should be able to use either virtual memory
|
||||
or temporary files.
|
||||
|
||||
2. Near/far pointer distinction. To run efficiently on 80x86 machines, the
|
||||
code should distinguish "small" objects (kept in near data space) from
|
||||
"large" ones (kept in far data space). This is an annoying restriction, but
|
||||
fortunately it does not impact code quality for less brain-damaged machines,
|
||||
and the source code clutter turns out to be minimal with sufficient use of
|
||||
pointer typedefs.
|
||||
|
||||
3. Data precision. We assume that "char" is at least 8 bits, "short" and
|
||||
"int" at least 16, "long" at least 32. The code will work fine with larger
|
||||
data sizes, although memory may be used inefficiently in some cases. However,
|
||||
the JPEG compressed datastream must ultimately appear on external storage as a
|
||||
sequence of 8-bit bytes if it is to conform to the standard. This may pose a
|
||||
problem on machines where char is wider than 8 bits. The library represents
|
||||
compressed data as an array of values of typedef JOCTET. If no data type
|
||||
exactly 8 bits wide is available, custom data source and data destination
|
||||
modules must be written to unpack and pack the chosen JOCTET datatype into
|
||||
8-bit external representation.
|
||||
|
||||
|
||||
*** System overview ***
|
||||
|
||||
The compressor and decompressor are each divided into two main sections:
|
||||
the JPEG compressor or decompressor proper, and the preprocessing or
|
||||
postprocessing functions. The interface between these two sections is the
|
||||
image data that the official JPEG spec regards as its input or output: this
|
||||
data is in the colorspace to be used for compression, and it is downsampled
|
||||
to the sampling factors to be used. The preprocessing and postprocessing
|
||||
steps are responsible for converting a normal image representation to or from
|
||||
this form. (Those few applications that want to deal with YCbCr downsampled
|
||||
data can skip the preprocessing or postprocessing step.)
|
||||
|
||||
Looking more closely, the compressor library contains the following main
|
||||
elements:
|
||||
|
||||
Preprocessing:
|
||||
* Color space conversion (e.g., RGB to YCbCr).
|
||||
* Edge expansion and downsampling. Optionally, this step can do simple
|
||||
smoothing --- this is often helpful for low-quality source data.
|
||||
JPEG proper:
|
||||
* MCU assembly, DCT, quantization.
|
||||
* Entropy coding (sequential or progressive, Huffman or arithmetic).
|
||||
|
||||
In addition to these modules we need overall control, marker generation,
|
||||
and support code (memory management & error handling). There is also a
|
||||
module responsible for physically writing the output data --- typically
|
||||
this is just an interface to fwrite(), but some applications may need to
|
||||
do something else with the data.
|
||||
|
||||
The decompressor library contains the following main elements:
|
||||
|
||||
JPEG proper:
|
||||
* Entropy decoding (sequential or progressive, Huffman or arithmetic).
|
||||
* Dequantization, inverse DCT, MCU disassembly.
|
||||
Postprocessing:
|
||||
* Upsampling. Optionally, this step may be able to do more general
|
||||
rescaling of the image.
|
||||
* Color space conversion (e.g., YCbCr to RGB). This step may also
|
||||
provide gamma adjustment [ currently it does not ].
|
||||
* Optional color quantization (e.g., reduction to 256 colors).
|
||||
* Optional color precision reduction (e.g., 24-bit to 15-bit color).
|
||||
[This feature is not currently implemented.]
|
||||
|
||||
We also need overall control, marker parsing, and a data source module.
|
||||
The support code (memory management & error handling) can be shared with
|
||||
the compression half of the library.
|
||||
|
||||
There may be several implementations of each of these elements, particularly
|
||||
in the decompressor, where a wide range of speed/quality tradeoffs is very
|
||||
useful. It must be understood that some of the best speedups involve
|
||||
merging adjacent steps in the pipeline. For example, upsampling, color space
|
||||
conversion, and color quantization might all be done at once when using a
|
||||
low-quality ordered-dither technique. The system architecture is designed to
|
||||
allow such merging where appropriate.
|
||||
|
||||
|
||||
Note: it is convenient to regard edge expansion (padding to block boundaries)
|
||||
as a preprocessing/postprocessing function, even though the JPEG spec includes
|
||||
it in compression/decompression. We do this because downsampling/upsampling
|
||||
can be simplified a little if they work on padded data: it's not necessary to
|
||||
have special cases at the right and bottom edges. Therefore the interface
|
||||
buffer is always an integral number of blocks wide and high, and we expect
|
||||
compression preprocessing to pad the source data properly. Padding will occur
|
||||
only to the next block (8-sample) boundary. In an interleaved-scan situation,
|
||||
additional dummy blocks may be used to fill out MCUs, but the MCU assembly and
|
||||
disassembly logic will create or discard these blocks internally. (This is
|
||||
advantageous for speed reasons, since we avoid DCTing the dummy blocks.
|
||||
It also permits a small reduction in file size, because the compressor can
|
||||
choose dummy block contents so as to minimize their size in compressed form.
|
||||
Finally, it makes the interface buffer specification independent of whether
|
||||
the file is actually interleaved or not.) Applications that wish to deal
|
||||
directly with the downsampled data must provide similar buffering and padding
|
||||
for odd-sized images.
|
||||
|
||||
|
||||
*** Poor man's object-oriented programming ***
|
||||
|
||||
It should be clear by now that we have a lot of quasi-independent processing
|
||||
steps, many of which have several possible behaviors. To avoid cluttering the
|
||||
code with lots of switch statements, we use a simple form of object-style
|
||||
programming to separate out the different possibilities.
|
||||
|
||||
For example, two different color quantization algorithms could be implemented
|
||||
as two separate modules that present the same external interface; at runtime,
|
||||
the calling code will access the proper module indirectly through an "object".
|
||||
|
||||
We can get the limited features we need while staying within portable C.
|
||||
The basic tool is a function pointer. An "object" is just a struct
|
||||
containing one or more function pointer fields, each of which corresponds to
|
||||
a method name in real object-oriented languages. During initialization we
|
||||
fill in the function pointers with references to whichever module we have
|
||||
determined we need to use in this run. Then invocation of the module is done
|
||||
by indirecting through a function pointer; on most machines this is no more
|
||||
expensive than a switch statement, which would be the only other way of
|
||||
making the required run-time choice. The really significant benefit, of
|
||||
course, is keeping the source code clean and well structured.
|
||||
|
||||
We can also arrange to have private storage that varies between different
|
||||
implementations of the same kind of object. We do this by making all the
|
||||
module-specific object structs be separately allocated entities, which will
|
||||
be accessed via pointers in the master compression or decompression struct.
|
||||
The "public" fields or methods for a given kind of object are specified by
|
||||
a commonly known struct. But a module's initialization code can allocate
|
||||
a larger struct that contains the common struct as its first member, plus
|
||||
additional private fields. With appropriate pointer casting, the module's
|
||||
internal functions can access these private fields. (For a simple example,
|
||||
see jdatadst.c, which implements the external interface specified by struct
|
||||
jpeg_destination_mgr, but adds extra fields.)
|
||||
|
||||
(Of course this would all be a lot easier if we were using C++, but we are
|
||||
not yet prepared to assume that everyone has a C++ compiler.)
|
||||
|
||||
An important benefit of this scheme is that it is easy to provide multiple
|
||||
versions of any method, each tuned to a particular case. While a lot of
|
||||
precalculation might be done to select an optimal implementation of a method,
|
||||
the cost per invocation is constant. For example, the upsampling step might
|
||||
have a "generic" method, plus one or more "hardwired" methods for the most
|
||||
popular sampling factors; the hardwired methods would be faster because they'd
|
||||
use straight-line code instead of for-loops. The cost to determine which
|
||||
method to use is paid only once, at startup, and the selection criteria are
|
||||
hidden from the callers of the method.
|
||||
|
||||
This plan differs a little bit from usual object-oriented structures, in that
|
||||
only one instance of each object class will exist during execution. The
|
||||
reason for having the class structure is that on different runs we may create
|
||||
different instances (choose to execute different modules). You can think of
|
||||
the term "method" as denoting the common interface presented by a particular
|
||||
set of interchangeable functions, and "object" as denoting a group of related
|
||||
methods, or the total shared interface behavior of a group of modules.
|
||||
|
||||
|
||||
*** Overall control structure ***
|
||||
|
||||
We previously mentioned the need for overall control logic in the compression
|
||||
and decompression libraries. In IJG implementations prior to v5, overall
|
||||
control was mostly provided by "pipeline control" modules, which proved to be
|
||||
large, unwieldy, and hard to understand. To improve the situation, the
|
||||
control logic has been subdivided into multiple modules. The control modules
|
||||
consist of:
|
||||
|
||||
1. Master control for module selection and initialization. This has two
|
||||
responsibilities:
|
||||
|
||||
1A. Startup initialization at the beginning of image processing.
|
||||
The individual processing modules to be used in this run are selected
|
||||
and given initialization calls.
|
||||
|
||||
1B. Per-pass control. This determines how many passes will be performed
|
||||
and calls each active processing module to configure itself
|
||||
appropriately at the beginning of each pass. End-of-pass processing,
|
||||
where necessary, is also invoked from the master control module.
|
||||
|
||||
Method selection is partially distributed, in that a particular processing
|
||||
module may contain several possible implementations of a particular method,
|
||||
which it will select among when given its initialization call. The master
|
||||
control code need only be concerned with decisions that affect more than
|
||||
one module.
|
||||
|
||||
2. Data buffering control. A separate control module exists for each
|
||||
inter-processing-step data buffer. This module is responsible for
|
||||
invoking the processing steps that write or read that data buffer.
|
||||
|
||||
Each buffer controller sees the world as follows:
|
||||
|
||||
input data => processing step A => buffer => processing step B => output data
|
||||
| | |
|
||||
------------------ controller ------------------
|
||||
|
||||
The controller knows the dataflow requirements of steps A and B: how much data
|
||||
they want to accept in one chunk and how much they output in one chunk. Its
|
||||
function is to manage its buffer and call A and B at the proper times.
|
||||
|
||||
A data buffer control module may itself be viewed as a processing step by a
|
||||
higher-level control module; thus the control modules form a binary tree with
|
||||
elementary processing steps at the leaves of the tree.
|
||||
|
||||
The control modules are objects. A considerable amount of flexibility can
|
||||
be had by replacing implementations of a control module. For example:
|
||||
* Merging of adjacent steps in the pipeline is done by replacing a control
|
||||
module and its pair of processing-step modules with a single processing-
|
||||
step module. (Hence the possible merges are determined by the tree of
|
||||
control modules.)
|
||||
* In some processing modes, a given interstep buffer need only be a "strip"
|
||||
buffer large enough to accommodate the desired data chunk sizes. In other
|
||||
modes, a full-image buffer is needed and several passes are required.
|
||||
The control module determines which kind of buffer is used and manipulates
|
||||
virtual array buffers as needed. One or both processing steps may be
|
||||
unaware of the multi-pass behavior.
|
||||
|
||||
In theory, we might be able to make all of the data buffer controllers
|
||||
interchangeable and provide just one set of implementations for all. In
|
||||
practice, each one contains considerable special-case processing for its
|
||||
particular job. The buffer controller concept should be regarded as an
|
||||
overall system structuring principle, not as a complete description of the
|
||||
task performed by any one controller.
|
||||
|
||||
|
||||
*** Compression object structure ***
|
||||
|
||||
Here is a sketch of the logical structure of the JPEG compression library:
|
||||
|
||||
|-- Colorspace conversion
|
||||
|-- Preprocessing controller --|
|
||||
| |-- Downsampling
|
||||
Main controller --|
|
||||
| |-- Forward DCT, quantize
|
||||
|-- Coefficient controller --|
|
||||
|-- Entropy encoding
|
||||
|
||||
This sketch also describes the flow of control (subroutine calls) during
|
||||
typical image data processing. Each of the components shown in the diagram is
|
||||
an "object" which may have several different implementations available. One
|
||||
or more source code files contain the actual implementation(s) of each object.
|
||||
|
||||
The objects shown above are:
|
||||
|
||||
* Main controller: buffer controller for the subsampled-data buffer, which
|
||||
holds the preprocessed input data. This controller invokes preprocessing to
|
||||
fill the subsampled-data buffer, and JPEG compression to empty it. There is
|
||||
usually no need for a full-image buffer here; a strip buffer is adequate.
|
||||
|
||||
* Preprocessing controller: buffer controller for the downsampling input data
|
||||
buffer, which lies between colorspace conversion and downsampling. Note
|
||||
that a unified conversion/downsampling module would probably replace this
|
||||
controller entirely.
|
||||
|
||||
* Colorspace conversion: converts application image data into the desired
|
||||
JPEG color space; also changes the data from pixel-interleaved layout to
|
||||
separate component planes. Processes one pixel row at a time.
|
||||
|
||||
* Downsampling: performs reduction of chroma components as required.
|
||||
Optionally may perform pixel-level smoothing as well. Processes a "row
|
||||
group" at a time, where a row group is defined as Vmax pixel rows of each
|
||||
component before downsampling, and Vk sample rows afterwards (remember Vk
|
||||
differs across components). Some downsampling or smoothing algorithms may
|
||||
require context rows above and below the current row group; the
|
||||
preprocessing controller is responsible for supplying these rows via proper
|
||||
buffering. The downsampler is responsible for edge expansion at the right
|
||||
edge (i.e., extending each sample row to a multiple of 8 samples); but the
|
||||
preprocessing controller is responsible for vertical edge expansion (i.e.,
|
||||
duplicating the bottom sample row as needed to make a multiple of 8 rows).
|
||||
|
||||
* Coefficient controller: buffer controller for the DCT-coefficient data.
|
||||
This controller handles MCU assembly, including insertion of dummy DCT
|
||||
blocks when needed at the right or bottom edge. When performing
|
||||
Huffman-code optimization or emitting a multiscan JPEG file, this
|
||||
controller is responsible for buffering the full image. The equivalent of
|
||||
one fully interleaved MCU row of subsampled data is processed per call,
|
||||
even when the JPEG file is noninterleaved.
|
||||
|
||||
* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients.
|
||||
Works on one or more DCT blocks at a time. (Note: the coefficients are now
|
||||
emitted in normal array order, which the entropy encoder is expected to
|
||||
convert to zigzag order as necessary. Prior versions of the IJG code did
|
||||
the conversion to zigzag order within the quantization step.)
|
||||
|
||||
* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the
|
||||
coded data to the data destination module. Works on one MCU per call.
|
||||
For progressive JPEG, the same DCT blocks are fed to the entropy coder
|
||||
during each pass, and the coder must emit the appropriate subset of
|
||||
coefficients.
|
||||
|
||||
In addition to the above objects, the compression library includes these
|
||||
objects:
|
||||
|
||||
* Master control: determines the number of passes required, controls overall
|
||||
and per-pass initialization of the other modules.
|
||||
|
||||
* Marker writing: generates JPEG markers (except for RSTn, which is emitted
|
||||
by the entropy encoder when needed).
|
||||
|
||||
* Data destination manager: writes the output JPEG datastream to its final
|
||||
destination (e.g., a file). The destination manager supplied with the
|
||||
library knows how to write to a stdio stream; for other behaviors, the
|
||||
surrounding application may provide its own destination manager.
|
||||
|
||||
* Memory manager: allocates and releases memory, controls virtual arrays
|
||||
(with backing store management, where required).
|
||||
|
||||
* Error handler: performs formatting and output of error and trace messages;
|
||||
determines handling of nonfatal errors. The surrounding application may
|
||||
override some or all of this object's methods to change error handling.
|
||||
|
||||
* Progress monitor: supports output of "percent-done" progress reports.
|
||||
This object represents an optional callback to the surrounding application:
|
||||
if wanted, it must be supplied by the application.
|
||||
|
||||
The error handler, destination manager, and progress monitor objects are
|
||||
defined as separate objects in order to simplify application-specific
|
||||
customization of the JPEG library. A surrounding application may override
|
||||
individual methods or supply its own all-new implementation of one of these
|
||||
objects. The object interfaces for these objects are therefore treated as
|
||||
part of the application interface of the library, whereas the other objects
|
||||
are internal to the library.
|
||||
|
||||
The error handler and memory manager are shared by JPEG compression and
|
||||
decompression; the progress monitor, if used, may be shared as well.
|
||||
|
||||
|
||||
*** Decompression object structure ***
|
||||
|
||||
Here is a sketch of the logical structure of the JPEG decompression library:
|
||||
|
||||
|-- Entropy decoding
|
||||
|-- Coefficient controller --|
|
||||
| |-- Dequantize, Inverse DCT
|
||||
Main controller --|
|
||||
| |-- Upsampling
|
||||
|-- Postprocessing controller --| |-- Colorspace conversion
|
||||
|-- Color quantization
|
||||
|-- Color precision reduction
|
||||
|
||||
As before, this diagram also represents typical control flow. The objects
|
||||
shown are:
|
||||
|
||||
* Main controller: buffer controller for the subsampled-data buffer, which
|
||||
holds the output of JPEG decompression proper. This controller's primary
|
||||
task is to feed the postprocessing procedure. Some upsampling algorithms
|
||||
may require context rows above and below the current row group; when this
|
||||
is true, the main controller is responsible for managing its buffer so as
|
||||
to make context rows available. In the current design, the main buffer is
|
||||
always a strip buffer; a full-image buffer is never required.
|
||||
|
||||
* Coefficient controller: buffer controller for the DCT-coefficient data.
|
||||
This controller handles MCU disassembly, including deletion of any dummy
|
||||
DCT blocks at the right or bottom edge. When reading a multiscan JPEG
|
||||
file, this controller is responsible for buffering the full image.
|
||||
(Buffering DCT coefficients, rather than samples, is necessary to support
|
||||
progressive JPEG.) The equivalent of one fully interleaved MCU row of
|
||||
subsampled data is processed per call, even when the source JPEG file is
|
||||
noninterleaved.
|
||||
|
||||
* Entropy decoding: Read coded data from the data source module and perform
|
||||
Huffman or arithmetic entropy decoding. Works on one MCU per call.
|
||||
For progressive JPEG decoding, the coefficient controller supplies the prior
|
||||
coefficients of each MCU (initially all zeroes), which the entropy decoder
|
||||
modifies in each scan.
|
||||
|
||||
* Dequantization and inverse DCT: like it says. Note that the coefficients
|
||||
buffered by the coefficient controller have NOT been dequantized; we
|
||||
merge dequantization and inverse DCT into a single step for speed reasons.
|
||||
When scaled-down output is asked for, simplified DCT algorithms may be used
|
||||
that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8.
|
||||
Works on one DCT block at a time.
|
||||
|
||||
* Postprocessing controller: buffer controller for the color quantization
|
||||
input buffer, when quantization is in use. (Without quantization, this
|
||||
controller just calls the upsampler.) For two-pass quantization, this
|
||||
controller is responsible for buffering the full-image data.
|
||||
|
||||
* Upsampling: restores chroma components to full size. (May support more
|
||||
general output rescaling, too. Note that if undersized DCT outputs have
|
||||
been emitted by the DCT module, this module must adjust so that properly
|
||||
sized outputs are created.) Works on one row group at a time. This module
|
||||
also calls the color conversion module, so its top level is effectively a
|
||||
buffer controller for the upsampling->color conversion buffer. However, in
|
||||
all but the highest-quality operating modes, upsampling and color
|
||||
conversion are likely to be merged into a single step.
|
||||
|
||||
* Colorspace conversion: convert from JPEG color space to output color space,
|
||||
and change data layout from separate component planes to pixel-interleaved.
|
||||
Works on one pixel row at a time.
|
||||
|
||||
* Color quantization: reduce the data to colormapped form, using either an
|
||||
externally specified colormap or an internally generated one. This module
|
||||
is not used for full-color output. Works on one pixel row at a time; may
|
||||
require two passes to generate a color map. Note that the output will
|
||||
always be a single component representing colormap indexes. In the current
|
||||
design, the output values are JSAMPLEs, so an 8-bit compilation cannot
|
||||
quantize to more than 256 colors. This is unlikely to be a problem in
|
||||
practice.
|
||||
|
||||
* Color reduction: this module handles color precision reduction, e.g.,
|
||||
generating 15-bit color (5 bits/primary) from JPEG's 24-bit output.
|
||||
Not quite clear yet how this should be handled... should we merge it with
|
||||
colorspace conversion???
|
||||
|
||||
Note that some high-speed operating modes might condense the entire
|
||||
postprocessing sequence to a single module (upsample, color convert, and
|
||||
quantize in one step).
|
||||
|
||||
In addition to the above objects, the decompression library includes these
|
||||
objects:
|
||||
|
||||
* Master control: determines the number of passes required, controls overall
|
||||
and per-pass initialization of the other modules. This is subdivided into
|
||||
input and output control: jdinput.c controls only input-side processing,
|
||||
while jdmaster.c handles overall initialization and output-side control.
|
||||
|
||||
* Marker reading: decodes JPEG markers (except for RSTn).
|
||||
|
||||
* Data source manager: supplies the input JPEG datastream. The source
|
||||
manager supplied with the library knows how to read from a stdio stream;
|
||||
for other behaviors, the surrounding application may provide its own source
|
||||
manager.
|
||||
|
||||
* Memory manager: same as for compression library.
|
||||
|
||||
* Error handler: same as for compression library.
|
||||
|
||||
* Progress monitor: same as for compression library.
|
||||
|
||||
As with compression, the data source manager, error handler, and progress
|
||||
monitor are candidates for replacement by a surrounding application.
|
||||
|
||||
|
||||
*** Decompression input and output separation ***
|
||||
|
||||
To support efficient incremental display of progressive JPEG files, the
|
||||
decompressor is divided into two sections that can run independently:
|
||||
|
||||
1. Data input includes marker parsing, entropy decoding, and input into the
|
||||
coefficient controller's DCT coefficient buffer. Note that this
|
||||
processing is relatively cheap and fast.
|
||||
|
||||
2. Data output reads from the DCT coefficient buffer and performs the IDCT
|
||||
and all postprocessing steps.
|
||||
|
||||
For a progressive JPEG file, the data input processing is allowed to get
|
||||
arbitrarily far ahead of the data output processing. (This occurs only
|
||||
if the application calls jpeg_consume_input(); otherwise input and output
|
||||
run in lockstep, since the input section is called only when the output
|
||||
section needs more data.) In this way the application can avoid making
|
||||
extra display passes when data is arriving faster than the display pass
|
||||
can run. Furthermore, it is possible to abort an output pass without
|
||||
losing anything, since the coefficient buffer is read-only as far as the
|
||||
output section is concerned. See libjpeg.doc for more detail.
|
||||
|
||||
A full-image coefficient array is only created if the JPEG file has multiple
|
||||
scans (or if the application specifies buffered-image mode anyway). When
|
||||
reading a single-scan file, the coefficient controller normally creates only
|
||||
a one-MCU buffer, so input and output processing must run in lockstep in this
|
||||
case. jpeg_consume_input() is effectively a no-op in this situation.
|
||||
|
||||
The main impact of dividing the decompressor in this fashion is that we must
|
||||
be very careful with shared variables in the cinfo data structure. Each
|
||||
variable that can change during the course of decompression must be
|
||||
classified as belonging to data input or data output, and each section must
|
||||
look only at its own variables. For example, the data output section may not
|
||||
depend on any of the variables that describe the current scan in the JPEG
|
||||
file, because these may change as the data input section advances into a new
|
||||
scan.
|
||||
|
||||
The progress monitor is (somewhat arbitrarily) defined to treat input of the
|
||||
file as one pass when buffered-image mode is not used, and to ignore data
|
||||
input work completely when buffered-image mode is used. Note that the
|
||||
library has no reliable way to predict the number of passes when dealing
|
||||
with a progressive JPEG file, nor can it predict the number of output passes
|
||||
in buffered-image mode. So the work estimate is inherently bogus anyway.
|
||||
|
||||
No comparable division is currently made in the compression library, because
|
||||
there isn't any real need for it.
|
||||
|
||||
|
||||
*** Data formats ***
|
||||
|
||||
Arrays of pixel sample values use the following data structure:
|
||||
|
||||
typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE
|
||||
typedef JSAMPLE *JSAMPROW; ptr to a row of samples
|
||||
typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows
|
||||
typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays
|
||||
|
||||
The basic element type JSAMPLE will typically be one of unsigned char,
|
||||
(signed) char, or short. Short will be used if samples wider than 8 bits are
|
||||
to be supported (this is a compile-time option). Otherwise, unsigned char is
|
||||
used if possible. If the compiler only supports signed chars, then it is
|
||||
necessary to mask off the value when reading. Thus, all reads of JSAMPLE
|
||||
values must be coded as "GETJSAMPLE(value)", where the macro will be defined
|
||||
as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere.
|
||||
|
||||
With these conventions, JSAMPLE values can be assumed to be >= 0. This helps
|
||||
simplify correct rounding during downsampling, etc. The JPEG standard's
|
||||
specification that sample values run from -128..127 is accommodated by
|
||||
subtracting 128 just as the sample value is copied into the source array for
|
||||
the DCT step (this will be an array of signed ints). Similarly, during
|
||||
decompression the output of the IDCT step will be immediately shifted back to
|
||||
0..255. (NB: different values are required when 12-bit samples are in use.
|
||||
The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be
|
||||
defined as 255 and 128 respectively in an 8-bit implementation, and as 4095
|
||||
and 2048 in a 12-bit implementation.)
|
||||
|
||||
We use a pointer per row, rather than a two-dimensional JSAMPLE array. This
|
||||
choice costs only a small amount of memory and has several benefits:
|
||||
* Code using the data structure doesn't need to know the allocated width of
|
||||
the rows. This simplifies edge expansion/compression, since we can work
|
||||
in an array that's wider than the logical picture width.
|
||||
* Indexing doesn't require multiplication; this is a performance win on many
|
||||
machines.
|
||||
* Arrays with more than 64K total elements can be supported even on machines
|
||||
where malloc() cannot allocate chunks larger than 64K.
|
||||
* The rows forming a component array may be allocated at different times
|
||||
without extra copying. This trick allows some speedups in smoothing steps
|
||||
that need access to the previous and next rows.
|
||||
|
||||
Note that each color component is stored in a separate array; we don't use the
|
||||
traditional layout in which the components of a pixel are stored together.
|
||||
This simplifies coding of modules that work on each component independently,
|
||||
because they don't need to know how many components there are. Furthermore,
|
||||
we can read or write each component to a temporary file independently, which
|
||||
is helpful when dealing with noninterleaved JPEG files.
|
||||
|
||||
In general, a specific sample value is accessed by code such as
|
||||
GETJSAMPLE(image[colorcomponent][row][col])
|
||||
where col is measured from the image left edge, but row is measured from the
|
||||
first sample row currently in memory. Either of the first two indexings can
|
||||
be precomputed by copying the relevant pointer.
|
||||
|
||||
|
||||
Since most image-processing applications prefer to work on images in which
|
||||
the components of a pixel are stored together, the data passed to or from the
|
||||
surrounding application uses the traditional convention: a single pixel is
|
||||
represented by N consecutive JSAMPLE values, and an image row is an array of
|
||||
(# of color components)*(image width) JSAMPLEs. One or more rows of data can
|
||||
be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is
|
||||
converted to component-wise storage inside the JPEG library. (Applications
|
||||
that want to skip JPEG preprocessing or postprocessing will have to contend
|
||||
with component-wise storage.)
|
||||
|
||||
|
||||
Arrays of DCT-coefficient values use the following data structure:
|
||||
|
||||
typedef short JCOEF; a 16-bit signed integer
|
||||
typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients
|
||||
typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks
|
||||
typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows
|
||||
typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays
|
||||
|
||||
The underlying type is at least a 16-bit signed integer; while "short" is big
|
||||
enough on all machines of interest, on some machines it is preferable to use
|
||||
"int" for speed reasons, despite the storage cost. Coefficients are grouped
|
||||
into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than
|
||||
"8" and "64").
|
||||
|
||||
The contents of a coefficient block may be in either "natural" or zigzagged
|
||||
order, and may be true values or divided by the quantization coefficients,
|
||||
depending on where the block is in the processing pipeline. In the current
|
||||
library, coefficient blocks are kept in natural order everywhere; the entropy
|
||||
codecs zigzag or dezigzag the data as it is written or read. The blocks
|
||||
contain quantized coefficients everywhere outside the DCT/IDCT subsystems.
|
||||
(This latter decision may need to be revisited to support variable
|
||||
quantization a la JPEG Part 3.)
|
||||
|
||||
Notice that the allocation unit is now a row of 8x8 blocks, corresponding to
|
||||
eight rows of samples. Otherwise the structure is much the same as for
|
||||
samples, and for the same reasons.
|
||||
|
||||
On machines where malloc() can't handle a request bigger than 64Kb, this data
|
||||
structure limits us to rows of less than 512 JBLOCKs, or a picture width of
|
||||
4000+ pixels. This seems an acceptable restriction.
|
||||
|
||||
|
||||
On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW)
|
||||
must be declared as "far" pointers, but the upper levels can be "near"
|
||||
(implying that the pointer lists are allocated in the DS segment).
|
||||
We use a #define symbol FAR, which expands to the "far" keyword when
|
||||
compiling on 80x86 machines and to nothing elsewhere.
|
||||
|
||||
|
||||
*** Suspendable processing ***
|
||||
|
||||
In some applications it is desirable to use the JPEG library as an
|
||||
incremental, memory-to-memory filter. In this situation the data source or
|
||||
destination may be a limited-size buffer, and we can't rely on being able to
|
||||
empty or refill the buffer at arbitrary times. Instead the application would
|
||||
like to have control return from the library at buffer overflow/underrun, and
|
||||
then resume compression or decompression at a later time.
|
||||
|
||||
This scenario is supported for simple cases. (For anything more complex, we
|
||||
recommend that the application "bite the bullet" and develop real multitasking
|
||||
capability.) The libjpeg.doc file goes into more detail about the usage and
|
||||
limitations of this capability; here we address the implications for library
|
||||
structure.
|
||||
|
||||
The essence of the problem is that the entropy codec (coder or decoder) must
|
||||
be prepared to stop at arbitrary times. In turn, the controllers that call
|
||||
the entropy codec must be able to stop before having produced or consumed all
|
||||
the data that they normally would handle in one call. That part is reasonably
|
||||
straightforward: we make the controller call interfaces include "progress
|
||||
counters" which indicate the number of data chunks successfully processed, and
|
||||
we require callers to test the counter rather than just assume all of the data
|
||||
was processed.
|
||||
|
||||
Rather than trying to restart at an arbitrary point, the current Huffman
|
||||
codecs are designed to restart at the beginning of the current MCU after a
|
||||
suspension due to buffer overflow/underrun. At the start of each call, the
|
||||
codec's internal state is loaded from permanent storage (in the JPEG object
|
||||
structures) into local variables. On successful completion of the MCU, the
|
||||
permanent state is updated. (This copying is not very expensive, and may even
|
||||
lead to *improved* performance if the local variables can be registerized.)
|
||||
If a suspension occurs, the codec simply returns without updating the state,
|
||||
thus effectively reverting to the start of the MCU. Note that this implies
|
||||
leaving some data unprocessed in the source/destination buffer (ie, the
|
||||
compressed partial MCU). The data source/destination module interfaces are
|
||||
specified so as to make this possible. This also implies that the data buffer
|
||||
must be large enough to hold a worst-case compressed MCU; a couple thousand
|
||||
bytes should be enough.
|
||||
|
||||
In a successive-approximation AC refinement scan, the progressive Huffman
|
||||
decoder has to be able to undo assignments of newly nonzero coefficients if it
|
||||
suspends before the MCU is complete, since decoding requires distinguishing
|
||||
previously-zero and previously-nonzero coefficients. This is a bit tedious
|
||||
but probably won't have much effect on performance. Other variants of Huffman
|
||||
decoding need not worry about this, since they will just store the same values
|
||||
again if forced to repeat the MCU.
|
||||
|
||||
This approach would probably not work for an arithmetic codec, since its
|
||||
modifiable state is quite large and couldn't be copied cheaply. Instead it
|
||||
would have to suspend and resume exactly at the point of the buffer end.
|
||||
|
||||
The JPEG marker reader is designed to cope with suspension at an arbitrary
|
||||
point. It does so by backing up to the start of the marker parameter segment,
|
||||
so the data buffer must be big enough to hold the largest marker of interest.
|
||||
Again, a couple KB should be adequate. (A special "skip" convention is used
|
||||
to bypass COM and APPn markers, so these can be larger than the buffer size
|
||||
without causing problems; otherwise a 64K buffer would be needed in the worst
|
||||
case.)
|
||||
|
||||
The JPEG marker writer currently does *not* cope with suspension. I feel that
|
||||
this is not necessary; it is much easier simply to require the application to
|
||||
ensure there is enough buffer space before starting. (An empty 2K buffer is
|
||||
more than sufficient for the header markers; and ensuring there are a dozen or
|
||||
two bytes available before calling jpeg_finish_compress() will suffice for the
|
||||
trailer.) This would not work for writing multi-scan JPEG files, but
|
||||
we simply do not intend to support that capability with suspension.
|
||||
|
||||
|
||||
*** Memory manager services ***
|
||||
|
||||
The JPEG library's memory manager controls allocation and deallocation of
|
||||
memory, and it manages large "virtual" data arrays on machines where the
|
||||
operating system does not provide virtual memory. Note that the same
|
||||
memory manager serves both compression and decompression operations.
|
||||
|
||||
In all cases, allocated objects are tied to a particular compression or
|
||||
decompression master record, and they will be released when that master
|
||||
record is destroyed.
|
||||
|
||||
The memory manager does not provide explicit deallocation of objects.
|
||||
Instead, objects are created in "pools" of free storage, and a whole pool
|
||||
can be freed at once. This approach helps prevent storage-leak bugs, and
|
||||
it speeds up operations whenever malloc/free are slow (as they often are).
|
||||
The pools can be regarded as lifetime identifiers for objects. Two
|
||||
pools/lifetimes are defined:
|
||||
* JPOOL_PERMANENT lasts until master record is destroyed
|
||||
* JPOOL_IMAGE lasts until done with image (JPEG datastream)
|
||||
Permanent lifetime is used for parameters and tables that should be carried
|
||||
across from one datastream to another; this includes all application-visible
|
||||
parameters. Image lifetime is used for everything else. (A third lifetime,
|
||||
JPOOL_PASS = one processing pass, was originally planned. However it was
|
||||
dropped as not being worthwhile. The actual usage patterns are such that the
|
||||
peak memory usage would be about the same anyway; and having per-pass storage
|
||||
substantially complicates the virtual memory allocation rules --- see below.)
|
||||
|
||||
The memory manager deals with three kinds of object:
|
||||
1. "Small" objects. Typically these require no more than 10K-20K total.
|
||||
2. "Large" objects. These may require tens to hundreds of K depending on
|
||||
image size. Semantically they behave the same as small objects, but we
|
||||
distinguish them for two reasons:
|
||||
* On MS-DOS machines, large objects are referenced by FAR pointers,
|
||||
small objects by NEAR pointers.
|
||||
* Pool allocation heuristics may differ for large and small objects.
|
||||
Note that individual "large" objects cannot exceed the size allowed by
|
||||
type size_t, which may be 64K or less on some machines.
|
||||
3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs
|
||||
(typically large enough for the entire image being processed). The
|
||||
memory manager provides stripwise access to these arrays. On machines
|
||||
without virtual memory, the rest of the array may be swapped out to a
|
||||
temporary file.
|
||||
|
||||
(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large
|
||||
objects for the data proper and small objects for the row pointers. For
|
||||
convenience and speed, the memory manager provides single routines to create
|
||||
these structures. Similarly, virtual arrays include a small control block
|
||||
and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.)
|
||||
|
||||
In the present implementation, virtual arrays are only permitted to have image
|
||||
lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is
|
||||
not very useful since a virtual array's raison d'etre is to store data for
|
||||
multiple passes through the image.) We also expect that only "small" objects
|
||||
will be given permanent lifespan, though this restriction is not required by
|
||||
the memory manager.
|
||||
|
||||
In a non-virtual-memory machine, some performance benefit can be gained by
|
||||
making the in-memory buffers for virtual arrays be as large as possible.
|
||||
(For small images, the buffers might fit entirely in memory, so blind
|
||||
swapping would be very wasteful.) The memory manager will adjust the height
|
||||
of the buffers to fit within a prespecified maximum memory usage. In order
|
||||
to do this in a reasonably optimal fashion, the manager needs to allocate all
|
||||
of the virtual arrays at once. Therefore, there isn't a one-step allocation
|
||||
routine for virtual arrays; instead, there is a "request" routine that simply
|
||||
allocates the control block, and a "realize" routine (called just once) that
|
||||
determines space allocation and creates all of the actual buffers. The
|
||||
realize routine must allow for space occupied by non-virtual large objects.
|
||||
(We don't bother to factor in the space needed for small objects, on the
|
||||
grounds that it isn't worth the trouble.)
|
||||
|
||||
To support all this, we establish the following protocol for doing business
|
||||
with the memory manager:
|
||||
1. Modules must request virtual arrays (which may have only image lifespan)
|
||||
during the initial setup phase, i.e., in their jinit_xxx routines.
|
||||
2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be
|
||||
allocated during initial setup.
|
||||
3. realize_virt_arrays will be called at the completion of initial setup.
|
||||
The above conventions ensure that sufficient information is available
|
||||
for it to choose a good size for virtual array buffers.
|
||||
Small objects of any lifespan may be allocated at any time. We expect that
|
||||
the total space used for small objects will be small enough to be negligible
|
||||
in the realize_virt_arrays computation.
|
||||
|
||||
In a virtual-memory machine, we simply pretend that the available space is
|
||||
infinite, thus causing realize_virt_arrays to decide that it can allocate all
|
||||
the virtual arrays as full-size in-memory buffers. The overhead of the
|
||||
virtual-array access protocol is very small when no swapping occurs.
|
||||
|
||||
A virtual array can be specified to be "pre-zeroed"; when this flag is set,
|
||||
never-yet-written sections of the array are set to zero before being made
|
||||
available to the caller. If this flag is not set, never-written sections
|
||||
of the array contain garbage. (This feature exists primarily because the
|
||||
equivalent logic would otherwise be needed in jdcoefct.c for progressive
|
||||
JPEG mode; we may as well make it available for possible other uses.)
|
||||
|
||||
The first write pass on a virtual array is required to occur in top-to-bottom
|
||||
order; read passes, as well as any write passes after the first one, may
|
||||
access the array in any order. This restriction exists partly to simplify
|
||||
the virtual array control logic, and partly because some file systems may not
|
||||
support seeking beyond the current end-of-file in a temporary file. The main
|
||||
implication of this restriction is that rearrangement of rows (such as
|
||||
converting top-to-bottom data order to bottom-to-top) must be handled while
|
||||
reading data out of the virtual array, not while putting it in.
|
||||
|
||||
|
||||
*** Memory manager internal structure ***
|
||||
|
||||
To isolate system dependencies as much as possible, we have broken the
|
||||
memory manager into two parts. There is a reasonably system-independent
|
||||
"front end" (jmemmgr.c) and a "back end" that contains only the code
|
||||
likely to change across systems. All of the memory management methods
|
||||
outlined above are implemented by the front end. The back end provides
|
||||
the following routines for use by the front end (none of these routines
|
||||
are known to the rest of the JPEG code):
|
||||
|
||||
jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown
|
||||
|
||||
jpeg_get_small, jpeg_free_small interface to malloc and free library routines
|
||||
(or their equivalents)
|
||||
|
||||
jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines;
|
||||
else usually the same as
|
||||
jpeg_get_small/jpeg_free_small
|
||||
|
||||
jpeg_mem_available estimate available memory
|
||||
|
||||
jpeg_open_backing_store create a backing-store object
|
||||
|
||||
read_backing_store, manipulate a backing-store object
|
||||
write_backing_store,
|
||||
close_backing_store
|
||||
|
||||
On some systems there will be more than one type of backing-store object
|
||||
(specifically, in MS-DOS a backing store file might be an area of extended
|
||||
memory as well as a disk file). jpeg_open_backing_store is responsible for
|
||||
choosing how to implement a given object. The read/write/close routines
|
||||
are method pointers in the structure that describes a given object; this
|
||||
lets them be different for different object types.
|
||||
|
||||
It may be necessary to ensure that backing store objects are explicitly
|
||||
released upon abnormal program termination. For example, MS-DOS won't free
|
||||
extended memory by itself. To support this, we will expect the main program
|
||||
or surrounding application to arrange to call self_destruct (typically via
|
||||
jpeg_destroy) upon abnormal termination. This may require a SIGINT signal
|
||||
handler or equivalent. We don't want to have the back end module install its
|
||||
own signal handler, because that would pre-empt the surrounding application's
|
||||
ability to control signal handling.
|
||||
|
||||
The IJG distribution includes several memory manager back end implementations.
|
||||
Usually the same back end should be suitable for all applications on a given
|
||||
system, but it is possible for an application to supply its own back end at
|
||||
need.
|
||||
|
||||
|
||||
*** Implications of DNL marker ***
|
||||
|
||||
Some JPEG files may use a DNL marker to postpone definition of the image
|
||||
height (this would be useful for a fax-like scanner's output, for instance).
|
||||
In these files the SOF marker claims the image height is 0, and you only
|
||||
find out the true image height at the end of the first scan.
|
||||
|
||||
We could read these files as follows:
|
||||
1. Upon seeing zero image height, replace it by 65535 (the maximum allowed).
|
||||
2. When the DNL is found, update the image height in the global image
|
||||
descriptor.
|
||||
This implies that control modules must avoid making copies of the image
|
||||
height, and must re-test for termination after each MCU row. This would
|
||||
be easy enough to do.
|
||||
|
||||
In cases where image-size data structures are allocated, this approach will
|
||||
result in very inefficient use of virtual memory or much-larger-than-necessary
|
||||
temporary files. This seems acceptable for something that probably won't be a
|
||||
mainstream usage. People might have to forgo use of memory-hogging options
|
||||
(such as two-pass color quantization or noninterleaved JPEG files) if they
|
||||
want efficient conversion of such files. (One could improve efficiency by
|
||||
demanding a user-supplied upper bound for the height, less than 65536; in most
|
||||
cases it could be much less.)
|
||||
|
||||
The standard also permits the SOF marker to overestimate the image height,
|
||||
with a DNL to give the true, smaller height at the end of the first scan.
|
||||
This would solve the space problems if the overestimate wasn't too great.
|
||||
However, it implies that you don't even know whether DNL will be used.
|
||||
|
||||
This leads to a couple of very serious objections:
|
||||
1. Testing for a DNL marker must occur in the inner loop of the decompressor's
|
||||
Huffman decoder; this implies a speed penalty whether the feature is used
|
||||
or not.
|
||||
2. There is no way to hide the last-minute change in image height from an
|
||||
application using the decoder. Thus *every* application using the IJG
|
||||
library would suffer a complexity penalty whether it cared about DNL or
|
||||
not.
|
||||
We currently do not support DNL because of these problems.
|
||||
|
||||
A different approach is to insist that DNL-using files be preprocessed by a
|
||||
separate program that reads ahead to the DNL, then goes back and fixes the SOF
|
||||
marker. This is a much simpler solution and is probably far more efficient.
|
||||
Even if one wants piped input, buffering the first scan of the JPEG file needs
|
||||
a lot smaller temp file than is implied by the maximum-height method. For
|
||||
this approach we'd simply treat DNL as a no-op in the decompressor (at most,
|
||||
check that it matches the SOF image height).
|
||||
|
||||
We will not worry about making the compressor capable of outputting DNL.
|
||||
Something similar to the first scheme above could be applied if anyone ever
|
||||
wants to make that work.
|
||||
BIN
testimg.bmp
Normal file
BIN
testimg.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
testimg.jpg
Normal file
BIN
testimg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
4
testimg.ppm
Normal file
4
testimg.ppm
Normal file
File diff suppressed because one or more lines are too long
BIN
testimgp.jpg
Normal file
BIN
testimgp.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
BIN
testorig.jpg
Normal file
BIN
testorig.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
BIN
testprog.jpg
Normal file
BIN
testprog.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
928
transupp.c
Normal file
928
transupp.c
Normal file
@@ -0,0 +1,928 @@
|
||||
/*
|
||||
* transupp.c
|
||||
*
|
||||
* Copyright (C) 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 image transformation routines and other utility code
|
||||
* used by the jpegtran sample application. These are NOT part of the core
|
||||
* JPEG library. But we keep these routines separate from jpegtran.c to
|
||||
* ease the task of maintaining jpegtran-like programs that have other user
|
||||
* interfaces.
|
||||
*/
|
||||
|
||||
/* Although this file really shouldn't have access to the library internals,
|
||||
* it's helpful to let it call jround_up() and jcopy_block_row().
|
||||
*/
|
||||
#define JPEG_INTERNALS
|
||||
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "transupp.h" /* My own external interface */
|
||||
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Lossless image transformation routines. These routines work on DCT
|
||||
* coefficient arrays and thus do not require any lossy decompression
|
||||
* or recompression of the image.
|
||||
* Thanks to Guido Vollbeding for the initial design and code of this feature.
|
||||
*
|
||||
* Horizontal flipping is done in-place, using a single top-to-bottom
|
||||
* pass through the virtual source array. It will thus be much the
|
||||
* fastest option for images larger than main memory.
|
||||
*
|
||||
* The other routines require a set of destination virtual arrays, so they
|
||||
* need twice as much memory as jpegtran normally does. The destination
|
||||
* arrays are always written in normal scan order (top to bottom) because
|
||||
* the virtual array manager expects this. The source arrays will be scanned
|
||||
* in the corresponding order, which means multiple passes through the source
|
||||
* arrays for most of the transforms. That could result in much thrashing
|
||||
* if the image is larger than main memory.
|
||||
*
|
||||
* Some notes about the operating environment of the individual transform
|
||||
* routines:
|
||||
* 1. Both the source and destination virtual arrays are allocated from the
|
||||
* source JPEG object, and therefore should be manipulated by calling the
|
||||
* source's memory manager.
|
||||
* 2. The destination's component count should be used. It may be smaller
|
||||
* than the source's when forcing to grayscale.
|
||||
* 3. Likewise the destination's sampling factors should be used. When
|
||||
* forcing to grayscale the destination's sampling factors will be all 1,
|
||||
* and we may as well take that as the effective iMCU size.
|
||||
* 4. When "trim" is in effect, the destination's dimensions will be the
|
||||
* trimmed values but the source's will be untrimmed.
|
||||
* 5. All the routines assume that the source and destination buffers are
|
||||
* padded out to a full iMCU boundary. This is true, although for the
|
||||
* source buffer it is an undocumented property of jdcoefct.c.
|
||||
* Notes 2,3,4 boil down to this: generally we should use the destination's
|
||||
* dimensions and ignore the source's.
|
||||
*/
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays)
|
||||
/* Horizontal flip; done in-place, so no separate dest array is required */
|
||||
{
|
||||
JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
|
||||
int ci, k, offset_y;
|
||||
JBLOCKARRAY buffer;
|
||||
JCOEFPTR ptr1, ptr2;
|
||||
JCOEF temp1, temp2;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Horizontal mirroring of DCT blocks is accomplished by swapping
|
||||
* pairs of blocks in-place. Within a DCT block, we perform horizontal
|
||||
* mirroring by changing the signs of odd-numbered columns.
|
||||
* Partial iMCUs at the right edge are left untouched.
|
||||
*/
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
for (blk_y = 0; blk_y < compptr->height_in_blocks;
|
||||
blk_y += compptr->v_samp_factor) {
|
||||
buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
|
||||
ptr1 = buffer[offset_y][blk_x];
|
||||
ptr2 = buffer[offset_y][comp_width - blk_x - 1];
|
||||
/* this unrolled loop doesn't need to know which row it's on... */
|
||||
for (k = 0; k < DCTSIZE2; k += 2) {
|
||||
temp1 = *ptr1; /* swap even column */
|
||||
temp2 = *ptr2;
|
||||
*ptr1++ = temp2;
|
||||
*ptr2++ = temp1;
|
||||
temp1 = *ptr1; /* swap odd column with sign change */
|
||||
temp2 = *ptr2;
|
||||
*ptr1++ = -temp2;
|
||||
*ptr2++ = -temp1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Vertical flip */
|
||||
{
|
||||
JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JBLOCKROW src_row_ptr, dst_row_ptr;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* We output into a separate array because we can't touch different
|
||||
* rows of the source virtual array simultaneously. Otherwise, this
|
||||
* is a pretty straightforward analog of horizontal flip.
|
||||
* Within a DCT block, vertical mirroring is done by changing the signs
|
||||
* of odd-numbered rows.
|
||||
* Partial iMCUs at the bottom edge are copied verbatim.
|
||||
*/
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
||||
comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
} else {
|
||||
/* Bottom-edge blocks will be copied verbatim. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
/* copy even row */
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
/* copy odd row with sign change */
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Just copy row verbatim. */
|
||||
jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
|
||||
compptr->width_in_blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Transpose source into destination */
|
||||
{
|
||||
JDIMENSION dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Transposing pixels within a block just requires transposing the
|
||||
* DCT coefficients.
|
||||
* Partial iMCUs at the edges require no special treatment; we simply
|
||||
* process all the available DCT blocks for every component.
|
||||
*/
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 90 degree rotation is equivalent to
|
||||
* 1. Transposing the image;
|
||||
* 2. Horizontal mirroring.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Because of the horizontal mirror step, we can't process partial iMCUs
|
||||
* at the (output) right edge properly. They just get transposed and
|
||||
* not mirrored.
|
||||
*/
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Block is within the mirrorable area. */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
} else {
|
||||
/* Edge blocks are transposed but not mirrored. */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 270 degree rotation is equivalent to
|
||||
* 1. Horizontal mirroring;
|
||||
* 2. Transposing the image.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Because of the horizontal mirror step, we can't process partial iMCUs
|
||||
* at the (output) bottom edge properly. They just get transposed and
|
||||
* not mirrored.
|
||||
*/
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Block is within the mirrorable area. */
|
||||
src_ptr = src_buffer[offset_x]
|
||||
[comp_height - dst_blk_y - offset_y - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Edge blocks are transposed but not mirrored. */
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 180 degree rotation is equivalent to
|
||||
* 1. Vertical mirroring;
|
||||
* 2. Horizontal mirroring.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JBLOCKROW src_row_ptr, dst_row_ptr;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the vertically mirrorable area. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
||||
comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
} else {
|
||||
/* Bottom-edge rows are only mirrored horizontally. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
|
||||
/* Process the blocks that can be mirrored both ways. */
|
||||
for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
/* For even row, negate every odd column. */
|
||||
for (j = 0; j < DCTSIZE; j += 2) {
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
/* For odd row, negate every even column. */
|
||||
for (j = 0; j < DCTSIZE; j += 2) {
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only mirrored vertically. */
|
||||
for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Remaining rows are just mirrored horizontally. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[offset_y];
|
||||
/* Process the blocks that can be mirrored. */
|
||||
for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
|
||||
for (i = 0; i < DCTSIZE2; i += 2) {
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only copied. */
|
||||
for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE2; i++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Transverse transpose is equivalent to
|
||||
* 1. 180 degree rotation;
|
||||
* 2. Transposition;
|
||||
* or
|
||||
* 1. Horizontal mirroring;
|
||||
* 2. Transposition;
|
||||
* 3. Horizontal mirroring.
|
||||
* These steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
src_ptr = src_buffer[offset_x]
|
||||
[comp_height - dst_blk_y - offset_y - 1];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Block is within the mirrorable area. */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Right-edge blocks are mirrored in y only */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Bottom-edge blocks are mirrored in x only */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
} else {
|
||||
/* At lower right corner, just transpose, no mirroring */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Request any required workspace.
|
||||
*
|
||||
* We allocate the workspace virtual arrays from the source decompression
|
||||
* object, so that all the arrays (both the original data and the workspace)
|
||||
* will be taken into account while making memory management decisions.
|
||||
* Hence, this routine must be called after jpeg_read_header (which reads
|
||||
* the image dimensions) and before jpeg_read_coefficients (which realizes
|
||||
* the source's virtual arrays).
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jtransform_request_workspace (j_decompress_ptr srcinfo,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
jvirt_barray_ptr *coef_arrays = NULL;
|
||||
jpeg_component_info *compptr;
|
||||
int ci;
|
||||
|
||||
if (info->force_grayscale &&
|
||||
srcinfo->jpeg_color_space == JCS_YCbCr &&
|
||||
srcinfo->num_components == 3) {
|
||||
/* We'll only process the first component */
|
||||
info->num_components = 1;
|
||||
} else {
|
||||
/* Process all the components */
|
||||
info->num_components = srcinfo->num_components;
|
||||
}
|
||||
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
case JXFORM_FLIP_H:
|
||||
/* Don't need a workspace array */
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
case JXFORM_ROT_180:
|
||||
/* Need workspace arrays having same dimensions as source image.
|
||||
* Note that we allocate arrays padded out to the next iMCU boundary,
|
||||
* so that transform routines need not worry about missing edge blocks.
|
||||
*/
|
||||
coef_arrays = (jvirt_barray_ptr *)
|
||||
(*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
|
||||
SIZEOF(jvirt_barray_ptr) * info->num_components);
|
||||
for (ci = 0; ci < info->num_components; ci++) {
|
||||
compptr = srcinfo->comp_info + ci;
|
||||
coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
case JXFORM_TRANSVERSE:
|
||||
case JXFORM_ROT_90:
|
||||
case JXFORM_ROT_270:
|
||||
/* Need workspace arrays having transposed dimensions.
|
||||
* Note that we allocate arrays padded out to the next iMCU boundary,
|
||||
* so that transform routines need not worry about missing edge blocks.
|
||||
*/
|
||||
coef_arrays = (jvirt_barray_ptr *)
|
||||
(*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
|
||||
SIZEOF(jvirt_barray_ptr) * info->num_components);
|
||||
for (ci = 0; ci < info->num_components; ci++) {
|
||||
compptr = srcinfo->comp_info + ci;
|
||||
coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->h_samp_factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
info->workspace_coef_arrays = coef_arrays;
|
||||
}
|
||||
|
||||
|
||||
/* Transpose destination image parameters */
|
||||
|
||||
LOCAL(void)
|
||||
transpose_critical_parameters (j_compress_ptr dstinfo)
|
||||
{
|
||||
int tblno, i, j, ci, itemp;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL *qtblptr;
|
||||
JDIMENSION dtemp;
|
||||
UINT16 qtemp;
|
||||
|
||||
/* Transpose basic image dimensions */
|
||||
dtemp = dstinfo->image_width;
|
||||
dstinfo->image_width = dstinfo->image_height;
|
||||
dstinfo->image_height = dtemp;
|
||||
|
||||
/* Transpose sampling factors */
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
itemp = compptr->h_samp_factor;
|
||||
compptr->h_samp_factor = compptr->v_samp_factor;
|
||||
compptr->v_samp_factor = itemp;
|
||||
}
|
||||
|
||||
/* Transpose quantization tables */
|
||||
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
|
||||
qtblptr = dstinfo->quant_tbl_ptrs[tblno];
|
||||
if (qtblptr != NULL) {
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
qtemp = qtblptr->quantval[i*DCTSIZE+j];
|
||||
qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
|
||||
qtblptr->quantval[j*DCTSIZE+i] = qtemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Trim off any partial iMCUs on the indicated destination edge */
|
||||
|
||||
LOCAL(void)
|
||||
trim_right_edge (j_compress_ptr dstinfo)
|
||||
{
|
||||
int ci, max_h_samp_factor;
|
||||
JDIMENSION MCU_cols;
|
||||
|
||||
/* We have to compute max_h_samp_factor ourselves,
|
||||
* because it hasn't been set yet in the destination
|
||||
* (and we don't want to use the source's value).
|
||||
*/
|
||||
max_h_samp_factor = 1;
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
|
||||
max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
|
||||
}
|
||||
MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
|
||||
if (MCU_cols > 0) /* can't trim to 0 pixels */
|
||||
dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
|
||||
}
|
||||
|
||||
LOCAL(void)
|
||||
trim_bottom_edge (j_compress_ptr dstinfo)
|
||||
{
|
||||
int ci, max_v_samp_factor;
|
||||
JDIMENSION MCU_rows;
|
||||
|
||||
/* We have to compute max_v_samp_factor ourselves,
|
||||
* because it hasn't been set yet in the destination
|
||||
* (and we don't want to use the source's value).
|
||||
*/
|
||||
max_v_samp_factor = 1;
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
|
||||
max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
|
||||
}
|
||||
MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
|
||||
if (MCU_rows > 0) /* can't trim to 0 pixels */
|
||||
dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
|
||||
}
|
||||
|
||||
|
||||
/* Adjust output image parameters as needed.
|
||||
*
|
||||
* This must be called after jpeg_copy_critical_parameters()
|
||||
* and before jpeg_write_coefficients().
|
||||
*
|
||||
* The return value is the set of virtual coefficient arrays to be written
|
||||
* (either the ones allocated by jtransform_request_workspace, or the
|
||||
* original source data arrays). The caller will need to pass this value
|
||||
* to jpeg_write_coefficients().
|
||||
*/
|
||||
|
||||
GLOBAL(jvirt_barray_ptr *)
|
||||
jtransform_adjust_parameters (j_decompress_ptr srcinfo,
|
||||
j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
/* If force-to-grayscale is requested, adjust destination parameters */
|
||||
if (info->force_grayscale) {
|
||||
/* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
|
||||
* properly. Among other things, the target h_samp_factor & v_samp_factor
|
||||
* will get set to 1, which typically won't match the source.
|
||||
* In fact we do this even if the source is already grayscale; that
|
||||
* provides an easy way of coercing a grayscale JPEG with funny sampling
|
||||
* factors to the customary 1,1. (Some decoders fail on other factors.)
|
||||
*/
|
||||
if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
|
||||
dstinfo->num_components == 3) ||
|
||||
(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
|
||||
dstinfo->num_components == 1)) {
|
||||
/* We have to preserve the source's quantization table number. */
|
||||
int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
|
||||
jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
|
||||
dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
|
||||
} else {
|
||||
/* Sorry, can't do it */
|
||||
ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Correct the destination's image dimensions etc if necessary */
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
case JXFORM_FLIP_H:
|
||||
if (info->trim)
|
||||
trim_right_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
if (info->trim)
|
||||
trim_bottom_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
/* transpose does NOT have to trim anything */
|
||||
break;
|
||||
case JXFORM_TRANSVERSE:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim) {
|
||||
trim_right_edge(dstinfo);
|
||||
trim_bottom_edge(dstinfo);
|
||||
}
|
||||
break;
|
||||
case JXFORM_ROT_90:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim)
|
||||
trim_right_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_ROT_180:
|
||||
if (info->trim) {
|
||||
trim_right_edge(dstinfo);
|
||||
trim_bottom_edge(dstinfo);
|
||||
}
|
||||
break;
|
||||
case JXFORM_ROT_270:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim)
|
||||
trim_bottom_edge(dstinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return the appropriate output data set */
|
||||
if (info->workspace_coef_arrays != NULL)
|
||||
return info->workspace_coef_arrays;
|
||||
return src_coef_arrays;
|
||||
}
|
||||
|
||||
|
||||
/* Execute the actual transformation, if any.
|
||||
*
|
||||
* This must be called *after* jpeg_write_coefficients, because it depends
|
||||
* on jpeg_write_coefficients to have computed subsidiary values such as
|
||||
* the per-component width and height fields in the destination object.
|
||||
*
|
||||
* Note that some transformations will modify the source data arrays!
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jtransform_execute_transformation (j_decompress_ptr srcinfo,
|
||||
j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
|
||||
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
break;
|
||||
case JXFORM_FLIP_H:
|
||||
do_flip_h(srcinfo, dstinfo, src_coef_arrays);
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_TRANSVERSE:
|
||||
do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_90:
|
||||
do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_180:
|
||||
do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_270:
|
||||
do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
|
||||
/* Setup decompression object to save desired markers in memory.
|
||||
* This must be called before jpeg_read_header() to have the desired effect.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
|
||||
{
|
||||
#ifdef SAVE_MARKERS_SUPPORTED
|
||||
int m;
|
||||
|
||||
/* Save comments except under NONE option */
|
||||
if (option != JCOPYOPT_NONE) {
|
||||
jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
|
||||
}
|
||||
/* Save all types of APPn markers iff ALL option */
|
||||
if (option == JCOPYOPT_ALL) {
|
||||
for (m = 0; m < 16; m++)
|
||||
jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
|
||||
}
|
||||
#endif /* SAVE_MARKERS_SUPPORTED */
|
||||
}
|
||||
|
||||
/* Copy markers saved in the given source object to the destination object.
|
||||
* This should be called just after jpeg_start_compress() or
|
||||
* jpeg_write_coefficients().
|
||||
* Note that those routines will have written the SOI, and also the
|
||||
* JFIF APP0 or Adobe APP14 markers if selected.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option)
|
||||
{
|
||||
jpeg_saved_marker_ptr marker;
|
||||
|
||||
/* In the current implementation, we don't actually need to examine the
|
||||
* option flag here; we just copy everything that got saved.
|
||||
* But to avoid confusion, we do not output JFIF and Adobe APP14 markers
|
||||
* if the encoder library already wrote one.
|
||||
*/
|
||||
for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||
if (dstinfo->write_JFIF_header &&
|
||||
marker->marker == JPEG_APP0 &&
|
||||
marker->data_length >= 5 &&
|
||||
GETJOCTET(marker->data[0]) == 0x4A &&
|
||||
GETJOCTET(marker->data[1]) == 0x46 &&
|
||||
GETJOCTET(marker->data[2]) == 0x49 &&
|
||||
GETJOCTET(marker->data[3]) == 0x46 &&
|
||||
GETJOCTET(marker->data[4]) == 0)
|
||||
continue; /* reject duplicate JFIF */
|
||||
if (dstinfo->write_Adobe_marker &&
|
||||
marker->marker == JPEG_APP0+14 &&
|
||||
marker->data_length >= 5 &&
|
||||
GETJOCTET(marker->data[0]) == 0x41 &&
|
||||
GETJOCTET(marker->data[1]) == 0x64 &&
|
||||
GETJOCTET(marker->data[2]) == 0x6F &&
|
||||
GETJOCTET(marker->data[3]) == 0x62 &&
|
||||
GETJOCTET(marker->data[4]) == 0x65)
|
||||
continue; /* reject duplicate Adobe */
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
/* We could use jpeg_write_marker if the data weren't FAR... */
|
||||
{
|
||||
unsigned int i;
|
||||
jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
|
||||
for (i = 0; i < marker->data_length; i++)
|
||||
jpeg_write_m_byte(dstinfo, marker->data[i]);
|
||||
}
|
||||
#else
|
||||
jpeg_write_marker(dstinfo, marker->marker,
|
||||
marker->data, marker->data_length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
135
transupp.h
Normal file
135
transupp.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* transupp.h
|
||||
*
|
||||
* Copyright (C) 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 image transformation routines and
|
||||
* other utility code used by the jpegtran sample application. These are
|
||||
* NOT part of the core JPEG library. But we keep these routines separate
|
||||
* from jpegtran.c to ease the task of maintaining jpegtran-like programs
|
||||
* that have other user interfaces.
|
||||
*
|
||||
* NOTE: all the routines declared here have very specific requirements
|
||||
* about when they are to be executed during the reading and writing of the
|
||||
* source and destination files. See the comments in transupp.c, or see
|
||||
* jpegtran.c for an example of correct usage.
|
||||
*/
|
||||
|
||||
/* If you happen not to want the image transform support, disable it here */
|
||||
#ifndef TRANSFORMS_SUPPORTED
|
||||
#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
|
||||
#endif
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jtransform_request_workspace jTrRequest
|
||||
#define jtransform_adjust_parameters jTrAdjust
|
||||
#define jtransform_execute_transformation jTrExec
|
||||
#define jcopy_markers_setup jCMrkSetup
|
||||
#define jcopy_markers_execute jCMrkExec
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/*
|
||||
* Codes for supported types of image transformations.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JXFORM_NONE, /* no transformation */
|
||||
JXFORM_FLIP_H, /* horizontal flip */
|
||||
JXFORM_FLIP_V, /* vertical flip */
|
||||
JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
|
||||
JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
|
||||
JXFORM_ROT_90, /* 90-degree clockwise rotation */
|
||||
JXFORM_ROT_180, /* 180-degree rotation */
|
||||
JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
|
||||
} JXFORM_CODE;
|
||||
|
||||
/*
|
||||
* Although rotating and flipping data expressed as DCT coefficients is not
|
||||
* hard, there is an asymmetry in the JPEG format specification for images
|
||||
* whose dimensions aren't multiples of the iMCU size. The right and bottom
|
||||
* image edges are padded out to the next iMCU boundary with junk data; but
|
||||
* no padding is possible at the top and left edges. If we were to flip
|
||||
* the whole image including the pad data, then pad garbage would become
|
||||
* visible at the top and/or left, and real pixels would disappear into the
|
||||
* pad margins --- perhaps permanently, since encoders & decoders may not
|
||||
* bother to preserve DCT blocks that appear to be completely outside the
|
||||
* nominal image area. So, we have to exclude any partial iMCUs from the
|
||||
* basic transformation.
|
||||
*
|
||||
* Transpose is the only transformation that can handle partial iMCUs at the
|
||||
* right and bottom edges completely cleanly. flip_h can flip partial iMCUs
|
||||
* at the bottom, but leaves any partial iMCUs at the right edge untouched.
|
||||
* Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
|
||||
* The other transforms are defined as combinations of these basic transforms
|
||||
* and process edge blocks in a way that preserves the equivalence.
|
||||
*
|
||||
* The "trim" option causes untransformable partial iMCUs to be dropped;
|
||||
* this is not strictly lossless, but it usually gives the best-looking
|
||||
* result for odd-size images. Note that when this option is active,
|
||||
* the expected mathematical equivalences between the transforms may not hold.
|
||||
* (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
|
||||
* followed by -rot 180 -trim trims both edges.)
|
||||
*
|
||||
* We also offer a "force to grayscale" option, which simply discards the
|
||||
* chrominance channels of a YCbCr image. This is lossless in the sense that
|
||||
* the luminance channel is preserved exactly. It's not the same kind of
|
||||
* thing as the rotate/flip transformations, but it's convenient to handle it
|
||||
* as part of this package, mainly because the transformation routines have to
|
||||
* be aware of the option to know how many components to work on.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
/* Options: set by caller */
|
||||
JXFORM_CODE transform; /* image transform operator */
|
||||
boolean trim; /* if TRUE, trim partial MCUs as needed */
|
||||
boolean force_grayscale; /* if TRUE, convert color image to grayscale */
|
||||
|
||||
/* Internal workspace: caller should not touch these */
|
||||
int num_components; /* # of components in workspace */
|
||||
jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
|
||||
} jpeg_transform_info;
|
||||
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/* Request any required workspace */
|
||||
EXTERN(void) jtransform_request_workspace
|
||||
JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
|
||||
/* Adjust output image parameters */
|
||||
EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Execute the actual transformation, if any */
|
||||
EXTERN(void) jtransform_execute_transformation
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Support for copying optional markers from source to destination file.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCOPYOPT_NONE, /* copy no optional markers */
|
||||
JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
|
||||
JCOPYOPT_ALL /* copy all optional markers */
|
||||
} JCOPY_OPTION;
|
||||
|
||||
#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
|
||||
|
||||
/* Setup decompression object to save desired markers in memory */
|
||||
EXTERN(void) jcopy_markers_setup
|
||||
JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
|
||||
/* Copy markers saved in the given source object to the destination object */
|
||||
EXTERN(void) jcopy_markers_execute
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option));
|
||||
562
usage.doc
Normal file
562
usage.doc
Normal file
@@ -0,0 +1,562 @@
|
||||
USAGE instructions for the Independent JPEG Group's JPEG software
|
||||
=================================================================
|
||||
|
||||
This file describes usage of the JPEG conversion programs cjpeg and djpeg,
|
||||
as well as the utility programs jpegtran, rdjpgcom and wrjpgcom. (See
|
||||
the other documentation files if you wish to use the JPEG library within
|
||||
your own programs.)
|
||||
|
||||
If you are on a Unix machine you may prefer to read the Unix-style manual
|
||||
pages in files cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
These programs implement JPEG image compression and decompression. JPEG
|
||||
(pronounced "jay-peg") is a standardized compression method for full-color
|
||||
and gray-scale images. JPEG is designed to handle "real-world" scenes,
|
||||
for example scanned photographs. Cartoons, line drawings, and other
|
||||
non-realistic images are not JPEG's strong suit; on that sort of material
|
||||
you may get poor image quality and/or little compression.
|
||||
|
||||
JPEG is lossy, meaning that the output image is not necessarily identical to
|
||||
the input image. Hence you should not use JPEG if you have to have identical
|
||||
output bits. However, on typical real-world images, very good compression
|
||||
levels can be obtained with no visible change, and amazingly high compression
|
||||
is possible if you can tolerate a low-quality image. You can trade off image
|
||||
quality against file size by adjusting the compressor's "quality" setting.
|
||||
|
||||
|
||||
GENERAL USAGE
|
||||
|
||||
We provide two programs, cjpeg to compress an image file into JPEG format,
|
||||
and djpeg to decompress a JPEG file back into a conventional image format.
|
||||
|
||||
On Unix-like systems, you say:
|
||||
cjpeg [switches] [imagefile] >jpegfile
|
||||
or
|
||||
djpeg [switches] [jpegfile] >imagefile
|
||||
The programs read the specified input file, or standard input if none is
|
||||
named. They always write to standard output (with trace/error messages to
|
||||
standard error). These conventions are handy for piping images between
|
||||
programs.
|
||||
|
||||
On most non-Unix systems, you say:
|
||||
cjpeg [switches] imagefile jpegfile
|
||||
or
|
||||
djpeg [switches] jpegfile imagefile
|
||||
i.e., both the input and output files are named on the command line. This
|
||||
style is a little more foolproof, and it loses no functionality if you don't
|
||||
have pipes. (You can get this style on Unix too, if you prefer, by defining
|
||||
TWO_FILE_COMMANDLINE when you compile the programs; see install.doc.)
|
||||
|
||||
You can also say:
|
||||
cjpeg [switches] -outfile jpegfile imagefile
|
||||
or
|
||||
djpeg [switches] -outfile imagefile jpegfile
|
||||
This syntax works on all systems, so it is useful for scripts.
|
||||
|
||||
The currently supported image file formats are: PPM (PBMPLUS color format),
|
||||
PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster Toolkit
|
||||
format). (RLE is supported only if the URT library is available.)
|
||||
cjpeg recognizes the input image format automatically, with the exception
|
||||
of some Targa-format files. You have to tell djpeg which format to generate.
|
||||
|
||||
JPEG files are in the defacto standard JFIF file format. There are other,
|
||||
less widely used JPEG-based file formats, but we don't support them.
|
||||
|
||||
All switch names may be abbreviated; for example, -grayscale may be written
|
||||
-gray or -gr. Most of the "basic" switches can be abbreviated to as little as
|
||||
one letter. Upper and lower case are equivalent (-BMP is the same as -bmp).
|
||||
British spellings are also accepted (e.g., -greyscale), though for brevity
|
||||
these are not mentioned below.
|
||||
|
||||
|
||||
CJPEG DETAILS
|
||||
|
||||
The basic command line switches for cjpeg are:
|
||||
|
||||
-quality N Scale quantization tables to adjust image quality.
|
||||
Quality is 0 (worst) to 100 (best); default is 75.
|
||||
(See below for more info.)
|
||||
|
||||
-grayscale Create monochrome JPEG file from color input.
|
||||
Be sure to use this switch when compressing a grayscale
|
||||
BMP file, because cjpeg isn't bright enough to notice
|
||||
whether a BMP file uses only shades of gray. By
|
||||
saying -grayscale, you'll get a smaller JPEG file that
|
||||
takes less time to process.
|
||||
|
||||
-optimize Perform optimization of entropy encoding parameters.
|
||||
Without this, default encoding parameters are used.
|
||||
-optimize usually makes the JPEG file a little smaller,
|
||||
but cjpeg runs somewhat slower and needs much more
|
||||
memory. Image quality and speed of decompression are
|
||||
unaffected by -optimize.
|
||||
|
||||
-progressive Create progressive JPEG file (see below).
|
||||
|
||||
-targa Input file is Targa format. Targa files that contain
|
||||
an "identification" field will not be automatically
|
||||
recognized by cjpeg; for such files you must specify
|
||||
-targa to make cjpeg treat the input as Targa format.
|
||||
For most Targa files, you won't need this switch.
|
||||
|
||||
The -quality switch lets you trade off compressed file size against quality of
|
||||
the reconstructed image: the higher the quality setting, the larger the JPEG
|
||||
file, and the closer the output image will be to the original input. Normally
|
||||
you want to use the lowest quality setting (smallest file) that decompresses
|
||||
into something visually indistinguishable from the original image. For this
|
||||
purpose the quality setting should be between 50 and 95; the default of 75 is
|
||||
often about right. If you see defects at -quality 75, then go up 5 or 10
|
||||
counts at a time until you are happy with the output image. (The optimal
|
||||
setting will vary from one image to another.)
|
||||
|
||||
-quality 100 will generate a quantization table of all 1's, minimizing loss
|
||||
in the quantization step (but there is still information loss in subsampling,
|
||||
as well as roundoff error). This setting is mainly of interest for
|
||||
experimental purposes. Quality values above about 95 are NOT recommended for
|
||||
normal use; the compressed file size goes up dramatically for hardly any gain
|
||||
in output image quality.
|
||||
|
||||
In the other direction, quality values below 50 will produce very small files
|
||||
of low image quality. Settings around 5 to 10 might be useful in preparing an
|
||||
index of a large image library, for example. Try -quality 2 (or so) for some
|
||||
amusing Cubist effects. (Note: quality values below about 25 generate 2-byte
|
||||
quantization tables, which are considered optional in the JPEG standard.
|
||||
cjpeg emits a warning message when you give such a quality value, because some
|
||||
other JPEG programs may be unable to decode the resulting file. Use -baseline
|
||||
if you need to ensure compatibility at low quality values.)
|
||||
|
||||
The -progressive switch creates a "progressive JPEG" file. In this type of
|
||||
JPEG file, the data is stored in multiple scans of increasing quality. If the
|
||||
file is being transmitted over a slow communications link, the decoder can use
|
||||
the first scan to display a low-quality image very quickly, and can then
|
||||
improve the display with each subsequent scan. The final image is exactly
|
||||
equivalent to a standard JPEG file of the same quality setting, and the total
|
||||
file size is about the same --- often a little smaller. CAUTION: progressive
|
||||
JPEG is not yet widely implemented, so many decoders will be unable to view a
|
||||
progressive JPEG file at all.
|
||||
|
||||
Switches for advanced users:
|
||||
|
||||
-dct int Use integer DCT method (default).
|
||||
-dct fast Use fast integer DCT (less accurate).
|
||||
-dct float Use floating-point DCT method.
|
||||
The float method is very slightly more accurate than
|
||||
the int method, but is much slower unless your machine
|
||||
has very fast floating-point hardware. Also note that
|
||||
results of the floating-point method may vary slightly
|
||||
across machines, while the integer methods should give
|
||||
the same results everywhere. The fast integer method
|
||||
is much less accurate than the other two.
|
||||
|
||||
-restart N Emit a JPEG restart marker every N MCU rows, or every
|
||||
N MCU blocks if "B" is attached to the number.
|
||||
-restart 0 (the default) means no restart markers.
|
||||
|
||||
-smooth N Smooth the input image to eliminate dithering noise.
|
||||
N, ranging from 1 to 100, indicates the strength of
|
||||
smoothing. 0 (the default) means no smoothing.
|
||||
|
||||
-maxmemory N Set limit for amount of memory to use in processing
|
||||
large images. Value is in thousands of bytes, or
|
||||
millions of bytes if "M" is attached to the number.
|
||||
For example, -max 4m selects 4000000 bytes. If more
|
||||
space is needed, temporary files will be used.
|
||||
|
||||
-verbose Enable debug printout. More -v's give more printout.
|
||||
or -debug Also, version information is printed at startup.
|
||||
|
||||
The -restart option inserts extra markers that allow a JPEG decoder to
|
||||
resynchronize after a transmission error. Without restart markers, any damage
|
||||
to a compressed file will usually ruin the image from the point of the error
|
||||
to the end of the image; with restart markers, the damage is usually confined
|
||||
to the portion of the image up to the next restart marker. Of course, the
|
||||
restart markers occupy extra space. We recommend -restart 1 for images that
|
||||
will be transmitted across unreliable networks such as Usenet.
|
||||
|
||||
The -smooth option filters the input to eliminate fine-scale noise. This is
|
||||
often useful when converting dithered images to JPEG: a moderate smoothing
|
||||
factor of 10 to 50 gets rid of dithering patterns in the input file, resulting
|
||||
in a smaller JPEG file and a better-looking image. Too large a smoothing
|
||||
factor will visibly blur the image, however.
|
||||
|
||||
Switches for wizards:
|
||||
|
||||
-baseline Force baseline-compatible quantization tables to be
|
||||
generated. This clamps quantization values to 8 bits
|
||||
even at low quality settings. (This switch is poorly
|
||||
named, since it does not ensure that the output is
|
||||
actually baseline JPEG. For example, you can use
|
||||
-baseline and -progressive together.)
|
||||
|
||||
-qtables file Use the quantization tables given in the specified
|
||||
text file.
|
||||
|
||||
-qslots N[,...] Select which quantization table to use for each color
|
||||
component.
|
||||
|
||||
-sample HxV[,...] Set JPEG sampling factors for each color component.
|
||||
|
||||
-scans file Use the scan script given in the specified text file.
|
||||
|
||||
The "wizard" switches are intended for experimentation with JPEG. If you
|
||||
don't know what you are doing, DON'T USE THEM. These switches are documented
|
||||
further in the file wizard.doc.
|
||||
|
||||
|
||||
DJPEG DETAILS
|
||||
|
||||
The basic command line switches for djpeg are:
|
||||
|
||||
-colors N Reduce image to at most N colors. This reduces the
|
||||
or -quantize N number of colors used in the output image, so that it
|
||||
can be displayed on a colormapped display or stored in
|
||||
a colormapped file format. For example, if you have
|
||||
an 8-bit display, you'd need to reduce to 256 or fewer
|
||||
colors. (-colors is the recommended name, -quantize
|
||||
is provided only for backwards compatibility.)
|
||||
|
||||
-fast Select recommended processing options for fast, low
|
||||
quality output. (The default options are chosen for
|
||||
highest quality output.) Currently, this is equivalent
|
||||
to "-dct fast -nosmooth -onepass -dither ordered".
|
||||
|
||||
-grayscale Force gray-scale output even if JPEG file is color.
|
||||
Useful for viewing on monochrome displays; also,
|
||||
djpeg runs noticeably faster in this mode.
|
||||
|
||||
-scale M/N Scale the output image by a factor M/N. Currently
|
||||
the scale factor must be 1/1, 1/2, 1/4, or 1/8.
|
||||
Scaling is handy if the image is larger than your
|
||||
screen; also, djpeg runs much faster when scaling
|
||||
down the output.
|
||||
|
||||
-bmp Select BMP output format (Windows flavor). 8-bit
|
||||
colormapped format is emitted if -colors or -grayscale
|
||||
is specified, or if the JPEG file is gray-scale;
|
||||
otherwise, 24-bit full-color format is emitted.
|
||||
|
||||
-gif Select GIF output format. Since GIF does not support
|
||||
more than 256 colors, -colors 256 is assumed (unless
|
||||
you specify a smaller number of colors). If you
|
||||
specify -fast, the default number of colors is 216.
|
||||
|
||||
-os2 Select BMP output format (OS/2 1.x flavor). 8-bit
|
||||
colormapped format is emitted if -colors or -grayscale
|
||||
is specified, or if the JPEG file is gray-scale;
|
||||
otherwise, 24-bit full-color format is emitted.
|
||||
|
||||
-pnm Select PBMPLUS (PPM/PGM) output format (this is the
|
||||
default format). PGM is emitted if the JPEG file is
|
||||
gray-scale or if -grayscale is specified; otherwise
|
||||
PPM is emitted.
|
||||
|
||||
-rle Select RLE output format. (Requires URT library.)
|
||||
|
||||
-targa Select Targa output format. Gray-scale format is
|
||||
emitted if the JPEG file is gray-scale or if
|
||||
-grayscale is specified; otherwise, colormapped format
|
||||
is emitted if -colors is specified; otherwise, 24-bit
|
||||
full-color format is emitted.
|
||||
|
||||
Switches for advanced users:
|
||||
|
||||
-dct int Use integer DCT method (default).
|
||||
-dct fast Use fast integer DCT (less accurate).
|
||||
-dct float Use floating-point DCT method.
|
||||
The float method is very slightly more accurate than
|
||||
the int method, but is much slower unless your machine
|
||||
has very fast floating-point hardware. Also note that
|
||||
results of the floating-point method may vary slightly
|
||||
across machines, while the integer methods should give
|
||||
the same results everywhere. The fast integer method
|
||||
is much less accurate than the other two.
|
||||
|
||||
-dither fs Use Floyd-Steinberg dithering in color quantization.
|
||||
-dither ordered Use ordered dithering in color quantization.
|
||||
-dither none Do not use dithering in color quantization.
|
||||
By default, Floyd-Steinberg dithering is applied when
|
||||
quantizing colors; this is slow but usually produces
|
||||
the best results. Ordered dither is a compromise
|
||||
between speed and quality; no dithering is fast but
|
||||
usually looks awful. Note that these switches have
|
||||
no effect unless color quantization is being done.
|
||||
Ordered dither is only available in -onepass mode.
|
||||
|
||||
-map FILE Quantize to the colors used in the specified image
|
||||
file. This is useful for producing multiple files
|
||||
with identical color maps, or for forcing a predefined
|
||||
set of colors to be used. The FILE must be a GIF
|
||||
or PPM file. This option overrides -colors and
|
||||
-onepass.
|
||||
|
||||
-nosmooth Use a faster, lower-quality upsampling routine.
|
||||
|
||||
-onepass Use one-pass instead of two-pass color quantization.
|
||||
The one-pass method is faster and needs less memory,
|
||||
but it produces a lower-quality image. -onepass is
|
||||
ignored unless you also say -colors N. Also,
|
||||
the one-pass method is always used for gray-scale
|
||||
output (the two-pass method is no improvement then).
|
||||
|
||||
-maxmemory N Set limit for amount of memory to use in processing
|
||||
large images. Value is in thousands of bytes, or
|
||||
millions of bytes if "M" is attached to the number.
|
||||
For example, -max 4m selects 4000000 bytes. If more
|
||||
space is needed, temporary files will be used.
|
||||
|
||||
-verbose Enable debug printout. More -v's give more printout.
|
||||
or -debug Also, version information is printed at startup.
|
||||
|
||||
|
||||
HINTS FOR CJPEG
|
||||
|
||||
Color GIF files are not the ideal input for JPEG; JPEG is really intended for
|
||||
compressing full-color (24-bit) images. In particular, don't try to convert
|
||||
cartoons, line drawings, and other images that have only a few distinct
|
||||
colors. GIF works great on these, JPEG does not. If you want to convert a
|
||||
GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options
|
||||
to get a satisfactory conversion. -smooth 10 or so is often helpful.
|
||||
|
||||
Avoid running an image through a series of JPEG compression/decompression
|
||||
cycles. Image quality loss will accumulate; after ten or so cycles the image
|
||||
may be noticeably worse than it was after one cycle. It's best to use a
|
||||
lossless format while manipulating an image, then convert to JPEG format when
|
||||
you are ready to file the image away.
|
||||
|
||||
The -optimize option to cjpeg is worth using when you are making a "final"
|
||||
version for posting or archiving. It's also a win when you are using low
|
||||
quality settings to make very small JPEG files; the percentage improvement
|
||||
is often a lot more than it is on larger files. (At present, -optimize
|
||||
mode is always selected when generating progressive JPEG files.)
|
||||
|
||||
GIF input files are no longer supported, to avoid the Unisys LZW patent.
|
||||
Use a Unisys-licensed program if you need to read a GIF file. (Conversion
|
||||
of GIF files to JPEG is usually a bad idea anyway.)
|
||||
|
||||
|
||||
HINTS FOR DJPEG
|
||||
|
||||
To get a quick preview of an image, use the -grayscale and/or -scale switches.
|
||||
"-grayscale -scale 1/8" is the fastest case.
|
||||
|
||||
Several options are available that trade off image quality to gain speed.
|
||||
"-fast" turns on the recommended settings.
|
||||
|
||||
"-dct fast" and/or "-nosmooth" gain speed at a small sacrifice in quality.
|
||||
When producing a color-quantized image, "-onepass -dither ordered" is fast but
|
||||
much lower quality than the default behavior. "-dither none" may give
|
||||
acceptable results in two-pass mode, but is seldom tolerable in one-pass mode.
|
||||
|
||||
If you are fortunate enough to have very fast floating point hardware,
|
||||
"-dct float" may be even faster than "-dct fast". But on most machines
|
||||
"-dct float" is slower than "-dct int"; in this case it is not worth using,
|
||||
because its theoretical accuracy advantage is too small to be significant
|
||||
in practice.
|
||||
|
||||
Two-pass color quantization requires a good deal of memory; on MS-DOS machines
|
||||
it may run out of memory even with -maxmemory 0. In that case you can still
|
||||
decompress, with some loss of image quality, by specifying -onepass for
|
||||
one-pass quantization.
|
||||
|
||||
To avoid the Unisys LZW patent, djpeg produces uncompressed GIF files. These
|
||||
are larger than they should be, but are readable by standard GIF decoders.
|
||||
|
||||
|
||||
HINTS FOR BOTH PROGRAMS
|
||||
|
||||
If more space is needed than will fit in the available main memory (as
|
||||
determined by -maxmemory), temporary files will be used. (MS-DOS versions
|
||||
will try to get extended or expanded memory first.) The temporary files are
|
||||
often rather large: in typical cases they occupy three bytes per pixel, for
|
||||
example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough
|
||||
free disk space, leave out -progressive and -optimize (for cjpeg) or specify
|
||||
-onepass (for djpeg).
|
||||
|
||||
On MS-DOS, the temporary files are created in the directory named by the TMP
|
||||
or TEMP environment variable, or in the current directory if neither of those
|
||||
exist. Amiga implementations put the temp files in the directory named by
|
||||
JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free
|
||||
space.
|
||||
|
||||
The default memory usage limit (-maxmemory) is set when the software is
|
||||
compiled. If you get an "insufficient memory" error, try specifying a smaller
|
||||
-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You
|
||||
may want to recompile with a smaller default value if this happens often.
|
||||
|
||||
On machines that have "environment" variables, you can define the environment
|
||||
variable JPEGMEM to set the default memory limit. The value is specified as
|
||||
described for the -maxmemory switch. JPEGMEM overrides the default value
|
||||
specified when the program was compiled, and itself is overridden by an
|
||||
explicit -maxmemory switch.
|
||||
|
||||
On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to
|
||||
use. (Extended or expanded memory is also used if available.) Most
|
||||
DOS-specific versions of this software do their own memory space estimation
|
||||
and do not need you to specify -maxmemory.
|
||||
|
||||
|
||||
JPEGTRAN
|
||||
|
||||
jpegtran performs various useful transformations of JPEG files.
|
||||
It can translate the coded representation from one variant of JPEG to another,
|
||||
for example from baseline JPEG to progressive JPEG or vice versa. It can also
|
||||
perform some rearrangements of the image data, for example turning an image
|
||||
from landscape to portrait format by rotation.
|
||||
|
||||
jpegtran works by rearranging the compressed data (DCT coefficients), without
|
||||
ever fully decoding the image. Therefore, its transformations are lossless:
|
||||
there is no image degradation at all, which would not be true if you used
|
||||
djpeg followed by cjpeg to accomplish the same conversion. But by the same
|
||||
token, jpegtran cannot perform lossy operations such as changing the image
|
||||
quality.
|
||||
|
||||
jpegtran uses a command line syntax similar to cjpeg or djpeg.
|
||||
On Unix-like systems, you say:
|
||||
jpegtran [switches] [inputfile] >outputfile
|
||||
On most non-Unix systems, you say:
|
||||
jpegtran [switches] inputfile outputfile
|
||||
where both the input and output files are JPEG files.
|
||||
|
||||
To specify the coded JPEG representation used in the output file,
|
||||
jpegtran accepts a subset of the switches recognized by cjpeg:
|
||||
-optimize Perform optimization of entropy encoding parameters.
|
||||
-progressive Create progressive JPEG file.
|
||||
-restart N Emit a JPEG restart marker every N MCU rows, or every
|
||||
N MCU blocks if "B" is attached to the number.
|
||||
-scans file Use the scan script given in the specified text file.
|
||||
See the previous discussion of cjpeg for more details about these switches.
|
||||
If you specify none of these switches, you get a plain baseline-JPEG output
|
||||
file. The quality setting and so forth are determined by the input file.
|
||||
|
||||
The image can be losslessly transformed by giving one of these switches:
|
||||
-flip horizontal Mirror image horizontally (left-right).
|
||||
-flip vertical Mirror image vertically (top-bottom).
|
||||
-rotate 90 Rotate image 90 degrees clockwise.
|
||||
-rotate 180 Rotate image 180 degrees.
|
||||
-rotate 270 Rotate image 270 degrees clockwise (or 90 ccw).
|
||||
-transpose Transpose image (across UL-to-LR axis).
|
||||
-transverse Transverse transpose (across UR-to-LL axis).
|
||||
|
||||
The transpose transformation has no restrictions regarding image dimensions.
|
||||
The other transformations operate rather oddly if the image dimensions are not
|
||||
a multiple of the iMCU size (usually 8 or 16 pixels), because they can only
|
||||
transform complete blocks of DCT coefficient data in the desired way.
|
||||
|
||||
jpegtran's default behavior when transforming an odd-size image is designed
|
||||
to preserve exact reversibility and mathematical consistency of the
|
||||
transformation set. As stated, transpose is able to flip the entire image
|
||||
area. Horizontal mirroring leaves any partial iMCU column at the right edge
|
||||
untouched, but is able to flip all rows of the image. Similarly, vertical
|
||||
mirroring leaves any partial iMCU row at the bottom edge untouched, but is
|
||||
able to flip all columns. The other transforms can be built up as sequences
|
||||
of transpose and flip operations; for consistency, their actions on edge
|
||||
pixels are defined to be the same as the end result of the corresponding
|
||||
transpose-and-flip sequence.
|
||||
|
||||
For practical use, you may prefer to discard any untransformable edge pixels
|
||||
rather than having a strange-looking strip along the right and/or bottom edges
|
||||
of a transformed image. To do this, add the -trim switch:
|
||||
-trim Drop non-transformable edge blocks.
|
||||
Obviously, a transformation with -trim is not reversible, so strictly speaking
|
||||
jpegtran with this switch is not lossless. Also, the expected mathematical
|
||||
equivalences between the transformations no longer hold. For example,
|
||||
"-rot 270 -trim" trims only the bottom edge, but "-rot 90 -trim" followed by
|
||||
"-rot 180 -trim" trims both edges.
|
||||
|
||||
Another not-strictly-lossless transformation switch is:
|
||||
-grayscale Force grayscale output.
|
||||
This option discards the chrominance channels if the input image is YCbCr
|
||||
(ie, a standard color JPEG), resulting in a grayscale JPEG file. The
|
||||
luminance channel is preserved exactly, so this is a better method of reducing
|
||||
to grayscale than decompression, conversion, and recompression. This switch
|
||||
is particularly handy for fixing a monochrome picture that was mistakenly
|
||||
encoded as a color JPEG. (In such a case, the space savings from getting rid
|
||||
of the near-empty chroma channels won't be large; but the decoding time for
|
||||
a grayscale JPEG is substantially less than that for a color JPEG.)
|
||||
|
||||
jpegtran also recognizes these switches that control what to do with "extra"
|
||||
markers, such as comment blocks:
|
||||
-copy none Copy no extra markers from source file. This setting
|
||||
suppresses all comments and other excess baggage
|
||||
present in the source file.
|
||||
-copy comments Copy only comment markers. This setting copies
|
||||
comments from the source file, but discards
|
||||
any other inessential data.
|
||||
-copy all Copy all extra markers. This setting preserves
|
||||
miscellaneous markers found in the source file, such
|
||||
as JFIF thumbnails and Photoshop settings. In some
|
||||
files these extra markers can be sizable.
|
||||
The default behavior is -copy comments. (Note: in IJG releases v6 and v6a,
|
||||
jpegtran always did the equivalent of -copy none.)
|
||||
|
||||
Additional switches recognized by jpegtran are:
|
||||
-outfile filename
|
||||
-maxmemory N
|
||||
-verbose
|
||||
-debug
|
||||
These work the same as in cjpeg or djpeg.
|
||||
|
||||
|
||||
THE COMMENT UTILITIES
|
||||
|
||||
The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file.
|
||||
Although the standard doesn't actually define what COM blocks are for, they
|
||||
are widely used to hold user-supplied text strings. This lets you add
|
||||
annotations, titles, index terms, etc to your JPEG files, and later retrieve
|
||||
them as text. COM blocks do not interfere with the image stored in the JPEG
|
||||
file. The maximum size of a COM block is 64K, but you can have as many of
|
||||
them as you like in one JPEG file.
|
||||
|
||||
We provide two utility programs to display COM block contents and add COM
|
||||
blocks to a JPEG file.
|
||||
|
||||
rdjpgcom searches a JPEG file and prints the contents of any COM blocks on
|
||||
standard output. The command line syntax is
|
||||
rdjpgcom [-verbose] [inputfilename]
|
||||
The switch "-verbose" (or just "-v") causes rdjpgcom to also display the JPEG
|
||||
image dimensions. If you omit the input file name from the command line,
|
||||
the JPEG file is read from standard input. (This may not work on some
|
||||
operating systems, if binary data can't be read from stdin.)
|
||||
|
||||
wrjpgcom adds a COM block, containing text you provide, to a JPEG file.
|
||||
Ordinarily, the COM block is added after any existing COM blocks, but you
|
||||
can delete the old COM blocks if you wish. wrjpgcom produces a new JPEG
|
||||
file; it does not modify the input file. DO NOT try to overwrite the input
|
||||
file by directing wrjpgcom's output back into it; on most systems this will
|
||||
just destroy your file.
|
||||
|
||||
The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like
|
||||
systems, it is
|
||||
wrjpgcom [switches] [inputfilename]
|
||||
The output file is written to standard output. The input file comes from
|
||||
the named file, or from standard input if no input file is named.
|
||||
|
||||
On most non-Unix systems, the syntax is
|
||||
wrjpgcom [switches] inputfilename outputfilename
|
||||
where both input and output file names must be given explicitly.
|
||||
|
||||
wrjpgcom understands three switches:
|
||||
-replace Delete any existing COM blocks from the file.
|
||||
-comment "Comment text" Supply new COM text on command line.
|
||||
-cfile name Read text for new COM block from named file.
|
||||
(Switch names can be abbreviated.) If you have only one line of comment text
|
||||
to add, you can provide it on the command line with -comment. The comment
|
||||
text must be surrounded with quotes so that it is treated as a single
|
||||
argument. Longer comments can be read from a text file.
|
||||
|
||||
If you give neither -comment nor -cfile, then wrjpgcom will read the comment
|
||||
text from standard input. (In this case an input image file name MUST be
|
||||
supplied, so that the source JPEG file comes from somewhere else.) You can
|
||||
enter multiple lines, up to 64KB worth. Type an end-of-file indicator
|
||||
(usually control-D or control-Z) to terminate the comment text entry.
|
||||
|
||||
wrjpgcom will not add a COM block if the provided comment string is empty.
|
||||
Therefore -replace -comment "" can be used to delete all COM blocks from a
|
||||
file.
|
||||
|
||||
These utility programs do not depend on the IJG JPEG library. In
|
||||
particular, the source code for rdjpgcom is intended as an illustration of
|
||||
the minimum amount of code required to parse a JPEG file header correctly.
|
||||
211
wizard.doc
Normal file
211
wizard.doc
Normal file
@@ -0,0 +1,211 @@
|
||||
Advanced usage instructions for the Independent JPEG Group's JPEG software
|
||||
==========================================================================
|
||||
|
||||
This file describes cjpeg's "switches for wizards".
|
||||
|
||||
The "wizard" switches are intended for experimentation with JPEG by persons
|
||||
who are reasonably knowledgeable about the JPEG standard. If you don't know
|
||||
what you are doing, DON'T USE THESE SWITCHES. You'll likely produce files
|
||||
with worse image quality and/or poorer compression than you'd get from the
|
||||
default settings. Furthermore, these switches must be used with caution
|
||||
when making files intended for general use, because not all JPEG decoders
|
||||
will support unusual JPEG parameter settings.
|
||||
|
||||
|
||||
Quantization Table Adjustment
|
||||
-----------------------------
|
||||
|
||||
Ordinarily, cjpeg starts with a default set of tables (the same ones given
|
||||
as examples in the JPEG standard) and scales them up or down according to
|
||||
the -quality setting. The details of the scaling algorithm can be found in
|
||||
jcparam.c. At very low quality settings, some quantization table entries
|
||||
can get scaled up to values exceeding 255. Although 2-byte quantization
|
||||
values are supported by the IJG software, this feature is not in baseline
|
||||
JPEG and is not supported by all implementations. If you need to ensure
|
||||
wide compatibility of low-quality files, you can constrain the scaled
|
||||
quantization values to no more than 255 by giving the -baseline switch.
|
||||
Note that use of -baseline will result in poorer quality for the same file
|
||||
size, since more bits than necessary are expended on higher AC coefficients.
|
||||
|
||||
You can substitute a different set of quantization values by using the
|
||||
-qtables switch:
|
||||
|
||||
-qtables file Use the quantization tables given in the named file.
|
||||
|
||||
The specified file should be a text file containing decimal quantization
|
||||
values. The file should contain one to four tables, each of 64 elements.
|
||||
The tables are implicitly numbered 0,1,etc. in order of appearance. Table
|
||||
entries appear in normal array order (NOT in the zigzag order in which they
|
||||
will be stored in the JPEG file).
|
||||
|
||||
Quantization table files are free format, in that arbitrary whitespace can
|
||||
appear between numbers. Also, comments can be included: a comment starts
|
||||
with '#' and extends to the end of the line. Here is an example file that
|
||||
duplicates the default quantization tables:
|
||||
|
||||
# Quantization tables given in JPEG spec, section K.1
|
||||
|
||||
# This is table 0 (the luminance table):
|
||||
16 11 10 16 24 40 51 61
|
||||
12 12 14 19 26 58 60 55
|
||||
14 13 16 24 40 57 69 56
|
||||
14 17 22 29 51 87 80 62
|
||||
18 22 37 56 68 109 103 77
|
||||
24 35 55 64 81 104 113 92
|
||||
49 64 78 87 103 121 120 101
|
||||
72 92 95 98 112 100 103 99
|
||||
|
||||
# This is table 1 (the chrominance table):
|
||||
17 18 24 47 99 99 99 99
|
||||
18 21 26 66 99 99 99 99
|
||||
24 26 56 99 99 99 99 99
|
||||
47 66 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
|
||||
If the -qtables switch is used without -quality, then the specified tables
|
||||
are used exactly as-is. If both -qtables and -quality are used, then the
|
||||
tables taken from the file are scaled in the same fashion that the default
|
||||
tables would be scaled for that quality setting. If -baseline appears, then
|
||||
the quantization values are constrained to the range 1-255.
|
||||
|
||||
By default, cjpeg will use quantization table 0 for luminance components and
|
||||
table 1 for chrominance components. To override this choice, use the -qslots
|
||||
switch:
|
||||
|
||||
-qslots N[,...] Select which quantization table to use for
|
||||
each color component.
|
||||
|
||||
The -qslots switch specifies a quantization table number for each color
|
||||
component, in the order in which the components appear in the JPEG SOF marker.
|
||||
For example, to create a separate table for each of Y,Cb,Cr, you could
|
||||
provide a -qtables file that defines three quantization tables and say
|
||||
"-qslots 0,1,2". If -qslots gives fewer table numbers than there are color
|
||||
components, then the last table number is repeated as necessary.
|
||||
|
||||
|
||||
Sampling Factor Adjustment
|
||||
--------------------------
|
||||
|
||||
By default, cjpeg uses 2:1 horizontal and vertical downsampling when
|
||||
compressing YCbCr data, and no downsampling for all other color spaces.
|
||||
You can override this default with the -sample switch:
|
||||
|
||||
-sample HxV[,...] Set JPEG sampling factors for each color
|
||||
component.
|
||||
|
||||
The -sample switch specifies the JPEG sampling factors for each color
|
||||
component, in the order in which they appear in the JPEG SOF marker.
|
||||
If you specify fewer HxV pairs than there are components, the remaining
|
||||
components are set to 1x1 sampling. For example, the default YCbCr setting
|
||||
is equivalent to "-sample 2x2,1x1,1x1", which can be abbreviated to
|
||||
"-sample 2x2".
|
||||
|
||||
There are still some JPEG decoders in existence that support only 2x1
|
||||
sampling (also called 4:2:2 sampling). Compatibility with such decoders can
|
||||
be achieved by specifying "-sample 2x1". This is not recommended unless
|
||||
really necessary, since it increases file size and encoding/decoding time
|
||||
with very little quality gain.
|
||||
|
||||
|
||||
Multiple Scan / Progression Control
|
||||
-----------------------------------
|
||||
|
||||
By default, cjpeg emits a single-scan sequential JPEG file. The
|
||||
-progressive switch generates a progressive JPEG file using a default series
|
||||
of progression parameters. You can create multiple-scan sequential JPEG
|
||||
files or progressive JPEG files with custom progression parameters by using
|
||||
the -scans switch:
|
||||
|
||||
-scans file Use the scan sequence given in the named file.
|
||||
|
||||
The specified file should be a text file containing a "scan script".
|
||||
The script specifies the contents and ordering of the scans to be emitted.
|
||||
Each entry in the script defines one scan. A scan definition specifies
|
||||
the components to be included in the scan, and for progressive JPEG it also
|
||||
specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan
|
||||
definitions are separated by semicolons (';'). A semicolon after the last
|
||||
scan definition is optional.
|
||||
|
||||
Each scan definition contains one to four component indexes, optionally
|
||||
followed by a colon (':') and the four progressive-JPEG parameters. The
|
||||
component indexes denote which color component(s) are to be transmitted in
|
||||
the scan. Components are numbered in the order in which they appear in the
|
||||
JPEG SOF marker, with the first component being numbered 0. (Note that these
|
||||
indexes are not the "component ID" codes assigned to the components, just
|
||||
positional indexes.)
|
||||
|
||||
The progression parameters for each scan are:
|
||||
Ss Zigzag index of first coefficient included in scan
|
||||
Se Zigzag index of last coefficient included in scan
|
||||
Ah Zero for first scan of a coefficient, else Al of prior scan
|
||||
Al Successive approximation low bit position for scan
|
||||
If the progression parameters are omitted, the values 0,63,0,0 are used,
|
||||
producing a sequential JPEG file. cjpeg automatically determines whether
|
||||
the script represents a progressive or sequential file, by observing whether
|
||||
Ss and Se values other than 0 and 63 appear. (The -progressive switch is
|
||||
not needed to specify this; in fact, it is ignored when -scans appears.)
|
||||
The scan script must meet the JPEG restrictions on progression sequences.
|
||||
(cjpeg checks that the spec's requirements are obeyed.)
|
||||
|
||||
Scan script files are free format, in that arbitrary whitespace can appear
|
||||
between numbers and around punctuation. Also, comments can be included: a
|
||||
comment starts with '#' and extends to the end of the line. For additional
|
||||
legibility, commas or dashes can be placed between values. (Actually, any
|
||||
single punctuation character other than ':' or ';' can be inserted.) For
|
||||
example, the following two scan definitions are equivalent:
|
||||
0 1 2: 0 63 0 0;
|
||||
0,1,2 : 0-63, 0,0 ;
|
||||
|
||||
Here is an example of a scan script that generates a partially interleaved
|
||||
sequential JPEG file:
|
||||
|
||||
0; # Y only in first scan
|
||||
1 2; # Cb and Cr in second scan
|
||||
|
||||
Here is an example of a progressive scan script using only spectral selection
|
||||
(no successive approximation):
|
||||
|
||||
# Interleaved DC scan for Y,Cb,Cr:
|
||||
0,1,2: 0-0, 0, 0 ;
|
||||
# AC scans:
|
||||
0: 1-2, 0, 0 ; # First two Y AC coefficients
|
||||
0: 3-5, 0, 0 ; # Three more
|
||||
1: 1-63, 0, 0 ; # All AC coefficients for Cb
|
||||
2: 1-63, 0, 0 ; # All AC coefficients for Cr
|
||||
0: 6-9, 0, 0 ; # More Y coefficients
|
||||
0: 10-63, 0, 0 ; # Remaining Y coefficients
|
||||
|
||||
Here is an example of a successive-approximation script. This is equivalent
|
||||
to the default script used by "cjpeg -progressive" for YCbCr images:
|
||||
|
||||
# Initial DC scan for Y,Cb,Cr (lowest bit not sent)
|
||||
0,1,2: 0-0, 0, 1 ;
|
||||
# First AC scan: send first 5 Y AC coefficients, minus 2 lowest bits:
|
||||
0: 1-5, 0, 2 ;
|
||||
# Send all Cr,Cb AC coefficients, minus lowest bit:
|
||||
# (chroma data is usually too small to be worth subdividing further;
|
||||
# but note we send Cr first since eye is least sensitive to Cb)
|
||||
2: 1-63, 0, 1 ;
|
||||
1: 1-63, 0, 1 ;
|
||||
# Send remaining Y AC coefficients, minus 2 lowest bits:
|
||||
0: 6-63, 0, 2 ;
|
||||
# Send next-to-lowest bit of all Y AC coefficients:
|
||||
0: 1-63, 2, 1 ;
|
||||
# At this point we've sent all but the lowest bit of all coefficients.
|
||||
# Send lowest bit of DC coefficients
|
||||
0,1,2: 0-0, 1, 0 ;
|
||||
# Send lowest bit of AC coefficients
|
||||
2: 1-63, 1, 0 ;
|
||||
1: 1-63, 1, 0 ;
|
||||
# Y AC lowest bit scan is last; it's usually the largest scan
|
||||
0: 1-63, 1, 0 ;
|
||||
|
||||
It may be worth pointing out that this script is tuned for quality settings
|
||||
of around 50 to 75. For lower quality settings, you'd probably want to use
|
||||
a script with fewer stages of successive approximation (otherwise the
|
||||
initial scans will be really bad). For higher quality settings, you might
|
||||
want to use more stages of successive approximation (so that the initial
|
||||
scans are not too large).
|
||||
103
wrjpgcom.1
Normal file
103
wrjpgcom.1
Normal file
@@ -0,0 +1,103 @@
|
||||
.TH WRJPGCOM 1 "15 June 1995"
|
||||
.SH NAME
|
||||
wrjpgcom \- insert text comments into a JPEG file
|
||||
.SH SYNOPSIS
|
||||
.B wrjpgcom
|
||||
[
|
||||
.B \-replace
|
||||
]
|
||||
[
|
||||
.BI \-comment " text"
|
||||
]
|
||||
[
|
||||
.BI \-cfile " name"
|
||||
]
|
||||
[
|
||||
.I filename
|
||||
]
|
||||
.LP
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
.B wrjpgcom
|
||||
reads the named JPEG/JFIF file, or the standard input if no file is named,
|
||||
and generates a new JPEG/JFIF file on standard output. A comment block is
|
||||
added to the file.
|
||||
.PP
|
||||
The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file.
|
||||
Although the standard doesn't actually define what COM blocks are for, they
|
||||
are widely used to hold user-supplied text strings. This lets you add
|
||||
annotations, titles, index terms, etc to your JPEG files, and later retrieve
|
||||
them as text. COM blocks do not interfere with the image stored in the JPEG
|
||||
file. The maximum size of a COM block is 64K, but you can have as many of
|
||||
them as you like in one JPEG file.
|
||||
.PP
|
||||
.B wrjpgcom
|
||||
adds a COM block, containing text you provide, to a JPEG file.
|
||||
Ordinarily, the COM block is added after any existing COM blocks; but you
|
||||
can delete the old COM blocks if you wish.
|
||||
.SH OPTIONS
|
||||
Switch names may be abbreviated, and are not case sensitive.
|
||||
.TP
|
||||
.B \-replace
|
||||
Delete any existing COM blocks from the file.
|
||||
.TP
|
||||
.BI \-comment " text"
|
||||
Supply text for new COM block on command line.
|
||||
.TP
|
||||
.BI \-cfile " name"
|
||||
Read text for new COM block from named file.
|
||||
.PP
|
||||
If you have only one line of comment text to add, you can provide it on the
|
||||
command line with
|
||||
.BR \-comment .
|
||||
The comment text must be surrounded with quotes so that it is treated as a
|
||||
single argument. Longer comments can be read from a text file.
|
||||
.PP
|
||||
If you give neither
|
||||
.B \-comment
|
||||
nor
|
||||
.BR \-cfile ,
|
||||
then
|
||||
.B wrjpgcom
|
||||
will read the comment text from standard input. (In this case an input image
|
||||
file name MUST be supplied, so that the source JPEG file comes from somewhere
|
||||
else.) You can enter multiple lines, up to 64KB worth. Type an end-of-file
|
||||
indicator (usually control-D) to terminate the comment text entry.
|
||||
.PP
|
||||
.B wrjpgcom
|
||||
will not add a COM block if the provided comment string is empty. Therefore
|
||||
\fB\-replace \-comment ""\fR can be used to delete all COM blocks from a file.
|
||||
.SH EXAMPLES
|
||||
.LP
|
||||
Add a short comment to in.jpg, producing out.jpg:
|
||||
.IP
|
||||
.B wrjpgcom \-c
|
||||
\fI"View of my back yard" in.jpg
|
||||
.B >
|
||||
.I out.jpg
|
||||
.PP
|
||||
Attach a long comment previously stored in comment.txt:
|
||||
.IP
|
||||
.B wrjpgcom
|
||||
.I in.jpg
|
||||
.B <
|
||||
.I comment.txt
|
||||
.B >
|
||||
.I out.jpg
|
||||
.PP
|
||||
or equivalently
|
||||
.IP
|
||||
.B wrjpgcom
|
||||
.B -cfile
|
||||
.I comment.txt
|
||||
.B <
|
||||
.I in.jpg
|
||||
.B >
|
||||
.I out.jpg
|
||||
.SH SEE ALSO
|
||||
.BR cjpeg (1),
|
||||
.BR djpeg (1),
|
||||
.BR jpegtran (1),
|
||||
.BR rdjpgcom (1)
|
||||
.SH AUTHOR
|
||||
Independent JPEG Group
|
||||
583
wrjpgcom.c
Normal file
583
wrjpgcom.c
Normal file
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* wrjpgcom.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 a very simple stand-alone application that inserts
|
||||
* user-supplied text as a COM (comment) marker in a JFIF file.
|
||||
* This may be useful as an example of the minimum logic needed to parse
|
||||
* JPEG markers.
|
||||
*/
|
||||
|
||||
#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
|
||||
#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
|
||||
|
||||
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc() */
|
||||
extern void * malloc ();
|
||||
#endif
|
||||
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||
#ifdef USE_SETMODE
|
||||
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||
#include <io.h> /* to declare setmode() */
|
||||
#endif
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#define WRITE_BINARY "w"
|
||||
#else
|
||||
#ifdef VMS /* VMS is very nonstandard */
|
||||
#define READ_BINARY "rb", "ctx=stm"
|
||||
#define WRITE_BINARY "wb", "ctx=stm"
|
||||
#else /* standard ANSI-compliant case */
|
||||
#define READ_BINARY "rb"
|
||||
#define WRITE_BINARY "wb"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
#ifdef VMS
|
||||
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
|
||||
#else
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Reduce this value if your malloc() can't allocate blocks up to 64K.
|
||||
* On DOS, compiling in large model is usually a better solution.
|
||||
*/
|
||||
|
||||
#ifndef MAX_COM_LENGTH
|
||||
#define MAX_COM_LENGTH 65000L /* must be <= 65533 in any case */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These macros are used to read the input file and write the output file.
|
||||
* To reuse this code in another application, you might need to change these.
|
||||
*/
|
||||
|
||||
static FILE * infile; /* input JPEG file */
|
||||
|
||||
/* Return next input byte, or EOF if no more */
|
||||
#define NEXTBYTE() getc(infile)
|
||||
|
||||
static FILE * outfile; /* output JPEG file */
|
||||
|
||||
/* Emit an output byte */
|
||||
#define PUTBYTE(x) putc((x), outfile)
|
||||
|
||||
|
||||
/* Error exit handler */
|
||||
#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
|
||||
|
||||
|
||||
/* Read one byte, testing for EOF */
|
||||
static int
|
||||
read_1_byte (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = NEXTBYTE();
|
||||
if (c == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Read 2 bytes, convert to unsigned int */
|
||||
/* All 2-byte quantities in JPEG markers are MSB first */
|
||||
static unsigned int
|
||||
read_2_bytes (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
if (c1 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
c2 = NEXTBYTE();
|
||||
if (c2 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return (((unsigned int) c1) << 8) + ((unsigned int) c2);
|
||||
}
|
||||
|
||||
|
||||
/* Routines to write data to output file */
|
||||
|
||||
static void
|
||||
write_1_byte (int c)
|
||||
{
|
||||
PUTBYTE(c);
|
||||
}
|
||||
|
||||
static void
|
||||
write_2_bytes (unsigned int val)
|
||||
{
|
||||
PUTBYTE((val >> 8) & 0xFF);
|
||||
PUTBYTE(val & 0xFF);
|
||||
}
|
||||
|
||||
static void
|
||||
write_marker (int marker)
|
||||
{
|
||||
PUTBYTE(0xFF);
|
||||
PUTBYTE(marker);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_rest_of_file (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = NEXTBYTE()) != EOF)
|
||||
PUTBYTE(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||||
* code byte (which is not an FF). Here are the marker codes of interest
|
||||
* in this program. (See jdmarker.c for a more complete list.)
|
||||
*/
|
||||
|
||||
#define M_SOF0 0xC0 /* Start Of Frame N */
|
||||
#define M_SOF1 0xC1 /* N indicates which compression process */
|
||||
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
|
||||
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
|
||||
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
|
||||
#define M_COM 0xFE /* COMment */
|
||||
|
||||
|
||||
/*
|
||||
* Find the next JPEG marker and return its marker code.
|
||||
* We expect at least one FF byte, possibly more if the compressor used FFs
|
||||
* to pad the file. (Padding FFs will NOT be replicated in the output file.)
|
||||
* There could also be non-FF garbage between markers. The treatment of such
|
||||
* garbage is unspecified; we choose to skip over it but emit a warning msg.
|
||||
* NB: this routine must not be used after seeing SOS marker, since it will
|
||||
* not deal correctly with FF/00 sequences in the compressed image data...
|
||||
*/
|
||||
|
||||
static int
|
||||
next_marker (void)
|
||||
{
|
||||
int c;
|
||||
int discarded_bytes = 0;
|
||||
|
||||
/* Find 0xFF byte; count and skip any non-FFs. */
|
||||
c = read_1_byte();
|
||||
while (c != 0xFF) {
|
||||
discarded_bytes++;
|
||||
c = read_1_byte();
|
||||
}
|
||||
/* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
|
||||
* are legal as pad bytes, so don't count them in discarded_bytes.
|
||||
*/
|
||||
do {
|
||||
c = read_1_byte();
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (discarded_bytes != 0) {
|
||||
fprintf(stderr, "Warning: garbage data found in JPEG file\n");
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the initial marker, which should be SOI.
|
||||
* For a JFIF file, the first two bytes of the file should be literally
|
||||
* 0xFF M_SOI. To be more general, we could use next_marker, but if the
|
||||
* input file weren't actually JPEG at all, next_marker might read the whole
|
||||
* file and then return a misleading error message...
|
||||
*/
|
||||
|
||||
static int
|
||||
first_marker (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
c2 = NEXTBYTE();
|
||||
if (c1 != 0xFF || c2 != M_SOI)
|
||||
ERREXIT("Not a JPEG file");
|
||||
return c2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Most types of marker are followed by a variable-length parameter segment.
|
||||
* This routine skips over the parameters for any marker we don't otherwise
|
||||
* want to process.
|
||||
* Note that we MUST skip the parameter segment explicitly in order not to
|
||||
* be fooled by 0xFF bytes that might appear within the parameter segment;
|
||||
* such bytes do NOT introduce new markers.
|
||||
*/
|
||||
|
||||
static void
|
||||
copy_variable (void)
|
||||
/* Copy an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
write_2_bytes(length);
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Skip over the remaining bytes */
|
||||
while (length > 0) {
|
||||
write_1_byte(read_1_byte());
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
skip_variable (void)
|
||||
/* Skip over an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Skip over the remaining bytes */
|
||||
while (length > 0) {
|
||||
(void) read_1_byte();
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the marker stream until SOFn or EOI is seen;
|
||||
* copy data to output, but discard COM markers unless keep_COM is true.
|
||||
*/
|
||||
|
||||
static int
|
||||
scan_JPEG_header (int keep_COM)
|
||||
{
|
||||
int marker;
|
||||
|
||||
/* Expect SOI at start of file */
|
||||
if (first_marker() != M_SOI)
|
||||
ERREXIT("Expected SOI marker first");
|
||||
write_marker(M_SOI);
|
||||
|
||||
/* Scan miscellaneous markers until we reach SOFn. */
|
||||
for (;;) {
|
||||
marker = next_marker();
|
||||
switch (marker) {
|
||||
/* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
|
||||
* treated as SOFn. C4 in particular is actually DHT.
|
||||
*/
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
case M_SOF5: /* Differential sequential, Huffman */
|
||||
case M_SOF6: /* Differential progressive, Huffman */
|
||||
case M_SOF7: /* Differential lossless, Huffman */
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
case M_SOF13: /* Differential sequential, arithmetic */
|
||||
case M_SOF14: /* Differential progressive, arithmetic */
|
||||
case M_SOF15: /* Differential lossless, arithmetic */
|
||||
return marker;
|
||||
|
||||
case M_SOS: /* should not see compressed data before SOF */
|
||||
ERREXIT("SOS without prior SOFn");
|
||||
break;
|
||||
|
||||
case M_EOI: /* in case it's a tables-only JPEG stream */
|
||||
return marker;
|
||||
|
||||
case M_COM: /* Existing COM: conditionally discard */
|
||||
if (keep_COM) {
|
||||
write_marker(marker);
|
||||
copy_variable();
|
||||
} else {
|
||||
skip_variable();
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Anything else just gets copied */
|
||||
write_marker(marker);
|
||||
copy_variable(); /* we assume it has a parameter count... */
|
||||
break;
|
||||
}
|
||||
} /* end loop */
|
||||
}
|
||||
|
||||
|
||||
/* Command line parsing code */
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n");
|
||||
fprintf(stderr, "You can add to or replace any existing comment(s).\n");
|
||||
|
||||
fprintf(stderr, "Usage: %s [switches] ", progname);
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, "[inputfile]\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -replace Delete any existing comments\n");
|
||||
fprintf(stderr, " -comment \"text\" Insert comment with given text\n");
|
||||
fprintf(stderr, " -cfile name Read comment from named file\n");
|
||||
fprintf(stderr, "Notice that you must put quotes around the comment text\n");
|
||||
fprintf(stderr, "when you use -comment.\n");
|
||||
fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n");
|
||||
fprintf(stderr, "then the comment text is read from standard input.\n");
|
||||
fprintf(stderr, "It can be multiple lines, up to %u characters total.\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
#ifndef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "You must specify an input JPEG file name when supplying\n");
|
||||
fprintf(stderr, "comment text from standard input.\n");
|
||||
#endif
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
keymatch (char * arg, const char * keyword, int minchars)
|
||||
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
|
||||
/* keyword is the constant keyword (must be lower case already), */
|
||||
/* minchars is length of minimum legal abbreviation. */
|
||||
{
|
||||
register int ca, ck;
|
||||
register int nmatched = 0;
|
||||
|
||||
while ((ca = *arg++) != '\0') {
|
||||
if ((ck = *keyword++) == '\0')
|
||||
return 0; /* arg longer than keyword, no good */
|
||||
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||
ca = tolower(ca);
|
||||
if (ca != ck)
|
||||
return 0; /* no good */
|
||||
nmatched++; /* count matched characters */
|
||||
}
|
||||
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||
if (nmatched < minchars)
|
||||
return 0;
|
||||
return 1; /* A-OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
int keep_COM = 1;
|
||||
char * comment_arg = NULL;
|
||||
FILE * comment_file = NULL;
|
||||
unsigned int comment_length = 0;
|
||||
int marker;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "wrjpgcom"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Parse switches, if any */
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (arg[0] != '-')
|
||||
break; /* not switch, must be file name */
|
||||
arg++; /* advance over '-' */
|
||||
if (keymatch(arg, "replace", 1)) {
|
||||
keep_COM = 0;
|
||||
} else if (keymatch(arg, "cfile", 2)) {
|
||||
if (++argn >= argc) usage();
|
||||
if ((comment_file = fopen(argv[argn], "r")) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (keymatch(arg, "comment", 1)) {
|
||||
if (++argn >= argc) usage();
|
||||
comment_arg = argv[argn];
|
||||
/* If the comment text starts with '"', then we are probably running
|
||||
* under MS-DOG and must parse out the quoted string ourselves. Sigh.
|
||||
*/
|
||||
if (comment_arg[0] == '"') {
|
||||
comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
|
||||
if (comment_arg == NULL)
|
||||
ERREXIT("Insufficient memory");
|
||||
strcpy(comment_arg, argv[argn]+1);
|
||||
for (;;) {
|
||||
comment_length = (unsigned int) strlen(comment_arg);
|
||||
if (comment_length > 0 && comment_arg[comment_length-1] == '"') {
|
||||
comment_arg[comment_length-1] = '\0'; /* zap terminating quote */
|
||||
break;
|
||||
}
|
||||
if (++argn >= argc)
|
||||
ERREXIT("Missing ending quote mark");
|
||||
strcat(comment_arg, " ");
|
||||
strcat(comment_arg, argv[argn]);
|
||||
}
|
||||
}
|
||||
comment_length = (unsigned int) strlen(comment_arg);
|
||||
} else
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Cannot use both -comment and -cfile. */
|
||||
if (comment_arg != NULL && comment_file != NULL)
|
||||
usage();
|
||||
/* If there is neither -comment nor -cfile, we will read the comment text
|
||||
* from stdin; in this case there MUST be an input JPEG file name.
|
||||
*/
|
||||
if (comment_arg == NULL && comment_file == NULL && argn >= argc)
|
||||
usage();
|
||||
|
||||
/* Open the input file. */
|
||||
if (argn < argc) {
|
||||
if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default input file is stdin */
|
||||
#ifdef USE_SETMODE /* need to hack file mode? */
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
#endif
|
||||
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
|
||||
if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdin\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
infile = stdin;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
/* Must have explicit output file name */
|
||||
if (argn != argc-2) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
/* Unix style: expect zero or one file name */
|
||||
if (argn < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", progname);
|
||||
usage();
|
||||
}
|
||||
/* default output file is stdout */
|
||||
#ifdef USE_SETMODE /* need to hack file mode? */
|
||||
setmode(fileno(stdout), O_BINARY);
|
||||
#endif
|
||||
#ifdef USE_FDOPEN /* need to re-open in binary mode? */
|
||||
if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdout\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
outfile = stdout;
|
||||
#endif
|
||||
#endif /* TWO_FILE_COMMANDLINE */
|
||||
|
||||
/* Collect comment text from comment_file or stdin, if necessary */
|
||||
if (comment_arg == NULL) {
|
||||
FILE * src_file;
|
||||
int c;
|
||||
|
||||
comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
|
||||
if (comment_arg == NULL)
|
||||
ERREXIT("Insufficient memory");
|
||||
comment_length = 0;
|
||||
src_file = (comment_file != NULL ? comment_file : stdin);
|
||||
while ((c = getc(src_file)) != EOF) {
|
||||
if (comment_length >= (unsigned int) MAX_COM_LENGTH) {
|
||||
fprintf(stderr, "Comment text may not exceed %u bytes\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
comment_arg[comment_length++] = (char) c;
|
||||
}
|
||||
if (comment_file != NULL)
|
||||
fclose(comment_file);
|
||||
}
|
||||
|
||||
/* Copy JPEG headers until SOFn marker;
|
||||
* we will insert the new comment marker just before SOFn.
|
||||
* This (a) causes the new comment to appear after, rather than before,
|
||||
* existing comments; and (b) ensures that comments come after any JFIF
|
||||
* or JFXX markers, as required by the JFIF specification.
|
||||
*/
|
||||
marker = scan_JPEG_header(keep_COM);
|
||||
/* Insert the new COM marker, but only if nonempty text has been supplied */
|
||||
if (comment_length > 0) {
|
||||
write_marker(M_COM);
|
||||
write_2_bytes(comment_length + 2);
|
||||
while (comment_length > 0) {
|
||||
write_1_byte(*comment_arg++);
|
||||
comment_length--;
|
||||
}
|
||||
}
|
||||
/* Duplicate the remainder of the source file.
|
||||
* Note that any COM markers occuring after SOF will not be touched.
|
||||
*/
|
||||
write_marker(marker);
|
||||
copy_rest_of_file();
|
||||
|
||||
/* All done. */
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
305
wrrle.c
Normal file
305
wrrle.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* wrrle.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 routines to write output images in RLE format.
|
||||
* The Utah Raster Toolkit library is required (version 3.1 or later).
|
||||
*
|
||||
* These routines may need modification for non-Unix environments or
|
||||
* specialized applications. As they stand, they assume output to
|
||||
* an ordinary stdio stream.
|
||||
*
|
||||
* Based on code contributed by Mike Lijewski,
|
||||
* with updates from Robert Hutchinson.
|
||||
*/
|
||||
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
|
||||
#ifdef RLE_SUPPORTED
|
||||
|
||||
/* rle.h is provided by the Utah Raster Toolkit. */
|
||||
|
||||
#include <rle.h>
|
||||
|
||||
/*
|
||||
* We assume that JSAMPLE has the same representation as rle_pixel,
|
||||
* to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE != 8
|
||||
Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Since RLE stores scanlines bottom-to-top, we have to invert the image
|
||||
* from JPEG's top-to-bottom order. To do this, we save the outgoing data
|
||||
* in a virtual array during put_pixel_row calls, then actually emit the
|
||||
* RLE file during finish_output.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* For now, if we emit an RLE color map then it is always 256 entries long,
|
||||
* though not all of the entries need be used.
|
||||
*/
|
||||
|
||||
#define CMAPBITS 8
|
||||
#define CMAPLENGTH (1<<(CMAPBITS))
|
||||
|
||||
typedef struct {
|
||||
struct djpeg_dest_struct pub; /* public fields */
|
||||
|
||||
jvirt_sarray_ptr image; /* virtual array to store the output image */
|
||||
rle_map *colormap; /* RLE-style color map, or NULL if none */
|
||||
rle_pixel **rle_row; /* To pass rows to rle_putrow() */
|
||||
|
||||
} rle_dest_struct;
|
||||
|
||||
typedef rle_dest_struct * rle_dest_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(void) rle_put_pixel_rows
|
||||
JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
JDIMENSION rows_supplied));
|
||||
|
||||
|
||||
/*
|
||||
* Write the file header.
|
||||
*
|
||||
* In this module it's easier to wait till finish_output to write anything.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
|
||||
{
|
||||
rle_dest_ptr dest = (rle_dest_ptr) dinfo;
|
||||
size_t cmapsize;
|
||||
int i, ci;
|
||||
#ifdef PROGRESS_REPORT
|
||||
cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure the image can be stored in RLE format.
|
||||
*
|
||||
* - RLE stores image dimensions as *signed* 16 bit integers. JPEG
|
||||
* uses unsigned, so we have to check the width.
|
||||
*
|
||||
* - Colorspace is expected to be grayscale or RGB.
|
||||
*
|
||||
* - The number of channels (components) is expected to be 1 (grayscale/
|
||||
* pseudocolor) or 3 (truecolor/directcolor).
|
||||
* (could be 2 or 4 if using an alpha channel, but we aren't)
|
||||
*/
|
||||
|
||||
if (cinfo->output_width > 32767 || cinfo->output_height > 32767)
|
||||
ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width,
|
||||
cinfo->output_height);
|
||||
|
||||
if (cinfo->out_color_space != JCS_GRAYSCALE &&
|
||||
cinfo->out_color_space != JCS_RGB)
|
||||
ERREXIT(cinfo, JERR_RLE_COLORSPACE);
|
||||
|
||||
if (cinfo->output_components != 1 && cinfo->output_components != 3)
|
||||
ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components);
|
||||
|
||||
/* Convert colormap, if any, to RLE format. */
|
||||
|
||||
dest->colormap = NULL;
|
||||
|
||||
if (cinfo->quantize_colors) {
|
||||
/* Allocate storage for RLE-style cmap, zero any extra entries */
|
||||
cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map);
|
||||
dest->colormap = (rle_map *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize);
|
||||
MEMZERO(dest->colormap, cmapsize);
|
||||
|
||||
/* Save away data in RLE format --- note 8-bit left shift! */
|
||||
/* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
|
||||
for (ci = 0; ci < cinfo->out_color_components; ci++) {
|
||||
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
||||
dest->colormap[ci * CMAPLENGTH + i] =
|
||||
GETJSAMPLE(cinfo->colormap[ci][i]) << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the output buffer to the first row */
|
||||
dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE);
|
||||
dest->pub.buffer_height = 1;
|
||||
|
||||
dest->pub.put_pixel_rows = rle_put_pixel_rows;
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->total_extra_passes++; /* count file writing as separate pass */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write some pixel data.
|
||||
*
|
||||
* This routine just saves the data away in a virtual array.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
|
||||
JDIMENSION rows_supplied)
|
||||
{
|
||||
rle_dest_ptr dest = (rle_dest_ptr) dinfo;
|
||||
|
||||
if (cinfo->output_scanline < cinfo->output_height) {
|
||||
dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, dest->image,
|
||||
cinfo->output_scanline, (JDIMENSION) 1, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish up at the end of the file.
|
||||
*
|
||||
* Here is where we really output the RLE file.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
|
||||
{
|
||||
rle_dest_ptr dest = (rle_dest_ptr) dinfo;
|
||||
rle_hdr header; /* Output file information */
|
||||
rle_pixel **rle_row, *red, *green, *blue;
|
||||
JSAMPROW output_row;
|
||||
char cmapcomment[80];
|
||||
int row, col;
|
||||
int ci;
|
||||
#ifdef PROGRESS_REPORT
|
||||
cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
|
||||
#endif
|
||||
|
||||
/* Initialize the header info */
|
||||
header = *rle_hdr_init(NULL);
|
||||
header.rle_file = dest->pub.output_file;
|
||||
header.xmin = 0;
|
||||
header.xmax = cinfo->output_width - 1;
|
||||
header.ymin = 0;
|
||||
header.ymax = cinfo->output_height - 1;
|
||||
header.alpha = 0;
|
||||
header.ncolors = cinfo->output_components;
|
||||
for (ci = 0; ci < cinfo->output_components; ci++) {
|
||||
RLE_SET_BIT(header, ci);
|
||||
}
|
||||
if (cinfo->quantize_colors) {
|
||||
header.ncmap = cinfo->out_color_components;
|
||||
header.cmaplen = CMAPBITS;
|
||||
header.cmap = dest->colormap;
|
||||
/* Add a comment to the output image with the true colormap length. */
|
||||
sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors);
|
||||
rle_putcom(cmapcomment, &header);
|
||||
}
|
||||
|
||||
/* Emit the RLE header and color map (if any) */
|
||||
rle_put_setup(&header);
|
||||
|
||||
/* Now output the RLE data from our virtual array.
|
||||
* We assume here that (a) rle_pixel is represented the same as JSAMPLE,
|
||||
* and (b) we are not on a machine where FAR pointers differ from regular.
|
||||
*/
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_limit = cinfo->output_height;
|
||||
progress->pub.pass_counter = 0;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cinfo->output_components == 1) {
|
||||
for (row = cinfo->output_height-1; row >= 0; row--) {
|
||||
rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, dest->image,
|
||||
(JDIMENSION) row, (JDIMENSION) 1, FALSE);
|
||||
rle_putrow(rle_row, (int) cinfo->output_width, &header);
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_counter++;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
for (row = cinfo->output_height-1; row >= 0; row--) {
|
||||
rle_row = (rle_pixel **) dest->rle_row;
|
||||
output_row = * (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, dest->image,
|
||||
(JDIMENSION) row, (JDIMENSION) 1, FALSE);
|
||||
red = rle_row[0];
|
||||
green = rle_row[1];
|
||||
blue = rle_row[2];
|
||||
for (col = cinfo->output_width; col > 0; col--) {
|
||||
*red++ = GETJSAMPLE(*output_row++);
|
||||
*green++ = GETJSAMPLE(*output_row++);
|
||||
*blue++ = GETJSAMPLE(*output_row++);
|
||||
}
|
||||
rle_putrow(rle_row, (int) cinfo->output_width, &header);
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL) {
|
||||
progress->pub.pass_counter++;
|
||||
(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
if (progress != NULL)
|
||||
progress->completed_extra_passes++;
|
||||
#endif
|
||||
|
||||
/* Emit file trailer */
|
||||
rle_puteof(&header);
|
||||
fflush(dest->pub.output_file);
|
||||
if (ferror(dest->pub.output_file))
|
||||
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The module selection routine for RLE format output.
|
||||
*/
|
||||
|
||||
GLOBAL(djpeg_dest_ptr)
|
||||
jinit_write_rle (j_decompress_ptr cinfo)
|
||||
{
|
||||
rle_dest_ptr dest;
|
||||
|
||||
/* Create module interface object, fill in method pointers */
|
||||
dest = (rle_dest_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(rle_dest_struct));
|
||||
dest->pub.start_output = start_output_rle;
|
||||
dest->pub.finish_output = finish_output_rle;
|
||||
|
||||
/* Calculate output image dimensions so we can allocate space */
|
||||
jpeg_calc_output_dimensions(cinfo);
|
||||
|
||||
/* Allocate a work array for output to the RLE library. */
|
||||
dest->rle_row = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
cinfo->output_width, (JDIMENSION) cinfo->output_components);
|
||||
|
||||
/* Allocate a virtual array to hold the image. */
|
||||
dest->image = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) (cinfo->output_width * cinfo->output_components),
|
||||
cinfo->output_height, (JDIMENSION) 1);
|
||||
|
||||
return (djpeg_dest_ptr) dest;
|
||||
}
|
||||
|
||||
#endif /* RLE_SUPPORTED */
|
||||
Reference in New Issue
Block a user