Commit Graph

34 Commits

Author SHA1 Message Date
DRC
55d342c788 TurboJPEG: Expose/extend hidden "max pixels" param
TJPARAM_MAXPIXELS was previously hidden and used only for fuzz testing,
but it is potentially useful for calling applications as well,
particularly if they want to guard against excessive memory consumption
by the tj3LoadImage*() functions.  The parameter has also been extended
to decompression and lossless transformation functions/methods, mainly
as a convenience.  (It was already possible for calling applications to
impose their own JPEG image size limits by reading the JPEG header prior
to decompressing or transforming the image.)
2023-11-16 15:36:47 -05:00
DRC
e8b40f3c2b Vastly improve 12-bit JPEG integration
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.
2022-11-04 12:30:33 -05:00
DRC
b579fc114d Eliminate unnecessary JFREAD()/JFWRITE() macros 2022-02-09 16:07:18 -06:00
DRC
172972394a Eliminate non-ANSI C compatibility macros
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.
2022-01-06 11:50:26 -06:00
DRC
73eff6effe cjpeg: auto. compr. gray BMP/GIF-->grayscale JPEG
aa7459050d was supposed to enable this for
BMP input images but didn't, due to a similar oversight to the one fixed
in the previous commit.
2021-11-30 16:10:23 -06:00
DRC
171b875b27 OSS-Fuzz: Check img size b4 readers allocate mem
After the completion of the start_input() method, it's too late to check
the image size, because the image readers may have already tried to
allocate memory for the image.  If the width and height are excessively
large, then attempting to allocate memory for the image could slow
performance or lead to out-of-memory errors prior to the fuzz target
checking the image size.

NOTE: Specifically, the aforementioned OOM errors and slow units were
observed with the compression fuzz targets when using MSan.
2021-04-15 21:20:33 -05:00
DRC
ebaa67ea32 rdbmp.c: Fix more innocuous UBSan errors
- Referring to 3311fc0001, we need to use
  unsigned intermediate math in order to make UBSan happy, even though
  (JDIMENSION)(A * B) is effectively the same as
  (JDIMENSION)A *(JDIMENSION)B, regardless of intermediate overflow.

- Because of the previous commit, it is now possible for bfOffBits to be
  INT_MIN, which would cause the initial computation of bPad to
  underflow a signed integer.  Thus, we need to check for that
  possibility as soon as we know the values of bfOffBits and headerSize.
  The worst case from this regression is that bPad could wrap around to
  a large positive value, which would cause a "Premature end of input
  file" error in the subsequent read_byte() loop.  Thus, this issue was
  effectively innocuous as well, since it resulted in catching the same
  error later and in a different way.  Also, the issue was very
  well-contained, since it was both introduced and fixed as part of the
  ongoing OSS-Fuzz integration project.
2021-04-12 11:48:14 -05:00
DRC
dd830b3ffe rdbmp.c/rdppm.c: Fix more innocuous UBSan errors
- rdbmp.c: Because of 8fb37b8171,
  bfOffBits, biClrUsed, and headerSize were made into unsigned ints.
  Thus, if bPad would eventually be negative due to a malformed header,
  UBSan complained about unsigned math being used in the intermediate
  computations.  It was unnecessary to make those variables unsigned,
  since they are only meant to hold small values, so this commit makes
  them signed again.  The UBSan error was innocuous, because it is
  effectively (if not officially) the case that
  (int)((unsigned int)a - (unsigned int)b) == (int)a - (int)b.

- rdbmp.c: If (biWidth * source->bits_per_pixel / 8) would overflow an
  unsigned int, then UBSan complained at the point at which row_width
  was set in start_input_bmp(), even though the overflow would have been
  detected later in the function.  This commit adds overflow checks
  prior to setting row_width.

- rdppm.c: read_pbm_integer() now bounds-checks the intermediate
  value computations in order to catch integer overflow caused by a
  malformed text PPM.  It's possible, though extremely unlikely, that
  the intermediate value computations could have wrapped around to a
  value smaller than maxval, but the worst case is that this would have
  generated a bogus pixel in the uncompressed image rather than throwing
  an error.
2021-04-09 20:09:04 -05:00
DRC
3311fc0001 rdbmp.c: Fix innocuous UBSan error
A fuzzing test case with an image width of 838860946 triggered a UBSan
error:

rdbmp.c:633:34: runtime error: signed integer overflow:
838860946 * 3 cannot be represented in type 'int'

Because the result is cast to an unsigned int (JDIMENSION), this error
is irrelevant, because

(unsigned int)((int)838860946 * (int)3) ==
(unsigned int)838860946 * (unsigned int)3
2021-04-07 15:23:32 -05:00
DRC
88ae60986e Merge branch 'ijg' into dev
- Restore GIF read/compressed GIF write support from jpeg-6a and
  jpeg-9d.
- Integrate jpegtran -wipe and -drop options from jpeg-9a and jpeg-9d.
- Integrate jpegtran -crop extension (for expanding the image size) from
  jpeg-9a and jpeg-9d.
- Integrate other minor code tweaks from jpeg-9*
2020-10-27 13:32:13 -05:00
Guido Vollbeding
9fc018fd1a The Independent JPEG Group's JPEG software v9d 2020-10-23 10:00:48 -05:00
Guido Vollbeding
96e4e7eb60 The Independent JPEG Group's JPEG software v9c 2020-10-23 09:56:39 -05:00
DRC
01e3032354 Eliminate support for compilers w/o unsigned char
libjpeg-turbo has never really supported such compilers, since (AFAIK)
they are non-existent on any modern computing platform and thus
impossible for us to test.  (Also, the TurboJPEG API would break without
unsigned chars.)

Furthermore, the unified CMake-based build system introduced in 2.0
always defines HAVE_UNSIGNED_CHAR, so retaining other code paths is
pointless.  Eliminating support for compilers without unsigned char
eliminates the need for the GETJSAMPLE() macro, which improves the
readability of many parts of the code as well as improving the
performance of writing Targa and Windows BMP files.

Fixes #317
2019-01-23 15:12:26 -06:00
DRC
9c78a04df4 cjpeg: Fix OOB read caused by malformed 8-bit BMP
... in which one or more of the color indices is out of range for the
number of palette entries.

Fix partly borrowed from jpeg-9c.  This commit also adopts Guido's
JERR_PPM_OUTOFRANGE enum value in lieu of our project-specific
JERR_PPM_TOOLARGE enum value.

Fixes #258
2018-07-20 19:57:43 -05:00
DRC
43e84cff1b tjLoadImage(): Fix FPE triggered by malformed BMP
In rdbmp.c, it is necessary to guard against 32-bit overflow/wraparound
when allocating the row buffer, because since BMP files have 32-bit
width and height fields, the value of biWidth can be up to 4294967295.
Specifically, if biWidth is 1073741824 and cinfo->input_components = 4,
then the samplesperrow argument in alloc_sarray() would wrap around to
0, and a division by zero error would occur at line 458 in jmemmgr.c.

If biWidth is set to a higher value, then samplesperrow would wrap
around to a small number, which would likely cause a buffer overflow
(this has not been tested or verified.)
2018-06-12 21:17:34 -05:00
DRC
19c791cdac Improve code formatting consistency
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.
2018-03-16 02:14:34 -05:00
DRC
e817c07779 tjLoadImage(): return TJPF_GRAY for grayscale BMPs
... if *pixelFormat=TJPF_UNKNOWN is passed to the function.
2017-11-19 08:43:07 -06:00
DRC
479fa1d870 tjLoadImage(): Don't convert RGB to grayscale
Loading RGB image files into a grayscale buffer isn't a particularly
useful feature, given that libjpeg-turbo can perform this conversion
much more optimally (with SIMD acceleration on some platforms) during
the compression process.  Also, the RGB2GRAY() macro was not producing
deterministic cross-platform results because of variations in the
round-off behavior of various floating point implementations, so
`tjunittest -bmp` was failing in i386 builds.
2017-11-18 11:40:53 -06:00
DRC
aa7459050d TurboJPEG C API: Add BMP/PPM load/save functions
The main justification for this is to provide new libjpeg-turbo users
with a quick & easy way of developing a complete JPEG
compression/decompression program without requiring them to build
libjpeg-turbo from source (which was necessary in order to use the
project-private bmp API) or to use external libraries.  These new
functions build upon significant enhancements to rdbmp.c, wrbmp.c,
rdppm.c, and wrppm.c which allow those engines to convert directly
between the native pixel format of the file and a pixel format
("colorspace" in libjpeg parlance) specified by the calling program.
rdbmp.c and wrbmp.c have also been modified such that the calling
program can choose to read or write image rows in the native (bottom-up)
order of the file format, thus eliminating the need to use an inversion
array.  tjLoadImage() and tjSaveImage() leverage these new underlying
features in order to significantly improve upon the performance of the
old bmp API.

Because these new functions cannot work without the libjpeg-turbo
colorspace extensions, the libjpeg-compatible code in turbojpeg.c has
been removed.  That code was only there to serve as an example of how
to use the TurboJPEG API on top of libjpeg, but more specific, buildable
examples now exist in the https://github.com/libjpeg-turbo/ijg
repository.
2017-11-17 19:32:52 -06:00
DRC
bd49803f92 Use consistent/modern code formatting for pointers
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.
2016-02-19 09:10:07 -06:00
DRC
7e3acc0e0a Rename README, LICENSE, BUILDING text files
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.
2015-10-10 10:31:33 -05:00
DRC
8fb37b8171 Fix cjpeg segfault when Windows BMP width/height<0
rdbmp.c used the ambiguous INT32 datatype, which is sometimes typedef'ed
to long.  Windows bitmap headers use 32-bit signed integers for the
width and height, because height can sometimes be negative (this
indicates a top-down bitmap.)  If biWidth or biHeight was negative and
INT32 was a 64-bit long, then biWidth and biHeight were read as a
positive integer > INT32_MAX, which failed the test in line 385:

    if (biWidth <= 0 || biHeight <= 0)
        ERREXIT(cinfo, JERR_BMP_EMPTY);

This commit refactors rdbmp.c so that it uses the datatypes specified by
Microsoft for the Windows BMP header.

This closes #9 and also provides a better solution for mozilla/mozjpeg#153.
2015-08-13 11:09:05 -05:00
Guido Vollbeding
f18f81b7e2 The Independent JPEG Group's JPEG software v8a 2015-07-27 13:46:36 -05:00
Guido Vollbeding
989630f70c The Independent JPEG Group's JPEG software v8 2015-07-27 13:45:31 -05:00
Thomas G. Lane
489583f516 The Independent JPEG Group's JPEG software v6a 2015-07-29 15:32:35 -05:00
Thomas G. Lane
bc79e0680a The Independent JPEG Group's JPEG software v6 2015-07-29 15:31:30 -05:00
Thomas G. Lane
9ba2f5ed36 The Independent JPEG Group's JPEG software v5a 2015-07-29 15:29:17 -05:00
Thomas G. Lane
36a4ccccd3 The Independent JPEG Group's JPEG software v5 2015-07-29 15:28:00 -05:00
DRC
5de454b291 libjpeg-turbo has never supported non-ANSI compilers, so get rid of the crufty SIZEOF() macro. It was not being used consistently anyhow, so it would not have been possible to build prior releases of libjpeg-turbo using the broken compilers for which that macro was designed.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1313 632fc199-4ca6-4c93-a231-07263d6284db
2014-05-18 19:04:03 +00:00
DRC
e5eaf37440 Convert tabs to spaces in the libjpeg code and the SIMD code (TurboJPEG retains the use of tabs for historical reasons. They were annoying in the libjpeg code primarily because they were not consistently used and because they were used to format as well as indent the code. In the case of TurboJPEG, tabs are used just to indent the code, so even if the editor assumes a different tab width, the code will still be readable.)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1278 632fc199-4ca6-4c93-a231-07263d6284db
2014-05-09 18:00:32 +00:00
DRC
61976bd8a9 We use __CHAR_UNSIGNED__ (automatically defined by the AC_C_CHAR_UNSIGNED macro) rather than CHAR_IS_UNSIGNED (defined by custom autoconf code in libjpeg that we didn't port over), although I doubt it matters on any of the platforms we support.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.3.x@1264 632fc199-4ca6-4c93-a231-07263d6284db
2014-04-20 19:13:10 +00:00
DRC
a6ef282a49 Some of the IJG headers say "Modified by", so clarify that our "Modifications" are not referring to these.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.3.x@1053 632fc199-4ca6-4c93-a231-07263d6284db
2013-09-28 03:23:49 +00:00
DRC
cf763c0cd8 Further changes to the copyright/attribution notices to make it clear that our modified files are not part of the IJG's software.
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.2.x@876 632fc199-4ca6-4c93-a231-07263d6284db
2013-01-01 09:51:37 +00:00
DRC
049aef51d4 Eliminate excessive I/O overhead when reading BMP files in cjpeg
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.1.x@592 632fc199-4ca6-4c93-a231-07263d6284db
2011-04-25 22:41:14 +00:00