@@ -273,12 +273,12 @@ endif()
|
|||||||
# 1: + In-memory source/destination managers (libjpeg-turbo 1.3.x)
|
# 1: + In-memory source/destination managers (libjpeg-turbo 1.3.x)
|
||||||
# 2: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
# 2: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
||||||
# 3: + ICC functions (libjpeg-turbo 2.0.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:
|
# libjpeg v8 API/ABI emulation:
|
||||||
# 1: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
# 1: + Partial image decompression functions (libjpeg-turbo 1.5.x)
|
||||||
# 2: + ICC functions (libjpeg-turbo 2.0.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)
|
set(SO_AGE 3)
|
||||||
if(NOT WITH_JPEG8)
|
if(NOT WITH_JPEG8)
|
||||||
set(SO_AGE 4)
|
set(SO_AGE 4)
|
||||||
@@ -535,10 +535,11 @@ if(CMAKE_EXECUTABLE_SUFFIX_TMP)
|
|||||||
endif()
|
endif()
|
||||||
message(STATUS "CMAKE_EXECUTABLE_SUFFIX = ${CMAKE_EXECUTABLE_SUFFIX}")
|
message(STATUS "CMAKE_EXECUTABLE_SUFFIX = ${CMAKE_EXECUTABLE_SUFFIX}")
|
||||||
|
|
||||||
set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c
|
set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c
|
||||||
jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c
|
jcdiffct.c jchuff.c jcicc.c jcinit.c jclhuff.c jclossls.c jcmainct.c
|
||||||
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c
|
jcmarker.c jcmaster.c jcomapi.c jcparam.c jcphuff.c jcprepct.c jcsample.c
|
||||||
jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.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
|
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
|
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)
|
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
|
# Compile a separate version of these source files with 12-bit data
|
||||||
# precision.
|
# precision.
|
||||||
add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcmainct.c
|
add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c
|
||||||
jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c jddctmgr.c jdmainct.c
|
jclossls.c jcmainct.c jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c
|
||||||
jdmerge.c jdpostct.c jdsample.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c
|
jddctmgr.c jddiffct.c jdlossls.c jdmainct.c jdmerge.c jdpostct.c jdsample.c
|
||||||
jidctint.c jidctred.c jquant1.c jquant2.c jutils.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")
|
set_property(TARGET jpeg12 PROPERTY COMPILE_FLAGS "-DBITS_IN_JSAMPLE=12")
|
||||||
|
|
||||||
if(WITH_SIMD)
|
if(WITH_SIMD)
|
||||||
@@ -1046,6 +1048,8 @@ foreach(libtype ${TEST_LIBTYPES})
|
|||||||
set(MD5_PPM_420M_ISLOW_3_8 343d19015531b7bbe746124127244fa8)
|
set(MD5_PPM_420M_ISLOW_3_8 343d19015531b7bbe746124127244fa8)
|
||||||
set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
|
set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
|
||||||
set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7)
|
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_SKIP15_31 86664cd9dc956536409e44e244d20a97)
|
||||||
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
||||||
452a21656115a163029cfba5c04fa76a)
|
452a21656115a163029cfba5c04fa76a)
|
||||||
@@ -1121,6 +1125,8 @@ foreach(libtype ${TEST_LIBTYPES})
|
|||||||
set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2)
|
set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2)
|
||||||
set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f)
|
set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f)
|
||||||
set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b)
|
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_SKIP15_31 c4c65c1e43d7275cd50328a61e6534f0)
|
||||||
set(MD5_PPM_420_ISLOW_ARI_SKIP16_139 087c6b123db16ac00cb88c5b590bb74a)
|
set(MD5_PPM_420_ISLOW_ARI_SKIP16_139 087c6b123db16ac00cb88c5b590bb74a)
|
||||||
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71
|
||||||
@@ -1362,6 +1368,16 @@ foreach(libtype ${TEST_LIBTYPES})
|
|||||||
${MD5_BMP_420M_ISLOW_565D})
|
${MD5_BMP_420M_ISLOW_565D})
|
||||||
endif()
|
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
|
# Partial decode tests. These tests are designed to cover all of the
|
||||||
# possible code paths in jpeg_skip_scanlines().
|
# possible code paths in jpeg_skip_scanlines().
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ tables.
|
|||||||
3. All deprecated fields, constructors, and methods in the TurboJPEG Java API
|
3. All deprecated fields, constructors, and methods in the TurboJPEG Java API
|
||||||
have been removed.
|
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
|
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
|
quality may have to be used to avoid visible compression artifacts with such
|
||||||
images.
|
images.
|
||||||
|
|
||||||
JPEG is lossy, meaning that the output pixels are not necessarily identical to
|
JPEG is normally lossy, meaning that the output pixels are not necessarily
|
||||||
the input pixels. However, on photographic content and other "smooth" images,
|
identical to the input pixels. However, on photographic content and other
|
||||||
very good compression ratios can be obtained with no visible compression
|
"smooth" images, very good compression ratios can be obtained with no visible
|
||||||
artifacts, and extremely high compression ratios are possible if you are
|
compression artifacts, and extremely high compression ratios are possible if
|
||||||
willing to sacrifice image quality (by reducing the "quality" setting in the
|
you are willing to sacrifice image quality (by reducing the "quality" setting
|
||||||
compressor.)
|
in the compressor.)
|
||||||
|
|
||||||
This software implements JPEG baseline, extended-sequential, and progressive
|
This software implements JPEG baseline, extended-sequential, progressive, and
|
||||||
compression processes. Provision is made for supporting all variants of these
|
lossless compression processes. Provision is made for supporting all variants
|
||||||
processes, although some uncommon parameter settings aren't implemented yet.
|
of these processes, although some uncommon parameter settings aren't
|
||||||
We have made no provision for supporting the hierarchical or lossless
|
implemented yet. We have made no provision for supporting the hierarchical
|
||||||
processes defined in the standard.
|
processes defined in the standard.
|
||||||
|
|
||||||
We provide a set of library routines for reading and writing JPEG image files,
|
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).
|
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
|
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
|
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
|
JPEG 2000 and JPEG XR). This software therefore does not support these
|
||||||
formats. Indeed, one of the original reasons for developing this free software
|
formats. Indeed, one of the original reasons for developing this free software
|
||||||
was to help force convergence on a common, interoperable format standard for
|
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
|
.SH NAME
|
||||||
cjpeg \- compress an image file to a JPEG file
|
cjpeg \- compress an image file to a JPEG file
|
||||||
.SH SYNOPSIS
|
.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
|
12-bit JPEG is not yet widely implemented, so many decoders will be unable to
|
||||||
view a 12-bit JPEG file at all.
|
view a 12-bit JPEG file at all.
|
||||||
.TP
|
.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
|
.B \-arithmetic
|
||||||
Use arithmetic coding.
|
Use arithmetic coding.
|
||||||
.B Caution:
|
.B Caution:
|
||||||
@@ -201,8 +240,8 @@ machines.
|
|||||||
Embed ICC color management profile contained in the specified file.
|
Embed ICC color management profile contained in the specified file.
|
||||||
.TP
|
.TP
|
||||||
.BI \-restart " N"
|
.BI \-restart " N"
|
||||||
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is
|
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks (samples in
|
||||||
attached to the number.
|
lossless mode) if "B" is attached to the number.
|
||||||
.B \-restart 0
|
.B \-restart 0
|
||||||
(the default) means no restart markers.
|
(the default) means no restart markers.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
29
cjpeg.c
29
cjpeg.c
@@ -4,6 +4,8 @@
|
|||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
* Modified 2003-2011 by Guido Vollbeding.
|
* Modified 2003-2011 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander.
|
* Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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, "Switches for advanced users:\n");
|
||||||
fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\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");
|
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
|
#ifdef C_ARITH_CODING_SUPPORTED
|
||||||
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -265,6 +270,9 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
|
|||||||
{
|
{
|
||||||
int argn;
|
int argn;
|
||||||
char *arg;
|
char *arg;
|
||||||
|
#ifdef C_LOSSLESS_SUPPORTED
|
||||||
|
int psv, pt = 0;
|
||||||
|
#endif
|
||||||
boolean force_baseline;
|
boolean force_baseline;
|
||||||
boolean simple_progressive;
|
boolean simple_progressive;
|
||||||
char *qualityarg = NULL; /* saves -quality parm if any */
|
char *qualityarg = NULL; /* saves -quality parm if any */
|
||||||
@@ -361,6 +369,27 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
|
|||||||
usage();
|
usage();
|
||||||
icc_filename = argv[argn];
|
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)) {
|
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||||
/* Maximum memory in Kb (or Mb with 'm'). */
|
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||||
long lval;
|
long lval;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#define JPEG_INTERNALS
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
#include "jpeglib.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 */
|
/* OK, I'm ready */
|
||||||
cinfo->global_state = CSTATE_START;
|
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)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
if (cinfo->global_state != CSTATE_RAW_OK)
|
if (cinfo->global_state != CSTATE_RAW_OK)
|
||||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
if (cinfo->next_scanline >= cinfo->image_height) {
|
if (cinfo->next_scanline >= cinfo->image_height) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* This file contains the coefficient buffer controller for compression.
|
* 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.
|
* 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;
|
cconvert->pub._color_convert = null_convert;
|
||||||
break;
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander.
|
* Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander.
|
||||||
* Copyright (C) 2015, Matthieu Darbois.
|
* Copyright (C) 2015, Matthieu Darbois.
|
||||||
@@ -30,7 +32,7 @@
|
|||||||
#ifdef WITH_SIMD
|
#ifdef WITH_SIMD
|
||||||
#include "jsimd.h"
|
#include "jsimd.h"
|
||||||
#else
|
#else
|
||||||
#include "jchuff.h"
|
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||||
#endif
|
#endif
|
||||||
#include <limits.h>
|
#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.
|
* Compute the derived values for a Huffman table.
|
||||||
* This routine also performs some validation checks on the 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)
|
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->ehufco, 0, sizeof(dtbl->ehufco));
|
||||||
memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi));
|
memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi));
|
||||||
|
|
||||||
/* This is also a convenient place to check for out-of-range
|
/* This is also a convenient place to check for out-of-range and duplicated
|
||||||
* and duplicated VAL entries. We allow 0..255 for AC symbols
|
* VAL entries. We allow 0..255 for AC symbols but only 0..15 for DC in
|
||||||
* but only 0..15 for DC. (We could constrain them further
|
* lossy mode and 0..16 for DC in lossless mode. (We could constrain them
|
||||||
* based on data depth and mode, but this seems enough.)
|
* 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++) {
|
for (p = 0; p < lastp; p++) {
|
||||||
i = htbl->huffval[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.
|
* 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
|
* 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
|
* 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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2020, 2022, D. R. Commander.
|
* Copyright (C) 2020, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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 */);
|
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Forward DCT */
|
|
||||||
if (cinfo->data_precision == 12)
|
if (cinfo->master->lossless) {
|
||||||
j12init_forward_dct(cinfo);
|
#ifdef C_LOSSLESS_SUPPORTED
|
||||||
else
|
/* Prediction, sample differencing, and point transform */
|
||||||
jinit_forward_dct(cinfo);
|
if (cinfo->data_precision == 12)
|
||||||
/* Entropy encoding: either Huffman or arithmetic coding. */
|
j12init_lossless_compressor(cinfo);
|
||||||
if (cinfo->arith_code) {
|
else
|
||||||
#ifdef C_ARITH_CODING_SUPPORTED
|
jinit_lossless_compressor(cinfo);
|
||||||
jinit_arith_encoder(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
|
#else
|
||||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (cinfo->progressive_mode) {
|
/* Forward DCT */
|
||||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
if (cinfo->data_precision == 12)
|
||||||
jinit_phuff_encoder(cinfo);
|
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
|
#else
|
||||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
#endif
|
#endif
|
||||||
} else
|
} else {
|
||||||
jinit_huff_encoder(cinfo);
|
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)
|
||||||
if (cinfo->data_precision == 12) {
|
|
||||||
j12init_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
|
||||||
cinfo->optimize_coding));
|
|
||||||
j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
} else {
|
else
|
||||||
jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
|
|
||||||
cinfo->optimize_coding));
|
|
||||||
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||||
}
|
|
||||||
|
|
||||||
jinit_marker_writer(cinfo);
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2022, D. R. Commander.
|
* Copyright (C) 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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)
|
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)
|
||||||
{
|
{
|
||||||
my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
|
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) {
|
while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
|
||||||
/* Read input data if we haven't filled the main buffer yet */
|
/* 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,
|
(*cinfo->prep->_pre_process_data) (cinfo, input_buf, in_row_ctr,
|
||||||
in_rows_avail, main_ptr->buffer,
|
in_rows_avail, main_ptr->buffer,
|
||||||
&main_ptr->rowgroup_ctr,
|
&main_ptr->rowgroup_ctr, data_unit);
|
||||||
(JDIMENSION)DCTSIZE);
|
|
||||||
|
|
||||||
/* If we don't have a full iMCU row buffered, return to application for
|
/* 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
|
* more data. Note that preprocessor will always pad to fill the iMCU row
|
||||||
* at the bottom of the image.
|
* at the bottom of the image.
|
||||||
*/
|
*/
|
||||||
if (main_ptr->rowgroup_ctr != DCTSIZE)
|
if (main_ptr->rowgroup_ctr != data_unit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Send the completed row to the compressor */
|
/* 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;
|
my_main_ptr main_ptr;
|
||||||
int ci;
|
int ci;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
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++) {
|
ci++, compptr++) {
|
||||||
main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||||
compptr->width_in_blocks * DCTSIZE,
|
compptr->width_in_blocks * data_unit,
|
||||||
(JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
|
(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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
* Modified 2003-2010 by Guido Vollbeding.
|
* Modified 2003-2010 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010, 2022, D. R. Commander.
|
* Copyright (C) 2010, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
@@ -497,25 +499,26 @@ write_file_header(j_compress_ptr cinfo)
|
|||||||
METHODDEF(void)
|
METHODDEF(void)
|
||||||
write_frame_header(j_compress_ptr cinfo)
|
write_frame_header(j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
int ci, prec;
|
int ci, prec = 0;
|
||||||
boolean is_baseline;
|
boolean is_baseline;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
/* Emit DQT for each quantization table.
|
if (!cinfo->master->lossless) {
|
||||||
* Note that emit_dqt() suppresses any duplicate tables.
|
/* 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;
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
ci++, compptr++) {
|
ci++, compptr++) {
|
||||||
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
|
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.
|
/* Check for a non-baseline specification.
|
||||||
* Note we assume that Huffman table numbers won't be changed later.
|
* Note we assume that Huffman table numbers won't be changed later.
|
||||||
*/
|
*/
|
||||||
if (cinfo->arith_code || cinfo->progressive_mode ||
|
if (cinfo->arith_code || cinfo->progressive_mode ||
|
||||||
cinfo->data_precision != 8) {
|
cinfo->master->lossless || cinfo->data_precision != 8) {
|
||||||
is_baseline = FALSE;
|
is_baseline = FALSE;
|
||||||
} else {
|
} else {
|
||||||
is_baseline = TRUE;
|
is_baseline = TRUE;
|
||||||
@@ -540,6 +543,8 @@ write_frame_header(j_compress_ptr cinfo)
|
|||||||
} else {
|
} else {
|
||||||
if (cinfo->progressive_mode)
|
if (cinfo->progressive_mode)
|
||||||
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
|
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)
|
else if (is_baseline)
|
||||||
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
|
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
|
||||||
else
|
else
|
||||||
@@ -574,10 +579,11 @@ write_scan_header(j_compress_ptr cinfo)
|
|||||||
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
for (i = 0; i < cinfo->comps_in_scan; i++) {
|
||||||
compptr = cinfo->cur_comp_info[i];
|
compptr = cinfo->cur_comp_info[i];
|
||||||
/* DC needs no table for refinement scan */
|
/* 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);
|
emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
|
||||||
/* AC needs no table when not present */
|
/* AC needs no table when not present, and lossless mode uses only DC
|
||||||
if (cinfo->Se)
|
tables. */
|
||||||
|
if (cinfo->Se && !cinfo->master->lossless)
|
||||||
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 2003-2010 by Guido Vollbeding.
|
* Modified 2003-2010 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
@@ -19,38 +21,7 @@
|
|||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
#include "jpeglib.h"
|
#include "jpeglib.h"
|
||||||
#include "jpegapicomp.h"
|
#include "jpegapicomp.h"
|
||||||
|
#include "jcmaster.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;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -68,11 +39,13 @@ GLOBAL(void)
|
|||||||
jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
|
jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
|
||||||
/* Do computations that are needed before master selection phase */
|
/* Do computations that are needed before master selection phase */
|
||||||
{
|
{
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
/* Hardwire it to "no scaling" */
|
/* Hardwire it to "no scaling" */
|
||||||
cinfo->jpeg_width = cinfo->image_width;
|
cinfo->jpeg_width = cinfo->image_width;
|
||||||
cinfo->jpeg_height = cinfo->image_height;
|
cinfo->jpeg_height = cinfo->image_height;
|
||||||
cinfo->min_DCT_h_scaled_size = DCTSIZE;
|
cinfo->min_DCT_h_scaled_size = data_unit;
|
||||||
cinfo->min_DCT_v_scaled_size = DCTSIZE;
|
cinfo->min_DCT_v_scaled_size = data_unit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -85,6 +58,7 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
|
|||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
long samplesperrow;
|
long samplesperrow;
|
||||||
JDIMENSION jd_samplesperrow;
|
JDIMENSION jd_samplesperrow;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#if JPEG_LIB_VERSION >= 70
|
||||||
#if JPEG_LIB_VERSION >= 80
|
#if JPEG_LIB_VERSION >= 80
|
||||||
@@ -140,17 +114,17 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
|
|||||||
compptr->component_index = ci;
|
compptr->component_index = ci;
|
||||||
/* For compression, we never do DCT scaling. */
|
/* For compression, we never do DCT scaling. */
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#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
|
#else
|
||||||
compptr->DCT_scaled_size = DCTSIZE;
|
compptr->DCT_scaled_size = data_unit;
|
||||||
#endif
|
#endif
|
||||||
/* Size in DCT blocks */
|
/* Size in data units */
|
||||||
compptr->width_in_blocks = (JDIMENSION)
|
compptr->width_in_blocks = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
|
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)
|
compptr->height_in_blocks = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
|
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 */
|
/* Size in samples */
|
||||||
compptr->downsampled_width = (JDIMENSION)
|
compptr->downsampled_width = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
|
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
|
/* 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)
|
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_height,
|
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)
|
LOCAL(void)
|
||||||
validate_script(j_compress_ptr cinfo)
|
validate_script(j_compress_ptr cinfo)
|
||||||
@@ -192,13 +170,29 @@ validate_script(j_compress_ptr cinfo)
|
|||||||
if (cinfo->num_scans <= 0)
|
if (cinfo->num_scans <= 0)
|
||||||
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 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 sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
|
||||||
* for progressive JPEG, no scan can have this.
|
* for progressive JPEG, no scan can have this.
|
||||||
*/
|
*/
|
||||||
scanptr = cinfo->scan_info;
|
else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
|
||||||
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
|
|
||||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||||
cinfo->progressive_mode = TRUE;
|
cinfo->progressive_mode = TRUE;
|
||||||
|
cinfo->master->lossless = FALSE;
|
||||||
last_bitpos_ptr = &last_bitpos[0][0];
|
last_bitpos_ptr = &last_bitpos[0][0];
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||||
for (coefi = 0; coefi < DCTSIZE2; coefi++)
|
for (coefi = 0; coefi < DCTSIZE2; coefi++)
|
||||||
@@ -207,7 +201,7 @@ validate_script(j_compress_ptr cinfo)
|
|||||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
cinfo->progressive_mode = FALSE;
|
cinfo->progressive_mode = cinfo->master->lossless = FALSE;
|
||||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||||
component_sent[ci] = FALSE;
|
component_sent[ci] = FALSE;
|
||||||
}
|
}
|
||||||
@@ -270,9 +264,25 @@ validate_script(j_compress_ptr cinfo)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* For sequential JPEG, all progression parameters must be these: */
|
#ifdef C_LOSSLESS_SUPPORTED
|
||||||
if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0)
|
if (cinfo->master->lossless) {
|
||||||
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
|
/* 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 */
|
/* Make sure components are not sent twice */
|
||||||
for (ci = 0; ci < ncomps; ci++) {
|
for (ci = 0; ci < ncomps; ci++) {
|
||||||
thisi = scanptr->component_index[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)
|
LOCAL(void)
|
||||||
@@ -313,7 +323,7 @@ select_scan_parameters(j_compress_ptr cinfo)
|
|||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
|
|
||||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
#ifdef NEED_SCAN_SCRIPT
|
||||||
if (cinfo->scan_info != NULL) {
|
if (cinfo->scan_info != NULL) {
|
||||||
/* Prepare for current scan --- the script is already validated */
|
/* Prepare for current scan --- the script is already validated */
|
||||||
my_master_ptr master = (my_master_ptr)cinfo->master;
|
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++) {
|
for (ci = 0; ci < cinfo->num_components; ci++) {
|
||||||
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
|
||||||
}
|
}
|
||||||
cinfo->Ss = 0;
|
if (!cinfo->master->lossless) {
|
||||||
cinfo->Se = DCTSIZE2 - 1;
|
cinfo->Ss = 0;
|
||||||
cinfo->Ah = 0;
|
cinfo->Se = DCTSIZE2 - 1;
|
||||||
cinfo->Al = 0;
|
cinfo->Ah = 0;
|
||||||
|
cinfo->Al = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +366,7 @@ per_scan_setup(j_compress_ptr cinfo)
|
|||||||
{
|
{
|
||||||
int ci, mcublks, tmp;
|
int ci, mcublks, tmp;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
if (cinfo->comps_in_scan == 1) {
|
if (cinfo->comps_in_scan == 1) {
|
||||||
|
|
||||||
@@ -368,7 +381,7 @@ per_scan_setup(j_compress_ptr cinfo)
|
|||||||
compptr->MCU_width = 1;
|
compptr->MCU_width = 1;
|
||||||
compptr->MCU_height = 1;
|
compptr->MCU_height = 1;
|
||||||
compptr->MCU_blocks = 1;
|
compptr->MCU_blocks = 1;
|
||||||
compptr->MCU_sample_width = DCTSIZE;
|
compptr->MCU_sample_width = data_unit;
|
||||||
compptr->last_col_width = 1;
|
compptr->last_col_width = 1;
|
||||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
/* 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 block rows present in the last iMCU row.
|
||||||
@@ -391,10 +404,10 @@ per_scan_setup(j_compress_ptr cinfo)
|
|||||||
/* Overall image size in MCUs */
|
/* Overall image size in MCUs */
|
||||||
cinfo->MCUs_per_row = (JDIMENSION)
|
cinfo->MCUs_per_row = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_width,
|
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)
|
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->_jpeg_height,
|
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;
|
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_width = compptr->h_samp_factor;
|
||||||
compptr->MCU_height = compptr->v_samp_factor;
|
compptr->MCU_height = compptr->v_samp_factor;
|
||||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
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 */
|
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||||
tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
|
tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
|
||||||
if (tmp == 0) tmp = 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. */
|
/* Do Huffman optimization for a scan after the first one. */
|
||||||
select_scan_parameters(cinfo);
|
select_scan_parameters(cinfo);
|
||||||
per_scan_setup(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->entropy->start_pass) (cinfo, TRUE);
|
||||||
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||||
master->pub.call_pass_startup = FALSE;
|
master->pub.call_pass_startup = FALSE;
|
||||||
@@ -585,22 +599,15 @@ finish_pass_master(j_compress_ptr cinfo)
|
|||||||
GLOBAL(void)
|
GLOBAL(void)
|
||||||
jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
|
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.prepare_for_pass = prepare_for_pass;
|
||||||
master->pub.pass_startup = pass_startup;
|
master->pub.pass_startup = pass_startup;
|
||||||
master->pub.finish_pass = finish_pass_master;
|
master->pub.finish_pass = finish_pass_master;
|
||||||
master->pub.is_last_pass = FALSE;
|
master->pub.is_last_pass = FALSE;
|
||||||
|
|
||||||
/* Validate parameters, determine derived values */
|
|
||||||
initial_setup(cinfo, transcode_only);
|
|
||||||
|
|
||||||
if (cinfo->scan_info != NULL) {
|
if (cinfo->scan_info != NULL) {
|
||||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
#ifdef NEED_SCAN_SCRIPT
|
||||||
validate_script(cinfo);
|
validate_script(cinfo);
|
||||||
#else
|
#else
|
||||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
@@ -610,9 +617,30 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
|
|||||||
cinfo->num_scans = 1;
|
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
|
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
||||||
progressive mode */
|
progressive mode or lossless mode */
|
||||||
if (cinfo->data_precision == 12)
|
if (cinfo->data_precision == 12)
|
||||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit
|
cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit
|
||||||
data precision */
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
* Modified 2003-2008 by Guido Vollbeding.
|
* Modified 2003-2008 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2018, D. R. Commander.
|
* Copyright (C) 2009-2011, 2018, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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_BGRA:
|
||||||
case JCS_EXT_ABGR:
|
case JCS_EXT_ABGR:
|
||||||
case JCS_EXT_ARGB:
|
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;
|
break;
|
||||||
case JCS_YCbCr:
|
case JCS_YCbCr:
|
||||||
jpeg_set_colorspace(cinfo, 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)
|
if (cinfo->global_state != CSTATE_START)
|
||||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
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! */
|
/* Figure space needed for script. Calculation must match code below! */
|
||||||
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
|
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
/* Custom script for YCbCr color images. */
|
/* Custom script for YCbCr color images. */
|
||||||
@@ -538,3 +548,38 @@ jpeg_simple_progression(j_compress_ptr cinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* C_PROGRESSIVE_SUPPORTED */
|
#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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander.
|
* Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander.
|
||||||
* Copyright (C) 2016, 2018, Matthieu Darbois.
|
* Copyright (C) 2016, 2018, Matthieu Darbois.
|
||||||
@@ -24,7 +26,7 @@
|
|||||||
#ifdef WITH_SIMD
|
#ifdef WITH_SIMD
|
||||||
#include "jsimd.h"
|
#include "jsimd.h"
|
||||||
#else
|
#else
|
||||||
#include "jchuff.h"
|
#include "jchuff.h" /* Declarations shared with jc*huff.c */
|
||||||
#endif
|
#endif
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|||||||
14
jcprepct.c
14
jcprepct.c
@@ -1,8 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* jcprepct.c
|
* 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.
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2022, D. R. Commander.
|
* Copyright (C) 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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;
|
int numrows, ci;
|
||||||
JDIMENSION inrows;
|
JDIMENSION inrows;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
while (*in_row_ctr < in_rows_avail &&
|
while (*in_row_ctr < in_rows_avail &&
|
||||||
*out_row_group_ctr < out_row_groups_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) {
|
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;
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
ci++, compptr++) {
|
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_group_ctr * compptr->v_samp_factor),
|
||||||
(int)(out_row_groups_avail * 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;
|
int ci, i;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
_JSAMPARRAY true_buffer, fake_buffer;
|
_JSAMPARRAY true_buffer, fake_buffer;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
/* Grab enough space for fake row pointers for all the components;
|
/* Grab enough space for fake row pointers for all the components;
|
||||||
* we need five row groups' worth of pointers for each component.
|
* 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)
|
true_buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
((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),
|
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||||
(JDIMENSION)(3 * rgroup_height));
|
(JDIMENSION)(3 * rgroup_height));
|
||||||
/* Copy true buffer row pointers into the middle of the fake row array */
|
/* 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;
|
my_prep_ptr prep;
|
||||||
int ci;
|
int ci;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
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++) {
|
ci++, compptr++) {
|
||||||
prep->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
prep->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
|
||||||
((j_common_ptr)cinfo, JPOOL_IMAGE,
|
((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),
|
cinfo->max_h_samp_factor) / compptr->h_samp_factor),
|
||||||
(JDIMENSION)cinfo->max_v_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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||||
* Copyright (C) 2014, MIPS Technologies, Inc., California.
|
* 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;
|
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
|
||||||
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
|
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;
|
_JSAMPROW inptr, outptr;
|
||||||
JLONG outvalue;
|
JLONG outvalue;
|
||||||
|
|
||||||
@@ -195,12 +198,14 @@ METHODDEF(void)
|
|||||||
fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||||
_JSAMPARRAY input_data, _JSAMPARRAY output_data)
|
_JSAMPARRAY input_data, _JSAMPARRAY output_data)
|
||||||
{
|
{
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
/* Copy the data */
|
/* Copy the data */
|
||||||
_jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor,
|
_jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor,
|
||||||
cinfo->image_width);
|
cinfo->image_width);
|
||||||
/* Edge-expand */
|
/* Edge-expand */
|
||||||
expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
|
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;
|
int outrow;
|
||||||
JDIMENSION outcol;
|
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 _JSAMPROW inptr, outptr;
|
||||||
register int bias;
|
register int bias;
|
||||||
|
|
||||||
@@ -258,7 +264,8 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
|||||||
{
|
{
|
||||||
int inrow, outrow;
|
int inrow, outrow;
|
||||||
JDIMENSION outcol;
|
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 _JSAMPROW inptr0, inptr1, outptr;
|
||||||
register int bias;
|
register int bias;
|
||||||
|
|
||||||
@@ -300,7 +307,8 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
|||||||
{
|
{
|
||||||
int inrow, outrow;
|
int inrow, outrow;
|
||||||
JDIMENSION colctr;
|
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;
|
register _JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
|
||||||
JLONG membersum, neighsum, memberscale, neighscale;
|
JLONG membersum, neighsum, memberscale, neighscale;
|
||||||
|
|
||||||
@@ -388,7 +396,8 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
|||||||
{
|
{
|
||||||
int outrow;
|
int outrow;
|
||||||
JDIMENSION colctr;
|
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;
|
register _JSAMPROW inptr, above_ptr, below_ptr, outptr;
|
||||||
JLONG membersum, neighsum, memberscale, neighscale;
|
JLONG membersum, neighsum, memberscale, neighscale;
|
||||||
int colsum, lastcolsum, nextcolsum;
|
int colsum, lastcolsum, nextcolsum;
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo,
|
|||||||
GLOBAL(void)
|
GLOBAL(void)
|
||||||
jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
|
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)
|
if (cinfo->global_state != CSTATE_START)
|
||||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
/* Mark all tables to be written */
|
/* 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;
|
JQUANT_TBL *c_quant, *slot_quant;
|
||||||
int tblno, ci, coefi;
|
int tblno, ci, coefi;
|
||||||
|
|
||||||
|
if (srcinfo->master->lossless)
|
||||||
|
ERREXIT(dstinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
/* Safety check to ensure start_compress not called yet. */
|
/* Safety check to ensure start_compress not called yet. */
|
||||||
if (dstinfo->global_state != CSTATE_START)
|
if (dstinfo->global_state != CSTATE_START)
|
||||||
ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
|
ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1994-1998, Thomas G. Lane.
|
* Copyright (C) 1994-1998, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2016, 2022, D. R. Commander.
|
* Copyright (C) 2016, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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' */
|
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||||
else {
|
else {
|
||||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
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. */
|
/* 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)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
if ((cinfo->global_state != DSTATE_SCANNING &&
|
if ((cinfo->global_state != DSTATE_SCANNING &&
|
||||||
cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0)
|
cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0)
|
||||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
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)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
/* Two-pass color quantization is not supported. */
|
/* Two-pass color quantization is not supported. */
|
||||||
if (cinfo->quantize_colors && cinfo->two_pass_quantize)
|
if (cinfo->quantize_colors && cinfo->two_pass_quantize)
|
||||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
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)
|
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||||
|
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
if (cinfo->global_state != DSTATE_RAW_OK)
|
if (cinfo->global_state != DSTATE_RAW_OK)
|
||||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||||
if (cinfo->output_scanline >= cinfo->output_height) {
|
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* This file contains the coefficient buffer controller for decompression.
|
* 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.
|
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
|
||||||
*
|
*
|
||||||
* In buffered-image mode, this controller is the interface between
|
* In buffered-image mode, this controller is the interface between
|
||||||
|
|||||||
@@ -884,6 +884,15 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
|||||||
break;
|
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)
|
if (cinfo->quantize_colors)
|
||||||
cinfo->output_components = 1; /* single colormapped output component */
|
cinfo->output_components = 1; /* single colormapped output component */
|
||||||
else
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2016, 2018-2019, 2022, D. R. Commander.
|
* Copyright (C) 2009-2011, 2016, 2018-2019, 2022, D. R. Commander.
|
||||||
* Copyright (C) 2018, Matthias Räncker.
|
* Copyright (C) 2018, Matthias Räncker.
|
||||||
@@ -24,7 +26,7 @@
|
|||||||
#define JPEG_INTERNALS
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
#include "jpeglib.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 "jpegapicomp.h"
|
||||||
#include "jstdhuff.c"
|
#include "jstdhuff.c"
|
||||||
|
|
||||||
@@ -134,7 +136,7 @@ start_pass_huff_decoder(j_decompress_ptr cinfo)
|
|||||||
* Compute the derived values for a Huffman table.
|
* Compute the derived values for a Huffman table.
|
||||||
* This routine also performs some validation checks on the 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)
|
GLOBAL(void)
|
||||||
@@ -245,14 +247,14 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno,
|
|||||||
|
|
||||||
/* Validate symbols as being reasonable.
|
/* Validate symbols as being reasonable.
|
||||||
* For AC tables, we make no check, but accept all byte values 0..255.
|
* 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.
|
* For DC tables, we require the symbols to be in range 0..15 in lossy mode
|
||||||
* (Tighter bounds could be applied depending on the data depth and mode,
|
* and 0..16 in lossless mode. (Tighter bounds could be applied depending on
|
||||||
* but this is sufficient to ensure safe decoding.)
|
* the data depth and mode, but this is sufficient to ensure safe decoding.)
|
||||||
*/
|
*/
|
||||||
if (isDC) {
|
if (isDC) {
|
||||||
for (i = 0; i < numsymbols; i++) {
|
for (i = 0; i < numsymbols; i++) {
|
||||||
int sym = htbl->huffval[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);
|
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.
|
* See jdhuff.h for info about usage.
|
||||||
* Note: current values of get_buffer and bits_left are passed as parameters,
|
* Note: current values of get_buffer and bits_left are passed as parameters,
|
||||||
* but are returned in the corresponding fields of the state struct.
|
* 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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander.
|
* Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander.
|
||||||
* Copyright (C) 2018, Matthias Räncker.
|
* Copyright (C) 2018, Matthias Räncker.
|
||||||
@@ -10,8 +12,9 @@
|
|||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* This file contains declarations for Huffman entropy decoding routines
|
* This file contains declarations for Huffman entropy decoding routines
|
||||||
* that are shared between the sequential decoder (jdhuff.c) and the
|
* that are shared between the sequential decoder (jdhuff.c), the progressive
|
||||||
* progressive decoder (jdphuff.c). No other modules need to see these.
|
* decoder (jdphuff.c), and the lossless decoder (jdlhuff.c). No other modules
|
||||||
|
* need to see these.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jconfigint.h"
|
#include "jconfigint.h"
|
||||||
|
|||||||
54
jdinput.c
54
jdinput.c
@@ -3,6 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file was part of the Independent JPEG Group's software:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
* Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander.
|
||||||
* Copyright (C) 2015, Google, Inc.
|
* Copyright (C) 2015, Google, Inc.
|
||||||
@@ -11,8 +13,9 @@
|
|||||||
*
|
*
|
||||||
* This file contains input control logic for the JPEG decompressor.
|
* This file contains input control logic for the JPEG decompressor.
|
||||||
* These routines are concerned with controlling the decompressor's input
|
* These routines are concerned with controlling the decompressor's input
|
||||||
* processing (marker reading and coefficient decoding). The actual input
|
* processing (marker reading and coefficient/difference decoding).
|
||||||
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
|
* The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c,
|
||||||
|
* and jdlhuff.c.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define JPEG_INTERNALS
|
#define JPEG_INTERNALS
|
||||||
@@ -46,6 +49,7 @@ initial_setup(j_decompress_ptr cinfo)
|
|||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
/* Make sure image isn't bigger than I can handle */
|
/* Make sure image isn't bigger than I can handle */
|
||||||
if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION ||
|
if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION ||
|
||||||
@@ -78,36 +82,36 @@ initial_setup(j_decompress_ptr cinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if JPEG_LIB_VERSION >= 80
|
#if JPEG_LIB_VERSION >= 80
|
||||||
cinfo->block_size = DCTSIZE;
|
cinfo->block_size = data_unit;
|
||||||
cinfo->natural_order = jpeg_natural_order;
|
cinfo->natural_order = jpeg_natural_order;
|
||||||
cinfo->lim_Se = DCTSIZE2 - 1;
|
cinfo->lim_Se = DCTSIZE2 - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
|
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE in lossy
|
||||||
* In the full decompressor, this will be overridden by jdmaster.c;
|
* 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.
|
* but in the transcoder, jdmaster.c is not used, so we must do it here.
|
||||||
*/
|
*/
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#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
|
#else
|
||||||
cinfo->min_DCT_scaled_size = DCTSIZE;
|
cinfo->min_DCT_scaled_size = data_unit;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Compute dimensions of components */
|
/* Compute dimensions of components */
|
||||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
ci++, compptr++) {
|
ci++, compptr++) {
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#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
|
#else
|
||||||
compptr->DCT_scaled_size = DCTSIZE;
|
compptr->DCT_scaled_size = data_unit;
|
||||||
#endif
|
#endif
|
||||||
/* Size in DCT blocks */
|
/* Size in data units */
|
||||||
compptr->width_in_blocks = (JDIMENSION)
|
compptr->width_in_blocks = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
|
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)
|
compptr->height_in_blocks = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor,
|
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.
|
/* Set the first and last MCU columns to decompress from multi-scan images.
|
||||||
* By default, decompress all of the MCU columns.
|
* 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. */
|
/* Compute number of fully interleaved MCU rows. */
|
||||||
cinfo->total_iMCU_rows = (JDIMENSION)
|
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->image_height,
|
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 */
|
/* Decide whether file contains multiple scans */
|
||||||
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
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;
|
int ci, mcublks, tmp;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
int data_unit = cinfo->master->lossless ? 1 : DCTSIZE;
|
||||||
|
|
||||||
if (cinfo->comps_in_scan == 1) {
|
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->MCUs_per_row = compptr->width_in_blocks;
|
||||||
cinfo->MCU_rows_in_scan = compptr->height_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_width = 1;
|
||||||
compptr->MCU_height = 1;
|
compptr->MCU_height = 1;
|
||||||
compptr->MCU_blocks = 1;
|
compptr->MCU_blocks = 1;
|
||||||
compptr->MCU_sample_width = compptr->_DCT_scaled_size;
|
compptr->MCU_sample_width = compptr->_DCT_scaled_size;
|
||||||
compptr->last_col_width = 1;
|
compptr->last_col_width = 1;
|
||||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
/* 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);
|
tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
|
||||||
if (tmp == 0) tmp = 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 */
|
/* Overall image size in MCUs */
|
||||||
cinfo->MCUs_per_row = (JDIMENSION)
|
cinfo->MCUs_per_row = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->image_width,
|
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)
|
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||||
jdiv_round_up((long)cinfo->image_height,
|
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;
|
cinfo->blocks_in_MCU = 0;
|
||||||
|
|
||||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||||
compptr = cinfo->cur_comp_info[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_width = compptr->h_samp_factor;
|
||||||
compptr->MCU_height = compptr->v_samp_factor;
|
compptr->MCU_height = compptr->v_samp_factor;
|
||||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||||
compptr->MCU_sample_width = compptr->MCU_width *
|
compptr->MCU_sample_width = compptr->MCU_width *
|
||||||
compptr->_DCT_scaled_size;
|
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);
|
tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
|
||||||
if (tmp == 0) tmp = compptr->MCU_width;
|
if (tmp == 0) tmp = compptr->MCU_width;
|
||||||
compptr->last_col_width = tmp;
|
compptr->last_col_width = tmp;
|
||||||
@@ -281,7 +286,8 @@ METHODDEF(void)
|
|||||||
start_input_pass(j_decompress_ptr cinfo)
|
start_input_pass(j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
per_scan_setup(cinfo);
|
per_scan_setup(cinfo);
|
||||||
latch_quant_tables(cinfo);
|
if (!cinfo->master->lossless)
|
||||||
|
latch_quant_tables(cinfo);
|
||||||
(*cinfo->entropy->start_pass) (cinfo);
|
(*cinfo->entropy->start_pass) (cinfo);
|
||||||
(*cinfo->coef->start_input_pass) (cinfo);
|
(*cinfo->coef->start_input_pass) (cinfo);
|
||||||
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
|
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.
|
* Finish up after inputting a compressed-data scan.
|
||||||
* This is called by the coefficient controller after it's read all
|
* This is called by the coefficient or difference controller after it's read
|
||||||
* the expected data of the scan.
|
* all the expected data of the scan.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF(void)
|
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.
|
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||||
*
|
*
|
||||||
* The consume_input method pointer points either here or to the
|
* The consume_input method pointer points either here or to the
|
||||||
* coefficient controller's consume_data routine, depending on whether
|
* coefficient or difference controller's consume_data routine, depending on
|
||||||
* we are reading a compressed data segment or inter-segment markers.
|
* whether we are reading a compressed data segment or inter-segment markers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
METHODDEF(int)
|
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
|
* 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
|
* buffer; any full-height buffers will be found inside the coefficient,
|
||||||
* postprocessing controllers. Nonetheless, the main controller is not
|
* difference, or postprocessing controllers. Nonetheless, the main controller
|
||||||
* trivial. Its responsibility is to provide context rows for upsampling/
|
* is not trivial. Its responsibility is to provide context rows for
|
||||||
* rescaling, and doing this in an efficient fashion is a bit tricky.
|
* upsampling/rescaling, and doing this in an efficient fashion is a bit
|
||||||
|
* tricky.
|
||||||
*
|
*
|
||||||
* Postprocessor input data is counted in "row groups". A row group
|
* 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)
|
* 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
|
* row group (times any additional scale factor that the upsampler is
|
||||||
* applying).
|
* applying).
|
||||||
*
|
*
|
||||||
* The coefficient controller will deliver data to us one iMCU row at a time;
|
* The coefficient or difference controller will deliver data to us one iMCU
|
||||||
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
|
* row at a time; each iMCU row contains v_samp_factor * DCT_scaled_size sample
|
||||||
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
|
* rows, or exactly min_DCT_scaled_size row groups. (This amount of data
|
||||||
* to one row of MCUs when the image is fully interleaved.) Note that the
|
* corresponds to one row of MCUs when the image is fully interleaved.) Note
|
||||||
* number of sample rows varies across components, but the number of row
|
* that the number of sample rows varies across components, but the number of
|
||||||
* groups does not. Some garbage sample rows may be included in the last iMCU
|
* row groups does not. Some garbage sample rows may be included in the last
|
||||||
* row at the bottom of the image.
|
* iMCU row at the bottom of the image.
|
||||||
*
|
*
|
||||||
* Depending on the vertical scaling algorithm used, the upsampler may need
|
* 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.
|
* 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
|
* 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
|
* 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
|
* obtain one iMCU row at a time from the coefficient or difference controller
|
||||||
* out as row groups to the postprocessor.
|
* and dole it out as row groups to the postprocessor.
|
||||||
*
|
*
|
||||||
* When need_context_rows is TRUE, this controller guarantees that the buffer
|
* 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
|
* 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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2012, 2015, 2022, D. R. Commander.
|
* Copyright (C) 2012, 2015, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
@@ -237,7 +239,8 @@ get_soi(j_decompress_ptr cinfo)
|
|||||||
|
|
||||||
|
|
||||||
LOCAL(boolean)
|
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 */
|
/* Process a SOFn marker */
|
||||||
{
|
{
|
||||||
JLONG length;
|
JLONG length;
|
||||||
@@ -246,6 +249,7 @@ get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
|
|||||||
INPUT_VARS(cinfo);
|
INPUT_VARS(cinfo);
|
||||||
|
|
||||||
cinfo->progressive_mode = is_prog;
|
cinfo->progressive_mode = is_prog;
|
||||||
|
cinfo->master->lossless = is_lossless;
|
||||||
cinfo->arith_code = is_arith;
|
cinfo->arith_code = is_arith;
|
||||||
|
|
||||||
INPUT_2BYTES(cinfo, length, return FALSE);
|
INPUT_2BYTES(cinfo, length, return FALSE);
|
||||||
@@ -990,32 +994,40 @@ read_markers(j_decompress_ptr cinfo)
|
|||||||
|
|
||||||
case M_SOF0: /* Baseline */
|
case M_SOF0: /* Baseline */
|
||||||
case M_SOF1: /* Extended sequential, Huffman */
|
case M_SOF1: /* Extended sequential, Huffman */
|
||||||
if (!get_sof(cinfo, FALSE, FALSE))
|
if (!get_sof(cinfo, FALSE, FALSE, FALSE))
|
||||||
return JPEG_SUSPENDED;
|
return JPEG_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_SOF2: /* Progressive, Huffman */
|
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;
|
return JPEG_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_SOF9: /* Extended sequential, arithmetic */
|
case M_SOF9: /* Extended sequential, arithmetic */
|
||||||
if (!get_sof(cinfo, FALSE, TRUE))
|
if (!get_sof(cinfo, FALSE, FALSE, TRUE))
|
||||||
return JPEG_SUSPENDED;
|
return JPEG_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_SOF10: /* Progressive, arithmetic */
|
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;
|
return JPEG_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Currently unsupported SOFn types */
|
/* Currently unsupported SOFn types */
|
||||||
case M_SOF3: /* Lossless, Huffman */
|
|
||||||
case M_SOF5: /* Differential sequential, Huffman */
|
case M_SOF5: /* Differential sequential, Huffman */
|
||||||
case M_SOF6: /* Differential progressive, Huffman */
|
case M_SOF6: /* Differential progressive, Huffman */
|
||||||
case M_SOF7: /* Differential lossless, Huffman */
|
case M_SOF7: /* Differential lossless, Huffman */
|
||||||
case M_JPG: /* Reserved for JPEG extensions */
|
case M_JPG: /* Reserved for JPEG extensions */
|
||||||
case M_SOF11: /* Lossless, arithmetic */
|
|
||||||
case M_SOF13: /* Differential sequential, arithmetic */
|
case M_SOF13: /* Differential sequential, arithmetic */
|
||||||
case M_SOF14: /* Differential progressive, arithmetic */
|
case M_SOF14: /* Differential progressive, arithmetic */
|
||||||
case M_SOF15: /* Differential lossless, 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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 2002-2009 by Guido Vollbeding.
|
* Modified 2002-2009 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2016, 2019, 2022, D. R. Commander.
|
* Copyright (C) 2009-2011, 2016, 2019, 2022, D. R. Commander.
|
||||||
* Copyright (C) 2013, Linaro Limited.
|
* Copyright (C) 2013, Linaro Limited.
|
||||||
@@ -97,154 +99,154 @@ jpeg_core_output_dimensions(j_decompress_ptr cinfo)
|
|||||||
int ci;
|
int ci;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
|
||||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
if (!cinfo->master->lossless) {
|
||||||
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
|
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||||
/* Provide 1/block_size scaling */
|
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 1/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 1;
|
jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 1;
|
cinfo->_min_DCT_h_scaled_size = 1;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
|
cinfo->_min_DCT_v_scaled_size = 1;
|
||||||
/* Provide 2/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 2/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 2;
|
jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 2;
|
cinfo->_min_DCT_h_scaled_size = 2;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
|
cinfo->_min_DCT_v_scaled_size = 2;
|
||||||
/* Provide 3/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 3/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 3;
|
jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 3;
|
cinfo->_min_DCT_h_scaled_size = 3;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
|
cinfo->_min_DCT_v_scaled_size = 3;
|
||||||
/* Provide 4/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 4/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 4;
|
jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 4;
|
cinfo->_min_DCT_h_scaled_size = 4;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
|
cinfo->_min_DCT_v_scaled_size = 4;
|
||||||
/* Provide 5/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 5/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 5;
|
jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 5;
|
cinfo->_min_DCT_h_scaled_size = 5;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
|
cinfo->_min_DCT_v_scaled_size = 5;
|
||||||
/* Provide 6/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 6/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 6;
|
jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 6;
|
cinfo->_min_DCT_h_scaled_size = 6;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
|
cinfo->_min_DCT_v_scaled_size = 6;
|
||||||
/* Provide 7/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 7/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 7;
|
jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 7;
|
cinfo->_min_DCT_h_scaled_size = 7;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
|
cinfo->_min_DCT_v_scaled_size = 7;
|
||||||
/* Provide 8/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 8/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 8;
|
jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 8;
|
cinfo->_min_DCT_h_scaled_size = 8;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
|
cinfo->_min_DCT_v_scaled_size = 8;
|
||||||
/* Provide 9/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 9/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 9;
|
jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 9;
|
cinfo->_min_DCT_h_scaled_size = 9;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
|
cinfo->_min_DCT_v_scaled_size = 9;
|
||||||
/* Provide 10/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 10/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 10;
|
jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 10;
|
cinfo->_min_DCT_h_scaled_size = 10;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
|
cinfo->_min_DCT_v_scaled_size = 10;
|
||||||
/* Provide 11/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 11/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 11;
|
jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 11;
|
cinfo->_min_DCT_h_scaled_size = 11;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
|
cinfo->_min_DCT_v_scaled_size = 11;
|
||||||
/* Provide 12/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 12/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 12;
|
jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 12;
|
cinfo->_min_DCT_h_scaled_size = 12;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
|
cinfo->_min_DCT_v_scaled_size = 12;
|
||||||
/* Provide 13/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 13/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 13;
|
jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 13;
|
cinfo->_min_DCT_h_scaled_size = 13;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
|
cinfo->_min_DCT_v_scaled_size = 13;
|
||||||
/* Provide 14/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 14/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 14;
|
jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 14;
|
cinfo->_min_DCT_h_scaled_size = 14;
|
||||||
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
|
cinfo->_min_DCT_v_scaled_size = 14;
|
||||||
/* Provide 15/block_size scaling */
|
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 15/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 15;
|
jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 15;
|
cinfo->_min_DCT_h_scaled_size = 15;
|
||||||
} else {
|
cinfo->_min_DCT_v_scaled_size = 15;
|
||||||
/* Provide 16/block_size scaling */
|
} else {
|
||||||
cinfo->output_width = (JDIMENSION)
|
/* Provide 16/block_size scaling */
|
||||||
jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
|
cinfo->output_width = (JDIMENSION)
|
||||||
cinfo->output_height = (JDIMENSION)
|
jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
|
||||||
jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
|
cinfo->output_height = (JDIMENSION)
|
||||||
cinfo->_min_DCT_h_scaled_size = 16;
|
jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
|
||||||
cinfo->_min_DCT_v_scaled_size = 16;
|
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
|
#ifdef IDCT_SCALING_SUPPORTED
|
||||||
|
|
||||||
/* In selecting the actual DCT scaling for each component, we try to
|
if (!cinfo->master->lossless) {
|
||||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
/* In selecting the actual DCT scaling for each component, we try to
|
||||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||||
* Note this code adapts subsampling ratios which are powers of 2.
|
* 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++) {
|
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||||
int ssize = cinfo->_min_DCT_scaled_size;
|
ci++, compptr++) {
|
||||||
while (ssize < DCTSIZE &&
|
int ssize = cinfo->_min_DCT_scaled_size;
|
||||||
((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) %
|
while (ssize < DCTSIZE &&
|
||||||
(compptr->h_samp_factor * ssize * 2) == 0) &&
|
((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||||
((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) %
|
(compptr->h_samp_factor * ssize * 2) == 0) &&
|
||||||
(compptr->v_samp_factor * ssize * 2) == 0)) {
|
((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) %
|
||||||
ssize = ssize * 2;
|
(compptr->v_samp_factor * ssize * 2) == 0)) {
|
||||||
}
|
ssize = ssize * 2;
|
||||||
|
}
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#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
|
#else
|
||||||
compptr->DCT_scaled_size = ssize;
|
compptr->DCT_scaled_size = ssize;
|
||||||
#endif
|
#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 */
|
#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. */
|
/* Report number of components in selected colorspace. */
|
||||||
/* Probably this should be in the color conversion module... */
|
/* Probably this should be in the color conversion module... */
|
||||||
@@ -478,6 +482,17 @@ master_selection(j_decompress_ptr cinfo)
|
|||||||
long samplesperrow;
|
long samplesperrow;
|
||||||
JDIMENSION jd_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 */
|
/* Initialize dimensions and other stuff */
|
||||||
jpeg_calc_output_dimensions(cinfo);
|
jpeg_calc_output_dimensions(cinfo);
|
||||||
prepare_range_limit_table(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 */
|
||||||
/* Post-processing: in particular, color conversion first */
|
if (!cinfo->raw_data_out) {
|
||||||
if (!cinfo->raw_data_out) {
|
if (master->using_merged_upsample) {
|
||||||
if (master->using_merged_upsample) {
|
|
||||||
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||||
|
if (cinfo->data_precision == 12)
|
||||||
j12init_merged_upsampler(cinfo); /* does color conversion too */
|
j12init_merged_upsampler(cinfo); /* does color conversion too */
|
||||||
#else
|
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
|
|
||||||
jinit_merged_upsampler(cinfo); /* does color conversion too */
|
jinit_merged_upsampler(cinfo); /* does color conversion too */
|
||||||
#else
|
#else
|
||||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
if (cinfo->data_precision == 12) {
|
||||||
|
j12init_color_deconverter(cinfo);
|
||||||
|
j12init_upsampler(cinfo);
|
||||||
} else {
|
} else {
|
||||||
jinit_color_deconverter(cinfo);
|
jinit_color_deconverter(cinfo);
|
||||||
jinit_upsampler(cinfo);
|
jinit_upsampler(cinfo);
|
||||||
}
|
}
|
||||||
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
|
||||||
}
|
}
|
||||||
/* Inverse DCT */
|
if (cinfo->data_precision == 12)
|
||||||
jinit_inverse_dct(cinfo);
|
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) {
|
if (cinfo->master->lossless) {
|
||||||
#ifdef D_ARITH_CODING_SUPPORTED
|
#ifdef D_LOSSLESS_SUPPORTED
|
||||||
jinit_arith_decoder(cinfo);
|
/* 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
|
#else
|
||||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (cinfo->progressive_mode) {
|
/* Inverse DCT */
|
||||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
if (cinfo->data_precision == 12)
|
||||||
jinit_phuff_decoder(cinfo);
|
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
|
#else
|
||||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||||
#endif
|
#endif
|
||||||
} else
|
} else {
|
||||||
jinit_huff_decoder(cinfo);
|
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. */
|
if (!cinfo->raw_data_out) {
|
||||||
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
if (cinfo->data_precision == 12)
|
||||||
if (cinfo->data_precision == 12) {
|
|
||||||
j12init_d_coef_controller(cinfo, use_c_buffer);
|
|
||||||
|
|
||||||
if (!cinfo->raw_data_out)
|
|
||||||
j12init_d_main_controller(cinfo,
|
j12init_d_main_controller(cinfo,
|
||||||
FALSE /* never need full buffer here */);
|
FALSE /* never need full buffer here */);
|
||||||
} else {
|
else
|
||||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
|
||||||
|
|
||||||
if (!cinfo->raw_data_out)
|
|
||||||
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2015-2016, 2018-2022, D. R. Commander.
|
* Copyright (C) 2015-2016, 2018-2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
#define JPEG_INTERNALS
|
#define JPEG_INTERNALS
|
||||||
#include "jinclude.h"
|
#include "jinclude.h"
|
||||||
#include "jpeglib.h"
|
#include "jpeglib.h"
|
||||||
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
|
#include "jdhuff.h" /* Declarations shared with jd*huff.c */
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo);
|
|||||||
GLOBAL(jvirt_barray_ptr *)
|
GLOBAL(jvirt_barray_ptr *)
|
||||||
jpeg_read_coefficients(j_decompress_ptr cinfo)
|
jpeg_read_coefficients(j_decompress_ptr cinfo)
|
||||||
{
|
{
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||||
|
|
||||||
if (cinfo->global_state == DSTATE_READY) {
|
if (cinfo->global_state == DSTATE_READY) {
|
||||||
/* First call: initialize active modules */
|
/* First call: initialize active modules */
|
||||||
transdecode_master_selection(cinfo);
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||||
* Modified 1997-2009 by Guido Vollbeding.
|
* Modified 1997-2009 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2014, 2017, 2021-2022, D. R. Commander.
|
* Copyright (C) 2014, 2017, 2021-2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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
|
#if JPEG_LIB_VERSION >= 70
|
||||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||||
#endif
|
#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")
|
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#if JPEG_LIB_VERSION >= 70
|
||||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
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_POOL_ID, "Invalid memory pool code %d")
|
||||||
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||||
JMESSAGE(JERR_BAD_PROGRESSION,
|
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,
|
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_SAMPLING, "Bogus sampling factors")
|
||||||
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||||
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||||
@@ -180,7 +183,7 @@ JMESSAGE(JTRC_THUMB_PALETTE,
|
|||||||
JMESSAGE(JTRC_THUMB_RGB,
|
JMESSAGE(JTRC_THUMB_RGB,
|
||||||
"JFIF extension marker: RGB thumbnail image, length %u")
|
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
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_CLOSE, "Freed XMS handle %u")
|
||||||
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||||
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
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,
|
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||||
#endif
|
#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
|
#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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 1997-2009 by Guido Vollbeding.
|
* Modified 1997-2009 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, D. R. Commander.
|
* Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* 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_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||||
|
#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */
|
||||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||||
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
|
/* 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
|
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||||
* precision, so jchuff.c normally uses entropy optimization to compute
|
* precision, so jchuff.c normally uses entropy optimization to compute
|
||||||
* usable tables for higher precision. If you don't want to do optimization,
|
* usable tables for higher precision. If you don't want to do optimization,
|
||||||
* you'll have to supply different default Huffman tables.
|
* you'll have to supply different default Huffman tables.
|
||||||
* The exact same statements apply for progressive JPEG: the default tables
|
* The exact same statements apply for progressive and lossless JPEG:
|
||||||
* don't work for progressive mode. (This may get fixed, however.)
|
* 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? */
|
#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_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||||
|
#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */
|
||||||
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
|
#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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 1997-2009 by Guido Vollbeding.
|
* Modified 1997-2009 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2015-2016, 2019, 2021-2022, D. R. Commander.
|
* Copyright (C) 2015-2016, 2019, 2021-2022, D. R. Commander.
|
||||||
* Copyright (C) 2015, Google, Inc.
|
* 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 */
|
/* Declarations for both compression & decompression */
|
||||||
|
|
||||||
typedef enum { /* Operating modes for buffer controllers */
|
typedef enum { /* Operating modes for buffer controllers */
|
||||||
@@ -80,6 +93,7 @@ struct jpeg_comp_master {
|
|||||||
/* State variables made visible to other modules */
|
/* State variables made visible to other modules */
|
||||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||||
boolean is_last_pass; /* True during last pass */
|
boolean is_last_pass; /* True during last pass */
|
||||||
|
boolean lossless; /* True if lossless mode is enabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Main buffer control (downsampled-data buffer) */
|
/* Main buffer control (downsampled-data buffer) */
|
||||||
@@ -107,7 +121,9 @@ struct jpeg_c_prep_controller {
|
|||||||
JDIMENSION out_row_groups_avail);
|
JDIMENSION out_row_groups_avail);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Coefficient buffer control */
|
/* Lossy mode: Coefficient buffer control
|
||||||
|
* Lossless mode: Difference buffer control
|
||||||
|
*/
|
||||||
struct jpeg_c_coef_controller {
|
struct jpeg_c_coef_controller {
|
||||||
void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode);
|
void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode);
|
||||||
boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
|
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 */
|
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 {
|
struct jpeg_forward_dct {
|
||||||
void (*start_pass) (j_compress_ptr cinfo);
|
void (*start_pass) (j_compress_ptr cinfo);
|
||||||
|
|
||||||
|
/* Lossy mode */
|
||||||
/* perhaps this should be an array??? */
|
/* perhaps this should be an array??? */
|
||||||
void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr,
|
void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||||
@@ -155,7 +175,14 @@ struct jpeg_forward_dct {
|
|||||||
/* Entropy encoding */
|
/* Entropy encoding */
|
||||||
struct jpeg_entropy_encoder {
|
struct jpeg_entropy_encoder {
|
||||||
void (*start_pass) (j_compress_ptr cinfo, boolean gather_statistics);
|
void (*start_pass) (j_compress_ptr cinfo, boolean gather_statistics);
|
||||||
|
|
||||||
|
/* Lossy mode */
|
||||||
boolean (*encode_mcu) (j_compress_ptr cinfo, JBLOCKROW *MCU_data);
|
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);
|
void (*finish_pass) (j_compress_ptr cinfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,6 +210,7 @@ struct jpeg_decomp_master {
|
|||||||
|
|
||||||
/* State variables made visible to other modules */
|
/* State variables made visible to other modules */
|
||||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||||
|
boolean lossless; /* True if decompressing a lossless image */
|
||||||
|
|
||||||
/* Partial decompression variables */
|
/* Partial decompression variables */
|
||||||
JDIMENSION first_iMCU_col;
|
JDIMENSION first_iMCU_col;
|
||||||
@@ -216,13 +244,25 @@ struct jpeg_d_main_controller {
|
|||||||
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
|
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 {
|
struct jpeg_d_coef_controller {
|
||||||
void (*start_input_pass) (j_decompress_ptr cinfo);
|
void (*start_input_pass) (j_decompress_ptr cinfo);
|
||||||
int (*consume_data) (j_decompress_ptr cinfo);
|
int (*consume_data) (j_decompress_ptr cinfo);
|
||||||
void (*start_output_pass) (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) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
|
||||||
int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE 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 */
|
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||||
jvirt_barray_ptr *coef_arrays;
|
jvirt_barray_ptr *coef_arrays;
|
||||||
};
|
};
|
||||||
@@ -266,14 +306,24 @@ struct jpeg_marker_reader {
|
|||||||
/* Entropy decoding */
|
/* Entropy decoding */
|
||||||
struct jpeg_entropy_decoder {
|
struct jpeg_entropy_decoder {
|
||||||
void (*start_pass) (j_decompress_ptr cinfo);
|
void (*start_pass) (j_decompress_ptr cinfo);
|
||||||
|
|
||||||
|
/* Lossy mode */
|
||||||
boolean (*decode_mcu) (j_decompress_ptr cinfo, JBLOCKROW *MCU_data);
|
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; */
|
/* This is here to share code between baseline and progressive decoders; */
|
||||||
/* other modules probably should not use it */
|
/* other modules probably should not use it */
|
||||||
boolean insufficient_data; /* set TRUE after emitting warning */
|
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,
|
typedef void (*inverse_DCT_method_ptr) (j_decompress_ptr cinfo,
|
||||||
jpeg_component_info *compptr,
|
jpeg_component_info *compptr,
|
||||||
JCOEFPTR coef_block,
|
JCOEFPTR coef_block,
|
||||||
@@ -287,6 +337,8 @@ typedef void (*inverse_DCT_12_method_ptr) (j_decompress_ptr cinfo,
|
|||||||
|
|
||||||
struct jpeg_inverse_dct {
|
struct jpeg_inverse_dct {
|
||||||
void (*start_pass) (j_decompress_ptr cinfo);
|
void (*start_pass) (j_decompress_ptr cinfo);
|
||||||
|
|
||||||
|
/* Lossy mode */
|
||||||
/* It is useful to allow each component to have a separate IDCT method. */
|
/* It is useful to allow each component to have a separate IDCT method. */
|
||||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||||
inverse_DCT_12_method_ptr inverse_DCT_12[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_phuff_encoder(j_compress_ptr cinfo);
|
||||||
EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
|
EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
|
||||||
EXTERN(void) jinit_marker_writer(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 */
|
/* Decompression module initialization routines */
|
||||||
EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo);
|
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) j12init_2pass_quantizer(j_decompress_ptr cinfo);
|
||||||
EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
|
EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
|
||||||
EXTERN(void) j12init_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 */
|
/* Memory manager initialization */
|
||||||
EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo);
|
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:
|
* This file was part of the Independent JPEG Group's software:
|
||||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||||
* Modified 2002-2009 by Guido Vollbeding.
|
* Modified 2002-2009 by Guido Vollbeding.
|
||||||
|
* Lossless JPEG Modifications:
|
||||||
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022, D. R. Commander.
|
* Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022, D. R. Commander.
|
||||||
* Copyright (C) 2015, Google, Inc.
|
* Copyright (C) 2015, Google, Inc.
|
||||||
@@ -43,6 +45,13 @@ extern "C" {
|
|||||||
* if you want to be compatible.
|
* 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 DCTSIZE 8 /* The basic DCT block is 8x8 samples */
|
||||||
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
|
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
|
||||||
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
|
#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
|
* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
|
||||||
* sometimes emits noncompliant files doesn't mean you should too.
|
* 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
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -142,17 +151,20 @@ typedef struct {
|
|||||||
/* Remaining fields should be treated as private by applications. */
|
/* Remaining fields should be treated as private by applications. */
|
||||||
|
|
||||||
/* These values are computed during compression or decompression startup: */
|
/* These values are computed during compression or decompression startup: */
|
||||||
/* Component's size in DCT blocks.
|
/* Component's size in data units.
|
||||||
* Any dummy blocks added to complete an MCU are not counted; therefore
|
* In lossy mode, any dummy blocks added to complete an MCU are not counted;
|
||||||
* these values do not depend on whether a scan is interleaved or not.
|
* 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 width_in_blocks;
|
||||||
JDIMENSION height_in_blocks;
|
JDIMENSION height_in_blocks;
|
||||||
/* Size of a DCT block in samples. Always DCTSIZE for compression.
|
/* Size of a data unit in samples. Always DCTSIZE for lossy compression.
|
||||||
* For decompression this is the size of the output from one DCT block,
|
* 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.
|
* reflecting any scaling we choose to apply during the IDCT step.
|
||||||
* Values from 1 to 16 are supported.
|
* Values from 1 to 16 are supported. Note that different components may
|
||||||
* Note that different components may receive different IDCT scalings.
|
* receive different IDCT scalings. In lossless mode, this is always equal
|
||||||
|
* to 1.
|
||||||
*/
|
*/
|
||||||
#if JPEG_LIB_VERSION >= 70
|
#if JPEG_LIB_VERSION >= 70
|
||||||
int DCT_h_scaled_size;
|
int DCT_h_scaled_size;
|
||||||
@@ -163,8 +175,10 @@ typedef struct {
|
|||||||
/* The downsampled dimensions are the component's actual, unpadded number
|
/* The downsampled dimensions are the component's actual, unpadded number
|
||||||
* of samples at the main buffer (preprocessing/compression interface), thus
|
* of samples at the main buffer (preprocessing/compression interface), thus
|
||||||
* downsampled_width = ceil(image_width * Hi/Hmax)
|
* 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)
|
* 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_width; /* actual width in samples */
|
||||||
JDIMENSION downsampled_height; /* actual height 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. */
|
/* These values are computed before starting a scan of the component. */
|
||||||
/* The decompressor output side may not use these variables. */
|
/* The decompressor output side may not use these variables. */
|
||||||
int MCU_width; /* number of blocks per MCU, horizontally */
|
int MCU_width; /* number of data units per MCU, horizontally */
|
||||||
int MCU_height; /* number of blocks per MCU, vertically */
|
int MCU_height; /* number of data units per MCU, vertically */
|
||||||
int MCU_blocks; /* MCU_width * MCU_height */
|
int MCU_blocks; /* MCU_width * MCU_height */
|
||||||
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */
|
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_col_width; /* # of non-dummy data units across in last MCU */
|
||||||
int last_row_height; /* # of non-dummy blocks down 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.
|
/* Saved quantization table for component; NULL if none yet saved.
|
||||||
* See jdinput.c comments about the need for this information.
|
* See jdinput.c comments about the need for this information.
|
||||||
@@ -199,8 +213,12 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int comps_in_scan; /* number of components encoded in this scan */
|
int comps_in_scan; /* number of components encoded in this scan */
|
||||||
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
|
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
|
||||||
int Ss, Se; /* progressive JPEG spectral selection parms */
|
int Ss, Se; /* progressive JPEG spectral selection parms
|
||||||
int Ah, Al; /* progressive JPEG successive approx. 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;
|
} jpeg_scan_info;
|
||||||
|
|
||||||
/* The decompressor can save APPn and COM markers in a list of these: */
|
/* 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 */
|
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
|
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or
|
||||||
/* The coefficient controller receives data in units of MCU rows as defined
|
difference controller */
|
||||||
* for fully interleaved scans (whether the JPEG file is interleaved or not).
|
/* The coefficient or difference controller receives data in units of MCU
|
||||||
* There are v_samp_factor * DCTSIZE sample rows of each component in an
|
* rows as defined for fully interleaved scans (whether the JPEG file is
|
||||||
* "iMCU" (interleaved MCU) row.
|
* 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 MCUs_per_row; /* # of MCUs across the image */
|
||||||
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in 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];
|
int MCU_membership[C_MAX_BLOCKS_IN_MCU];
|
||||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
/* 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
|
#if JPEG_LIB_VERSION >= 80
|
||||||
int block_size; /* the basic DCT block size: 1..16 */
|
int block_size; /* the basic DCT block size: 1..16 */
|
||||||
@@ -658,12 +679,13 @@ struct jpeg_decompress_struct {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
|
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
|
||||||
/* The coefficient controller's input and output progress is measured in
|
/* The coefficient or difference controller's input and output progress is
|
||||||
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
|
* measured in units of "iMCU" (interleaved MCU) rows. These are the same as
|
||||||
* in fully interleaved JPEG scans, but are used whether the scan is
|
* 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
|
* interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor
|
||||||
* rows of each component. Therefore, the IDCT output contains
|
* 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.
|
* 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
|
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 MCUs_per_row; /* # of MCUs across the image */
|
||||||
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in 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];
|
int MCU_membership[D_MAX_BLOCKS_IN_MCU];
|
||||||
/* MCU_membership[i] is index in cur_comp_info of component owning */
|
/* 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
|
#if JPEG_LIB_VERSION >= 80
|
||||||
/* These fields are derived from Se of first SOS marker.
|
/* 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,
|
const unsigned int *basic_table,
|
||||||
int scale_factor, boolean force_baseline);
|
int scale_factor, boolean force_baseline);
|
||||||
EXTERN(int) jpeg_quality_scaling(int quality);
|
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_simple_progression(j_compress_ptr cinfo);
|
||||||
EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
|
EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
|
||||||
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
|
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
|
||||||
|
|||||||
@@ -73,6 +73,10 @@
|
|||||||
#define _jinit_color_converter j12init_color_converter
|
#define _jinit_color_converter j12init_color_converter
|
||||||
#define _jinit_downsampler j12init_downsampler
|
#define _jinit_downsampler j12init_downsampler
|
||||||
#define _jinit_forward_dct j12init_forward_dct
|
#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_main_controller j12init_d_main_controller
|
||||||
#define _jinit_d_coef_controller j12init_d_coef_controller
|
#define _jinit_d_coef_controller j12init_d_coef_controller
|
||||||
@@ -83,6 +87,10 @@
|
|||||||
#define _jinit_1pass_quantizer j12init_1pass_quantizer
|
#define _jinit_1pass_quantizer j12init_1pass_quantizer
|
||||||
#define _jinit_2pass_quantizer j12init_2pass_quantizer
|
#define _jinit_2pass_quantizer j12init_2pass_quantizer
|
||||||
#define _jinit_merged_upsampler j12init_merged_upsampler
|
#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
|
#define _jcopy_sample_rows j12copy_sample_rows
|
||||||
|
|
||||||
@@ -180,6 +188,10 @@
|
|||||||
#define _jinit_color_converter jinit_color_converter
|
#define _jinit_color_converter jinit_color_converter
|
||||||
#define _jinit_downsampler jinit_downsampler
|
#define _jinit_downsampler jinit_downsampler
|
||||||
#define _jinit_forward_dct jinit_forward_dct
|
#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_main_controller jinit_d_main_controller
|
||||||
#define _jinit_d_coef_controller jinit_d_coef_controller
|
#define _jinit_d_coef_controller jinit_d_coef_controller
|
||||||
@@ -190,6 +202,10 @@
|
|||||||
#define _jinit_1pass_quantizer jinit_1pass_quantizer
|
#define _jinit_1pass_quantizer jinit_1pass_quantizer
|
||||||
#define _jinit_2pass_quantizer jinit_2pass_quantizer
|
#define _jinit_2pass_quantizer jinit_2pass_quantizer
|
||||||
#define _jinit_merged_upsampler jinit_merged_upsampler
|
#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
|
#define _jcopy_sample_rows jcopy_sample_rows
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
|
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
|
||||||
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
|
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
|
||||||
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
|
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
|
||||||
|
"Copyright (C) 1999 Ken Murchison\n" \
|
||||||
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
|
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
|
||||||
|
|
||||||
#define JCOPYRIGHT_SHORT \
|
#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:
|
This file was part of the Independent JPEG Group's software:
|
||||||
Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding.
|
Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding.
|
||||||
|
Lossless JPEG Modifications:
|
||||||
|
Copyright (C) 1999, Ken Murchison.
|
||||||
libjpeg-turbo Modifications:
|
libjpeg-turbo Modifications:
|
||||||
Copyright (C) 2010, 2014-2018, 2020, 2022, D. R. Commander.
|
Copyright (C) 2010, 2014-2018, 2020, 2022, D. R. Commander.
|
||||||
Copyright (C) 2015, Google, Inc.
|
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
|
JPEG processes are supported. (Our subset includes all features now in common
|
||||||
use.) Unsupported ISO options include:
|
use.) Unsupported ISO options include:
|
||||||
* Hierarchical storage
|
* Hierarchical storage
|
||||||
* Lossless JPEG
|
|
||||||
* DNL marker
|
* DNL marker
|
||||||
* Nonintegral subsampling ratios
|
* Nonintegral subsampling ratios
|
||||||
We support both 8- and 12-bit data precision.
|
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
|
unless you want to make a custom scan sequence. You must ensure that
|
||||||
the JPEG color space is set correctly before calling this routine.
|
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:
|
Compression parameters (cinfo fields) include:
|
||||||
|
|
||||||
@@ -1061,15 +1085,15 @@ boolean optimize_coding
|
|||||||
unsigned int restart_interval
|
unsigned int restart_interval
|
||||||
int restart_in_rows
|
int restart_in_rows
|
||||||
To emit restart markers in the JPEG file, set one of these nonzero.
|
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_interval to specify the exact interval in MCU blocks
|
||||||
Set restart_in_rows to specify the interval in MCU rows. (If
|
(samples in lossless mode). Set restart_in_rows to specify the
|
||||||
restart_in_rows is not 0, then restart_interval is set after the
|
interval in MCU rows. (If restart_in_rows is not 0, then
|
||||||
image width in MCUs is computed.) Defaults are zero (no restarts).
|
restart_interval is set after the image width in MCUs is computed.)
|
||||||
One restart marker per MCU row is often a good choice.
|
Defaults are zero (no restarts). One restart marker per MCU row is
|
||||||
NOTE: the overhead of restart markers is higher in grayscale JPEG
|
often a good choice. NOTE: the overhead of restart markers is higher
|
||||||
files than in color files, and MUCH higher in progressive JPEGs.
|
in grayscale JPEG files than in color files, and MUCH higher in
|
||||||
If you use restarts, you may want to use larger intervals in those
|
progressive JPEGs. If you use restarts, you may want to use larger
|
||||||
cases.
|
intervals in those cases.
|
||||||
|
|
||||||
const jpeg_scan_info *scan_info
|
const jpeg_scan_info *scan_info
|
||||||
int num_scans
|
int num_scans
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ IJG JPEG LIBRARY: SYSTEM ARCHITECTURE
|
|||||||
|
|
||||||
This file was part of the Independent JPEG Group's software:
|
This file was part of the Independent JPEG Group's software:
|
||||||
Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
|
Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
|
||||||
It was modified by The libjpeg-turbo Project to include only information
|
Lossless JPEG Modifications:
|
||||||
relevant to libjpeg-turbo.
|
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.
|
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 "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 "coefficient" is a frequency coefficient (a DCT transform output number).
|
||||||
A "block" is an 8x8 group of samples or coefficients.
|
A "block" is an 8x8 group of samples or coefficients.
|
||||||
An "MCU" (minimum coded unit) is an interleaved set of blocks of size
|
A "data unit" is an abstract data type that is either a block for lossy
|
||||||
determined by the sampling factors, or a single block in a
|
(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.
|
noninterleaved scan.
|
||||||
We do not use the terms "pixel" and "sample" interchangeably. When we say
|
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
|
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.
|
formats. This document concentrates on the library itself.
|
||||||
|
|
||||||
We desire the library to be capable of supporting all JPEG baseline, extended
|
We desire the library to be capable of supporting all JPEG baseline, extended
|
||||||
sequential, and progressive DCT processes. Hierarchical processes are not
|
sequential, progressive DCT, and lossless (spatial) processes. Hierarchical
|
||||||
supported.
|
processes are not supported.
|
||||||
|
|
||||||
The library does not support the lossless (spatial) JPEG process. Lossless
|
|
||||||
JPEG shares little or no code with lossy JPEG, and would normally be used
|
|
||||||
without the extensive pre- and post-processing provided by this library.
|
|
||||||
We feel that lossless JPEG is better handled by a separate library.
|
|
||||||
|
|
||||||
Within these limits, any set of compression parameters allowed by the JPEG
|
Within these limits, any set of compression parameters allowed by the JPEG
|
||||||
spec should be readable for decompression. (We can be more restrictive about
|
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).
|
* Color space conversion (e.g., RGB to YCbCr).
|
||||||
* Edge expansion and downsampling. Optionally, this step can do simple
|
* Edge expansion and downsampling. Optionally, this step can do simple
|
||||||
smoothing --- this is often helpful for low-quality source data.
|
smoothing --- this is often helpful for low-quality source data.
|
||||||
JPEG proper:
|
Lossy JPEG proper:
|
||||||
* MCU assembly, DCT, quantization.
|
* MCU assembly, DCT, quantization.
|
||||||
* Entropy coding (sequential or progressive, Huffman or arithmetic).
|
* 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,
|
In addition to these modules we need overall control, marker generation,
|
||||||
and support code (memory management & error handling). There is also a
|
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:
|
The decompressor library contains the following main elements:
|
||||||
|
|
||||||
JPEG proper:
|
Lossy JPEG proper:
|
||||||
* Entropy decoding (sequential or progressive, Huffman or arithmetic).
|
* Entropy decoding (sequential or progressive, Huffman or arithmetic).
|
||||||
* Dequantization, inverse DCT, MCU disassembly.
|
* Dequantization, inverse DCT, MCU disassembly.
|
||||||
|
Lossless JPEG proper:
|
||||||
|
* Entropy decoding (Huffman or arithmetic).
|
||||||
|
* Prediction, undifferencing.
|
||||||
|
* Point transform, sample size scaling.
|
||||||
Postprocessing:
|
Postprocessing:
|
||||||
* Upsampling. Optionally, this step may be able to do more general
|
* Upsampling. Optionally, this step may be able to do more general
|
||||||
rescaling of the image.
|
rescaling of the image.
|
||||||
@@ -280,7 +287,8 @@ task performed by any one controller.
|
|||||||
|
|
||||||
*** Compression object structure ***
|
*** 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
|
|-- Colorspace conversion
|
||||||
|-- Preprocessing controller --|
|
|-- Preprocessing controller --|
|
||||||
@@ -290,6 +298,19 @@ Main controller --|
|
|||||||
|-- Coefficient controller --|
|
|-- Coefficient controller --|
|
||||||
|-- Entropy encoding
|
|-- 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
|
This sketch also describes the flow of control (subroutine calls) during
|
||||||
typical image data processing. Each of the components shown in the diagram is
|
typical image data processing. Each of the components shown in the diagram is
|
||||||
an "object" which may have several different implementations available. One
|
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
|
during each pass, and the coder must emit the appropriate subset of
|
||||||
coefficients.
|
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
|
In addition to the above objects, the compression library includes these
|
||||||
objects:
|
objects:
|
||||||
|
|
||||||
@@ -383,7 +420,8 @@ decompression; the progress monitor, if used, may be shared as well.
|
|||||||
|
|
||||||
*** Decompression object structure ***
|
*** 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
|
|-- Entropy decoding
|
||||||
|-- Coefficient controller --|
|
|-- Coefficient controller --|
|
||||||
@@ -394,6 +432,21 @@ Main controller --|
|
|||||||
|-- Color quantization
|
|-- Color quantization
|
||||||
|-- Color precision reduction
|
|-- 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
|
As before, this diagram also represents typical control flow. The objects
|
||||||
shown are:
|
shown are:
|
||||||
|
|
||||||
@@ -427,6 +480,22 @@ shown are:
|
|||||||
that emit fewer samples per DCT block, not the full 8x8. Works on one DCT
|
that emit fewer samples per DCT block, not the full 8x8. Works on one DCT
|
||||||
block at a time.
|
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
|
* Postprocessing controller: buffer controller for the color quantization
|
||||||
input buffer, when quantization is in use. (Without quantization, this
|
input buffer, when quantization is in use. (Without quantization, this
|
||||||
controller just calls the upsampler.) For two-pass 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:
|
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
|
-arithmetic Use arithmetic coding. CAUTION: arithmetic coded JPEG
|
||||||
is not yet widely implemented, so many decoders will
|
is not yet widely implemented, so many decoders will
|
||||||
be unable to view an arithmetic coded JPEG file at
|
be unable to view an arithmetic coded JPEG file at
|
||||||
@@ -207,8 +232,9 @@ Switches for advanced users:
|
|||||||
same results on all machines.
|
same results on all machines.
|
||||||
|
|
||||||
-restart N Emit a JPEG restart marker every N MCU rows, or every
|
-restart N Emit a JPEG restart marker every N MCU rows, or every
|
||||||
N MCU blocks if "B" is attached to the number.
|
N MCU blocks (samples in lossless mode) if "B" is
|
||||||
-restart 0 (the default) means no restart markers.
|
attached to the number. -restart 0 (the default) means
|
||||||
|
no restart markers.
|
||||||
|
|
||||||
-smooth N Smooth the input image to eliminate dithering noise.
|
-smooth N Smooth the input image to eliminate dithering noise.
|
||||||
N, ranging from 1 to 100, indicates the strength of
|
N, ranging from 1 to 100, indicates the strength of
|
||||||
|
|||||||
@@ -128,3 +128,4 @@ EXPORTS
|
|||||||
jpeg12_write_scanlines @ 127 ;
|
jpeg12_write_scanlines @ 127 ;
|
||||||
jpeg12_skip_scanlines @ 128 ;
|
jpeg12_skip_scanlines @ 128 ;
|
||||||
jpeg12_crop_scanline @ 129 ;
|
jpeg12_crop_scanline @ 129 ;
|
||||||
|
jpeg_enable_lossless @ 130 ;
|
||||||
|
|||||||
@@ -130,3 +130,4 @@ EXPORTS
|
|||||||
jpeg12_write_scanlines @ 129 ;
|
jpeg12_write_scanlines @ 129 ;
|
||||||
jpeg12_skip_scanlines @ 130 ;
|
jpeg12_skip_scanlines @ 130 ;
|
||||||
jpeg12_crop_scanline @ 131 ;
|
jpeg12_crop_scanline @ 131 ;
|
||||||
|
jpeg_enable_lossless @ 132 ;
|
||||||
|
|||||||
@@ -131,3 +131,4 @@ EXPORTS
|
|||||||
jpeg12_write_scanlines @ 130 ;
|
jpeg12_write_scanlines @ 130 ;
|
||||||
jpeg12_skip_scanlines @ 131 ;
|
jpeg12_skip_scanlines @ 131 ;
|
||||||
jpeg12_crop_scanline @ 132 ;
|
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
|
By default, cjpeg emits a single-scan sequential JPEG file. The
|
||||||
-progressive switch generates a progressive JPEG file using a default series
|
-progressive switch generates a progressive JPEG file using a default series
|
||||||
of progression parameters. You can create multiple-scan sequential JPEG
|
of progression parameters. You can create multiple-scan sequential or lossless
|
||||||
files or progressive JPEG files with custom progression parameters by using
|
JPEG files or progressive JPEG files with custom progression parameters by
|
||||||
the -scans switch:
|
using the -scans switch:
|
||||||
|
|
||||||
-scans file Use the scan sequence given in the named file.
|
-scans file Use the scan sequence given in the named file.
|
||||||
|
|
||||||
The specified file should be a text file containing a "scan script".
|
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.
|
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
|
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
|
the components to be included in the scan, and for progressive and lossless
|
||||||
specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan
|
JPEG it also specifies the progression/lossless parameters Ss,Se,Ah,Al for the
|
||||||
definitions are separated by semicolons (';'). A semicolon after the last
|
scan. Scan definitions are separated by semicolons (';'). A semicolon after
|
||||||
scan definition is optional.
|
the last scan definition is optional.
|
||||||
|
|
||||||
Each scan definition contains one to four component indexes, optionally
|
Each scan definition contains one to four component indexes, optionally
|
||||||
followed by a colon (':') and the four progressive-JPEG parameters. The
|
followed by a colon (':') and the four progressive/lossless-JPEG parameters.
|
||||||
component indexes denote which color component(s) are to be transmitted in
|
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
|
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
|
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
|
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
|
Se Zigzag index of last coefficient included in scan
|
||||||
Ah Zero for first scan of a coefficient, else Al of prior scan
|
Ah Zero for first scan of a coefficient, else Al of prior scan
|
||||||
Al Successive approximation low bit position for 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
|
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
|
Ss and Se values other than 0 and 63 appear. cjpeg also automatically
|
||||||
not needed to specify this; in fact, it is ignored when -scans appears.)
|
determines whether the script represents a lossless file, by observing whether
|
||||||
The scan script must meet the JPEG restrictions on progression sequences.
|
Ss (the predictor selection value) is non-zero and Se is zero, which are
|
||||||
(cjpeg checks that the spec's requirements are obeyed.) More specifically:
|
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.
|
* An AC scan cannot include coefficients from more than one component.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user