TurboJPEG: Fix 12-bit-per-sample arith-coded compr
(Regression introduced by7bb958b732) Because of7bb958b732, the TurboJPEG compression and encoding functions no longer transfer the value of TJPARAM_OPTIMIZE into cinfo->data_precision unless the data precision is 8. The intent of that was to prevent using_std_huff_tables() from being called more than once when reusing the same compressor object to generate multiple 12-bit-per-sample JPEG images. However, because cinfo->optimize_coding is always set to TRUE by jpeg_set_defaults() if the data precision is 12, calling applications that use 12-bit data precision had to unset cinfo->optimize_coding if they set cinfo->arith_code after calling jpeg_set_defaults(). Because of7bb958b732, the TurboJPEG API stopped doing that except with 8-bit data precision. Thus, attempting to generate a 12-bit-per-sample arithmetic-coded lossy JPEG image using the TurboJPEG API failed with "Requested features are incompatible." Since the compressor will always fail if cinfo->arith_code and cinfo->optimize_coding are both set, and since cinfo->optimize_coding has no relevance for arithmetic coding, the most robust and user-proof solution is for jinit_c_master_control() to set cinfo->optimize_coding to FALSE if cinfo->arith_code is TRUE. This commit also: - modifies TJBench so that it no longer reports that it is using optimized baseline entropy coding in modes where that setting is irrelevant, - amends the cjpeg documentation to clarify that -optimize is implied when specifying -progressive or '-precision 12' without -arithmetic, and - prevents jpeg_set_defaults() from uselessly checking the value of cinfo->arith_code immediately after it has been set to FALSE.
This commit is contained in:
@@ -24,6 +24,10 @@ response to a prematurely-terminated JPEG data stream.
|
|||||||
greater than 7 resulted in an error ("Invalid progressive/lossless parameters")
|
greater than 7 resulted in an error ("Invalid progressive/lossless parameters")
|
||||||
unless the `-precision` option was specified before the `-lossless` option.
|
unless the `-precision` option was specified before the `-lossless` option.
|
||||||
|
|
||||||
|
4. Fixed a regression introduced by 3.0.3[3] that made it impossible for
|
||||||
|
calling applications to generate 12-bit-per-sample arithmetic-coded lossy JPEG
|
||||||
|
images using the TurboJPEG API.
|
||||||
|
|
||||||
|
|
||||||
3.0.3
|
3.0.3
|
||||||
=====
|
=====
|
||||||
|
|||||||
15
cjpeg.1
15
cjpeg.1
@@ -1,4 +1,4 @@
|
|||||||
.TH CJPEG 1 "21 June 2024"
|
.TH CJPEG 1 "24 June 2024"
|
||||||
.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
|
||||||
@@ -60,7 +60,11 @@ decompression are unaffected by
|
|||||||
.BR \-optimize .
|
.BR \-optimize .
|
||||||
.TP
|
.TP
|
||||||
.B \-progressive
|
.B \-progressive
|
||||||
Create progressive JPEG file (see below).
|
Create progressive JPEG file (see below). Implies
|
||||||
|
.B \-optimize
|
||||||
|
unless
|
||||||
|
.B \-arithmetic
|
||||||
|
is also specified.
|
||||||
.TP
|
.TP
|
||||||
.B \-targa
|
.B \-targa
|
||||||
Input file is Targa format [legacy feature]. Targa files that contain an
|
Input file is Targa format [legacy feature]. Targa files that contain an
|
||||||
@@ -168,6 +172,13 @@ will cause it to print information about the precision of the input file.
|
|||||||
12-bit and 16-bit data precision is not yet widely implemented, so many
|
12-bit and 16-bit data precision is not yet widely implemented, so many
|
||||||
decoders will be unable to handle a 12-bit-per-sample or 16-bit-per-sample JPEG
|
decoders will be unable to handle a 12-bit-per-sample or 16-bit-per-sample JPEG
|
||||||
file at all.
|
file at all.
|
||||||
|
.IP
|
||||||
|
.B \-precision\ 12
|
||||||
|
implies
|
||||||
|
.B \-optimize
|
||||||
|
unless
|
||||||
|
.B \-arithmetic
|
||||||
|
is also specified.
|
||||||
.TP
|
.TP
|
||||||
.BI \-lossless " psv[,Pt]"
|
.BI \-lossless " psv[,Pt]"
|
||||||
Create a lossless JPEG file using the specified predictor selection value
|
Create a lossless JPEG file using the specified predictor selection value
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C)2009-2014, 2016-2019, 2021-2023 D. R. Commander.
|
* Copyright (C)2009-2014, 2016-2019, 2021-2024 D. R. Commander.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -926,7 +926,6 @@ final class TJBench {
|
|||||||
System.out.println("Using fastest DCT/IDCT algorithm\n");
|
System.out.println("Using fastest DCT/IDCT algorithm\n");
|
||||||
fastDCT = true;
|
fastDCT = true;
|
||||||
} else if (argv[i].equalsIgnoreCase("-optimize")) {
|
} else if (argv[i].equalsIgnoreCase("-optimize")) {
|
||||||
System.out.println("Using optimized baseline entropy coding\n");
|
|
||||||
optimize = true;
|
optimize = true;
|
||||||
xformOpt |= TJTransform.OPT_OPTIMIZE;
|
xformOpt |= TJTransform.OPT_OPTIMIZE;
|
||||||
} else if (argv[i].equalsIgnoreCase("-progressive")) {
|
} else if (argv[i].equalsIgnoreCase("-progressive")) {
|
||||||
@@ -1127,6 +1126,10 @@ final class TJBench {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optimize && !progressive && !arithmetic && !lossless &&
|
||||||
|
precision != 12)
|
||||||
|
System.out.println("Using optimized baseline entropy coding\n");
|
||||||
|
|
||||||
if (precision == 16 && !lossless)
|
if (precision == 16 && !lossless)
|
||||||
throw new Exception("-lossless must be specified along with -precision 16");
|
throw new Exception("-lossless must be specified along with -precision 16");
|
||||||
if (precision != 8 && doYUV)
|
if (precision != 8 && doYUV)
|
||||||
|
|||||||
31
jcmaster.c
31
jcmaster.c
@@ -751,22 +751,25 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
|
|||||||
/* Validate parameters, determine derived values */
|
/* Validate parameters, determine derived values */
|
||||||
initial_setup(cinfo, transcode_only);
|
initial_setup(cinfo, transcode_only);
|
||||||
|
|
||||||
if (cinfo->master->lossless || /* TEMPORARY HACK ??? */
|
if (cinfo->arith_code)
|
||||||
(cinfo->progressive_mode && !cinfo->arith_code))
|
cinfo->optimize_coding = FALSE;
|
||||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
else {
|
||||||
progressive mode or lossless mode */
|
if (cinfo->master->lossless || /* TEMPORARY HACK ??? */
|
||||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
cinfo->progressive_mode)
|
||||||
if (cinfo->dc_huff_tbl_ptrs[i] != NULL ||
|
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
||||||
cinfo->ac_huff_tbl_ptrs[i] != NULL) {
|
progressive mode or lossless mode */
|
||||||
empty_huff_tables = FALSE;
|
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||||
break;
|
if (cinfo->dc_huff_tbl_ptrs[i] != NULL ||
|
||||||
|
cinfo->ac_huff_tbl_ptrs[i] != NULL) {
|
||||||
|
empty_huff_tables = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (cinfo->data_precision == 12 && !cinfo->optimize_coding &&
|
||||||
|
(empty_huff_tables || using_std_huff_tables(cinfo)))
|
||||||
|
cinfo->optimize_coding = TRUE; /* assume default tables no good for
|
||||||
|
12-bit data precision */
|
||||||
}
|
}
|
||||||
if (cinfo->data_precision == 12 && !cinfo->arith_code &&
|
|
||||||
!cinfo->optimize_coding &&
|
|
||||||
(empty_huff_tables || using_std_huff_tables(cinfo)))
|
|
||||||
cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit
|
|
||||||
data precision */
|
|
||||||
|
|
||||||
/* Initialize my private state */
|
/* Initialize my private state */
|
||||||
if (transcode_only) {
|
if (transcode_only) {
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ jpeg_set_defaults(j_compress_ptr cinfo)
|
|||||||
* tables will be computed. This test can be removed if default tables
|
* tables will be computed. This test can be removed if default tables
|
||||||
* are supplied that are valid for the desired precision.
|
* are supplied that are valid for the desired precision.
|
||||||
*/
|
*/
|
||||||
if (cinfo->data_precision == 12 && !cinfo->arith_code)
|
if (cinfo->data_precision == 12)
|
||||||
cinfo->optimize_coding = TRUE;
|
cinfo->optimize_coding = TRUE;
|
||||||
|
|
||||||
/* By default, use the simpler non-cosited sampling alignment */
|
/* By default, use the simpler non-cosited sampling alignment */
|
||||||
|
|||||||
@@ -1141,10 +1141,11 @@ boolean optimize_coding
|
|||||||
Huffman tables. In most cases optimal tables save only a few percent
|
Huffman tables. In most cases optimal tables save only a few percent
|
||||||
of file size compared to the default tables. Note that when this is
|
of file size compared to the default tables. Note that when this is
|
||||||
TRUE, you need not supply Huffman tables at all, and any you do
|
TRUE, you need not supply Huffman tables at all, and any you do
|
||||||
supply will be overwritten. This parameter has no effect in
|
supply will be overwritten. Optimal Huffman tables are always
|
||||||
progressive mode or lossless mode, in which optimal Huffman tables are
|
computed, and this parameter has no effect, in progressive mode or
|
||||||
always computed, and it defaults to TRUE for 12-bit data precision
|
lossless mode or with 12-bit data precision (unless Huffman tables have
|
||||||
unless Huffman tables have been supplied.
|
been supplied.) This parameter also has no effect when using
|
||||||
|
arithmetic coding.
|
||||||
|
|
||||||
unsigned int restart_interval
|
unsigned int restart_interval
|
||||||
int restart_in_rows
|
int restart_in_rows
|
||||||
|
|||||||
@@ -1047,7 +1047,6 @@ int main(int argc, char *argv[])
|
|||||||
printf("Using fastest DCT/IDCT algorithm\n\n");
|
printf("Using fastest DCT/IDCT algorithm\n\n");
|
||||||
fastDCT = 1;
|
fastDCT = 1;
|
||||||
} else if (!strcasecmp(argv[i], "-optimize")) {
|
} else if (!strcasecmp(argv[i], "-optimize")) {
|
||||||
printf("Using optimized baseline entropy coding\n\n");
|
|
||||||
optimize = 1;
|
optimize = 1;
|
||||||
xformOpt |= TJXOPT_OPTIMIZE;
|
xformOpt |= TJXOPT_OPTIMIZE;
|
||||||
} else if (!strcasecmp(argv[i], "-progressive")) {
|
} else if (!strcasecmp(argv[i], "-progressive")) {
|
||||||
@@ -1197,6 +1196,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optimize && !progressive && !arithmetic && !lossless && precision != 12)
|
||||||
|
printf("Using optimized baseline entropy coding\n\n");
|
||||||
|
|
||||||
if (precision == 16 && !lossless) {
|
if (precision == 16 && !lossless) {
|
||||||
printf("ERROR: -lossless must be specified along with -precision 16\n");
|
printf("ERROR: -lossless must be specified along with -precision 16\n");
|
||||||
retval = -1; goto bailout;
|
retval = -1; goto bailout;
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ The basic command line switches for cjpeg are:
|
|||||||
memory. Image quality and speed of decompression are
|
memory. Image quality and speed of decompression are
|
||||||
unaffected by -optimize.
|
unaffected by -optimize.
|
||||||
|
|
||||||
-progressive Create progressive JPEG file (see below).
|
-progressive Create progressive JPEG file (see below). Implies
|
||||||
|
-optimize unless -arithmetic is also specified.
|
||||||
|
|
||||||
-targa Input file is Targa format [legacy feature]. Targa
|
-targa Input file is Targa format [legacy feature]. Targa
|
||||||
files that contain an "identification" field will not
|
files that contain an "identification" field will not
|
||||||
@@ -181,6 +182,9 @@ Switches for advanced users:
|
|||||||
decoders will be unable to handle a 12-bit-per-sample or
|
decoders will be unable to handle a 12-bit-per-sample or
|
||||||
16-bit-per-sample JPEG file at all.
|
16-bit-per-sample JPEG file at all.
|
||||||
|
|
||||||
|
"-precision 12" implies -optimize unless -arithmetic is
|
||||||
|
also specified.
|
||||||
|
|
||||||
-lossless psv[,Pt] Create a lossless JPEG file using the specified
|
-lossless psv[,Pt] Create a lossless JPEG file using the specified
|
||||||
predictor selection value (1 - 7) and optional point
|
predictor selection value (1 - 7) and optional point
|
||||||
transform (0 - {precision}-1, where {precision} is the
|
transform (0 - {precision}-1, where {precision} is the
|
||||||
|
|||||||
Reference in New Issue
Block a user