@@ -273,12 +273,12 @@ endif()
|
||||
# 1: + In-memory source/destination managers (libjpeg-turbo 1.3.x)
|
||||
# 2: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
||||
# 3: + ICC functions (libjpeg-turbo 2.0.x)
|
||||
# 4: + 12-bit-per-component functions (libjpeg-turbo 2.2.x)
|
||||
# 4: + 12-bit-per-component and lossless functions (libjpeg-turbo 2.2.x)
|
||||
#
|
||||
# libjpeg v8 API/ABI emulation:
|
||||
# 1: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
||||
# 2: + ICC functions (libjpeg-turbo 2.0.x)
|
||||
# 3: + 12-bit-per-component functions (libjpeg-turbo 2.2.x)
|
||||
# 3: + 12-bit-per-component and lossless functions (libjpeg-turbo 2.2.x)
|
||||
set(SO_AGE 3)
|
||||
if(NOT WITH_JPEG8)
|
||||
set(SO_AGE 4)
|
||||
@@ -535,10 +535,11 @@ if(CMAKE_EXECUTABLE_SUFFIX_TMP)
|
||||
endif()
|
||||
message(STATUS "CMAKE_EXECUTABLE_SUFFIX = ${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
|
||||
set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c
|
||||
jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c
|
||||
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c
|
||||
jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.c
|
||||
set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c
|
||||
jcdiffct.c jchuff.c jcicc.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 jdicc.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 jmemnobs.c)
|
||||
@@ -557,10 +558,11 @@ endif()
|
||||
|
||||
# Compile a separate version of these source files with 12-bit data
|
||||
# precision.
|
||||
add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcmainct.c
|
||||
jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c jddctmgr.c jdmainct.c
|
||||
jdmerge.c jdpostct.c jdsample.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c
|
||||
jidctint.c jidctred.c jquant1.c jquant2.c jutils.c)
|
||||
add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c
|
||||
jclossls.c jcmainct.c jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c
|
||||
jddctmgr.c jddiffct.c jdlossls.c jdmainct.c jdmerge.c jdpostct.c jdsample.c
|
||||
jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c
|
||||
jquant2.c jutils.c)
|
||||
set_property(TARGET jpeg12 PROPERTY COMPILE_FLAGS "-DBITS_IN_JSAMPLE=12")
|
||||
|
||||
if(WITH_SIMD)
|
||||
@@ -1046,6 +1048,8 @@ foreach(libtype ${TEST_LIBTYPES})
|
||||
set(MD5_PPM_420M_ISLOW_3_8 343d19015531b7bbe746124127244fa8)
|
||||
set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
|
||||
set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7)
|
||||
set(MD5_JPEG_LOSSLESS a153297ef3ae6e51357be06fc5efca2a)
|
||||
set(MD5_PPM_LOSSLESS 1da3fb2620e5a4e258e0fcb891bc67e8)
|
||||
set(MD5_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97)
|
||||
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
||||
452a21656115a163029cfba5c04fa76a)
|
||||
@@ -1121,6 +1125,8 @@ foreach(libtype ${TEST_LIBTYPES})
|
||||
set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2)
|
||||
set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f)
|
||||
set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b)
|
||||
set(MD5_JPEG_LOSSLESS dd21c541d22a87cccabdb48b796d8bcd)
|
||||
set(MD5_PPM_LOSSLESS 64072f1dbdc5b3a187777788604971a5)
|
||||
set(MD5_PPM_420_ISLOW_SKIP15_31 c4c65c1e43d7275cd50328a61e6534f0)
|
||||
set(MD5_PPM_420_ISLOW_ARI_SKIP16_139 087c6b123db16ac00cb88c5b590bb74a)
|
||||
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
||||
@@ -1362,6 +1368,16 @@ foreach(libtype ${TEST_LIBTYPES})
|
||||
${MD5_BMP_420M_ISLOW_565D})
|
||||
endif()
|
||||
|
||||
# Lossless (all arguments other than -lossless should have no effect)
|
||||
add_bittest(${cjpeg} lossless
|
||||
"-lossless;4;-quality;1;-grayscale;-optimize;-dct;float;-smooth;100;-baseline;-qslots;1,0,0;-sample;1x2,3x4,2x1"
|
||||
${testout}_lossless.jpg ${TESTIMAGES}/testorig.ppm
|
||||
${MD5_JPEG_LOSSLESS})
|
||||
add_bittest(${djpeg} lossless
|
||||
"-fast;-scale;1/8;-dct;float;-dither;none;-nosmooth;-onepass"
|
||||
${testout}_lossless.ppm ${testout}_lossless.jpg
|
||||
${MD5_PPM_LOSSLESS} ${cjpeg}-${libtype}-lossless)
|
||||
|
||||
# Partial decode tests. These tests are designed to cover all of the
|
||||
# possible code paths in jpeg_skip_scanlines().
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ tables.
|
||||
3. All deprecated fields, constructors, and methods in the TurboJPEG Java API
|
||||
have been removed.
|
||||
|
||||
4. Added support for 8-bit and 12-bit lossless JPEG images. A new libjpeg API
|
||||
function (`jpeg_enable_lossless()`) and cjpeg command-line argument
|
||||
(`-lossless`) can be used to create a lossless JPEG image. (Decompression of
|
||||
lossless JPEG images is handled automatically.)
|
||||
|
||||
|
||||
2.1.5
|
||||
=====
|
||||
|
||||
22
README.ijg
22
README.ijg
@@ -68,17 +68,17 @@ other abrupt features may not compress well with JPEG, and a higher JPEG
|
||||
quality may have to be used to avoid visible compression artifacts with such
|
||||
images.
|
||||
|
||||
JPEG is lossy, meaning that the output pixels are not necessarily identical to
|
||||
the input pixels. However, on photographic content and other "smooth" images,
|
||||
very good compression ratios can be obtained with no visible compression
|
||||
artifacts, and extremely high compression ratios are possible if you are
|
||||
willing to sacrifice image quality (by reducing the "quality" setting in the
|
||||
compressor.)
|
||||
JPEG is normally lossy, meaning that the output pixels are not necessarily
|
||||
identical to the input pixels. However, on photographic content and other
|
||||
"smooth" images, very good compression ratios can be obtained with no visible
|
||||
compression artifacts, and extremely high compression ratios are possible if
|
||||
you are willing to sacrifice image quality (by reducing the "quality" setting
|
||||
in the compressor.)
|
||||
|
||||
This software implements JPEG baseline, extended-sequential, and progressive
|
||||
compression processes. Provision is made for supporting all variants of these
|
||||
processes, although some uncommon parameter settings aren't implemented yet.
|
||||
We have made no provision for supporting the hierarchical or lossless
|
||||
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. We have made no provision for supporting the hierarchical
|
||||
processes defined in the standard.
|
||||
|
||||
We provide a set of library routines for reading and writing JPEG image files,
|
||||
@@ -241,7 +241,7 @@ This software implements ITU T.81 | ISO/IEC 10918 with some extensions from
|
||||
ITU T.871 | ISO/IEC 10918-5 (JPEG File Interchange Format-- see REFERENCES).
|
||||
Informally, the term "JPEG image" or "JPEG file" most often refers to JFIF or
|
||||
a subset thereof, but there are other formats containing the name "JPEG" that
|
||||
are incompatible with the DCT-based JPEG standard or with JFIF (for instance,
|
||||
are incompatible with the original JPEG standard or with JFIF (for instance,
|
||||
JPEG 2000 and JPEG XR). This software therefore does not support these
|
||||
formats. Indeed, one of the original reasons for developing this free software
|
||||
was to help force convergence on a common, interoperable format standard for
|
||||
|
||||
45
cjpeg.1
45
cjpeg.1
@@ -1,4 +1,4 @@
|
||||
.TH CJPEG 1 "2 November 2022"
|
||||
.TH CJPEG 1 "14 November 2022"
|
||||
.SH NAME
|
||||
cjpeg \- compress an image file to a JPEG file
|
||||
.SH SYNOPSIS
|
||||
@@ -155,6 +155,45 @@ Create JPEG file with N-bit data precision. N is 8 or 12; default is 8.
|
||||
12-bit JPEG is not yet widely implemented, so many decoders will be unable to
|
||||
view a 12-bit JPEG file at all.
|
||||
.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
|
||||
- Partial image decompression
|
||||
.IP
|
||||
- Transformations using
|
||||
.B jpegtran
|
||||
.IP
|
||||
Any switches used to enable or configure those features will be ignored.
|
||||
.TP
|
||||
.B \-arithmetic
|
||||
Use arithmetic coding.
|
||||
.B Caution:
|
||||
@@ -201,8 +240,8 @@ machines.
|
||||
Embed ICC color management profile contained in the specified file.
|
||||
.TP
|
||||
.BI \-restart " N"
|
||||
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
|
||||
attached to the number.
|
||||
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
|
||||
|
||||
29
cjpeg.c
29
cjpeg.c
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2003-2011 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -212,6 +214,9 @@ usage(void)
|
||||
fprintf(stderr, "Switches for advanced users:\n");
|
||||
fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n");
|
||||
fprintf(stderr, " (N is 8 or 12; default is 8)\n");
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
|
||||
#endif
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||
#endif
|
||||
@@ -265,6 +270,9 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
|
||||
{
|
||||
int argn;
|
||||
char *arg;
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
int psv, pt = 0;
|
||||
#endif
|
||||
boolean force_baseline;
|
||||
boolean simple_progressive;
|
||||
char *qualityarg = NULL; /* saves -quality parm if any */
|
||||
@@ -361,6 +369,27 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
|
||||
usage();
|
||||
icc_filename = argv[argn];
|
||||
|
||||
} else if (keymatch(arg, "lossless", 1)) {
|
||||
/* Enable lossless mode. */
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
char ch = ',', *ptr;
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
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);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||
long lval;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -94,6 +95,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));
|
||||
memset(cinfo->master, 0, sizeof(my_comp_master));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -136,6 +136,9 @@ _jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data,
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
|
||||
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) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -716,4 +716,13 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
cconvert->pub._color_convert = null_convert;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prevent lossy color conversion in lossless mode */
|
||||
if (cinfo->master->lossless) {
|
||||
if ((cinfo->jpeg_color_space == JCS_GRAYSCALE &&
|
||||
cinfo->in_color_space != JCS_GRAYSCALE) ||
|
||||
(cinfo->jpeg_color_space != JCS_GRAYSCALE &&
|
||||
cconvert->pub._color_convert != null_convert))
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
411
jcdiffct.c
Normal file
411
jcdiffct.c
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* jcdiffct.c
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* 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 the prediction/differencing and entropy
|
||||
* encoding steps.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
/* We use a full-image sample buffer when doing Huffman optimization,
|
||||
* and also for writing multiple-scan JPEG files. In all cases, the
|
||||
* full-image buffer is filled during the first pass, and the scaling,
|
||||
* prediction and differencing steps are run during subsequent passes.
|
||||
*/
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
#define FULL_SAMP_BUFFER_SUPPORTED
|
||||
#else
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
#define FULL_SAMP_BUFFER_SUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_c_coef_controller pub; /* public fields */
|
||||
|
||||
JDIMENSION iMCU_row_num; /* iMCU row # within image */
|
||||
JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
_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];
|
||||
} my_diff_controller;
|
||||
|
||||
typedef my_diff_controller *my_diff_ptr;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf);
|
||||
#ifdef FULL_SAMP_BUFFER_SUPPORTED
|
||||
METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
|
||||
_JSAMPIMAGE input_buf);
|
||||
METHODDEF(boolean) compress_output(j_compress_ptr cinfo,
|
||||
_JSAMPIMAGE input_buf);
|
||||
#endif
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
start_iMCU_row(j_compress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row */
|
||||
{
|
||||
my_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.
|
||||
* But at the bottom of the image, process only what's left.
|
||||
*/
|
||||
if (cinfo->comps_in_scan > 1) {
|
||||
diff->MCU_rows_per_iMCU_row = 1;
|
||||
} else {
|
||||
if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1))
|
||||
diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||
else
|
||||
diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||
}
|
||||
|
||||
diff->mcu_ctr = 0;
|
||||
diff->MCU_vert_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_diff(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
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);
|
||||
|
||||
switch (pass_mode) {
|
||||
case JBUF_PASS_THRU:
|
||||
if (diff->whole_image[0] != NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
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);
|
||||
diff->pub._compress_data = compress_first_pass;
|
||||
break;
|
||||
case JBUF_CRANK_DEST:
|
||||
if (diff->whole_image[0] == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
diff->pub._compress_data = compress_output;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define SWAP_ROWS(rowa, rowb) { \
|
||||
_JSAMPROW temp = rowa; \
|
||||
rowa = rowb; rowb = temp; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Process some data in the single-pass case.
|
||||
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||
* per call, ie, v_samp_factor rows for each component in the image.
|
||||
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
|
||||
*
|
||||
* NB: input_buf contains a plane for each component in image,
|
||||
* which we index according to the component's SOF position.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
|
||||
{
|
||||
my_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_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int ci, compi, yoffset, samp_row, samp_rows, samps_across;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Loop to write as much as one whole iMCU row */
|
||||
for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
|
||||
yoffset++) {
|
||||
|
||||
MCU_col_num = diff->mcu_ctr;
|
||||
|
||||
/* Scale and predict each scanline of the MCU row separately.
|
||||
*
|
||||
* 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 (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_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
|
||||
* will encode to the smallest amount of data.
|
||||
*/
|
||||
for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
|
||||
samp_row++)
|
||||
memset(diff->diff_buf[compi][samp_row], 0,
|
||||
jround_up((long)compptr->width_in_blocks,
|
||||
(long)compptr->h_samp_factor) * sizeof(JDIFF));
|
||||
}
|
||||
}
|
||||
samps_across = compptr->width_in_blocks;
|
||||
|
||||
for (samp_row = 0; samp_row < samp_rows; samp_row++) {
|
||||
(*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). */
|
||||
MCU_count =
|
||||
(*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);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FULL_SAMP_BUFFER_SUPPORTED
|
||||
|
||||
/*
|
||||
* Process some data in the first pass of a multi-pass case.
|
||||
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||
* per call, ie, v_samp_factor rows for each component in the image.
|
||||
* This amount of data is read from the source buffer and saved into the
|
||||
* virtual arrays.
|
||||
*
|
||||
* We must also emit the data to the compressor. This is conveniently
|
||||
* done by calling compress_output() after we've loaded the current strip
|
||||
* of the virtual arrays.
|
||||
*
|
||||
* NB: input_buf contains a plane for each component in image. All components
|
||||
* are loaded into the virtual arrays in this pass. However, it may be that
|
||||
* only a subset of the components are emitted to the compressor during
|
||||
* this first pass; be careful about looking at the scan-dependent variables
|
||||
* (MCU dimensions, etc).
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
|
||||
{
|
||||
my_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;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Align the virtual buffer for this component. */
|
||||
buffer = (_JSAMPARRAY)(*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);
|
||||
|
||||
/* Count non-dummy sample rows in this iMCU row. */
|
||||
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_blocks % compptr->v_samp_factor);
|
||||
if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
|
||||
}
|
||||
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
|
||||
* processes a complete row of samples.
|
||||
*/
|
||||
for (samp_row = 0; samp_row < samp_rows; samp_row++) {
|
||||
memcpy(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.
|
||||
*/
|
||||
|
||||
/* Emit data to the compressor, sharing code with subsequent passes */
|
||||
return compress_output(cinfo, input_buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data in subsequent passes of a multi-pass case.
|
||||
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
||||
* per call, ie, v_samp_factor rows for each component in the scan.
|
||||
* The data is obtained from the virtual arrays and fed to the compressor.
|
||||
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
|
||||
*
|
||||
* NB: input_buf is ignored; it is likely to be a NULL pointer.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf)
|
||||
{
|
||||
my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
|
||||
int ci, compi;
|
||||
_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 (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
compi = compptr->component_index;
|
||||
buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr)cinfo, diff->whole_image[compi],
|
||||
diff->iMCU_row_num * compptr->v_samp_factor,
|
||||
(JDIMENSION)compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
|
||||
return compress_data(cinfo, buffer);
|
||||
}
|
||||
|
||||
#endif /* FULL_SAMP_BUFFER_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize difference buffer controller.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
_jinit_c_diff_controller(j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
my_diff_ptr diff;
|
||||
int ci, row;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
diff = (my_diff_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
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] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION)jround_up((long)compptr->width_in_blocks,
|
||||
(long)compptr->h_samp_factor),
|
||||
(JDIMENSION)1);
|
||||
diff->prev_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION)jround_up((long)compptr->width_in_blocks,
|
||||
(long)compptr->h_samp_factor),
|
||||
(JDIMENSION)1);
|
||||
}
|
||||
|
||||
/* Create the difference buffer. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
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
|
||||
* to the smallest amount of data.
|
||||
*/
|
||||
for (row = 0; row < compptr->v_samp_factor; row++)
|
||||
memset(diff->diff_buf[ci][row], 0,
|
||||
jround_up((long)compptr->width_in_blocks,
|
||||
(long)compptr->h_samp_factor) * sizeof(JDIFF));
|
||||
}
|
||||
|
||||
/* Create the sample buffer. */
|
||||
if (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. */
|
||||
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_blocks,
|
||||
(long)compptr->h_samp_factor),
|
||||
(JDIMENSION)jround_up((long)compptr->height_in_blocks,
|
||||
(long)compptr->v_samp_factor),
|
||||
(JDIMENSION)compptr->v_samp_factor);
|
||||
}
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
#endif
|
||||
} else
|
||||
diff->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
18
jchuff.c
18
jchuff.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander.
|
||||
* Copyright (C) 2015, Matthieu Darbois.
|
||||
@@ -30,7 +32,7 @@
|
||||
#ifdef WITH_SIMD
|
||||
#include "jsimd.h"
|
||||
#else
|
||||
#include "jchuff.h"
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
@@ -251,7 +253,7 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
|
||||
* 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.
|
||||
* Note this is also used by jcphuff.c and jclhuff.c.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
@@ -327,12 +329,12 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
|
||||
memset(dtbl->ehufco, 0, sizeof(dtbl->ehufco));
|
||||
memset(dtbl->ehufsi, 0, 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..15 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 ? 15 : 255;
|
||||
maxsymbol = isDC ? (cinfo->master->lossless ? 16 : 15) : 255;
|
||||
|
||||
for (p = 0; p < lastp; p++) {
|
||||
i = htbl->huffval[p];
|
||||
@@ -918,7 +920,7 @@ encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/*
|
||||
* Generate the best Huffman code table for the given counts, fill htbl.
|
||||
* Note this is also used by jcphuff.c.
|
||||
* 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
|
||||
|
||||
79
jcinit.c
79
jcinit.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2020, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -49,39 +51,68 @@ jinit_compress_master(j_compress_ptr cinfo)
|
||||
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
}
|
||||
}
|
||||
/* Forward DCT */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_forward_dct(cinfo);
|
||||
else
|
||||
jinit_forward_dct(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
jinit_arith_encoder(cinfo);
|
||||
|
||||
if (cinfo->master->lossless) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
/* Prediction, sample differencing, and point transform */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_lossless_compressor(cinfo);
|
||||
else
|
||||
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. */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
else
|
||||
jinit_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_encoder(cinfo);
|
||||
/* Forward DCT */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_forward_dct(cinfo);
|
||||
else
|
||||
jinit_forward_dct(cinfo);
|
||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
jinit_arith_encoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_encoder(cinfo);
|
||||
} 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. */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
else
|
||||
jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
}
|
||||
|
||||
/* Need a full-image coefficient buffer in any multi-pass mode. */
|
||||
if (cinfo->data_precision == 12) {
|
||||
j12init_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
} else {
|
||||
jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
||||
cinfo->optimize_coding));
|
||||
else
|
||||
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
}
|
||||
|
||||
jinit_marker_writer(cinfo);
|
||||
|
||||
|
||||
587
jclhuff.c
Normal file
587
jclhuff.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* jclhuff.c
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains Huffman entropy encoding routines for lossless 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 "jlossls.h" /* Private declarations for lossless codec */
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
JLONG put_buffer; /* current bit-accumulation buffer */
|
||||
int put_bits; /* # of bits now in it */
|
||||
} savable_state;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int ci, yoffset, MCU_width;
|
||||
} lhe_input_ptr_info;
|
||||
|
||||
|
||||
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. */
|
||||
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 *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_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_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_BLOCKS_IN_MCU];
|
||||
|
||||
/* Number of input pointers in use for the current MCU. This is the sum
|
||||
* of all Vi in the MCU.
|
||||
*/
|
||||
int num_input_ptrs;
|
||||
|
||||
/* Information used for positioning the input pointers within the input
|
||||
* difference rows.
|
||||
*/
|
||||
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_BLOCKS_IN_MCU];
|
||||
|
||||
} lhuff_entropy_encoder;
|
||||
|
||||
typedef lhuff_entropy_encoder *lhuff_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(JDIMENSION) encode_mcus_huff(j_compress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU);
|
||||
METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo);
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
METHODDEF(JDIMENSION) encode_mcus_gather(j_compress_ptr cinfo,
|
||||
JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num,
|
||||
JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU);
|
||||
METHODDEF(void) finish_pass_gather(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_lhuff(j_compress_ptr cinfo, boolean gather_statistics)
|
||||
{
|
||||
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
|
||||
entropy->pub.encode_mcus = encode_mcus_gather;
|
||||
entropy->pub.finish_pass = finish_pass_gather;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
entropy->pub.encode_mcus = encode_mcus_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;
|
||||
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);
|
||||
/* Allocate and zero the statistics tables */
|
||||
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
|
||||
if (entropy->count_ptrs[dctbl] == NULL)
|
||||
entropy->count_ptrs[dctbl] = (long *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
257 * sizeof(long));
|
||||
memset(entropy->count_ptrs[dctbl], 0, 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->derived_tbls[dctbl]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Precalculate encoding info for each sample in an MCU of this scan */
|
||||
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++) {
|
||||
/* Precalculate the setup info for each input pointer */
|
||||
entropy->input_ptr_info[ptrn].ci = ci;
|
||||
entropy->input_ptr_info[ptrn].yoffset = yoffset;
|
||||
entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width;
|
||||
for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
|
||||
/* Precalculate the input pointer index for each sample */
|
||||
entropy->input_ptr_index[sampn] = ptrn;
|
||||
/* Precalculate which tables to use for each sample */
|
||||
entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
|
||||
entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no];
|
||||
}
|
||||
}
|
||||
}
|
||||
entropy->num_input_ptrs = ptrn;
|
||||
|
||||
/* 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 JLONG put_buffer = (JLONG)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 &= (((JLONG)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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emit a restart marker & resynchronize predictions.
|
||||
*/
|
||||
|
||||
LOCAL(boolean)
|
||||
emit_restart(working_state *state, int restart_num)
|
||||
{
|
||||
if (!flush_bits(state))
|
||||
return FALSE;
|
||||
|
||||
emit_byte(state, 0xFF, return FALSE);
|
||||
emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
|
||||
|
||||
/* The restart counter is not updated until we successfully write the MCU. */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode and output nMCU MCUs' worth of Huffman-compressed differences.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
encode_mcus_huff(j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU)
|
||||
{
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
|
||||
working_state state;
|
||||
int sampn, ci, yoffset, MCU_width, ptrn;
|
||||
JDIMENSION mcu_num;
|
||||
|
||||
/* Load up working state */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
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 0;
|
||||
}
|
||||
|
||||
/* Set input pointer locations based on MCU_col_num */
|
||||
for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
|
||||
ci = entropy->input_ptr_info[ptrn].ci;
|
||||
yoffset = entropy->input_ptr_info[ptrn].yoffset;
|
||||
MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
|
||||
entropy->input_ptr[ptrn] =
|
||||
diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
|
||||
}
|
||||
|
||||
for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
|
||||
|
||||
/* Inner loop handles the samples in the MCU */
|
||||
for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
|
||||
|
||||
/* Encode the difference per section H.1.2.2 */
|
||||
|
||||
/* Input the sample difference */
|
||||
temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
|
||||
|
||||
if (temp & 0x8000) { /* instead of temp < 0 */
|
||||
temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
|
||||
if (temp == 0) /* special case: magnitude = 32768 */
|
||||
temp2 = temp = 0x8000;
|
||||
temp2 = ~temp; /* one's complement of magnitude */
|
||||
} else {
|
||||
temp &= 0x7FFF; /* abs value mod 2^16 */
|
||||
temp2 = temp; /* magnitude */
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the difference */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range difference values.
|
||||
*/
|
||||
if (nbits > MAX_DIFF_BITS)
|
||||
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]))
|
||||
return mcu_num;
|
||||
|
||||
/* 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 */
|
||||
nbits != 16) /* special case: no bits should be emitted */
|
||||
if (!emit_bits(&state, (unsigned int)temp2, nbits))
|
||||
return mcu_num;
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
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 nMCU;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at the end of a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_huff(j_compress_ptr cinfo)
|
||||
{
|
||||
lhuff_entropy_ptr entropy = (lhuff_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;
|
||||
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;
|
||||
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
|
||||
|
||||
/*
|
||||
* Trial-encode nMCU MCUs' worth of Huffman-compressed differences.
|
||||
* No data is actually output, so no suspension return is possible.
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
encode_mcus_gather(j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU)
|
||||
{
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
|
||||
int sampn, ci, yoffset, MCU_width, ptrn;
|
||||
JDIMENSION mcu_num;
|
||||
|
||||
/* Take care of restart intervals if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0) {
|
||||
/* Update restart state */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
entropy->restarts_to_go--;
|
||||
}
|
||||
|
||||
/* Set input pointer locations based on MCU_col_num */
|
||||
for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
|
||||
ci = entropy->input_ptr_info[ptrn].ci;
|
||||
yoffset = entropy->input_ptr_info[ptrn].yoffset;
|
||||
MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
|
||||
entropy->input_ptr[ptrn] =
|
||||
diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
|
||||
}
|
||||
|
||||
for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
|
||||
|
||||
/* Inner loop handles the samples in the MCU */
|
||||
for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) {
|
||||
register int temp;
|
||||
register int nbits;
|
||||
long *counts = entropy->cur_counts[sampn];
|
||||
|
||||
/* Encode the difference per section H.1.2.2 */
|
||||
|
||||
/* Input the sample difference */
|
||||
temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
|
||||
|
||||
if (temp & 0x8000) { /* instead of temp < 0 */
|
||||
temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
|
||||
if (temp == 0) /* special case: magnitude = 32768 */
|
||||
temp = 0x8000;
|
||||
} else
|
||||
temp &= 0x7FFF; /* abs value mod 2^16 */
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the difference */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range difference values.
|
||||
*/
|
||||
if (nbits > MAX_DIFF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
counts[nbits]++;
|
||||
}
|
||||
}
|
||||
|
||||
return nMCU;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up a statistics-gathering pass and create the new Huffman tables.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
finish_pass_gather(j_compress_ptr cinfo)
|
||||
{
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
|
||||
int ci, dctbl;
|
||||
jpeg_component_info *compptr;
|
||||
JHUFF_TBL **htblptr;
|
||||
boolean did_dc[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!
|
||||
*/
|
||||
memset(did_dc, 0, sizeof(did_dc));
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_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->count_ptrs[dctbl]);
|
||||
did_dc[dctbl] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* ENTROPY_OPT_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy encoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lhuff_encoder(j_compress_ptr cinfo)
|
||||
{
|
||||
lhuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (lhuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
sizeof(lhuff_entropy_encoder));
|
||||
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++) {
|
||||
entropy->derived_tbls[i] = NULL;
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
entropy->count_ptrs[i] = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
318
jclossls.c
Normal file
318
jclossls.c
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* jclossls.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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains prediction, sample differencing, and point transform
|
||||
* routines for the lossless JPEG compressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#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(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 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 = *input_buf++; \
|
||||
*diff_buf++ = samp - INITIAL_PREDICTOR; \
|
||||
\
|
||||
while (--width) { \
|
||||
Ra = samp; \
|
||||
samp = *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 = *prev_row++; \
|
||||
samp = *input_buf++; \
|
||||
*diff_buf++ = samp - PREDICTOR2; \
|
||||
\
|
||||
while (--width) { \
|
||||
Rc = Rb; \
|
||||
Rb = *prev_row++; \
|
||||
Ra = samp; \
|
||||
samp = *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(*input_buf++, cinfo->Al);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_compress_ptr cinfo,
|
||||
_JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
memcpy(output_buf, input_buf, width * sizeof(_JSAMPLE));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_lossless(j_compress_ptr cinfo)
|
||||
{
|
||||
lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct;
|
||||
int ci;
|
||||
|
||||
/* 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 compressor.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
_jinit_lossless_compressor(j_compress_ptr cinfo)
|
||||
{
|
||||
lossless_comp_ptr losslessc;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
losslessc = (lossless_comp_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
|
||||
sizeof(jpeg_lossless_compressor));
|
||||
cinfo->fdct = (struct jpeg_forward_dct *)losslessc;
|
||||
losslessc->pub.start_pass = start_pass_lossless;
|
||||
}
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
15
jcmainct.c
15
jcmainct.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -81,20 +83,20 @@ process_data_simple_main(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
|
||||
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)
|
||||
{
|
||||
my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
|
||||
JDIMENSION data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
if (main_ptr->rowgroup_ctr < DCTSIZE)
|
||||
if (main_ptr->rowgroup_ctr < data_unit)
|
||||
(*cinfo->prep->_pre_process_data) (cinfo, input_buf, in_row_ctr,
|
||||
in_rows_avail, main_ptr->buffer,
|
||||
&main_ptr->rowgroup_ctr,
|
||||
(JDIMENSION)DCTSIZE);
|
||||
&main_ptr->rowgroup_ctr, data_unit);
|
||||
|
||||
/* If we don't have a full iMCU row buffered, return to application for
|
||||
* more data. Note that preprocessor will always pad to fill the iMCU row
|
||||
* at the bottom of the image.
|
||||
*/
|
||||
if (main_ptr->rowgroup_ctr != DCTSIZE)
|
||||
if (main_ptr->rowgroup_ctr != data_unit)
|
||||
return;
|
||||
|
||||
/* Send the completed row to the compressor */
|
||||
@@ -134,6 +136,7 @@ _jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
my_main_ptr main_ptr;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
@@ -159,8 +162,8 @@ _jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
compptr->width_in_blocks * DCTSIZE,
|
||||
(JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
|
||||
compptr->width_in_blocks * data_unit,
|
||||
(JDIMENSION)(compptr->v_samp_factor * data_unit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
jcmarker.c
32
jcmarker.c
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2003-2010 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -497,25 +499,26 @@ 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;
|
||||
|
||||
/* 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);
|
||||
if (!cinfo->master->lossless) {
|
||||
/* Emit DQT for each quantization table.
|
||||
* Note that emit_dqt() suppresses any duplicate tables.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
|
||||
}
|
||||
/* now prec is nonzero iff there are any 16-bit quant tables. */
|
||||
}
|
||||
/* now prec is nonzero iff there are any 16-bit quant tables. */
|
||||
|
||||
/* Check for a non-baseline specification.
|
||||
* Note we assume that Huffman table numbers won't be changed later.
|
||||
*/
|
||||
if (cinfo->arith_code || cinfo->progressive_mode ||
|
||||
cinfo->data_precision != 8) {
|
||||
cinfo->master->lossless || cinfo->data_precision != 8) {
|
||||
is_baseline = FALSE;
|
||||
} else {
|
||||
is_baseline = TRUE;
|
||||
@@ -540,6 +543,8 @@ write_frame_header(j_compress_ptr cinfo)
|
||||
} else {
|
||||
if (cinfo->progressive_mode)
|
||||
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
|
||||
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 */
|
||||
else
|
||||
@@ -574,10 +579,11 @@ write_scan_header(j_compress_ptr cinfo)
|
||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||
compptr = cinfo->cur_comp_info[i];
|
||||
/* DC needs no table for refinement scan */
|
||||
if (cinfo->Ss == 0 && cinfo->Ah == 0)
|
||||
if ((cinfo->Ss == 0 && cinfo->Ah == 0) || cinfo->master->lossless)
|
||||
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
|
||||
/* AC needs no table when not present */
|
||||
if (cinfo->Se)
|
||||
/* AC needs no table when not present, and lossless mode uses only DC
|
||||
tables. */
|
||||
if (cinfo->Se && !cinfo->master->lossless)
|
||||
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
168
jcmaster.c
168
jcmaster.c
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2003-2010 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -19,38 +21,7 @@
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jpegapicomp.h"
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef enum {
|
||||
main_pass, /* input data, also do first output step */
|
||||
huff_opt_pass, /* Huffman code optimization pass */
|
||||
output_pass /* data output pass */
|
||||
} c_pass_type;
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_comp_master pub; /* public fields */
|
||||
|
||||
c_pass_type pass_type; /* the type of the current pass */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
int total_passes; /* total # of passes needed */
|
||||
|
||||
int scan_number; /* current index in scan_info[] */
|
||||
|
||||
/*
|
||||
* This is here so we can add libjpeg-turbo version/build information to the
|
||||
* global string table without introducing a new global symbol. Adding this
|
||||
* information to the global string table allows one to examine a binary
|
||||
* object and determine which version of libjpeg-turbo it was built from or
|
||||
* linked against.
|
||||
*/
|
||||
const char *jpeg_version;
|
||||
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master *my_master_ptr;
|
||||
#include "jcmaster.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -68,11 +39,13 @@ GLOBAL(void)
|
||||
jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
|
||||
/* Do computations that are needed before master selection phase */
|
||||
{
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->jpeg_width = cinfo->image_width;
|
||||
cinfo->jpeg_height = cinfo->image_height;
|
||||
cinfo->min_DCT_h_scaled_size = DCTSIZE;
|
||||
cinfo->min_DCT_v_scaled_size = DCTSIZE;
|
||||
cinfo->min_DCT_h_scaled_size = data_unit;
|
||||
cinfo->min_DCT_v_scaled_size = data_unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -85,6 +58,7 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
|
||||
jpeg_component_info *compptr;
|
||||
long samplesperrow;
|
||||
JDIMENSION jd_samplesperrow;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
#if JPEG_LIB_VERSION >= 80
|
||||
@@ -140,17 +114,17 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
|
||||
compptr->component_index = ci;
|
||||
/* For compression, we never do DCT scaling. */
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE;
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit;
|
||||
#else
|
||||
compptr->DCT_scaled_size = DCTSIZE;
|
||||
compptr->DCT_scaled_size = data_unit;
|
||||
#endif
|
||||
/* Size in DCT blocks */
|
||||
/* Size in data units */
|
||||
compptr->width_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
|
||||
(long)(cinfo->max_h_samp_factor * DCTSIZE));
|
||||
(long)(cinfo->max_h_samp_factor * data_unit));
|
||||
compptr->height_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
|
||||
(long)(cinfo->max_v_samp_factor * DCTSIZE));
|
||||
(long)(cinfo->max_v_samp_factor * data_unit));
|
||||
/* Size in samples */
|
||||
compptr->downsampled_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
|
||||
@@ -163,15 +137,19 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
|
||||
}
|
||||
|
||||
/* 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->_jpeg_height,
|
||||
(long)(cinfo->max_v_samp_factor * DCTSIZE));
|
||||
(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
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SCAN_SCRIPT
|
||||
|
||||
LOCAL(void)
|
||||
validate_script(j_compress_ptr cinfo)
|
||||
@@ -192,13 +170,29 @@ validate_script(j_compress_ptr cinfo)
|
||||
if (cinfo->num_scans <= 0)
|
||||
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
|
||||
|
||||
#ifndef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (cinfo->num_scans > 1)
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
|
||||
scanptr = cinfo->scan_info;
|
||||
if (scanptr->Ss != 0 && scanptr->Se == 0) {
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
cinfo->master->lossless = TRUE;
|
||||
cinfo->progressive_mode = FALSE;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
component_sent[ci] = FALSE;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
}
|
||||
/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
|
||||
* for progressive JPEG, no scan can have this.
|
||||
*/
|
||||
scanptr = cinfo->scan_info;
|
||||
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
|
||||
else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
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++)
|
||||
@@ -207,7 +201,7 @@ validate_script(j_compress_ptr cinfo)
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
cinfo->progressive_mode = FALSE;
|
||||
cinfo->progressive_mode = cinfo->master->lossless = FALSE;
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
component_sent[ci] = FALSE;
|
||||
}
|
||||
@@ -270,9 +264,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];
|
||||
@@ -304,7 +314,7 @@ validate_script(j_compress_ptr cinfo)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* C_MULTISCAN_FILES_SUPPORTED */
|
||||
#endif /* NEED_SCAN_SCRIPT */
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
@@ -313,7 +323,7 @@ select_scan_parameters(j_compress_ptr cinfo)
|
||||
{
|
||||
int ci;
|
||||
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
#ifdef NEED_SCAN_SCRIPT
|
||||
if (cinfo->scan_info != NULL) {
|
||||
/* Prepare for current scan --- the script is already validated */
|
||||
my_master_ptr master = (my_master_ptr)cinfo->master;
|
||||
@@ -339,10 +349,12 @@ select_scan_parameters(j_compress_ptr cinfo)
|
||||
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||
}
|
||||
cinfo->Ss = 0;
|
||||
cinfo->Se = DCTSIZE2 - 1;
|
||||
cinfo->Ah = 0;
|
||||
cinfo->Al = 0;
|
||||
if (!cinfo->master->lossless) {
|
||||
cinfo->Ss = 0;
|
||||
cinfo->Se = DCTSIZE2 - 1;
|
||||
cinfo->Ah = 0;
|
||||
cinfo->Al = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +366,7 @@ per_scan_setup(j_compress_ptr cinfo)
|
||||
{
|
||||
int ci, mcublks, tmp;
|
||||
jpeg_component_info *compptr;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
|
||||
@@ -368,7 +381,7 @@ per_scan_setup(j_compress_ptr cinfo)
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_blocks = 1;
|
||||
compptr->MCU_sample_width = DCTSIZE;
|
||||
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.
|
||||
@@ -391,10 +404,10 @@ per_scan_setup(j_compress_ptr cinfo)
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->_jpeg_width,
|
||||
(long)(cinfo->max_h_samp_factor * DCTSIZE));
|
||||
(long)(cinfo->max_h_samp_factor * data_unit));
|
||||
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->_jpeg_height,
|
||||
(long)(cinfo->max_v_samp_factor * DCTSIZE));
|
||||
(long)(cinfo->max_v_samp_factor * data_unit));
|
||||
|
||||
cinfo->blocks_in_MCU = 0;
|
||||
|
||||
@@ -404,7 +417,7 @@ per_scan_setup(j_compress_ptr cinfo)
|
||||
compptr->MCU_width = compptr->h_samp_factor;
|
||||
compptr->MCU_height = compptr->v_samp_factor;
|
||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
|
||||
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_blocks % compptr->MCU_width);
|
||||
if (tmp == 0) tmp = compptr->MCU_width;
|
||||
@@ -476,7 +489,8 @@ 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->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
|
||||
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;
|
||||
@@ -585,22 +599,15 @@ 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;
|
||||
|
||||
/* Validate parameters, determine derived values */
|
||||
initial_setup(cinfo, transcode_only);
|
||||
|
||||
if (cinfo->scan_info != NULL) {
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
#ifdef NEED_SCAN_SCRIPT
|
||||
validate_script(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
@@ -610,9 +617,30 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
|
||||
cinfo->num_scans = 1;
|
||||
}
|
||||
|
||||
if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */
|
||||
/* 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, transcode_only);
|
||||
|
||||
if (cinfo->master->lossless || /* TEMPORARY HACK ??? */
|
||||
(cinfo->progressive_mode && !cinfo->arith_code))
|
||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
||||
progressive mode */
|
||||
progressive mode or lossless mode */
|
||||
if (cinfo->data_precision == 12)
|
||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit
|
||||
data precision */
|
||||
|
||||
43
jcmaster.h
Normal file
43
jcmaster.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* jcmaster.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2016, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* 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[] */
|
||||
|
||||
/*
|
||||
* This is here so we can add libjpeg-turbo version/build information to the
|
||||
* global string table without introducing a new global symbol. Adding this
|
||||
* information to the global string table allows one to examine a binary
|
||||
* object and determine which version of libjpeg-turbo it was built from or
|
||||
* linked against.
|
||||
*/
|
||||
const char *jpeg_version;
|
||||
|
||||
} my_comp_master;
|
||||
|
||||
typedef my_comp_master *my_master_ptr;
|
||||
47
jcparam.c
47
jcparam.c
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2003-2008 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2018, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -295,7 +297,10 @@ jpeg_default_colorspace(j_compress_ptr cinfo)
|
||||
case JCS_EXT_BGRA:
|
||||
case JCS_EXT_ABGR:
|
||||
case JCS_EXT_ARGB:
|
||||
jpeg_set_colorspace(cinfo, JCS_YCbCr);
|
||||
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);
|
||||
@@ -474,6 +479,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. */
|
||||
@@ -538,3 +548,38 @@ jpeg_simple_progression(j_compress_ptr cinfo)
|
||||
}
|
||||
|
||||
#endif /* C_PROGRESSIVE_SUPPORTED */
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Enable lossless mode.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_enable_lossless(j_compress_ptr cinfo, int predictor_selection_value,
|
||||
int point_transform)
|
||||
{
|
||||
/* Safety check to ensure start_compress not called yet. */
|
||||
if (cinfo->global_state != CSTATE_START)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
cinfo->master->lossless = TRUE;
|
||||
cinfo->Ss = predictor_selection_value;
|
||||
cinfo->Se = 0;
|
||||
cinfo->Ah = 0;
|
||||
cinfo->Al = point_transform;
|
||||
|
||||
/* 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->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 */
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander.
|
||||
* Copyright (C) 2016, 2018, Matthieu Darbois.
|
||||
@@ -24,7 +26,7 @@
|
||||
#ifdef WITH_SIMD
|
||||
#include "jsimd.h"
|
||||
#else
|
||||
#include "jchuff.h"
|
||||
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
14
jcprepct.c
14
jcprepct.c
@@ -1,8 +1,10 @@
|
||||
/*
|
||||
* jcprepct.c
|
||||
*
|
||||
* This file is part of the Independent JPEG Group's software:
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -138,6 +140,7 @@ pre_process_data(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
|
||||
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) {
|
||||
@@ -175,7 +178,8 @@ pre_process_data(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
|
||||
if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) {
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE,
|
||||
expand_bottom_edge(output_buf[ci],
|
||||
compptr->width_in_blocks * data_unit,
|
||||
(int)(*out_row_group_ctr * compptr->v_samp_factor),
|
||||
(int)(out_row_groups_avail * compptr->v_samp_factor));
|
||||
}
|
||||
@@ -269,6 +273,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.
|
||||
@@ -286,7 +291,7 @@ create_context_buffer(j_compress_ptr cinfo)
|
||||
*/
|
||||
true_buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
|
||||
(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 */
|
||||
@@ -315,6 +320,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 (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
@@ -347,7 +353,7 @@ _jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer)
|
||||
ci++, compptr++) {
|
||||
prep->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
|
||||
(JDIMENSION)(((long)compptr->width_in_blocks * data_unit *
|
||||
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||
(JDIMENSION)cinfo->max_v_samp_factor);
|
||||
}
|
||||
|
||||
21
jcsample.c
21
jcsample.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
* Copyright (C) 2014, MIPS Technologies, Inc., California.
|
||||
@@ -150,7 +152,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_blocks * DCTSIZE;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
_JSAMPROW inptr, outptr;
|
||||
JLONG outvalue;
|
||||
|
||||
@@ -195,12 +198,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_blocks * DCTSIZE);
|
||||
compptr->width_in_blocks * data_unit);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +227,8 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
int outrow;
|
||||
JDIMENSION outcol;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * data_unit;
|
||||
register _JSAMPROW inptr, outptr;
|
||||
register int bias;
|
||||
|
||||
@@ -258,7 +264,8 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
int inrow, outrow;
|
||||
JDIMENSION outcol;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||
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;
|
||||
|
||||
@@ -300,7 +307,8 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
int inrow, outrow;
|
||||
JDIMENSION colctr;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||
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;
|
||||
JLONG membersum, neighsum, memberscale, neighscale;
|
||||
|
||||
@@ -388,7 +396,8 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
int outrow;
|
||||
JDIMENSION colctr;
|
||||
JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
|
||||
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;
|
||||
JLONG membersum, neighsum, memberscale, neighscale;
|
||||
int colsum, lastcolsum, nextcolsum;
|
||||
|
||||
@@ -42,6 +42,9 @@ LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo,
|
||||
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 */
|
||||
@@ -72,6 +75,9 @@ jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
|
||||
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);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2016, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -164,7 +166,10 @@ default_decompress_parms(j_decompress_ptr cinfo)
|
||||
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||
else {
|
||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||
if (cinfo->master->lossless)
|
||||
cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */
|
||||
else
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||
}
|
||||
}
|
||||
/* Always guess RGB is proper output colorspace. */
|
||||
|
||||
@@ -175,6 +175,9 @@ _jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if ((cinfo->global_state != DSTATE_SCANNING &&
|
||||
cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
@@ -443,6 +446,9 @@ _jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
/* Two-pass color quantization is not supported. */
|
||||
if (cinfo->quantize_colors && cinfo->two_pass_quantize)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
@@ -623,6 +629,9 @@ _jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data,
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
|
||||
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) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* file.
|
||||
*
|
||||
* This file contains the coefficient buffer controller for decompression.
|
||||
* This controller is the top level of the JPEG decompressor proper.
|
||||
* This controller is the top level of the lossy JPEG decompressor proper.
|
||||
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
|
||||
*
|
||||
* In buffered-image mode, this controller is the interface between
|
||||
|
||||
@@ -884,6 +884,15 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prevent lossy color conversion in lossless mode */
|
||||
if (cinfo->master->lossless) {
|
||||
if ((cinfo->out_color_space == JCS_GRAYSCALE &&
|
||||
cinfo->jpeg_color_space != JCS_GRAYSCALE) ||
|
||||
(cinfo->out_color_space != JCS_GRAYSCALE &&
|
||||
cconvert->pub._color_convert != null_convert))
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
|
||||
if (cinfo->quantize_colors)
|
||||
cinfo->output_components = 1; /* single colormapped output component */
|
||||
else
|
||||
|
||||
403
jddiffct.c
Normal file
403
jddiffct.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* jddiffct.c
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains the [un]difference buffer controller for decompression.
|
||||
* This controller is the top level of the lossless JPEG decompressor proper.
|
||||
* The difference buffer lies between the entropy decoding and
|
||||
* prediction/undifferencing steps. The undifference buffer lies between the
|
||||
* prediction/undifferencing and scaling steps.
|
||||
*
|
||||
* In buffered-image mode, this controller is the interface between
|
||||
* input-oriented processing and output-oriented processing.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h" /* Private declarations for lossless codec */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
/* 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 MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||
|
||||
JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */
|
||||
JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* In multi-pass modes, we need a virtual sample array for each component. */
|
||||
jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
|
||||
#endif
|
||||
} my_diff_controller;
|
||||
|
||||
typedef my_diff_controller *my_diff_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF(int) decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf);
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
METHODDEF(int) output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf);
|
||||
#endif
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
start_iMCU_row(j_decompress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||
{
|
||||
my_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.
|
||||
* But at the bottom of the image, process only what's left.
|
||||
*/
|
||||
if (cinfo->comps_in_scan > 1) {
|
||||
diff->MCU_rows_per_iMCU_row = 1;
|
||||
} else {
|
||||
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
|
||||
diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||
else
|
||||
diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||
}
|
||||
|
||||
diff->MCU_ctr = 0;
|
||||
diff->MCU_vert_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_input_pass(j_decompress_ptr cinfo)
|
||||
{
|
||||
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 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);
|
||||
|
||||
/* Initialize restart counter */
|
||||
diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
|
||||
|
||||
cinfo->input_iMCU_row = 0;
|
||||
start_iMCU_row(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for a restart marker & resynchronize decoder, undifferencer.
|
||||
* Returns FALSE if must suspend.
|
||||
*/
|
||||
|
||||
METHODDEF(boolean)
|
||||
process_restart(j_decompress_ptr cinfo)
|
||||
{
|
||||
my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct;
|
||||
|
||||
if (!(*cinfo->entropy->process_restart) (cinfo))
|
||||
return FALSE;
|
||||
|
||||
(*losslessd->predict_process_restart) (cinfo);
|
||||
|
||||
/* Reset restart counter */
|
||||
diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an output processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_output_pass(j_decompress_ptr cinfo)
|
||||
{
|
||||
cinfo->output_iMCU_row = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decompress and return some data in the supplied buffer.
|
||||
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||
* Input and output must run in lockstep since we have only a one-MCU buffer.
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*
|
||||
* NB: output_buf contains a plane for each component in image,
|
||||
* which we index according to the component's SOF position.
|
||||
*/
|
||||
|
||||
METHODDEF(int)
|
||||
decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf)
|
||||
{
|
||||
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 ci, compi, row, prev_row;
|
||||
unsigned int yoffset;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Loop to process as much as one whole iMCU row */
|
||||
for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
|
||||
yoffset++) {
|
||||
|
||||
/* Process restart marker if needed; may have to suspend */
|
||||
if (cinfo->restart_interval) {
|
||||
if (diff->restart_rows_to_go == 0)
|
||||
if (!process_restart(cinfo))
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
|
||||
MCU_col_num = diff->MCU_ctr;
|
||||
/* Try to fetch an MCU row (or remaining portion of suspended MCU row). */
|
||||
MCU_count =
|
||||
(*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;
|
||||
diff->MCU_ctr += MCU_count;
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
diff->restart_rows_to_go--;
|
||||
|
||||
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||
diff->MCU_ctr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 (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++) {
|
||||
(*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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Completed the iMCU row, advance counters for next one.
|
||||
*
|
||||
* NB: output_data will increment output_iMCU_row.
|
||||
* This counter is not needed for the single-pass case
|
||||
* or the input side of the multi-pass case.
|
||||
*/
|
||||
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
|
||||
start_iMCU_row(cinfo);
|
||||
return JPEG_ROW_COMPLETED;
|
||||
}
|
||||
/* Completed the scan */
|
||||
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dummy consume-input routine for single-pass operation.
|
||||
*/
|
||||
|
||||
METHODDEF(int)
|
||||
dummy_consume_data(j_decompress_ptr cinfo)
|
||||
{
|
||||
return JPEG_SUSPENDED; /* Always indicate nothing was done */
|
||||
}
|
||||
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
/*
|
||||
* Consume input data and store it in the full-image sample buffer.
|
||||
* We read as much as one fully interleaved MCU row ("iMCU" row) per call,
|
||||
* ie, v_samp_factor rows for each component in the scan.
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*/
|
||||
|
||||
METHODDEF(int)
|
||||
consume_data(j_decompress_ptr cinfo)
|
||||
{
|
||||
my_diff_ptr diff = (my_diff_ptr)cinfo->coef;
|
||||
int ci, compi;
|
||||
_JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Align the virtual buffers for the components used in this scan. */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
compi = compptr->component_index;
|
||||
buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr)cinfo, diff->whole_image[compi],
|
||||
cinfo->input_iMCU_row * compptr->v_samp_factor,
|
||||
(JDIMENSION)compptr->v_samp_factor, TRUE);
|
||||
}
|
||||
|
||||
return decompress_data(cinfo, buffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* NB: output_buf contains a plane for each component in image.
|
||||
*/
|
||||
|
||||
METHODDEF(int)
|
||||
output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf)
|
||||
{
|
||||
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;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Force some input to be done if we are getting ahead of the input. */
|
||||
while (cinfo->input_scan_number < cinfo->output_scan_number ||
|
||||
(cinfo->input_scan_number == cinfo->output_scan_number &&
|
||||
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
|
||||
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
|
||||
/* OK, output from the virtual arrays. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Align the virtual buffer for this component. */
|
||||
buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr)cinfo, diff->whole_image[ci],
|
||||
cinfo->output_iMCU_row * compptr->v_samp_factor,
|
||||
(JDIMENSION)compptr->v_samp_factor, FALSE);
|
||||
|
||||
if (cinfo->output_iMCU_row < last_iMCU_row)
|
||||
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_blocks % compptr->v_samp_factor);
|
||||
if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
|
||||
}
|
||||
|
||||
for (row = 0; row < samp_rows; row++) {
|
||||
memcpy(output_buf[ci][row], buffer[row],
|
||||
compptr->width_in_blocks * sizeof(_JSAMPLE));
|
||||
}
|
||||
}
|
||||
|
||||
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||
return JPEG_ROW_COMPLETED;
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize difference buffer controller.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
_jinit_d_diff_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
my_diff_ptr diff;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
diff = (my_diff_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
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] =
|
||||
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) {
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* Allocate a full-image virtual array for each component. */
|
||||
int access_rows;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
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_blocks,
|
||||
(long)compptr->h_samp_factor),
|
||||
(JDIMENSION)jround_up((long)compptr->height_in_blocks,
|
||||
(long)compptr->v_samp_factor),
|
||||
(JDIMENSION)access_rows);
|
||||
}
|
||||
diff->pub.consume_data = consume_data;
|
||||
diff->pub._decompress_data = output_data;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
diff->pub.consume_data = dummy_consume_data;
|
||||
diff->pub._decompress_data = decompress_data;
|
||||
diff->whole_image[0] = NULL; /* flag for no virtual arrays */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
16
jdhuff.c
16
jdhuff.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2016, 2018-2019, 2022, D. R. Commander.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
@@ -24,7 +26,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdhuff.h" /* Declarations shared with jdphuff.c */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
#include "jpegapicomp.h"
|
||||
#include "jstdhuff.c"
|
||||
|
||||
@@ -134,7 +136,7 @@ start_pass_huff_decoder(j_decompress_ptr cinfo)
|
||||
* 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.
|
||||
* Note this is also used by jdphuff.c and jdlhuff.c.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
@@ -245,14 +247,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..15.
|
||||
* (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 > 15)
|
||||
if (sym < 0 || sym > (cinfo->master->lossless ? 16 : 15))
|
||||
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +262,7 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno,
|
||||
|
||||
|
||||
/*
|
||||
* Out-of-line code for bit fetching (shared with jdphuff.c).
|
||||
* 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.
|
||||
|
||||
7
jdhuff.h
7
jdhuff.h
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
@@ -10,8 +12,9 @@
|
||||
* file.
|
||||
*
|
||||
* This file contains declarations for Huffman entropy decoding routines
|
||||
* that are shared between the sequential decoder (jdhuff.c) and the
|
||||
* progressive decoder (jdphuff.c). No other modules need to see these.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jconfigint.h"
|
||||
|
||||
54
jdinput.c
54
jdinput.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
@@ -11,8 +13,9 @@
|
||||
*
|
||||
* This file contains input control logic for the JPEG decompressor.
|
||||
* These routines are concerned with controlling the decompressor's input
|
||||
* processing (marker reading and coefficient decoding). The actual input
|
||||
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
|
||||
* processing (marker reading and coefficient/difference decoding).
|
||||
* The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c,
|
||||
* and jdlhuff.c.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
@@ -46,6 +49,7 @@ 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 ||
|
||||
@@ -78,36 +82,36 @@ initial_setup(j_decompress_ptr cinfo)
|
||||
}
|
||||
|
||||
#if JPEG_LIB_VERSION >= 80
|
||||
cinfo->block_size = DCTSIZE;
|
||||
cinfo->block_size = data_unit;
|
||||
cinfo->natural_order = jpeg_natural_order;
|
||||
cinfo->lim_Se = DCTSIZE2 - 1;
|
||||
#endif
|
||||
|
||||
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
|
||||
* 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.
|
||||
*/
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = DCTSIZE;
|
||||
cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = data_unit;
|
||||
#else
|
||||
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||
cinfo->min_DCT_scaled_size = data_unit;
|
||||
#endif
|
||||
|
||||
/* Compute dimensions of components */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE;
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit;
|
||||
#else
|
||||
compptr->DCT_scaled_size = DCTSIZE;
|
||||
compptr->DCT_scaled_size = data_unit;
|
||||
#endif
|
||||
/* Size in DCT blocks */
|
||||
/* Size in data units */
|
||||
compptr->width_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
|
||||
(long)(cinfo->max_h_samp_factor * DCTSIZE));
|
||||
(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 * DCTSIZE));
|
||||
(long)(cinfo->max_v_samp_factor * data_unit));
|
||||
/* Set the first and last MCU columns to decompress from multi-scan images.
|
||||
* By default, decompress all of the MCU columns.
|
||||
*/
|
||||
@@ -133,7 +137,7 @@ 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 * DCTSIZE));
|
||||
(long)(cinfo->max_v_samp_factor * data_unit));
|
||||
|
||||
/* Decide whether file contains multiple scans */
|
||||
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
||||
@@ -150,6 +154,7 @@ 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) {
|
||||
|
||||
@@ -160,14 +165,14 @@ per_scan_setup(j_decompress_ptr cinfo)
|
||||
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 */
|
||||
/* For noninterleaved scan, always one data unit per MCU */
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_blocks = 1;
|
||||
compptr->MCU_sample_width = compptr->_DCT_scaled_size;
|
||||
compptr->last_col_width = 1;
|
||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||
* as the number of block rows present in the last iMCU row.
|
||||
* as the number of data unit rows present in the last iMCU row.
|
||||
*/
|
||||
tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||
@@ -187,22 +192,22 @@ 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 * DCTSIZE));
|
||||
(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 * DCTSIZE));
|
||||
(long)(cinfo->max_v_samp_factor * data_unit));
|
||||
|
||||
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 */
|
||||
/* 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_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width *
|
||||
compptr->_DCT_scaled_size;
|
||||
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||
/* Figure number of non-dummy data units in last MCU column & row */
|
||||
tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
|
||||
if (tmp == 0) tmp = compptr->MCU_width;
|
||||
compptr->last_col_width = tmp;
|
||||
@@ -281,7 +286,8 @@ METHODDEF(void)
|
||||
start_input_pass(j_decompress_ptr cinfo)
|
||||
{
|
||||
per_scan_setup(cinfo);
|
||||
latch_quant_tables(cinfo);
|
||||
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;
|
||||
@@ -290,8 +296,8 @@ start_input_pass(j_decompress_ptr cinfo)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
@@ -307,8 +313,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)
|
||||
|
||||
303
jdlhuff.c
Normal file
303
jdlhuff.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* jdlhuff.c
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines for lossless 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 "jlossls.h" /* Private declarations for lossless codec */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
typedef struct {
|
||||
int ci, yoffset, MCU_width;
|
||||
} lhd_output_ptr_info;
|
||||
|
||||
/*
|
||||
* Expanded entropy decoder object for Huffman decoding in lossless mode.
|
||||
*/
|
||||
|
||||
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 */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
d_derived_tbl *derived_tbls[NUM_HUFF_TBLS];
|
||||
|
||||
/* 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_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_BLOCKS_IN_MCU];
|
||||
|
||||
/* Number of output pointers in use for the current MCU. This is the sum
|
||||
* of all Vi in the MCU.
|
||||
*/
|
||||
int num_output_ptrs;
|
||||
|
||||
/* Information used for positioning the output pointers within the output
|
||||
* difference rows.
|
||||
*/
|
||||
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_BLOCKS_IN_MCU];
|
||||
|
||||
} lhuff_entropy_decoder;
|
||||
|
||||
typedef lhuff_entropy_decoder *lhuff_entropy_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_lhuff_decoder(j_decompress_ptr cinfo)
|
||||
{
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
|
||||
int ci, dctbl, sampn, ptrn, yoffset, xoffset;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
/* Make sure requested tables are present */
|
||||
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
|
||||
cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
|
||||
/* 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->derived_tbls[dctbl]);
|
||||
}
|
||||
|
||||
/* Precalculate decoding info for each sample in an MCU of this scan */
|
||||
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++) {
|
||||
/* Precalculate the setup info for each output pointer */
|
||||
entropy->output_ptr_info[ptrn].ci = ci;
|
||||
entropy->output_ptr_info[ptrn].yoffset = yoffset;
|
||||
entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width;
|
||||
for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
|
||||
/* Precalculate the output pointer index for each sample */
|
||||
entropy->output_ptr_index[sampn] = ptrn;
|
||||
/* Precalculate which table to use for each sample */
|
||||
entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
|
||||
}
|
||||
}
|
||||
}
|
||||
entropy->num_output_ptrs = ptrn;
|
||||
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Figure F.12: extend sign bit.
|
||||
* On some machines, a shift and add will be faster than a table lookup.
|
||||
*/
|
||||
|
||||
#define AVOID_TABLES
|
||||
#ifdef AVOID_TABLES
|
||||
|
||||
#define NEG_1 ((unsigned int)-1)
|
||||
#define HUFF_EXTEND(x, s) \
|
||||
((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1)))
|
||||
|
||||
#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)
|
||||
{
|
||||
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 */
|
||||
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;
|
||||
|
||||
/* 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 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
|
||||
* diff_buf.
|
||||
*
|
||||
* 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.)
|
||||
*/
|
||||
|
||||
METHODDEF(JDIMENSION)
|
||||
decode_mcus(j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
|
||||
{
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct;
|
||||
lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy;
|
||||
int sampn, ci, yoffset, MCU_width, ptrn;
|
||||
JDIMENSION mcu_num;
|
||||
BITREAD_STATE_VARS;
|
||||
|
||||
/* Set output pointer locations based on MCU_col_num */
|
||||
for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) {
|
||||
ci = entropy->output_ptr_info[ptrn].ci;
|
||||
yoffset = entropy->output_ptr_info[ptrn].yoffset;
|
||||
MCU_width = entropy->output_ptr_info[ptrn].MCU_width;
|
||||
entropy->output_ptr[ptrn] =
|
||||
diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've run out of data, zero out the buffers and return.
|
||||
* By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
|
||||
*
|
||||
* NB: We should find a way to do this without interacting with the
|
||||
* undifferencer module directly.
|
||||
*/
|
||||
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));
|
||||
|
||||
(*losslessd->predict_process_restart) (cinfo);
|
||||
|
||||
} else {
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
|
||||
|
||||
/* 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->blocks_in_MCU; sampn++) {
|
||||
d_derived_tbl *dctbl = entropy->cur_tbls[sampn];
|
||||
register int s, r;
|
||||
|
||||
/* Section H.2.2: decode the sample difference */
|
||||
HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
|
||||
if (s) {
|
||||
if (s == 16) /* special case: always output 32768 */
|
||||
s = 32768;
|
||||
else { /* normal case: fetch subsequent bits */
|
||||
CHECK_BIT_BUFFER(br_state, s, return mcu_num);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the sample difference */
|
||||
*entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF)s;
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
|
||||
}
|
||||
}
|
||||
|
||||
return nMCU;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for lossless mode Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jinit_lhuff_decoder(j_decompress_ptr cinfo)
|
||||
{
|
||||
lhuff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (lhuff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
sizeof(lhuff_entropy_decoder));
|
||||
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++) {
|
||||
entropy->derived_tbls[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
287
jdlossls.c
Normal file
287
jdlossls.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* jdlossls.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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains prediction, sample undifferencing, point transform, and
|
||||
* sample scaling routines for the lossless JPEG decompressor.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jlossls.h"
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
|
||||
/**************** Sample undifferencing (reconstruction) *****************/
|
||||
|
||||
/*
|
||||
* 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 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 = *prev_row++; \
|
||||
Ra = (*diff_buf++ + PREDICTOR2) & 0xFFFF; \
|
||||
*undiff_buf++ = Ra; \
|
||||
\
|
||||
while (--width) { \
|
||||
Rc = Rb; \
|
||||
Rb = *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)
|
||||
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);
|
||||
(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 upscaling by 2^Pt ************************/
|
||||
|
||||
METHODDEF(void)
|
||||
simple_upscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
while (width--)
|
||||
*output_buf++ = (_JSAMPLE)(*diff_buf++ << cinfo->Al);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
noscale(j_decompress_ptr cinfo,
|
||||
JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width)
|
||||
{
|
||||
while (width--)
|
||||
*output_buf++ = (_JSAMPLE)(*diff_buf++);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
start_pass_lossless(j_decompress_ptr cinfo)
|
||||
{
|
||||
lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct;
|
||||
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 <= (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;
|
||||
|
||||
/* Set scaler function based on Pt */
|
||||
if (cinfo->Al)
|
||||
losslessd->scaler_scale = simple_upscale;
|
||||
else
|
||||
losslessd->scaler_scale = noscale;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the lossless decompressor.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
_jinit_lossless_decompressor(j_decompress_ptr cinfo)
|
||||
{
|
||||
lossless_decomp_ptr losslessd;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
losslessd = (lossless_decomp_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
|
||||
sizeof(jpeg_lossless_decompressor));
|
||||
cinfo->idct = (struct jpeg_inverse_dct *)losslessd;
|
||||
losslessd->pub.start_pass = start_pass_lossless;
|
||||
}
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
27
jdmainct.c
27
jdmainct.c
@@ -22,10 +22,11 @@
|
||||
|
||||
/*
|
||||
* 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 * DCT_scaled_size / min_DCT_scaled_size)
|
||||
@@ -37,20 +38,20 @@
|
||||
* row group (times any additional scale factor that the upsampler is
|
||||
* applying).
|
||||
*
|
||||
* The coefficient controller will deliver data to us one iMCU row at a time;
|
||||
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
|
||||
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
|
||||
* to one row of MCUs when the image is fully interleaved.) Note that the
|
||||
* number of sample rows varies across components, but the number of row
|
||||
* groups does not. Some garbage sample rows may be included in the last iMCU
|
||||
* row at the bottom of the image.
|
||||
* 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
|
||||
|
||||
26
jdmarker.c
26
jdmarker.c
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* 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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2012, 2015, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -237,7 +239,8 @@ get_soi(j_decompress_ptr cinfo)
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
|
||||
get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_lossless,
|
||||
boolean is_arith)
|
||||
/* Process a SOFn marker */
|
||||
{
|
||||
JLONG length;
|
||||
@@ -246,6 +249,7 @@ get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
|
||||
INPUT_VARS(cinfo);
|
||||
|
||||
cinfo->progressive_mode = is_prog;
|
||||
cinfo->master->lossless = is_lossless;
|
||||
cinfo->arith_code = is_arith;
|
||||
|
||||
INPUT_2BYTES(cinfo, length, return FALSE);
|
||||
@@ -990,32 +994,40 @@ read_markers(j_decompress_ptr cinfo)
|
||||
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
if (!get_sof(cinfo, FALSE, FALSE))
|
||||
if (!get_sof(cinfo, FALSE, FALSE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
if (!get_sof(cinfo, TRUE, FALSE))
|
||||
if (!get_sof(cinfo, TRUE, FALSE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
if (!get_sof(cinfo, FALSE, TRUE, FALSE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
if (!get_sof(cinfo, FALSE, TRUE))
|
||||
if (!get_sof(cinfo, FALSE, FALSE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
if (!get_sof(cinfo, TRUE, TRUE))
|
||||
if (!get_sof(cinfo, TRUE, FALSE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
if (!get_sof(cinfo, FALSE, TRUE, TRUE))
|
||||
return JPEG_SUSPENDED;
|
||||
break;
|
||||
|
||||
/* Currently unsupported SOFn types */
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
case M_SOF5: /* Differential sequential, Huffman */
|
||||
case M_SOF6: /* Differential progressive, Huffman */
|
||||
case M_SOF7: /* Differential lossless, Huffman */
|
||||
case M_JPG: /* Reserved for JPEG extensions */
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
case M_SOF13: /* Differential sequential, arithmetic */
|
||||
case M_SOF14: /* Differential progressive, arithmetic */
|
||||
case M_SOF15: /* Differential lossless, arithmetic */
|
||||
|
||||
510
jdmaster.c
510
jdmaster.c
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2002-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2016, 2019, 2022, D. R. Commander.
|
||||
* Copyright (C) 2013, Linaro Limited.
|
||||
@@ -97,154 +99,154 @@ jpeg_core_output_dimensions(j_decompress_ptr cinfo)
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
|
||||
/* Provide 1/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 1;
|
||||
cinfo->_min_DCT_v_scaled_size = 1;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
|
||||
/* Provide 2/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 2;
|
||||
cinfo->_min_DCT_v_scaled_size = 2;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
|
||||
/* Provide 3/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 3;
|
||||
cinfo->_min_DCT_v_scaled_size = 3;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
|
||||
/* Provide 4/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 4;
|
||||
cinfo->_min_DCT_v_scaled_size = 4;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
|
||||
/* Provide 5/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 5;
|
||||
cinfo->_min_DCT_v_scaled_size = 5;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
|
||||
/* Provide 6/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 6;
|
||||
cinfo->_min_DCT_v_scaled_size = 6;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
|
||||
/* Provide 7/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 7;
|
||||
cinfo->_min_DCT_v_scaled_size = 7;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
|
||||
/* Provide 8/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 8;
|
||||
cinfo->_min_DCT_v_scaled_size = 8;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
|
||||
/* Provide 9/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 9;
|
||||
cinfo->_min_DCT_v_scaled_size = 9;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
|
||||
/* Provide 10/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 10;
|
||||
cinfo->_min_DCT_v_scaled_size = 10;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
|
||||
/* Provide 11/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 11;
|
||||
cinfo->_min_DCT_v_scaled_size = 11;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
|
||||
/* Provide 12/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 12;
|
||||
cinfo->_min_DCT_v_scaled_size = 12;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
|
||||
/* Provide 13/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 13;
|
||||
cinfo->_min_DCT_v_scaled_size = 13;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
|
||||
/* Provide 14/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 14;
|
||||
cinfo->_min_DCT_v_scaled_size = 14;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
|
||||
/* Provide 15/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 15;
|
||||
cinfo->_min_DCT_v_scaled_size = 15;
|
||||
} else {
|
||||
/* Provide 16/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 16;
|
||||
cinfo->_min_DCT_v_scaled_size = 16;
|
||||
if (!cinfo->master->lossless) {
|
||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
|
||||
/* Provide 1/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 1;
|
||||
cinfo->_min_DCT_v_scaled_size = 1;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
|
||||
/* Provide 2/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 2;
|
||||
cinfo->_min_DCT_v_scaled_size = 2;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
|
||||
/* Provide 3/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 3;
|
||||
cinfo->_min_DCT_v_scaled_size = 3;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
|
||||
/* Provide 4/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 4;
|
||||
cinfo->_min_DCT_v_scaled_size = 4;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
|
||||
/* Provide 5/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 5;
|
||||
cinfo->_min_DCT_v_scaled_size = 5;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
|
||||
/* Provide 6/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 6;
|
||||
cinfo->_min_DCT_v_scaled_size = 6;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
|
||||
/* Provide 7/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 7;
|
||||
cinfo->_min_DCT_v_scaled_size = 7;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
|
||||
/* Provide 8/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 8;
|
||||
cinfo->_min_DCT_v_scaled_size = 8;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
|
||||
/* Provide 9/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 9;
|
||||
cinfo->_min_DCT_v_scaled_size = 9;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
|
||||
/* Provide 10/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 10;
|
||||
cinfo->_min_DCT_v_scaled_size = 10;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
|
||||
/* Provide 11/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 11;
|
||||
cinfo->_min_DCT_v_scaled_size = 11;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
|
||||
/* Provide 12/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 12;
|
||||
cinfo->_min_DCT_v_scaled_size = 12;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
|
||||
/* Provide 13/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 13;
|
||||
cinfo->_min_DCT_v_scaled_size = 13;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
|
||||
/* Provide 14/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 14;
|
||||
cinfo->_min_DCT_v_scaled_size = 14;
|
||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
|
||||
/* Provide 15/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 15;
|
||||
cinfo->_min_DCT_v_scaled_size = 15;
|
||||
} else {
|
||||
/* Provide 16/block_size scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
|
||||
cinfo->_min_DCT_h_scaled_size = 16;
|
||||
cinfo->_min_DCT_v_scaled_size = 16;
|
||||
}
|
||||
|
||||
/* Recompute dimensions of components */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size;
|
||||
compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size;
|
||||
}
|
||||
} else
|
||||
#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,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Recompute dimensions of components */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size;
|
||||
compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size;
|
||||
}
|
||||
|
||||
#else /* !IDCT_SCALING_SUPPORTED */
|
||||
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
/* jdinput.c has already initialized DCT_scaled_size,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
*/
|
||||
|
||||
#endif /* IDCT_SCALING_SUPPORTED */
|
||||
}
|
||||
|
||||
|
||||
@@ -273,54 +275,56 @@ jpeg_calc_output_dimensions(j_decompress_ptr cinfo)
|
||||
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
|
||||
/* In selecting the actual DCT scaling for each component, we try to
|
||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||
* Note this code adapts subsampling ratios which are powers of 2.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
int ssize = cinfo->_min_DCT_scaled_size;
|
||||
while (ssize < DCTSIZE &&
|
||||
((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||
(compptr->h_samp_factor * ssize * 2) == 0) &&
|
||||
((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||
(compptr->v_samp_factor * ssize * 2) == 0)) {
|
||||
ssize = ssize * 2;
|
||||
}
|
||||
if (!cinfo->master->lossless) {
|
||||
/* In selecting the actual DCT scaling for each component, we try to
|
||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||
* Note this code adapts subsampling ratios which are powers of 2.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
int ssize = cinfo->_min_DCT_scaled_size;
|
||||
while (ssize < DCTSIZE &&
|
||||
((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||
(compptr->h_samp_factor * ssize * 2) == 0) &&
|
||||
((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||
(compptr->v_samp_factor * ssize * 2) == 0)) {
|
||||
ssize = ssize * 2;
|
||||
}
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize;
|
||||
compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize;
|
||||
#else
|
||||
compptr->DCT_scaled_size = ssize;
|
||||
compptr->DCT_scaled_size = ssize;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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 /* !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.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 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... */
|
||||
@@ -478,6 +482,17 @@ master_selection(j_decompress_ptr cinfo)
|
||||
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);
|
||||
@@ -548,71 +563,96 @@ master_selection(j_decompress_ptr cinfo)
|
||||
*/
|
||||
}
|
||||
|
||||
if (cinfo->data_precision == 12) {
|
||||
/* Post-processing: in particular, color conversion first */
|
||||
if (!cinfo->raw_data_out) {
|
||||
if (master->using_merged_upsample) {
|
||||
/* Post-processing: in particular, color conversion first */
|
||||
if (!cinfo->raw_data_out) {
|
||||
if (master->using_merged_upsample) {
|
||||
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_merged_upsampler(cinfo); /* does color conversion too */
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
j12init_color_deconverter(cinfo);
|
||||
j12init_upsampler(cinfo);
|
||||
}
|
||||
j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
}
|
||||
/* Inverse DCT */
|
||||
j12init_inverse_dct(cinfo);
|
||||
} else {
|
||||
/* Post-processing: in particular, color conversion first */
|
||||
if (!cinfo->raw_data_out) {
|
||||
if (master->using_merged_upsample) {
|
||||
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||
else
|
||||
jinit_merged_upsampler(cinfo); /* does color conversion too */
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
if (cinfo->data_precision == 12) {
|
||||
j12init_color_deconverter(cinfo);
|
||||
j12init_upsampler(cinfo);
|
||||
} else {
|
||||
jinit_color_deconverter(cinfo);
|
||||
jinit_upsampler(cinfo);
|
||||
}
|
||||
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
}
|
||||
/* Inverse DCT */
|
||||
jinit_inverse_dct(cinfo);
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
else
|
||||
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
}
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
#ifdef D_ARITH_CODING_SUPPORTED
|
||||
jinit_arith_decoder(cinfo);
|
||||
|
||||
if (cinfo->master->lossless) {
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
/* Prediction, sample undifferencing, point transform, and sample size
|
||||
* scaling
|
||||
*/
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_lossless_decompressor(cinfo);
|
||||
else
|
||||
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;
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_d_diff_controller(cinfo, use_c_buffer);
|
||||
else
|
||||
jinit_d_diff_controller(cinfo, use_c_buffer);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
/* Inverse DCT */
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_inverse_dct(cinfo);
|
||||
else
|
||||
jinit_inverse_dct(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
#ifdef D_ARITH_CODING_SUPPORTED
|
||||
jinit_arith_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_decoder(cinfo);
|
||||
} 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;
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_d_coef_controller(cinfo, use_c_buffer);
|
||||
else
|
||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||
}
|
||||
|
||||
/* Initialize principal buffer controllers. */
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
||||
if (cinfo->data_precision == 12) {
|
||||
j12init_d_coef_controller(cinfo, use_c_buffer);
|
||||
|
||||
if (!cinfo->raw_data_out)
|
||||
if (!cinfo->raw_data_out) {
|
||||
if (cinfo->data_precision == 12)
|
||||
j12init_d_main_controller(cinfo,
|
||||
FALSE /* never need full buffer here */);
|
||||
} else {
|
||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||
|
||||
if (!cinfo->raw_data_out)
|
||||
else
|
||||
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2016, 2018-2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -23,7 +25,7 @@
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
|
||||
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo);
|
||||
GLOBAL(jvirt_barray_ptr *)
|
||||
jpeg_read_coefficients(j_decompress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
|
||||
if (cinfo->global_state == DSTATE_READY) {
|
||||
/* First call: initialize active modules */
|
||||
transdecode_master_selection(cinfo);
|
||||
|
||||
13
jerror.h
13
jerror.h
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2014, 2017, 2021-2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -53,7 +55,8 @@ JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||
#endif
|
||||
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")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
@@ -69,9 +72,9 @@ 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")
|
||||
"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")
|
||||
@@ -180,7 +183,7 @@ JMESSAGE(JTRC_THUMB_PALETTE,
|
||||
JMESSAGE(JTRC_THUMB_RGB,
|
||||
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr")
|
||||
"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")
|
||||
@@ -211,6 +214,8 @@ JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_RESTART,
|
||||
"Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)")
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
|
||||
104
jlossls.h
Normal file
104
jlossls.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* jlossls.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.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This include file contains common declarations for the lossless JPEG
|
||||
* codec modules.
|
||||
*/
|
||||
|
||||
#ifndef JLOSSLS_H
|
||||
#define JLOSSLS_H
|
||||
|
||||
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jpeglib.h"
|
||||
#include "jsamplecomp.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.
|
||||
*/
|
||||
|
||||
#define PREDICTOR1 Ra
|
||||
#define PREDICTOR2 Rb
|
||||
#define PREDICTOR3 Rc
|
||||
#define PREDICTOR4 (int)((JLONG)Ra + (JLONG)Rb - (JLONG)Rc)
|
||||
#define PREDICTOR5 (int)((JLONG)Ra + RIGHT_SHIFT((JLONG)Rb - (JLONG)Rc, 1))
|
||||
#define PREDICTOR6 (int)((JLONG)Rb + RIGHT_SHIFT((JLONG)Ra - (JLONG)Rc, 1))
|
||||
#define PREDICTOR7 (int)RIGHT_SHIFT((JLONG)Ra + (JLONG)Rb, 1)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
|
||||
typedef void (*predict_difference_method_ptr) (j_compress_ptr cinfo, int ci,
|
||||
_JSAMPROW input_buf,
|
||||
_JSAMPROW prev_row,
|
||||
JDIFFROW diff_buf,
|
||||
JDIMENSION width);
|
||||
|
||||
/* Lossless compressor */
|
||||
typedef struct {
|
||||
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];
|
||||
|
||||
/* MCU rows left in the restart interval for each component */
|
||||
unsigned int restart_rows_to_go[MAX_COMPONENTS];
|
||||
|
||||
/* Sample scaling */
|
||||
void (*scaler_scale) (j_compress_ptr cinfo, _JSAMPROW input_buf,
|
||||
_JSAMPROW output_buf, JDIMENSION width);
|
||||
} jpeg_lossless_compressor;
|
||||
|
||||
typedef jpeg_lossless_compressor *lossless_comp_ptr;
|
||||
|
||||
#endif /* C_LOSSLESS_SUPPORTED */
|
||||
|
||||
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
|
||||
typedef void (*predict_undifference_method_ptr) (j_decompress_ptr cinfo,
|
||||
int comp_index,
|
||||
JDIFFROW diff_buf,
|
||||
JDIFFROW prev_row,
|
||||
JDIFFROW undiff_buf,
|
||||
JDIMENSION width);
|
||||
|
||||
/* Lossless decompressor */
|
||||
typedef struct {
|
||||
struct jpeg_inverse_dct pub; /* public fields */
|
||||
|
||||
/* Prediction, undifferencing */
|
||||
void (*predict_process_restart) (j_decompress_ptr cinfo);
|
||||
|
||||
/* It is useful to allow each component to have a separate undiff method. */
|
||||
predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS];
|
||||
|
||||
/* Sample scaling */
|
||||
void (*scaler_scale) (j_decompress_ptr cinfo, JDIFFROW diff_buf,
|
||||
_JSAMPROW output_buf, JDIMENSION width);
|
||||
} jpeg_lossless_decompressor;
|
||||
|
||||
typedef jpeg_lossless_decompressor *lossless_decomp_ptr;
|
||||
|
||||
#endif /* D_LOSSLESS_SUPPORTED */
|
||||
|
||||
#endif /* JLOSSLS_H */
|
||||
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -232,14 +234,16 @@ typedef int boolean;
|
||||
|
||||
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */
|
||||
#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 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 JPEG: the default tables
|
||||
* don't work for progressive mode. (This may get fixed, however.)
|
||||
* The exact same statements apply for progressive and lossless JPEG:
|
||||
* the default tables don't work for progressive mode or lossless mode.
|
||||
* (This may get fixed, however.)
|
||||
*/
|
||||
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
|
||||
|
||||
@@ -247,6 +251,7 @@ typedef int boolean;
|
||||
|
||||
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */
|
||||
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
|
||||
|
||||
78
jpegint.h
78
jpegint.h
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2016, 2019, 2021-2022, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
@@ -17,6 +19,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 */
|
||||
@@ -80,6 +93,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) */
|
||||
@@ -107,7 +121,9 @@ struct jpeg_c_prep_controller {
|
||||
JDIMENSION out_row_groups_avail);
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
/* Lossy mode: Coefficient buffer control
|
||||
* Lossless mode: Difference buffer control
|
||||
*/
|
||||
struct jpeg_c_coef_controller {
|
||||
void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode);
|
||||
boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
|
||||
@@ -138,9 +154,13 @@ struct jpeg_downsampler {
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
/* Lossy mode: Forward DCT (also controls coefficient quantization)
|
||||
* Lossless mode: Prediction, sample differencing, and point transform
|
||||
*/
|
||||
struct jpeg_forward_dct {
|
||||
void (*start_pass) (j_compress_ptr cinfo);
|
||||
|
||||
/* Lossy mode */
|
||||
/* perhaps this should be an array??? */
|
||||
void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
@@ -155,7 +175,14 @@ struct jpeg_forward_dct {
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
void (*start_pass) (j_compress_ptr cinfo, boolean gather_statistics);
|
||||
|
||||
/* Lossy mode */
|
||||
boolean (*encode_mcu) (j_compress_ptr cinfo, JBLOCKROW *MCU_data);
|
||||
/* Lossless mode */
|
||||
JDIMENSION (*encode_mcus) (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU);
|
||||
|
||||
void (*finish_pass) (j_compress_ptr cinfo);
|
||||
};
|
||||
|
||||
@@ -183,6 +210,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 */
|
||||
|
||||
/* Partial decompression variables */
|
||||
JDIMENSION first_iMCU_col;
|
||||
@@ -216,13 +244,25 @@ struct jpeg_d_main_controller {
|
||||
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
/* Lossy mode: Coefficient buffer control
|
||||
* Lossless mode: Difference buffer control
|
||||
*/
|
||||
struct jpeg_d_coef_controller {
|
||||
void (*start_input_pass) (j_decompress_ptr cinfo);
|
||||
int (*consume_data) (j_decompress_ptr cinfo);
|
||||
void (*start_output_pass) (j_decompress_ptr cinfo);
|
||||
int (*decompress_data) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
|
||||
int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE output_buf);
|
||||
|
||||
/* These variables keep track of the current location of the input side. */
|
||||
/* cinfo->input_iMCU_row is also used for this. */
|
||||
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||
|
||||
/* Lossy mode */
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
@@ -266,14 +306,24 @@ struct jpeg_marker_reader {
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
void (*start_pass) (j_decompress_ptr cinfo);
|
||||
|
||||
/* Lossy mode */
|
||||
boolean (*decode_mcu) (j_decompress_ptr cinfo, JBLOCKROW *MCU_data);
|
||||
/* Lossless mode */
|
||||
JDIMENSION (*decode_mcus) (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
|
||||
JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
|
||||
JDIMENSION nMCU);
|
||||
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 */
|
||||
};
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
/* Lossy mode: Inverse DCT (also performs dequantization)
|
||||
* Lossless mode: Prediction, sample undifferencing, point transform, and
|
||||
* sample size scaling
|
||||
*/
|
||||
typedef void (*inverse_DCT_method_ptr) (j_decompress_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
JCOEFPTR coef_block,
|
||||
@@ -287,6 +337,8 @@ typedef void (*inverse_DCT_12_method_ptr) (j_decompress_ptr cinfo,
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
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];
|
||||
inverse_DCT_12_method_ptr inverse_DCT_12[MAX_COMPONENTS];
|
||||
@@ -386,6 +438,15 @@ EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo);
|
||||
EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo);
|
||||
EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
|
||||
EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo);
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
EXTERN(void) jinit_c_diff_controller(j_compress_ptr cinfo,
|
||||
boolean need_full_buffer);
|
||||
EXTERN(void) j12init_c_diff_controller(j_compress_ptr cinfo,
|
||||
boolean need_full_buffer);
|
||||
EXTERN(void) jinit_lhuff_encoder(j_compress_ptr cinfo);
|
||||
EXTERN(void) jinit_lossless_compressor(j_compress_ptr cinfo);
|
||||
EXTERN(void) j12init_lossless_compressor(j_compress_ptr cinfo);
|
||||
#endif
|
||||
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo);
|
||||
@@ -418,6 +479,15 @@ EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo);
|
||||
EXTERN(void) j12init_2pass_quantizer(j_decompress_ptr cinfo);
|
||||
EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
|
||||
EXTERN(void) j12init_merged_upsampler(j_decompress_ptr cinfo);
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
EXTERN(void) jinit_d_diff_controller(j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer);
|
||||
EXTERN(void) j12init_d_diff_controller(j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer);
|
||||
EXTERN(void) jinit_lhuff_decoder(j_decompress_ptr cinfo);
|
||||
EXTERN(void) jinit_lossless_decompressor(j_decompress_ptr cinfo);
|
||||
EXTERN(void) j12init_lossless_decompressor(j_decompress_ptr cinfo);
|
||||
#endif
|
||||
|
||||
/* Memory manager initialization */
|
||||
EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo);
|
||||
|
||||
90
jpeglib.h
90
jpeglib.h
@@ -4,6 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2002-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
@@ -43,6 +45,13 @@ extern "C" {
|
||||
* 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 */
|
||||
@@ -57,9 +66,9 @@ extern "C" {
|
||||
* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
|
||||
* sometimes emits noncompliant files doesn't mean you should too.
|
||||
*/
|
||||
#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */
|
||||
#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 blocks per MCU */
|
||||
#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -142,17 +151,20 @@ typedef struct {
|
||||
/* Remaining fields should be treated as private by applications. */
|
||||
|
||||
/* These values are computed during compression or decompression startup: */
|
||||
/* Component's size in DCT blocks.
|
||||
* Any dummy blocks added to complete an MCU are not counted; therefore
|
||||
* these values do not depend on whether a scan is interleaved or not.
|
||||
/* Component's size in data units.
|
||||
* 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_blocks;
|
||||
JDIMENSION height_in_blocks;
|
||||
/* Size of a DCT block in samples. Always DCTSIZE for compression.
|
||||
* For decompression this is the size of the output from one DCT block,
|
||||
/* 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 from 1 to 16 are supported.
|
||||
* Note that different components may receive different IDCT scalings.
|
||||
* Values from 1 to 16 are supported. Note that different components may
|
||||
* receive different IDCT scalings. In lossless mode, this is always equal
|
||||
* to 1.
|
||||
*/
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
int DCT_h_scaled_size;
|
||||
@@ -163,8 +175,10 @@ typedef struct {
|
||||
/* The downsampled dimensions are the component's actual, unpadded number
|
||||
* of samples at the main buffer (preprocessing/compression interface), thus
|
||||
* downsampled_width = ceil(image_width * Hi/Hmax)
|
||||
* and similarly for height. For decompression, IDCT scaling is included, so
|
||||
* and similarly for height. For lossy decompression, IDCT scaling is
|
||||
* included, so
|
||||
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]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 */
|
||||
@@ -176,12 +190,12 @@ typedef struct {
|
||||
|
||||
/* These values are computed before starting a scan of the component. */
|
||||
/* The decompressor output side may not use these variables. */
|
||||
int MCU_width; /* number of blocks per MCU, horizontally */
|
||||
int MCU_height; /* number of blocks per MCU, vertically */
|
||||
int MCU_width; /* number of data units per MCU, horizontally */
|
||||
int MCU_height; /* number of data units per MCU, vertically */
|
||||
int MCU_blocks; /* MCU_width * MCU_height */
|
||||
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */
|
||||
int last_col_width; /* # of non-dummy blocks across in last MCU */
|
||||
int last_row_height; /* # of non-dummy blocks down in last MCU */
|
||||
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.
|
||||
@@ -199,8 +213,12 @@ typedef struct {
|
||||
typedef struct {
|
||||
int comps_in_scan; /* number of components encoded in this scan */
|
||||
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
|
||||
int Ss, Se; /* progressive JPEG spectral selection parms */
|
||||
int Ah, Al; /* progressive JPEG successive approx. parms */
|
||||
int Ss, Se; /* progressive JPEG spectral selection parms
|
||||
(Ss is the predictor selection value in
|
||||
lossless mode) */
|
||||
int Ah, Al; /* progressive JPEG successive approx. parms
|
||||
(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: */
|
||||
@@ -426,11 +444,13 @@ struct jpeg_compress_struct {
|
||||
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
|
||||
#endif
|
||||
|
||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
|
||||
/* The coefficient controller receives data in units of MCU rows as defined
|
||||
* for fully interleaved scans (whether the JPEG file is interleaved or not).
|
||||
* There are v_samp_factor * DCTSIZE sample rows of each component in an
|
||||
* "iMCU" (interleaved MCU) row.
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -444,12 +464,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 blocks_in_MCU; /* # of DCT blocks per 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 JPEG parameters for scan */
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for
|
||||
scan */
|
||||
|
||||
#if JPEG_LIB_VERSION >= 80
|
||||
int block_size; /* the basic DCT block size: 1..16 */
|
||||
@@ -658,12 +679,13 @@ struct jpeg_decompress_struct {
|
||||
#endif
|
||||
|
||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
|
||||
/* The coefficient controller's input and output progress is measured in
|
||||
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
|
||||
* in fully interleaved JPEG scans, but are used whether the scan is
|
||||
* interleaved or not. We define an iMCU row as v_samp_factor DCT block
|
||||
* rows of each component. Therefore, the IDCT output contains
|
||||
/* 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_[v_]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
|
||||
@@ -684,12 +706,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 blocks_in_MCU; /* # of DCT blocks per 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 block in an MCU */
|
||||
/* i'th data unit in an MCU */
|
||||
|
||||
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
|
||||
int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for
|
||||
scan */
|
||||
|
||||
#if JPEG_LIB_VERSION >= 80
|
||||
/* These fields are derived from Se of first SOS marker.
|
||||
@@ -960,6 +983,9 @@ EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
|
||||
const unsigned int *basic_table,
|
||||
int scale_factor, boolean force_baseline);
|
||||
EXTERN(int) jpeg_quality_scaling(int quality);
|
||||
EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo,
|
||||
int predictor_selection_value,
|
||||
int point_transform);
|
||||
EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo);
|
||||
EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
|
||||
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
#define _jinit_color_converter j12init_color_converter
|
||||
#define _jinit_downsampler j12init_downsampler
|
||||
#define _jinit_forward_dct j12init_forward_dct
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
#define _jinit_c_diff_controller j12init_c_diff_controller
|
||||
#define _jinit_lossless_compressor j12init_lossless_compressor
|
||||
#endif
|
||||
|
||||
#define _jinit_d_main_controller j12init_d_main_controller
|
||||
#define _jinit_d_coef_controller j12init_d_coef_controller
|
||||
@@ -83,6 +87,10 @@
|
||||
#define _jinit_1pass_quantizer j12init_1pass_quantizer
|
||||
#define _jinit_2pass_quantizer j12init_2pass_quantizer
|
||||
#define _jinit_merged_upsampler j12init_merged_upsampler
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
#define _jinit_d_diff_controller j12init_d_diff_controller
|
||||
#define _jinit_lossless_decompressor j12init_lossless_decompressor
|
||||
#endif
|
||||
|
||||
#define _jcopy_sample_rows j12copy_sample_rows
|
||||
|
||||
@@ -180,6 +188,10 @@
|
||||
#define _jinit_color_converter jinit_color_converter
|
||||
#define _jinit_downsampler jinit_downsampler
|
||||
#define _jinit_forward_dct jinit_forward_dct
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
#define _jinit_c_diff_controller jinit_c_diff_controller
|
||||
#define _jinit_lossless_compressor jinit_lossless_compressor
|
||||
#endif
|
||||
|
||||
#define _jinit_d_main_controller jinit_d_main_controller
|
||||
#define _jinit_d_coef_controller jinit_d_coef_controller
|
||||
@@ -190,6 +202,10 @@
|
||||
#define _jinit_1pass_quantizer jinit_1pass_quantizer
|
||||
#define _jinit_2pass_quantizer jinit_2pass_quantizer
|
||||
#define _jinit_merged_upsampler jinit_merged_upsampler
|
||||
#ifdef D_LOSSLESS_SUPPORTED
|
||||
#define _jinit_d_diff_controller jinit_d_diff_controller
|
||||
#define _jinit_lossless_decompressor jinit_lossless_decompressor
|
||||
#endif
|
||||
|
||||
#define _jcopy_sample_rows jcopy_sample_rows
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
|
||||
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
|
||||
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
|
||||
"Copyright (C) 1999 Ken Murchison\n" \
|
||||
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
|
||||
|
||||
#define JCOPYRIGHT_SHORT \
|
||||
|
||||
44
libjpeg.txt
44
libjpeg.txt
@@ -2,6 +2,8 @@ USING THE IJG JPEG LIBRARY
|
||||
|
||||
This file was part of the Independent JPEG Group's software:
|
||||
Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding.
|
||||
Lossless JPEG Modifications:
|
||||
Copyright (C) 1999, Ken Murchison.
|
||||
libjpeg-turbo Modifications:
|
||||
Copyright (C) 2010, 2014-2018, 2020, 2022, D. R. Commander.
|
||||
Copyright (C) 2015, Google, Inc.
|
||||
@@ -97,7 +99,6 @@ the ISO JPEG standard; most baseline, extended-sequential, and progressive
|
||||
JPEG processes are supported. (Our subset includes all features now in common
|
||||
use.) Unsupported ISO options include:
|
||||
* Hierarchical storage
|
||||
* Lossless JPEG
|
||||
* DNL marker
|
||||
* Nonintegral subsampling ratios
|
||||
We support both 8- and 12-bit data precision.
|
||||
@@ -994,6 +995,29 @@ 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_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:
|
||||
* Partial image decompression
|
||||
* 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:
|
||||
|
||||
@@ -1061,15 +1085,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
|
||||
|
||||
@@ -2,8 +2,10 @@ IJG JPEG LIBRARY: SYSTEM ARCHITECTURE
|
||||
|
||||
This file was part of the Independent JPEG Group's software:
|
||||
Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
|
||||
It was modified by The libjpeg-turbo Project to include only information
|
||||
relevant to libjpeg-turbo.
|
||||
Lossless JPEG Modifications:
|
||||
Copyright (C) 1999, Ken Murchison.
|
||||
libjpeg-turbo Modifications:
|
||||
Copyright (C) 2022, D. R. Commander.
|
||||
For conditions of distribution and use, see the accompanying README.ijg file.
|
||||
|
||||
|
||||
@@ -23,8 +25,10 @@ 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.
|
||||
An "MCU" (minimum coded unit) is an interleaved set of blocks of size
|
||||
determined by the sampling factors, or a single block in a
|
||||
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
|
||||
noninterleaved scan.
|
||||
We do not use the terms "pixel" and "sample" interchangeably. When we say
|
||||
pixel, we mean an element of the full-size image, while a sample is an element
|
||||
@@ -45,13 +49,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. Hierarchical processes are not
|
||||
supported.
|
||||
|
||||
The library does not support the lossless (spatial) JPEG process. Lossless
|
||||
JPEG shares little or no code with lossy JPEG, and would normally be used
|
||||
without the extensive pre- and post-processing provided by this library.
|
||||
We feel that lossless JPEG is better handled by a separate library.
|
||||
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
|
||||
@@ -100,9 +99,13 @@ elements:
|
||||
* Color space conversion (e.g., RGB to YCbCr).
|
||||
* Edge expansion and downsampling. Optionally, this step can do simple
|
||||
smoothing --- this is often helpful for low-quality source data.
|
||||
JPEG proper:
|
||||
Lossy JPEG proper:
|
||||
* MCU assembly, DCT, quantization.
|
||||
* Entropy coding (sequential or progressive, Huffman or arithmetic).
|
||||
Lossless JPEG proper:
|
||||
* Point transform.
|
||||
* Prediction, differencing.
|
||||
* Entropy coding (Huffman or arithmetic)
|
||||
|
||||
In addition to these modules we need overall control, marker generation,
|
||||
and support code (memory management & error handling). There is also a
|
||||
@@ -112,9 +115,13 @@ do something else with the data.
|
||||
|
||||
The decompressor library contains the following main elements:
|
||||
|
||||
JPEG proper:
|
||||
Lossy JPEG proper:
|
||||
* Entropy decoding (sequential or progressive, Huffman or arithmetic).
|
||||
* Dequantization, inverse DCT, MCU disassembly.
|
||||
Lossless JPEG proper:
|
||||
* Entropy decoding (Huffman or arithmetic).
|
||||
* Prediction, undifferencing.
|
||||
* Point transform, sample size scaling.
|
||||
Postprocessing:
|
||||
* Upsampling. Optionally, this step may be able to do more general
|
||||
rescaling of the image.
|
||||
@@ -280,7 +287,8 @@ task performed by any one controller.
|
||||
|
||||
*** 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 --|
|
||||
@@ -290,6 +298,19 @@ Main controller --|
|
||||
|-- Coefficient controller --|
|
||||
|-- Entropy encoding
|
||||
|
||||
... and in lossless mode:
|
||||
|
||||
|-- 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
|
||||
an "object" which may have several different implementations available. One
|
||||
@@ -343,6 +364,22 @@ The objects shown above are:
|
||||
during each pass, and the coder must emit the appropriate subset of
|
||||
coefficients.
|
||||
|
||||
* Difference controller: buffer controller for the spatial difference data.
|
||||
When emitting a multiscan JPEG file, this controller is responsible for
|
||||
buffering the full image. The equivalent of one fully interleaved MCU row
|
||||
of subsampled data is processed per call, even when the JPEG file is
|
||||
noninterleaved.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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:
|
||||
|
||||
@@ -383,7 +420,8 @@ 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:
|
||||
|
||||
|-- Entropy decoding
|
||||
|-- Coefficient controller --|
|
||||
@@ -394,6 +432,21 @@ Main controller --|
|
||||
|-- Color quantization
|
||||
|-- Color precision reduction
|
||||
|
||||
... and in lossless mode:
|
||||
|
||||
|-- 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:
|
||||
|
||||
@@ -427,6 +480,22 @@ shown are:
|
||||
that emit fewer samples per DCT block, not the full 8x8. Works on one DCT
|
||||
block at a time.
|
||||
|
||||
* Difference controller: buffer controller for the spatial difference data.
|
||||
When reading a multiscan JPEG file, this controller is responsible for
|
||||
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 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.
|
||||
|
||||
* 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
|
||||
controller just calls the upsampler.) For two-pass quantization, this
|
||||
|
||||
30
usage.txt
30
usage.txt
@@ -163,6 +163,31 @@ file size is about the same --- often a little smaller.
|
||||
|
||||
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
|
||||
* Partial image decompression
|
||||
* Transformations using jpegtran
|
||||
Any switches used to enable or configure those features
|
||||
will be ignored.
|
||||
|
||||
-arithmetic Use arithmetic coding. CAUTION: arithmetic coded JPEG
|
||||
is not yet widely implemented, so many decoders will
|
||||
be unable to view an arithmetic coded JPEG file at
|
||||
@@ -207,8 +232,9 @@ Switches for advanced users:
|
||||
same results on all machines.
|
||||
|
||||
-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
|
||||
|
||||
@@ -128,3 +128,4 @@ EXPORTS
|
||||
jpeg12_write_scanlines @ 127 ;
|
||||
jpeg12_skip_scanlines @ 128 ;
|
||||
jpeg12_crop_scanline @ 129 ;
|
||||
jpeg_enable_lossless @ 130 ;
|
||||
|
||||
@@ -130,3 +130,4 @@ EXPORTS
|
||||
jpeg12_write_scanlines @ 129 ;
|
||||
jpeg12_skip_scanlines @ 130 ;
|
||||
jpeg12_crop_scanline @ 131 ;
|
||||
jpeg_enable_lossless @ 132 ;
|
||||
|
||||
@@ -131,3 +131,4 @@ EXPORTS
|
||||
jpeg12_write_scanlines @ 130 ;
|
||||
jpeg12_skip_scanlines @ 131 ;
|
||||
jpeg12_crop_scanline @ 132 ;
|
||||
jpeg_enable_lossless @ 133 ;
|
||||
|
||||
41
wizard.txt
41
wizard.txt
@@ -116,23 +116,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
|
||||
@@ -143,13 +143,24 @@ 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.) More specifically:
|
||||
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.)
|
||||
More specifically:
|
||||
|
||||
* An AC scan cannot include coefficients from more than one component.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user