* commit '15274b901acb75d6d2433e8578f3cfbc6f4f5fd9': (98 commits)
AppVeyor: Use SignPath release cert/only sign tags
xform fuzz: Use only xform opts to set entropy alg
jchuff.c: Test for out-of-range coefficients
turbojpeg.h: Make customFilter() proto match doc
ChangeLog.md: Fix typo
djpeg: Fix -map option with 12-bit data precision
Disallow color quantization with lossless decomp
tj3Transform: Calc dst buf size from xformed dims
README.md: Include link to project home page
AppVeyor: Only add installers to zip file
AppVeyor: Integrate with SignPath.io
Fix build warnings/errs w/ -DNO_GETENV/-DNO_PUTENV
GitHub: Fix x32 build
Bump version to 3.0.0
tjexample.c: Prevent integer overflow
Disallow merged upsampling with lossless decomp
SECURITY.md: Wordsmithing and clarifications
GitHub: Add security policy
ChangeLog.md: List CVE ID fixed by 9f756bc6
jpeg_crop_scanline: Fix calc w/sclg + 2x4,4x2 samp
...
If a hypothetical calling application does something really stupid and
changes cinfo->data_precision after calling jpeg_start_*compress(), then
the precision-specific methods called by jpeg_write_scanlines(),
jpeg_write_raw_data(), jpeg_finish_compress(), jpeg_read_scanlines(),
jpeg_read_raw_data(), or jpeg_start_output() may not be initialized.
Ensure that the first precision-specific method (which will always be
cinfo->main->process_data*(), cinfo->coef->compress_data*(), or
cinfo->coef->decompress_data()) called by any global function that may
be called after jpeg_start_*compress() is initialized and non-NULL.
This increases the likelihood (but does not guarantee) that a
hypothetical stupid calling application will fail gracefully rather than
segfault if it changes cinfo->data_precision after calling
jpeg_start_*compress(). A hypothetical stupid calling application can
still bork itself by changing cinfo->data_precision after initializing
the source manager but before calling jpeg_start_compress(), or after
initializing the destination manager but before calling
jpeg_start_decompress().
Those changes worked around an innocuous UBSan warning that was
exposed by the new TurboJPEG 3 transform fuzz target, due to the fact
that tj3Transform() no longer rejects images with unknown subsampling
configurations. That UBSan warning was a false positive, and attempting
to fix it introduced a buffer overrun triggered by a malformed input
image that causes jpeg_write_marker() to be called with datalen == 0. I
suspect that the UBSan false positive was only reproducible on my local
machine, but I guess we'll see.
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55413
(ChangeLog update forthcoming)
- Prefix all function names with "tj3" and remove version suffixes from
function names. (Future API overhauls will increment the prefix to
"tj4", etc., thus retaining backward API/ABI compatibility without
versioning each individual function.)
- Replace stateless boolean flags (including TJ*FLAG_ARITHMETIC and
TJ*FLAG_LOSSLESS, which were never released) with stateful integer
parameters, the value of which persists between function calls.
* Use parameters for the JPEG quality and subsampling as well, in
order to eliminate the awkwardness of specifying function arguments
that weren't relevant for lossless compression.
* tj3DecompressHeader() now stores all relevant information about the
JPEG image, including the width, height, subsampling type, entropy
coding type, etc. in parameters rather than returning that
information in its arguments.
* TJ*FLAG_LIMITSCANS has been reimplemented as an integer parameter
(TJ*PARAM_SCANLIMIT) that allows the number of scans to be
specified.
- Use the const keyword for all pointer arguments to unmodified
buffers, as well as for both dimensions of 2D pointers. Addresses
#395.
- Use size_t rather than unsigned long to represent buffer sizes, since
unsigned long is a 32-bit type on Windows. Addresses #24.
- Return 0 from all buffer size functions if an error occurs, rather
than awkwardly trying to return -1 in an unsigned data type.
- Implement 12-bit and 16-bit data precision using dedicated
compression, decompression, and image I/O functions/methods.
* Suffix the names of all data-precision-specific functions with 8,
12, or 16.
* Because the YUV functions are intended to be used for video, they
are currently only implemented with 8-bit data precision, but they
can be expanded to 12-bit data precision in the future, if
necessary.
* Extend TJUnitTest and TJBench to test 12-bit and 16-bit data
precision, using a new -precision option.
* Add appropriate regression tests for all of the above to the 'test'
target.
* Extend tjbenchtest to test 12-bit and 16-bit data precision, and
add separate 'tjtest12' and 'tjtest16' targets.
* BufferedImage I/O in the Java API is currently limited to 8-bit
data precision, since the BufferedImage class does not
straightforwardly support higher data precisions.
* Extend the PPM reader to convert 12-bit and 16-bit PBMPLUS files
to grayscale or CMYK pixels, as it already does for 8-bit files.
- Properly accommodate lossless JPEG using dedicated parameters
(TJ*PARAM_LOSSLESS, TJ*PARAM_LOSSLESSPSV, and TJ*PARAM_LOSSLESSPT),
rather than using a flag and awkwardly repurposing the JPEG quality.
Update TJBench to properly reflect whether a JPEG image is lossless.
- Re-organize the TJBench usage screen.
- Update the Java docs using Java 11, to improve the formatting and
eliminate HTML frames.
- Use the accurate integer DCT algorithm by default for both
compression and decompression, since the "fast" algorithm is a legacy
feature, it does not pass the ISO compliance tests, and it is not
actually faster on modern x86 CPUs.
* Remove the -accuratedct option from TJBench and TJExample.
- Re-implement the 'tjtest' target using a CMake script that enables
the appropriate tests, depending on the data precision and whether or
not the Java API is part of the build.
- Consolidate the C and Java versions of tjbenchtest into one script.
- Consolidate the C and Java versions of tjexampletest into one script.
- Combine all initialization functions into a single function
(tj3Init()) that accepts an integer parameter specifying the
subsystems to initialize.
- Enable decompression scaling explicitly, using a new function/method
(tj3SetScalingFactor()/TJDecompressor.setScalingFactor()), rather
than implicitly using awkward "desired width"/"desired height"
parameters.
- Introduce a new macro/constant (TJUNSCALED/TJ.UNSCALED) that maps to
a scaling factor of 1/1.
- Implement partial image decompression, using a new function/method
(tj3SetCroppingRegion()/TJDecompressor.setCroppingRegion()) and
TJBench option (-crop). Extend tjbenchtest to test the new feature.
Addresses #1.
- Allow the JPEG colorspace to be specified explicitly when
compressing, using a new parameter (TJ*PARAM_COLORSPACE). This
allows JPEG images with the RGB and CMYK colorspaces to be created.
- Remove the error/difference image feature from TJBench. Identical
images to the ones that TJBench created can be generated using
ImageMagick with
'magick composite <original_image> <output_image> -compose difference <diff_image>'
- Handle JPEG images with unknown subsampling types. TJ*PARAM_SUBSAMP
is set to TJ*SAMP_UNKNOWN (== -1) for such images, but they can still
be decompressed fully into packed-pixel images or losslessly
transformed (with the exception of lossless cropping.) They cannot
be partially decompressed or decompressed into planar YUV images.
Note also that TJBench, due to its lack of support for imperfect
transforms, requires that the subsampling type be known when
rotating, flipping, or transversely transposing an image. Addresses
#436
- The Java version of TJBench now has identical functionality to the C
version. This was accomplished by (somewhat hackishly) calling the
TurboJPEG C image I/O functions through JNI and copying the pixels
between the C heap and the Java heap.
- Add parameters (TJ*PARAM_RESTARTROWS and TJ*PARAM_RESTARTBLOCKS) and
a TJBench option (-restart) to allow the restart marker interval to
be specified when compressing. Eliminate the undocumented TJ_RESTART
environment variable.
- Add a parameter (TJ*PARAM_OPTIMIZE), a transform option
(TJ*OPT_OPTIMIZE), and a TJBench option (-optimize) to allow
optimized baseline Huffman coding to be specified when compressing.
Eliminate the undocumented TJ_OPTIMIZE environment variable.
- Add parameters (TJ*PARAM_XDENSITY, TJ*PARAM_DENSITY, and
TJ*DENSITYUNITS) to allow the pixel density to be specified when
compressing or saving a Windows BMP image and to be queried when
decompressing or loading a Windows BMP image. Addresses #77.
- Refactor the fuzz targets to use the new API.
* Extend decompression coverage to 12-bit and 16-bit data precision.
* Replace the awkward cjpeg12 and cjpeg16 targets with proper
TurboJPEG-based compress12, compress12-lossless, and
compress16-lossless targets
- Fix innocuous UBSan warnings uncovered by the new fuzzers.
- Implement previous versions of the TurboJPEG API by wrapping the new
functions (tested by running the 2.1.x versions of TJBench, via
tjbenchtest, and TJUnitTest against the new implementation.)
* Remove all JNI functions for deprecated Java methods and implement
the deprecated methods using pure Java wrappers. It should be
understood that backward API compatibility in Java applies only to
the Java classes and that one cannot mix and match a JAR file from
one version of libjpeg-turbo with a JNI library from another
version.
- tj3Destroy() now silently accepts a NULL handle.
- tj3Alloc() and tj3Free() now return/accept void pointers, as malloc()
and free() do.
- The image I/O functions now accept a TurboJPEG instance handle, which
is used to transmit/receive parameters and to receive error
information.
Closes#517
- Rename jpeg_simple_lossless() to jpeg_enable_lossless() and modify the
function so that it stores the lossless parameters directly in the Ss
and Al fields of jpeg_compress_struct rather than using a scan script.
- Move the cjpeg -lossless switch into "Switches for advanced users".
- Document the libjpeg API and run-time features that are unavailable in
lossless mode, and ensure that all parameters, functions, and switches
related to unavailable features are ignored or generate errors in
lossless mode.
- Defer any action that depends on whether lossless mode is enabled
until jpeg_start_compress()/jpeg_start_decompress() is called.
- Document the purpose of the point transform value.
- "Codec" stands for coder/decoder, so it is a bit awkward to say
"lossless compression codec" and "lossless decompression codec".
Use "lossless compressor" and "lossless decompressor" instead.
- Restore backward API/ABI compatibility with libjpeg v6b:
* Move the new 'lossless' field from the exposed jpeg_compress_struct
and jpeg_decompress_struct structures into the opaque
jpeg_comp_master and jpeg_decomp_master structures, and allocate the
master structures in the body of jpeg_create_compress() and
jpeg_create_decompress().
* Remove the new 'process' field from jpeg_compress_struct and
jpeg_decompress_struct and replace it with the old
'progressive_mode' field and the new 'lossless' field.
* Remove the new 'data_unit' field from jpeg_compress_struct and
jpeg_decompress_struct and replace it with a locally-computed
data unit variable.
* Restore the names of macros and fields that refer to DCT blocks, and
document that they have a different meaning in lossless mode. (Most
of them aren't very meaningful in lossless mode anyhow.)
* Remove the new alloc_darray() method from jpeg_memory_mgr and
replace it with an internal macro that wraps the alloc_sarray()
method.
* Move the JDIFF* data types from jpeglib.h and jmorecfg.h into
jpegint.h.
* Remove the new 'codec' field from jpeg_compress_struct and
jpeg_decompress_struct and instead reuse the existing internal
coefficient control, forward/inverse DCT, and entropy
encoding/decoding structures for lossless compression/decompression.
* Repurpose existing error codes rather than introducing new ones.
(The new JERR_BAD_RESTART and JWRN_MUST_DOWNSCALE codes remain,
although JWRN_MUST_DOWNSCALE will probably be removed in
libjpeg-turbo, since we have a different way of handling multiple
data precisions.)
- Automatically enable lossless mode when a scan script with parameters
that are only valid for lossless mode is detected, and document the
use of scan scripts to generate lossless JPEG images.
- Move the sequential and shared Huffman routines back into jchuff.c and
jdhuff.c, and document that those routines are shared with jclhuff.c
and jdlhuff.c as well as with jcphuff.c and jdphuff.c.
- Move MAX_DIFF_BITS from jchuff.h into jclhuff.c, the only place where
it is used.
- Move the predictor and scaler code into jclossls.c and jdlossls.c.
- Streamline register usage in the [un]differencers (inspired by similar
optimizations in the color [de]converters.)
- Restructure the logic in a few places to reduce duplicated code.
- Ensure that all lossless-specific code is guarded by
C_LOSSLESS_SUPPORTED or D_LOSSLESS_SUPPORTED and that the library can
be built successfully if either or both of those macros is undefined.
- Remove all short forms of external names introduced by the lossless
JPEG patch. (These will not be needed by libjpeg-turbo, so there is
no use cleaning them up.)
- Various wordsmithing, formatting, and punctuation tweaks
- Eliminate various compiler warnings.
In libjpeg-turbo 2.1.x and prior, the WITH_12BIT CMake variable was used
to enable 12-bit JPEG support at compile time, because the libjpeg API
library could not handle multiple JPEG data precisions at run time. The
initial approach to handling multiple JPEG data precisions at run time
(7fec5074f9) created a whole new API,
library, and applications for 12-bit data precision, so it made sense to
repurpose WITH_12BIT to allow 12-bit data precision to be disabled.
e8b40f3c2b made it so that the libjpeg API
library can handle multiple JPEG data precisions at run time via a
handful of straightforward API extensions. Referring to
6c2bc901e2, it hasn't been possible to
build libjpeg-turbo with both forward and backward libjpeg API/ABI
compatibility since libjpeg-turbo 1.4.x. Thus, whereas we retain full
backward API/ABI compatibility with libjpeg v6b-v8, forward libjpeg
API/ABI compatibility ceased being realistic years ago, so it no longer
makes sense to provide compile-time options that give a false sense of
forward API/ABI compatibility by allowing some (but not all) of our
libjpeg API extensions to be disabled. Such options are difficult to
maintain and clutter the code with #ifdefs.
The Gordian knot that 7fec5074f9 attempted
to unravel was caused by the fact that there are several
data-precision-dependent (JSAMPLE-dependent) fields and methods in the
exposed libjpeg API structures, and if you change the exposed libjpeg
API structures, then you have to change the whole API. If you change
the whole API, then you have to provide a whole new library to support
the new API, and that makes it difficult to support multiple data
precisions in the same application. (It is not impossible, as example.c
demonstrated, but using data-precision-dependent libjpeg API structures
would have made the cjpeg, djpeg, and jpegtran source code hard to read,
so it made more sense to build, install, and package 12-bit-specific
versions of those applications.)
Unfortunately, the result of that initial integration effort was an
unreadable and unmaintainable mess, which is a problem for a library
that is an ISO/ITU-T reference implementation. Also, as I dug into the
problem of lossless JPEG support, I realized that 16-bit lossless JPEG
images are a thing, and supporting yet another version of the libjpeg
API just for those images is untenable.
In fact, however, the touch points for JSAMPLE in the exposed libjpeg
API structures are minimal:
- The colormap and sample_range_limit fields in jpeg_decompress_struct
- The alloc_sarray() and access_virt_sarray() methods in
jpeg_memory_mgr
- jpeg_write_scanlines() and jpeg_write_raw_data()
- jpeg_read_scanlines() and jpeg_read_raw_data()
- jpeg_skip_scanlines() and jpeg_crop_scanline()
(This is subtle, but both of those functions use JSAMPLE-dependent
opaque structures behind the scenes.)
It is much more readable and maintainable to provide 12-bit-specific
versions of those six top-level API functions and to document that the
aforementioned methods and fields must be type-cast when using 12-bit
samples. Since that eliminates the need to provide a 12-bit-specific
version of the exposed libjpeg API structures, we can:
- Compile only the precision-dependent libjpeg modules (the
coefficient buffer controllers, the colorspace converters, the
DCT/IDCT managers, the main buffer controllers, the preprocessing
and postprocessing controller, the downsampler and upsamplers, the
quantizers, the integer DCT methods, and the IDCT methods) for
multiple data precisions.
- Introduce 12-bit-specific methods into the various internal
structures defined in jpegint.h.
- Create precision-independent data type, macro, method, field, and
function names that are prefixed by an underscore, and use an
internal header to convert those into precision-dependent data
type, macro, method, field, and function names, based on the value
of BITS_IN_JSAMPLE, when compiling the precision-dependent libjpeg
modules.
- Expose precision-dependent jinit*() functions for each of the
precision-dependent libjpeg modules.
- Abstract the precision-dependent libjpeg modules by calling the
appropriate precision-dependent jinit*() function, based on the
value of cinfo->data_precision, from top-level libjpeg API
functions.
libjpeg-turbo has never supported non-ANSI C compilers. Per the spec,
ANSI C compilers must have locale.h, stddef.h, stdlib.h, memset(),
memcpy(), unsigned char, and unsigned short. They must also handle
undefined structures.
With rare exceptions ...
- Always separate line continuation characters by one space from
preceding code.
- Always use two-space indentation. Never use tabs.
- Always use K&R-style conditional blocks.
- Always surround operators with spaces, except in raw assembly code.
- Always put a space after, but not before, a comma.
- Never put a space between type casts and variables/function calls.
- Never put a space between the function name and the argument list in
function declarations and prototypes.
- Always surround braces ('{' and '}') with spaces.
- Always surround statements (if, for, else, catch, while, do, switch)
with spaces.
- Always attach pointer symbols ('*' and '**') to the variable or
function name.
- Always precede pointer symbols ('*' and '**') by a space in type
casts.
- Use the MIN() macro from jpegint.h within the libjpeg and TurboJPEG
API libraries (using min() from tjutil.h is still necessary for
TJBench.)
- Where it makes sense (particularly in the TurboJPEG code), put a blank
line after variable declaration blocks.
- Always separate statements in one-liners by two spaces.
The purpose of this was to ease maintenance on my part and also to make
it easier for contributors to figure out how to format patch
submissions. This was admittedly confusing (even to me sometimes) when
we had 3 or 4 different style conventions in the same source tree. The
new convention is more consistent with the formatting of other OSS code
bases.
This commit corrects deviations from the chosen formatting style in the
libjpeg API code and reformats the TurboJPEG API code such that it
conforms to the same standard.
NOTES:
- Although it is no longer necessary for the function name in function
declarations to begin in Column 1 (this was historically necessary
because of the ansi2knr utility, which allowed libjpeg to be built
with non-ANSI compilers), we retain that formatting for the libjpeg
code because it improves readability when using libjpeg's function
attribute macros (GLOBAL(), etc.)
- This reformatting project was accomplished with the help of AStyle and
Uncrustify, although neither was completely up to the task, and thus
a great deal of manual tweaking was required. Note to developers of
code formatting utilities: the libjpeg-turbo code base is an
excellent test bed, because AFAICT, it breaks every single one of the
utilities that are currently available.
- The legacy (MMX, SSE, 3DNow!) assembly code for i386 has been
formatted to match the SSE2 code (refer to
ff5685d5344273df321eb63a005eaae19d2496e3.) I hadn't intended to
bother with this, but the Loongson MMI implementation demonstrated
that there is still academic value to the MMX implementation, as an
algorithmic model for other 64-bit vector implementations. Thus, it
is desirable to improve its readability in the same manner as that of
the SSE2 implementation.
* libjpeg-turbo/master: (140 commits)
Increase severity of tjDecompressToYUV2() bug desc
Catch libjpeg errors in tjDecompressToYUV2()
BUILDING.md: Fix "... OR ..." indentation again
BUILDING.md: Fix confusing Windows build reqs
ChangeLog.md: Improve readability of plain text
change.log: Refer users to ChangeLog.md
Markdown version of ChangeLog.txt
Rename ChangeLog.txt
README.md: Link to BUILDING.md
BUILDING.md and README.md: Cosmetic tweaks
ChangeLog: "1.5 beta1" --> "1.4.90 (1.5 beta1)"
Java: Fix parallel make with autotools
Win/x64: Fix improper callee save of xmm8-xmm11
Bump TurboJPEG C API revision to 1.5
ChangeLog: Mention jpeg_crop_scanline() function
1.5 beta1
Fix v7/v8-compatible build
libjpeg API: Partial scanline decompression
Build: Make the NASM autoconf variable persistent
Use consistent/modern code formatting for dbl ptrs
...
The convention used by libjpeg:
type * variable;
is not very common anymore, because it looks too much like
multiplication. Some (particularly C++ programmers) prefer to tuck the
pointer symbol against the type:
type* variable;
to emphasize that a pointer to a type is effectively a new type.
However, this can also be confusing, since defining multiple variables
on the same line would not work properly:
type* variable1, variable2; /* Only variable1 is actually a
pointer. */
This commit reformats the entirety of the libjpeg-turbo code base so
that it uses the same code formatting convention for pointers that the
TurboJPEG API code uses:
type *variable1, *variable2;
This seems to be the most common convention among C programmers, and
it is the convention used by other codec libraries, such as libpng and
libtiff.
The IJG README file has been renamed to README.ijg, in order to avoid
confusion (many people were assuming that that was our project's README
file and weren't reading README-turbo.txt) and to lay the groundwork for
markdown versions of the libjpeg-turbo README and build instructions.
There was an oversight in the extension framework. jpeg_start_compress() can
be called multiple times between the time that a compress structure is created
and the time it is destroyed. If this happened, then the following sequence
would occur:
-- heap alloc of master struct within jpeg_create_compress()
-- heap free of master struct within jinit_c_master_control()
-- static alloc of extended master struct (JPOOL_IMAGE) within
jinit_c_master_control()
-- free extended master struct in jpeg_finish_compress()
-- jinit_c_master_control() now sees that cinfo->master is set and tries to
free it, even though it has already been freed. Chaos ensues.
The fix involved breaking out the extended master struct into a header so that
jpeg_create_compress() can go ahead and allocate it to the correct size, thus
eliminating the need to free and reallocate it in jinit_c_master_control().
Further, the master struct is now created in the permanent pool, so it will
survive until the compression struct is destroyed. Further,
jinit_c_master_control() now resets all fields in the master struct that
are not related to the extension parameters.
This eliminates JBOOLEAN_USE_MOZ_DEFAULTS and replaces it with
JINT_COMPRESS_PROFILE, a more flexible and descriptive parameter. Currently,
this new parameter works in much the same way as the old-- it changes the
behavior of jpeg_set_defaults(). It currently supports only two values
(max. compression, i.e. mozjpeg defaults, and fastest, i.e. libjpeg-turbo
defaults), but it can be extended in the future with additional profiles that
balance compression ratio with performance.
Since mozjpeg is now backward ABI-compatible with libjpeg[-turbo], it is now
possible to temporarily load mozjpeg into a binary application and cause that
application to generate uber-compressed JPEGs (at the expense of an extreme
performance loss, of course.) For instance, someone could do
LD_LIBRARY_PATH=/opt/mozjpeg/lib convert blah_blah_blah
to make ImageMagick use mozjpeg instead of the system's pre-installed JPEG
library (libjpeg-turbo, in most cases.) However, this only makes sense if
mozjpeg is actually producing different behavior by default than libjpeg-turbo.
Currently it isn't. Currently it requires the application to set
JBOOLEAN_USE_MOZ_DEFAULTS to TRUE in order to enable the mozjpeg-specific
behavior, but of course applications that were built to use libjpeg[-turbo]
won't do that. Thus, this patch sets use_moz_defaults to TRUE by default,
requiring an application to explicitly set it to FALSE in order to revert to
the libjpeg[-turbo] behavior (makes sense, since the only applications that
would need to revert to the libjpeg[-turbo] behavior would be mozjpeg-aware
applications.)
Note that we discussed the possibility of adding a function
(jpeg_revert_defaults()), which would act the same as jpeg_set_defaults() does
in libjpeg[-turbo]. This is a good solution for implementing the -revert
switch in cjpeg, but unfortunately it doesn't work for jpegtran. The reason
is that jpeg_set_defaults() is called within the body of
jpeg_copy_critical_parameters(), which is part of the API. So yet again,
if mozjpeg were loaded into a non-mozjpeg-aware application at run time, it
would be desirable for jpeg_copy_critical_parameters() to set the parameters
to mozjpeg defaults. That means that, in order to implement the -revert
switch in jpegtran, it would be necessary to introduce a new function
(jpeg_revert_critical_parameters(), perhaps). It seems cleaner to just keep
using the JBOOLEAN_USE_MOZ_DEFAULTS parameter to control the behavior of
jpeg_set_defaults(), even though this represents a minor abuse of the libjpeg
API (jpeg_set_defaults() is technically supposed to set all of the parameters
to defaults, irrespective of any previous state. However, as long as we
document that JBOOLEAN_USE_MOZ_DEFAULTS works differently, then it should be
OK.)