Clean up the lossless JPEG feature
- Rename jpeg_simple_lossless() to jpeg_enable_lossless() and modify the
function so that it stores the lossless parameters directly in the Ss
and Al fields of jpeg_compress_struct rather than using a scan script.
- Move the cjpeg -lossless switch into "Switches for advanced users".
- Document the libjpeg API and run-time features that are unavailable in
lossless mode, and ensure that all parameters, functions, and switches
related to unavailable features are ignored or generate errors in
lossless mode.
- Defer any action that depends on whether lossless mode is enabled
until jpeg_start_compress()/jpeg_start_decompress() is called.
- Document the purpose of the point transform value.
- "Codec" stands for coder/decoder, so it is a bit awkward to say
"lossless compression codec" and "lossless decompression codec".
Use "lossless compressor" and "lossless decompressor" instead.
- Restore backward API/ABI compatibility with libjpeg v6b:
* Move the new 'lossless' field from the exposed jpeg_compress_struct
and jpeg_decompress_struct structures into the opaque
jpeg_comp_master and jpeg_decomp_master structures, and allocate the
master structures in the body of jpeg_create_compress() and
jpeg_create_decompress().
* Remove the new 'process' field from jpeg_compress_struct and
jpeg_decompress_struct and replace it with the old
'progressive_mode' field and the new 'lossless' field.
* Remove the new 'data_unit' field from jpeg_compress_struct and
jpeg_decompress_struct and replace it with a locally-computed
data unit variable.
* Restore the names of macros and fields that refer to DCT blocks, and
document that they have a different meaning in lossless mode. (Most
of them aren't very meaningful in lossless mode anyhow.)
* Remove the new alloc_darray() method from jpeg_memory_mgr and
replace it with an internal macro that wraps the alloc_sarray()
method.
* Move the JDIFF* data types from jpeglib.h and jmorecfg.h into
jpegint.h.
* Remove the new 'codec' field from jpeg_compress_struct and
jpeg_decompress_struct and instead reuse the existing internal
coefficient control, forward/inverse DCT, and entropy
encoding/decoding structures for lossless compression/decompression.
* Repurpose existing error codes rather than introducing new ones.
(The new JERR_BAD_RESTART and JWRN_MUST_DOWNSCALE codes remain,
although JWRN_MUST_DOWNSCALE will probably be removed in
libjpeg-turbo, since we have a different way of handling multiple
data precisions.)
- Automatically enable lossless mode when a scan script with parameters
that are only valid for lossless mode is detected, and document the
use of scan scripts to generate lossless JPEG images.
- Move the sequential and shared Huffman routines back into jchuff.c and
jdhuff.c, and document that those routines are shared with jclhuff.c
and jdlhuff.c as well as with jcphuff.c and jdphuff.c.
- Move MAX_DIFF_BITS from jchuff.h into jclhuff.c, the only place where
it is used.
- Move the predictor and scaler code into jclossls.c and jdlossls.c.
- Streamline register usage in the [un]differencers (inspired by similar
optimizations in the color [de]converters.)
- Restructure the logic in a few places to reduce duplicated code.
- Ensure that all lossless-specific code is guarded by
C_LOSSLESS_SUPPORTED or D_LOSSLESS_SUPPORTED and that the library can
be built successfully if either or both of those macros is undefined.
- Remove all short forms of external names introduced by the lossless
JPEG patch. (These will not be needed by libjpeg-turbo, so there is
no use cleaning them up.)
- Various wordsmithing, formatting, and punctuation tweaks
- Eliminate various compiler warnings.
This commit is contained in:
8
README
8
README
@@ -74,10 +74,10 @@ remarkably high compression levels are possible if you can tolerate a
|
||||
low-quality image. For more details, see the references, or just experiment
|
||||
with various compression settings.
|
||||
|
||||
This software implements JPEG baseline, extended-sequential, progressive
|
||||
and lossless compression processes. Provision is made for supporting all
|
||||
variants of these processes, although some uncommon parameter settings aren't
|
||||
implemented yet. For legal reasons, we are not distributing code for the
|
||||
This software implements JPEG baseline, extended-sequential, progressive, and
|
||||
lossless compression processes. Provision is made for supporting all variants
|
||||
of these processes, although some uncommon parameter settings aren't
|
||||
implemented yet. For legal reasons, we are not distributing code for the
|
||||
arithmetic-coding variants of JPEG; see LEGAL ISSUES. We have made no
|
||||
provision for supporting the hierarchical processes defined in the standard.
|
||||
|
||||
|
||||
5
TODO
5
TODO
@@ -6,8 +6,3 @@ List of things to complete for lossless codec:
|
||||
|
||||
* How to check BITS_PER_JSAMPLE for lossy mode (ie, 16-bit data)? -
|
||||
see jdinput.c.
|
||||
|
||||
* Check comment blocks for errors/changes.
|
||||
|
||||
* Review new filenames. Try to avoid filename conflicts with possible JPEG-LS
|
||||
codec.
|
||||
|
||||
5
cdjpeg.h
5
cdjpeg.h
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* cdjpeg.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains common declarations for the sample applications
|
||||
@@ -137,7 +135,6 @@ EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
|
||||
EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
|
||||
EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
|
||||
EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));
|
||||
EXTERN(boolean) set_simple_lossless JPP((j_compress_ptr cinfo, char *arg));
|
||||
|
||||
/* djpeg support routines (in rdcolmap.c) */
|
||||
|
||||
|
||||
50
cjpeg.1
50
cjpeg.1
@@ -1,4 +1,4 @@
|
||||
.TH CJPEG 1 "27 April 1999"
|
||||
.TH CJPEG 1 "11 November 2022"
|
||||
.SH NAME
|
||||
cjpeg \- compress an image file to a JPEG file
|
||||
.SH SYNOPSIS
|
||||
@@ -62,13 +62,6 @@ decompression are unaffected by
|
||||
.B \-progressive
|
||||
Create progressive JPEG file (see below).
|
||||
.TP
|
||||
.BI \-lossless " psv[,Pt]"
|
||||
Create a lossless JPEG file using the specified predictor selection value (1-7)
|
||||
and optional point transform.
|
||||
.B Caution:
|
||||
lossless JPEG is not widely implemented, so many decoders will be
|
||||
unable to view a lossless JPEG file at all.
|
||||
.TP
|
||||
.B \-targa
|
||||
Input file is Targa format. Targa files that contain an "identification"
|
||||
field will not be automatically recognized by
|
||||
@@ -130,6 +123,43 @@ unable to view a progressive JPEG file at all.
|
||||
.PP
|
||||
Switches for advanced users:
|
||||
.TP
|
||||
.BI \-lossless " psv[,Pt]"
|
||||
Create a lossless JPEG file using the specified predictor selection value
|
||||
(1 through 7) and optional point transform (0 through
|
||||
.nh
|
||||
.I precision
|
||||
.hy
|
||||
- 1, where
|
||||
.nh
|
||||
.I precision
|
||||
.hy
|
||||
is the JPEG data precision in bits). A point transform value of 0 (the
|
||||
default) is necessary in order to create a fully lossless JPEG file. (A
|
||||
non-zero point transform value right-shifts the input samples by the specified
|
||||
number of bits, which is effectively a form of lossy color quantization.)
|
||||
.B Caution:
|
||||
lossless JPEG is not yet widely implemented, so many decoders will be unable to
|
||||
view a lossless JPEG file at all. Note that the following features will be
|
||||
unavailable when compressing or decompressing a lossless JPEG file:
|
||||
.IP
|
||||
- Quality/quantization table selection
|
||||
.IP
|
||||
- Color conversion (the JPEG image will use the same color space as the input
|
||||
image)
|
||||
.IP
|
||||
- DCT/IDCT algorithm selection
|
||||
.IP
|
||||
- Smoothing
|
||||
.IP
|
||||
- Downsampling/upsampling
|
||||
.IP
|
||||
- IDCT scaling
|
||||
.IP
|
||||
- Transformations using
|
||||
.B jpegtran
|
||||
.IP
|
||||
Any switches used to enable or configure those features will be ignored.
|
||||
.TP
|
||||
.B \-dct int
|
||||
Use integer DCT method (default).
|
||||
.TP
|
||||
@@ -145,8 +175,8 @@ machines, while the integer methods should give the same results everywhere.
|
||||
The fast integer method is much less accurate than the other two.
|
||||
.TP
|
||||
.BI \-restart " N"
|
||||
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
|
||||
attached to the number.
|
||||
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks (samples in
|
||||
lossless mode) if "B" is attached to the number.
|
||||
.B \-restart 0
|
||||
(the default) means no restart markers.
|
||||
.TP
|
||||
|
||||
31
cjpeg.c
31
cjpeg.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a command-line user interface for the JPEG compressor.
|
||||
@@ -159,13 +160,13 @@ usage (void)
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
fprintf(stderr, " -progressive Create progressive JPEG file\n");
|
||||
#endif
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
|
||||
#endif
|
||||
#ifdef TARGA_SUPPORTED
|
||||
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
|
||||
#endif
|
||||
fprintf(stderr, "Switches for advanced users:\n");
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
|
||||
#endif
|
||||
#ifdef DCT_ISLOW_SUPPORTED
|
||||
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||
@@ -214,6 +215,9 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
int psv, pt = 0;
|
||||
#endif
|
||||
int quality; /* -quality parameter */
|
||||
int q_scale_factor; /* scaling percentage for -qtables */
|
||||
boolean force_baseline;
|
||||
@@ -222,7 +226,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
char * qslotsarg = NULL; /* saves -qslots parm if any */
|
||||
char * samplearg = NULL; /* saves -sample parm if any */
|
||||
char * scansarg = NULL; /* saves -scans parm if any */
|
||||
char * losslsarg = NULL; /* saves -lossless parm if any */
|
||||
|
||||
/* Set up default JPEG parameters. */
|
||||
/* Note that default -quality level need not, and does not,
|
||||
@@ -294,12 +297,20 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||
|
||||
} else if (keymatch(arg, "lossless", 1)) {
|
||||
/* Select simple lossless mode. */
|
||||
/* Enable lossless mode. */
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
char ch = ',', *ptr;
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
losslsarg = argv[argn];
|
||||
/* We must postpone execution until num_components is known. */
|
||||
if (sscanf(argv[argn], "%d%c", &psv, &ch) < 1 || ch != ',')
|
||||
usage();
|
||||
ptr = argv[argn];
|
||||
while (*ptr && *ptr++ != ',') /* advance to next segment of arg string */
|
||||
;
|
||||
if (*ptr)
|
||||
sscanf(ptr, "%d", &pt);
|
||||
jpeg_enable_lossless(cinfo, psv, pt);
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, lossless output was not compiled\n",
|
||||
progname);
|
||||
@@ -461,12 +472,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
jpeg_simple_progression(cinfo);
|
||||
#endif
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
if (losslsarg != NULL) /* process -lossless if it was present */
|
||||
if (! set_simple_lossless(cinfo, losslsarg))
|
||||
usage();
|
||||
#endif
|
||||
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (scansarg != NULL) /* process -scans if it was present */
|
||||
if (! read_scan_script(cinfo, scansarg))
|
||||
|
||||
26
filelist.doc
26
filelist.doc
@@ -1,9 +1,10 @@
|
||||
IJG JPEG LIBRARY: FILE LIST
|
||||
|
||||
This file was part of the Independent JPEG Group's software:
|
||||
Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
Lossless JPEG Modifications:
|
||||
Copyright (C) 1999, Ken Murchison.
|
||||
Copyright (C) 2022, D. R. Commander.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
|
||||
@@ -31,7 +32,6 @@ jinclude.h Central include file used by all IJG .c files to reference
|
||||
system include files.
|
||||
jpegint.h JPEG library's internal data structures.
|
||||
jlossls.h JPEG library's lossless codec data structures.
|
||||
jlossy.h JPEG library's lossy codec 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.
|
||||
@@ -68,30 +68,27 @@ 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).
|
||||
jchuff.c Codec-independent Huffman entropy encoding routines.
|
||||
jcprepct.c Preprocessor buffer controller.
|
||||
jccolor.c Color space conversion.
|
||||
jcsample.c Downsampling.
|
||||
jchuff.c Shared Huffman entropy encoding routines.
|
||||
jcmarker.c JPEG marker writing.
|
||||
jdatadst.c Data destination manager for stdio output.
|
||||
|
||||
Lossy (DCT) codec:
|
||||
|
||||
jlossy.c Lossy compressor proper.
|
||||
jccoefct.c Buffer controller for DCT coefficient buffer.
|
||||
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.
|
||||
jcshuff.c Huffman entropy coding for sequential JPEG.
|
||||
jchuff.c Huffman entropy coding for sequential JPEG.
|
||||
jcphuff.c Huffman entropy coding for progressive JPEG.
|
||||
|
||||
Lossless (spatial) codec:
|
||||
|
||||
jclossls.c Lossless compressor proper.
|
||||
jcdiffct.c Buffer controller for difference buffer.
|
||||
jcscale.c Point transformation.
|
||||
jcpred.c Sample predictor and differencer.
|
||||
jclossls.c Prediction, sample differencing, and point transform
|
||||
jclhuff.c Huffman entropy encoding for lossless JPEG.
|
||||
|
||||
Decompression side of the library:
|
||||
@@ -99,9 +96,9 @@ 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).
|
||||
jdhuff.c Codec-independent Huffman entropy decoding routines.
|
||||
jdpostct.c Postprocessor buffer controller.
|
||||
jdmarker.c JPEG marker reading.
|
||||
jdhuff.c Shared Huffman entropy decoding routines.
|
||||
jdsample.c Upsampling.
|
||||
jdcolor.c Color space conversion.
|
||||
jdmerge.c Merged upsampling/color conversion (faster, lower quality).
|
||||
@@ -112,9 +109,8 @@ jdatasrc.c Data source manager for stdio input.
|
||||
|
||||
Lossy (DCT) codec:
|
||||
|
||||
jdlossy.c Lossy decompressor proper.
|
||||
jdcoefct.c Buffer controller for DCT coefficient buffer.
|
||||
jdshuff.c Huffman entropy decoding for sequential JPEG.
|
||||
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.
|
||||
@@ -124,17 +120,15 @@ jidctred.c Inverse DCTs with reduced-size outputs.
|
||||
|
||||
Lossless (spatial) codec:
|
||||
|
||||
jdlossls.c Lossless decompressor proper.
|
||||
jddiffct.c Buffer controller for difference buffers.
|
||||
jddiffct.c Buffer controller for difference buffer.
|
||||
jdlossls.c Prediction, sample undifferencing, point transform, and sample
|
||||
scaling
|
||||
jdlhuff.c Huffman entropy decoding for lossless JPEG.
|
||||
jdpred.c Sample predictor and undifferencer.
|
||||
jdscale.c Point transformation, sample size scaling.
|
||||
|
||||
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.
|
||||
jcodec.c Codec-independent utility routines.
|
||||
jutils.c Miscellaneous utility routines.
|
||||
|
||||
jmemmgr.c relies on a system-dependent memory management module. The IJG
|
||||
|
||||
13
jcapimin.c
13
jcapimin.c
@@ -4,7 +4,7 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the compression half
|
||||
@@ -21,6 +21,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -79,6 +80,14 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
|
||||
|
||||
/* OK, I'm ready */
|
||||
cinfo->global_state = CSTATE_START;
|
||||
|
||||
/* The master struct is used to store extension parameters, so we allocate it
|
||||
* here.
|
||||
*/
|
||||
cinfo->master = (struct jpeg_comp_master *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(my_comp_master));
|
||||
MEMZERO(cinfo->master, SIZEOF(my_comp_master));
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +179,7 @@ jpeg_finish_compress (j_compress_ptr cinfo)
|
||||
/* We bypass the main controller and invoke coef controller directly;
|
||||
* all work is being done from the coefficient buffer.
|
||||
*/
|
||||
if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL))
|
||||
if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
|
||||
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||
}
|
||||
(*cinfo->master->finish_pass) (cinfo);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the compression half
|
||||
@@ -124,6 +124,9 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
|
||||
{
|
||||
JDIMENSION lines_per_iMCU_row;
|
||||
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if (cinfo->global_state != CSTATE_RAW_OK)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
if (cinfo->next_scanline >= cinfo->image_height) {
|
||||
@@ -147,12 +150,12 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
|
||||
(*cinfo->master->pass_startup) (cinfo);
|
||||
|
||||
/* Verify that at least one iMCU row has been passed. */
|
||||
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->data_unit;
|
||||
lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
|
||||
if (num_lines < lines_per_iMCU_row)
|
||||
ERREXIT(cinfo, JERR_BUFFER_SIZE);
|
||||
|
||||
/* Directly compress the row. */
|
||||
if (! (*cinfo->codec->compress_data) (cinfo, data)) {
|
||||
if (! (*cinfo->coef->compress_data) (cinfo, data)) {
|
||||
/* If compressor did not consume the whole row, suspend processing. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
81
jccoefct.c
81
jccoefct.c
@@ -2,20 +2,19 @@
|
||||
* jccoefct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the coefficient buffer controller for compression.
|
||||
* This controller is the top level of the JPEG compressor proper.
|
||||
* This controller is the top level of the lossy JPEG compressor proper.
|
||||
* The coefficient buffer lies between forward-DCT and entropy encoding steps.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
|
||||
|
||||
/* We use a full-image coefficient buffer when doing Huffman optimization,
|
||||
@@ -35,6 +34,8 @@
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_c_coef_controller pub; /* public fields */
|
||||
|
||||
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
@@ -42,20 +43,20 @@ typedef struct {
|
||||
|
||||
/* For single-pass compression, it's sufficient to buffer just one MCU
|
||||
* (although this may prove a bit slow in practice). We allocate a
|
||||
* workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for
|
||||
* each MCU constructed and sent. (On 80x86, the workspace is FAR even
|
||||
* though it's not really very big; this is to keep the module interfaces
|
||||
* unchanged when a large coefficient buffer is necessary.)
|
||||
* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
|
||||
* MCU constructed and sent. (On 80x86, the workspace is FAR even though
|
||||
* it's not really very big; this is to keep the module interfaces unchanged
|
||||
* when a large coefficient buffer is necessary.)
|
||||
* In multi-pass modes, this array points to the current MCU's blocks
|
||||
* within the virtual arrays.
|
||||
*/
|
||||
JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
|
||||
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
||||
} c_coef_controller;
|
||||
} my_coef_controller;
|
||||
|
||||
typedef c_coef_controller * c_coef_ptr;
|
||||
typedef my_coef_controller * my_coef_ptr;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
@@ -73,8 +74,7 @@ LOCAL(void)
|
||||
start_iMCU_row (j_compress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row */
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
@@ -101,8 +101,7 @@ start_iMCU_row (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
coef->iMCU_row_num = 0;
|
||||
start_iMCU_row(cinfo);
|
||||
@@ -111,18 +110,18 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
case JBUF_PASS_THRU:
|
||||
if (coef->whole_image[0] != NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
lossyc->pub.compress_data = compress_data;
|
||||
coef->pub.compress_data = compress_data;
|
||||
break;
|
||||
#ifdef FULL_COEF_BUFFER_SUPPORTED
|
||||
case JBUF_SAVE_AND_PASS:
|
||||
if (coef->whole_image[0] == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
lossyc->pub.compress_data = compress_first_pass;
|
||||
coef->pub.compress_data = compress_first_pass;
|
||||
break;
|
||||
case JBUF_CRANK_DEST:
|
||||
if (coef->whole_image[0] == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
lossyc->pub.compress_data = compress_output;
|
||||
coef->pub.compress_data = compress_output;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -145,8 +144,7 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
METHODDEF(boolean)
|
||||
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
@@ -178,10 +176,10 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||
if (coef->iMCU_row_num < last_iMCU_row ||
|
||||
yoffset+yindex < compptr->last_row_height) {
|
||||
(*lossyc->fdct_forward_DCT) (cinfo, compptr,
|
||||
input_buf[compptr->component_index],
|
||||
coef->MCU_buffer[blkn],
|
||||
ypos, xpos, (JDIMENSION) blockcnt);
|
||||
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
|
||||
input_buf[compptr->component_index],
|
||||
coef->MCU_buffer[blkn],
|
||||
ypos, xpos, (JDIMENSION) blockcnt);
|
||||
if (blockcnt < compptr->MCU_width) {
|
||||
/* Create some dummy blocks at the right edge of the image. */
|
||||
jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
|
||||
@@ -205,7 +203,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
/* Try to write the MCU. In event of a suspension failure, we will
|
||||
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
|
||||
*/
|
||||
if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->mcu_ctr = MCU_col_num;
|
||||
@@ -248,8 +246,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
METHODDEF(boolean)
|
||||
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION blocks_across, MCUs_across, MCUindex;
|
||||
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
|
||||
@@ -270,10 +267,10 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
block_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here, since may not be set! */
|
||||
block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
}
|
||||
blocks_across = compptr->width_in_data_units;
|
||||
blocks_across = compptr->width_in_blocks;
|
||||
h_samp_factor = compptr->h_samp_factor;
|
||||
/* Count number of dummy blocks to be added at the right margin. */
|
||||
ndummy = (int) (blocks_across % h_samp_factor);
|
||||
@@ -284,7 +281,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
*/
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
thisblockrow = buffer[block_row];
|
||||
(*lossyc->fdct_forward_DCT) (cinfo, compptr,
|
||||
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
|
||||
input_buf[ci], thisblockrow,
|
||||
(JDIMENSION) (block_row * DCTSIZE),
|
||||
(JDIMENSION) 0, blocks_across);
|
||||
@@ -345,8 +342,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
METHODDEF(boolean)
|
||||
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
int blkn, ci, xindex, yindex, yoffset;
|
||||
JDIMENSION start_col;
|
||||
@@ -384,7 +380,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
}
|
||||
}
|
||||
/* Try to write the MCU. */
|
||||
if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->mcu_ctr = MCU_col_num;
|
||||
@@ -410,14 +406,13 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
GLOBAL(void)
|
||||
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef;
|
||||
my_coef_ptr coef;
|
||||
|
||||
coef = (c_coef_ptr)
|
||||
coef = (my_coef_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(c_coef_controller));
|
||||
lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
|
||||
lossyc->coef_start_pass = start_pass_coef;
|
||||
SIZEOF(my_coef_controller));
|
||||
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
|
||||
coef->pub.start_pass = start_pass_coef;
|
||||
|
||||
/* Create the coefficient buffer. */
|
||||
if (need_full_buffer) {
|
||||
@@ -431,9 +426,9 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
@@ -447,8 +442,8 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
|
||||
buffer = (JBLOCKROW)
|
||||
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
|
||||
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
|
||||
coef->MCU_buffer[i] = buffer + i;
|
||||
}
|
||||
coef->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||
|
||||
24
jccolor.c
24
jccolor.c
@@ -1,8 +1,10 @@
|
||||
/*
|
||||
* jccolor.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains input colorspace conversion routines.
|
||||
@@ -391,9 +393,15 @@ jinit_color_converter (j_compress_ptr cinfo)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check num_components, set conversion method based on requested space */
|
||||
/* Check num_components, set conversion method based on requested space.
|
||||
* NOTE: We do not allow any lossy color conversion algorithms in lossless
|
||||
* mode.
|
||||
*/
|
||||
switch (cinfo->jpeg_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 1)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_GRAYSCALE)
|
||||
@@ -408,6 +416,9 @@ jinit_color_converter (j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_RGB:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
|
||||
@@ -417,6 +428,9 @@ jinit_color_converter (j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_YCbCr:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_RGB) {
|
||||
@@ -429,6 +443,9 @@ jinit_color_converter (j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_CMYK)
|
||||
@@ -438,6 +455,9 @@ jinit_color_converter (j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_YCCK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_CMYK) {
|
||||
|
||||
39
jcdctmgr.c
39
jcdctmgr.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* jcdctmgr.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the forward-DCT management logic.
|
||||
@@ -16,13 +14,14 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||
|
||||
|
||||
/* Private subobject for this module */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_forward_dct pub; /* public fields */
|
||||
|
||||
/* Pointer to the DCT routine actually in use */
|
||||
forward_DCT_method_ptr do_dct;
|
||||
|
||||
@@ -37,9 +36,9 @@ typedef struct {
|
||||
float_DCT_method_ptr do_float_dct;
|
||||
FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
|
||||
#endif
|
||||
} fdct_controller;
|
||||
} my_fdct_controller;
|
||||
|
||||
typedef fdct_controller * fdct_ptr;
|
||||
typedef my_fdct_controller * my_fdct_ptr;
|
||||
|
||||
|
||||
/*
|
||||
@@ -54,8 +53,7 @@ typedef fdct_controller * fdct_ptr;
|
||||
METHODDEF(void)
|
||||
start_pass_fdctmgr (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
|
||||
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||
int ci, qtblno, i;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL * qtbl;
|
||||
@@ -186,8 +184,7 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
/* This version is used for integer DCT implementations. */
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding it tightly. */
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
|
||||
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||
forward_DCT_method_ptr do_dct = fdct->do_dct;
|
||||
DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
|
||||
DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
|
||||
@@ -277,8 +274,7 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
/* This version is used for floating-point DCT implementations. */
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding it tightly. */
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
|
||||
my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
|
||||
float_DCT_method_ptr do_dct = fdct->do_float_dct;
|
||||
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
|
||||
FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
|
||||
@@ -348,32 +344,31 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
GLOBAL(void)
|
||||
jinit_forward_dct (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
fdct_ptr fdct;
|
||||
my_fdct_ptr fdct;
|
||||
int i;
|
||||
|
||||
fdct = (fdct_ptr)
|
||||
fdct = (my_fdct_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(fdct_controller));
|
||||
lossyc->fdct_private = (struct jpeg_forward_dct *) fdct;
|
||||
lossyc->fdct_start_pass = start_pass_fdctmgr;
|
||||
SIZEOF(my_fdct_controller));
|
||||
cinfo->fdct = (struct jpeg_forward_dct *) fdct;
|
||||
fdct->pub.start_pass = start_pass_fdctmgr;
|
||||
|
||||
switch (cinfo->dct_method) {
|
||||
#ifdef DCT_ISLOW_SUPPORTED
|
||||
case JDCT_ISLOW:
|
||||
lossyc->fdct_forward_DCT = forward_DCT;
|
||||
fdct->pub.forward_DCT = forward_DCT;
|
||||
fdct->do_dct = jpeg_fdct_islow;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_IFAST_SUPPORTED
|
||||
case JDCT_IFAST:
|
||||
lossyc->fdct_forward_DCT = forward_DCT;
|
||||
fdct->pub.forward_DCT = forward_DCT;
|
||||
fdct->do_dct = jpeg_fdct_ifast;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
case JDCT_FLOAT:
|
||||
lossyc->fdct_forward_DCT = forward_DCT_float;
|
||||
fdct->pub.forward_DCT = forward_DCT_float;
|
||||
fdct->do_float_dct = jpeg_fdct_float;
|
||||
break;
|
||||
#endif
|
||||
|
||||
158
jcdiffct.c
158
jcdiffct.c
@@ -2,15 +2,16 @@
|
||||
* jcdiffct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the difference buffer controller for compression.
|
||||
* This controller is the top level of the lossless JPEG compressor proper.
|
||||
* The difference buffer lies between prediction/differencing and entropy
|
||||
* encoding.
|
||||
* The difference buffer lies between the prediction/differencing and entropy
|
||||
* encoding steps.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
@@ -38,20 +39,22 @@
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_c_coef_controller pub; /* public fields */
|
||||
|
||||
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */
|
||||
JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point-transformed samples */
|
||||
JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */
|
||||
JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */
|
||||
|
||||
/* In multi-pass modes, we need a virtual sample array for each component. */
|
||||
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
|
||||
} c_diff_controller;
|
||||
} my_diff_controller;
|
||||
|
||||
typedef c_diff_controller * c_diff_ptr;
|
||||
typedef my_diff_controller * my_diff_ptr;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
@@ -69,8 +72,7 @@ LOCAL(void)
|
||||
start_iMCU_row (j_compress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row */
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
@@ -97,8 +99,15 @@ start_iMCU_row (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
|
||||
/* Because it is hitching a ride on the jpeg_forward_dct struct,
|
||||
* start_pass_lossless() will be called at the start of the initial pass.
|
||||
* This ensures that it will be called at the start of the Huffman
|
||||
* optimization and output passes as well.
|
||||
*/
|
||||
if (pass_mode == JBUF_CRANK_DEST)
|
||||
(*cinfo->fdct->start_pass) (cinfo);
|
||||
|
||||
diff->iMCU_row_num = 0;
|
||||
start_iMCU_row(cinfo);
|
||||
@@ -107,18 +116,18 @@ start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
case JBUF_PASS_THRU:
|
||||
if (diff->whole_image[0] != NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
losslsc->pub.compress_data = compress_data;
|
||||
diff->pub.compress_data = compress_data;
|
||||
break;
|
||||
#ifdef FULL_SAMP_BUFFER_SUPPORTED
|
||||
case JBUF_SAVE_AND_PASS:
|
||||
if (diff->whole_image[0] == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
losslsc->pub.compress_data = compress_first_pass;
|
||||
diff->pub.compress_data = compress_first_pass;
|
||||
break;
|
||||
case JBUF_CRANK_DEST:
|
||||
if (diff->whole_image[0] == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
losslsc->pub.compress_data = compress_output;
|
||||
diff->pub.compress_data = compress_output;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -143,13 +152,12 @@ start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
METHODDEF(boolean)
|
||||
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr) cinfo->fdct;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION MCU_count; /* number of MCUs encoded */
|
||||
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int comp, ci, yoffset, samp_row, samp_rows, samps_across;
|
||||
int ci, compi, yoffset, samp_row, samp_rows, samps_across;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Loop to write as much as one whole iMCU row */
|
||||
@@ -158,20 +166,20 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
|
||||
MCU_col_num = diff->mcu_ctr;
|
||||
|
||||
/* Scale and predict each scanline of the MCU-row separately.
|
||||
/* Scale and predict each scanline of the MCU row separately.
|
||||
*
|
||||
* Note: We only do this if we are at the start of a MCU-row, ie,
|
||||
* Note: We only do this if we are at the start of an MCU row, ie,
|
||||
* we don't want to reprocess a row suspended by the output.
|
||||
*/
|
||||
if (MCU_col_num == 0) {
|
||||
for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
|
||||
compptr = cinfo->cur_comp_info[comp];
|
||||
ci = compptr->component_index;
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
compi = compptr->component_index;
|
||||
if (diff->iMCU_row_num < last_iMCU_row)
|
||||
samp_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here, since may not be set! */
|
||||
samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
samp_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* Fill dummy difference rows at the bottom edge with zeros, which
|
||||
@@ -179,43 +187,39 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
*/
|
||||
for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
|
||||
samp_row++)
|
||||
MEMZERO(diff->diff_buf[ci][samp_row],
|
||||
jround_up((long) compptr->width_in_data_units,
|
||||
MEMZERO(diff->diff_buf[compi][samp_row],
|
||||
jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor) * SIZEOF(JDIFF));
|
||||
}
|
||||
}
|
||||
samps_across = compptr->width_in_data_units;
|
||||
samps_across = compptr->width_in_blocks;
|
||||
|
||||
for (samp_row = 0; samp_row < samp_rows; samp_row++) {
|
||||
(*losslsc->scaler_scale) (cinfo,
|
||||
input_buf[ci][samp_row],
|
||||
diff->cur_row[ci], samps_across);
|
||||
(*losslsc->predict_difference[ci]) (cinfo, ci,
|
||||
diff->cur_row[ci],
|
||||
diff->prev_row[ci],
|
||||
diff->diff_buf[ci][samp_row],
|
||||
samps_across);
|
||||
SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]);
|
||||
(*losslessc->scaler_scale) (cinfo,
|
||||
input_buf[compi][samp_row],
|
||||
diff->cur_row[compi],
|
||||
samps_across);
|
||||
(*losslessc->predict_difference[compi])
|
||||
(cinfo, compi, diff->cur_row[compi], diff->prev_row[compi],
|
||||
diff->diff_buf[compi][samp_row], samps_across);
|
||||
SWAP_ROWS(diff->cur_row[compi], diff->prev_row[compi]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to write the MCU-row (or remaining portion of suspended MCU-row). */
|
||||
/* Try to write the MCU row (or remaining portion of suspended MCU row). */
|
||||
MCU_count =
|
||||
(*losslsc->entropy_encode_mcus) (cinfo,
|
||||
diff->diff_buf, yoffset, MCU_col_num,
|
||||
cinfo->MCUs_per_row - MCU_col_num);
|
||||
(*cinfo->entropy->encode_mcus) (cinfo,
|
||||
diff->diff_buf, yoffset, MCU_col_num,
|
||||
cinfo->MCUs_per_row - MCU_col_num);
|
||||
if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
diff->MCU_vert_offset = yoffset;
|
||||
diff->mcu_ctr += MCU_col_num;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||
diff->mcu_ctr = 0;
|
||||
}
|
||||
|
||||
/* Completed the iMCU row, advance counters for next one */
|
||||
diff->iMCU_row_num++;
|
||||
start_iMCU_row(cinfo);
|
||||
@@ -246,18 +250,17 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
METHODDEF(boolean)
|
||||
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION samps_across;
|
||||
int ci, samp_row, samp_rows;
|
||||
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||
JSAMPARRAY buffer;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Align the virtual buffers for this component. */
|
||||
buffer[ci] = (*cinfo->mem->access_virt_sarray)
|
||||
/* Align the virtual buffer for this component. */
|
||||
buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, diff->whole_image[ci],
|
||||
diff->iMCU_row_num * compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
@@ -267,21 +270,20 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
samp_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here, since may not be set! */
|
||||
samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
samp_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
|
||||
}
|
||||
samps_across = compptr->width_in_data_units;
|
||||
samps_across = compptr->width_in_blocks;
|
||||
|
||||
/* Perform point transform scaling and prediction/differencing for all
|
||||
* non-dummy rows in this iMCU row. Each call on these functions
|
||||
* process a complete row of samples.
|
||||
* processes a complete row of samples.
|
||||
*/
|
||||
for (samp_row = 0; samp_row < samp_rows; samp_row++) {
|
||||
MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row],
|
||||
MEMCOPY(buffer[samp_row], input_buf[ci][samp_row],
|
||||
samps_across * SIZEOF(JSAMPLE));
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: compress_output will increment iMCU_row_num if successful.
|
||||
* A suspension return will result in redoing all the work above next time.
|
||||
*/
|
||||
@@ -304,23 +306,19 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
METHODDEF(boolean)
|
||||
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION MCU_count; /* number of MCUs encoded */
|
||||
int comp, ci, yoffset;
|
||||
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
int ci;
|
||||
JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Align the virtual buffers for the components used in this scan.
|
||||
* NB: during first pass, this is safe only because the buffers will
|
||||
* already be aligned properly, so jmemmgr.c won't need to do any I/O.
|
||||
*/
|
||||
for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
|
||||
compptr = cinfo->cur_comp_info[comp];
|
||||
ci = compptr->component_index;
|
||||
buffer[ci] = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, diff->whole_image[ci],
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
buffer[compptr->component_index] = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, diff->whole_image[compptr->component_index],
|
||||
diff->iMCU_row_num * compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
@@ -338,28 +336,27 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
GLOBAL(void)
|
||||
jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_diff_ptr diff;
|
||||
my_diff_ptr diff;
|
||||
int ci, row;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
diff = (c_diff_ptr)
|
||||
diff = (my_diff_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(c_diff_controller));
|
||||
losslsc->diff_private = (void *) diff;
|
||||
losslsc->diff_start_pass = start_pass_diff;
|
||||
SIZEOF(my_diff_controller));
|
||||
cinfo->coef = (struct jpeg_c_coef_controller *) diff;
|
||||
diff->pub.start_pass = start_pass_diff;
|
||||
|
||||
/* Create the prediction row buffers. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) 1);
|
||||
diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) 1);
|
||||
}
|
||||
@@ -367,11 +364,11 @@ jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
/* Create the difference buffer. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
diff->diff_buf[ci] =
|
||||
ALLOC_DARRAY(JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
/* Prefill difference rows with zeros. We do this because only actual
|
||||
* data is placed in the buffers during prediction/differencing, leaving
|
||||
* any dummy differences at the right edge as zeros, which will encode
|
||||
@@ -379,7 +376,7 @@ jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
*/
|
||||
for (row = 0; row < compptr->v_samp_factor; row++)
|
||||
MEMZERO(diff->diff_buf[ci][row],
|
||||
jround_up((long) compptr->width_in_data_units,
|
||||
jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor) * SIZEOF(JDIFF));
|
||||
}
|
||||
|
||||
@@ -388,16 +385,13 @@ jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
#ifdef FULL_SAMP_BUFFER_SUPPORTED
|
||||
/* Allocate a full-image virtual array for each component, */
|
||||
/* padded to a multiple of samp_factor differences in each direction. */
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
|
||||
653
jchuff.c
653
jchuff.c
@@ -2,13 +2,19 @@
|
||||
* jchuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines which are shared
|
||||
* by the sequential, progressive and lossless decoders.
|
||||
* This file contains Huffman entropy encoding routines.
|
||||
*
|
||||
* Much of the complexity here has to do with supporting output suspension.
|
||||
* If the data destination module demands suspension, we want to be able to
|
||||
* back up to the start of the current MCU. To do this, we copy state
|
||||
* variables into local working storage, and update them back to the
|
||||
* permanent JPEG objects only upon successful completion of an MCU.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
@@ -17,9 +23,159 @@
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
|
||||
|
||||
/* Expanded entropy encoder object for Huffman encoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
INT32 put_buffer; /* current bit-accumulation buffer */
|
||||
int put_bits; /* # of bits now in it */
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest,src) \
|
||||
((dest).put_buffer = (src).put_buffer, \
|
||||
(dest).put_bits = (src).put_bits, \
|
||||
(dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_encoder pub; /* public fields */
|
||||
|
||||
savable_state saved; /* Bit buffer & DC state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||
int next_restart_num; /* next restart number to write (0-7) */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||
c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
|
||||
long * dc_count_ptrs[NUM_HUFF_TBLS];
|
||||
long * ac_count_ptrs[NUM_HUFF_TBLS];
|
||||
#endif
|
||||
} huff_entropy_encoder;
|
||||
|
||||
typedef huff_entropy_encoder * huff_entropy_ptr;
|
||||
|
||||
/* Working state while writing an MCU.
|
||||
* This struct contains all the fields that are needed by subroutines.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
JOCTET * next_output_byte; /* => next byte to write in buffer */
|
||||
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
|
||||
savable_state cur; /* Current bit buffer & DC state */
|
||||
j_compress_ptr cinfo; /* dump_buffer needs access to this */
|
||||
} working_state;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
* If gather_statistics is TRUE, we do not output anything during the scan,
|
||||
* just count the Huffman symbols used and generate Huffman code tables.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
if (gather_statistics) {
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
entropy->pub.encode_mcu = encode_mcu_gather;
|
||||
entropy->pub.finish_pass = finish_pass_gather;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
entropy->pub.encode_mcu = encode_mcu_huff;
|
||||
entropy->pub.finish_pass = finish_pass_huff;
|
||||
}
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
if (gather_statistics) {
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
/* Check for invalid table indexes */
|
||||
/* (make_c_derived_tbl does this in the other path) */
|
||||
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
|
||||
if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
|
||||
/* Allocate and zero the statistics tables */
|
||||
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
|
||||
if (entropy->dc_count_ptrs[dctbl] == NULL)
|
||||
entropy->dc_count_ptrs[dctbl] = (long *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
257 * SIZEOF(long));
|
||||
MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
|
||||
if (entropy->ac_count_ptrs[actbl] == NULL)
|
||||
entropy->ac_count_ptrs[actbl] = (long *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
257 * SIZEOF(long));
|
||||
MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
|
||||
#endif
|
||||
} else {
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for a table, but it's not expensive */
|
||||
jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
|
||||
& entropy->dc_derived_tbls[dctbl]);
|
||||
jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
|
||||
& entropy->ac_derived_tbls[actbl]);
|
||||
}
|
||||
/* Initialize DC predictions to 0 */
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Initialize bit buffer to empty */
|
||||
entropy->saved.put_buffer = 0;
|
||||
entropy->saved.put_bits = 0;
|
||||
|
||||
/* Initialize restart stuff */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
entropy->next_restart_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute the derived values for a Huffman table.
|
||||
* This routine also performs some validation checks on the table.
|
||||
*
|
||||
* Note this is also used by jcphuff.c and jclhuff.c.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
@@ -94,12 +250,12 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
|
||||
*/
|
||||
MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
|
||||
|
||||
/* This is also a convenient place to check for out-of-range
|
||||
* and duplicated VAL entries. We allow 0..255 for AC symbols
|
||||
* but only 0..16 for DC. (We could constrain them further
|
||||
* based on data depth and mode, but this seems enough.)
|
||||
/* This is also a convenient place to check for out-of-range and duplicated
|
||||
* VAL entries. We allow 0..255 for AC symbols but only 0..15 for DC in
|
||||
* lossy mode and 0..16 for DC in lossless mode. (We could constrain them
|
||||
* further based on data depth and mode, but this seems enough.)
|
||||
*/
|
||||
maxsymbol = isDC ? 16 : 255;
|
||||
maxsymbol = isDC ? (cinfo->master->lossless ? 16 : 15) : 255;
|
||||
|
||||
for (p = 0; p < lastp; p++) {
|
||||
i = htbl->huffval[p];
|
||||
@@ -111,8 +267,418 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
|
||||
}
|
||||
|
||||
|
||||
/* Outputting bytes to the file */
|
||||
|
||||
/* Emit a byte, taking 'action' if must suspend. */
|
||||
#define emit_byte(state,val,action) \
|
||||
{ *(state)->next_output_byte++ = (JOCTET) (val); \
|
||||
if (--(state)->free_in_buffer == 0) \
|
||||
if (! dump_buffer(state)) \
|
||||
{ action; } }
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
dump_buffer (working_state * state)
|
||||
/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
|
||||
{
|
||||
struct jpeg_destination_mgr * dest = state->cinfo->dest;
|
||||
|
||||
if (! (*dest->empty_output_buffer) (state->cinfo))
|
||||
return FALSE;
|
||||
/* After a successful buffer dump, must reset buffer pointers */
|
||||
state->next_output_byte = dest->next_output_byte;
|
||||
state->free_in_buffer = dest->free_in_buffer;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Outputting bits to the file */
|
||||
|
||||
/* Only the right 24 bits of put_buffer are used; the valid bits are
|
||||
* left-justified in this part. At most 16 bits can be passed to emit_bits
|
||||
* in one call, and we never retain more than 7 bits in put_buffer
|
||||
* between calls, so 24 bits are sufficient.
|
||||
*/
|
||||
|
||||
INLINE
|
||||
LOCAL(boolean)
|
||||
emit_bits (working_state * state, unsigned int code, int size)
|
||||
/* Emit some bits; return TRUE if successful, FALSE if must suspend */
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding tightly. */
|
||||
register INT32 put_buffer = (INT32) code;
|
||||
register int put_bits = state->cur.put_bits;
|
||||
|
||||
/* if size is 0, caller used an invalid Huffman table entry */
|
||||
if (size == 0)
|
||||
ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
|
||||
|
||||
put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
|
||||
|
||||
put_bits += size; /* new number of bits in buffer */
|
||||
|
||||
put_buffer <<= 24 - put_bits; /* align incoming bits */
|
||||
|
||||
put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
|
||||
|
||||
while (put_bits >= 8) {
|
||||
int c = (int) ((put_buffer >> 16) & 0xFF);
|
||||
|
||||
emit_byte(state, c, return FALSE);
|
||||
if (c == 0xFF) { /* need to stuff a zero byte? */
|
||||
emit_byte(state, 0, return FALSE);
|
||||
}
|
||||
put_buffer <<= 8;
|
||||
put_bits -= 8;
|
||||
}
|
||||
|
||||
state->cur.put_buffer = put_buffer; /* update state variables */
|
||||
state->cur.put_bits = put_bits;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
flush_bits (working_state * state)
|
||||
{
|
||||
if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
|
||||
return FALSE;
|
||||
state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
|
||||
state->cur.put_bits = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Encode a single block's worth of coefficients */
|
||||
|
||||
LOCAL(boolean)
|
||||
encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
|
||||
c_derived_tbl *dctbl, c_derived_tbl *actbl)
|
||||
{
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
register int k, r, i;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = temp2 = block[0] - last_dc_val;
|
||||
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (nbits) /* emit_bits rejects calls with size 0 */
|
||||
if (! emit_bits(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[jpeg_natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
|
||||
return FALSE;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
temp2 = temp;
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit Huffman symbol for run length / number of bits */
|
||||
i = (r << 4) + nbits;
|
||||
if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (! emit_bits(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emit a restart marker & resynchronize predictions.
|
||||
*/
|
||||
|
||||
LOCAL(boolean)
|
||||
emit_restart (working_state * state, int restart_num)
|
||||
{
|
||||
int ci;
|
||||
|
||||
if (! flush_bits(state))
|
||||
return FALSE;
|
||||
|
||||
emit_byte(state, 0xFF, return FALSE);
|
||||
emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
|
||||
state->cur.last_dc_val[ci] = 0;
|
||||
|
||||
/* The restart counter is not updated until we successfully write the MCU. */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode and output one MCU's worth of Huffman-compressed coefficients.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
working_state state;
|
||||
int blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Load up working state */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cinfo = cinfo;
|
||||
|
||||
/* Emit restart marker if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0)
|
||||
if (! emit_restart(&state, entropy->next_restart_num))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Encode the MCU data blocks */
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
if (! encode_one_block(&state,
|
||||
MCU_data[blkn][0], state.cur.last_dc_val[ci],
|
||||
entropy->dc_derived_tbls[compptr->dc_tbl_no],
|
||||
entropy->ac_derived_tbls[compptr->ac_tbl_no]))
|
||||
return FALSE;
|
||||
/* Update last_dc_val */
|
||||
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
|
||||
/* Update restart-interval state too */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0) {
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
entropy->next_restart_num++;
|
||||
entropy->next_restart_num &= 7;
|
||||
}
|
||||
entropy->restarts_to_go--;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_huff (j_compress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
working_state state;
|
||||
|
||||
/* Load up working state ... flush_bits needs it */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cinfo = cinfo;
|
||||
|
||||
/* Flush out the last data */
|
||||
if (! flush_bits(&state))
|
||||
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||
|
||||
/* Update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Huffman coding optimization.
|
||||
*
|
||||
* We first scan the supplied data and count the number of uses of each symbol
|
||||
* that is to be Huffman-coded. (This process MUST agree with the code above.)
|
||||
* Then we build a Huffman coding tree for the observed counts.
|
||||
* Symbols which are not needed at all for the particular image are not
|
||||
* assigned any code, which saves space in the DHT marker as well as in
|
||||
* the compressed data.
|
||||
*/
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
|
||||
/* Process a single block's worth of coefficients */
|
||||
|
||||
LOCAL(void)
|
||||
htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
|
||||
long dc_counts[], long ac_counts[])
|
||||
{
|
||||
register int temp;
|
||||
register int nbits;
|
||||
register int k, r;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = block[0] - last_dc_val;
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[nbits]++;
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[jpeg_natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
ac_counts[0xF0]++;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count Huffman symbol for run length / number of bits */
|
||||
ac_counts[(r << 4) + nbits]++;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
ac_counts[0]++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Trial-encode one MCU's worth of Huffman-compressed coefficients.
|
||||
* No data is actually output, so no suspension return is possible.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Take care of restart intervals if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0) {
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
/* Update restart state */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
entropy->restarts_to_go--;
|
||||
}
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
|
||||
entropy->dc_count_ptrs[compptr->dc_tbl_no],
|
||||
entropy->ac_count_ptrs[compptr->ac_tbl_no]);
|
||||
entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate the best Huffman code table for the given counts, fill htbl.
|
||||
* Note this is also used by jcphuff.c and jclhuff.c.
|
||||
*
|
||||
* The JPEG standard requires that no symbol be assigned a codeword of all
|
||||
* one bits (so that padding bits added at the end of a compressed segment
|
||||
@@ -273,3 +839,74 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
|
||||
/* Set sent_table FALSE so updated table will be written to JPEG file. */
|
||||
htbl->sent_table = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up a statistics-gathering pass and create the new Huffman tables.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_gather (j_compress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
JHUFF_TBL **htblptr;
|
||||
boolean did_dc[NUM_HUFF_TBLS];
|
||||
boolean did_ac[NUM_HUFF_TBLS];
|
||||
|
||||
/* It's important not to apply jpeg_gen_optimal_table more than once
|
||||
* per table, because it clobbers the input frequency counts!
|
||||
*/
|
||||
MEMZERO(did_dc, SIZEOF(did_dc));
|
||||
MEMZERO(did_ac, SIZEOF(did_ac));
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
if (! did_dc[dctbl]) {
|
||||
htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
|
||||
did_dc[dctbl] = TRUE;
|
||||
}
|
||||
if (! did_ac[actbl]) {
|
||||
htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
|
||||
did_ac[actbl] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_huff_encoder (j_compress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (huff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(huff_entropy_encoder));
|
||||
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_huff;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
11
jchuff.h
11
jchuff.h
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* jchuff.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for Huffman entropy encoding routines
|
||||
@@ -24,13 +22,6 @@
|
||||
#define MAX_COEF_BITS 14
|
||||
#endif
|
||||
|
||||
/* The legal range of a spatial difference is
|
||||
* -32767 .. +32768.
|
||||
* Hence the magnitude should always fit in 16 bits.
|
||||
*/
|
||||
|
||||
#define MAX_DIFF_BITS 16
|
||||
|
||||
/* Derived data constructed for each Huffman table */
|
||||
|
||||
typedef struct {
|
||||
|
||||
43
jcinit.c
43
jcinit.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains initialization logic for the JPEG compressor.
|
||||
@@ -34,9 +35,6 @@ jinit_compress_master (j_compress_ptr cinfo)
|
||||
/* Initialize master control (includes parameter checking/processing) */
|
||||
jinit_c_master_control(cinfo, FALSE /* full compression */);
|
||||
|
||||
/* Initialize compression codec */
|
||||
jinit_c_codec(cinfo);
|
||||
|
||||
/* Preprocessing */
|
||||
if (! cinfo->raw_data_in) {
|
||||
jinit_color_converter(cinfo);
|
||||
@@ -44,6 +42,45 @@ jinit_compress_master (j_compress_ptr cinfo)
|
||||
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
}
|
||||
|
||||
if (cinfo->master->lossless) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
/* Prediction, sample differencing, and point transform */
|
||||
jinit_lossless_compressor(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
jinit_lhuff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* Need a full-image difference buffer in any multi-pass mode. */
|
||||
jinit_c_diff_controller(cinfo,
|
||||
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
/* Forward DCT */
|
||||
jinit_forward_dct(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_encoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* Need a full-image coefficient buffer in any multi-pass mode. */
|
||||
jinit_c_coef_controller(cinfo,
|
||||
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
|
||||
}
|
||||
|
||||
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
|
||||
jinit_marker_writer(cinfo);
|
||||
|
||||
92
jclhuff.c
92
jclhuff.c
@@ -2,9 +2,10 @@
|
||||
* jclhuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy encoding routines for lossless JPEG.
|
||||
@@ -23,7 +24,17 @@
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
|
||||
|
||||
/* Expanded entropy encoder object for Huffman encoding.
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
/* The legal range of a spatial difference is
|
||||
* -32767 .. +32768.
|
||||
* Hence the magnitude should always fit in 16 bits.
|
||||
*/
|
||||
|
||||
#define MAX_DIFF_BITS 16
|
||||
|
||||
|
||||
/* Expanded entropy encoder object for Huffman encoding in lossless mode.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
@@ -54,6 +65,8 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_encoder pub; /* public fields */
|
||||
|
||||
savable_state saved; /* Bit buffer at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
@@ -64,19 +77,19 @@ typedef struct {
|
||||
c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
/* Pointers to derived tables to be used for each data unit within an MCU */
|
||||
c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU];
|
||||
c_derived_tbl * cur_tbls[C_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
|
||||
long * count_ptrs[NUM_HUFF_TBLS];
|
||||
|
||||
/* Pointers to stats tables to be used for each data unit within an MCU */
|
||||
long * cur_counts[C_MAX_DATA_UNITS_IN_MCU];
|
||||
long * cur_counts[C_MAX_BLOCKS_IN_MCU];
|
||||
#endif
|
||||
|
||||
/* Pointers to the proper input difference row for each group of data units
|
||||
* within an MCU. For each component, there are Vi groups of Hi data units.
|
||||
*/
|
||||
JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU];
|
||||
JDIFFROW input_ptr[C_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* Number of input pointers in use for the current MCU. This is the sum
|
||||
* of all Vi in the MCU.
|
||||
@@ -86,10 +99,10 @@ typedef struct {
|
||||
/* Information used for positioning the input pointers within the input
|
||||
* difference rows.
|
||||
*/
|
||||
lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU];
|
||||
lhe_input_ptr_info input_ptr_info[C_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* Index of the proper input pointer for each data unit within an MCU */
|
||||
int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU];
|
||||
int input_ptr_index[C_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
} lhuff_entropy_encoder;
|
||||
|
||||
@@ -131,23 +144,22 @@ METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
start_pass_lhuff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl, sampn, ptrn, yoffset, xoffset;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
if (gather_statistics) {
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
losslsc->entropy_encode_mcus = encode_mcus_gather;
|
||||
losslsc->pub.entropy_finish_pass = finish_pass_gather;
|
||||
entropy->pub.encode_mcus = encode_mcus_gather;
|
||||
entropy->pub.finish_pass = finish_pass_gather;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
losslsc->entropy_encode_mcus = encode_mcus_huff;
|
||||
losslsc->pub.entropy_finish_pass = finish_pass_huff;
|
||||
entropy->pub.encode_mcus = encode_mcus_huff;
|
||||
entropy->pub.finish_pass = finish_pass_huff;
|
||||
}
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
@@ -176,11 +188,9 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
}
|
||||
|
||||
/* Precalculate encoding info for each sample in an MCU of this scan */
|
||||
for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
|
||||
for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) {
|
||||
compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
|
||||
ci = compptr->component_index;
|
||||
/* ci = cinfo->MCU_membership[sampn];
|
||||
compptr = cinfo->cur_comp_info[ci];*/
|
||||
for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
|
||||
/* Precalculate the setup info for each input pointer */
|
||||
entropy->input_ptr_info[ptrn].ci = ci;
|
||||
@@ -297,8 +307,6 @@ flush_bits (working_state * state)
|
||||
LOCAL(boolean)
|
||||
emit_restart (working_state * state, int restart_num)
|
||||
{
|
||||
int ci;
|
||||
|
||||
if (! flush_bits(state))
|
||||
return FALSE;
|
||||
|
||||
@@ -312,7 +320,7 @@ emit_restart (working_state * state, int restart_num)
|
||||
|
||||
|
||||
/*
|
||||
* Encode and output one nMCU's worth of Huffman-compressed differences.
|
||||
* Encode and output nMCU MCUs' worth of Huffman-compressed differences.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
@@ -320,11 +328,9 @@ encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
working_state state;
|
||||
int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Load up working state */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
@@ -351,8 +357,8 @@ encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
|
||||
|
||||
/* Inner loop handles the samples in the MCU */
|
||||
for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
|
||||
register int temp, temp2, temp3;
|
||||
for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
|
||||
|
||||
@@ -380,7 +386,7 @@ encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
/* Check for out-of-range difference values.
|
||||
*/
|
||||
if (nbits > MAX_DIFF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DIFF);
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
|
||||
@@ -422,8 +428,7 @@ encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
METHODDEF(void)
|
||||
finish_pass_huff (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
working_state state;
|
||||
|
||||
/* Load up working state ... flush_bits needs it */
|
||||
@@ -457,7 +462,7 @@ finish_pass_huff (j_compress_ptr cinfo)
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
/*
|
||||
* Trial-encode one nMCU's worth of Huffman-compressed differences.
|
||||
* Trial-encode nMCU MCUs' worth of Huffman-compressed differences.
|
||||
* No data is actually output, so no suspension return is possible.
|
||||
*/
|
||||
|
||||
@@ -466,10 +471,8 @@ encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Take care of restart intervals if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
@@ -492,10 +495,9 @@ encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
|
||||
|
||||
/* Inner loop handles the samples in the MCU */
|
||||
for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
|
||||
for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
|
||||
register int temp;
|
||||
register int nbits;
|
||||
c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
|
||||
long * counts = entropy->cur_counts[sampn];
|
||||
|
||||
/* Encode the difference per section H.1.2.2 */
|
||||
@@ -519,7 +521,7 @@ encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
/* Check for out-of-range difference values.
|
||||
*/
|
||||
if (nbits > MAX_DIFF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DIFF);
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
counts[nbits]++;
|
||||
@@ -537,8 +539,7 @@ encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
METHODDEF(void)
|
||||
finish_pass_gather (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl;
|
||||
jpeg_component_info * compptr;
|
||||
JHUFF_TBL **htblptr;
|
||||
@@ -566,30 +567,21 @@ finish_pass_gather (j_compress_ptr cinfo)
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
METHODDEF(boolean)
|
||||
need_optimization_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy encoding.
|
||||
* Module initialization routine for lossless mode Huffman entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lhuff_encoder (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (lhuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(lhuff_entropy_encoder));
|
||||
losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
|
||||
losslsc->pub.entropy_start_pass = start_pass_huff;
|
||||
losslsc->pub.need_optimization_pass = need_optimization_pass;
|
||||
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_lhuff;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
@@ -599,3 +591,5 @@ jinit_lhuff_encoder (j_compress_ptr cinfo)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
319
jclossls.c
319
jclossls.c
@@ -5,9 +5,11 @@
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the control logic for the lossless JPEG compressor.
|
||||
* This file contains prediction, sample differencing, and point transform
|
||||
* routines for the lossless JPEG compressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
@@ -15,66 +17,301 @@
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h"
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
|
||||
/************************** Sample differencing **************************/
|
||||
|
||||
/*
|
||||
* In order to avoid a performance penalty for checking which predictor is
|
||||
* being used and which row is being processed for each call of the
|
||||
* undifferencer, and to promote optimization, we have separate differencing
|
||||
* functions for each predictor selection value.
|
||||
*
|
||||
* We are able to avoid duplicating source code by implementing the predictors
|
||||
* and differencers as macros. Each of the differencing functions is simply a
|
||||
* wrapper around a DIFFERENCE macro with the appropriate PREDICTOR macro
|
||||
* passed as an argument.
|
||||
*/
|
||||
|
||||
/* Forward declarations */
|
||||
LOCAL(void) reset_predictor JPP((j_compress_ptr cinfo, int ci));
|
||||
|
||||
|
||||
/* Predictor for the first column of the first row: 2^(P-Pt-1) */
|
||||
#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
|
||||
|
||||
/* Predictor for the first column of the remaining rows: Rb */
|
||||
#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
|
||||
|
||||
|
||||
/*
|
||||
* 1-Dimensional differencer routine.
|
||||
*
|
||||
* This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
|
||||
* is used as the special case predictor for the first column, which must be
|
||||
* either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
|
||||
* use PREDICTOR1.
|
||||
*/
|
||||
|
||||
#define DIFFERENCE_1D(INITIAL_PREDICTOR) \
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr) cinfo->fdct; \
|
||||
boolean restart = FALSE; \
|
||||
int samp, Ra; \
|
||||
\
|
||||
samp = GETJSAMPLE(*input_buf++); \
|
||||
*diff_buf++ = samp - INITIAL_PREDICTOR; \
|
||||
\
|
||||
while (--width) { \
|
||||
Ra = samp; \
|
||||
samp = GETJSAMPLE(*input_buf++); \
|
||||
*diff_buf++ = samp - PREDICTOR1; \
|
||||
} \
|
||||
\
|
||||
/* Account for restart interval (no-op if not using restarts) */ \
|
||||
if (cinfo->restart_interval) { \
|
||||
if (--(losslessc->restart_rows_to_go[ci]) == 0) { \
|
||||
reset_predictor(cinfo, ci); \
|
||||
restart = TRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 2-Dimensional differencer routine.
|
||||
*
|
||||
* This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
|
||||
* used as the special case predictor for the first column. The remaining
|
||||
* samples use PREDICTOR, which is a function of Ra, Rb, and Rc.
|
||||
*
|
||||
* Because prev_row and output_buf may point to the same storage area (in an
|
||||
* interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
|
||||
* before writing the current reconstructed sample value into output_buf.
|
||||
*/
|
||||
|
||||
#define DIFFERENCE_2D(PREDICTOR) \
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr) cinfo->fdct; \
|
||||
int samp, Ra, Rb, Rc; \
|
||||
\
|
||||
Rb = GETJSAMPLE(*prev_row++); \
|
||||
samp = GETJSAMPLE(*input_buf++); \
|
||||
*diff_buf++ = samp - PREDICTOR2; \
|
||||
\
|
||||
while (--width) { \
|
||||
Rc = Rb; \
|
||||
Rb = GETJSAMPLE(*prev_row++); \
|
||||
Ra = samp; \
|
||||
samp = GETJSAMPLE(*input_buf++); \
|
||||
*diff_buf++ = samp - PREDICTOR; \
|
||||
} \
|
||||
\
|
||||
/* Account for restart interval (no-op if not using restarts) */ \
|
||||
if (cinfo->restart_interval) { \
|
||||
if (--losslessc->restart_rows_to_go[ci] == 0) \
|
||||
reset_predictor(cinfo, ci); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Differencers for the second and subsequent rows in a scan or restart
|
||||
* interval. The first sample in the row is differenced using the vertical
|
||||
* predictor (2). The rest of the samples are differenced using the predictor
|
||||
* specified in the scan header.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference1(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_1D(INITIAL_PREDICTOR2);
|
||||
(void)(restart);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference2(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR2);
|
||||
(void)(Ra);
|
||||
(void)(Rc);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference3(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR3);
|
||||
(void)(Ra);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference4(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR4);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference5(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR5);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference6(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR6);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference7(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR7);
|
||||
(void)(Rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Differencer for the first row in a scan or restart interval. The first
|
||||
* sample in the row is differenced using the special predictor constant
|
||||
* x=2^(P-Pt-1). The rest of the samples are differenced using the
|
||||
* 1-D horizontal predictor (1).
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference_first_row(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_1D(INITIAL_PREDICTORx);
|
||||
|
||||
/*
|
||||
* Now that we have differenced the first row, we want to use the
|
||||
* differencer that corresponds to the predictor specified in the
|
||||
* scan header.
|
||||
*
|
||||
* Note that we don't do this if we have just reset the predictor
|
||||
* for a new restart interval.
|
||||
*/
|
||||
if (! restart) {
|
||||
switch (cinfo->Ss) {
|
||||
case 1:
|
||||
losslessc->predict_difference[ci] = jpeg_difference1;
|
||||
break;
|
||||
case 2:
|
||||
losslessc->predict_difference[ci] = jpeg_difference2;
|
||||
break;
|
||||
case 3:
|
||||
losslessc->predict_difference[ci] = jpeg_difference3;
|
||||
break;
|
||||
case 4:
|
||||
losslessc->predict_difference[ci] = jpeg_difference4;
|
||||
break;
|
||||
case 5:
|
||||
losslessc->predict_difference[ci] = jpeg_difference5;
|
||||
break;
|
||||
case 6:
|
||||
losslessc->predict_difference[ci] = jpeg_difference6;
|
||||
break;
|
||||
case 7:
|
||||
losslessc->predict_difference[ci] = jpeg_difference7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset predictor at the start of a pass or restart interval.
|
||||
*/
|
||||
|
||||
LOCAL(void)
|
||||
reset_predictor (j_compress_ptr cinfo, int ci)
|
||||
{
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr) cinfo->fdct;
|
||||
|
||||
/* Initialize restart counter */
|
||||
losslessc->restart_rows_to_go[ci] =
|
||||
cinfo->restart_interval / cinfo->MCUs_per_row;
|
||||
|
||||
/* Set difference function to first row function */
|
||||
losslessc->predict_difference[ci] = jpeg_difference_first_row;
|
||||
}
|
||||
|
||||
|
||||
/********************** Sample downscaling by 2^Pt ***********************/
|
||||
|
||||
METHODDEF(void)
|
||||
simple_downscale(j_compress_ptr cinfo,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
while (width--)
|
||||
*output_buf++ = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(*input_buf++), cinfo->Al);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_compress_ptr cinfo,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
start_pass_lossless (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr) cinfo->fdct;
|
||||
int ci;
|
||||
|
||||
(*losslsc->scaler_start_pass) (cinfo);
|
||||
(*losslsc->predict_start_pass) (cinfo);
|
||||
(*losslsc->diff_start_pass) (cinfo, pass_mode);
|
||||
/* Set scaler function based on Pt */
|
||||
if (cinfo->Al)
|
||||
losslessc->scaler_scale = simple_downscale;
|
||||
else
|
||||
losslessc->scaler_scale = noscale;
|
||||
|
||||
/* Check that the restart interval is an integer multiple of the number
|
||||
* of MCUs in an MCU row.
|
||||
*/
|
||||
if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
|
||||
ERREXIT2(cinfo, JERR_BAD_RESTART,
|
||||
cinfo->restart_interval, cinfo->MCUs_per_row);
|
||||
|
||||
/* Set predictors for start of pass */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
reset_predictor(cinfo, ci);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the lossless compression codec.
|
||||
* This is called only once, during master selection.
|
||||
* Initialize the lossless compressor.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lossless_c_codec(j_compress_ptr cinfo)
|
||||
jinit_lossless_compressor(j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc;
|
||||
lossless_comp_ptr losslessc;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
losslsc = (j_lossless_c_ptr)
|
||||
losslessc = (lossless_comp_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(jpeg_lossless_c_codec));
|
||||
cinfo->codec = (struct jpeg_c_codec *) losslsc;
|
||||
|
||||
/* Initialize sub-modules */
|
||||
|
||||
/* Scaler */
|
||||
jinit_c_scaler(cinfo);
|
||||
|
||||
/* Differencer */
|
||||
jinit_differencer(cinfo);
|
||||
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
jinit_lhuff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* Need a full-image difference buffer in any multi-pass mode. */
|
||||
jinit_c_diff_controller(cinfo,
|
||||
(boolean) (cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
|
||||
/* Initialize method pointers.
|
||||
*
|
||||
* Note: entropy_start_pass and entropy_finish_pass are assigned in
|
||||
* jclhuff.c and compress_data is assigned in jcdiffct.c.
|
||||
*/
|
||||
losslsc->pub.start_pass = start_pass;
|
||||
SIZEOF(jpeg_lossless_compressor));
|
||||
cinfo->fdct = (struct jpeg_forward_dct *) losslessc;
|
||||
losslessc->pub.start_pass = start_pass_lossless;
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
78
jclossy.c
78
jclossy.c
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* jclossy.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the control logic for the lossy JPEG compressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
|
||||
(*lossyc->fdct_start_pass) (cinfo);
|
||||
(*lossyc->coef_start_pass) (cinfo, pass_mode);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the lossy compression codec.
|
||||
* This is called only once, during master selection.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lossy_c_codec (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
lossyc = (j_lossy_c_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(jpeg_lossy_c_codec));
|
||||
cinfo->codec = (struct jpeg_c_codec *) lossyc;
|
||||
|
||||
/* Initialize sub-modules */
|
||||
|
||||
/* Forward DCT */
|
||||
jinit_forward_dct(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_encoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_shuff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* Need a full-image coefficient buffer in any multi-pass mode. */
|
||||
jinit_c_coef_controller(cinfo,
|
||||
(boolean) (cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
|
||||
/* Initialize method pointers.
|
||||
*
|
||||
* Note: entropy_start_pass and entropy_finish_pass are assigned in
|
||||
* jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c.
|
||||
*/
|
||||
lossyc->pub.start_pass = start_pass;
|
||||
}
|
||||
19
jcmainct.c
19
jcmainct.c
@@ -2,9 +2,10 @@
|
||||
* jcmainct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the main buffer controller for compression.
|
||||
@@ -117,7 +118,7 @@ process_data_simple_main (j_compress_ptr cinfo,
|
||||
JDIMENSION in_rows_avail)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int data_unit = cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
@@ -135,7 +136,7 @@ process_data_simple_main (j_compress_ptr cinfo,
|
||||
return;
|
||||
|
||||
/* Send the completed row to the compressor */
|
||||
if (! (*cinfo->codec->compress_data) (cinfo, main->buffer)) {
|
||||
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
|
||||
/* If compressor did not consume the whole row, then we must need to
|
||||
* suspend processing and return to the application. In this situation
|
||||
* we pretend we didn't yet consume the last input row; otherwise, if
|
||||
@@ -177,7 +178,7 @@ process_data_buffer_main (j_compress_ptr cinfo,
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
|
||||
int data_unit = cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||
/* Realign the virtual buffers if at the start of an iMCU row. */
|
||||
@@ -210,7 +211,7 @@ process_data_buffer_main (j_compress_ptr cinfo,
|
||||
|
||||
/* Emit data, unless this is a sink-only pass. */
|
||||
if (main->pass_mode != JBUF_SAVE_SOURCE) {
|
||||
if (! (*cinfo->codec->compress_data) (cinfo, main->buffer)) {
|
||||
if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
|
||||
/* If compressor did not consume the whole row, then we must need to
|
||||
* suspend processing and return to the application. In this situation
|
||||
* we pretend we didn't yet consume the last input row; otherwise, if
|
||||
@@ -251,7 +252,7 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
my_main_ptr main;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
int data_unit = cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
main = (my_main_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
@@ -274,8 +275,8 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
compptr->width_in_data_units * data_unit,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
compptr->width_in_blocks * data_unit,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor) * data_unit,
|
||||
(JDIMENSION) (compptr->v_samp_factor * data_unit));
|
||||
}
|
||||
@@ -291,7 +292,7 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
compptr->width_in_data_units * data_unit,
|
||||
compptr->width_in_blocks * data_unit,
|
||||
(JDIMENSION) (compptr->v_samp_factor * data_unit));
|
||||
}
|
||||
}
|
||||
|
||||
20
jcmarker.c
20
jcmarker.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to write JPEG datastream markers.
|
||||
@@ -324,7 +325,7 @@ emit_sos (j_compress_ptr cinfo)
|
||||
emit_byte(cinfo, compptr->component_id);
|
||||
td = compptr->dc_tbl_no;
|
||||
ta = compptr->ac_tbl_no;
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Progressive mode: only DC or only AC tables are used in one scan;
|
||||
* furthermore, Huffman coding of DC refinement uses no table at all.
|
||||
* We emit 0 for unused field(s); this is recommended by the P&M text
|
||||
@@ -495,15 +496,14 @@ write_file_header (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
write_frame_header (j_compress_ptr cinfo)
|
||||
{
|
||||
int ci, prec;
|
||||
int ci, prec = 0;
|
||||
boolean is_baseline;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
if (cinfo->process != JPROC_LOSSLESS) {
|
||||
if (! cinfo->master->lossless) {
|
||||
/* Emit DQT for each quantization table.
|
||||
* Note that emit_dqt() suppresses any duplicate tables.
|
||||
*/
|
||||
prec = 0;
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
|
||||
@@ -514,8 +514,8 @@ write_frame_header (j_compress_ptr cinfo)
|
||||
/* Check for a non-baseline specification.
|
||||
* Note we assume that Huffman table numbers won't be changed later.
|
||||
*/
|
||||
if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL ||
|
||||
cinfo->data_precision != 8) {
|
||||
if (cinfo->arith_code || cinfo->progressive_mode ||
|
||||
cinfo->master->lossless || cinfo->data_precision != 8) {
|
||||
is_baseline = FALSE;
|
||||
} else {
|
||||
is_baseline = TRUE;
|
||||
@@ -535,9 +535,9 @@ write_frame_header (j_compress_ptr cinfo)
|
||||
if (cinfo->arith_code) {
|
||||
emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
|
||||
} else {
|
||||
if (cinfo->process == JPROC_PROGRESSIVE)
|
||||
if (cinfo->progressive_mode)
|
||||
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
|
||||
else if (cinfo->process == JPROC_LOSSLESS)
|
||||
else if (cinfo->master->lossless)
|
||||
emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */
|
||||
else if (is_baseline)
|
||||
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
|
||||
@@ -572,7 +572,7 @@ write_scan_header (j_compress_ptr cinfo)
|
||||
*/
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
compptr = cinfo->cur_comp_info[i];
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Progressive mode: only DC or only AC tables are used in one scan */
|
||||
if (cinfo->Ss == 0) {
|
||||
if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
|
||||
@@ -580,7 +580,7 @@ write_scan_header (j_compress_ptr cinfo)
|
||||
} else {
|
||||
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
|
||||
}
|
||||
} else if (cinfo->process == JPROC_LOSSLESS) {
|
||||
} else if (cinfo->master->lossless) {
|
||||
/* Lossless mode: only DC tables are used */
|
||||
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
|
||||
} else {
|
||||
|
||||
200
jcmaster.c
200
jcmaster.c
@@ -2,9 +2,10 @@
|
||||
* jcmaster.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains master control logic for the JPEG compressor.
|
||||
@@ -16,29 +17,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef enum {
|
||||
main_pass, /* input data, also do first output step */
|
||||
huff_opt_pass, /* Huffman code optimization pass */
|
||||
output_pass /* data output pass */
|
||||
} c_pass_type;
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_comp_master pub; /* public fields */
|
||||
|
||||
c_pass_type pass_type; /* the type of the current pass */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
int total_passes; /* total # of passes needed */
|
||||
|
||||
int scan_number; /* current index in scan_info[] */
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master * my_master_ptr;
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -53,7 +32,7 @@ initial_setup (j_compress_ptr cinfo)
|
||||
jpeg_component_info *compptr;
|
||||
long samplesperrow;
|
||||
JDIMENSION jd_samplesperrow;
|
||||
int data_unit = cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Sanity check on image dimensions */
|
||||
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|
||||
@@ -99,13 +78,13 @@ initial_setup (j_compress_ptr cinfo)
|
||||
ci++, compptr++) {
|
||||
/* Fill in the correct component_index value; don't rely on application */
|
||||
compptr->component_index = ci;
|
||||
/* For compression, we never do any codec-based processing. */
|
||||
compptr->codec_data_unit = data_unit;
|
||||
/* For compression, we never do DCT scaling. */
|
||||
compptr->DCT_scaled_size = data_unit;
|
||||
/* Size in data units */
|
||||
compptr->width_in_data_units = (JDIMENSION)
|
||||
compptr->width_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||
(long) (cinfo->max_h_samp_factor * data_unit));
|
||||
compptr->height_in_data_units = (JDIMENSION)
|
||||
compptr->height_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||
(long) (cinfo->max_v_samp_factor * data_unit));
|
||||
/* Size in samples */
|
||||
@@ -120,19 +99,16 @@ initial_setup (j_compress_ptr cinfo)
|
||||
}
|
||||
|
||||
/* Compute number of fully interleaved MCU rows (number of times that
|
||||
* main controller will call coefficient controller).
|
||||
* main controller will call coefficient or difference controller).
|
||||
*/
|
||||
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*data_unit));
|
||||
}
|
||||
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
#if defined(C_MULTISCAN_FILES_SUPPORTED) || defined(C_LOSSLESS_SUPPORTED)
|
||||
#define NEED_SCAN_SCRIPT
|
||||
#else
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
#define NEED_SCAN_SCRIPT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SCAN_SCRIPT
|
||||
@@ -140,7 +116,7 @@ initial_setup (j_compress_ptr cinfo)
|
||||
LOCAL(void)
|
||||
validate_script (j_compress_ptr cinfo)
|
||||
/* Verify that the scan script in cinfo->scan_info[] is valid; also
|
||||
* determine whether it uses progressive JPEG, and set cinfo->process.
|
||||
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
|
||||
*/
|
||||
{
|
||||
const jpeg_scan_info * scanptr;
|
||||
@@ -162,9 +138,10 @@ validate_script (j_compress_ptr cinfo)
|
||||
#endif
|
||||
|
||||
scanptr = cinfo->scan_info;
|
||||
if (cinfo->lossless) {
|
||||
if (scanptr->Ss != 0 && scanptr->Se == 0) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
cinfo->process = JPROC_LOSSLESS;
|
||||
cinfo->master->lossless = TRUE;
|
||||
cinfo->progressive_mode = FALSE;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
component_sent[ci] = FALSE;
|
||||
#else
|
||||
@@ -176,7 +153,8 @@ validate_script (j_compress_ptr cinfo)
|
||||
*/
|
||||
else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
cinfo->process = JPROC_PROGRESSIVE;
|
||||
cinfo->progressive_mode = TRUE;
|
||||
cinfo->master->lossless = FALSE;
|
||||
last_bitpos_ptr = & last_bitpos[0][0];
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
for (coefi = 0; coefi < DCTSIZE2; coefi++)
|
||||
@@ -185,7 +163,7 @@ validate_script (j_compress_ptr cinfo)
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
cinfo->process = JPROC_SEQUENTIAL;
|
||||
cinfo->progressive_mode = cinfo->master->lossless = FALSE;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
component_sent[ci] = FALSE;
|
||||
}
|
||||
@@ -208,26 +186,7 @@ validate_script (j_compress_ptr cinfo)
|
||||
Se = scanptr->Se;
|
||||
Ah = scanptr->Ah;
|
||||
Al = scanptr->Al;
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
/* The JPEG spec simply gives the range 0..15 for Al (Pt), but that
|
||||
* seems wrong: the upper bound ought to depend on data precision.
|
||||
* Perhaps they really meant 0..N-1 for N-bit precision, which is what
|
||||
* we allow here.
|
||||
*/
|
||||
if (Ss < 1 || Ss > 7 || /* predictor selector */
|
||||
Se != 0 || Ah != 0 ||
|
||||
Al < 0 || Al >= cinfo->data_precision) /* point transform */
|
||||
ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno);
|
||||
/* Make sure components are not sent twice */
|
||||
for (ci = 0; ci < ncomps; ci++) {
|
||||
thisi = scanptr->component_index[ci];
|
||||
if (component_sent[thisi])
|
||||
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
|
||||
component_sent[thisi] = TRUE;
|
||||
}
|
||||
#endif
|
||||
} else if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
/* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
|
||||
* seems wrong: the upper bound ought to depend on data precision.
|
||||
@@ -270,9 +229,25 @@ validate_script (j_compress_ptr cinfo)
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* For sequential JPEG, all progression parameters must be these: */
|
||||
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
|
||||
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
if (cinfo->master->lossless) {
|
||||
/* The JPEG spec simply gives the range 0..15 for Al (Pt), but that
|
||||
* seems wrong: the upper bound ought to depend on data precision.
|
||||
* Perhaps they really meant 0..N-1 for N-bit precision, which is what
|
||||
* we allow here. Values greater than or equal to the data precision
|
||||
* will result in a blank image.
|
||||
*/
|
||||
if (Ss < 1 || Ss > 7 || /* predictor selection value */
|
||||
Se != 0 || Ah != 0 ||
|
||||
Al < 0 || Al >= cinfo->data_precision) /* point transform */
|
||||
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* For sequential JPEG, all progression parameters must be these: */
|
||||
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
|
||||
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
||||
}
|
||||
/* Make sure components are not sent twice */
|
||||
for (ci = 0; ci < ncomps; ci++) {
|
||||
thisi = scanptr->component_index[ci];
|
||||
@@ -284,7 +259,7 @@ validate_script (j_compress_ptr cinfo)
|
||||
}
|
||||
|
||||
/* Now verify that everything got sent. */
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
/* For progressive mode, we only check that at least some DC data
|
||||
* got sent for each component; the spec does not require that all bits
|
||||
@@ -339,15 +314,7 @@ select_scan_parameters (j_compress_ptr cinfo)
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||
}
|
||||
if (cinfo->lossless) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
/* If we fall through to here, the user specified lossless, but did not
|
||||
* provide a scan script.
|
||||
*/
|
||||
ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT);
|
||||
#endif
|
||||
} else {
|
||||
cinfo->process = JPROC_SEQUENTIAL;
|
||||
if (! cinfo->master->lossless) {
|
||||
cinfo->Ss = 0;
|
||||
cinfo->Se = DCTSIZE2-1;
|
||||
cinfo->Ah = 0;
|
||||
@@ -364,7 +331,7 @@ per_scan_setup (j_compress_ptr cinfo)
|
||||
{
|
||||
int ci, mcublks, tmp;
|
||||
jpeg_component_info *compptr;
|
||||
int data_unit = cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
|
||||
@@ -372,24 +339,24 @@ per_scan_setup (j_compress_ptr cinfo)
|
||||
compptr = cinfo->cur_comp_info[0];
|
||||
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = compptr->width_in_data_units;
|
||||
cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
|
||||
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||
|
||||
/* For noninterleaved scan, always one block per MCU */
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_data_units = 1;
|
||||
compptr->MCU_blocks = 1;
|
||||
compptr->MCU_sample_width = data_unit;
|
||||
compptr->last_col_width = 1;
|
||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||
* as the number of block rows present in the last iMCU row.
|
||||
*/
|
||||
tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||
compptr->last_row_height = tmp;
|
||||
|
||||
/* Prepare array describing MCU composition */
|
||||
cinfo->data_units_in_MCU = 1;
|
||||
cinfo->blocks_in_MCU = 1;
|
||||
cinfo->MCU_membership[0] = 0;
|
||||
|
||||
} else {
|
||||
@@ -407,28 +374,28 @@ per_scan_setup (j_compress_ptr cinfo)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*data_unit));
|
||||
|
||||
cinfo->data_units_in_MCU = 0;
|
||||
cinfo->blocks_in_MCU = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Sampling factors give # of blocks of component in each MCU */
|
||||
compptr->MCU_width = compptr->h_samp_factor;
|
||||
compptr->MCU_height = compptr->v_samp_factor;
|
||||
compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width * data_unit;
|
||||
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||
tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
|
||||
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||
if (tmp == 0) tmp = compptr->MCU_width;
|
||||
compptr->last_col_width = tmp;
|
||||
tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||
if (tmp == 0) tmp = compptr->MCU_height;
|
||||
compptr->last_row_height = tmp;
|
||||
/* Prepare array describing MCU composition */
|
||||
mcublks = compptr->MCU_data_units;
|
||||
if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU)
|
||||
mcublks = compptr->MCU_blocks;
|
||||
if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
|
||||
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||
while (mcublks-- > 0) {
|
||||
cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
|
||||
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +421,6 @@ per_scan_setup (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
prepare_for_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
switch (master->pass_type) {
|
||||
@@ -469,10 +435,11 @@ prepare_for_pass (j_compress_ptr cinfo)
|
||||
(*cinfo->downsample->start_pass) (cinfo);
|
||||
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||
}
|
||||
(*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding);
|
||||
(*cinfo->codec->start_pass) (cinfo,
|
||||
(master->total_passes > 1 ?
|
||||
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
|
||||
(*cinfo->fdct->start_pass) (cinfo);
|
||||
(*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
|
||||
(*cinfo->coef->start_pass) (cinfo,
|
||||
(master->total_passes > 1 ?
|
||||
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
|
||||
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||
if (cinfo->optimize_coding) {
|
||||
/* No immediate data output; postpone writing frame/scan headers */
|
||||
@@ -487,9 +454,10 @@ prepare_for_pass (j_compress_ptr cinfo)
|
||||
/* Do Huffman optimization for a scan after the first one. */
|
||||
select_scan_parameters(cinfo);
|
||||
per_scan_setup(cinfo);
|
||||
if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) {
|
||||
(*cinfo->codec->entropy_start_pass) (cinfo, TRUE);
|
||||
(*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code ||
|
||||
cinfo->master->lossless) {
|
||||
(*cinfo->entropy->start_pass) (cinfo, TRUE);
|
||||
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
master->pub.call_pass_startup = FALSE;
|
||||
break;
|
||||
}
|
||||
@@ -507,8 +475,8 @@ prepare_for_pass (j_compress_ptr cinfo)
|
||||
select_scan_parameters(cinfo);
|
||||
per_scan_setup(cinfo);
|
||||
}
|
||||
(*cinfo->codec->entropy_start_pass) (cinfo, FALSE);
|
||||
(*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
(*cinfo->entropy->start_pass) (cinfo, FALSE);
|
||||
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
/* We emit frame/scan headers now */
|
||||
if (master->scan_number == 0)
|
||||
(*cinfo->marker->write_frame_header) (cinfo);
|
||||
@@ -556,13 +524,12 @@ pass_startup (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
finish_pass_master (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
/* The entropy coder always needs an end-of-pass call,
|
||||
* either to analyze statistics or to flush its output buffer.
|
||||
*/
|
||||
(*lossyc->pub.entropy_finish_pass) (cinfo);
|
||||
(*cinfo->entropy->finish_pass) (cinfo);
|
||||
|
||||
/* Update state for next pass */
|
||||
switch (master->pass_type) {
|
||||
@@ -597,22 +564,13 @@ finish_pass_master (j_compress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
|
||||
{
|
||||
my_master_ptr master;
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
master = (my_master_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_comp_master));
|
||||
cinfo->master = (struct jpeg_comp_master *) master;
|
||||
master->pub.prepare_for_pass = prepare_for_pass;
|
||||
master->pub.pass_startup = pass_startup;
|
||||
master->pub.finish_pass = finish_pass_master;
|
||||
master->pub.is_last_pass = FALSE;
|
||||
|
||||
cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Validate parameters, determine derived values */
|
||||
initial_setup(cinfo);
|
||||
|
||||
if (cinfo->scan_info != NULL) {
|
||||
#ifdef NEED_SCAN_SCRIPT
|
||||
validate_script(cinfo);
|
||||
@@ -620,12 +578,32 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
cinfo->process = JPROC_SEQUENTIAL;
|
||||
cinfo->progressive_mode = FALSE;
|
||||
cinfo->num_scans = 1;
|
||||
}
|
||||
|
||||
if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */
|
||||
cinfo->process == JPROC_LOSSLESS)
|
||||
/* Disable smoothing and subsampling in lossless mode, since those are lossy
|
||||
* algorithms. Set the JPEG colorspace to the input colorspace. Disable raw
|
||||
* (downsampled) data input, because it isn't particularly useful without
|
||||
* subsampling and has not been tested in lossless mode.
|
||||
*/
|
||||
if (cinfo->master->lossless) {
|
||||
int ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
cinfo->raw_data_in = FALSE;
|
||||
cinfo->smoothing_factor = 0;
|
||||
jpeg_default_colorspace(cinfo);
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++)
|
||||
compptr->h_samp_factor = compptr->v_samp_factor = 1;
|
||||
}
|
||||
|
||||
/* Validate parameters, determine derived values */
|
||||
initial_setup(cinfo);
|
||||
|
||||
if (cinfo->progressive_mode || /* TEMPORARY HACK ??? */
|
||||
cinfo->master->lossless)
|
||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
||||
* progressive mode or lossless mode */
|
||||
|
||||
|
||||
30
jcmaster.h
Normal file
30
jcmaster.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* jcmaster.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains master control structure for the JPEG compressor.
|
||||
*/
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef enum {
|
||||
main_pass, /* input data, also do first output step */
|
||||
huff_opt_pass, /* Huffman code optimization pass */
|
||||
output_pass /* data output pass */
|
||||
} c_pass_type;
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_comp_master pub; /* public fields */
|
||||
|
||||
c_pass_type pass_type; /* the type of the current pass */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
int total_passes; /* total # of passes needed */
|
||||
|
||||
int scan_number; /* current index in scan_info[] */
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master * my_master_ptr;
|
||||
55
jcodec.c
55
jcodec.c
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* jcodec.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains utility functions for the JPEG codec(s).
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h"
|
||||
#include "jlossls.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the compression codec.
|
||||
* This is called only once, during master selection.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_c_codec (j_compress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
jinit_lossless_c_codec(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_lossy_c_codec(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the decompression codec.
|
||||
* This is called only once, during master selection.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_d_codec (j_decompress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
jinit_lossless_d_codec(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_lossy_d_codec(cinfo);
|
||||
}
|
||||
171
jcparam.c
171
jcparam.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains optional default-setting code for the JPEG compressor.
|
||||
@@ -286,7 +287,6 @@ jpeg_set_defaults (j_compress_ptr cinfo)
|
||||
|
||||
/* Initialize everything not dependent on the color space */
|
||||
|
||||
cinfo->lossless = FALSE;
|
||||
cinfo->data_precision = BITS_IN_JSAMPLE;
|
||||
/* Set up two quantization tables using default quality of 75 */
|
||||
jpeg_set_quality(cinfo, 75, TRUE);
|
||||
@@ -361,31 +361,30 @@ jpeg_set_defaults (j_compress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jpeg_default_colorspace (j_compress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->lossless)
|
||||
jpeg_set_colorspace(cinfo, cinfo->in_color_space);
|
||||
else { /* lossy */
|
||||
switch (cinfo->in_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||
break;
|
||||
case JCS_RGB:
|
||||
switch (cinfo->in_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
|
||||
break;
|
||||
case JCS_RGB:
|
||||
if (cinfo->master->lossless)
|
||||
jpeg_set_colorspace(cinfo, JCS_RGB);
|
||||
else
|
||||
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||
break;
|
||||
case JCS_YCbCr:
|
||||
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
|
||||
break;
|
||||
case JCS_YCCK:
|
||||
jpeg_set_colorspace(cinfo, JCS_YCCK);
|
||||
break;
|
||||
case JCS_UNKNOWN:
|
||||
jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
|
||||
break;
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||
}
|
||||
break;
|
||||
case JCS_YCbCr:
|
||||
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
|
||||
break;
|
||||
case JCS_YCCK:
|
||||
jpeg_set_colorspace(cinfo, JCS_YCCK);
|
||||
break;
|
||||
case JCS_UNKNOWN:
|
||||
jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
|
||||
break;
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,16 +439,10 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
|
||||
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
|
||||
cinfo->num_components = 3;
|
||||
/* JFIF specifies component IDs 1,2,3 */
|
||||
if (cinfo->lossless) {
|
||||
SET_COMP(0, 1, 1,1, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
} else { /* lossy */
|
||||
/* We default to 2x2 subsamples of chrominance */
|
||||
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
}
|
||||
/* We default to 2x2 subsamples of chrominance */
|
||||
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
|
||||
@@ -462,17 +455,10 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
|
||||
case JCS_YCCK:
|
||||
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
|
||||
cinfo->num_components = 4;
|
||||
if (cinfo->lossless) {
|
||||
SET_COMP(0, 1, 1,1, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
SET_COMP(3, 4, 1,1, 0, 0,0);
|
||||
} else { /* lossy */
|
||||
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
SET_COMP(3, 4, 2,2, 0, 0,0);
|
||||
}
|
||||
SET_COMP(0, 1, 2,2, 0, 0,0);
|
||||
SET_COMP(1, 2, 1,1, 1, 1,1);
|
||||
SET_COMP(2, 3, 1,1, 1, 1,1);
|
||||
SET_COMP(3, 4, 2,2, 0, 0,0);
|
||||
break;
|
||||
case JCS_UNKNOWN:
|
||||
cinfo->num_components = cinfo->input_components;
|
||||
@@ -491,6 +477,21 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
|
||||
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
|
||||
LOCAL(jpeg_scan_info *)
|
||||
fill_a_scan (jpeg_scan_info * scanptr, int ci,
|
||||
int Ss, int Se, int Ah, int Al)
|
||||
/* Support routine: generate one scan for specified component */
|
||||
{
|
||||
scanptr->comps_in_scan = 1;
|
||||
scanptr->component_index[0] = ci;
|
||||
scanptr->Ss = Ss;
|
||||
scanptr->Se = Se;
|
||||
scanptr->Ah = Ah;
|
||||
scanptr->Al = Al;
|
||||
scanptr++;
|
||||
return scanptr;
|
||||
}
|
||||
|
||||
LOCAL(jpeg_scan_info *)
|
||||
fill_scans (jpeg_scan_info * scanptr, int ncomps,
|
||||
int Ss, int Se, int Ah, int Al)
|
||||
@@ -510,22 +511,6 @@ fill_scans (jpeg_scan_info * scanptr, int ncomps,
|
||||
return scanptr;
|
||||
}
|
||||
|
||||
|
||||
LOCAL(jpeg_scan_info *)
|
||||
fill_a_scan (jpeg_scan_info * scanptr, int ci,
|
||||
int Ss, int Se, int Ah, int Al)
|
||||
/* Support routine: generate one scan for specified component */
|
||||
{
|
||||
scanptr->comps_in_scan = 1;
|
||||
scanptr->component_index[0] = ci;
|
||||
scanptr->Ss = Ss;
|
||||
scanptr->Se = Se;
|
||||
scanptr->Ah = Ah;
|
||||
scanptr->Al = Al;
|
||||
scanptr++;
|
||||
return scanptr;
|
||||
}
|
||||
|
||||
LOCAL(jpeg_scan_info *)
|
||||
fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
|
||||
/* Support routine: generate interleaved DC scan if possible, else N scans */
|
||||
@@ -565,6 +550,11 @@ jpeg_simple_progression (j_compress_ptr cinfo)
|
||||
if (cinfo->global_state != CSTATE_START)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
if (cinfo->master->lossless) {
|
||||
cinfo->master->lossless = FALSE;
|
||||
jpeg_default_colorspace(cinfo);
|
||||
}
|
||||
|
||||
/* Figure space needed for script. Calculation must match code below! */
|
||||
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
/* Custom script for YCbCr color images. */
|
||||
@@ -634,56 +624,33 @@ jpeg_simple_progression (j_compress_ptr cinfo)
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Create a single-entry lossless-JPEG script containing all components.
|
||||
* cinfo->num_components must be correct.
|
||||
* Enable lossless mode.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform)
|
||||
jpeg_enable_lossless (j_compress_ptr cinfo, int predictor_selection_value,
|
||||
int point_transform)
|
||||
{
|
||||
int ncomps = cinfo->num_components;
|
||||
int nscans = 1;
|
||||
int ci;
|
||||
jpeg_scan_info * scanptr;
|
||||
|
||||
/* Safety check to ensure start_compress not called yet. */
|
||||
if (cinfo->global_state != CSTATE_START)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
cinfo->lossless = TRUE;
|
||||
cinfo->master->lossless = TRUE;
|
||||
cinfo->Ss = predictor_selection_value;
|
||||
cinfo->Se = 0;
|
||||
cinfo->Ah = 0;
|
||||
cinfo->Al = point_transform;
|
||||
|
||||
/* Set jpeg_color_space. */
|
||||
jpeg_default_colorspace(cinfo);
|
||||
|
||||
/* Check to ensure that all components will fit in one scan. */
|
||||
if (cinfo->num_components > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||
MAX_COMPS_IN_SCAN);
|
||||
|
||||
/* Allocate space for script.
|
||||
* We need to put it in the permanent pool in case the application performs
|
||||
* multiple compressions without changing the settings. To avoid a memory
|
||||
* leak if jpeg_simple_lossless is called repeatedly for the same JPEG
|
||||
* object, we try to re-use previously allocated space.
|
||||
/* The JPEG spec simply gives the range 0..15 for Al (Pt), but that seems
|
||||
* wrong: the upper bound ought to depend on data precision. Perhaps they
|
||||
* really meant 0..N-1 for N-bit precision, which is what we allow here.
|
||||
* Values greater than or equal to the data precision will result in a blank
|
||||
* image.
|
||||
*/
|
||||
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
|
||||
cinfo->script_space_size = nscans;
|
||||
cinfo->script_space = (jpeg_scan_info *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
cinfo->script_space_size * SIZEOF(jpeg_scan_info));
|
||||
}
|
||||
scanptr = cinfo->script_space;
|
||||
cinfo->scan_info = scanptr;
|
||||
cinfo->num_scans = nscans;
|
||||
|
||||
/* Fill the script. */
|
||||
scanptr->comps_in_scan = ncomps;
|
||||
for (ci = 0; ci < ncomps; ci++)
|
||||
scanptr->component_index[ci] = ci;
|
||||
scanptr->Ss = predictor;
|
||||
scanptr->Se = 0;
|
||||
scanptr->Ah = 0;
|
||||
scanptr->Al = point_transform;
|
||||
if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
|
||||
cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision)
|
||||
ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
|
||||
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
55
jcphuff.c
55
jcphuff.c
@@ -2,7 +2,7 @@
|
||||
* jcphuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
@@ -17,7 +17,6 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
@@ -25,6 +24,8 @@
|
||||
/* Expanded entropy encoder object for progressive Huffman encoding. */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_encoder pub; /* public fields */
|
||||
|
||||
/* Mode flag: TRUE for optimization, FALSE for actual data output */
|
||||
boolean gather_statistics;
|
||||
|
||||
@@ -106,8 +107,7 @@ METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
|
||||
METHODDEF(void)
|
||||
start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
boolean is_DC_band;
|
||||
int ci, tbl;
|
||||
jpeg_component_info * compptr;
|
||||
@@ -122,14 +122,14 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
/* Select execution routines */
|
||||
if (cinfo->Ah == 0) {
|
||||
if (is_DC_band)
|
||||
lossyc->entropy_encode_mcu = encode_mcu_DC_first;
|
||||
entropy->pub.encode_mcu = encode_mcu_DC_first;
|
||||
else
|
||||
lossyc->entropy_encode_mcu = encode_mcu_AC_first;
|
||||
entropy->pub.encode_mcu = encode_mcu_AC_first;
|
||||
} else {
|
||||
if (is_DC_band)
|
||||
lossyc->entropy_encode_mcu = encode_mcu_DC_refine;
|
||||
entropy->pub.encode_mcu = encode_mcu_DC_refine;
|
||||
else {
|
||||
lossyc->entropy_encode_mcu = encode_mcu_AC_refine;
|
||||
entropy->pub.encode_mcu = encode_mcu_AC_refine;
|
||||
/* AC refinement needs a correction bit buffer */
|
||||
if (entropy->bit_buffer == NULL)
|
||||
entropy->bit_buffer = (char *)
|
||||
@@ -138,9 +138,9 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
}
|
||||
}
|
||||
if (gather_statistics)
|
||||
lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff;
|
||||
entropy->pub.finish_pass = finish_pass_gather_phuff;
|
||||
else
|
||||
lossyc->pub.entropy_finish_pass = finish_pass_phuff;
|
||||
entropy->pub.finish_pass = finish_pass_phuff;
|
||||
|
||||
/* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
|
||||
* for AC coefficients.
|
||||
@@ -378,8 +378,7 @@ emit_restart (phuff_entropy_ptr entropy, int restart_num)
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
int blkn, ci;
|
||||
@@ -397,7 +396,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
emit_restart(entropy, entropy->next_restart_num);
|
||||
|
||||
/* Encode the MCU data blocks */
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
block = MCU_data[blkn];
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
@@ -466,8 +465,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
register int r, k;
|
||||
@@ -574,8 +572,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
register int temp;
|
||||
int blkn;
|
||||
int Al = cinfo->Al;
|
||||
@@ -590,7 +587,7 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
emit_restart(entropy, entropy->next_restart_num);
|
||||
|
||||
/* Encode the MCU data blocks */
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
block = MCU_data[blkn];
|
||||
|
||||
/* We simply emit the Al'th bit of the DC coefficient value. */
|
||||
@@ -622,8 +619,7 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
register int temp;
|
||||
register int r, k;
|
||||
int EOB;
|
||||
@@ -751,8 +747,7 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(void)
|
||||
finish_pass_phuff (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
|
||||
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
@@ -773,8 +768,7 @@ finish_pass_phuff (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
finish_pass_gather_phuff (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
boolean is_DC_band;
|
||||
int ci, tbl;
|
||||
jpeg_component_info * compptr;
|
||||
@@ -814,13 +808,6 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(boolean)
|
||||
need_optimization_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
return (cinfo->Ss != 0 || cinfo->Ah == 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for progressive Huffman entropy encoding.
|
||||
*/
|
||||
@@ -828,16 +815,14 @@ need_optimization_pass (j_compress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jinit_phuff_encoder (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (phuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(phuff_entropy_encoder));
|
||||
lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
|
||||
lossyc->pub.entropy_start_pass = start_pass_phuff;
|
||||
lossyc->pub.need_optimization_pass = need_optimization_pass;
|
||||
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_phuff;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
|
||||
299
jcpred.c
299
jcpred.c
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* jcpred.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains sample differencing for lossless JPEG.
|
||||
*
|
||||
* In order to avoid paying the performance penalty of having to check the
|
||||
* predictor being used and the row being processed for each call of the
|
||||
* undifferencer, and to promote optimization, we have separate differencing
|
||||
* functions for each case.
|
||||
*
|
||||
* We are able to avoid duplicating source code by implementing the predictors
|
||||
* and differencers as macros. Each of the differencing functions are
|
||||
* simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR
|
||||
* macro passed as an argument.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
/* Private predictor object */
|
||||
|
||||
typedef struct {
|
||||
/* MCU-rows left in the restart interval for each component */
|
||||
unsigned int restart_rows_to_go[MAX_COMPONENTS];
|
||||
} c_predictor;
|
||||
|
||||
typedef c_predictor * c_pred_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
LOCAL(void) reset_predictor
|
||||
JPP((j_compress_ptr cinfo, int ci));
|
||||
METHODDEF(void) start_pass
|
||||
JPP((j_compress_ptr cinfo));
|
||||
|
||||
|
||||
/* Predictor for the first column of the first row: 2^(P-Pt-1) */
|
||||
#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
|
||||
|
||||
/* Predictor for the first column of the remaining rows: Rb */
|
||||
#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
|
||||
|
||||
|
||||
/*
|
||||
* 1-Dimensional differencer routine.
|
||||
*
|
||||
* This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
|
||||
* is used as the special case predictor for the first column, which must be
|
||||
* either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
|
||||
* use PREDICTOR1.
|
||||
*/
|
||||
|
||||
#define DIFFERENCE_1D(INITIAL_PREDICTOR) \
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
|
||||
c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
|
||||
boolean restart = FALSE; \
|
||||
int xindex; \
|
||||
int samp, Ra; \
|
||||
\
|
||||
samp = GETJSAMPLE(input_buf[0]); \
|
||||
diff_buf[0] = samp - INITIAL_PREDICTOR; \
|
||||
\
|
||||
for (xindex = 1; xindex < width; xindex++) { \
|
||||
Ra = samp; \
|
||||
samp = GETJSAMPLE(input_buf[xindex]); \
|
||||
diff_buf[xindex] = samp - PREDICTOR1; \
|
||||
} \
|
||||
\
|
||||
/* Account for restart interval (no-op if not using restarts) */ \
|
||||
if (cinfo->restart_interval) { \
|
||||
if (--(pred->restart_rows_to_go[ci]) == 0) { \
|
||||
reset_predictor(cinfo, ci); \
|
||||
restart = TRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 2-Dimensional differencer routine.
|
||||
*
|
||||
* This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
|
||||
* used as the special case predictor for the first column. The remaining
|
||||
* samples use PREDICTOR, which is a function of Ra, Rb, Rc.
|
||||
*
|
||||
* Because prev_row and output_buf may point to the same storage area (in an
|
||||
* interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
|
||||
* before writing the current reconstructed sample value into output_buf.
|
||||
*/
|
||||
|
||||
#define DIFFERENCE_2D(PREDICTOR) \
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
|
||||
c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
|
||||
int xindex; \
|
||||
int samp, Ra, Rb, Rc; \
|
||||
\
|
||||
Rb = GETJSAMPLE(prev_row[0]); \
|
||||
samp = GETJSAMPLE(input_buf[0]); \
|
||||
diff_buf[0] = samp - PREDICTOR2; \
|
||||
\
|
||||
for (xindex = 1; xindex < width; xindex++) { \
|
||||
Rc = Rb; \
|
||||
Rb = GETJSAMPLE(prev_row[xindex]); \
|
||||
Ra = samp; \
|
||||
samp = GETJSAMPLE(input_buf[xindex]); \
|
||||
diff_buf[xindex] = samp - PREDICTOR; \
|
||||
} \
|
||||
\
|
||||
/* Account for restart interval (no-op if not using restarts) */ \
|
||||
if (cinfo->restart_interval) { \
|
||||
if (--pred->restart_rows_to_go[ci] == 0) \
|
||||
reset_predictor(cinfo, ci); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Differencers for the all rows but the first in a scan or restart interval.
|
||||
* The first sample in the row is differenced using the vertical
|
||||
* predictor (2). The rest of the samples are differenced using the
|
||||
* predictor specified in the scan header.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference1(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_1D(INITIAL_PREDICTOR2);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference2(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR2);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference3(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR3);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference4(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR4);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference5(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR5);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference6(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR6);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference7(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_2D(PREDICTOR7);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Differencer for the first row in a scan or restart interval. The first
|
||||
* sample in the row is differenced using the special predictor constant
|
||||
* x=2^(P-Pt-1). The rest of the samples are differenced using the
|
||||
* 1-D horizontal predictor (1).
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_difference_first_row(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width)
|
||||
{
|
||||
DIFFERENCE_1D(INITIAL_PREDICTORx);
|
||||
|
||||
/*
|
||||
* Now that we have differenced the first row, we want to use the
|
||||
* differencer which corresponds to the predictor specified in the
|
||||
* scan header.
|
||||
*
|
||||
* Note that we don't to do this if we have just reset the predictor
|
||||
* for a new restart interval.
|
||||
*/
|
||||
if (!restart) {
|
||||
switch (cinfo->Ss) {
|
||||
case 1:
|
||||
losslsc->predict_difference[ci] = jpeg_difference1;
|
||||
break;
|
||||
case 2:
|
||||
losslsc->predict_difference[ci] = jpeg_difference2;
|
||||
break;
|
||||
case 3:
|
||||
losslsc->predict_difference[ci] = jpeg_difference3;
|
||||
break;
|
||||
case 4:
|
||||
losslsc->predict_difference[ci] = jpeg_difference4;
|
||||
break;
|
||||
case 5:
|
||||
losslsc->predict_difference[ci] = jpeg_difference5;
|
||||
break;
|
||||
case 6:
|
||||
losslsc->predict_difference[ci] = jpeg_difference6;
|
||||
break;
|
||||
case 7:
|
||||
losslsc->predict_difference[ci] = jpeg_difference7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset predictor at the start of a pass or restart interval.
|
||||
*/
|
||||
|
||||
LOCAL(void)
|
||||
reset_predictor (j_compress_ptr cinfo, int ci)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
|
||||
|
||||
/* Initialize restart counter */
|
||||
pred->restart_rows_to_go[ci] =
|
||||
cinfo->restart_interval / cinfo->MCUs_per_row;
|
||||
|
||||
/* Set difference function to first row function */
|
||||
losslsc->predict_difference[ci] = jpeg_difference_first_row;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
|
||||
int ci;
|
||||
|
||||
/* Check that the restart interval is an integer multiple of the number
|
||||
* of MCU in an MCU-row.
|
||||
*/
|
||||
if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
|
||||
ERREXIT2(cinfo, JERR_BAD_RESTART,
|
||||
cinfo->restart_interval, cinfo->MCUs_per_row);
|
||||
|
||||
/* Set predictors for start of pass */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
reset_predictor(cinfo, ci);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for the differencer.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_differencer (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
c_pred_ptr pred;
|
||||
|
||||
pred = (c_pred_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(c_predictor));
|
||||
losslsc->pred_private = (void *) pred;
|
||||
losslsc->predict_start_pass = start_pass;
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
12
jcprepct.c
12
jcprepct.c
@@ -2,9 +2,10 @@
|
||||
* jcprepct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the compression preprocessing controller.
|
||||
@@ -137,6 +138,7 @@ pre_process_data (j_compress_ptr cinfo,
|
||||
int numrows, ci;
|
||||
JDIMENSION inrows;
|
||||
jpeg_component_info * compptr;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
while (*in_row_ctr < in_rows_avail &&
|
||||
*out_row_group_ctr < out_row_groups_avail) {
|
||||
@@ -176,7 +178,7 @@ pre_process_data (j_compress_ptr cinfo,
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
expand_bottom_edge(output_buf[ci],
|
||||
compptr->width_in_data_units * cinfo->data_unit,
|
||||
compptr->width_in_blocks * data_unit,
|
||||
(int) (*out_row_group_ctr * compptr->v_samp_factor),
|
||||
(int) (out_row_groups_avail * compptr->v_samp_factor));
|
||||
}
|
||||
@@ -273,6 +275,7 @@ create_context_buffer (j_compress_ptr cinfo)
|
||||
int ci, i;
|
||||
jpeg_component_info * compptr;
|
||||
JSAMPARRAY true_buffer, fake_buffer;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Grab enough space for fake row pointers for all the components;
|
||||
* we need five row groups' worth of pointers for each component.
|
||||
@@ -290,7 +293,7 @@ create_context_buffer (j_compress_ptr cinfo)
|
||||
*/
|
||||
true_buffer = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
|
||||
(JDIMENSION) (((long) compptr->width_in_blocks * data_unit *
|
||||
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||
(JDIMENSION) (3 * rgroup_height));
|
||||
/* Copy true buffer row pointers into the middle of the fake row array */
|
||||
@@ -319,6 +322,7 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
my_prep_ptr prep;
|
||||
int ci;
|
||||
jpeg_component_info * compptr;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
if (need_full_buffer) /* safety check */
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
@@ -348,7 +352,7 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
|
||||
(JDIMENSION) (((long) compptr->width_in_blocks * data_unit *
|
||||
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||
(JDIMENSION) cinfo->max_v_samp_factor);
|
||||
}
|
||||
|
||||
22
jcsample.c
22
jcsample.c
@@ -2,9 +2,10 @@
|
||||
* jcsample.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains downsampling routines.
|
||||
@@ -144,7 +145,8 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
{
|
||||
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
|
||||
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
|
||||
JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
JSAMPROW inptr, outptr;
|
||||
INT32 outvalue;
|
||||
|
||||
@@ -189,12 +191,14 @@ METHODDEF(void)
|
||||
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY output_data)
|
||||
{
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Copy the data */
|
||||
jcopy_sample_rows(input_data, 0, output_data, 0,
|
||||
cinfo->max_v_samp_factor, cinfo->image_width);
|
||||
/* Edge-expand */
|
||||
expand_right_edge(output_data, cinfo->max_v_samp_factor,
|
||||
cinfo->image_width, compptr->width_in_data_units * cinfo->data_unit);
|
||||
cinfo->image_width, compptr->width_in_blocks * data_unit);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +220,8 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
{
|
||||
int outrow;
|
||||
JDIMENSION outcol;
|
||||
JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
register JSAMPROW inptr, outptr;
|
||||
register int bias;
|
||||
|
||||
@@ -253,7 +258,8 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
{
|
||||
int inrow, outrow;
|
||||
JDIMENSION outcol;
|
||||
JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
register JSAMPROW inptr0, inptr1, outptr;
|
||||
register int bias;
|
||||
|
||||
@@ -296,7 +302,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
{
|
||||
int inrow, outrow;
|
||||
JDIMENSION colctr;
|
||||
JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
|
||||
INT32 membersum, neighsum, memberscale, neighscale;
|
||||
|
||||
@@ -396,7 +403,8 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
int outrow;
|
||||
JDIMENSION colctr;
|
||||
JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
register JSAMPROW inptr, above_ptr, below_ptr, outptr;
|
||||
INT32 membersum, neighsum, memberscale, neighscale;
|
||||
int colsum, lastcolsum, nextcolsum;
|
||||
|
||||
64
jcscale.c
64
jcscale.c
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* jcscale.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains sample downscaling by 2^Pt for lossless JPEG.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
METHODDEF(void)
|
||||
simple_downscale(j_compress_ptr cinfo,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
int xindex;
|
||||
|
||||
for (xindex = 0; xindex < width; xindex++)
|
||||
output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]),
|
||||
cinfo->Al);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_compress_ptr cinfo,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
scaler_start_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
|
||||
/* Set scaler function based on Pt */
|
||||
if (cinfo->Al)
|
||||
losslsc->scaler_scale = simple_downscale;
|
||||
else
|
||||
losslsc->scaler_scale = noscale;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_c_scaler (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
|
||||
|
||||
losslsc->scaler_start_pass = scaler_start_pass;
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
663
jcshuff.c
663
jcshuff.c
@@ -1,663 +0,0 @@
|
||||
/*
|
||||
* jcshuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy encoding routines for sequential JPEG.
|
||||
*
|
||||
* Much of the complexity here has to do with supporting output suspension.
|
||||
* If the data destination module demands suspension, we want to be able to
|
||||
* back up to the start of the current MCU. To do this, we copy state
|
||||
* variables into local working storage, and update them back to the
|
||||
* permanent JPEG objects only upon successful completion of an MCU.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
|
||||
|
||||
/* Expanded entropy encoder object for Huffman encoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
INT32 put_buffer; /* current bit-accumulation buffer */
|
||||
int put_bits; /* # of bits now in it */
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest,src) \
|
||||
((dest).put_buffer = (src).put_buffer, \
|
||||
(dest).put_bits = (src).put_bits, \
|
||||
(dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
savable_state saved; /* Bit buffer & DC state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||
int next_restart_num; /* next restart number to write (0-7) */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||
c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
|
||||
long * dc_count_ptrs[NUM_HUFF_TBLS];
|
||||
long * ac_count_ptrs[NUM_HUFF_TBLS];
|
||||
#endif
|
||||
} shuff_entropy_encoder;
|
||||
|
||||
typedef shuff_entropy_encoder * shuff_entropy_ptr;
|
||||
|
||||
/* Working state while writing an MCU.
|
||||
* This struct contains all the fields that are needed by subroutines.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
JOCTET * next_output_byte; /* => next byte to write in buffer */
|
||||
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
|
||||
savable_state cur; /* Current bit buffer & DC state */
|
||||
j_compress_ptr cinfo; /* dump_buffer needs access to this */
|
||||
} working_state;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
* If gather_statistics is TRUE, we do not output anything during the scan,
|
||||
* just count the Huffman symbols used and generate Huffman code tables.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
|
||||
int ci, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
if (gather_statistics) {
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
lossyc->entropy_encode_mcu = encode_mcu_gather;
|
||||
lossyc->pub.entropy_finish_pass = finish_pass_gather;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
lossyc->entropy_encode_mcu = encode_mcu_huff;
|
||||
lossyc->pub.entropy_finish_pass = finish_pass_huff;
|
||||
}
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
if (gather_statistics) {
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
/* Check for invalid table indexes */
|
||||
/* (make_c_derived_tbl does this in the other path) */
|
||||
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
|
||||
if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
|
||||
/* Allocate and zero the statistics tables */
|
||||
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
|
||||
if (entropy->dc_count_ptrs[dctbl] == NULL)
|
||||
entropy->dc_count_ptrs[dctbl] = (long *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
257 * SIZEOF(long));
|
||||
MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
|
||||
if (entropy->ac_count_ptrs[actbl] == NULL)
|
||||
entropy->ac_count_ptrs[actbl] = (long *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
257 * SIZEOF(long));
|
||||
MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
|
||||
#endif
|
||||
} else {
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for a table, but it's not expensive */
|
||||
jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
|
||||
& entropy->dc_derived_tbls[dctbl]);
|
||||
jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
|
||||
& entropy->ac_derived_tbls[actbl]);
|
||||
}
|
||||
/* Initialize DC predictions to 0 */
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Initialize bit buffer to empty */
|
||||
entropy->saved.put_buffer = 0;
|
||||
entropy->saved.put_bits = 0;
|
||||
|
||||
/* Initialize restart stuff */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
entropy->next_restart_num = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Outputting bytes to the file */
|
||||
|
||||
/* Emit a byte, taking 'action' if must suspend. */
|
||||
#define emit_byte(state,val,action) \
|
||||
{ *(state)->next_output_byte++ = (JOCTET) (val); \
|
||||
if (--(state)->free_in_buffer == 0) \
|
||||
if (! dump_buffer(state)) \
|
||||
{ action; } }
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
dump_buffer (working_state * state)
|
||||
/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
|
||||
{
|
||||
struct jpeg_destination_mgr * dest = state->cinfo->dest;
|
||||
|
||||
if (! (*dest->empty_output_buffer) (state->cinfo))
|
||||
return FALSE;
|
||||
/* After a successful buffer dump, must reset buffer pointers */
|
||||
state->next_output_byte = dest->next_output_byte;
|
||||
state->free_in_buffer = dest->free_in_buffer;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Outputting bits to the file */
|
||||
|
||||
/* Only the right 24 bits of put_buffer are used; the valid bits are
|
||||
* left-justified in this part. At most 16 bits can be passed to emit_bits
|
||||
* in one call, and we never retain more than 7 bits in put_buffer
|
||||
* between calls, so 24 bits are sufficient.
|
||||
*/
|
||||
|
||||
INLINE
|
||||
LOCAL(boolean)
|
||||
emit_bits (working_state * state, unsigned int code, int size)
|
||||
/* Emit some bits; return TRUE if successful, FALSE if must suspend */
|
||||
{
|
||||
/* This routine is heavily used, so it's worth coding tightly. */
|
||||
register INT32 put_buffer = (INT32) code;
|
||||
register int put_bits = state->cur.put_bits;
|
||||
|
||||
/* if size is 0, caller used an invalid Huffman table entry */
|
||||
if (size == 0)
|
||||
ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
|
||||
|
||||
put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
|
||||
|
||||
put_bits += size; /* new number of bits in buffer */
|
||||
|
||||
put_buffer <<= 24 - put_bits; /* align incoming bits */
|
||||
|
||||
put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
|
||||
|
||||
while (put_bits >= 8) {
|
||||
int c = (int) ((put_buffer >> 16) & 0xFF);
|
||||
|
||||
emit_byte(state, c, return FALSE);
|
||||
if (c == 0xFF) { /* need to stuff a zero byte? */
|
||||
emit_byte(state, 0, return FALSE);
|
||||
}
|
||||
put_buffer <<= 8;
|
||||
put_bits -= 8;
|
||||
}
|
||||
|
||||
state->cur.put_buffer = put_buffer; /* update state variables */
|
||||
state->cur.put_bits = put_bits;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
flush_bits (working_state * state)
|
||||
{
|
||||
if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
|
||||
return FALSE;
|
||||
state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
|
||||
state->cur.put_bits = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Encode a single block's worth of coefficients */
|
||||
|
||||
LOCAL(boolean)
|
||||
encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
|
||||
c_derived_tbl *dctbl, c_derived_tbl *actbl)
|
||||
{
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
register int k, r, i;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = temp2 = block[0] - last_dc_val;
|
||||
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (nbits) /* emit_bits rejects calls with size 0 */
|
||||
if (! emit_bits(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[jpeg_natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
|
||||
return FALSE;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
temp2 = temp;
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit Huffman symbol for run length / number of bits */
|
||||
i = (r << 4) + nbits;
|
||||
if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (! emit_bits(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emit a restart marker & resynchronize predictions.
|
||||
*/
|
||||
|
||||
LOCAL(boolean)
|
||||
emit_restart (working_state * state, int restart_num)
|
||||
{
|
||||
int ci;
|
||||
|
||||
if (! flush_bits(state))
|
||||
return FALSE;
|
||||
|
||||
emit_byte(state, 0xFF, return FALSE);
|
||||
emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
|
||||
state->cur.last_dc_val[ci] = 0;
|
||||
|
||||
/* The restart counter is not updated until we successfully write the MCU. */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode and output one MCU's worth of Huffman-compressed coefficients.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
|
||||
working_state state;
|
||||
int blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Load up working state */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cinfo = cinfo;
|
||||
|
||||
/* Emit restart marker if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0)
|
||||
if (! emit_restart(&state, entropy->next_restart_num))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Encode the MCU data blocks */
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
if (! encode_one_block(&state,
|
||||
MCU_data[blkn][0], state.cur.last_dc_val[ci],
|
||||
entropy->dc_derived_tbls[compptr->dc_tbl_no],
|
||||
entropy->ac_derived_tbls[compptr->ac_tbl_no]))
|
||||
return FALSE;
|
||||
/* Update last_dc_val */
|
||||
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
|
||||
/* Update restart-interval state too */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0) {
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
entropy->next_restart_num++;
|
||||
entropy->next_restart_num &= 7;
|
||||
}
|
||||
entropy->restarts_to_go--;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_huff (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
|
||||
working_state state;
|
||||
|
||||
/* Load up working state ... flush_bits needs it */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cinfo = cinfo;
|
||||
|
||||
/* Flush out the last data */
|
||||
if (! flush_bits(&state))
|
||||
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||
|
||||
/* Update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Huffman coding optimization.
|
||||
*
|
||||
* We first scan the supplied data and count the number of uses of each symbol
|
||||
* that is to be Huffman-coded. (This process MUST agree with the code above.)
|
||||
* Then we build a Huffman coding tree for the observed counts.
|
||||
* Symbols which are not needed at all for the particular image are not
|
||||
* assigned any code, which saves space in the DHT marker as well as in
|
||||
* the compressed data.
|
||||
*/
|
||||
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
|
||||
|
||||
/* Process a single block's worth of coefficients */
|
||||
|
||||
LOCAL(void)
|
||||
htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
|
||||
long dc_counts[], long ac_counts[])
|
||||
{
|
||||
register int temp;
|
||||
register int nbits;
|
||||
register int k, r;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = block[0] - last_dc_val;
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[nbits]++;
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
if ((temp = block[jpeg_natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
ac_counts[0xF0]++;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count Huffman symbol for run length / number of bits */
|
||||
ac_counts[(r << 4) + nbits]++;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0)
|
||||
ac_counts[0]++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Trial-encode one MCU's worth of Huffman-compressed coefficients.
|
||||
* No data is actually output, so no suspension return is possible.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
|
||||
int blkn, ci;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Take care of restart intervals if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0) {
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
/* Update restart state */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
entropy->restarts_to_go--;
|
||||
}
|
||||
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
|
||||
entropy->dc_count_ptrs[compptr->dc_tbl_no],
|
||||
entropy->ac_count_ptrs[compptr->ac_tbl_no]);
|
||||
entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up a statistics-gathering pass and create the new Huffman tables.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_gather (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
|
||||
int ci, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
JHUFF_TBL **htblptr;
|
||||
boolean did_dc[NUM_HUFF_TBLS];
|
||||
boolean did_ac[NUM_HUFF_TBLS];
|
||||
|
||||
/* It's important not to apply jpeg_gen_optimal_table more than once
|
||||
* per table, because it clobbers the input frequency counts!
|
||||
*/
|
||||
MEMZERO(did_dc, SIZEOF(did_dc));
|
||||
MEMZERO(did_ac, SIZEOF(did_ac));
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
if (! did_dc[dctbl]) {
|
||||
htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
|
||||
did_dc[dctbl] = TRUE;
|
||||
}
|
||||
if (! did_ac[actbl]) {
|
||||
htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
|
||||
if (*htblptr == NULL)
|
||||
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
|
||||
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
|
||||
did_ac[actbl] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
METHODDEF(boolean)
|
||||
need_optimization_pass (j_compress_ptr cinfo)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_shuff_encoder (j_compress_ptr cinfo)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (shuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(shuff_entropy_encoder));
|
||||
lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
|
||||
lossyc->pub.entropy_start_pass = start_pass_huff;
|
||||
lossyc->pub.need_optimization_pass = need_optimization_pass;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
112
jctrans.c
112
jctrans.c
@@ -4,7 +4,7 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains library routines for transcoding compression,
|
||||
@@ -15,14 +15,11 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
LOCAL(void) transencode_master_selection
|
||||
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
|
||||
LOCAL(void) transencode_codec
|
||||
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
|
||||
LOCAL(void) transencode_coef_controller
|
||||
JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
|
||||
|
||||
@@ -42,6 +39,9 @@ LOCAL(void) transencode_coef_controller
|
||||
GLOBAL(void)
|
||||
jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
|
||||
{
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if (cinfo->global_state != CSTATE_START)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
/* Mark all tables to be written */
|
||||
@@ -73,6 +73,9 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
|
||||
JQUANT_TBL *c_quant, *slot_quant;
|
||||
int tblno, ci, coefi;
|
||||
|
||||
if (srcinfo->master->lossless)
|
||||
ERREXIT(dstinfo, JERR_NOTIMPL);
|
||||
|
||||
/* Safety check to ensure start_compress not called yet. */
|
||||
if (dstinfo->global_state != CSTATE_START)
|
||||
ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
|
||||
@@ -163,7 +166,6 @@ LOCAL(void)
|
||||
transencode_master_selection (j_compress_ptr cinfo,
|
||||
jvirt_barray_ptr * coef_arrays)
|
||||
{
|
||||
cinfo->data_unit = DCTSIZE;
|
||||
/* Although we don't actually use input_components for transcoding,
|
||||
* jcmaster.c's initial_setup will complain if input_components is 0.
|
||||
*/
|
||||
@@ -171,8 +173,22 @@ transencode_master_selection (j_compress_ptr cinfo,
|
||||
/* Initialize master control (includes parameter checking/processing) */
|
||||
jinit_c_master_control(cinfo, TRUE /* transcode only */);
|
||||
|
||||
/* We need a special compression codec. */
|
||||
transencode_codec(cinfo, coef_arrays);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_encoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* We need a special coefficient buffer controller. */
|
||||
transencode_coef_controller(cinfo, coef_arrays);
|
||||
|
||||
jinit_marker_writer(cinfo);
|
||||
|
||||
@@ -198,6 +214,8 @@ transencode_master_selection (j_compress_ptr cinfo,
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_c_coef_controller pub; /* public fields */
|
||||
|
||||
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
@@ -207,18 +225,17 @@ typedef struct {
|
||||
jvirt_barray_ptr * whole_image;
|
||||
|
||||
/* Workspace for constructing dummy blocks at right/bottom edges. */
|
||||
JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU];
|
||||
} c_coef_controller;
|
||||
JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||
} my_coef_controller;
|
||||
|
||||
typedef c_coef_controller * c_coef_ptr;
|
||||
typedef my_coef_controller * my_coef_ptr;
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
start_iMCU_row (j_compress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row */
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
@@ -245,8 +262,7 @@ start_iMCU_row (j_compress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
if (pass_mode != JBUF_CRANK_DEST)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
@@ -269,15 +285,14 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
METHODDEF(boolean)
|
||||
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int blkn, ci, xindex, yindex, yoffset, blockcnt;
|
||||
JDIMENSION start_col;
|
||||
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||
JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
|
||||
JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
|
||||
JBLOCKROW buffer_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
@@ -327,7 +342,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
}
|
||||
}
|
||||
/* Try to write the MCU. */
|
||||
if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) {
|
||||
if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->mcu_ctr = MCU_col_num;
|
||||
@@ -348,7 +363,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
* Initialize coefficient buffer controller.
|
||||
*
|
||||
* Each passed coefficient array must be the right size for that
|
||||
* coefficient: width_in_data_units wide and height_in_data_units high,
|
||||
* coefficient: width_in_blocks wide and height_in_blocks high,
|
||||
* with unitheight at least v_samp_factor.
|
||||
*/
|
||||
|
||||
@@ -356,15 +371,16 @@ LOCAL(void)
|
||||
transencode_coef_controller (j_compress_ptr cinfo,
|
||||
jvirt_barray_ptr * coef_arrays)
|
||||
{
|
||||
j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
|
||||
c_coef_ptr coef;
|
||||
my_coef_ptr coef;
|
||||
JBLOCKROW buffer;
|
||||
int i;
|
||||
|
||||
coef = (c_coef_ptr)
|
||||
coef = (my_coef_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(c_coef_controller));
|
||||
lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
|
||||
SIZEOF(my_coef_controller));
|
||||
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
|
||||
coef->pub.start_pass = start_pass_coef;
|
||||
coef->pub.compress_data = compress_output;
|
||||
|
||||
/* Save pointer to virtual arrays */
|
||||
coef->whole_image = coef_arrays;
|
||||
@@ -372,51 +388,9 @@ transencode_coef_controller (j_compress_ptr cinfo,
|
||||
/* Allocate and pre-zero space for dummy DCT blocks. */
|
||||
buffer = (JBLOCKROW)
|
||||
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
|
||||
jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
|
||||
C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||
jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
|
||||
coef->dummy_buffer[i] = buffer + i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the transencoer codec.
|
||||
* This is called only once, during master selection.
|
||||
*/
|
||||
|
||||
LOCAL(void)
|
||||
transencode_codec (j_compress_ptr cinfo,
|
||||
jvirt_barray_ptr * coef_arrays)
|
||||
{
|
||||
j_lossy_c_ptr lossyc;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
lossyc = (j_lossy_c_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(jpeg_lossy_c_codec));
|
||||
cinfo->codec = (struct jpeg_c_codec *) lossyc;
|
||||
|
||||
/* Initialize sub-modules */
|
||||
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_encoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_shuff_encoder(cinfo);
|
||||
}
|
||||
|
||||
/* We need a special coefficient buffer controller. */
|
||||
transencode_coef_controller(cinfo, coef_arrays);
|
||||
|
||||
/* Initialize method pointers */
|
||||
lossyc->pub.start_pass = start_pass_coef;
|
||||
lossyc->pub.compress_data = compress_output;
|
||||
}
|
||||
|
||||
19
jdapimin.c
19
jdapimin.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the decompression half
|
||||
@@ -21,6 +22,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -82,6 +84,14 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
|
||||
|
||||
/* OK, I'm ready */
|
||||
cinfo->global_state = DSTATE_START;
|
||||
|
||||
/* The master struct is used to store extension parameters, so we allocate it
|
||||
* here.
|
||||
*/
|
||||
cinfo->master = (struct jpeg_decomp_master *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(my_decomp_master));
|
||||
MEMZERO(cinfo->master, SIZEOF(my_decomp_master));
|
||||
}
|
||||
|
||||
|
||||
@@ -151,14 +161,11 @@ default_decompress_parms (j_decompress_ptr cinfo)
|
||||
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
|
||||
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||
else {
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2);
|
||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
||||
if (cinfo->master->lossless)
|
||||
cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */
|
||||
}
|
||||
else { /* Lossy processes */
|
||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2);
|
||||
else
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Always guess RGB is proper output colorspace. */
|
||||
|
||||
11
jdapistd.c
11
jdapistd.c
@@ -2,9 +2,9 @@
|
||||
* jdapistd.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the decompression half
|
||||
@@ -189,6 +189,9 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
||||
{
|
||||
JDIMENSION lines_per_iMCU_row;
|
||||
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if (cinfo->global_state != DSTATE_RAW_OK)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||
@@ -204,12 +207,12 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
||||
}
|
||||
|
||||
/* Verify that at least one iMCU row can be returned. */
|
||||
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_codec_data_unit;
|
||||
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
|
||||
if (max_lines < lines_per_iMCU_row)
|
||||
ERREXIT(cinfo, JERR_BUFFER_SIZE);
|
||||
|
||||
/* Decompress directly into user's buffer. */
|
||||
if (! (*cinfo->codec->decompress_data) (cinfo, data))
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo, data))
|
||||
return 0; /* suspension forced, can do nothing more */
|
||||
|
||||
/* OK, we processed one iMCU row. */
|
||||
|
||||
115
jdcoefct.c
115
jdcoefct.c
@@ -2,9 +2,9 @@
|
||||
* jdcoefct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the coefficient buffer controller for decompression.
|
||||
@@ -19,7 +19,6 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h"
|
||||
|
||||
/* Block smoothing is only applicable for progressive JPEG, so: */
|
||||
#ifndef D_PROGRESSIVE_SUPPORTED
|
||||
@@ -29,6 +28,8 @@
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_d_coef_controller pub; /* public fields */
|
||||
|
||||
/* These variables keep track of the current location of the input side. */
|
||||
/* cinfo->input_iMCU_row is also used for this. */
|
||||
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||
@@ -38,7 +39,7 @@ typedef struct {
|
||||
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||
|
||||
/* In single-pass modes, it's sufficient to buffer just one MCU.
|
||||
* We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks,
|
||||
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
|
||||
* and let the entropy decoder write into that workspace each time.
|
||||
* (On 80x86, the workspace is FAR even though it's not really very big;
|
||||
* this is to keep the module interfaces unchanged when a large coefficient
|
||||
@@ -46,7 +47,7 @@ typedef struct {
|
||||
* In multi-pass modes, this array points to the current MCU's blocks
|
||||
* within the virtual arrays; it is used only by the input side.
|
||||
*/
|
||||
JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU];
|
||||
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||
@@ -58,9 +59,9 @@ typedef struct {
|
||||
int * coef_bits_latch;
|
||||
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
||||
#endif
|
||||
} d_coef_controller;
|
||||
} my_coef_controller;
|
||||
|
||||
typedef d_coef_controller * d_coef_ptr;
|
||||
typedef my_coef_controller * my_coef_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(int) decompress_onepass
|
||||
@@ -80,8 +81,7 @@ LOCAL(void)
|
||||
start_iMCU_row (j_decompress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
@@ -121,15 +121,14 @@ METHODDEF(void)
|
||||
start_output_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* If multipass, check to see whether to use block smoothing on this pass */
|
||||
if (lossyd->coef_arrays != NULL) {
|
||||
if (coef->pub.coef_arrays != NULL) {
|
||||
if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
|
||||
lossyd->pub.decompress_data = decompress_smooth_data;
|
||||
coef->pub.decompress_data = decompress_smooth_data;
|
||||
else
|
||||
lossyd->pub.decompress_data = decompress_data;
|
||||
coef->pub.decompress_data = decompress_data;
|
||||
}
|
||||
#endif
|
||||
cinfo->output_iMCU_row = 0;
|
||||
@@ -149,8 +148,7 @@ start_output_pass (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
@@ -167,8 +165,8 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
MCU_col_num++) {
|
||||
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
|
||||
jzero_far((void FAR *) coef->MCU_buffer[0],
|
||||
(size_t) (cinfo->data_units_in_MCU * SIZEOF(JBLOCK)));
|
||||
if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
|
||||
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->MCU_ctr = MCU_col_num;
|
||||
@@ -184,14 +182,14 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Don't bother to IDCT an uninteresting component. */
|
||||
if (! compptr->component_needed) {
|
||||
blkn += compptr->MCU_data_units;
|
||||
blkn += compptr->MCU_blocks;
|
||||
continue;
|
||||
}
|
||||
inverse_DCT = lossyd->inverse_DCT[compptr->component_index];
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
|
||||
useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
|
||||
: compptr->last_col_width;
|
||||
output_ptr = output_buf[compptr->component_index] +
|
||||
yoffset * compptr->codec_data_unit;
|
||||
yoffset * compptr->DCT_scaled_size;
|
||||
start_col = MCU_col_num * compptr->MCU_sample_width;
|
||||
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||
if (cinfo->input_iMCU_row < last_iMCU_row ||
|
||||
@@ -201,11 +199,11 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
(*inverse_DCT) (cinfo, compptr,
|
||||
(JCOEFPTR) coef->MCU_buffer[blkn+xindex],
|
||||
output_ptr, output_col);
|
||||
output_col += compptr->codec_data_unit;
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
blkn += compptr->MCU_width;
|
||||
output_ptr += compptr->codec_data_unit;
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,8 +245,7 @@ dummy_consume_data (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
consume_data (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
int blkn, ci, xindex, yindex, yoffset;
|
||||
JDIMENSION start_col;
|
||||
@@ -287,7 +284,7 @@ consume_data (j_decompress_ptr cinfo)
|
||||
}
|
||||
}
|
||||
/* Try to fetch the MCU. */
|
||||
if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->MCU_ctr = MCU_col_num;
|
||||
@@ -319,8 +316,7 @@ consume_data (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION block_num;
|
||||
int ci, block_row, block_rows;
|
||||
@@ -355,22 +351,22 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
block_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
}
|
||||
inverse_DCT = lossyd->inverse_DCT[ci];
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||
output_ptr = output_buf[ci];
|
||||
/* Loop over all DCT blocks to be processed. */
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
buffer_ptr = buffer[block_row];
|
||||
output_col = 0;
|
||||
for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) {
|
||||
for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
|
||||
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
|
||||
output_ptr, output_col);
|
||||
buffer_ptr++;
|
||||
output_col += compptr->codec_data_unit;
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
output_ptr += compptr->codec_data_unit;
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,8 +406,7 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
LOCAL(boolean)
|
||||
smoothing_ok (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
boolean smoothing_useful = FALSE;
|
||||
int ci, coefi;
|
||||
jpeg_component_info *compptr;
|
||||
@@ -419,7 +414,7 @@ smoothing_ok (j_decompress_ptr cinfo)
|
||||
int * coef_bits;
|
||||
int * coef_bits_latch;
|
||||
|
||||
if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL)
|
||||
if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Allocate latch area if not already done */
|
||||
@@ -467,8 +462,7 @@ smoothing_ok (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION block_num, last_block_column;
|
||||
int ci, block_row, block_rows, access_rows;
|
||||
@@ -516,7 +510,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
last_row = FALSE;
|
||||
} else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
access_rows = block_rows; /* this iMCU row only */
|
||||
last_row = TRUE;
|
||||
@@ -545,7 +539,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
Q20 = quanttbl->quantval[Q20_POS];
|
||||
Q11 = quanttbl->quantval[Q11_POS];
|
||||
Q02 = quanttbl->quantval[Q02_POS];
|
||||
inverse_DCT = lossyd->inverse_DCT[ci];
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||
output_ptr = output_buf[ci];
|
||||
/* Loop over all DCT blocks to be processed. */
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
@@ -565,7 +559,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
|
||||
DC7 = DC8 = DC9 = (int) next_block_row[0][0];
|
||||
output_col = 0;
|
||||
last_block_column = compptr->width_in_data_units - 1;
|
||||
last_block_column = compptr->width_in_blocks - 1;
|
||||
for (block_num = 0; block_num <= last_block_column; block_num++) {
|
||||
/* Fetch current DCT block into workspace so we can modify it. */
|
||||
jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
|
||||
@@ -662,9 +656,9 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
DC4 = DC5; DC5 = DC6;
|
||||
DC7 = DC8; DC8 = DC9;
|
||||
buffer_ptr++, prev_block_row++, next_block_row++;
|
||||
output_col += compptr->codec_data_unit;
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
output_ptr += compptr->codec_data_unit;
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,15 +677,14 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
GLOBAL(void)
|
||||
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
d_coef_ptr coef;
|
||||
my_coef_ptr coef;
|
||||
|
||||
coef = (d_coef_ptr)
|
||||
coef = (my_coef_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(d_coef_controller));
|
||||
lossyd->coef_private = (void *) coef;
|
||||
lossyd->coef_start_input_pass = start_input_pass;
|
||||
lossyd->coef_start_output_pass = start_output_pass;
|
||||
SIZEOF(my_coef_controller));
|
||||
cinfo->coef = (struct jpeg_d_coef_controller *) coef;
|
||||
coef->pub.start_input_pass = start_input_pass;
|
||||
coef->pub.start_output_pass = start_output_pass;
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
coef->coef_bits_latch = NULL;
|
||||
#endif
|
||||
@@ -710,20 +703,20 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
access_rows = compptr->v_samp_factor;
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
/* If block smoothing could be used, need a bigger window */
|
||||
if (cinfo->process == JPROC_PROGRESSIVE)
|
||||
if (cinfo->progressive_mode)
|
||||
access_rows *= 3;
|
||||
#endif
|
||||
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) access_rows);
|
||||
}
|
||||
lossyd->pub.consume_data = consume_data;
|
||||
lossyd->pub.decompress_data = decompress_data;
|
||||
lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */
|
||||
coef->pub.consume_data = consume_data;
|
||||
coef->pub.decompress_data = decompress_data;
|
||||
coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
@@ -734,12 +727,12 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
|
||||
buffer = (JBLOCKROW)
|
||||
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) {
|
||||
D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
|
||||
coef->MCU_buffer[i] = buffer + i;
|
||||
}
|
||||
lossyd->pub.consume_data = dummy_consume_data;
|
||||
lossyd->pub.decompress_data = decompress_onepass;
|
||||
lossyd->coef_arrays = NULL; /* flag for no virtual arrays */
|
||||
coef->pub.consume_data = dummy_consume_data;
|
||||
coef->pub.decompress_data = decompress_onepass;
|
||||
coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
|
||||
}
|
||||
}
|
||||
|
||||
15
jdcolor.c
15
jdcolor.c
@@ -1,8 +1,10 @@
|
||||
/*
|
||||
* jdcolor.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains output colorspace conversion routines.
|
||||
@@ -340,10 +342,15 @@ jinit_color_deconverter (j_decompress_ptr cinfo)
|
||||
/* Set out_color_components and conversion method based on requested space.
|
||||
* Also clear the component_needed flags for any unused components,
|
||||
* so that earlier pipeline stages can avoid useless computation.
|
||||
* NOTE: We do not allow any lossy color conversion algorithms in lossless
|
||||
* mode.
|
||||
*/
|
||||
|
||||
switch (cinfo->out_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->jpeg_color_space != cinfo->out_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = 1;
|
||||
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
||||
cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
@@ -356,6 +363,9 @@ jinit_color_deconverter (j_decompress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_RGB:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->jpeg_color_space != JCS_RGB)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = RGB_PIXELSIZE;
|
||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
cconvert->pub.color_convert = ycc_rgb_convert;
|
||||
@@ -369,6 +379,9 @@ jinit_color_deconverter (j_decompress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->jpeg_color_space != cinfo->out_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = 4;
|
||||
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
||||
cconvert->pub.color_convert = ycck_cmyk_convert;
|
||||
|
||||
33
jddctmgr.c
33
jddctmgr.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* jddctmgr.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the inverse-DCT management logic.
|
||||
@@ -20,7 +18,6 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy subsystem */
|
||||
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||
|
||||
|
||||
@@ -44,15 +41,17 @@
|
||||
/* Private subobject for this module */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_inverse_dct pub; /* public fields */
|
||||
|
||||
/* This array contains the IDCT method code that each multiplier table
|
||||
* is currently set up for, or -1 if it's not yet set up.
|
||||
* The actual multiplier tables are pointed to by dct_table in the
|
||||
* per-component comp_info structures.
|
||||
*/
|
||||
int cur_method[MAX_COMPONENTS];
|
||||
} idct_controller;
|
||||
} my_idct_controller;
|
||||
|
||||
typedef idct_controller * idct_ptr;
|
||||
typedef my_idct_controller * my_idct_ptr;
|
||||
|
||||
|
||||
/* Allocated multiplier tables: big enough for any supported variant */
|
||||
@@ -89,8 +88,7 @@ typedef union {
|
||||
METHODDEF(void)
|
||||
start_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
idct_ptr idct = (idct_ptr) lossyd->idct_private;
|
||||
my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
|
||||
int ci, i;
|
||||
jpeg_component_info *compptr;
|
||||
int method = 0;
|
||||
@@ -100,7 +98,7 @@ start_pass (j_decompress_ptr cinfo)
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Select the proper IDCT routine for this component's scaling */
|
||||
switch (compptr->codec_data_unit) {
|
||||
switch (compptr->DCT_scaled_size) {
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
case 1:
|
||||
method_ptr = jpeg_idct_1x1;
|
||||
@@ -141,10 +139,10 @@ start_pass (j_decompress_ptr cinfo)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit);
|
||||
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
|
||||
break;
|
||||
}
|
||||
lossyd->inverse_DCT[ci] = method_ptr;
|
||||
idct->pub.inverse_DCT[ci] = method_ptr;
|
||||
/* Create multiplier table from quant table.
|
||||
* However, we can skip this if the component is uninteresting
|
||||
* or if we already built the table. Also, if no quant table
|
||||
@@ -248,16 +246,15 @@ start_pass (j_decompress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jinit_inverse_dct (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
idct_ptr idct;
|
||||
my_idct_ptr idct;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
idct = (idct_ptr)
|
||||
idct = (my_idct_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(idct_controller));
|
||||
lossyd->idct_private = (void *) idct;
|
||||
lossyd->idct_start_pass = start_pass;
|
||||
SIZEOF(my_idct_controller));
|
||||
cinfo->idct = (struct jpeg_inverse_dct *) idct;
|
||||
idct->pub.start_pass = start_pass;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
|
||||
144
jddiffct.c
144
jddiffct.c
@@ -2,9 +2,10 @@
|
||||
* jddiffct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the [un]difference buffer controller for decompression.
|
||||
@@ -20,7 +21,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
@@ -28,10 +29,13 @@
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_d_coef_controller pub; /* public fields */
|
||||
|
||||
/* These variables keep track of the current location of the input side. */
|
||||
/* cinfo->input_iMCU_row is also used for this. */
|
||||
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||
unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */
|
||||
unsigned int restart_rows_to_go; /* MCU rows left in this restart
|
||||
interval */
|
||||
unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
@@ -44,9 +48,9 @@ typedef struct {
|
||||
/* In multi-pass modes, we need a virtual sample array for each component. */
|
||||
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
|
||||
#endif
|
||||
} d_diff_controller;
|
||||
} my_diff_controller;
|
||||
|
||||
typedef d_diff_controller * d_diff_ptr;
|
||||
typedef my_diff_controller * my_diff_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(int) decompress_data
|
||||
@@ -61,8 +65,7 @@ LOCAL(void)
|
||||
start_iMCU_row (j_decompress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
@@ -89,11 +92,17 @@ start_iMCU_row (j_decompress_ptr cinfo)
|
||||
METHODDEF(void)
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
|
||||
/* Because it is hitching a ride on the jpeg_inverse_dct struct,
|
||||
* start_pass_lossless() will be called at the start of the output pass.
|
||||
* This ensures that it will be called at the start of the input pass as
|
||||
* well.
|
||||
*/
|
||||
(*cinfo->idct->start_pass) (cinfo);
|
||||
|
||||
/* Check that the restart interval is an integer multiple of the number
|
||||
* of MCU in an MCU-row.
|
||||
* of MCUs in an MCU row.
|
||||
*/
|
||||
if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
|
||||
ERREXIT2(cinfo, JERR_BAD_RESTART,
|
||||
@@ -115,13 +124,12 @@ start_input_pass (j_decompress_ptr cinfo)
|
||||
METHODDEF(boolean)
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
|
||||
if (! (*losslsd->entropy_process_restart) (cinfo))
|
||||
if (! (*cinfo->entropy->process_restart) (cinfo))
|
||||
return FALSE;
|
||||
|
||||
(*losslsd->predict_process_restart) (cinfo);
|
||||
(*cinfo->idct->start_pass) (cinfo);
|
||||
|
||||
/* Reset restart counter */
|
||||
diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
|
||||
@@ -154,12 +162,12 @@ start_output_pass (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr) cinfo->idct;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION MCU_count; /* number of MCUs decoded */
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int comp, ci, yoffset, row, prev_row;
|
||||
int ci, compi, yoffset, row, prev_row;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Loop to process as much as one whole iMCU row */
|
||||
@@ -174,11 +182,11 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
|
||||
MCU_col_num = diff->MCU_ctr;
|
||||
/* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */
|
||||
/* Try to fetch an MCU row (or remaining portion of suspended MCU row). */
|
||||
MCU_count =
|
||||
(*losslsd->entropy_decode_mcus) (cinfo,
|
||||
diff->diff_buf, yoffset, MCU_col_num,
|
||||
cinfo->MCUs_per_row - MCU_col_num);
|
||||
(*cinfo->entropy->decode_mcus) (cinfo,
|
||||
diff->diff_buf, yoffset, MCU_col_num,
|
||||
cinfo->MCUs_per_row - MCU_col_num);
|
||||
if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
diff->MCU_vert_offset = yoffset;
|
||||
@@ -194,25 +202,24 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Undifference and scale each scanline of the disassembled MCU-row
|
||||
* Undifference and scale each scanline of the disassembled MCU row
|
||||
* separately. We do not process dummy samples at the end of a scanline
|
||||
* or dummy rows at the end of the image.
|
||||
*/
|
||||
for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
|
||||
compptr = cinfo->cur_comp_info[comp];
|
||||
ci = compptr->component_index;
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
compi = compptr->component_index;
|
||||
for (row = 0, prev_row = compptr->v_samp_factor - 1;
|
||||
row < (cinfo->input_iMCU_row == last_iMCU_row ?
|
||||
compptr->last_row_height : compptr->v_samp_factor);
|
||||
prev_row = row, row++) {
|
||||
(*losslsd->predict_undifference[ci]) (cinfo, ci,
|
||||
diff->diff_buf[ci][row],
|
||||
diff->undiff_buf[ci][prev_row],
|
||||
diff->undiff_buf[ci][row],
|
||||
compptr->width_in_data_units);
|
||||
(*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row],
|
||||
output_buf[ci][row],
|
||||
compptr->width_in_data_units);
|
||||
(*losslessd->predict_undifference[compi])
|
||||
(cinfo, compi, diff->diff_buf[compi][row],
|
||||
diff->undiff_buf[compi][prev_row], diff->undiff_buf[compi][row],
|
||||
compptr->width_in_blocks);
|
||||
(*losslessd->scaler_scale) (cinfo, diff->undiff_buf[compi][row],
|
||||
output_buf[compi][row],
|
||||
compptr->width_in_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,21 +262,16 @@ dummy_consume_data (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
consume_data (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION MCU_count; /* number of MCUs decoded */
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int comp, ci, yoffset, row, prev_row;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
int ci;
|
||||
JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Align the virtual buffers for the components used in this scan. */
|
||||
for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
|
||||
compptr = cinfo->cur_comp_info[comp];
|
||||
ci = compptr->component_index;
|
||||
buffer[ci] = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, diff->whole_image[ci],
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
buffer[compptr->component_index] = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, diff->whole_image[compptr->component_index],
|
||||
cinfo->input_iMCU_row * compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
}
|
||||
@@ -279,7 +281,7 @@ consume_data (j_decompress_ptr cinfo)
|
||||
|
||||
|
||||
/*
|
||||
* Output some data from the full-image buffer sample in the multi-pass case.
|
||||
* Output some data from the full-image sample buffer in the multi-pass case.
|
||||
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*
|
||||
@@ -289,8 +291,7 @@ consume_data (j_decompress_ptr cinfo)
|
||||
METHODDEF(int)
|
||||
output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
|
||||
my_diff_ptr diff = (my_diff_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int ci, samp_rows, row;
|
||||
JSAMPARRAY buffer;
|
||||
@@ -317,13 +318,13 @@ output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
samp_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
samp_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
|
||||
}
|
||||
|
||||
for (row = 0; row < samp_rows; row++) {
|
||||
MEMCOPY(output_buf[ci][row], buffer[row],
|
||||
compptr->width_in_data_units * SIZEOF(JSAMPLE));
|
||||
compptr->width_in_blocks * SIZEOF(JSAMPLE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,31 +343,30 @@ output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
GLOBAL(void)
|
||||
jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
d_diff_ptr diff;
|
||||
my_diff_ptr diff;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
diff = (d_diff_ptr)
|
||||
diff = (my_diff_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(d_diff_controller));
|
||||
losslsd->diff_private = (void *) diff;
|
||||
losslsd->diff_start_input_pass = start_input_pass;
|
||||
losslsd->pub.start_output_pass = start_output_pass;
|
||||
SIZEOF(my_diff_controller));
|
||||
cinfo->coef = (struct jpeg_d_coef_controller *) diff;
|
||||
diff->pub.start_input_pass = start_input_pass;
|
||||
diff->pub.start_output_pass = start_output_pass;
|
||||
|
||||
/* Create the [un]difference buffers. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
diff->diff_buf[ci] =
|
||||
ALLOC_DARRAY(JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
diff->undiff_buf[ci] =
|
||||
ALLOC_DARRAY(JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
|
||||
if (need_full_buffer) {
|
||||
@@ -379,20 +379,20 @@ jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
access_rows = compptr->v_samp_factor;
|
||||
diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) access_rows);
|
||||
}
|
||||
losslsd->pub.consume_data = consume_data;
|
||||
losslsd->pub.decompress_data = output_data;
|
||||
diff->pub.consume_data = consume_data;
|
||||
diff->pub.decompress_data = output_data;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
losslsd->pub.consume_data = dummy_consume_data;
|
||||
losslsd->pub.decompress_data = decompress_data;
|
||||
diff->pub.consume_data = dummy_consume_data;
|
||||
diff->pub.decompress_data = decompress_data;
|
||||
diff->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||
}
|
||||
}
|
||||
|
||||
371
jdhuff.c
371
jdhuff.c
@@ -2,26 +2,150 @@
|
||||
* jdhuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines which are shared
|
||||
* by the sequential, progressive and lossless decoders.
|
||||
* This file contains Huffman entropy decoding routines.
|
||||
*
|
||||
* Much of the complexity here has to do with supporting input suspension.
|
||||
* If the data source module demands suspension, we want to be able to back
|
||||
* up to the start of the current MCU. To do this, we copy state variables
|
||||
* into local working storage, and update them back to the permanent
|
||||
* storage only upon successful completion of an MCU.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
|
||||
|
||||
/*
|
||||
* Expanded entropy decoder object for Huffman decoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest,src) \
|
||||
((dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
/* These fields are loaded into local variables at start of each MCU.
|
||||
* In case of suspension, we exit WITHOUT updating them.
|
||||
*/
|
||||
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||
savable_state saved; /* Other state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||
d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
/* Precalculated info set up by start_pass for use in decode_mcu: */
|
||||
|
||||
/* Pointers to derived tables to be used for each block within an MCU */
|
||||
d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
|
||||
d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
|
||||
/* Whether we care about the DC and AC coefficient values for each block */
|
||||
boolean dc_needed[D_MAX_BLOCKS_IN_MCU];
|
||||
boolean ac_needed[D_MAX_BLOCKS_IN_MCU];
|
||||
} huff_entropy_decoder;
|
||||
|
||||
typedef huff_entropy_decoder * huff_entropy_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_huff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci, blkn, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
|
||||
* This ought to be an error condition, but we make it a warning because
|
||||
* there are some baseline files out there with all zeroes in these bytes.
|
||||
*/
|
||||
if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
|
||||
cinfo->Ah != 0 || cinfo->Al != 0)
|
||||
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for a table, but it's not expensive */
|
||||
jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
|
||||
& entropy->dc_derived_tbls[dctbl]);
|
||||
jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
|
||||
& entropy->ac_derived_tbls[actbl]);
|
||||
/* Initialize DC predictions to 0 */
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Precalculate decoding info for each block in an MCU of this scan */
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Precalculate which table to use for each block */
|
||||
entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
|
||||
entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
|
||||
/* Decide whether we really care about the coefficient values */
|
||||
if (compptr->component_needed) {
|
||||
entropy->dc_needed[blkn] = TRUE;
|
||||
/* we don't need the ACs if producing a 1/8th-size image */
|
||||
entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1);
|
||||
} else {
|
||||
entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
/* Initialize restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute the derived values for a Huffman table.
|
||||
* This routine also performs some validation checks on the table.
|
||||
*
|
||||
* Note this is also used by jdphuff.c and jdlhuff.c.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
@@ -131,14 +255,14 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||
|
||||
/* Validate symbols as being reasonable.
|
||||
* For AC tables, we make no check, but accept all byte values 0..255.
|
||||
* For DC tables, we require the symbols to be in range 0..16.
|
||||
* (Tighter bounds could be applied depending on the data depth and mode,
|
||||
* but this is sufficient to ensure safe decoding.)
|
||||
* For DC tables, we require the symbols to be in range 0..15 in lossy mode
|
||||
* and 0..16 in lossless mode. (Tighter bounds could be applied depending on
|
||||
* the data depth and mode, but this is sufficient to ensure safe decoding.)
|
||||
*/
|
||||
if (isDC) {
|
||||
for (i = 0; i < numsymbols; i++) {
|
||||
int sym = htbl->huffval[i];
|
||||
if (sym < 0 || sym > 16)
|
||||
if (sym < 0 || sym > (cinfo->master->lossless ? 16 : 15))
|
||||
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||
}
|
||||
}
|
||||
@@ -146,7 +270,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||
|
||||
|
||||
/*
|
||||
* Out-of-line code for bit fetching.
|
||||
* Out-of-line code for bit fetching (shared with jdphuff.c and jdlhuff.c).
|
||||
* See jdhuff.h for info about usage.
|
||||
* Note: current values of get_buffer and bits_left are passed as parameters,
|
||||
* but are returned in the corresponding fields of the state struct.
|
||||
@@ -248,14 +372,9 @@ jpeg_fill_bit_buffer (bitread_working_state * state,
|
||||
* We use a nonvolatile flag to ensure that only one warning message
|
||||
* appears per data segment.
|
||||
*/
|
||||
huffd_common_ptr huffd;
|
||||
if (cinfo->process == JPROC_LOSSLESS)
|
||||
huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private;
|
||||
else
|
||||
huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private;
|
||||
if (! huffd->insufficient_data) {
|
||||
if (! cinfo->entropy->insufficient_data) {
|
||||
WARNMS(cinfo, JWRN_HIT_MARKER);
|
||||
huffd->insufficient_data = TRUE;
|
||||
cinfo->entropy->insufficient_data = TRUE;
|
||||
}
|
||||
/* Fill the buffer with zero bits */
|
||||
get_buffer <<= MIN_GET_BITS - bits_left;
|
||||
@@ -315,3 +434,221 @@ jpeg_huff_decode (bitread_working_state * state,
|
||||
|
||||
return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Figure F.12: extend sign bit.
|
||||
* On some machines, a shift and add will be faster than a table lookup.
|
||||
*/
|
||||
|
||||
#ifdef AVOID_TABLES
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||
|
||||
#else
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
|
||||
|
||||
static const int extend_test[16] = /* entry n is 2**(n-1) */
|
||||
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
||||
|
||||
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
|
||||
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
|
||||
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
|
||||
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
|
||||
|
||||
#endif /* AVOID_TABLES */
|
||||
|
||||
|
||||
/*
|
||||
* Check for a restart marker & resynchronize decoder.
|
||||
* Returns FALSE if must suspend.
|
||||
*/
|
||||
|
||||
LOCAL(boolean)
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci;
|
||||
|
||||
/* Throw away any unused bits remaining in bit buffer; */
|
||||
/* include any full bytes in next_marker's count of discarded bytes */
|
||||
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
|
||||
entropy->bitstate.bits_left = 0;
|
||||
|
||||
/* Advance past the RSTn marker */
|
||||
if (! (*cinfo->marker->read_restart_marker) (cinfo))
|
||||
return FALSE;
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
|
||||
/* Reset restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
|
||||
/* Reset out-of-data flag, unless read_restart_marker left us smack up
|
||||
* against a marker. In that case we will end up treating the next data
|
||||
* segment as empty, and we can avoid producing bogus output pixels by
|
||||
* leaving the flag set.
|
||||
*/
|
||||
if (cinfo->unread_marker == 0)
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode and return one MCU's worth of Huffman-compressed coefficients.
|
||||
* The coefficients are reordered from zigzag order into natural array order,
|
||||
* but are not dequantized.
|
||||
*
|
||||
* The i'th block of the MCU is stored into the block pointed to by
|
||||
* MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
|
||||
* (Wholesale zeroing is usually a little faster than retail...)
|
||||
*
|
||||
* Returns FALSE if data source requested suspension. In that case no
|
||||
* changes have been made to permanent state. (Exception: some output
|
||||
* coefficients may already have been assigned. This is harmless for
|
||||
* this module, since we'll just re-assign them on the next call.)
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int blkn;
|
||||
BITREAD_STATE_VARS;
|
||||
savable_state state;
|
||||
|
||||
/* Process restart marker if needed; may have to suspend */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0)
|
||||
if (! process_restart(cinfo))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||
* This way, we return uniform gray for the remainder of the segment.
|
||||
*/
|
||||
if (! entropy->pub.insufficient_data) {
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
JBLOCKROW block = MCU_data[blkn];
|
||||
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
||||
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
||||
register int s, k, r;
|
||||
|
||||
/* Decode a single block's worth of coefficients */
|
||||
|
||||
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||
HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
|
||||
if (s) {
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
}
|
||||
|
||||
if (entropy->dc_needed[blkn]) {
|
||||
/* Convert DC difference to actual value, update last_dc_val */
|
||||
int ci = cinfo->MCU_membership[blkn];
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||
(*block)[0] = (JCOEF) s;
|
||||
}
|
||||
|
||||
if (entropy->ac_needed[blkn]) {
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* Since zeroes are skipped, output area must be cleared beforehand */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
/* Output coefficient in natural (dezigzagged) order.
|
||||
* Note: the extra entries in jpeg_natural_order[] will save us
|
||||
* if k >= DCTSIZE2, which could happen if the data is corrupted.
|
||||
*/
|
||||
(*block)[jpeg_natural_order[k]] = (JCOEF) s;
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* In this path we just discard the values */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
DROP_BITS(s);
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_huff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (huff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(huff_entropy_decoder));
|
||||
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_huff_decoder;
|
||||
entropy->pub.decode_mcu = decode_mcu;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
35
jdhuff.h
35
jdhuff.h
@@ -2,15 +2,15 @@
|
||||
* jdhuff.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for Huffman entropy decoding routines
|
||||
* that are shared between the sequential decoder (jdhuff.c), the
|
||||
* progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c).
|
||||
* No other modules need to see these.
|
||||
* that are shared between the sequential decoder (jdhuff.c), the progressive
|
||||
* decoder (jdphuff.c), and the lossless decoder (jdlhuff.c). No other modules
|
||||
* need to see these.
|
||||
*/
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
@@ -202,30 +202,3 @@ slowlabel: \
|
||||
EXTERN(int) jpeg_huff_decode
|
||||
JPP((bitread_working_state * state, register bit_buf_type get_buffer,
|
||||
register int bits_left, d_derived_tbl * htbl, int min_bits));
|
||||
|
||||
|
||||
/* Common fields between sequential, progressive and lossless Huffman entropy
|
||||
* decoder master structs.
|
||||
*/
|
||||
|
||||
#define huffd_common_fields \
|
||||
boolean insufficient_data; /* set TRUE after emmitting warning */ \
|
||||
/* These fields are loaded into local variables at start of each MCU. \
|
||||
* In case of suspension, we exit WITHOUT updating them. \
|
||||
*/ \
|
||||
bitread_perm_state bitstate /* Bit buffer at start of MCU */
|
||||
|
||||
/* Routines that are to be used by any or all of the entropy decoders are
|
||||
* declared to receive a pointer to this structure. There are no actual
|
||||
* instances of huffd_common_struct, only of shuff_entropy_decoder,
|
||||
* phuff_entropy_decoder and lhuff_entropy_decoder.
|
||||
*/
|
||||
struct huffd_common_struct {
|
||||
huffd_common_fields; /* Fields common to all decoder struct types */
|
||||
/* Additional fields follow in an actual shuff_entropy_decoder,
|
||||
* phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs
|
||||
* must agree on these initial fields! (This would be a lot cleaner in C++.)
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct huffd_common_struct * huffd_common_ptr;
|
||||
|
||||
134
jdinput.c
134
jdinput.c
@@ -2,9 +2,10 @@
|
||||
* jdinput.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains input control logic for the JPEG decompressor.
|
||||
@@ -44,19 +45,19 @@ initial_setup (j_decompress_ptr cinfo)
|
||||
{
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Make sure image isn't bigger than I can handle */
|
||||
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
|
||||
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
|
||||
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
|
||||
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
if (cinfo->master->lossless) {
|
||||
/* If precision > compiled-in value, we must downscale */
|
||||
if (cinfo->data_precision > BITS_IN_JSAMPLE)
|
||||
WARNMS2(cinfo, JWRN_MUST_DOWNSCALE,
|
||||
cinfo->data_precision, BITS_IN_JSAMPLE);
|
||||
}
|
||||
else { /* Lossy processes */
|
||||
} else {
|
||||
/* For now, precision must match compiled-in value... */
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
@@ -81,23 +82,23 @@ initial_setup (j_decompress_ptr cinfo)
|
||||
compptr->v_samp_factor);
|
||||
}
|
||||
|
||||
/* We initialize codec_data_unit and min_codec_data_unit to data_unit.
|
||||
* In the full decompressor, this will be overridden by jdmaster.c;
|
||||
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE in lossy
|
||||
* mode. In the full decompressor, this will be overridden by jdmaster.c;
|
||||
* but in the transcoder, jdmaster.c is not used, so we must do it here.
|
||||
*/
|
||||
cinfo->min_codec_data_unit = cinfo->data_unit;
|
||||
cinfo->min_DCT_scaled_size = data_unit;
|
||||
|
||||
/* Compute dimensions of components */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
compptr->codec_data_unit = cinfo->data_unit;
|
||||
compptr->DCT_scaled_size = data_unit;
|
||||
/* Size in data units */
|
||||
compptr->width_in_data_units = (JDIMENSION)
|
||||
compptr->width_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||
(long) (cinfo->max_h_samp_factor * cinfo->data_unit));
|
||||
compptr->height_in_data_units = (JDIMENSION)
|
||||
(long) (cinfo->max_h_samp_factor * data_unit));
|
||||
compptr->height_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||
(long) (cinfo->max_v_samp_factor * cinfo->data_unit));
|
||||
(long) (cinfo->max_v_samp_factor * data_unit));
|
||||
/* downsampled_width and downsampled_height will also be overridden by
|
||||
* jdmaster.c if we are doing full decompression. The transcoder library
|
||||
* doesn't use these values, but the calling application might.
|
||||
@@ -118,11 +119,10 @@ initial_setup (j_decompress_ptr cinfo)
|
||||
/* Compute number of fully interleaved MCU rows. */
|
||||
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*cinfo->data_unit));
|
||||
(long) (cinfo->max_v_samp_factor*data_unit));
|
||||
|
||||
/* Decide whether file contains multiple scans */
|
||||
if (cinfo->comps_in_scan < cinfo->num_components ||
|
||||
cinfo->process == JPROC_PROGRESSIVE)
|
||||
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
||||
cinfo->inputctl->has_multiple_scans = TRUE;
|
||||
else
|
||||
cinfo->inputctl->has_multiple_scans = FALSE;
|
||||
@@ -136,31 +136,32 @@ per_scan_setup (j_decompress_ptr cinfo)
|
||||
{
|
||||
int ci, mcublks, tmp;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
|
||||
/* Noninterleaved (single-component) scan */
|
||||
compptr = cinfo->cur_comp_info[0];
|
||||
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = compptr->width_in_data_units;
|
||||
cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
|
||||
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||
|
||||
/* For noninterleaved scan, always one data unit per MCU */
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_data_units = 1;
|
||||
compptr->MCU_sample_width = compptr->codec_data_unit;
|
||||
compptr->MCU_blocks = 1;
|
||||
compptr->MCU_sample_width = compptr->DCT_scaled_size;
|
||||
compptr->last_col_width = 1;
|
||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||
* as the number of data unit rows present in the last iMCU row.
|
||||
*/
|
||||
tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||
compptr->last_row_height = tmp;
|
||||
|
||||
/* Prepare array describing MCU composition */
|
||||
cinfo->data_units_in_MCU = 1;
|
||||
cinfo->blocks_in_MCU = 1;
|
||||
cinfo->MCU_membership[0] = 0;
|
||||
|
||||
} else {
|
||||
@@ -173,33 +174,33 @@ per_scan_setup (j_decompress_ptr cinfo)
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width,
|
||||
(long) (cinfo->max_h_samp_factor*cinfo->data_unit));
|
||||
(long) (cinfo->max_h_samp_factor*data_unit));
|
||||
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*cinfo->data_unit));
|
||||
(long) (cinfo->max_v_samp_factor*data_unit));
|
||||
|
||||
cinfo->data_units_in_MCU = 0;
|
||||
cinfo->blocks_in_MCU = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Sampling factors give # of data units of component in each MCU */
|
||||
compptr->MCU_width = compptr->h_samp_factor;
|
||||
compptr->MCU_height = compptr->v_samp_factor;
|
||||
compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit;
|
||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
|
||||
/* Figure number of non-dummy data units in last MCU column & row */
|
||||
tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
|
||||
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||
if (tmp == 0) tmp = compptr->MCU_width;
|
||||
compptr->last_col_width = tmp;
|
||||
tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||
if (tmp == 0) tmp = compptr->MCU_height;
|
||||
compptr->last_row_height = tmp;
|
||||
/* Prepare array describing MCU composition */
|
||||
mcublks = compptr->MCU_data_units;
|
||||
if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU)
|
||||
mcublks = compptr->MCU_blocks;
|
||||
if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
|
||||
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||
while (mcublks-- > 0) {
|
||||
cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
|
||||
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +208,54 @@ per_scan_setup (j_decompress_ptr cinfo)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save away a copy of the Q-table referenced by each component present
|
||||
* in the current scan, unless already saved during a prior scan.
|
||||
*
|
||||
* In a multiple-scan JPEG file, the encoder could assign different components
|
||||
* the same Q-table slot number, but change table definitions between scans
|
||||
* so that each component uses a different Q-table. (The IJG encoder is not
|
||||
* currently capable of doing this, but other encoders might.) Since we want
|
||||
* to be able to dequantize all the components at the end of the file, this
|
||||
* means that we have to save away the table actually used for each component.
|
||||
* We do this by copying the table at the start of the first scan containing
|
||||
* the component.
|
||||
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
|
||||
* slot between scans of a component using that slot. If the encoder does so
|
||||
* anyway, this decoder will simply use the Q-table values that were current
|
||||
* at the start of the first scan for the component.
|
||||
*
|
||||
* The decompressor output side looks only at the saved quant tables,
|
||||
* not at the current Q-table slots.
|
||||
*/
|
||||
|
||||
LOCAL(void)
|
||||
latch_quant_tables (j_decompress_ptr cinfo)
|
||||
{
|
||||
int ci, qtblno;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL * qtbl;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* No work if we already saved Q-table for this component */
|
||||
if (compptr->quant_table != NULL)
|
||||
continue;
|
||||
/* Make sure specified quantization table is present */
|
||||
qtblno = compptr->quant_tbl_no;
|
||||
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||
/* OK, save away the quantization table */
|
||||
qtbl = (JQUANT_TBL *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(JQUANT_TBL));
|
||||
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
|
||||
compptr->quant_table = qtbl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the input modules to read a scan of compressed data.
|
||||
* The first call to this is done by jdmaster.c after initializing
|
||||
@@ -218,15 +267,18 @@ METHODDEF(void)
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
per_scan_setup(cinfo);
|
||||
(*cinfo->codec->start_input_pass) (cinfo);
|
||||
cinfo->inputctl->consume_input = cinfo->codec->consume_data;
|
||||
if (! cinfo->master->lossless)
|
||||
latch_quant_tables(cinfo);
|
||||
(*cinfo->entropy->start_pass) (cinfo);
|
||||
(*cinfo->coef->start_input_pass) (cinfo);
|
||||
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up after inputting a compressed-data scan.
|
||||
* This is called by the coefficient controller after it's read all
|
||||
* the expected data of the scan.
|
||||
* This is called by the coefficient or difference controller after it's read
|
||||
* all the expected data of the scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
@@ -242,8 +294,8 @@ finish_input_pass (j_decompress_ptr cinfo)
|
||||
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*
|
||||
* The consume_input method pointer points either here or to the
|
||||
* coefficient controller's consume_data routine, depending on whether
|
||||
* we are reading a compressed data segment or inter-segment markers.
|
||||
* coefficient or difference controller's consume_data routine, depending on
|
||||
* whether we are reading a compressed data segment or inter-segment markers.
|
||||
*/
|
||||
|
||||
METHODDEF(int)
|
||||
@@ -261,12 +313,6 @@ consume_markers (j_decompress_ptr cinfo)
|
||||
case JPEG_REACHED_SOS: /* Found SOS */
|
||||
if (inputctl->inheaders) { /* 1st SOS */
|
||||
initial_setup(cinfo);
|
||||
/*
|
||||
* Initialize the decompression codec. We need to do this here so that
|
||||
* any codec-specific fields and function pointers are available to
|
||||
* the rest of the library.
|
||||
*/
|
||||
jinit_d_codec(cinfo);
|
||||
inputctl->inheaders = FALSE;
|
||||
/* Note: start_input_pass must be called by jdmaster.c
|
||||
* before any more input can be consumed. jdapimin.c is
|
||||
|
||||
67
jdlhuff.c
67
jdlhuff.c
@@ -2,9 +2,10 @@
|
||||
* jdlhuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines for lossless JPEG.
|
||||
@@ -30,11 +31,16 @@ typedef struct {
|
||||
} lhd_output_ptr_info;
|
||||
|
||||
/*
|
||||
* Private entropy decoder object for lossless Huffman decoding.
|
||||
* Expanded entropy decoder object for Huffman decoding in lossless mode.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
huffd_common_fields; /* Fields shared with other entropy decoders */
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
/* These fields are loaded into local variables at start of each MCU.
|
||||
* In case of suspension, we exit WITHOUT updating them.
|
||||
*/
|
||||
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
|
||||
@@ -42,12 +48,12 @@ typedef struct {
|
||||
/* Precalculated info set up by start_pass for use in decode_mcus: */
|
||||
|
||||
/* Pointers to derived tables to be used for each data unit within an MCU */
|
||||
d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
|
||||
d_derived_tbl * cur_tbls[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* Pointers to the proper output difference row for each group of data units
|
||||
* within an MCU. For each component, there are Vi groups of Hi data units.
|
||||
*/
|
||||
JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU];
|
||||
JDIFFROW output_ptr[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* Number of output pointers in use for the current MCU. This is the sum
|
||||
* of all Vi in the MCU.
|
||||
@@ -57,10 +63,10 @@ typedef struct {
|
||||
/* Information used for positioning the output pointers within the output
|
||||
* difference rows.
|
||||
*/
|
||||
lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU];
|
||||
lhd_output_ptr_info output_ptr_info[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
/* Index of the proper output pointer for each data unit within an MCU */
|
||||
int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU];
|
||||
int output_ptr_index[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
} lhuff_entropy_decoder;
|
||||
|
||||
@@ -74,8 +80,7 @@ typedef lhuff_entropy_decoder * lhuff_entropy_ptr;
|
||||
METHODDEF(void)
|
||||
start_pass_lhuff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl, sampn, ptrn, yoffset, xoffset;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
@@ -93,7 +98,7 @@ start_pass_lhuff_decoder (j_decompress_ptr cinfo)
|
||||
}
|
||||
|
||||
/* Precalculate decoding info for each sample in an MCU of this scan */
|
||||
for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
|
||||
for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) {
|
||||
compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
|
||||
ci = compptr->component_index;
|
||||
for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
|
||||
@@ -114,7 +119,7 @@ start_pass_lhuff_decoder (j_decompress_ptr cinfo)
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->insufficient_data = FALSE;
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -149,12 +154,10 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||
* Returns FALSE if must suspend.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
LOCAL(boolean)
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
|
||||
int ci;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
|
||||
/* Throw away any unused bits remaining in bit buffer; */
|
||||
/* include any full bytes in next_marker's count of discarded bytes */
|
||||
@@ -171,23 +174,23 @@ process_restart (j_decompress_ptr cinfo)
|
||||
* leaving the flag set.
|
||||
*/
|
||||
if (cinfo->unread_marker == 0)
|
||||
entropy->insufficient_data = FALSE;
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode and return nMCU's worth of Huffman-compressed differences.
|
||||
* Decode and return nMCU MCUs' worth of Huffman-compressed differences.
|
||||
* Each MCU is also disassembled and placed accordingly in diff_buf.
|
||||
*
|
||||
* MCU_col_num specifies the column of the first MCU being requested within
|
||||
* the MCU-row. This tells us where to position the output row pointers in
|
||||
* the MCU row. This tells us where to position the output row pointers in
|
||||
* diff_buf.
|
||||
*
|
||||
* Returns the number of MCUs decoded. This may be less than nMCU if data
|
||||
* source requested suspension. In that case no changes have been made to
|
||||
* permanent state. (Exception: some output differences may already have
|
||||
* Returns the number of MCUs decoded. This may be less than nMCU MCUs if
|
||||
* data source requested suspension. In that case no changes have been made
|
||||
* to permanent state. (Exception: some output differences may already have
|
||||
* been assigned. This is harmless for this module, since we'll just
|
||||
* re-assign them on the next call.)
|
||||
*/
|
||||
@@ -196,8 +199,7 @@ METHODDEF(JDIMENSION)
|
||||
decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) cinfo->entropy;
|
||||
int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
|
||||
BITREAD_STATE_VARS;
|
||||
|
||||
@@ -217,12 +219,12 @@ decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
* NB: We should find a way to do this without interacting with the
|
||||
* undifferencer module directly.
|
||||
*/
|
||||
if (entropy->insufficient_data) {
|
||||
if (entropy->pub.insufficient_data) {
|
||||
for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++)
|
||||
jzero_far((void FAR *) entropy->output_ptr[ptrn],
|
||||
nMCU * entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF));
|
||||
|
||||
(*losslsd->predict_process_restart) (cinfo);
|
||||
(*cinfo->idct->start_pass) (cinfo);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -230,12 +232,12 @@ decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
|
||||
/* Outer loop handles the number of MCU requested */
|
||||
/* Outer loop handles the number of MCUs requested */
|
||||
|
||||
for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
|
||||
|
||||
/* Inner loop handles the samples in the MCU */
|
||||
for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
|
||||
for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
|
||||
d_derived_tbl * dctbl = entropy->cur_tbls[sampn];
|
||||
register int s, r;
|
||||
|
||||
@@ -265,23 +267,22 @@ decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for lossless Huffman entropy decoding.
|
||||
* Module initialization routine for lossless mode Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lhuff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
lhuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (lhuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(lhuff_entropy_decoder));
|
||||
losslsd->entropy_private = (void *) entropy;
|
||||
losslsd->entropy_start_pass = start_pass_lhuff_decoder;
|
||||
losslsd->entropy_process_restart = process_restart;
|
||||
losslsd->entropy_decode_mcus = decode_mcus;
|
||||
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_lhuff_decoder;
|
||||
entropy->pub.decode_mcus = decode_mcus;
|
||||
entropy->pub.process_restart = process_restart;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
|
||||
319
jdlossls.c
319
jdlossls.c
@@ -5,9 +5,11 @@
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the control logic for the lossless JPEG decompressor.
|
||||
* This file contains prediction, sample undifferencing, point transform, and
|
||||
* sample scaling routines for the lossless JPEG decompressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
@@ -15,22 +17,234 @@
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h"
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
|
||||
/**************** Sample undifferencing (reconstruction) *****************/
|
||||
|
||||
/*
|
||||
* Compute output image dimensions and related values.
|
||||
* In order to avoid a performance penalty for checking which predictor is
|
||||
* being used and which row is being processed for each call of the
|
||||
* undifferencer, and to promote optimization, we have separate undifferencing
|
||||
* functions for each predictor selection value.
|
||||
*
|
||||
* We are able to avoid duplicating source code by implementing the predictors
|
||||
* and undifferencers as macros. Each of the undifferencing functions is
|
||||
* simply a wrapper around an UNDIFFERENCE macro with the appropriate PREDICTOR
|
||||
* macro passed as an argument.
|
||||
*/
|
||||
|
||||
/* Predictor for the first column of the first row: 2^(P-Pt-1) */
|
||||
#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
|
||||
|
||||
/* Predictor for the first column of the remaining rows: Rb */
|
||||
#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
|
||||
|
||||
|
||||
/*
|
||||
* 1-Dimensional undifferencer routine.
|
||||
*
|
||||
* This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
|
||||
* is used as the special case predictor for the first column, which must be
|
||||
* either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
|
||||
* use PREDICTOR1.
|
||||
*
|
||||
* The reconstructed sample is supposed to be calculated modulo 2^16, so we
|
||||
* logically AND the result with 0xFFFF.
|
||||
*/
|
||||
|
||||
#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \
|
||||
int Ra; \
|
||||
\
|
||||
Ra = (*diff_buf++ + INITIAL_PREDICTOR) & 0xFFFF; \
|
||||
*undiff_buf++ = Ra; \
|
||||
\
|
||||
while (--width) { \
|
||||
Ra = (*diff_buf++ + PREDICTOR1) & 0xFFFF; \
|
||||
*undiff_buf++ = Ra; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 2-Dimensional undifferencer routine.
|
||||
*
|
||||
* This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
|
||||
* used as the special case predictor for the first column. The remaining
|
||||
* samples use PREDICTOR, which is a function of Ra, Rb, and Rc.
|
||||
*
|
||||
* Because prev_row and output_buf may point to the same storage area (in an
|
||||
* interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
|
||||
* before writing the current reconstructed sample value into output_buf.
|
||||
*
|
||||
* The reconstructed sample is supposed to be calculated modulo 2^16, so we
|
||||
* logically AND the result with 0xFFFF.
|
||||
*/
|
||||
|
||||
#define UNDIFFERENCE_2D(PREDICTOR) \
|
||||
int Ra, Rb, Rc; \
|
||||
\
|
||||
Rb = GETJSAMPLE(*prev_row++); \
|
||||
Ra = (*diff_buf++ + PREDICTOR2) & 0xFFFF; \
|
||||
*undiff_buf++ = Ra; \
|
||||
\
|
||||
while (--width) { \
|
||||
Rc = Rb; \
|
||||
Rb = GETJSAMPLE(*prev_row++); \
|
||||
Ra = (*diff_buf++ + PREDICTOR) & 0xFFFF; \
|
||||
*undiff_buf++ = Ra; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Undifferencers for the second and subsequent rows in a scan or restart
|
||||
* interval. The first sample in the row is undifferenced using the vertical
|
||||
* predictor (2). The rest of the samples are undifferenced using the
|
||||
* predictor specified in the scan header.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
calc_output_dimensions (j_decompress_ptr cinfo)
|
||||
jpeg_undifference1(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
/* jdinput.c has already initialized codec_data_unit to 1,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
UNDIFFERENCE_1D(INITIAL_PREDICTOR2);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference2(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR2);
|
||||
(void)(Rc);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference3(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR3);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference4(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR4);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference5(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR5);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference6(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR6);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference7(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR7);
|
||||
(void)(Rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Undifferencer for the first row in a scan or restart interval. The first
|
||||
* sample in the row is undifferenced using the special predictor constant
|
||||
* x=2^(P-Pt-1). The rest of the samples are undifferenced using the
|
||||
* 1-D horizontal predictor (1).
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr) cinfo->idct;
|
||||
|
||||
UNDIFFERENCE_1D(INITIAL_PREDICTORx);
|
||||
|
||||
/*
|
||||
* Now that we have undifferenced the first row, we want to use the
|
||||
* undifferencer that corresponds to the predictor specified in the
|
||||
* scan header.
|
||||
*/
|
||||
switch (cinfo->Ss) {
|
||||
case 1:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference1;
|
||||
break;
|
||||
case 2:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference2;
|
||||
break;
|
||||
case 3:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference3;
|
||||
break;
|
||||
case 4:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference4;
|
||||
break;
|
||||
case 5:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference5;
|
||||
break;
|
||||
case 6:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference6;
|
||||
break;
|
||||
case 7:
|
||||
losslessd->predict_undifference[comp_index] = jpeg_undifference7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************** Sample scaling *****************************/
|
||||
|
||||
/*
|
||||
* This is a combination of upscaling the undifferenced sample by 2^Pt and
|
||||
* downscaling the sample to fit into JSAMPLE.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
simple_upscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr) cinfo->idct;
|
||||
|
||||
while (width--)
|
||||
*output_buf++ = (JSAMPLE) (*diff_buf++ << losslessd->scale_factor);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
simple_downscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr) cinfo->idct;
|
||||
|
||||
while (width--)
|
||||
*output_buf++ = (JSAMPLE) RIGHT_SHIFT(*diff_buf++,
|
||||
losslessd->scale_factor);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
while (width--)
|
||||
*output_buf++ = (JSAMPLE) *diff_buf++;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,58 +253,67 @@ calc_output_dimensions (j_decompress_ptr cinfo)
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
start_pass_lossless (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr) cinfo->idct;
|
||||
int ci, downscale;
|
||||
|
||||
(*losslsd->entropy_start_pass) (cinfo);
|
||||
(*losslsd->predict_start_pass) (cinfo);
|
||||
(*losslsd->scaler_start_pass) (cinfo);
|
||||
(*losslsd->diff_start_input_pass) (cinfo);
|
||||
/* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG.
|
||||
*
|
||||
* Ss is the predictor selection value (psv). Legal values for sequential
|
||||
* lossless JPEG are: 1 <= psv <= 7.
|
||||
*
|
||||
* Se and Ah are not used and should be zero.
|
||||
*
|
||||
* Al specifies the point transform (Pt).
|
||||
* Legal values are: 0 <= Pt <= (data precision - 1).
|
||||
*/
|
||||
if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
|
||||
cinfo->Se != 0 || cinfo->Ah != 0 ||
|
||||
cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision)
|
||||
ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
|
||||
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
|
||||
|
||||
/* Set undifference functions to first row function */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
losslessd->predict_undifference[ci] = jpeg_undifference_first_row;
|
||||
|
||||
/*
|
||||
* Downscale by the difference in the input vs. output precision. If the
|
||||
* output precision >= input precision, then do not downscale.
|
||||
*/
|
||||
downscale = BITS_IN_JSAMPLE < cinfo->data_precision ?
|
||||
cinfo->data_precision - BITS_IN_JSAMPLE : 0;
|
||||
|
||||
losslessd->scale_factor = cinfo->Al - downscale;
|
||||
|
||||
/* Set scaler functions based on scale_factor (positive = left shift) */
|
||||
if (losslessd->scale_factor > 0)
|
||||
losslessd->scaler_scale = simple_upscale;
|
||||
else if (losslessd->scale_factor < 0) {
|
||||
losslessd->scale_factor = -losslessd->scale_factor;
|
||||
losslessd->scaler_scale = simple_downscale;
|
||||
}
|
||||
else
|
||||
losslessd->scaler_scale = noscale;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the lossless decompression codec.
|
||||
* This is called only once, during master selection.
|
||||
* Initialize the lossless decompressor.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lossless_d_codec(j_decompress_ptr cinfo)
|
||||
jinit_lossless_decompressor(j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd;
|
||||
boolean use_c_buffer;
|
||||
lossless_decomp_ptr losslessd;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
losslsd = (j_lossless_d_ptr)
|
||||
losslessd = (lossless_decomp_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(jpeg_lossless_d_codec));
|
||||
cinfo->codec = (struct jpeg_d_codec *) losslsd;
|
||||
|
||||
/* Initialize sub-modules */
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
jinit_lhuff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Undifferencer */
|
||||
jinit_undifferencer(cinfo);
|
||||
|
||||
/* Scaler */
|
||||
jinit_d_scaler(cinfo);
|
||||
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
||||
jinit_d_diff_controller(cinfo, use_c_buffer);
|
||||
|
||||
/* Initialize method pointers.
|
||||
*
|
||||
* Note: consume_data, start_output_pass and decompress_data are
|
||||
* assigned in jddiffct.c.
|
||||
*/
|
||||
losslsd->pub.calc_output_dimensions = calc_output_dimensions;
|
||||
losslsd->pub.start_input_pass = start_input_pass;
|
||||
SIZEOF(jpeg_lossless_decompressor));
|
||||
cinfo->idct = (struct jpeg_inverse_dct *) losslessd;
|
||||
losslessd->pub.start_pass = start_pass_lossless;
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
|
||||
230
jdlossy.c
230
jdlossy.c
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* jdlossy.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the control logic for the lossy JPEG decompressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h"
|
||||
|
||||
|
||||
/*
|
||||
* Compute output image dimensions and related values.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
calc_output_dimensions (j_decompress_ptr cinfo)
|
||||
{
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
|
||||
/* Provide 1/8 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 8L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 8L);
|
||||
cinfo->min_codec_data_unit = 1;
|
||||
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
|
||||
/* Provide 1/4 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 4L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 4L);
|
||||
cinfo->min_codec_data_unit = 2;
|
||||
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
|
||||
/* Provide 1/2 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 2L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 2L);
|
||||
cinfo->min_codec_data_unit = 4;
|
||||
} else {
|
||||
/* Provide 1/1 scaling */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
cinfo->min_codec_data_unit = DCTSIZE;
|
||||
}
|
||||
/* In selecting the actual DCT scaling for each component, we try to
|
||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||
* Note this code assumes that the supported DCT scalings are powers of 2.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
int ssize = cinfo->min_codec_data_unit;
|
||||
while (ssize < DCTSIZE &&
|
||||
(compptr->h_samp_factor * ssize * 2 <=
|
||||
cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) &&
|
||||
(compptr->v_samp_factor * ssize * 2 <=
|
||||
cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) {
|
||||
ssize = ssize * 2;
|
||||
}
|
||||
compptr->codec_data_unit = ssize;
|
||||
}
|
||||
|
||||
/* Recompute downsampled dimensions of components;
|
||||
* application needs to know these if using raw downsampled data.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Size in samples, after IDCT scaling */
|
||||
compptr->downsampled_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width *
|
||||
(long) (compptr->h_samp_factor * compptr->codec_data_unit),
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
compptr->downsampled_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height *
|
||||
(long) (compptr->v_samp_factor * compptr->codec_data_unit),
|
||||
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||
}
|
||||
|
||||
#else /* !IDCT_SCALING_SUPPORTED */
|
||||
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
/* jdinput.c has already initialized codec_data_unit to DCTSIZE,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
*/
|
||||
|
||||
#endif /* IDCT_SCALING_SUPPORTED */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save away a copy of the Q-table referenced by each component present
|
||||
* in the current scan, unless already saved during a prior scan.
|
||||
*
|
||||
* In a multiple-scan JPEG file, the encoder could assign different components
|
||||
* the same Q-table slot number, but change table definitions between scans
|
||||
* so that each component uses a different Q-table. (The IJG encoder is not
|
||||
* currently capable of doing this, but other encoders might.) Since we want
|
||||
* to be able to dequantize all the components at the end of the file, this
|
||||
* means that we have to save away the table actually used for each component.
|
||||
* We do this by copying the table at the start of the first scan containing
|
||||
* the component.
|
||||
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
|
||||
* slot between scans of a component using that slot. If the encoder does so
|
||||
* anyway, this decoder will simply use the Q-table values that were current
|
||||
* at the start of the first scan for the component.
|
||||
*
|
||||
* The decompressor output side looks only at the saved quant tables,
|
||||
* not at the current Q-table slots.
|
||||
*/
|
||||
|
||||
LOCAL(void)
|
||||
latch_quant_tables (j_decompress_ptr cinfo)
|
||||
{
|
||||
int ci, qtblno;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL * qtbl;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* No work if we already saved Q-table for this component */
|
||||
if (compptr->quant_table != NULL)
|
||||
continue;
|
||||
/* Make sure specified quantization table is present */
|
||||
qtblno = compptr->quant_tbl_no;
|
||||
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||
/* OK, save away the quantization table */
|
||||
qtbl = (JQUANT_TBL *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(JQUANT_TBL));
|
||||
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
|
||||
compptr->quant_table = qtbl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
|
||||
latch_quant_tables(cinfo);
|
||||
(*lossyd->entropy_start_pass) (cinfo);
|
||||
(*lossyd->coef_start_input_pass) (cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an output processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_output_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
|
||||
(*lossyd->idct_start_pass) (cinfo);
|
||||
(*lossyd->coef_start_output_pass) (cinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the lossy decompression codec.
|
||||
* This is called only once, during master selection.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lossy_d_codec (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd;
|
||||
boolean use_c_buffer;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
lossyd = (j_lossy_d_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(jpeg_lossy_d_codec));
|
||||
cinfo->codec = (struct jpeg_d_codec *) lossyd;
|
||||
|
||||
/* Initialize sub-modules */
|
||||
|
||||
/* Inverse DCT */
|
||||
jinit_inverse_dct(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_shuff_decoder(cinfo);
|
||||
}
|
||||
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||
|
||||
/* Initialize method pointers.
|
||||
*
|
||||
* Note: consume_data and decompress_data are assigned in jdcoefct.c.
|
||||
*/
|
||||
lossyd->pub.calc_output_dimensions = calc_output_dimensions;
|
||||
lossyd->pub.start_input_pass = start_input_pass;
|
||||
lossyd->pub.start_output_pass = start_output_pass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
95
jdmainct.c
95
jdmainct.c
@@ -2,9 +2,9 @@
|
||||
* jdmainct.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the main buffer controller for decompression.
|
||||
@@ -22,35 +22,36 @@
|
||||
|
||||
/*
|
||||
* In the current system design, the main buffer need never be a full-image
|
||||
* buffer; any full-height buffers will be found inside the coefficient or
|
||||
* postprocessing controllers. Nonetheless, the main controller is not
|
||||
* trivial. Its responsibility is to provide context rows for upsampling/
|
||||
* rescaling, and doing this in an efficient fashion is a bit tricky.
|
||||
* buffer; any full-height buffers will be found inside the coefficient,
|
||||
* difference, or postprocessing controllers. Nonetheless, the main controller
|
||||
* is not trivial. Its responsibility is to provide context rows for
|
||||
* upsampling/rescaling, and doing this in an efficient fashion is a bit
|
||||
* tricky.
|
||||
*
|
||||
* Postprocessor input data is counted in "row groups". A row group
|
||||
* is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
|
||||
* sample rows of each component. (We require codec_data_unit values to be
|
||||
* chosen such that these numbers are integers. In practice codec_data_unit
|
||||
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||
* sample rows of each component. (We require DCT_scaled_size values to be
|
||||
* chosen such that these numbers are integers. In practice DCT_scaled_size
|
||||
* values will likely be powers of two, so we actually have the stronger
|
||||
* condition that codec_data_unit / min_codec_data_unit is an integer.)
|
||||
* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
|
||||
* Upsampling will typically produce max_v_samp_factor pixel rows from each
|
||||
* row group (times any additional scale factor that the upsampler is
|
||||
* applying).
|
||||
*
|
||||
* The decompression codec will deliver data to us one iMCU row at a time;
|
||||
* each iMCU row contains v_samp_factor * codec_data_unit sample rows, or
|
||||
* exactly min_codec_data_unit row groups. (This amount of data corresponds
|
||||
* to one row of MCUs when the image is fully interleaved.) Note that the
|
||||
* number of sample rows varies across components, but the number of row
|
||||
* groups does not. Some garbage sample rows may be included in the last iMCU
|
||||
* row at the bottom of the image.
|
||||
* The coefficient or difference controller will deliver data to us one iMCU
|
||||
* row at a time; each iMCU row contains v_samp_factor * DCT_scaled_size sample
|
||||
* rows, or exactly min_DCT_scaled_size row groups. (This amount of data
|
||||
* corresponds to one row of MCUs when the image is fully interleaved.) Note
|
||||
* that the number of sample rows varies across components, but the number of
|
||||
* row groups does not. Some garbage sample rows may be included in the last
|
||||
* iMCU row at the bottom of the image.
|
||||
*
|
||||
* Depending on the vertical scaling algorithm used, the upsampler may need
|
||||
* access to the sample row(s) above and below its current input row group.
|
||||
* The upsampler is required to set need_context_rows TRUE at global selection
|
||||
* time if so. When need_context_rows is FALSE, this controller can simply
|
||||
* obtain one iMCU row at a time from the coefficient controller and dole it
|
||||
* out as row groups to the postprocessor.
|
||||
* obtain one iMCU row at a time from the coefficient or difference controller
|
||||
* and dole it out as row groups to the postprocessor.
|
||||
*
|
||||
* When need_context_rows is TRUE, this controller guarantees that the buffer
|
||||
* passed to postprocessing contains at least one row group's worth of samples
|
||||
@@ -66,7 +67,7 @@
|
||||
* supporting arbitrary output rescaling might wish for more than one row
|
||||
* group of context when shrinking the image; tough, we don't handle that.
|
||||
* (This is justified by the assumption that downsizing will be handled mostly
|
||||
* by adjusting the codec_data_unit values, so that the actual scale factor at
|
||||
* by adjusting the DCT_scaled_size values, so that the actual scale factor at
|
||||
* the upsample step needn't be much less than one.)
|
||||
*
|
||||
* To provide the desired context, we have to retain the last two row groups
|
||||
@@ -76,7 +77,7 @@
|
||||
* We could do this most simply by copying data around in our buffer, but
|
||||
* that'd be very slow. We can avoid copying any data by creating a rather
|
||||
* strange pointer structure. Here's how it works. We allocate a workspace
|
||||
* consisting of M+2 row groups (where M = min_codec_data_unit is the number
|
||||
* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
|
||||
* of row groups per iMCU row). We create two sets of redundant pointers to
|
||||
* the workspace. Labeling the physical row groups 0 to M+1, the synthesized
|
||||
* pointer lists look like this:
|
||||
@@ -101,11 +102,11 @@
|
||||
* the first or last sample row as necessary (this is cheaper than copying
|
||||
* sample rows around).
|
||||
*
|
||||
* This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that
|
||||
* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
|
||||
* situation each iMCU row provides only one row group so the buffering logic
|
||||
* must be different (eg, we must read two iMCU rows before we can emit the
|
||||
* first row group). For now, we simply do not support providing context
|
||||
* rows when min_codec_data_unit is 1. That combination seems unlikely to
|
||||
* rows when min_DCT_scaled_size is 1. That combination seems unlikely to
|
||||
* be worth providing --- if someone wants a 1/8th-size preview, they probably
|
||||
* want it quick and dirty, so a context-free upsampler is sufficient.
|
||||
*/
|
||||
@@ -163,7 +164,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, rgroup;
|
||||
int M = cinfo->min_codec_data_unit;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY xbuf;
|
||||
|
||||
@@ -177,8 +178,8 @@ alloc_funny_pointers (j_decompress_ptr cinfo)
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit; /* height of a row group of component */
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
/* Get space for pointer lists --- M+4 row groups in each list.
|
||||
* We alloc both pointer lists with one call to save a few cycles.
|
||||
*/
|
||||
@@ -204,14 +205,14 @@ make_funny_pointers (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, i, rgroup;
|
||||
int M = cinfo->min_codec_data_unit;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY buf, xbuf0, xbuf1;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit; /* height of a row group of component */
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
xbuf0 = main->xbuffer[0][ci];
|
||||
xbuf1 = main->xbuffer[1][ci];
|
||||
/* First copy the workspace pointers as-is */
|
||||
@@ -244,14 +245,14 @@ set_wraparound_pointers (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, i, rgroup;
|
||||
int M = cinfo->min_codec_data_unit;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY xbuf0, xbuf1;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit; /* height of a row group of component */
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
xbuf0 = main->xbuffer[0][ci];
|
||||
xbuf1 = main->xbuffer[1][ci];
|
||||
for (i = 0; i < rgroup; i++) {
|
||||
@@ -279,8 +280,8 @@ set_bottom_pointers (j_decompress_ptr cinfo)
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Count sample rows in one iMCU row and in one row group */
|
||||
iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit;
|
||||
rgroup = iMCUheight / cinfo->min_codec_data_unit;
|
||||
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
|
||||
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
|
||||
/* Count nondummy sample rows remaining for this component */
|
||||
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
|
||||
if (rows_left == 0) rows_left = iMCUheight;
|
||||
@@ -353,13 +354,13 @@ process_data_simple_main (j_decompress_ptr cinfo,
|
||||
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
if (! main->buffer_full) {
|
||||
if (! (*cinfo->codec->decompress_data) (cinfo, main->buffer))
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
|
||||
return; /* suspension forced, can do nothing more */
|
||||
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||
}
|
||||
|
||||
/* There are always min_codec_data_unit row groups in an iMCU row. */
|
||||
rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit;
|
||||
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
|
||||
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
|
||||
/* Note: at the bottom of the image, we may pass extra garbage row groups
|
||||
* to the postprocessor. The postprocessor has to check for bottom
|
||||
* of image anyway (at row resolution), so no point in us doing it too.
|
||||
@@ -392,7 +393,7 @@ process_data_context_main (j_decompress_ptr cinfo,
|
||||
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
if (! main->buffer_full) {
|
||||
if (! (*cinfo->codec->decompress_data) (cinfo,
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo,
|
||||
main->xbuffer[main->whichptr]))
|
||||
return; /* suspension forced, can do nothing more */
|
||||
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||
@@ -419,7 +420,7 @@ process_data_context_main (j_decompress_ptr cinfo,
|
||||
case CTX_PREPARE_FOR_IMCU:
|
||||
/* Prepare to process first M-1 row groups of this iMCU row */
|
||||
main->rowgroup_ctr = 0;
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1);
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
|
||||
/* Check for bottom of image: if so, tweak pointers to "duplicate"
|
||||
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
|
||||
*/
|
||||
@@ -442,8 +443,8 @@ process_data_context_main (j_decompress_ptr cinfo,
|
||||
main->buffer_full = FALSE;
|
||||
/* Still need to process last row group of this iMCU row, */
|
||||
/* which is saved at index M+1 of the other xbuffer */
|
||||
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1);
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2);
|
||||
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
|
||||
main->context_state = CTX_POSTPONED_ROW;
|
||||
}
|
||||
}
|
||||
@@ -494,21 +495,21 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
* ngroups is the number of row groups we need.
|
||||
*/
|
||||
if (cinfo->upsample->need_context_rows) {
|
||||
if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */
|
||||
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
|
||||
ngroups = cinfo->min_codec_data_unit + 2;
|
||||
ngroups = cinfo->min_DCT_scaled_size + 2;
|
||||
} else {
|
||||
ngroups = cinfo->min_codec_data_unit;
|
||||
ngroups = cinfo->min_DCT_scaled_size;
|
||||
}
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit; /* height of a row group of component */
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
compptr->width_in_data_units * compptr->codec_data_unit,
|
||||
compptr->width_in_blocks * compptr->DCT_scaled_size,
|
||||
(JDIMENSION) (rgroup * ngroups));
|
||||
}
|
||||
}
|
||||
|
||||
21
jdmarker.c
21
jdmarker.c
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains routines to decode JPEG datastream markers.
|
||||
@@ -236,8 +237,8 @@ get_soi (j_decompress_ptr cinfo)
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith,
|
||||
int data_unit)
|
||||
get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_lossless,
|
||||
boolean is_arith)
|
||||
/* Process a SOFn marker */
|
||||
{
|
||||
INT32 length;
|
||||
@@ -245,8 +246,8 @@ get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith,
|
||||
jpeg_component_info * compptr;
|
||||
INPUT_VARS(cinfo);
|
||||
|
||||
cinfo->data_unit = data_unit;
|
||||
cinfo->process = process;
|
||||
cinfo->progressive_mode = is_prog;
|
||||
cinfo->master->lossless = is_lossless;
|
||||
cinfo->arith_code = is_arith;
|
||||
|
||||
INPUT_2BYTES(cinfo, length, return FALSE);
|
||||
@@ -980,32 +981,32 @@ read_markers (j_decompress_ptr cinfo)
|
||||
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE))
|
||||
if (! get_sof(cinfo, FALSE, FALSE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE))
|
||||
if (! get_sof(cinfo, TRUE, FALSE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1))
|
||||
if (! get_sof(cinfo, FALSE, TRUE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE))
|
||||
if (! get_sof(cinfo, FALSE, FALSE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE))
|
||||
if (! get_sof(cinfo, TRUE, FALSE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1))
|
||||
if (! get_sof(cinfo, FALSE, TRUE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
|
||||
179
jdmaster.c
179
jdmaster.c
@@ -2,9 +2,10 @@
|
||||
* jdmaster.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains master control logic for the JPEG decompressor.
|
||||
@@ -16,25 +17,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_decomp_master pub; /* public fields */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
|
||||
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
|
||||
|
||||
/* Saved references to initialized quantizer modules,
|
||||
* in case we need to switch modes.
|
||||
*/
|
||||
struct jpeg_color_quantizer * quantizer_1pass;
|
||||
struct jpeg_color_quantizer * quantizer_2pass;
|
||||
} my_decomp_master;
|
||||
|
||||
typedef my_decomp_master * my_master_ptr;
|
||||
#include "jdmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -62,11 +45,10 @@ use_merged_upsample (j_decompress_ptr cinfo)
|
||||
cinfo->comp_info[1].v_samp_factor != 1 ||
|
||||
cinfo->comp_info[2].v_samp_factor != 1)
|
||||
return FALSE;
|
||||
/* furthermore, it doesn't work if each component has been
|
||||
processed differently */
|
||||
if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit ||
|
||||
cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit ||
|
||||
cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit)
|
||||
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
|
||||
if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
|
||||
return FALSE;
|
||||
/* ??? also need to test for upsample-time rescaling, when & if supported */
|
||||
return TRUE; /* by golly, it'll work... */
|
||||
@@ -87,11 +69,89 @@ GLOBAL(void)
|
||||
jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
|
||||
/* Do computations that are needed before master selection phase */
|
||||
{
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
#endif
|
||||
|
||||
/* Prevent application from calling me at wrong times */
|
||||
if (cinfo->global_state != DSTATE_READY)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
(*cinfo->codec->calc_output_dimensions) (cinfo);
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
|
||||
if (! cinfo->master->lossless) {
|
||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
|
||||
/* Provide 1/8 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 8L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 8L);
|
||||
cinfo->min_DCT_scaled_size = 1;
|
||||
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
|
||||
/* Provide 1/4 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 4L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 4L);
|
||||
cinfo->min_DCT_scaled_size = 2;
|
||||
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
|
||||
/* Provide 1/2 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 2L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 2L);
|
||||
cinfo->min_DCT_scaled_size = 4;
|
||||
} else {
|
||||
/* Provide 1/1 scaling */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||
}
|
||||
/* In selecting the actual DCT scaling for each component, we try to
|
||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||
* Note this code assumes that the supported DCT scalings are powers of 2.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
int ssize = cinfo->min_DCT_scaled_size;
|
||||
while (ssize < DCTSIZE &&
|
||||
(compptr->h_samp_factor * ssize * 2 <=
|
||||
cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
|
||||
(compptr->v_samp_factor * ssize * 2 <=
|
||||
cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
|
||||
ssize = ssize * 2;
|
||||
}
|
||||
compptr->DCT_scaled_size = ssize;
|
||||
}
|
||||
|
||||
/* Recompute downsampled dimensions of components;
|
||||
* application needs to know these if using raw downsampled data.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Size in samples, after IDCT scaling */
|
||||
compptr->downsampled_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width *
|
||||
(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
compptr->downsampled_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height *
|
||||
(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
|
||||
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||
}
|
||||
} else
|
||||
#endif /* !IDCT_SCALING_SUPPORTED */
|
||||
{
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Report number of components in selected colorspace. */
|
||||
/* Probably this should be in the color conversion module... */
|
||||
@@ -213,9 +273,21 @@ LOCAL(void)
|
||||
master_selection (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
boolean use_c_buffer;
|
||||
long samplesperrow;
|
||||
JDIMENSION jd_samplesperrow;
|
||||
|
||||
/* Disable IDCT scaling and raw (downsampled) data output in lossless mode.
|
||||
* IDCT scaling is not useful in lossless mode, and it must be disabled in
|
||||
* order to properly calculate the output dimensions. Raw data output isn't
|
||||
* particularly useful without subsampling and has not been tested in
|
||||
* lossless mode.
|
||||
*/
|
||||
if (cinfo->master->lossless) {
|
||||
cinfo->raw_data_out = FALSE;
|
||||
cinfo->scale_num = cinfo->scale_denom = 1;
|
||||
}
|
||||
|
||||
/* Initialize dimensions and other stuff */
|
||||
jpeg_calc_output_dimensions(cinfo);
|
||||
prepare_range_limit_table(cinfo);
|
||||
@@ -294,7 +366,49 @@ master_selection (j_decompress_ptr cinfo)
|
||||
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
}
|
||||
|
||||
/* Initialize principal buffer controllers. */
|
||||
if (cinfo->master->lossless) {
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
/* Prediction, sample undifferencing, point transform, and sample size
|
||||
* scaling
|
||||
*/
|
||||
jinit_lossless_decompressor(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
jinit_lhuff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Initialize principal buffer controllers. */
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans ||
|
||||
cinfo->buffered_image;
|
||||
jinit_d_diff_controller(cinfo, use_c_buffer);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
/* Inverse DCT */
|
||||
jinit_inverse_dct(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Initialize principal buffer controllers. */
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans ||
|
||||
cinfo->buffered_image;
|
||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||
}
|
||||
|
||||
if (! cinfo->raw_data_out)
|
||||
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
|
||||
@@ -313,7 +427,7 @@ master_selection (j_decompress_ptr cinfo)
|
||||
cinfo->inputctl->has_multiple_scans) {
|
||||
int nscans;
|
||||
/* Estimate number of scans to set pass_limit. */
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
|
||||
nscans = 2 + 3 * cinfo->num_components;
|
||||
} else {
|
||||
@@ -367,7 +481,8 @@ prepare_for_output_pass (j_decompress_ptr cinfo)
|
||||
ERREXIT(cinfo, JERR_MODE_CHANGE);
|
||||
}
|
||||
}
|
||||
(*cinfo->codec->start_output_pass) (cinfo);
|
||||
(*cinfo->idct->start_pass) (cinfo);
|
||||
(*cinfo->coef->start_output_pass) (cinfo);
|
||||
if (! cinfo->raw_data_out) {
|
||||
if (! master->using_merged_upsample)
|
||||
(*cinfo->cconvert->start_pass) (cinfo);
|
||||
@@ -447,12 +562,8 @@ jpeg_new_colormap (j_decompress_ptr cinfo)
|
||||
GLOBAL(void)
|
||||
jinit_master_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master;
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
master = (my_master_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_decomp_master));
|
||||
cinfo->master = (struct jpeg_decomp_master *) master;
|
||||
master->pub.prepare_for_output_pass = prepare_for_output_pass;
|
||||
master->pub.finish_output_pass = finish_output_pass;
|
||||
|
||||
|
||||
27
jdmaster.h
Normal file
27
jdmaster.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* jdmaster.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the master control structure for the JPEG decompressor.
|
||||
*/
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_decomp_master pub; /* public fields */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
|
||||
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
|
||||
|
||||
/* Saved references to initialized quantizer modules,
|
||||
* in case we need to switch modes.
|
||||
*/
|
||||
struct jpeg_color_quantizer * quantizer_1pass;
|
||||
struct jpeg_color_quantizer * quantizer_2pass;
|
||||
} my_decomp_master;
|
||||
|
||||
typedef my_decomp_master * my_master_ptr;
|
||||
53
jdphuff.c
53
jdphuff.c
@@ -2,7 +2,7 @@
|
||||
* jdphuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
@@ -19,14 +19,13 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy subsystem */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
|
||||
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
|
||||
/*
|
||||
* Private entropy decoder object for progressive Huffman decoding.
|
||||
* Expanded entropy decoder object for progressive Huffman decoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
@@ -57,11 +56,12 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct {
|
||||
huffd_common_fields; /* Fields shared with other entropy decoders */
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
/* These fields are loaded into local variables at start of each MCU.
|
||||
* In case of suspension, we exit WITHOUT updating them.
|
||||
*/
|
||||
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||
savable_state saved; /* Other state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
@@ -93,8 +93,7 @@ METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
|
||||
METHODDEF(void)
|
||||
start_pass_phuff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
boolean is_DC_band, bad;
|
||||
int ci, coefi, tbl;
|
||||
int *coef_bit_ptr;
|
||||
@@ -151,14 +150,14 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
|
||||
/* Select MCU decoding routine */
|
||||
if (cinfo->Ah == 0) {
|
||||
if (is_DC_band)
|
||||
lossyd->entropy_decode_mcu = decode_mcu_DC_first;
|
||||
entropy->pub.decode_mcu = decode_mcu_DC_first;
|
||||
else
|
||||
lossyd->entropy_decode_mcu = decode_mcu_AC_first;
|
||||
entropy->pub.decode_mcu = decode_mcu_AC_first;
|
||||
} else {
|
||||
if (is_DC_band)
|
||||
lossyd->entropy_decode_mcu = decode_mcu_DC_refine;
|
||||
entropy->pub.decode_mcu = decode_mcu_DC_refine;
|
||||
else
|
||||
lossyd->entropy_decode_mcu = decode_mcu_AC_refine;
|
||||
entropy->pub.decode_mcu = decode_mcu_AC_refine;
|
||||
}
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
@@ -186,7 +185,7 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->insufficient_data = FALSE;
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
/* Initialize private state variables */
|
||||
entropy->saved.EOBRUN = 0;
|
||||
@@ -230,8 +229,7 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||
LOCAL(boolean)
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
int ci;
|
||||
|
||||
/* Throw away any unused bits remaining in bit buffer; */
|
||||
@@ -258,7 +256,7 @@ process_restart (j_decompress_ptr cinfo)
|
||||
* leaving the flag set.
|
||||
*/
|
||||
if (cinfo->unread_marker == 0)
|
||||
entropy->insufficient_data = FALSE;
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -289,8 +287,7 @@ process_restart (j_decompress_ptr cinfo)
|
||||
METHODDEF(boolean)
|
||||
decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
int Al = cinfo->Al;
|
||||
register int s, r;
|
||||
int blkn, ci;
|
||||
@@ -310,7 +307,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||
* This way, we return uniform gray for the remainder of the segment.
|
||||
*/
|
||||
if (! entropy->insufficient_data) {
|
||||
if (! entropy->pub.insufficient_data) {
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
@@ -318,7 +315,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
block = MCU_data[blkn];
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
@@ -361,8 +358,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
int Se = cinfo->Se;
|
||||
int Al = cinfo->Al;
|
||||
register int s, k, r;
|
||||
@@ -381,7 +377,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||
* This way, we return uniform gray for the remainder of the segment.
|
||||
*/
|
||||
if (! entropy->insufficient_data) {
|
||||
if (! entropy->pub.insufficient_data) {
|
||||
|
||||
/* Load up working state.
|
||||
* We can avoid loading/saving bitread state if in an EOB run.
|
||||
@@ -447,8 +443,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
|
||||
int blkn;
|
||||
JBLOCKROW block;
|
||||
@@ -470,7 +465,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
block = MCU_data[blkn];
|
||||
|
||||
/* Encoded data is simply the next bit of the two's-complement DC value */
|
||||
@@ -497,8 +492,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
METHODDEF(boolean)
|
||||
decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
|
||||
int Se = cinfo->Se;
|
||||
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
|
||||
int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
|
||||
@@ -520,7 +514,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* If we've run out of data, don't modify the MCU.
|
||||
*/
|
||||
if (! entropy->insufficient_data) {
|
||||
if (! entropy->pub.insufficient_data) {
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
@@ -648,7 +642,6 @@ undoit:
|
||||
GLOBAL(void)
|
||||
jinit_phuff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
phuff_entropy_ptr entropy;
|
||||
int *coef_bit_ptr;
|
||||
int ci, i;
|
||||
@@ -656,8 +649,8 @@ jinit_phuff_decoder (j_decompress_ptr cinfo)
|
||||
entropy = (phuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(phuff_entropy_decoder));
|
||||
lossyd->entropy_private = (void *) entropy;
|
||||
lossyd->entropy_start_pass = start_pass_phuff_decoder;
|
||||
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_phuff_decoder;
|
||||
|
||||
/* Mark derived tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
|
||||
249
jdpred.c
249
jdpred.c
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* jdpred.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains sample undifferencing (reconstruction) for lossless JPEG.
|
||||
*
|
||||
* In order to avoid paying the performance penalty of having to check the
|
||||
* predictor being used and the row being processed for each call of the
|
||||
* undifferencer, and to promote optimization, we have separate undifferencing
|
||||
* functions for each case.
|
||||
*
|
||||
* We are able to avoid duplicating source code by implementing the predictors
|
||||
* and undifferencers as macros. Each of the undifferencing functions are
|
||||
* simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR
|
||||
* macro passed as an argument.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
/* Predictor for the first column of the first row: 2^(P-Pt-1) */
|
||||
#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
|
||||
|
||||
/* Predictor for the first column of the remaining rows: Rb */
|
||||
#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
|
||||
|
||||
|
||||
/*
|
||||
* 1-Dimensional undifferencer routine.
|
||||
*
|
||||
* This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
|
||||
* is used as the special case predictor for the first column, which must be
|
||||
* either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
|
||||
* use PREDICTOR1.
|
||||
*
|
||||
* The reconstructed sample is supposed to be calculated modulo 2^16, so we
|
||||
* logically AND the result with 0xFFFF.
|
||||
*/
|
||||
|
||||
#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \
|
||||
int xindex; \
|
||||
int Ra; \
|
||||
\
|
||||
Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \
|
||||
undiff_buf[0] = Ra; \
|
||||
\
|
||||
for (xindex = 1; xindex < width; xindex++) { \
|
||||
Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \
|
||||
undiff_buf[xindex] = Ra; \
|
||||
}
|
||||
|
||||
/*
|
||||
* 2-Dimensional undifferencer routine.
|
||||
*
|
||||
* This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
|
||||
* used as the special case predictor for the first column. The remaining
|
||||
* samples use PREDICTOR, which is a function of Ra, Rb, Rc.
|
||||
*
|
||||
* Because prev_row and output_buf may point to the same storage area (in an
|
||||
* interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
|
||||
* before writing the current reconstructed sample value into output_buf.
|
||||
*
|
||||
* The reconstructed sample is supposed to be calculated modulo 2^16, so we
|
||||
* logically AND the result with 0xFFFF.
|
||||
*/
|
||||
|
||||
#define UNDIFFERENCE_2D(PREDICTOR) \
|
||||
int xindex; \
|
||||
int Ra, Rb, Rc; \
|
||||
\
|
||||
Rb = GETJSAMPLE(prev_row[0]); \
|
||||
Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \
|
||||
undiff_buf[0] = Ra; \
|
||||
\
|
||||
for (xindex = 1; xindex < width; xindex++) { \
|
||||
Rc = Rb; \
|
||||
Rb = GETJSAMPLE(prev_row[xindex]); \
|
||||
Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \
|
||||
undiff_buf[xindex] = Ra; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Undifferencers for the all rows but the first in a scan or restart interval.
|
||||
* The first sample in the row is undifferenced using the vertical
|
||||
* predictor (2). The rest of the samples are undifferenced using the
|
||||
* predictor specified in the scan header.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference1(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_1D(INITIAL_PREDICTOR2);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference2(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR2);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference3(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR3);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference4(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR4);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference5(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR5);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference6(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR6);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference7(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
UNDIFFERENCE_2D(PREDICTOR7);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Undifferencer for the first row in a scan or restart interval. The first
|
||||
* sample in the row is undifferenced using the special predictor constant
|
||||
* x=2^(P-Pt-1). The rest of the samples are undifferenced using the
|
||||
* 1-D horizontal predictor (1).
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
|
||||
UNDIFFERENCE_1D(INITIAL_PREDICTORx);
|
||||
|
||||
/*
|
||||
* Now that we have undifferenced the first row, we want to use the
|
||||
* undifferencer which corresponds to the predictor specified in the
|
||||
* scan header.
|
||||
*/
|
||||
switch (cinfo->Ss) {
|
||||
case 1:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference1;
|
||||
break;
|
||||
case 2:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference2;
|
||||
break;
|
||||
case 3:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference3;
|
||||
break;
|
||||
case 4:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference4;
|
||||
break;
|
||||
case 5:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference5;
|
||||
break;
|
||||
case 6:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference6;
|
||||
break;
|
||||
case 7:
|
||||
losslsd->predict_undifference[comp_index] = jpeg_undifference7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
predict_start_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
int ci;
|
||||
|
||||
/* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG.
|
||||
*
|
||||
* Ss is the predictor selection value (psv). Legal values for sequential
|
||||
* lossless JPEG are: 1 <= psv <= 7.
|
||||
*
|
||||
* Se and Ah are not used and should be zero.
|
||||
*
|
||||
* Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15.
|
||||
*/
|
||||
if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
|
||||
cinfo->Se != 0 || cinfo->Ah != 0 ||
|
||||
cinfo->Al > 15) /* need not check for < 0 */
|
||||
ERREXIT4(cinfo, JERR_BAD_LOSSLESS,
|
||||
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
|
||||
|
||||
/* Set undifference functions to first row function */
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
losslsd->predict_undifference[ci] = jpeg_undifference_first_row;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for the undifferencer.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_undifferencer (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
|
||||
losslsd->predict_start_pass = predict_start_pass;
|
||||
losslsd->predict_process_restart = predict_start_pass;
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
|
||||
20
jdsample.c
20
jdsample.c
@@ -1,16 +1,14 @@
|
||||
/*
|
||||
* jdsample.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains upsampling routines.
|
||||
*
|
||||
* Upsampling input data is counted in "row groups". A row group
|
||||
* is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
|
||||
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||
* sample rows of each component. Upsampling will normally produce
|
||||
* max_v_samp_factor pixel rows from each row group (but this could vary
|
||||
* if the upsampler is applying a scale factor of its own).
|
||||
@@ -417,10 +415,10 @@ jinit_upsampler (j_decompress_ptr cinfo)
|
||||
if (cinfo->CCIR601_sampling) /* this isn't supported */
|
||||
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
|
||||
|
||||
/* jdmainct.c doesn't support context rows when min_codec_data_unit = 1,
|
||||
/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
|
||||
* so don't ask for it.
|
||||
*/
|
||||
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1;
|
||||
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
|
||||
|
||||
/* Verify we can handle the sampling factors, select per-component methods,
|
||||
* and create storage as needed.
|
||||
@@ -430,10 +428,10 @@ jinit_upsampler (j_decompress_ptr cinfo)
|
||||
/* Compute size of an "input group" after IDCT scaling. This many samples
|
||||
* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
|
||||
*/
|
||||
h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit;
|
||||
v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) /
|
||||
cinfo->min_codec_data_unit;
|
||||
h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size;
|
||||
v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size;
|
||||
h_out_group = cinfo->max_h_samp_factor;
|
||||
v_out_group = cinfo->max_v_samp_factor;
|
||||
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
|
||||
|
||||
120
jdscale.c
120
jdscale.c
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* jdscale.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains sample scaling for lossless JPEG. This is a
|
||||
* combination of upscaling the undifferenced sample by 2^Pt and downscaling
|
||||
* the sample to fit into JSAMPLE.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Private scaler object for lossless decoding.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int scale_factor;
|
||||
} scaler;
|
||||
|
||||
typedef scaler * scaler_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Scalers for packing sample differences into JSAMPLEs.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
simple_upscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
|
||||
int scale_factor = scaler->scale_factor;
|
||||
int xindex;
|
||||
|
||||
for (xindex = 0; xindex < width; xindex++)
|
||||
output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
simple_downscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
|
||||
int scale_factor = scaler->scale_factor;
|
||||
int xindex;
|
||||
|
||||
for (xindex = 0; xindex < width; xindex++)
|
||||
output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width)
|
||||
{
|
||||
int xindex;
|
||||
|
||||
for (xindex = 0; xindex < width; xindex++)
|
||||
output_buf[xindex] = (JSAMPLE) diff_buf[xindex];
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
scaler_start_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
|
||||
int downscale;
|
||||
|
||||
/*
|
||||
* Downscale by the difference in the input vs. output precision. If the
|
||||
* output precision >= input precision, then do not downscale.
|
||||
*/
|
||||
downscale = BITS_IN_JSAMPLE < cinfo->data_precision ?
|
||||
cinfo->data_precision - BITS_IN_JSAMPLE : 0;
|
||||
|
||||
scaler->scale_factor = cinfo->Al - downscale;
|
||||
|
||||
/* Set scaler functions based on scale_factor (positive = left shift) */
|
||||
if (scaler->scale_factor > 0)
|
||||
losslsd->scaler_scale = simple_upscale;
|
||||
else if (scaler->scale_factor < 0) {
|
||||
scaler->scale_factor = -scaler->scale_factor;
|
||||
losslsd->scaler_scale = simple_downscale;
|
||||
}
|
||||
else
|
||||
losslsd->scaler_scale = noscale;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_d_scaler (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
|
||||
scaler_ptr scaler;
|
||||
|
||||
scaler = (scaler_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(scaler));
|
||||
losslsd->scaler_private = (void *) scaler;
|
||||
losslsd->scaler_start_pass = scaler_start_pass;
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
|
||||
362
jdshuff.c
362
jdshuff.c
@@ -1,362 +0,0 @@
|
||||
/*
|
||||
* jdshuff.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines for sequential JPEG.
|
||||
*
|
||||
* Much of the complexity here has to do with supporting input suspension.
|
||||
* If the data source module demands suspension, we want to be able to back
|
||||
* up to the start of the current MCU. To do this, we copy state variables
|
||||
* into local working storage, and update them back to the permanent
|
||||
* storage only upon successful completion of an MCU.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h" /* Private declarations for lossy codec */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
|
||||
|
||||
/*
|
||||
* Private entropy decoder object for Huffman decoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest,src) \
|
||||
((dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
huffd_common_fields; /* Fields shared with other entropy decoders */
|
||||
|
||||
/* These fields are loaded into local variables at start of each MCU.
|
||||
* In case of suspension, we exit WITHOUT updating them.
|
||||
*/
|
||||
savable_state saved; /* Other state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||
d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
/* Precalculated info set up by start_pass for use in decode_mcu: */
|
||||
|
||||
/* Pointers to derived tables to be used for each block within an MCU */
|
||||
d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
|
||||
d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
|
||||
/* Whether we care about the DC and AC coefficient values for each block */
|
||||
boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU];
|
||||
boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU];
|
||||
} shuff_entropy_decoder;
|
||||
|
||||
typedef shuff_entropy_decoder * shuff_entropy_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_huff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
|
||||
int ci, blkn, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
|
||||
* This ought to be an error condition, but we make it a warning because
|
||||
* there are some baseline files out there with all zeroes in these bytes.
|
||||
*/
|
||||
if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
|
||||
cinfo->Ah != 0 || cinfo->Al != 0)
|
||||
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for a table, but it's not expensive */
|
||||
jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
|
||||
& entropy->dc_derived_tbls[dctbl]);
|
||||
jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
|
||||
& entropy->ac_derived_tbls[actbl]);
|
||||
/* Initialize DC predictions to 0 */
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Precalculate decoding info for each block in an MCU of this scan */
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Precalculate which table to use for each block */
|
||||
entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
|
||||
entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
|
||||
/* Decide whether we really care about the coefficient values */
|
||||
if (compptr->component_needed) {
|
||||
entropy->dc_needed[blkn] = TRUE;
|
||||
/* we don't need the ACs if producing a 1/8th-size image */
|
||||
entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1);
|
||||
} else {
|
||||
entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->insufficient_data = FALSE;
|
||||
|
||||
/* Initialize restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Figure F.12: extend sign bit.
|
||||
* On some machines, a shift and add will be faster than a table lookup.
|
||||
*/
|
||||
|
||||
#ifdef AVOID_TABLES
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||
|
||||
#else
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
|
||||
|
||||
static const int extend_test[16] = /* entry n is 2**(n-1) */
|
||||
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
||||
|
||||
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
|
||||
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
|
||||
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
|
||||
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
|
||||
|
||||
#endif /* AVOID_TABLES */
|
||||
|
||||
|
||||
/*
|
||||
* Check for a restart marker & resynchronize decoder.
|
||||
* Returns FALSE if must suspend.
|
||||
*/
|
||||
|
||||
LOCAL(boolean)
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
|
||||
int ci;
|
||||
|
||||
/* Throw away any unused bits remaining in bit buffer; */
|
||||
/* include any full bytes in next_marker's count of discarded bytes */
|
||||
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
|
||||
entropy->bitstate.bits_left = 0;
|
||||
|
||||
/* Advance past the RSTn marker */
|
||||
if (! (*cinfo->marker->read_restart_marker) (cinfo))
|
||||
return FALSE;
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
|
||||
/* Reset restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
|
||||
/* Reset out-of-data flag, unless read_restart_marker left us smack up
|
||||
* against a marker. In that case we will end up treating the next data
|
||||
* segment as empty, and we can avoid producing bogus output pixels by
|
||||
* leaving the flag set.
|
||||
*/
|
||||
if (cinfo->unread_marker == 0)
|
||||
entropy->insufficient_data = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode and return one MCU's worth of Huffman-compressed coefficients.
|
||||
* The coefficients are reordered from zigzag order into natural array order,
|
||||
* but are not dequantized.
|
||||
*
|
||||
* The i'th block of the MCU is stored into the block pointed to by
|
||||
* MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
|
||||
* (Wholesale zeroing is usually a little faster than retail...)
|
||||
*
|
||||
* Returns FALSE if data source requested suspension. In that case no
|
||||
* changes have been made to permanent state. (Exception: some output
|
||||
* coefficients may already have been assigned. This is harmless for
|
||||
* this module, since we'll just re-assign them on the next call.)
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
|
||||
int blkn;
|
||||
BITREAD_STATE_VARS;
|
||||
savable_state state;
|
||||
|
||||
/* Process restart marker if needed; may have to suspend */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0)
|
||||
if (! process_restart(cinfo))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we've run out of data, just leave the MCU set to zeroes.
|
||||
* This way, we return uniform gray for the remainder of the segment.
|
||||
*/
|
||||
if (! entropy->insufficient_data) {
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
|
||||
JBLOCKROW block = MCU_data[blkn];
|
||||
d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
|
||||
d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
|
||||
register int s, k, r;
|
||||
|
||||
/* Decode a single block's worth of coefficients */
|
||||
|
||||
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||
HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
|
||||
if (s) {
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
}
|
||||
|
||||
if (entropy->dc_needed[blkn]) {
|
||||
/* Convert DC difference to actual value, update last_dc_val */
|
||||
int ci = cinfo->MCU_membership[blkn];
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||
(*block)[0] = (JCOEF) s;
|
||||
}
|
||||
|
||||
if (entropy->ac_needed[blkn]) {
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* Since zeroes are skipped, output area must be cleared beforehand */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
/* Output coefficient in natural (dezigzagged) order.
|
||||
* Note: the extra entries in jpeg_natural_order[] will save us
|
||||
* if k >= DCTSIZE2, which could happen if the data is corrupted.
|
||||
*/
|
||||
(*block)[jpeg_natural_order[k]] = (JCOEF) s;
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* In this path we just discard the values */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
DROP_BITS(s);
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_shuff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
|
||||
shuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (shuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(shuff_entropy_decoder));
|
||||
lossyd->entropy_private = (void *) entropy;
|
||||
lossyd->entropy_start_pass = start_pass_huff_decoder;
|
||||
lossyd->entropy_decode_mcu = decode_mcu;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||
}
|
||||
}
|
||||
36
jdtrans.c
36
jdtrans.c
@@ -2,9 +2,9 @@
|
||||
* jdtrans.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains library routines for transcoding decompression,
|
||||
@@ -15,7 +15,6 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossy.h"
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
@@ -47,13 +46,8 @@ LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
|
||||
GLOBAL(jvirt_barray_ptr *)
|
||||
jpeg_read_coefficients (j_decompress_ptr cinfo)
|
||||
{
|
||||
j_lossy_d_ptr decomp;
|
||||
|
||||
/* Can't read coefficients from lossless streams */
|
||||
if (cinfo->process == JPROC_LOSSLESS) {
|
||||
ERREXIT(cinfo, JERR_CANT_TRANSCODE);
|
||||
return NULL;
|
||||
}
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if (cinfo->global_state == DSTATE_READY) {
|
||||
/* First call: initialize active modules */
|
||||
@@ -91,7 +85,7 @@ jpeg_read_coefficients (j_decompress_ptr cinfo)
|
||||
*/
|
||||
if ((cinfo->global_state == DSTATE_STOPPING ||
|
||||
cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
|
||||
return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays;
|
||||
return cinfo->coef->coef_arrays;
|
||||
}
|
||||
/* Oops, improper usage */
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
@@ -110,8 +104,22 @@ transdecode_master_selection (j_decompress_ptr cinfo)
|
||||
/* This is effectively a buffered-image operation. */
|
||||
cinfo->buffered_image = TRUE;
|
||||
|
||||
/* Initialize decompression codec */
|
||||
jinit_d_codec(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Always get a full-image coefficient buffer. */
|
||||
jinit_d_coef_controller(cinfo, TRUE);
|
||||
|
||||
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||
@@ -123,7 +131,7 @@ transdecode_master_selection (j_decompress_ptr cinfo)
|
||||
if (cinfo->progress != NULL) {
|
||||
int nscans;
|
||||
/* Estimate number of scans to set pass_limit. */
|
||||
if (cinfo->process == JPROC_PROGRESSIVE) {
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
|
||||
nscans = 2 + 3 * cinfo->num_components;
|
||||
} else if (cinfo->inputctl->has_multiple_scans) {
|
||||
|
||||
30
jerror.h
30
jerror.h
@@ -2,9 +2,10 @@
|
||||
* jerror.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file defines the error and message codes for the JPEG library.
|
||||
@@ -47,27 +48,22 @@ JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
|
||||
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
|
||||
JMESSAGE(JERR_BAD_DCT_COEF,
|
||||
"DCT coefficient (lossy) or spatial difference (lossless) out of range")
|
||||
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||
JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range")
|
||||
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
|
||||
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
|
||||
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
|
||||
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
|
||||
JMESSAGE(JERR_BAD_LIB_VERSION,
|
||||
"Wrong JPEG library version: library is %d, caller expects %d")
|
||||
JMESSAGE(JERR_BAD_LOSSLESS,
|
||||
"Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT,
|
||||
"Invalid lossless parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
|
||||
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
|
||||
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||
JMESSAGE(JERR_BAD_PROGRESSION,
|
||||
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
"Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
JMESSAGE(JERR_BAD_PROG_SCRIPT,
|
||||
"Invalid progressive parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)")
|
||||
"Invalid progressive/lossless parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
|
||||
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||
@@ -76,8 +72,6 @@ JMESSAGE(JERR_BAD_STRUCT_SIZE,
|
||||
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
|
||||
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
|
||||
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
|
||||
JMESSAGE(JERR_CANT_TRANSCODE,
|
||||
"Cannot transcode to/from lossless JPEG datastreams")
|
||||
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
|
||||
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
|
||||
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
|
||||
@@ -106,7 +100,6 @@ JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
|
||||
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
|
||||
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
|
||||
JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied")
|
||||
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
|
||||
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
|
||||
@@ -176,10 +169,8 @@ JMESSAGE(JTRC_THUMB_PALETTE,
|
||||
"JFIF extension marker: palette thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_THUMB_RGB,
|
||||
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming RGB")
|
||||
JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr")
|
||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)")
|
||||
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
|
||||
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
||||
@@ -191,12 +182,13 @@ JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
|
||||
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
|
||||
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
|
||||
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
|
||||
JMESSAGE(JWRN_MUST_DOWNSCALE,
|
||||
"Must downscale data from %d bits to %d")
|
||||
JMESSAGE(JWRN_MUST_RESYNC,
|
||||
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
|
||||
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
|
||||
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
|
||||
JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)")
|
||||
JMESSAGE(JWRN_MUST_DOWNSCALE,
|
||||
"Must downscale data from %d bits to %d")
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
|
||||
111
jlossls.h
111
jlossls.h
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This include file contains common declarations for the lossless JPEG
|
||||
@@ -14,6 +15,17 @@
|
||||
#ifndef JLOSSLS_H
|
||||
#define JLOSSLS_H
|
||||
|
||||
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
#define ALLOC_DARRAY(pool_id, diffsperrow, numrows) \
|
||||
(JDIFFARRAY)(*cinfo->mem->alloc_sarray) \
|
||||
((j_common_ptr) cinfo, pool_id, \
|
||||
(diffsperrow) * sizeof(JDIFF) / sizeof(JSAMPLE), numrows)
|
||||
|
||||
|
||||
/*
|
||||
* Table H.1: Predictors for lossless coding.
|
||||
@@ -27,125 +39,62 @@
|
||||
#define PREDICTOR6 (int) ((INT32) Rb + RIGHT_SHIFT((INT32) Ra - (INT32) Rc, 1))
|
||||
#define PREDICTOR7 (int) RIGHT_SHIFT((INT32) Ra + (INT32) Rb, 1)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
typedef JMETHOD(void, predict_difference_method_ptr,
|
||||
(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf, JDIMENSION width));
|
||||
|
||||
typedef JMETHOD(void, scaler_method_ptr,
|
||||
(j_compress_ptr cinfo, int ci,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width));
|
||||
|
||||
/* Lossless-specific compression codec (compressor proper) */
|
||||
/* Lossless compressor */
|
||||
typedef struct {
|
||||
struct jpeg_c_codec pub; /* public fields */
|
||||
|
||||
|
||||
/* Difference buffer control */
|
||||
JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo,
|
||||
J_BUF_MODE pass_mode));
|
||||
|
||||
/* Pointer to data which is private to diff controller */
|
||||
void *diff_private;
|
||||
|
||||
|
||||
/* Entropy encoding */
|
||||
JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU));
|
||||
|
||||
/* Pointer to data which is private to entropy module */
|
||||
void *entropy_private;
|
||||
|
||||
|
||||
/* Prediction, differencing */
|
||||
JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo));
|
||||
struct jpeg_forward_dct pub; /* public fields */
|
||||
|
||||
/* It is useful to allow each component to have a separate diff method. */
|
||||
predict_difference_method_ptr predict_difference[MAX_COMPONENTS];
|
||||
|
||||
/* Pointer to data which is private to predictor module */
|
||||
void *pred_private;
|
||||
/* MCU rows left in the restart interval for each component */
|
||||
unsigned int restart_rows_to_go[MAX_COMPONENTS];
|
||||
|
||||
/* Sample scaling */
|
||||
JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, scaler_scale, (j_compress_ptr cinfo,
|
||||
JSAMPROW input_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width));
|
||||
} jpeg_lossless_compressor;
|
||||
|
||||
/* Pointer to data which is private to scaler module */
|
||||
void *scaler_private;
|
||||
typedef jpeg_lossless_compressor * lossless_comp_ptr;
|
||||
|
||||
} jpeg_lossless_c_codec;
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
typedef jpeg_lossless_c_codec * j_lossless_c_ptr;
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
typedef JMETHOD(void, predict_undifference_method_ptr,
|
||||
(j_decompress_ptr cinfo, int comp_index,
|
||||
JDIFFROW diff_buf, JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf, JDIMENSION width));
|
||||
|
||||
/* Lossless-specific decompression codec (decompressor proper) */
|
||||
/* Lossless decompressor */
|
||||
typedef struct {
|
||||
struct jpeg_d_codec pub; /* public fields */
|
||||
|
||||
|
||||
/* Difference buffer control */
|
||||
JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* Pointer to data which is private to diff controller */
|
||||
void *diff_private;
|
||||
|
||||
|
||||
/* Entropy decoding */
|
||||
JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo));
|
||||
JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU));
|
||||
|
||||
/* Pointer to data which is private to entropy module */
|
||||
void *entropy_private;
|
||||
|
||||
|
||||
/* Prediction, undifferencing */
|
||||
JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo));
|
||||
struct jpeg_inverse_dct pub; /* public fields */
|
||||
|
||||
/* It is useful to allow each component to have a separate undiff method. */
|
||||
predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS];
|
||||
|
||||
/* Pointer to data which is private to predictor module */
|
||||
void *pred_private;
|
||||
|
||||
/* Sample scaling */
|
||||
JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, JSAMPROW output_buf,
|
||||
JDIMENSION width));
|
||||
|
||||
/* Pointer to data which is private to scaler module */
|
||||
void *scaler_private;
|
||||
int scale_factor;
|
||||
|
||||
} jpeg_lossless_d_codec;
|
||||
} jpeg_lossless_decompressor;
|
||||
|
||||
typedef jpeg_lossless_d_codec * j_lossless_d_ptr;
|
||||
typedef jpeg_lossless_decompressor * lossless_decomp_ptr;
|
||||
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo));
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo));
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
|
||||
#endif /* JLOSSLS_H */
|
||||
|
||||
122
jlossy.h
122
jlossy.h
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* jlossy.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This include file contains common declarations for the lossy (DCT-based)
|
||||
* JPEG codec modules.
|
||||
*/
|
||||
|
||||
#ifndef JLOSSY_H
|
||||
#define JLOSSY_H
|
||||
|
||||
|
||||
/* Lossy-specific compression codec (compressor proper) */
|
||||
typedef struct {
|
||||
struct jpeg_c_codec pub; /* public fields */
|
||||
|
||||
|
||||
/* Coefficient buffer control */
|
||||
JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
/* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));*/
|
||||
|
||||
/* Pointer to data which is private to coef module */
|
||||
void *coef_private;
|
||||
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo));
|
||||
/* perhaps this should be an array??? */
|
||||
JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo,
|
||||
jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
|
||||
/* Pointer to data which is private to fdct module */
|
||||
void *fdct_private;
|
||||
|
||||
|
||||
/* Entropy encoding */
|
||||
JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
|
||||
/* Pointer to data which is private to entropy module */
|
||||
void *entropy_private;
|
||||
|
||||
} jpeg_lossy_c_codec;
|
||||
|
||||
typedef jpeg_lossy_c_codec * j_lossy_c_ptr;
|
||||
|
||||
|
||||
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
/* Lossy-specific decompression codec (decompressor proper) */
|
||||
typedef struct {
|
||||
struct jpeg_d_codec pub; /* public fields */
|
||||
|
||||
|
||||
/* Coefficient buffer control */
|
||||
JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
|
||||
/* Pointer to data which is private to coef module */
|
||||
void *coef_private;
|
||||
|
||||
|
||||
/* Entropy decoding */
|
||||
JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
|
||||
/* This is here to share code between baseline and progressive decoders; */
|
||||
/* other modules probably should not use it */
|
||||
boolean entropy_insufficient_data; /* set TRUE after emitting warning */
|
||||
|
||||
/* Pointer to data which is private to entropy module */
|
||||
void *entropy_private;
|
||||
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
|
||||
/* Pointer to data which is private to idct module */
|
||||
void *idct_private;
|
||||
|
||||
} jpeg_lossy_d_codec;
|
||||
|
||||
typedef jpeg_lossy_d_codec * j_lossy_d_ptr;
|
||||
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
|
||||
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
|
||||
#endif /* JLOSSY_H */
|
||||
72
jmemmgr.c
72
jmemmgr.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* jmemmgr.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the JPEG system-independent memory management
|
||||
@@ -44,12 +42,11 @@ extern char * getenv JPP((const char * name));
|
||||
* The allocation routines provided here must never return NULL.
|
||||
* They should exit to error_exit if unsuccessful.
|
||||
*
|
||||
* It's not a good idea to try to merge the sarray, barray and darray
|
||||
* routines, even though they are textually almost the same, because
|
||||
* samples are usually stored as bytes while coefficients and differenced
|
||||
* are shorts or ints. Thus, in machines where byte pointers have a
|
||||
* different representation from word pointers, the resulting machine
|
||||
* code could not be the same.
|
||||
* It's not a good idea to try to merge the sarray and barray routines,
|
||||
* even though they are textually almost the same, because samples are
|
||||
* usually stored as bytes while coefficients are shorts or ints. Thus,
|
||||
* in machines where byte pointers have a different representation from
|
||||
* word pointers, the resulting machine code could not be the same.
|
||||
*/
|
||||
|
||||
|
||||
@@ -485,58 +482,6 @@ alloc_barray (j_common_ptr cinfo, int pool_id,
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEED_DARRAY
|
||||
|
||||
/*
|
||||
* Creation of 2-D difference arrays.
|
||||
* This is essentially the same as the code for sample arrays, above.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIFFARRAY)
|
||||
alloc_darray (j_common_ptr cinfo, int pool_id,
|
||||
JDIMENSION diffsperrow, JDIMENSION numrows)
|
||||
/* Allocate a 2-D difference array */
|
||||
{
|
||||
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
|
||||
JDIFFARRAY result;
|
||||
JDIFFROW workspace;
|
||||
JDIMENSION rowsperchunk, currow, i;
|
||||
long ltemp;
|
||||
|
||||
/* Calculate max # of rows allowed in one allocation chunk */
|
||||
ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
|
||||
((long) diffsperrow * SIZEOF(JDIFF));
|
||||
if (ltemp <= 0)
|
||||
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
||||
if (ltemp < (long) numrows)
|
||||
rowsperchunk = (JDIMENSION) ltemp;
|
||||
else
|
||||
rowsperchunk = numrows;
|
||||
mem->last_rowsperchunk = rowsperchunk;
|
||||
|
||||
/* Get space for row pointers (small object) */
|
||||
result = (JDIFFARRAY) alloc_small(cinfo, pool_id,
|
||||
(size_t) (numrows * SIZEOF(JDIFFROW)));
|
||||
|
||||
/* Get the rows themselves (large objects) */
|
||||
currow = 0;
|
||||
while (currow < numrows) {
|
||||
rowsperchunk = MIN(rowsperchunk, numrows - currow);
|
||||
workspace = (JDIFFROW) alloc_large(cinfo, pool_id,
|
||||
(size_t) ((size_t) rowsperchunk * (size_t) diffsperrow
|
||||
* SIZEOF(JDIFF)));
|
||||
for (i = rowsperchunk; i > 0; i--) {
|
||||
result[currow++] = workspace;
|
||||
workspace += diffsperrow;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* About virtual array management:
|
||||
*
|
||||
@@ -1123,9 +1068,6 @@ jinit_memory_mgr (j_common_ptr cinfo)
|
||||
mem->pub.alloc_large = alloc_large;
|
||||
mem->pub.alloc_sarray = alloc_sarray;
|
||||
mem->pub.alloc_barray = alloc_barray;
|
||||
#ifdef NEED_DARRAY
|
||||
mem->pub.alloc_darray = alloc_darray;
|
||||
#endif
|
||||
mem->pub.request_virt_sarray = request_virt_sarray;
|
||||
mem->pub.request_virt_barray = request_virt_barray;
|
||||
mem->pub.realize_virt_arrays = realize_virt_arrays;
|
||||
|
||||
11
jmorecfg.h
11
jmorecfg.h
@@ -2,7 +2,7 @@
|
||||
* jmorecfg.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
@@ -128,13 +128,6 @@ typedef short JSAMPLE;
|
||||
typedef short JCOEF;
|
||||
|
||||
|
||||
/* Representation of a spatial difference value.
|
||||
* This should be a signed value of at least 16 bits; int is usually OK.
|
||||
*/
|
||||
|
||||
typedef int JDIFF;
|
||||
|
||||
|
||||
/* Compressed datastreams are represented as arrays of JOCTET.
|
||||
* These must be EXACTLY 8 bits wide, at least once they are written to
|
||||
* external storage. Note that when using the stdio data source/destination
|
||||
@@ -309,7 +302,7 @@ typedef int boolean;
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
* precision, so jcshuff.c normally uses entropy optimization to compute
|
||||
* precision, so jchuff.c normally uses entropy optimization to compute
|
||||
* usable tables for higher precision. If you don't want to do optimization,
|
||||
* you'll have to supply different default Huffman tables.
|
||||
* The exact same statements apply for progressive and lossless JPEG:
|
||||
|
||||
148
jpegint.h
148
jpegint.h
@@ -2,9 +2,10 @@
|
||||
* jpegint.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides common declarations for the various JPEG modules.
|
||||
@@ -13,6 +14,17 @@
|
||||
*/
|
||||
|
||||
|
||||
/* Representation of a spatial difference value.
|
||||
* This should be a signed value of at least 16 bits; int is usually OK.
|
||||
*/
|
||||
|
||||
typedef int JDIFF;
|
||||
|
||||
typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */
|
||||
typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */
|
||||
typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */
|
||||
|
||||
|
||||
/* Declarations for both compression & decompression */
|
||||
|
||||
typedef enum { /* Operating modes for buffer controllers */
|
||||
@@ -52,6 +64,7 @@ struct jpeg_comp_master {
|
||||
/* State variables made visible to other modules */
|
||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||
boolean is_last_pass; /* True during last pass */
|
||||
boolean lossless; /* True if lossless mode is enabled */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
@@ -74,12 +87,10 @@ struct jpeg_c_prep_controller {
|
||||
JDIMENSION out_row_groups_avail));
|
||||
};
|
||||
|
||||
/* Compression codec (compressor proper) */
|
||||
struct jpeg_c_codec {
|
||||
JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo,
|
||||
boolean gather_statistics));
|
||||
JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo));
|
||||
/* Lossy mode: Coefficient buffer control
|
||||
* Lossless mode: Difference buffer control
|
||||
*/
|
||||
struct jpeg_c_coef_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));
|
||||
@@ -104,6 +115,36 @@ struct jpeg_downsampler {
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Lossy mode: Forward DCT (also controls coefficient quantization)
|
||||
* Lossless mode: Prediction, sample differencing, and point transform
|
||||
*/
|
||||
struct jpeg_forward_dct {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
|
||||
/* Lossy mode */
|
||||
/* perhaps this should be an array??? */
|
||||
JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
|
||||
jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
};
|
||||
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
|
||||
|
||||
/* Lossy mode */
|
||||
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
/* Lossless mode */
|
||||
JMETHOD(JDIMENSION, encode_mcus, (j_compress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num, JDIMENSION nMCU));
|
||||
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Marker writing */
|
||||
struct jpeg_marker_writer {
|
||||
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
|
||||
@@ -128,6 +169,7 @@ struct jpeg_decomp_master {
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||
boolean lossless; /* True if decompressing a lossless image */
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
@@ -150,14 +192,19 @@ struct jpeg_d_main_controller {
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Decompression codec (decompressor proper) */
|
||||
struct jpeg_d_codec {
|
||||
JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo));
|
||||
/* Lossy mode: Coefficient buffer control
|
||||
* Lossless mode: Difference buffer control
|
||||
*/
|
||||
struct jpeg_d_coef_controller {
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE output_buf));
|
||||
|
||||
/* Lossy mode */
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
|
||||
/* Decompression postprocessing (color quantization buffer control) */
|
||||
@@ -192,6 +239,42 @@ struct jpeg_marker_reader {
|
||||
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||
};
|
||||
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* Lossy mode */
|
||||
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
/* Lossless mode */
|
||||
JMETHOD(JDIMENSION, decode_mcus, (j_decompress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num, JDIMENSION nMCU));
|
||||
JMETHOD(boolean, process_restart, (j_decompress_ptr cinfo));
|
||||
|
||||
/* This is here to share code between baseline and progressive decoders; */
|
||||
/* other modules probably should not use it */
|
||||
boolean insufficient_data; /* set TRUE after emitting warning */
|
||||
};
|
||||
|
||||
/* Lossy mode: Inverse DCT (also performs dequantization)
|
||||
* Lossless mode: Prediction, sample undifferencing, point transform, and
|
||||
* sample size scaling
|
||||
*/
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* Lossy mode */
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Upsampling (note that upsampler must also call color converter) */
|
||||
struct jpeg_upsampler {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
@@ -258,8 +341,6 @@ struct jpeg_color_quantizer {
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jinit_c_codec jICCodec
|
||||
#define jinit_lossy_c_codec jILossyC
|
||||
#define jinit_compress_master jICompress
|
||||
#define jinit_c_master_control jICMaster
|
||||
#define jinit_c_main_controller jICMainC
|
||||
@@ -268,24 +349,17 @@ struct jpeg_color_quantizer {
|
||||
#define jinit_color_converter jICColor
|
||||
#define jinit_downsampler jIDownsampler
|
||||
#define jinit_forward_dct jIFDCT
|
||||
#define jinit_shuff_encoder jISHEncoder
|
||||
#define jinit_huff_encoder jIHEncoder
|
||||
#define jinit_phuff_encoder jIPHEncoder
|
||||
#define jinit_marker_writer jIMWriter
|
||||
#define jinit_d_codec jIDCodec
|
||||
#define jinit_lossy_d_codec jILossyD
|
||||
#define jinit_lossless_d_codec jILosslsD
|
||||
#define jinit_master_decompress jIDMaster
|
||||
#define jinit_d_main_controller jIDMainC
|
||||
#define jinit_d_coef_controller jIDCoefC
|
||||
#define jinit_d_diff_controller jIDDiffC
|
||||
#define jinit_d_post_controller jIDPostC
|
||||
#define jinit_input_controller jIInCtlr
|
||||
#define jinit_marker_reader jIMReader
|
||||
#define jinit_shuff_decoder jISHDecoder
|
||||
#define jinit_huff_decoder jIHDecoder
|
||||
#define jinit_phuff_decoder jIPHDecoder
|
||||
#define jinit_lhuff_decoder jILHDecoder
|
||||
#define jinit_undifferencer jIUndiff
|
||||
#define jinit_d_scaler jIDScaler
|
||||
#define jinit_inverse_dct jIIDCT
|
||||
#define jinit_upsampler jIUpsampler
|
||||
#define jinit_color_deconverter jIDColor
|
||||
@@ -305,38 +379,50 @@ struct jpeg_color_quantizer {
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||
boolean transcode_only));
|
||||
EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_lossless_compressor JPP((j_compress_ptr cinfo));
|
||||
#endif
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_lossless_decompressor JPP((j_decompress_ptr cinfo));
|
||||
#endif
|
||||
/* Memory manager initialization */
|
||||
EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||
|
||||
|
||||
158
jpeglib.h
158
jpeglib.h
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file defines the application interface for the JPEG library.
|
||||
@@ -40,6 +41,13 @@
|
||||
* if you want to be compatible.
|
||||
*/
|
||||
|
||||
/* NOTE: In lossless mode, an MCU contains one or more samples rather than one
|
||||
* or more 8x8 DCT blocks, so the term "data unit" is used to generically
|
||||
* describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To
|
||||
* preserve backward API/ABI compatibility, the field and macro names retain
|
||||
* the "block" terminology.
|
||||
*/
|
||||
|
||||
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
|
||||
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
|
||||
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
|
||||
@@ -48,16 +56,15 @@
|
||||
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
|
||||
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
|
||||
/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
|
||||
* the PostScript DCT filter can emit files with many more than 10 data units
|
||||
* per MCU.
|
||||
* If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU
|
||||
* the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
|
||||
* If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
|
||||
* to handle it. We even let you do this from the jconfig.h file. However,
|
||||
* we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe
|
||||
* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
|
||||
* sometimes emits noncompliant files doesn't mean you should too.
|
||||
*/
|
||||
#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */
|
||||
#ifndef D_MAX_DATA_UNITS_IN_MCU
|
||||
#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */
|
||||
#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */
|
||||
#ifndef D_MAX_BLOCKS_IN_MCU
|
||||
#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -77,10 +84,6 @@ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
|
||||
|
||||
typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
|
||||
|
||||
typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */
|
||||
typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */
|
||||
typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */
|
||||
|
||||
|
||||
/* Types for JPEG compression parameters and working tables. */
|
||||
|
||||
@@ -140,25 +143,28 @@ typedef struct {
|
||||
|
||||
/* These values are computed during compression or decompression startup: */
|
||||
/* Component's size in data units.
|
||||
* Any dummy data units added to complete an MCU are not counted; therefore
|
||||
* these values do not depend on whether a scan is interleaved or not.
|
||||
* In lossy mode, any dummy blocks added to complete an MCU are not counted;
|
||||
* therefore these values do not depend on whether a scan is interleaved or
|
||||
* not. In lossless mode, these are always equal to the image width and
|
||||
* height.
|
||||
*/
|
||||
JDIMENSION width_in_data_units;
|
||||
JDIMENSION height_in_data_units;
|
||||
/* Size of a data unit in/output by the codec (in samples). Always
|
||||
* data_unit for compression. For decompression this is the size of the
|
||||
* output from one data_unit, reflecting any processing performed by the
|
||||
* codec. For example, in the DCT-based codec, scaling may be applied
|
||||
* during the IDCT step. Values of 1,2,4,8 are likely to be supported.
|
||||
* Note that different components may have different codec_data_unit sizes.
|
||||
JDIMENSION width_in_blocks;
|
||||
JDIMENSION height_in_blocks;
|
||||
/* Size of a data unit in samples. Always DCTSIZE for lossy compression.
|
||||
* For lossy decompression this is the size of the output from one DCT block,
|
||||
* reflecting any scaling we choose to apply during the IDCT step.
|
||||
* Values of 1,2,4,8 are likely to be supported. Note that different
|
||||
* components may receive different IDCT scalings. In lossless mode, this is
|
||||
* always equal to 1.
|
||||
*/
|
||||
int codec_data_unit;
|
||||
int DCT_scaled_size;
|
||||
/* The downsampled dimensions are the component's actual, unpadded number
|
||||
* of samples at the main buffer (preprocessing/compression interface), thus
|
||||
* downsampled_width = ceil(image_width * Hi/Hmax)
|
||||
* and similarly for height. For decompression, codec-based processing is
|
||||
* included (ie, IDCT scaling), so
|
||||
* downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit)
|
||||
* and similarly for height. For lossy decompression, IDCT scaling is
|
||||
* included, so
|
||||
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
|
||||
* In lossless mode, these are always equal to the image width and height.
|
||||
*/
|
||||
JDIMENSION downsampled_width; /* actual width in samples */
|
||||
JDIMENSION downsampled_height; /* actual height in samples */
|
||||
@@ -172,10 +178,10 @@ typedef struct {
|
||||
/* The decompressor output side may not use these variables. */
|
||||
int MCU_width; /* number of data units per MCU, horizontally */
|
||||
int MCU_height; /* number of data units per MCU, vertically */
|
||||
int MCU_data_units; /* MCU_width * MCU_height */
|
||||
int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */
|
||||
int last_col_width; /* # of non-dummy data_units across in last MCU */
|
||||
int last_row_height; /* # of non-dummy data_units down in last MCU */
|
||||
int MCU_blocks; /* MCU_width * MCU_height */
|
||||
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
|
||||
int last_col_width; /* # of non-dummy data units across in last MCU */
|
||||
int last_row_height; /* # of non-dummy data units down in last MCU */
|
||||
|
||||
/* Saved quantization table for component; NULL if none yet saved.
|
||||
* See jdinput.c comments about the need for this information.
|
||||
@@ -194,9 +200,11 @@ typedef struct {
|
||||
int comps_in_scan; /* number of components encoded in this scan */
|
||||
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
|
||||
int Ss, Se; /* progressive JPEG spectral selection parms
|
||||
lossless JPEG predictor select parm (Ss) */
|
||||
(Ss is the predictor selection value in
|
||||
lossless mode) */
|
||||
int Ah, Al; /* progressive JPEG successive approx. parms
|
||||
lossless JPEG point transform parm (Al) */
|
||||
(Al is the point transform value in lossless
|
||||
mode) */
|
||||
} jpeg_scan_info;
|
||||
|
||||
/* The decompressor can save APPn and COM markers in a list of these: */
|
||||
@@ -212,14 +220,6 @@ struct jpeg_marker_struct {
|
||||
/* the marker length word is not counted in data_length or original_length */
|
||||
};
|
||||
|
||||
/* Known codec processes. */
|
||||
|
||||
typedef enum {
|
||||
JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */
|
||||
JPROC_PROGRESSIVE, /* progressive DCT */
|
||||
JPROC_LOSSLESS /* lossless (sequential) */
|
||||
} J_CODEC_PROCESS;
|
||||
|
||||
/* Known color spaces. */
|
||||
|
||||
typedef enum {
|
||||
@@ -310,8 +310,6 @@ struct jpeg_compress_struct {
|
||||
* helper routines to simplify changing parameters.
|
||||
*/
|
||||
|
||||
boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */
|
||||
|
||||
int data_precision; /* bits of precision in image data */
|
||||
|
||||
int num_components; /* # of color components in JPEG image */
|
||||
@@ -381,17 +379,17 @@ struct jpeg_compress_struct {
|
||||
/*
|
||||
* These fields are computed during compression startup
|
||||
*/
|
||||
int data_unit; /* size of data unit in samples */
|
||||
J_CODEC_PROCESS process; /* encoding process of JPEG image */
|
||||
|
||||
boolean progressive_mode; /* TRUE if scan script uses progressive mode */
|
||||
int max_h_samp_factor; /* largest h_samp_factor */
|
||||
int max_v_samp_factor; /* largest v_samp_factor */
|
||||
|
||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */
|
||||
/* The codec receives data in units of MCU rows as defined for fully
|
||||
* interleaved scans (whether the JPEG file is interleaved or not).
|
||||
* There are v_samp_factor * data_unit sample rows of each component in an
|
||||
* "iMCU" (interleaved MCU) row.
|
||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or
|
||||
difference controller */
|
||||
/* The coefficient or difference controller receives data in units of MCU
|
||||
* rows as defined for fully interleaved scans (whether the JPEG file is
|
||||
* interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE
|
||||
* sample rows of each component in an "iMCU" (interleaved MCU) row. In
|
||||
* lossless mode, total_iMCU_rows is always equal to the image height.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -405,12 +403,13 @@ struct jpeg_compress_struct {
|
||||
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
|
||||
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||
|
||||
int data_units_in_MCU; /* # of data units per MCU */
|
||||
int MCU_membership[C_MAX_DATA_UNITS_IN_MCU];
|
||||
int blocks_in_MCU; /* # of data units per MCU */
|
||||
int MCU_membership[C_MAX_BLOCKS_IN_MCU];
|
||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||
/* i'th block in an MCU */
|
||||
/* i'th data unit in an MCU */
|
||||
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for
|
||||
scan */
|
||||
|
||||
/*
|
||||
* Links to compression subobjects (methods and private variables of modules)
|
||||
@@ -418,10 +417,12 @@ struct jpeg_compress_struct {
|
||||
struct jpeg_comp_master * master;
|
||||
struct jpeg_c_main_controller * main;
|
||||
struct jpeg_c_prep_controller * prep;
|
||||
struct jpeg_c_codec * codec;
|
||||
struct jpeg_c_coef_controller * coef;
|
||||
struct jpeg_marker_writer * marker;
|
||||
struct jpeg_color_converter * cconvert;
|
||||
struct jpeg_downsampler * downsample;
|
||||
struct jpeg_forward_dct * fdct;
|
||||
struct jpeg_entropy_encoder * entropy;
|
||||
jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
|
||||
int script_space_size;
|
||||
};
|
||||
@@ -556,6 +557,7 @@ struct jpeg_decompress_struct {
|
||||
jpeg_component_info * comp_info;
|
||||
/* comp_info[i] describes component that appears i'th in SOF */
|
||||
|
||||
boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
|
||||
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
|
||||
|
||||
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
|
||||
@@ -592,21 +594,19 @@ struct jpeg_decompress_struct {
|
||||
/*
|
||||
* These fields are computed during decompression startup
|
||||
*/
|
||||
int data_unit; /* size of data unit in samples */
|
||||
J_CODEC_PROCESS process; /* decoding process of JPEG image */
|
||||
|
||||
int max_h_samp_factor; /* largest h_samp_factor */
|
||||
int max_v_samp_factor; /* largest v_samp_factor */
|
||||
|
||||
int min_codec_data_unit; /* smallest codec_data_unit of any component */
|
||||
int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
|
||||
|
||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
|
||||
/* The codec's input and output progress is measured in units of "iMCU"
|
||||
* (interleaved MCU) rows. These are the same as MCU rows in fully
|
||||
* interleaved JPEG scans, but are used whether the scan is interleaved
|
||||
* or not. We define an iMCU row as v_samp_factor data_unit rows of each
|
||||
* component. Therefore, the codec output contains
|
||||
* v_samp_factor*codec_data_unit sample rows of a component per iMCU row.
|
||||
/* The coefficient or difference controller's input and output progress is
|
||||
* measured in units of "iMCU" (interleaved MCU) rows. These are the same as
|
||||
* MCU rows in fully interleaved JPEG scans, but are used whether the scan is
|
||||
* interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor
|
||||
* DCT block rows of each component. Therefore, the IDCT output contains
|
||||
* v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. In
|
||||
* lossless mode, total_iMCU_rows is always equal to the image height.
|
||||
*/
|
||||
|
||||
JSAMPLE * sample_range_limit; /* table for fast range-limiting */
|
||||
@@ -623,12 +623,13 @@ struct jpeg_decompress_struct {
|
||||
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
|
||||
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
|
||||
|
||||
int data_units_in_MCU; /* # of data _units per MCU */
|
||||
int MCU_membership[D_MAX_DATA_UNITS_IN_MCU];
|
||||
int blocks_in_MCU; /* # of data units per MCU */
|
||||
int MCU_membership[D_MAX_BLOCKS_IN_MCU];
|
||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
||||
/* i'th data unit in an MCU */
|
||||
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for
|
||||
scan */
|
||||
|
||||
/* This field is shared between entropy decoder and marker parser.
|
||||
* It is either zero or the code of a JPEG marker that has been
|
||||
@@ -641,10 +642,12 @@ struct jpeg_decompress_struct {
|
||||
*/
|
||||
struct jpeg_decomp_master * master;
|
||||
struct jpeg_d_main_controller * main;
|
||||
struct jpeg_d_codec * codec;
|
||||
struct jpeg_d_coef_controller * coef;
|
||||
struct jpeg_d_post_controller * post;
|
||||
struct jpeg_input_controller * inputctl;
|
||||
struct jpeg_marker_reader * marker;
|
||||
struct jpeg_entropy_decoder * entropy;
|
||||
struct jpeg_inverse_dct * idct;
|
||||
struct jpeg_upsampler * upsample;
|
||||
struct jpeg_color_deconverter * cconvert;
|
||||
struct jpeg_color_quantizer * cquantize;
|
||||
@@ -774,14 +777,6 @@ typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
|
||||
typedef struct jvirt_barray_control * jvirt_barray_ptr;
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
#define NEED_DARRAY
|
||||
#else
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
#define NEED_DARRAY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct jpeg_memory_mgr {
|
||||
/* Method pointers */
|
||||
JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
|
||||
@@ -794,11 +789,6 @@ struct jpeg_memory_mgr {
|
||||
JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
|
||||
JDIMENSION blocksperrow,
|
||||
JDIMENSION numrows));
|
||||
#ifdef NEED_DARRAY
|
||||
JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id,
|
||||
JDIMENSION diffsperrow,
|
||||
JDIMENSION numrows));
|
||||
#endif
|
||||
JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
|
||||
int pool_id,
|
||||
boolean pre_zero,
|
||||
@@ -877,7 +867,6 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
|
||||
#define jpeg_set_linear_quality jSetLQuality
|
||||
#define jpeg_add_quant_table jAddQuantTable
|
||||
#define jpeg_quality_scaling jQualityScaling
|
||||
#define jpeg_simple_lossless jSimLossless
|
||||
#define jpeg_simple_progression jSimProgress
|
||||
#define jpeg_suppress_tables jSuppressTables
|
||||
#define jpeg_alloc_quant_table jAlcQTable
|
||||
@@ -961,8 +950,9 @@ EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
|
||||
int scale_factor,
|
||||
boolean force_baseline));
|
||||
EXTERN(int) jpeg_quality_scaling JPP((int quality));
|
||||
EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo,
|
||||
int predictor, int point_transform));
|
||||
EXTERN(void) jpeg_enable_lossless JPP((j_compress_ptr cinfo,
|
||||
int predictor_selection_value,
|
||||
int point_transform));
|
||||
EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
|
||||
boolean suppress));
|
||||
|
||||
45
libjpeg.doc
45
libjpeg.doc
@@ -4,6 +4,7 @@ This file was part of the Independent JPEG Group's software:
|
||||
Copyright (C) 1994-1998, Thomas G. Lane.
|
||||
Lossless JPEG Modifications:
|
||||
Copyright (C) 1999, Ken Murchison.
|
||||
Copyright (C) 2022, D. R. Commander.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
|
||||
@@ -871,11 +872,27 @@ jpeg_simple_progression (j_compress_ptr cinfo)
|
||||
unless you want to make a custom scan sequence. You must ensure that
|
||||
the JPEG color space is set correctly before calling this routine.
|
||||
|
||||
jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform)
|
||||
Generates a default scan script for writing a lossless-JPEG file.
|
||||
This is the recommended method of creating a lossless file,
|
||||
unless you want to make a custom scan sequence. You must ensure that
|
||||
the JPEG color space is set correctly before calling this routine.
|
||||
jpeg_enable_lossless (j_compress_ptr cinfo, int predictor_selection_value,
|
||||
int point_transform)
|
||||
Enables lossless mode with the specified predictor selection value
|
||||
(1 - 7) and optional point transform (0 - {precision}-1, where
|
||||
{precision} is the JPEG data precision). A point transform value of 0
|
||||
is necessary in order to create a fully lossless JPEG image. (A
|
||||
non-zero point transform value right-shifts the input samples by the
|
||||
specified number of bits, which is effectively a form of lossy color
|
||||
quantization.) Note that the following features will be unavailable
|
||||
when compressing or decompressing lossless JPEG images:
|
||||
* Quality/quantization table selection
|
||||
* DCT/IDCT algorithm selection
|
||||
* Smoothing
|
||||
* Downsampling/upsampling
|
||||
* Color conversion (the JPEG image will use the same color space as
|
||||
the input image)
|
||||
* IDCT scaling
|
||||
* Raw (downsampled) data input/output
|
||||
* Transcoding of DCT coefficients
|
||||
Any parameters used to enable or configure those features will be
|
||||
ignored.
|
||||
|
||||
|
||||
Compression parameters (cinfo fields) include:
|
||||
@@ -915,15 +932,15 @@ boolean optimize_coding
|
||||
unsigned int restart_interval
|
||||
int restart_in_rows
|
||||
To emit restart markers in the JPEG file, set one of these nonzero.
|
||||
Set restart_interval to specify the exact interval in MCU blocks.
|
||||
Set restart_in_rows to specify the interval in MCU rows. (If
|
||||
restart_in_rows is not 0, then restart_interval is set after the
|
||||
image width in MCUs is computed.) Defaults are zero (no restarts).
|
||||
One restart marker per MCU row is often a good choice.
|
||||
NOTE: the overhead of restart markers is higher in grayscale JPEG
|
||||
files than in color files, and MUCH higher in progressive JPEGs.
|
||||
If you use restarts, you may want to use larger intervals in those
|
||||
cases.
|
||||
Set restart_interval to specify the exact interval in MCU blocks
|
||||
(samples in lossless mode). Set restart_in_rows to specify the
|
||||
interval in MCU rows. (If restart_in_rows is not 0, then
|
||||
restart_interval is set after the image width in MCUs is computed.)
|
||||
Defaults are zero (no restarts). One restart marker per MCU row is
|
||||
often a good choice. NOTE: the overhead of restart markers is higher
|
||||
in grayscale JPEG files than in color files, and MUCH higher in
|
||||
progressive JPEGs. If you use restarts, you may want to use larger
|
||||
intervals in those cases.
|
||||
|
||||
const jpeg_scan_info * scan_info
|
||||
int num_scans
|
||||
|
||||
72
makefile.cfg
72
makefile.cfg
@@ -74,15 +74,14 @@ INSTALL_DATA= @INSTALL_DATA@
|
||||
|
||||
# source files: JPEG library proper
|
||||
LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c \
|
||||
jchuff.c jcinit.c jclhuff.c jclossls.c jclossy.c jcmainct.c \
|
||||
jcmarker.c jcmaster.c jcodec.c jcomapi.c jcparam.c jcphuff.c jcpred.c \
|
||||
jcprepct.c jcsample.c jcscale.c jcshuff.c jctrans.c jdapimin.c \
|
||||
jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c \
|
||||
jddiffct.c jdhuff.c jdinput.c jdlhuff.c jdlossls.c jdlossy.c \
|
||||
jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c jdpostct.c \
|
||||
jdpred.c jdsample.c jdscale.c jdshuff.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
|
||||
jchuff.c jcinit.c jclhuff.c jclossls.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 jddiffct.c jdhuff.c jdinput.c jdlhuff.c \
|
||||
jdlossls.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
|
||||
@@ -91,9 +90,8 @@ APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.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 jlossls.h jlossy.h \
|
||||
jmemsys.h jmorecfg.h jpegint.h jpeglib.h jversion.h cdjpeg.h \
|
||||
cderror.h transupp.h
|
||||
INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jlossls.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 \
|
||||
@@ -113,22 +111,20 @@ TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \
|
||||
DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \
|
||||
$(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES)
|
||||
# library object files common to compression and decompression
|
||||
COMOBJECTS= jcomapi.$(O) jcodec.$(O) jutils.$(O) jerror.$(O) jmemmgr.$(O) \
|
||||
$(SYSDEPMEM)
|
||||
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) jclossls.$(O) jclossy.o jccoefct.$(O) jccolor.$(O) \
|
||||
jcsample.$(O) jchuff.$(O) jcphuff.$(O) jcshuff.$(O) jclhuff.$(O) \
|
||||
jcpred.$(O) jcscale.$(O) jcdiffct.$(O) jcdctmgr.$(O) jfdctfst.$(O) \
|
||||
jfdctflt.$(O) jfdctint.$(O)
|
||||
jcprepct.$(O) jclossls.$(O) jccoefct.$(O) jccolor.$(O) jcsample.$(O) \
|
||||
jchuff.$(O) jcphuff.$(O) jclhuff.$(O) jcdiffct.$(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) jdlossls.$(O) jdlossy.$(O) \
|
||||
jdhuff.$(O) jdlhuff.$(O) jdphuff.$(O) jdshuff.$(O) jdpred.$(O) \
|
||||
jdscale.$(O) jddiffct.$(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)
|
||||
jdmaster.$(O) jdinput.$(O) jdmarker.$(O) jdlossls.$(O) jdhuff.$(O) \
|
||||
jdlhuff.$(O) jdphuff.$(O) jddiffct.$(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)
|
||||
@@ -260,52 +256,44 @@ jconfig.h: jconfig.doc
|
||||
|
||||
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 jlossy.h
|
||||
jcodec.$(O): jcodec.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.h jlossls.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 jlossy.h jdct.h
|
||||
jcdctmgr.$(O): jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jcdiffct.$(O): jcdiffct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jchuff.$(O): jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.h jlossls.h jchuff.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
|
||||
jclhuff.$(O): jclhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h jchuff.h
|
||||
jclossls.$(O): jclossls.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jclossy.$(O): jclossy.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.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 jlossy.h jchuff.h
|
||||
jcpred.$(O): jcpred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.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
|
||||
jcscale.$(O): jcscale.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jcshuff.$(O): jcshuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.h jlossls.h jchuff.h
|
||||
jctrans.$(O): jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.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 jlossy.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 jlossy.h jdct.h
|
||||
jddctmgr.$(O): jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h
|
||||
jddiffct.$(O): jddiffct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jdhuff.$(O): jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.h jlossls.h jdhuff.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
|
||||
jdlhuff.$(O): jdlhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h jdhuff.h
|
||||
jdlossls.$(O): jdlossls.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jdlossy.$(O): jdlossy.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.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 jlossy.h jdhuff.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
|
||||
jdpred.$(O): jdpred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jdsample.$(O): jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h
|
||||
jdscale.$(O): jdscale.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossls.h
|
||||
jdshuff.$(O): jdshuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.h jdhuff.h
|
||||
jdtrans.$(O): jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jlossy.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
|
||||
|
||||
30
rdswitch.c
30
rdswitch.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* rdswitch.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* 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 process some of cjpeg's more complicated
|
||||
@@ -332,29 +330,3 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
GLOBAL(boolean)
|
||||
set_simple_lossless (j_compress_ptr cinfo, char *arg)
|
||||
{
|
||||
int pred, pt = 0;
|
||||
char ch;
|
||||
|
||||
ch = ','; /* if not set by sscanf, will be ',' */
|
||||
if (sscanf(arg, "%d%c", &pred, &ch) < 1)
|
||||
return FALSE;
|
||||
if (ch != ',') /* syntax check */
|
||||
return FALSE;
|
||||
while (*arg && *arg++ != ',') /* advance to next segment of arg string */
|
||||
;
|
||||
if (*arg) {
|
||||
if (sscanf(arg, "%d", &pt) != 1)
|
||||
pt = 0;
|
||||
}
|
||||
jpeg_simple_lossless(cinfo, pred, pt);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
122
structure.doc
122
structure.doc
@@ -4,6 +4,7 @@ This file was part of the Independent JPEG Group's software:
|
||||
Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
Lossless JPEG Modifications:
|
||||
Copyright (C) 1999, Ken Murchison.
|
||||
Copyright (C) 2022, D. R. Commander.
|
||||
For conditions of distribution and use, see the accompanying README file.
|
||||
|
||||
|
||||
@@ -23,7 +24,7 @@ In this document, JPEG-specific terminology follows the JPEG standard:
|
||||
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.
|
||||
A "data unit" is an abstract data type which is either a block for lossy
|
||||
A "data unit" is an abstract data type that is either a block for lossy
|
||||
(DCT-based) codecs or a sample for lossless (predictive) codecs.
|
||||
An "MCU" (minimum coded unit) is an interleaved set of data units of size
|
||||
determined by the sampling factors, or a single data unit in a
|
||||
@@ -47,8 +48,8 @@ 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, as well as the lossless (spatial)
|
||||
process. Hierarchical processes are not supported.
|
||||
sequential, progressive DCT, and lossless (spatial) processes. Hierarchical
|
||||
processes are not supported.
|
||||
|
||||
Within these limits, any set of compression parameters allowed by the JPEG
|
||||
spec should be readable for decompression. (We can be more restrictive about
|
||||
@@ -319,52 +320,31 @@ overall system structuring principle, not as a complete description of the
|
||||
task performed by any one controller.
|
||||
|
||||
|
||||
*** Codec object structure ***
|
||||
|
||||
As noted above, this library supports both the lossy (DCT-based) and lossless
|
||||
JPEG processes. Because these processes have little in common with one another
|
||||
(and their implementations share very little code), we need to provide a way to
|
||||
isloate the underlying JPEG process from the rest of the library. This is
|
||||
accomplished by introducing an abstract "codec object" which acts a generic
|
||||
interface to the JPEG (de)compressor proper.
|
||||
|
||||
Using the power of the object-oriented scheme described above, we build the
|
||||
lossy and lossless modules as two separate implementations of the codec object.
|
||||
Switching between lossy and lossless processes then becomes as trivial as
|
||||
assigning the appropriate method pointers during initialization of the library.
|
||||
|
||||
|
||||
*** Compression object structure ***
|
||||
|
||||
Here is a sketch of the logical structure of the JPEG compression library:
|
||||
Here is a sketch of the logical structure of the JPEG compression library in
|
||||
lossy mode:
|
||||
|
||||
|-- Colorspace conversion
|
||||
|-- Preprocessing controller --|
|
||||
| |-- Downsampling
|
||||
|
|
||||
Main controller --|
|
||||
| /--> Lossy codec
|
||||
| /
|
||||
|-- Compression codec < *OR*
|
||||
\
|
||||
\--> Lossless codec
|
||||
| |-- Forward DCT, quantize
|
||||
|-- Coefficient controller --|
|
||||
|-- Entropy encoding
|
||||
|
||||
... and in lossless mode:
|
||||
|
||||
where the lossy codec looks like:
|
||||
|
||||
|-- Forward DCT, quantize
|
||||
<-- Coefficient controller --|
|
||||
|-- Entropy encoding
|
||||
|
||||
|
||||
and the lossless codec looks like:
|
||||
|
||||
|-- Point transformation
|
||||
|
|
||||
<-- Difference controller --|-- Prediction, differencing
|
||||
|
|
||||
|-- Lossless entropy encoding
|
||||
|
||||
|-- Colorspace conversion
|
||||
|-- Preprocessing controller --|
|
||||
| |-- Downsampling
|
||||
Main controller --|
|
||||
| |-- Point transform
|
||||
| |
|
||||
|-- Difference controller --|-- Prediction, differencing
|
||||
|
|
||||
|-- Lossless mode 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
|
||||
@@ -425,16 +405,15 @@ The objects shown above are:
|
||||
of subsampled data is processed per call, even when the JPEG file is
|
||||
noninterleaved.
|
||||
|
||||
* Point transformation: Scale the data down by the point transformation
|
||||
parameter.
|
||||
* Point transform: Downscale the data by the point transform value.
|
||||
|
||||
* Prediction and differencing: Calculate the predictor and subtract it
|
||||
from the input. Works on one scanline per call. The difference
|
||||
controller supplies the prior scanline which is used for prediction.
|
||||
controller supplies the prior scanline, which is used for prediction.
|
||||
|
||||
* Lossless entropy encoding: Perform Huffman or arithmetic entropy coding and
|
||||
emit the coded data to the data destination module. This module handles MCU
|
||||
assembly. Works on one MCU-row per call.
|
||||
* Lossless mode entropy encoding: Perform Huffman or arithmetic entropy coding
|
||||
and emit the coded data to the data destination module. This module handles
|
||||
MCU assembly. Works on one MCU row per call.
|
||||
|
||||
In addition to the above objects, the compression library includes these
|
||||
objects:
|
||||
@@ -475,36 +454,32 @@ 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:
|
||||
Here is a sketch of the logical structure of the JPEG decompression library in
|
||||
lossy mode:
|
||||
|
||||
/--> Lossy codec
|
||||
/
|
||||
|-- Decompression codec < *OR*
|
||||
| \
|
||||
| \--> Lossless codec
|
||||
|-- Entropy decoding
|
||||
|-- Coefficient controller --|
|
||||
| |-- Dequantize, Inverse DCT
|
||||
Main controller --|
|
||||
|
|
||||
| |-- Upsampling
|
||||
|-- Postprocessing controller --| |-- Colorspace conversion
|
||||
|-- Color quantization
|
||||
|-- Color precision reduction
|
||||
|
||||
... and in lossless mode:
|
||||
|
||||
where the lossy codec looks like:
|
||||
|
||||
|-- Entropy decoding
|
||||
<-- Coefficient controller --|
|
||||
|-- Dequantize, Inverse DCT
|
||||
|
||||
|
||||
and the lossless codec looks like:
|
||||
|
||||
|-- Lossless entropy decoding
|
||||
|
|
||||
<-- Difference controller --|-- Prediction, undifferencing
|
||||
|
|
||||
|-- Point transformation, sample size scaling
|
||||
|
||||
|-- Lossless mode entropy
|
||||
| decoding
|
||||
|
|
||||
|-- Difference controller --|-- Prediction, undifferencing
|
||||
| |
|
||||
| |-- Point transform, sample size
|
||||
| scaling
|
||||
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:
|
||||
@@ -544,17 +519,16 @@ shown are:
|
||||
buffering the full image. The equivalent of one fully interleaved MCU row
|
||||
is processed per call, even when the source JPEG file is noninterleaved.
|
||||
|
||||
* Lossless entropy decoding: Read coded data from the data source module and
|
||||
perform Huffman or arithmetic entropy decoding. Works on one MCU-row per
|
||||
* Lossless mode entropy decoding: Read coded data from the data source module
|
||||
and perform Huffman or arithmetic entropy decoding. Works on one MCU row per
|
||||
call.
|
||||
|
||||
* Prediction and undifferencing: Calculate the predictor and add it to the
|
||||
decoded difference. Works on one scanline per call. The difference
|
||||
controller supplies the prior scanline which is used for prediction.
|
||||
controller supplies the prior scanline, which is used for prediction.
|
||||
|
||||
* Point transform and sample size scaling: Scale the data up by the point
|
||||
transformation parameter and scale it down to fit into the compiled-in
|
||||
sample size.
|
||||
* Point transform and sample size scaling: Upscale the data by the point
|
||||
transform value and downscale it to fit into the compiled-in sample size.
|
||||
|
||||
* Postprocessing controller: buffer controller for the color quantization
|
||||
input buffer, when quantization is in use. (Without quantization, this
|
||||
|
||||
44
transupp.c
44
transupp.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* transupp.c
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1997-1998, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* 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
|
||||
@@ -86,7 +84,7 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -138,7 +136,7 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -160,7 +158,7 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
/* 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_data_units;
|
||||
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];
|
||||
@@ -176,7 +174,7 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
} else {
|
||||
/* Just copy row verbatim. */
|
||||
jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
|
||||
compptr->width_in_data_units);
|
||||
compptr->width_in_blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,13 +201,13 @@ do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
*/
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -253,13 +251,13 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -317,13 +315,13 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -380,7 +378,7 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -420,7 +418,7 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only mirrored vertically. */
|
||||
for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) {
|
||||
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) {
|
||||
@@ -444,7 +442,7 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only copied. */
|
||||
for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) {
|
||||
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++)
|
||||
@@ -484,13 +482,13 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
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_data_units;
|
||||
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_data_units;
|
||||
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,
|
||||
@@ -602,9 +600,9 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
|
||||
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_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
@@ -624,9 +622,9 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
|
||||
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_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_data_units,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->h_samp_factor);
|
||||
}
|
||||
|
||||
29
usage.doc
29
usage.doc
@@ -140,6 +140,30 @@ progressive JPEG file at all.
|
||||
|
||||
Switches for advanced users:
|
||||
|
||||
-lossless psv[,Pt] Create a lossless JPEG file using the specified
|
||||
predictor selection value (1 - 7) and optional point
|
||||
transform (0 - {precision}-1, where {precision} is the
|
||||
JPEG data precision in bits). A point transform value
|
||||
of 0 (the default) is necessary in order to create a
|
||||
fully lossless JPEG file. (A non-zero point transform
|
||||
value right-shifts the input samples by the specified
|
||||
number of bits, which is effectively a form of lossy
|
||||
color quantization.) CAUTION: lossless JPEG is not yet
|
||||
widely implemented, so many decoders will be unable to
|
||||
view a lossless JPEG file at all. Note that the
|
||||
following features will be unavailable when compressing
|
||||
or decompressing a lossless JPEG file:
|
||||
* Quality/quantization table selection
|
||||
* Color conversion (the JPEG image will use the same
|
||||
color space as the input image)
|
||||
* DCT/IDCT algorithm selection
|
||||
* Smoothing
|
||||
* Downsampling/upsampling
|
||||
* IDCT scaling
|
||||
* Transformations using jpegtran
|
||||
Any switches used to enable or configure those features
|
||||
will be ignored.
|
||||
|
||||
-dct int Use integer DCT method (default).
|
||||
-dct fast Use fast integer DCT (less accurate).
|
||||
-dct float Use floating-point DCT method.
|
||||
@@ -152,8 +176,9 @@ Switches for advanced users:
|
||||
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.
|
||||
N MCU blocks (samples in lossless mode) 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
|
||||
|
||||
40
wizard.doc
40
wizard.doc
@@ -115,23 +115,23 @@ 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:
|
||||
of progression parameters. You can create multiple-scan sequential or lossless
|
||||
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.
|
||||
the components to be included in the scan, and for progressive and lossless
|
||||
JPEG it also specifies the progression/lossless 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
|
||||
followed by a colon (':') and the four progressive/lossless-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
|
||||
@@ -142,13 +142,23 @@ The progression parameters for each scan are:
|
||||
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 lossless parameters for each scan are:
|
||||
Ss Predictor selection value
|
||||
Se Must be zero
|
||||
Ah Must be zero
|
||||
Al Point transform value
|
||||
|
||||
If the progression/lossless 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.)
|
||||
Ss and Se values other than 0 and 63 appear. cjpeg also automatically
|
||||
determines whether the script represents a lossless file, by observing whether
|
||||
Ss (the predictor selection value) is non-zero and Se is zero, which are
|
||||
illegal values for progressive and sequential files. (The -progressive and
|
||||
-lossless switches are not needed to specify this; in fact, they are 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
|
||||
|
||||
Reference in New Issue
Block a user