Compare commits

..

272 Commits

Author SHA1 Message Date
DRC
8162eddf04 Fix issues w/ partial img decompr + buf img mode
Fixes #611
2022-08-08 16:03:55 -05:00
DRC
2e136a7190 Re-fix buf img mode decompr err w/short prog JPEGs
This commit reverts 4dbc293125 and
9f8f683e74 (the previous two commits) and
fixes #613 the correct way.  The crux of the issue wasn't the size of
the whole_image virtual array but rather that, since last_iMCU_row is
unsigned, (last_iMCU_row - 1) wrapped around to 0xFFFFFFFF when
last_iMCU_row was 0.  This caused the interblock smoothing algorithm
introduced in 6d91e950c8 to erroneously
try to access the next two iMCU rows, neither of which existed.  The
first attempt at a fix (4dbc293125)
exposed a NULL dereference, detected by OSS-Fuzz, that occurred when
attempting to decompress a specially-crafted malformed JPEG image to a
YUV buffer using tjDecompressToYUV*() with 1/4 IDCT scaling.

Fixes #613 (again)
Also fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=49898
2022-08-08 15:06:56 -05:00
DRC
9f8f683e74 jdcoefct.c: Fix signed/unsigned mismatch VC++ wrng
(introduced by previous commit)
2022-08-07 14:15:03 -05:00
DRC
4dbc293125 Fix buf image mode decompr err w/ short prog JPEGs
Regression introduced by 6d91e950c8

Because we're now using a 5x5 smoothing window when decompressing
progressive JPEG images, we need to ensure that the whole_image virtual
array contains at least five rows.  Previously that was not always the
case unless the progressive JPEG image being decompressed had at least
five iMCU rows.  Since an iMCU has a height of (8 * the vertical
sampling factor), attempting to decompress 4:2:2 and 4:4:4 images <= 32
pixels in height or 4:2:0 images <= 64 pixels in height triggered a
JERR_BAD_VIRTUAL_ACCESS error in decompress_smooth_data(), because
access_rows exceeded the number of rows in the virtual array.

Fixes #613
2022-08-07 13:38:47 -05:00
Donovan Watteau
59337a67b1 PowerPC: Detect AltiVec support on OS X
libjpeg-turbo's AltiVec SIMD extensions previously assumed that AltiVec
instructions were available on all Power Macs that supported OS X 10.4
"Tiger" (the earliest version of OS X that libjpeg-turbo has ever
supported), but Tiger can actually run on PowerPC G3 processors, which
lack AltiVec instructions.  This commit enables run-time detection of
AltiVec instructions on OS X/PowerPC systems if AltiVec instructions are
not force-enabled at compile time (using -maltivec).  This allows the
same build of libjpeg-turbo to support G3, G4, and G5 Power Macs.

Closes #609
2022-07-07 13:01:11 -05:00
DRC
ba22c0f76d tjDecompressHeader3(): Accept tables-only streams
Inspired by:
b3b15cfe74

Closes #604
Closes #605
2022-06-24 14:10:44 -05:00
DRC
a405519e96 Fix build if UPSAMPLE_MERGING_SUPPORTED undefined
Although it is uncommon, some downstream implementations undefine one or
more of the *_SUPPORTED macros in jmorecfg.h in order to reduce the size
of the library.  In the interest of maintaining backward compatibility
with libjpeg, this is still a supported use case.

Regression introduced by 9120a24743

Based on:
74c4d032f0

Closes #601
2022-05-27 11:59:56 -05:00
Jiaxun Yang
fac8381441 Build: Don't enable Loongson MMI with MIPS R6+
MIPS R6 removed some instructions, so Loongson MMI cannot be built with
MIPS R6+ toolchains.

Closes #598
2022-05-24 09:25:55 -05:00
modbw
290ddbf71a MinGW: Fix str*casecmp() macro redef. warning
MinGW defines strcasecmp() and strncasecmp() as macros in string.h if
__CRT__NO_INLINE is defined, which will be the case when including any
of the Win32 API headers.

Closes #594
2022-04-28 20:02:28 -05:00
DRC
9171fd4bde OSS-Fuzz: '.' --> '_' in fuzzer suffix
Referring to https://github.com/google/oss-fuzz/issues/7575, if the
fuzzer suffix contains periods, it can cause ClusterFuzz to misinterpret
the file extension of the fuzzer executables and thus misidentify them.
2022-04-27 12:34:28 -05:00
DRC
d0e7c4548a Don't install libturbojpeg.pc if WITH_TURBOJPEG=0
Fixes #593
2022-04-18 11:34:57 -05:00
Alex Richardson
dfc63d42ee Fix non-SIMD alignment if void* bigger than double
When building without the SIMD extensions, memory allocations are
currently aligned to sizeof(double).  However, this may be insufficient
on architectures such as Arm Morello or 64-bit CHERI-RISC-V where
pointers require 16-byte rather than 8-byte alignment.  This patch
causes memory allocations to be aligned to
MAX(sizeof(void *), sizeof(double)) when building without the SIMD
extensions.

(NOTE: With C11 we could instead use alignof(max_align_t), but C89
compatibility is still necessary in libjpeg-turbo.)

Closes #587
2022-04-12 13:53:56 -05:00
DRC
67cb059046 OSS-Fuzz: Allow fuzzer suffix to be specified
This facilitates fuzzing multiple branches of the code.
2022-04-06 11:15:54 -05:00
DRC
5c8cac97c0 CI: Un-integrate CIFuzz
Referring to the conversation in
https://github.com/google/oss-fuzz/issues/7479 and #559, there was a
misunderstanding regarding how CIFuzz works.  It cannot be used to fuzz
arbitrary PRs or code branches, and it has a 90-day delay in downloading
corpora from OSS-Fuzz.  That makes it unsuitable for libjpeg-turbo.
2022-04-06 10:58:53 -05:00
DRC
df3c3dcb9b BUILDING.md: Generify PowerTools repo advice
This advice applies to CentOS Stream as well as to popular CentOS 8
replacements, such as Rocky Linux and AlmaLinux.
2022-03-31 10:28:17 -05:00
DRC
2ee7264d40 Build: Don't set DEFAULT_FLOATTEST for x86 MSVC
Newer versions of the 32-bit x86 Visual Studio compiler produce results
compatible with FLOATTEST=no-fp-contract, so we can no longer
intelligently set a default FLOATTEST value for that platform.
2022-03-11 17:32:58 -06:00
DRC
30cba2a2f8 Build/Win: Fix CMake warning when WITH_TURBOJPEG=0
When 12-bit-per-component JPEG support is enabled (WITH_12BIT=1) or the
TurboJPEG API library and associated test programs are disabled
(WITH_TURBOJPEG=0), the Windows installer target should not depend on
the turbojpeg, turbojpeg-static, and tjbench targets.
2022-03-11 11:55:50 -06:00
DRC
a014845403 Win: Fix build with Visual Studio 2010
(broken by 607b668ff9)

- Visual Studio 2010 apparently doesn't have the snprintf() inline
  function, so restore the macro that emulates that function using
  _snprintf_s().

- Explicitly include errno.h in strtest.c, since jinclude.h doesn't
  include it when building with Visual Studio.
2022-03-11 11:19:40 -06:00
DRC
f3c716a2bc Link Sponsor button to GitHub Sponsors ...
... instead of PayPal.
2022-03-10 22:31:20 -06:00
DRC
6f1534d618 example.txt: Fix a typo 2022-03-09 12:58:55 -06:00
DRC
9abeff46d8 Remove extraneous #include directives
jinclude.h already includes stdio.h, stdlib.h, and string.h.
2022-03-09 11:49:27 -06:00
DRC
932b5bb0d5 IJG dox: Wordsmithing and formatting tweaks
- Remove the section in libjpeg.txt that advised against building
  libjpeg as a shared library.  We obviously do not follow that advice,
  and libjpeg-turbo does guarantee backward ABI compatibility in our
  libjpeg API library, even though libjpeg did not and does not.
  (Future expansion of our libjpeg API library, if necessary, will be
  accomplished using get/set functions that store the new parameters
  in the opaque master structs.  Refer to
  db2986c96f.)

- Unmention install.txt, which was never relevant to libjpeg-turbo and
  was removed in v1.3 (6f96153c67).

- Remove extraneous spaces.

- Document the fact that TWO_FILE_COMMANDLINE must be defined in order
  to use the two-file interface with cjpeg, djpeg, jpegtran, and
  wrjpgcom.  libjpeg-turbo never enables that interface by default.
2022-03-09 11:49:27 -06:00
DRC
fdab4a7af4 Progs: Eliminate obsolete Mac ccommand() interface
ccommand() was a 1990s-vintage hack for running console applications
without a console.  It doesn't exist in any modern macOS compiler.
2022-03-08 17:31:11 -06:00
DRC
0565548191 BUILDING.md: Mention sub-project best practices
People keep trying to include libjpeg-turbo into downstream CMake-based
build systems by way of the add_subdirectory() function and requesting
upstream support when something inevitably breaks.

(Refer to: #122, #173, #176, #202, #241, #349, #353, #412, #504,
a3d4aadd0d (commitcomment-67575889)).

libjpeg-turbo has never supported that method of sub-project
integration, because doing so would require that we (minimally):

1. avoid using certain CMake variables, such as CMAKE_SOURCE_DIR,
   CMAKE_BINARY_DIR, and CMAKE_PROJECT_NAME;
2. avoid using implicit include directories and relative paths;
3. provide a way to optionally skip the installation of libjpeg-turbo
   components in response to 'make install';
4. provide a way to optionally postfix target names, to avoid namespace
   conflicts;
5. restructure the top-level CMakeLists.txt so that it properly sets
   the PROJECT_VERSION variable; and
6. design automated CI tests to ensure that new commits don't break
   any of the above.

Even if we did all of that, issues would still arise, because it is
impossible for one upstream build system to anticipate the widely
varying needs of every downstream build system.  That's why the CMake
ExternalProject_Add() function exists, and it is my sincere hope that
adding a blurb to BUILDING.md mentioning the need to use that function
will head off future GitHub issues on this topic.  If not, then I can at
least post a link to this commit and the blurb and avoid doing the same
song and dance over and over again.
2022-02-28 22:27:58 -06:00
Jonathan Wright
c5f269eb96 Neon/AArch64: Explicitly unroll quant loop w/Clang
The loop in jsimd_quantize_neon() is only executed twice and should be
unrolled for AArch64 targets.  GCC does that by default, but Clang 11
and later versions available at the time of this writing do not.  This
patch adds an unroll pragma when targetting AArch64 with Clang.  We do
not use the unroll pragma for AArch32 targets, because it causes the
Clang-generated assembly code to exhaust the available Neon registers
(32 x 64-bit) and spill to the stack.  (DRC: Referring to the discussion
in #570, this is likely due to compiler confusion that results in poor
register allocation.  It is possible to eliminate the spillage and
reduce the instruction count by loading the data on a just-in-time
basis, thus explicitly interleaving compute and I/O, but the performance
implications of that are currently unknown.)

The effects of unrolling the quantization loop are:
1) elimination of the loop control flow overhead and
2) enabling the use of LDP/STP instructions that work from a single
   base pointer, instead of using double the number of LDR/STR
   instructions, each requiring an address calculation.

Closes #570
2022-02-25 12:53:05 -06:00
DRC
98bc3eeb3a Neon/AArch64: Fix/suppress UBSan warnings
- Suppress a UBSan warning regarding storing a 64-bit value to a
  non-64-bit-aligned address.  That behavior is technically undefined
  per the C spec but is supported in the context of the AArch64
  architecture and compilers.

- Explicitly promote block_diff[i] to unsigned int prior to left
  shifting it, in order to avoid a UBSan warning.  This warning also
  described behavior that is technically undefined per the C spec but is
  supported in the context of the AArch64 architecture and compilers.
  Changing the type cast order eliminated the warning without changing
  the generated assembly code.

Closes #582
2022-02-25 00:02:14 -06:00
Jonathan Wright
147548c055 Neon/AArch64: Accelerate Huffman encoding
- Make better use of 128-bit vector registers, thus reducing the number
  of Neon instructions required to construct the AC coefficient bitmap.

- Refactor the Neon computations of 'nbits' and 'diff' to use shorter
  and higher-throughput instruction sequences.

DRC's notes:

This commit partially integrates #570.  Arm reported a 1-4% speedup on
Cortex-A55 and Neoverse-N1 cores when using recent compilers but little
or no speedup with Clang 10.  I observed no speedup with Clang 10 on my
Cortex-A53 and Cortex-A72 cores.  Thus, referring to #582, the primary
purpose of this commit is to fix UBSan warnings regarding the shift
operations previously located at Line 253:

d640a45730/simd/arm/aarch64/jchuff-neon.c (L253)
2022-02-24 23:31:32 -06:00
DRC
d640a45730 AppVeyor: Test strict MSVC compiler warnings 2022-02-23 17:02:24 -06:00
DRC
eb21c023ab Eliminate incompatible pointer type warnings
(C4057 in MSVC and -Wincompatible-pointer-types in GCC/Clang)
2022-02-23 15:57:05 -06:00
DRC
13377e6b38 MSVC: Eliminate int conversion warnings (C4244) 2022-02-23 15:57:05 -06:00
DRC
607b668ff9 MSVC: Eliminate C4996 warnings in API libs
The primary purpose of this is to encourage adoption of libjpeg-turbo in
downstream Windows projects that forbid the use of "deprecated"
functions.  libjpeg-turbo's usage of those functions was not actually
unsafe, because:

- libjpeg-turbo always checks the return value of fopen() and ensures
  that a NULL filename can never be passed to it.

- libjpeg-turbo always checks the return value of getenv() and never
  passes a NULL argument to it.

- The sprintf() calls in format_message() (jerror.c) could never
  overflow the destination string buffer or leave it unterminated as
  long as the buffer was at least JMSG_LENGTH_MAX bytes in length, as
  instructed. (Regardless, this commit replaces those calls with
  snprintf() calls.)

- libjpeg-turbo never uses sscanf() to read strings or multi-byte
  character arrays.

- Because of b7d6e84d6a, wrjpgcom
  explicitly checks the bounds of the source and destination strings
  before calling strcat() and strcpy().

- libjpeg-turbo always ensures that the destination string is
  terminated when using strncpy().
  (548490fe5e made this explicit.)

Regarding thread safety:

Technically speaking, getenv() is not thread-safe, because the returned
pointer may be invalidated if another thread sets the same environment
variable between the time that the first thread calls getenv() and the
time that that thread uses the return value.  In practice, however, this
could only occur with libjpeg-turbo if:

(1) A multithreaded calling application used the deprecated and
undocumented TJFLAG_FORCEMMX/TJFLAG_FORCESSE/TJFLAG_FORCESSE2 flags in
the TurboJPEG API or set one of the corresponding environment variables
(which are only intended for testing purposes.)  Since the TurboJPEG API
library only ever passed string constants to putenv(), the only inherent
risk (i.e. the only risk introduced by the library and not the calling
application) was that the SIMD extensions may have read an incorrect
value from one of the aforementioned environment variables.

or

(2) A multithreaded calling application modified the value of the
JPEGMEM environment variable in one thread while another thread was
reading the value of that environment variable (in the body of
jpeg_create_compress() or jpeg_create_decompress().)  Given that the
libjpeg API provides a thread-safe way for applications to modify the
default memory limit without using the JPEGMEM environment variable,
direct modification of that environment variable by calling applications
is not supported.

Microsoft's implementation of getenv_s() does not claim to be
thread-safe either, so this commit uses getenv_s() solely to mollify
Visual Studio.  New inline functions and macros (GETENV_S() and
PUTENV_S) wrap getenv_s()/_putenv_s() when building for Visual Studio
and getenv()/setenv() otherwise, but GETENV_S()/PUTENV_S() provide no
advantages over getenv()/setenv() other than parameter validation.  They
are implemented solely for convenience.

Technically speaking, strerror() is not thread-safe, because the
returned pointer may be invalidated if another thread changes the locale
and/or calls strerror() between the time that the first thread calls
strerror() and the time that that thread uses the return value.  In
practice, however, this could only occur with libjpeg-turbo if a
multithreaded calling application encountered a file I/O error in
tjLoadImage() or tjSaveImage().  Since both of those functions
immediately copy the string returned from strerror() into a thread-local
buffer, the risk is minimal, and the worst case would involve an
incorrect error string being reported to the calling application.
Regardless, this commit uses strerror_s() in the TurboJPEG API library
when building for Visual Studio.  Note that strerror_r() could have been
used on Un*x systems, but it would have been necessary to handle both
the POSIX and GNU implementations of that function and perform
widespread compatibility testing.  Such is left as an exercise for
another day.

Fixes #568
2022-02-23 15:57:01 -06:00
DRC
ab6cae6f3b BUILDING.md: Clarify that Ninja works with Windows 2022-02-22 10:23:19 -06:00
DRC
3ccb6ead23 BUILDING.md: Remove NASM RPM rebuild instructions
All currently supported Linux platforms now provide a recent enough
version of either NASM or Yasm.
2022-02-11 10:05:18 -06:00
DRC
6441ad0f83 BUILDING.md: Document NASM/Yasm path variables
This was an oversight from the CMake build system overhaul in
libjpeg-turbo 2.0 (6abd39160c).

Closes #580
2022-02-11 10:02:28 -06:00
DRC
6d2d6d3baf "YASM" = "Yasm"
The assembler name was initially spelled "YASM", but it has been "Yasm"
for the entirety of libjpeg-turbo's existence.
2022-02-11 09:34:01 -06:00
DRC
e1588a2a7b Build: Fix Neon capability detection w/ MSVC
(broken by 57ba02a408)

Refer to #547
2022-02-10 22:24:19 -06:00
DRC
548490fe5e Ensure that strncpy() dest strings are terminated
- Since the ERREXITS() and TRACEMSS() macros are never used internally
  (they are a relic of the legacy memory managers that libjpeg
  provided), the only risk was that an external program might have
  invoked one of those macros with a string longer than 79 characters
  (JMSG_STR_PARM_MAX - 1).

- TJBench never invokes the THROW_TJ() macro with a string longer than
  199 (JMSG_LENGTH_MAX - 1) characters, so there was no risk.  However,
  it's a good idea to explicitly terminate the destination strings so
  that anyone looking at the code can immediately tell that it is safe.
2022-02-10 11:52:48 -06:00
DRC
b579fc114d Eliminate unnecessary JFREAD()/JFWRITE() macros 2022-02-09 16:07:18 -06:00
DRC
a3d4aadd0d Build: Embed version/API/(C) info in MSVC DLLs
Based on:
da7a18801a

Closes #576
2022-02-01 13:00:42 -06:00
DRC
d7d16df646 Fix segv w/ h2v2 merged upsamp, jpeg_crop_scanline
The h2v2 (4:2:0) merged upsampler uses a spare row buffer so that it can
upsample two rows at a time but return only one row to the application,
if necessary.  merged_2v_upsample() copies from this spare row buffer
into the application-supplied output buffer, using the out_row_width
field in the my_merged_upsampler struct to determine how many samples to
copy.  out_row_width is set in jinit_merged_upsampler(), which is called
within the body of jpeg_start_decompress().  Since jpeg_crop_scanline()
must be called after jpeg_start_decompress(), jpeg_crop_scanline() must
modify the value of out_row_width if the h2v2 merged upsampler will be
used.  Otherwise, merged_2v_upsample() can overflow the output buffer if
the number of bytes between the current output buffer position and the
end of the buffer is less than the number of bytes required to represent
an uncropped scanline of the output image.  All of the destination
managers used by djpeg allocate either a whole image buffer or a
scanline buffer based on the uncropped output image width, so this issue
is not reproducible using djpeg.

Fixes #574
2022-02-01 10:52:08 -06:00
DRC
14ce28a92d TJBench: Remove innocuous always-true condition
This was accidentally introduced into tjbench.c in
890f1e0413 and ported into the Java
version from there.

Based on
4be6d4e7bd

Refer to #571
2022-01-29 12:37:15 -06:00
DRC
da41ab94e7 GitHub Actions: Specify Catalina for macOS build
macos-latest now maps to the Big Sur image, which doesn't have Xcode
12.2 installed.
2022-01-06 12:57:26 -06:00
DRC
1f55ae7b0f Fix -Wpedantic compiler warnings
... and test for those warnings (and others) when performing CI builds.
2022-01-06 12:33:22 -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
Dmitry Tsarevich
a7f0244e9b turbojpeg.h: Parenthesize TJSCALED() dimension arg
This ensures that, for example,
TJSCALED(dim0 + dim1, sf)

will evaluate to
(((dim0 + dim1) * sf.num + sf.denom - 1) / sf.denom)

rather than
((dim0 + (dim1 * sf.num) + sf.denom - 1) / sf.denom)
2022-01-06 05:26:02 -06:00
DRC
a01857cff6 Build: Disallow NEON_INTRINSICS=0 if GAS is broken
If NEON_INTRINSICS=0, then run the GAS sanity check from libjpeg-turbo
2.0.x and force-enable NEON_INTRINSICS if the test fails.  This fixes
the AArch32 build when using Clang 6.0 on Linux or the Clang toolchain
in the Android NDK r15*-r16*.  It also prevents users from manually
disabling NEON_INTRINSICS if doing so would break the build (such as
with Xcode 5.)
2021-12-01 19:10:14 -06:00
DRC
57ba02a408 Build: Improve Neon capability detection
- Use check_c_source_compiles() rather than check_symbol_exists() to
  detect the presence of vld1_s16_x3(), vld1_u16_x2(), and
  vld1q_u8_x4().  check_symbol_exists() is unreliable for detecting
  intrinsics, and in practice, it did not detect the presence of the
  aforementioned intrinsics in versions of GCC that support them.

- Set DEFAULT_NEON_INTRINSICS=0 for GCC < 12, even if the aforementioned
  intrinsics are available.  The AArch64 back end in GCC 10 and 11
  supports the necessary intrinsics, but the GAS implementation is still
  faster when using those compilers.

Fixes #547
2021-12-01 11:26:57 -06:00
DRC
8a9a6dd15a Make incompatible feature errs more user-friendly
- Use JERR_NOTIMPL ("Not implemented yet") rather than JERR_NOT_COMPILED
  ("Requested feature was omitted at compile time") to indicate that
  arithmetic coding is incompatible with Huffman table optimization.
  This is more consistent with other parts of the libjpeg API code.
  JERR_NOT_COMPILED is typically used to indicate that a major feature
  was not compiled in, whereas JERR_NOTIMPL is typically used to
  indicate that two features were compiled in but are incompatible with
  each other (such as, for instance, two-pass color quantization and
  partial image decompression.)

- Change the text of JERR_NOTIMPL to "Requested features are
  incompatible".  This is a more accurate description of the situation.
  "Not implemented yet" implies that it may be possible to support the
  requested combination of features in the future, but that is not true
  in most of the cases where JERR_NOTIMPL is used.

Fixes #567
2021-12-01 09:43:15 -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
2ce32e0fe5 cjpeg: automatically compress PGM-->grayscale JPEG
(regression introduced by aa7459050d)

cjpeg sets cinfo.in_color_space to JCS_RGB as an "arbitrary guess."
Since tjLoadImage() never uses JCS_RGB, the PGM reader should treat
JCS_RGB the same as JCS_UNKNOWN.

Fixes #566
2021-11-30 16:09:21 -06:00
DRC
e869a81a7a jdarith.c: Require cinfo->Se == DCTSIZE2 - 1
This fixes an oversight from the integration of the arithmetic entropy
codec from libjpeg (66f97e6820).  I chose
to integrate the latest implementation available at the time, which was
from jpeg-8b.  However, I naively replaced cinfo->lim_Se with
DCTSIZE2 - 1, not realizing that-- because of SmartScale-- jpeg-8b
contains additional code
(https://github.com/libjpeg-turbo/libjpeg-turbo/blob/jpeg-8b/jdinput.c#L249-L334)
that guards against illegal values of cinfo->Se >= DCTSIZE2.  Thus,
libjpeg-turbo's implementation of arithmetic decoding has never guarded
against such illegal values.  This commit restores the relevant check
from the original jpeg-6b arithmetic entropy codec patch ("jpeg-ari",
1e247ac854).

Fixes #564
2021-11-23 10:41:29 -06:00
DRC
5446ff88d6 CI: CIFuzz integration
CIFuzz runs the project's fuzzers for a limited period of time any time
a commit is pushed or a PR is submitted.  This is not intended to
replace OSS-Fuzz but rather to allow us to more quickly catch some
fuzzing failures, including fuzzer build regressions like the one
introduced in ecf021bc0d.

Closes #559
2021-11-19 13:54:07 -06:00
DRC
0f88060b0f cjpeg.c: Fix fuzzer build failure
(caused by previous commit)
2021-11-19 13:36:42 -06:00
DRC
ecf021bc0d cjpeg: Add -strict arg to treat warnings as fatal
This adds fault tolerance to the LZW-compressed GIF reader, which is
the only compression-side code that can throw warnings.
2021-11-18 21:04:35 -06:00
DRC
4c5fa566b3 CI: Halt immediately on all sanitizer errors 2021-11-17 16:09:50 -06:00
Piotr Kubaj
d401d62514 PowerPC: Detect AltiVec support on FreeBSD
Recent FreeBSD/PowerPC compilers, such as Clang 11.0.x on FreeBSD 13, do
the equivalent of passing -maltivec to the compiler by default, so
run-time AltiVec detection is unnecessary.  However, it becomes
necessary when using other compilers or when passing -mno-altivec to the
compiler.

Closes #552
2021-10-30 16:53:51 -05:00
DRC
2fd4ae7b2c JNI: Fix warnings/errors reported by -Xcheck:jni
- Don't check for exceptions immediately after invoking the
  GetPrimitiveArrayCritical() method.  That method does not throw
  exceptions, and checking for them caused -Xcheck:jni to warn about
  calling other JNI functions in the scope of
  Get/ReleasePrimitiveArrayCritical().

- Check for exceptions immediately after invoking the
  CallStaticObjectMethod() method in the PROP2ENV() macro.

- Don't use the Get/ReleasePrimitiveArrayCritical() methods for small
  arrays.  -Xcheck:jni didn't complain about that, but there is no
  performance advantage to using those methods rather than the
  Get*ArrayRegion() methods for small arrays, and using
  Get*ArrayRegion() makes the code less error-prone.

- Don't release the source/destination planes arrays in the YUV methods
  until after the corresponding C TurboJPEG functions have returned.
2021-10-27 14:50:22 -05:00
Alex Xu (Hello71)
18edeff4e8 Build: Set CMP0065 NEW (respect ENABLE_EXPORTS)
Referring to https://cmake.org/cmake/help/latest/policy/CMP0065.html,
CMake 3.3 and earlier automatically added compiler/linker flags such as
-rdynamic/-export-dynamic, which caused symbols to be exported from
executables.  The primary purpose of this is to allow plugins loaded via
dlopen() to access symbols from the calling program.  libjpeg-turbo
does not need this functionality, and enabling it needlessly increases
the size of the libjpeg-turbo executables.

Setting CMP0065 to NEW when using CMake 3.4 and later prevents CMake
from automatically adding the aforementioned compiler/linker flags
unless the ENABLE_EXPORTS property is set for a target (or the
CMAKE_ENABLE_EXPORTS variable is set, which causes ENABLE_EXPORTS to be
set for all targets.)

Closes #554
2021-10-03 13:39:38 -05:00
DRC
a9c41fbc4f Build: Don't enable Neon SIMD exts with Armv6-
When building for 32-bit Arm platforms, test whether basic Neon
intrinsics will compile with the specified compiler and C flags.  This
prevents the build system from enabling the Neon SIMD extensions when
targetting Armv6 and other legacy architectures that do not support Neon
instructions.

Regression introduced by bbd8089297.
(Checking whether gas-preprocessor.pl was needed for 32-bit Arm builds
had the effect of checking whether Neon instructions were supported.)

Fixes #553
2021-10-03 13:10:35 -05:00
DRC
739ecbc5ec ChangeLog.md: List CVE ID fixed by 2849d86a 2021-09-30 16:28:51 -05:00
DRC
4c313544e2 AppVeyor: Deploy artifacts to Amazon S3
We would have been perfectly happy for AppVeyor to delete all artifacts
other than those from the latest builds in each branch.  Instead, they
chose to change the global artifact retention policy to 1 month.  In
addition to being unworkable, that new policy uses more storage than the
policy we requested.  Lose/lose, so we'll just deploy to S3 like we do
with other platforms.
2021-09-20 17:12:02 -05:00
DRC
173900b1ca tjTrans: Allow 8x8 crop alignmnt w/odd 4:4:4 JPEGs
Fixes #549
2021-09-02 13:31:11 -05:00
DRC
5d2430f4da ChangeLog.md: Add missing sub-header for 2.1.2 2021-09-02 13:18:10 -05:00
DRC
129f0cb763 Neon/AArch64: Don't put GAS functions in .rodata
Regression introduced by 240ba417aa

Closes #546
2021-08-25 12:54:24 -05:00
DRC
0a9b972178 jmemmgr.c: Pass correct size arg to jpeg_free_*()
This issue was introduced in 5557fd2217
due to an oversight, so it has existed in libjpeg-turbo since the
project's inception.  However, the issue is effectively a non-issue.
Although #325 proposes allowing programs to override jpeg_get_*() and
jpeg_free_*() externally, there is currently no way to override those
functions without modifying the libjpeg-turbo source code.
libjpeg-turbo only includes the malloc()/free() memory manager from
libjpeg, and the implementation of jpeg_free_*() in that memory manager
ignores the size argument.  libjpeg had several additional memory
managers for legacy systems (MS-DOS, System 7, etc.), but those memory
managers ignored the size argument to jpeg_free_*() as well.  Thus, this
issue would have only potentially affected custom memory managers in
downstream libjpeg-turbo forks, and since no one has complained until
now, apparently those are rare.

Fixes #542
2021-08-09 18:16:57 -05:00
DRC
2849d86aaa SSE2/64-bit: Fix trans. segfault w/ malformed JPEG
Attempting to losslessly transform certain malformed JPEG images can
cause the nbits table index in the Huffman encoder to exceed 32768, so
we need to pad the SSE2 implementation of that table to 65536 entries as
we do with the C implementation.

Regression introduced by 087c29e07f

Fixes #543
2021-08-06 14:04:34 -05:00
DRC
84d6306f64 Fix build w/CMake 3.14+ when CMAKE_SYSTEM_NAME=iOS
Closes #539
2021-07-27 11:26:51 -05:00
y-guyon
e6e952d5d5 Suppress UBSan error in decode_mcu_fast()
This is the same error that d147be83e9
suppressed in decode_mcu_slow().  The image that reproduces this error
in decode_mcu_fast() has been added to the libjpeg-turbo seed corpora.

Closes #537
2021-07-16 12:58:00 -05:00
Alex Richardson
a72816ed07 Use uintptr_t, if avail, for pointer-to-int casts
Although sizeof(void *) == sizeof(size_t) for all architectures that are
currently supported by libjpeg-turbo, such is not guaranteed by the C
standard.  Specifically, CHERI-enabled architectures (e.g. CHERI-RISC-V
or Arm's Morello) use capability pointers that are twice the size of
size_t (128 bits for Morello and RV64), so casting to size_t strips the
upper bits of the pointer (including the validity bit) and makes it
non-deferenceable, as indicated by the following compiler warning:

  warning: cast from provenance-free integer type to pointer type will
  give pointer that can not be dereferenced
  [-Werror,-Wcheri-capability-misuse]
    cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16);

Ignoring this warning results in a run-time crash.  Casting pointers to
uintptr_t, if it is available, avoids this problem, since uintptr_t is
defined as an unsigned integer type that can hold a pointer value.

Since C89 compatibility is still necessary in libjpeg-turbo, this commit
introduces a new typedef for pointer-to-integer casts that uses a
GNU-specific extension available in GCC 4.6+ and Clang 3.0+ and falls
back to using size_t if the extension is unavailable.  The only other
options would require C99 or Clang-specific builtins.

Closes #538
2021-07-16 12:23:29 -05:00
DRC
4d9f256b01 jpegtran: Add option to copy only ICC markers
Closes #533
2021-07-13 11:54:31 -05:00
Peter Kasting
b201838d8b Neon: Silence -Wimplicit-fallthrough warnings
Refer to https://bugs.chromium.org/p/chromium/issues/detail?id=995993

Closes #534
2021-07-13 10:21:38 -05:00
DRC
a1bfc05854 Neon/AArch32: Mark inline asm output as read/write
'buffer' is both passed into the inline assembly code and modified by
it.  See https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html, 6.47.2.3.

With GCC 4, this commit does not change the generated assembly code at
all.

With GCC 8, this commit fixes an assembly error:

  /tmp/{foo}.s: Assembler messages:
  /tmp/{foo}.s:775: Error: registers may not be the same --
                    `str r9,[r9],#4'

I'm not sure why that error went unnoticed, since I definitely
benchmarked the previous commit with GCC 8.  Anyhow, this commit changes
the generated assembly code slightly but does not alter performance.

With Clang 10, this commit changes the generated assembly code slightly
but does not alter performance.

Refer to #529
2021-07-12 15:22:24 -05:00
DRC
2a2970af67 Neon/AArch32: Work around Clang T32 miscompilation
Referring to the C standard
(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf,
J.2 Undefined behavior), the behavior of the compiler is undefined if
"conversion between two pointer types produces a result that is
incorrectly aligned."  Thus, the behavior of this code

  *((uint32_t *)buffer) = BUILTIN_BSWAP32(put_buffer);

in the AArch32 version of the FLUSH() macro is undefined unless 'buffer'
is 32-bit-aligned.  Referring to
https://bugs.llvm.org/show_bug.cgi?id=50785, certain versions of Clang,
when generating Thumb (T32) instructions, miscompile that code into an
assembly instruction (stm) that requires the destination to be
32-bit-aligned.  Since such alignment cannot be guaranteed within the
Huffman encoder, this reportedly led to crashes (SIGBUS: illegal
alignment) with AArch32/Thumb builds of libjpeg-turbo running on Android
devices, although thus far I have been unable to reproduce those crashes
with a plain Linux/Arm system.

The miscompilation is visible with the Compiler Explorer:
https://godbolt.org/z/rv1ccx1Pb
However, it goes away when removing the return statement from the
function.  Thus, it seems that Clang's behavior in this regard is
somewhat variable, which may explain why the crashes are only
reproducible on certain platforms.

The suggested workaround is to use memcpy(), but whereas Clang and
recent GCC releases are smart enough to compile a 4-byte memcpy() call
into a str instruction, GCC < 6 is not.  Referring to
https://godbolt.org/z/ae7Wje3P6, the only way to consistently produce
the desired str instruction across all supported compilers is to use
inline assembly.  Visual C++ presumably does not miscompile the code in
question, since no issues have been reported with it, but since the code
relies on undefined compiler behavior, prudence dictates that
e4ec23d7ae should be reverted for Visual
C++, which this commit does.  The performance impact of
e4ec23d7ae for Visual C++/Arm builds is
unknown (I have no ability to test such builds), but regardless, this
commit reverts the Visual C++/Arm performance to that of libjpeg-turbo
2.1 beta1.

Closes #529
2021-07-09 19:37:58 -05:00
DRC
97a1575cb8 RPM: Don't include system lib dir in file list
This resolves a conflict between the RPM generated by the libjpeg-turbo
build system and the Red Hat 'filesystem' RPM if
CMAKE_INSTALL_LIBDIR=/usr/lib[64].  This code was largely borrowed from
the VirtualGL RPM spec.  (I can legally do that because I hold the
copyright on VirtualGL's implementation.)

Fixes #532
2021-07-07 14:51:09 -05:00
DRC
0081c2de20 Neon/AArch32: Fix build if 'soft' float ABI used
Arm compilers have three floating point ABI options:

'soft' compiles floating point operations as function calls into a
software floating point library, which emulates floating point
operations using integer operations.  Floating point function arguments
are passed using integer registers.

'softfp' also compiles floating point operations as function calls into
a floating point library and passes floating point function arguments
using integer registers, but the floating point library functions can
use FPU instructions if the CPU supports them.

'hard' compiles floating point operations into inline FPU instructions,
similarly to x86 and other architectures, and passes floating point
function arguments using FPU registers.

Not all AArch32 CPUs have FPUs or support Neon instructions, so on Linux
and Android platforms, the AArch32 SIMD dispatcher in libjpeg-turbo only
enables the Neon SIMD extensions at run time if /proc/cpuinfo indicates
that the CPU supports Neon instructions or if Neon instructions are
explicitly enabled (e.g. by passing -mfpu=neon to the compiler.)  In
order to support all AArch32 CPUs using the same code base, i.e. to
support run-time FPU and Neon auto-detection, it is necessary to compile
the scalar C source code using -mfloat-abi=soft.  However, the 'soft'
floating point ABI cannot be used when compiling Neon intrinsics, so the
intrinsics implementation of the Neon SIMD extensions must be compiled
using -mfloat-abi=softfp if the scalar C source code is compiled using
-mfloat-abi=soft.

This commit modifies the build system so that it detects whether
-mfloat-abi=softfp must be explicitly added to the compiler flags when
building the intrinsics implementation of the Neon SIMD extensions.
This will be necessary if the build is using the 'soft' floating
point ABI along with run-time auto-detection of Neon instructions.

Fixes #523
2021-07-07 14:10:05 -05:00
Peter Kasting
9df5786f05 Fix -Wimplicit-fallthrough warnings with Clang
The existing /*FALLTHROUGH*/ comments work with GCC but not Clang, so
this commit adds a FALLTHROUGH macro that uses the 'fallthrough'
attribute if the compiler supports it.

Refer to https://bugs.chromium.org/p/chromium/issues/detail?id=995993

NOTE: All versions of GCC that support -Wimplicit-fallthrough also
support the 'fallthrough' attribute, but certain other compilers (Oracle
Solaris Studio, for instance) support /*FALLTHROUGH*/ but not the
'fallthrough' attribute.  Thus, this commit retains the /*FALLTHROUGH*/
comments, which have existed in the libjpeg code base in some form since
1994 (libjpeg v5.)

Closes #531
2021-07-06 12:37:34 -05:00
DRC
1a1fb615db ChangeLog.md: List CVE ID fixed by c76f4a08
Referring to #527, the security community did not assign this CVE ID
until more than 8 months after the fix for the issue was released.  By
the time they assigned the ID, libjpeg-turbo already had two production
releases containing the fix.  This calls into question the usefulness of
assigning a CVE ID to the issue, particularly given that the buffer
overrun in question was fully contained in the stack, not detectable
with valgrind, and confined to lossless transformation (it did not
affect JPEG compression or decompression.)

https://vuldb.com/?id.176175
says that "the exploitability is told to be easy" but provides no
clarification, and given that the author of that page does not seem to
be aware that a fix for the issue has been available since early
December of 2019, it calls into question the accuracy of everything else
on the page.

It would really be nice if the security community approached me about
these things before wasting my time, but I guess it's my lot in life to
modify a change log entry from 2019 to include a CVE ID from 2020.

So it goes...
2021-06-18 10:29:12 -05:00
DRC
5135c2e25d Build: Use PIC for jsimd_none.o in shared libs
In theory, all objects that will be included in a Un*x shared library
must be built using PIC.  In practice, most compilers don't require PIC
to be explicitly specified for jsimd_none.o, either because the compiler
automatically enables PIC in all cases (Ubuntu) or because the size of
the generated object is too small.  But some rare compilers do require
PIC to be explicitly specified for jsimd_none.o.

Fixes #520
2021-05-28 13:09:43 -05:00
DRC
3932190c2e Fix build w/ non-GCC-compatible Un*x/Arm compilers
Regression introduced by d2c4079959

Closes #519
2021-05-17 13:09:37 -05:00
DRC
a219fd13b0 GitHub bug-report.md: "master" branch --> "main" 2021-05-12 10:58:59 -05:00
DRC
c23672ce52 GitHub Actions: Don't build tags
Our workflow script does not currently work with tags, and there is no
point to building tags anyhow, since we do not use the CI system to spin
official builds.
2021-04-23 13:29:40 -05:00
DRC
4f51f36eb3 Bump version to 2.1.0 to prepare for final release 2021-04-23 11:42:40 -05:00
DRC
e0606dafff TurboJPEG: Update JPEG buf ptrs on comp/xform err
When using the in-memory destination manager, it is necessary to
explicitly call the destination manager's term_destination() method if
an error occurs.  That method is called by jpeg_finish_compress() but
not by jpeg_abort_compress().

This fixes a potential double free() that could occur if tjCompress*()
or tjTransform() returned an error and the calling application tried to
clean up a JPEG buffer that was dynamically re-allocated by one of those
functions.
2021-04-21 15:42:00 -05:00
DRC
ffc1aa9674 Include TJ.FLAG_LIMITSCANS in JNI header
(oversight from c81e91e8ca)

This is purely cosmetic, since the JNI wrapper doesn't actually use that
flag.
2021-04-21 12:33:00 -05:00
DRC
55ec9b3b89 OSS-Fuzz: Code comment tweaks for compr. targets
(oversight from 171b875b27)
2021-04-21 12:33:00 -05:00
DRC
4de8f6922a jdhuff.h: Fix ASan regression caused by 8fa70367
The 0xFF is, in fact, necessary.
2021-04-16 16:34:12 -05:00
DRC
785ec30eb4 cjpeg_fuzzer: Add cov for h2v2 smooth downsampling 2021-04-16 15:59:38 -05:00
DRC
d147be83e9 Huff decs: Fix/suppress more innocuous UBSan errs
- UBSan complained that entropy->restarts_to_go was underflowing an
  unsigned integer when it was decremented while
  cinfo->restart_interval == 0.  That was, of course, completely
  innocuous behavior, since the result of the underflowing computation
  was never used.

- d3a3a73f64 and
  7bc9fca430 silenced a UBSan signed
  integer overflow error, but unfortunately other malformed JPEG images
  have been discovered that cause unsigned integer overflow in the same
  computation.  Since, to the best of our understanding, this behavior
  is innocuous, this commit reverts the commits listed above, suppresses
  the UBSan errors, and adds code comments to document the issue.
2021-04-15 23:46:15 -05:00
DRC
8fa70367ed Huff dec: Fix non-deterministic output w/bad input
Referring to https://bugzilla.mozilla.org/show_bug.cgi?id=1050342,
there are certain very rare circumstances under which a malformed JPEG
image can cause different Huffman decoder output to be produced,
depending on the size of the source manager's I/O buffer.  (More
specifically, the fast Huffman decoder didn't handle invalid codes in
the same manner as the slow decoder, and since the fast decoder requires
all data to be memory-resident, the buffering strategy determines
whether or not the fast decoder can be used on a particular MCU block.)

After extensive experimentation, the Mozilla and Chrome developers and I
determined that this truly was an innocuous issue.  The patch that both
browsers adopted as a workaround caused a performance regression with
32-bit code, which is why it was not accepted into libjpeg-turbo.  This
commit fixes the problem in a less disruptive way with no performance
regression.
2021-04-15 22:55:50 -05: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
3ab3234875 OSS-Fuzz: More code coverage improvements 2021-04-13 11:58:20 -05:00
DRC
3e68a5ee20 jchuff.c: Fix MSan error
Certain rare malformed input images can cause the Huffman encoder to
generate a value for nbits that corresponds to an uninitialized member
of the DC code table.  The ramifications of this are minimal and would
basically amount to a different bogus JPEG image being generated from a
particular bogus input image.
2021-04-12 14:37:43 -05:00
DRC
4e45161654 compress_yuv_fuzzer: Minor code coverage tweak 2021-04-12 11:53:29 -05:00
DRC
629e96eedc cjpeg.c: Code formatting tweak 2021-04-12 11:52:55 -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
4ede2ef523 OSS-Fuzz: cjpeg fuzz target 2021-04-09 19:27:22 -05:00
DRC
5cda8c5e31 compress_yuv_fuzzer: Use unique filename template 2021-04-09 13:12:32 -05:00
DRC
47b66d1d1e OSS-Fuzz: Fix UBSan err caused by TJFLAG_FUZZING 2021-04-09 11:26:34 -05:00
DRC
55ab0d396c OSS-Fuzz: YUV encoding/compression fuzz target 2021-04-08 16:13:06 -05:00
DRC
18bc4c6114 compress.cc: Code formatting tweak 2021-04-07 16:08:59 -05:00
DRC
b1079002ad rdppm.c: Fix innocuous MSan error
A fuzzing test case that was effectively a 1-pixel PGM file with a
maximum value of 1 and an actual value of 8 caused an uninitialized
member of the rescale[] array to be accessed in get_gray_rgb_row() or
get_gray_cmyk_row().  Since, for performance reasons, those functions do
not perform bounds checking on the PPM values, we need to ensure that
unused members of the rescale[] array are initialized.
2021-04-07 16:08:48 -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
34d264d64e OSS-Fuzz: Private TurboJPEG API flag for fuzzing
This limits the tjLoadImage() behavioral changes to the scope of the
compress_fuzzer target.  Otherwise, TJBench in fuzzer builds would
refuse to load images larger than 1 Mpixel.
2021-04-07 15:09:29 -05:00
DRC
f35fd27ec6 tjLoadImage: Fix issues w/loading 16-bit PPMs/PGMs
- The PPM reader now throws an error rather than segfaulting (due to a
  buffer overrun) if an application attempts to load a 16-bit PPM file
  into a grayscale uncompressed image buffer.  No known applications
  allowed that (not even the test applications in libjpeg-turbo),
  because that mode of operation was never expected to work and did not
  work under any circumstances.  (In fact, it was necessary to modify
  TJBench in order to reproduce the issue outside of a fuzzing
  environment.)  This was purely a matter of making the library bow out
  gracefully rather than crash if an application tries to do something
  really stupid.

- The PPM reader now throws an error rather than generating incorrect
  pixels if an application attempts to load a 16-bit PGM file into an
  RGB uncompressed image buffer.

- The PPM reader now correctly loads 16-bit PPM files into extended
  RGB uncompressed image buffers.  (Previously it generated incorrect
  pixels unless the input colorspace was JCS_RGB or JCS_EXT_RGB.)

The only way that users could have potentially encountered these issues
was through the tjLoadImage() function.  cjpeg and TJBench were
unaffected.
2021-04-06 16:12:29 -05:00
DRC
df17d398ec jcphuff.c: -Wjump-misses-init warning w/GCC 9 -m32
(verified that this commit does not change the generated 64-bit or
32-bit assembly code)
2021-04-06 14:11:32 -05:00
DRC
cd9a318502 Bump TurboJPEG C API version to 2.1
(because of TJFLAG_LIMITSCANS)
2021-04-05 22:20:52 -05:00
DRC
d2d4465548 OSS-Fuzz: Compression fuzz target 2021-04-05 21:59:11 -05:00
DRC
5536ace198 OSS-Fuzz: Fix C++11 compiler warnings in targets 2021-04-05 21:12:29 -05:00
DRC
5dd906beff OSS-Fuzz: Test non-default opts w/ decompress_yuv
The non-default options were not being tested because of a pixel format
comparison buglet.  This commit also changes the code in both
decompression fuzz targets such that non-default options are tested
based on the pixel format index rather than the pixel format value,
which is a bit more idiot-proof.
2021-04-05 17:53:15 -05:00
DRC
c81e91e8ca TurboJPEG: New flag for limiting prog JPEG scans
This also fixes timeouts reported by OSS-Fuzz.
2021-04-05 16:33:44 -05:00
DRC
bff7959e34 OSS-Fuzz: Require static libraries
Refer to
https://google.github.io/oss-fuzz/further-reading/fuzzer-environment/#runtime-dependencies
for the reasons why this is necessary.
2021-04-02 14:58:55 -05:00
DRC
6ad658be17 OSS-Fuzz: Build fuzz targets using C++ compiler
Otherwise, the targets will require libstdc++, the i386 version of which
is not available in the OSS-Fuzz runtime environment.  The OSS-Fuzz
build environment passes -stdlib:libc++ in the CXXFLAGS environment
variable in order to mitigate this issue, since the runtime environment
has the i386 version of libc++, but using that compiler flag requires
using the C++ compiler.
2021-04-02 14:58:31 -05:00
DRC
7b57cba6b4 OSS-Fuzz: Fix uninitialized reads detected by MSan 2021-04-01 11:30:24 -05:00
DRC
2f9e8a1172 OSS-Fuzz integration
This commit integrates OSS-Fuzz targets directly into the libjpeg-turbo
source tree, thus obsoleting and improving code coverage relative to
Google's OSS-Fuzz target for libjpeg-turbo (previously available here:
https://github.com/google/oss-fuzz).

I hope to eventually create fuzz targets for the BMP, GIF, and PPM
readers as well, which would allow for fuzz-testing compression, but
since those readers all require an input file, it is unclear how to
build an efficient fuzzer around them.  It doesn't make sense to
fuzz-test compression in isolation, because compression can't accept
arbitrary input data.
2021-03-30 20:59:41 -05:00
Jonathan Wright
e4ec23d7ae Neon: Use byte-swap builtins instead of inline asm
Define compiler-independent byte-swap macros and use them instead of
executing 'rev' via inline assembly code with GCC-compatible compilers
or a slow shift-store sequence with Visual C++.

* This produces identical assembly code with:

  - 64-bit GCC 8.4.0 (Linux)
  - 64-bit GCC 9.3.0 (Linux)
  - 64-bit Clang 10.0.0 (Linux)
  - 64-bit Clang 10.0.0 (MinGW)
  - 64-bit Clang 12.0.0 (Xcode 12.2, macOS)
  - 64-bit Clang 12.0.0 (Xcode 12.2, iOS)

* This produces different assembly code with:

  - 64-bit GCC 4.9.1 (Linux)
  - 32-bit GCC 4.8.2 (Linux)
  - 32-bit GCC 8.4.0 (Linux)
  - 32-bit GCC 9.3.0 (Linux)
    Since the intrinsics implementation of Huffman encoding is not used
    by default with these compilers, this is not a concern.

  - 32-bit Clang 10.0.0 (Linux)
    Verified performance neutrality

Closes #507
2021-03-26 14:09:10 -05:00
DRC
e795afc330 SSE2: Fix prog Huff enc err if Sl%32==0 && Al!=0
(regression introduced by 16bd984557)

This implements the same fix for
jsimd_encode_mcu_AC_refine_prepare_sse2() that
a81a8c137b implemented for
jsimd_encode_mcu_AC_first_prepare_sse2().

Based on:
1a59587397
eb176a91d8

Fixes #509
Closes #510
2021-03-25 22:46:14 -05:00
Adrian Bunk
2c01200c5d Build: Fix incorrect regexes w/ if(...MATCHES...)
"arm*" as a regex means 'ar' followed by zero or more 'm' characters,
which matches 'parisc' and 'sparc64' as well.
2021-03-15 12:56:53 -05:00
DRC
ed70101da2 ChangeLog.md: List CVE ID fixed by 1719d12e
Referring to https://bugzilla.redhat.com/show_bug.cgi?id=1937385#c2,
it is my opinion that the severity of this bug was grossly overstated
and that a CVE never should have been assigned to it, but since one was
assigned, users need to know which version of libjpeg-turbo contains
the fix.

Dear security community, please learn what "DoS" actually means and stop
misusing that term for dramatic effect.  Thanks.
2021-03-15 12:36:55 -05:00
DRC
8a2cad0201 Build: Handle CMAKE_OSX_ARCHITECTURES=(i386|ppc)
We don't officially support i386 or PowerPC Mac builds of libjpeg-turbo
anymore, but they still work (bearing in mind that PowerPC builds
require GCC v4.0 in Xcode 3.2.6, and i386 builds require Xcode 9.x or
earlier.)  Referring to #495, apparently MacPorts needs this
functionality.
2021-01-21 10:51:49 -06:00
DRC
b6772910d3 Add Sponsor button for GitHub repository 2021-01-19 15:32:32 -06:00
DRC
399aa374bd Build: Support CMAKE_OSX_ARCHITECTURES
... as long as it contains only a singular value, which must equal
"x86_64" or "arm64".

Refer to #495
2021-01-19 12:25:11 -06:00
DRC
1719d12e51 cjpeg: Fix FPE when compressing 0-width GIF
Fixes #493
2021-01-14 18:38:06 -06:00
DRC
486cdcfb9d Fix build with Visual C++ and /std:c11 or /std:c17
Fixes #481
Closes #482
2021-01-12 17:45:55 -06:00
Richard Townsend
74e6ea45e3 Neon: Fix Huffman enc. error w/Visual Studio+Clang
The GNU builtin function __builtin_clzl() accepts an unsigned long
argument, which is 8 bytes wide on LP64 systems (most Un*x systems,
including Mac) but 4 bytes wide on LLP64 systems (Windows.)  This caused
the Neon intrinsics implementation of Huffman encoding to produce
mathematically incorrect results when compiled using Visual Studio with
Clang.

This commit changes all invocations of __builtin_clzl() in the Neon SIMD
extensions to __builtin_clzll(), which accepts an unsigned long long
argument that is guaranteed to be 8 bytes wide on all systems.

Fixes #480
Closes #490
2021-01-11 22:29:11 -06:00
Jonathan Wright
d2c4079959 Use CLZ compiler intrinsic for Windows/Arm builds
The __builtin_clz() compiler intrinsic was already used in the C Huffman
encoders when building libjpeg-turbo for Arm CPUs using a GCC-compatible
compiler.  This commit modifies the C Huffman encoders so that they also
use__builtin_clz() when building for Arm CPUs using Visual Studio +
Clang, as well as the equivalent _CountLeadingZeros() compiler intrinsic
when building for Arm CPUs using Visual C++.

In addition to making the C Huffman encoders faster on Windows/Arm, this
also prevents jpeg_nbits_table from being included in Windows/Arm builds,
thus saving 128 KB of memory.
2021-01-11 17:10:38 -06:00
DRC
3e8911aad5 Build: Use correct SIMD exts w/VStudio IDE + Arm64
When configuring a Visual Studio IDE build and passing -A arm64 to
CMake, CMAKE_SYSTEM_PROCESSOR will be amd64, so we should set CPU_TYPE
based on the value of CMAKE_GENERATOR_PLATFORM rather than the value of
CMAKE_SYSTEM_PROCESSOR.
2021-01-11 14:03:42 -06:00
DRC
4b838c38f9 jcphuff.c: Fix compiler warning with clang-cl
Fixes #492
2021-01-11 13:45:25 -06:00
DRC
944f5915cd Migrate from Travis CI to GitHub Actions
Note that this removes our ability to regression test the Armv8 and
PowerPC SIMD extensions, effectively reverting
a524b9b06b and
02227e48a9, but at the moment, there is no
other way.
2021-01-08 14:20:44 -06:00
DRC
3179f330b2 tjexample.c: Fix mem leak if tjTransform() fails
Fixes #479
2021-01-04 15:39:35 -06:00
DRC
1388ad6757 Build: Officially support Ninja 2020-12-08 21:25:47 -06:00
DRC
110d8d6dca decompress_smooth_data(): Fix another uninit. read
Regression introduced by 42825b68d5

The test case
https://user-images.githubusercontent.com/3491627/101376530-fde56180-38b0-11eb-938d-734119a5b5ba.jpg
is a malformed progressive JPEG image containing an interleaved Y/Cb/Cr
DC scan followed by two non-interleaved Y DC scans.  Thus, the
prev_coef_bits[] array was initialized for the Y component but not the
other components, the uninitialized values for Cb and Cr were
transferred to the prev_coef_bits_latch[] array in smoothing_ok(), and
because cinfo->master->last_good_iMCU_row was 0,
decompress_smooth_data() read those uninitialized values when attempting
to smooth the second iMCU row.

Possibly fixes #478
2020-12-07 12:51:26 -06:00
DRC
7b68764905 LICENSE.md: Remove trailing whitespace
Use <br> to indicate a line break, as we do in README.md, in order to
make checkstyle happy.
2020-12-03 21:20:42 -06:00
DRC
21d056847b Build: Test for correct AArch32 RPM/DEBARCH value
... based on the floating point ABI being used by the compiler (which
do you choose, a hard or soft option?)
2020-12-03 21:20:08 -06:00
DRC
6e4509a3f1 LICENSE.md: Formatting tweak 2020-12-01 09:04:27 -06:00
DRC
c7ca521bc8 Fix uninitialized read in decompress_smooth_data()
Regression introduced by 42825b68d5

Referring to the discussion in #459, the OSS-Fuzz test case
https://github.com/libjpeg-turbo/libjpeg-turbo/files/5597075/clusterfuzz-testcase-minimized-pngsave_buffer_fuzzer-5728375846731776.txt
created a situation in which
  cinfo->output_iMCU_row > cinfo->master->last_good_iMCU_row
but
  cinfo->input_scan_number == 1
thus causing decompress_smooth_data() to read from
prev_coef_bits_latch[], which was uninitialized.  I was unable to create
the same situation with a real JPEG image.
2020-11-28 07:06:08 -06:00
DRC
ccaba5d789 Fix buffer overrun with certain narrow prog JPEGs
Regression introduced by 6d91e950c8

last_block_column in decompress_smooth_data() can be 0 if, for instance,
decompressing a 4:4:4 image of width 8 or less or a 4:2:2 or 4:2:0 image
of width 16 or less.  Since last_block_column is an unsigned int,
subtracting 1 from it produced 0xFFFFFFFF, the test in line 590 passed,
and we attempted to access blocks from a second block column that didn't
actually exist.

Closes #476
2020-11-25 15:08:28 -06:00
DRC
cfc7e6e58e Bump revision to 2.0.91 for post-beta fixes 2020-11-25 14:10:55 -06:00
DRC
4e52b66f34 Travis: Use Docker tag that matches Git branch 2020-11-24 21:56:19 -06:00
DRC
8cf6f716bc Bump revision to 2.0.90 to prepare for beta 2020-11-24 21:32:48 -06:00
Jonathan Wright
eb14189caa Fix Neon SIMD build issues with Visual Studio
- Use the _M_ARM and _M_ARM64 macros provided by Visual Studio for
  compile-time detection of Arm builds, since __arm__ and __aarch64__
  are only present in GNU-compatible compilers.
- Neon/intrinsics: Use the _CountLeadingZeros() and
  _CountLeadingZeros64() intrinsics provided by Visual Studio, since
  __builtin_clz() and __builtin_clzl() are only present in
  GNU-compatible compilers.
- Neon/intrinsics: Since Visual Studio does not support static vector
  initialization, replace static initialization of Neon vectors with the
  appropriate intrinsics.  Compared to the static initialization
  approach, this produces identical assembly code with both GCC and
  Clang.
- Neon/intrinsics: Since Visual Studio does not support inline assembly
  code, provide alternative code paths for Visual Studio whenever inline
  assembly is used.
- Build: Set FLOATTEST appropriately for AArch64 Visual Studio builds
  (Visual Studio does not emit fused multiply-add [FMA] instructions by
  default for such builds.)
- Neon/intrinsics: Move temporary buffer allocation outside of nested
  loops.  Since Visual Studio configures Arm builds with a relatively
  small amount of stack memory, attempting to allocate those buffers
  within the inner loops caused a stack overflow.

Closes #461
Closes #475
2020-11-24 21:13:16 -06:00
DRC
91dd3b23ad ChangeLog: macOS Armv8/x86-64 univ. binary support 2020-11-24 20:31:59 -06:00
DRC
7e0d94d3a7 Merge branch 'master' into dev 2020-11-24 20:31:51 -06:00
DRC
1c839761cf Force Git to treat testorig.ppm as a binary file
Otherwise, because the file begins with an ASCII header, Git will
erroneously treat is as an ASCII file, and if Git for Windows is
configured with default options (specifically, "Checkout windows-style,
commit Unix-style line endings"), it will add carriage return characters
to all of the "linefeed" characters in the PPM file, thus corrupting it
and causing libjpeg-turbo's regression tests to fail.
2020-11-24 18:54:44 -06:00
DRC
6d91e950c8 Use 5x5 win & 9 AC coeffs when smoothing DC scans
... of progressive images.

Based on:
be8d36d13b
9d528f278e
85f36f0765
63a4d39e38
51336a6ad5

Closes #459
Closes #474
2020-11-24 18:21:42 -06:00
DRC
d523435e18 Travis: Use Xcode 12.2 for all iOS & macOS builds
There doesn't seem to be any performance or compatibility downside to
this, and it has the advantages of simplicity and consistency between
the PR and official builds.
2020-11-19 19:30:51 -06:00
DRC
1ac83cd636 Travis: The Mac build log is now log-macos.txt
(oversight from f7a10a61e3)
2020-11-18 18:16:12 -06:00
DRC
0ba70b6a13 Build: Support macOS Armv8/x86-64 univ. binaries
- Rename IOS_ARMV8_BUILD to ARMV8_BUILD.
- Rename install_ios() to install_subbuild() in makemacpkg.
- Wordsmith the build instructions accordingly.
- Use xcode12.2 image in Travis CI.
2020-11-18 17:40:44 -06:00
DRC
e417033d84 Merge branch 'master' into dev 2020-11-18 14:13:54 -06:00
DRC
6d2e8837b4 jpeg_skip_scanlines(): Avoid NULL + 0 UBSan error
This error occurs at the call to (*cinfo->cconvert->color_convert)() in
sep_upsample() whenever cinfo->upsample->need_context_rows == TRUE
(i.e. whenever h2v2 or h1v2 fancy upsampling is used.)  The error is
innocuous, since (*cinfo->cconvert->color_convert)() points to a dummy
function (noop_convert()) in that case.

Fixes #470
2020-11-18 13:33:47 -06:00
DRC
f7c5489244 Travis: Add /opt/local/bin to PATH for Mac build
(oversight from previous commit)

macports-ci does this, and it's necessary in order for the build script
to find md5sum.
2020-11-18 10:11:21 -06:00
DRC
f7a10a61e3 Build: "OS X"/"OSX" = "macOS"/"MACOS"
There are no supported versions of "OS X" anymore.  The operating system
has been named "macOS" since 10.12 Sierra, which was released four years
ago.
2020-11-17 13:53:33 -06:00
DRC
d111d9ff7a Merge branch 'master' into dev 2020-11-17 11:54:20 -06:00
DRC
292d78e786 Merge branch 'master' into dev 2020-11-16 15:28:02 -06:00
DRC
8f8305981b Merge branch 'master' into dev 2020-11-13 15:21:26 -06:00
DRC
33859880e9 Neon: Auto-detect compiler intrinsics completeness
This allows the Neon intrinsics code to be built successfully (albeit
likely with reduced run-time performance) with Xcode 5.0-6.2
(iOS/AArch64) and Android NDK < r19 (AArch32).  Note that Xcode 5.0-6.2
will not build the Armv8 GAS code without gas-preprocessor.pl, and no
version of Xcode will build the Armv7 GAS code without
gas-preprocessor.pl, so we always use the full Neon intrinsics
implementation by default with macOS and iOS builds.

Auto-detecting the completeness of the compiler's set of Neon intrinsics
also allows us to more intelligently set the default value of
NEON_INTRINSICS, based on the values of HAVE_VLD1*.  This is a
reasonable, albeit imperfect, proxy for whether a compiler has a full
and optimal set of Neon intrinsics.  Specific notes:

  - 64-bit RGB-to-YCbCr color conversion
    does not use any of the intrinsics in question, regresses with GCC
  - 64-bit accurate integer forward DCT
    uses vld1_s16_x3(), regresses with GCC
  - 64-bit Huffman encoding
    uses vld1q_u8_x4(), regresses with GCC
  - 64-bit YCbCr-to-RGB color conversion
    does not use any of the intrinsics in question, regresses with GCC
  - 64-bit accurate integer inverse DCT
    uses vld1_s16_x3(), regresses with GCC
  - 64-bit 4x4 inverse DCT
    uses vld1_s16_x3().  I did not test this algorithm in isolation, so
    it may in fact regress with GCC, but the regression may be hidden by
    the speedup from the new SIMD-accelerated upsampling algorithms.

  - 32-bit RGB-to-YCbCr color conversion:
    uses vld1_u16_x2(), regresses with GCC
  - 32-bit accurate integer forward DCT
    uses vld1_s16_x3(), regression irrelevant because there was no
    previous implementation
  - 32-bit accurate integer inverse DCT
    uses vld1_s16_x3(), regresses with GCC
  - 32-bit fast integer inverse DCT
    does not use any of the intrinsics in question, regresses with GCC
  - 32-bit 4x4 inverse DCT
    uses vld1_s16_x3().  I did not test this algorithm in isolation, so
    it may in fact regress with GCC, but the regression may be hidden by
    the speedup from the new SIMD-accelerated upsampling algorithms.

Presumably when GCC includes a full and optimal set of Neon intrinsics,
the HAVE_VLD1* tests will pass, and the full Neon intrinsics
implementation will be enabled automatically.
2020-11-13 15:16:34 -06:00
DRC
bbd8089297 Neon: Finalize intrinsics implementation
- Remove gas-preprocessor.pl.  None of the compilers that can build the
  new intrinsics implementation require gas-preprocessor.pl (tested
  with Xcode and with Clang 3.9+ for Linux.)
- Document that Xcode 6.3.x or later is now required for iOS builds
  (older versions of Xcode do not have a full set of Neon intrinsics.)
- Add a change log entry.
- Do not enable the ASM CMake language unless NEON_INTRINSICS is false.
- Add a Clang/Arm64 test to .travis.yml in order to test the new
  intrinsics implementation.

Closes #455
2020-11-10 19:58:28 -06:00
Martyn Jacques
141f26ff6d Neon: Intrinsics impl. of 2x2 and 4x4 scaled IDCTs
The previous AArch32 and AArch64 GAS implementations have been removed,
since the intrinsics implementations provide the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
4574f01f43 Neon: Intrinsics impl. of h2v1 & h2v2 plain upsamp
There was no previous GAS implementation.

NOTE: This doesn't produce much of a speedup when using -O3, because -O3
already enables Neon autovectorization, which works well for the scalar
C implementation of plain upsampling.  However, the Neon SIMD
implementation will benefit other optimization levels.
2020-11-10 19:09:09 -06:00
Jonathan Wright
ba52a3de32 Neon: Intrinsics impl of h2v1 & h2v2 merged upsamp
There was no previous GAS implementation.

This commit also reverts 40557b2301 and
7723d7f7d0.
7723d7f7d0 was only necessary because
there was no Neon implementation of merged upsampling/color conversion,
and 40557b2301 was only necessary because
of 7723d7f7d0.
2020-11-10 19:09:09 -06:00
Jonathan Wright
240ba417aa Neon: Intrinsics impl. of prog. Huffman encoding
The previous AArch64 GAS implementation has been removed, since the
intrinsics implementation provides the same or better performance.
There was no previous AArch32 GAS implementation.
2020-11-10 19:09:09 -06:00
Jonathan Wright
ed581cd935 Neon: Intrinsics impl. of accurate int inverse DCT
The previous AArch32 and AArch64 GAS implementations are retained by
default when using GCC, in order to avoid a performance regression.  The
intrinsics implementation can be forced on or off using the new
NEON_INTRINSICS CMake variable.
2020-11-10 19:09:09 -06:00
Jonathan Wright
2c6b68e283 Neon: Intrinsics impl. of fast integer Inverse DCT
The previous AArch32 GAS implementation is retained by default when
using GCC, in order to avoid a performance regression.  The intrinsics
implementation can be forced on or off using the new NEON_INTRINSICS
CMake variable.  The previous AArch64 GAS implementation has been
removed, since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
2acfb93c94 Neon: Intrinsics impl. of h1v2 fancy upsamling
There was no previous GAS implementation.
2020-11-10 19:09:09 -06:00
Jonathan Wright
975307775c Neon: Intrinsics impl. of h2v1 & h2v2 fancy upsamp
The previous AArch32 GAS implementation of h2v1 fancy upsampling has
been removed, since the intrinsics implementation provides the same or
better performance.  There was no previous GAS implementation of h2v2
fancy upsampling, and there was no previous AArch64 GAS implementation
of h2v1 fancy upsampling.
2020-11-10 19:09:09 -06:00
Jonathan Wright
5dbd39323c Neon: Intrinsics implementation of YCbCr->RGB565
The previous AArch64 GAS implementation is retained by default when
using GCC, in order to avoid a performance regression.  The intrinsics
implementation can be forced on or off using the new NEON_INTRINSICS
CMake variable.  The previous AArch32 GAS implementation has been
removed, since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
0f35cd68f2 Neon: Intrinsics implementation of YCbCr->RGB
The previous AArch64 GAS implementation is retained by default when
using GCC, in order to avoid a performance regression.  The intrinsics
implementation can be forced on or off using the new NEON_INTRINSICS
CMake variable.  The previous AArch32 GAS implementation has been
removed, since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
f3c3f01d23 Neon: Intrinsics impl. of Huffman encoding
The previous AArch64 GAS implementation is retained by default when
using GCC, in order to avoid a performance regression.  The intrinsics
implementation can be forced on or off using the new NEON_INTRINSICS
CMake variable.  The previous AArch32 GAS implementation has been
removed, since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
d0004de5dd Neon: Intrinsics impl. of accurate int forward DCT
The previous AArch64 GAS implementation is retained by default when
using GCC, in order to avoid a performance regression.  The intrinsics
implementation can be forced on or off using the new NEON_INTRINSICS
CMake variable.  There was no previous AArch32 GAS implementation.
2020-11-10 19:09:09 -06:00
Jonathan Wright
3d84668d42 Neon: Intrinsics impl. of fast integer forward DCT
The previous AArch32 and AArch64 GAS implementations have been removed,
since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
951d3677eb Neon: Intrinsics impl. of int sample conv./quant.
The previous AArch32 and AArch64 GAS implementations have been removed,
since the intrinsics implementation provides the same or better
performance.
2020-11-10 19:09:09 -06:00
Jonathan Wright
366168aa7d Neon: Intrinsics impl. of h2v1 & h2v2 downsampling
The previous AArch64 GAS implementation has been removed, since the
intrinsics implementation provides the same or better performance.
There was no previous AArch32 GAS implementation.
2020-11-10 19:09:09 -06:00
Jonathan Wright
f73b1dbc60 Neon: Intrinsics implementation of RGB->Grayscale
There was no previous GAS implementation.
2020-11-10 19:09:09 -06:00
Jonathan Wright
4f2216b435 Neon: Intrinsics implementation of RGB->YCbCr
The previous AArch32 and AArch64 GAS implementations are retained by
default when using GCC, in order to avoid a performance regression.  The
intrinsics implementation can be forced on or off using a new
NEON_INTRINSICS CMake variable.
2020-11-10 19:09:05 -06:00
DRC
0efc4858d4 Merge branch 'master' into dev 2020-11-09 19:02:28 -06:00
DRC
c7dd191271 Merge branch 'master' into dev 2020-11-08 15:15:02 -06:00
DRC
7c1a1789d2 Merge branch 'master' into dev 2020-11-05 16:04:55 -06:00
DRC
cd342acf7f Merge branch 'master' into dev 2020-10-27 16:45:23 -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
DRC
7e4eac7021 Merge branch 'master' into dev 2020-10-26 09:41:32 -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
59352195b2 Merge branch 'master' into dev 2020-10-19 21:17:46 -05:00
DRC
b8200c6601 Build: Add CMake package config files
Based on:
d34b89b411

Closes #339
Closes #342
2020-10-15 10:26:54 -05:00
DRC
ea8f643c16 Build: Remove lib32 symlink from official Mac pkg
(oversight from 4c5a15c362)
2020-10-15 10:26:17 -05:00
DRC
460dfe40e1 ChangeLog: Acknowledge 2.0.6 release 2020-10-15 10:26:17 -05:00
DRC
ae08115d4d Merge branch 'master' into dev 2020-10-15 10:25:46 -05:00
DRC
8789a5e255 Merge branch 'master' into dev 2020-10-01 21:27:47 -05:00
DRC
1d7faf84a0 Merge branch 'master' into dev 2020-10-01 18:17:46 -05:00
DRC
2b121d39e7 Merge branch 'master' into dev 2020-10-01 16:20:14 -05:00
DRC
6ab61fa1d1 Merge branch 'master' into dev 2020-09-13 17:02:27 -05:00
DRC
fe79f56b77 Merge branch 'master' into dev 2020-07-28 15:09:00 -05:00
DRC
fb6f5e8b01 Java/Mac:Remove obsolete libturbojpeg.jnilib alias
IIRC, this was only necessary with the version of Java 1.5 that shipped
with OS X 10.4 "Tiger".  Apple's implementation of Java 6 ("Java for
OS X Systems") supported both .jnilib and .dylib extensions for JNI
libraries, but Oracle's implementation of Java has only ever supported
the .dylib extension.
2020-06-25 21:41:30 -05:00
DRC
c77783ed41 BUILDING.md: Undocument 32-bit Mac build/packaging
(oversight from previous commit)
2020-06-25 21:28:33 -05:00
DRC
4c5a15c362 Eliminate 32-bit Mac build/packaging support
The scales have now tilted overwhelmingly in favor of eliminating
support for 32-bit Macs:

- 32-bit applications are only necessary in order to support OS X 10.5
  "Leopard" and OS X 10.6 "Snow Leopard".  OS X 10.7 "Lion" requires a
  64-bit Mac and supports all 64-bit Macs.
- 32-bit applications are no longer allowed in the macOS App Store.
- 32-bit applications no longer run in macOS 10.15 "Catalina".
- 32-bit applications do not support thread-local storage, so the
  TurboJPEG API library's global error handler is not thread-safe with
  such applications.
- libjpeg-turbo 2.1.x no longer supports 32-bit iOS apps, so it makes
  sense to also eliminate support for 32-bit macOS applications.

It's time.
2020-06-25 19:48:18 -05:00
DRC
b797f70012 Build: Eliminate Cygwin packaging support
We haven't provided official Cygwin builds since 1.4.x, since Cygwin
now supplies its own libjpeg-turbo packages (although they apparently
haven't been updated past 1.5.3.)
2020-06-25 19:05:45 -05:00
DRC
80d77720c3 AppVeyor: We no longer build/package JNI JARs
This was done solely to support Java Web Start, which is now obsolete.
2020-06-19 00:22:49 -05:00
DRC
aecee25695 Merge branch 'master' into dev 2020-06-19 00:03:51 -05:00
DRC
70040cb7ee Merge branch 'master' into dev 2020-06-02 15:05:43 -05:00
DRC
219e8e8f65 Merge branch 'master' into dev 2020-04-02 22:26:19 -05:00
DRC
b0f92a1d6c Merge branch 'master' into dev 2020-03-04 11:09:41 -06:00
DRC
77ff3bd66d Merge branch 'master' into dev 2020-02-18 12:56:01 -06:00
DRC
00d48d7e8c Merge branch 'master' into dev 2020-02-17 18:14:10 -06:00
DRC
9a2cf32317 Build: Enable separate iOS pkg/DMG w/ sim support
Refer to #406
2020-02-11 13:56:12 -06:00
DRC
6aabca86d3 Merge branch 'master' into dev 2020-02-11 12:47:12 -06:00
DRC
379edfd815 AppVeyor: Use Visual C++ 2015 instead of 2010
Visual C++ < 2015 is no longer under mainstream support, and Visual C++
2010 will not be supported at all after July of this year.
(https://docs.microsoft.com/en-us/visualstudio/releases/2019/servicing)
2020-01-16 20:55:42 -06:00
DRC
ada6ea5105 BUILDING.md: Update Visual C++ recommendations 2020-01-16 20:52:15 -06:00
DRC
167b5a8059 Merge branch 'master' into dev 2020-01-08 15:02:58 -06:00
DRC
4c57ad476c Merge branch 'master' into dev 2020-01-08 14:26:02 -06:00
DRC
04d3143a65 Merge branch 'master' into dev 2020-01-07 16:21:03 -06:00
DRC
b34c85ea4a Merge branch 'master' into dev 2019-12-31 01:20:12 -06:00
DRC
c4675d62e8 Merge branch 'master' into dev 2019-12-31 00:58:42 -06:00
DRC
80acd5c4a7 Remove code for the obsolete RLE image format
libjpeg-turbo never included that code, because it requires an external
library (the Utah Raster Toolkit.)  The RLE image format was supplanted
by GIF in the late 1980s, so it is rarely seen these days.  (It had a
lousy Weissman score, anyhow.)
2019-12-19 10:36:26 -06:00
DRC
5000eaa3a6 cdjpeg.c: Fix Visual C++ compiler warning
(introduced by previous commit)
2019-12-19 10:13:05 -06:00
DRC
e98b061282 Add fault tolerance features to djpeg and jpegtran
- Enable progress reporting at run time using a new -report argument
  (cjpeg now supports that argument as well)
- Limit the allowable number of scans using a new -maxscans argument
- Treat warnings as fatal using a new -strict argument

This mainly demonstrates how to work around the two issues with the
JPEG standard described here:
https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
since those and similar issues continue to be erroneously reported as
libjpeg-turbo bugs.
2019-12-18 15:35:56 -06:00
DRC
54288598bb ChangeLog.md: Document 81b8c0ee 2019-12-17 15:48:10 -06:00
DRC
81b8c0eed5 Loongson MMI: Merge with MIPS64/add auto-detection
Modern Loongson processors are MIPS64-compatible, and MMI instructions
are now supported in the mainline of GCC.  Thus, this commit adds
compile-time and run-time auto-detection of MMI instructions and moves
the MMI SIMD extensions for libjpeg-turbo from simd/loongson/ to
simd/mips64/.  That will allow MMI and MSA instructions to co-exist
in the same build once #377 has been integrated.

Based on:
82953ddd61

Closes #383
2019-12-17 14:35:49 -06:00
DRC
52fef34928 Eliminate internal use of GETJOCTET() macro
Because of 01e3032354 (officially
eliminating support for compilers without unsigned char, since we never
effectively supported those compilers anyhow), GETJOCTET() is now a
no-op.  Since that macro is in jmorecfg.h, it is part of the de facto
libjpeg API and must remain in the public headers.  However, there is no
reason to continue using it internally, and eliminating its internal use
improves code readability.
2019-12-10 19:10:55 -06:00
mayeut
e821464f79 ARM64 NEON SIMD impl. of prog. Huffman encoding
This commit adds ARM64 NEON optimizations for the
encode_mcu_AC_first() and encode_mcu_AC_refine() functions used in
progressive Huffman encoding.

Compression speedups for the typical set of five libjpeg-turbo test
images (https://libjpeg-turbo.org/About/Performance):
Cortex-A53: 23.8-39.2% (avg. 32.2%)
Cortex-A72: 26.8-41.1% (avg. 33.5%)
Apple A7:  29.7-45.9% (avg. 39.6%)

Closes #229
2019-12-10 00:21:57 -06:00
DRC
b8a7680e12 Merge branch 'master' into dev 2019-12-05 22:38:05 -06:00
DRC
f64c5508df Merge branch 'master' into dev 2019-12-05 15:41:28 -06:00
DRC
26b4d62a65 Merge branch 'master' into dev 2019-11-15 13:58:22 -06:00
DRC
9c6f79e919 Fix formatting issues detected by checkstyle 2019-11-14 12:16:38 -06:00
DRC
f60b6dd36f Remove vestigial jpeg_nbits_table.inc
Not needed since 087c29e07f
2019-11-12 17:42:39 -06:00
DRC
c43a5081ce Merge branch 'master' into dev 2019-11-12 17:07:46 -06:00
DRC
713c451f58 Enable SSE2 progressive Huffman encoder for x32
Referring to #289, I'm not sure where I arrived at the conclusion that
the SSE2 progressive Huffman encoder doesn't provide any speedup for
x32.  Upon re-testing, I discovered it to be about 50% faster than the
C encoder.

This commit also re-purposes one of the CI tests (specifically, the
jpeg-7 API/ABI test) so that it tests x32 as well.
2019-11-08 16:03:38 -06:00
DRC
2234deeeed Fix MSan use-of-uninitialized-value error
... introduced by 42825b68d5.  In fact,
fault-tolerant multi-scan block smoothing cannot currently be used with
the arithmetic decoder, because that decoder doesn't have any way of
distinguishing a normal end of scan from an unexpected end of scan.
Thus, this commit also modifies the change log to reset the expectations
regarding the scope of the fault-tolerant multi-scan block smoothing
feature.  If, at some point in the future, the arithmetic decoder can be
modified to detect an unexpected end of scan, then one would need only
set entropy->pub.insufficient_data = TRUE when the arithmetic decoder
encounters an unexpected end of scan in order to make fault-tolerant
block smoothing work properly with that decoder.
2019-11-08 13:51:34 -06:00
DRC
82695cfddf ChangeLog: Acknowledge 2.0.3/de-acknowledge 2.0.4
It is very unlikely that there will be an official 2.0.4 release.
2019-11-07 15:15:36 -06:00
DRC
42825b68d5 Fault-tolerant multi-scan block smoothing
This commit modifies the behavior of the block smoothing algorithm in
the libjpeg API library so that, if a scan in a multi-scan JPEG image is
incomplete (due to premature termination of the image stream), the block
smoothing parameters from the previous (complete) scan are used to
smooth any iMCU rows that the incomplete scan does not contain.

Closes #343
2019-11-07 15:12:54 -06:00
DRC
f2d4b47315 Travis: Use Docker tag that matches Git branch
dcommander/buildljt:dev is a CentOS 6 container with YASM 1.2.0 rather
than NASM 2.10, so it can build the new optimized SSE2 Huffman encoder.
2019-11-07 03:07:17 -06:00
DRC
45dff48c9f Merge branch 'master' into dev 2019-11-06 23:02:03 -06:00
DRC
d70047fcd2 Travis: Use GCC 6 for Mac pre-release builds
The primary impetus for this is to eliminate build warnings, such as

  (32-bit only)
  section "__textcoal_nt" is deprecated

  object file (XXXXXX.o) was built for newer OSX version (10.XX) than
  being linked (10.5)

Upgrading to GCC 6 results in neutral performance for compression,
a measured average overall decompression speedup of 2.5% for 64-bit
code, and a measured average overall decompression speedup of -4.3% for
32-bit code on a 3 GHz Core i7.  The 4.3% slow-down for 32-bit code is
deemed acceptable, given that 32-bit macOS apps are deprecated.
2019-11-05 17:57:59 -06:00
DRC
cbf0fcc8b7 i386 SSE2 Huffman: Fix pointer arithmetic issue
Splitting the pointer arithmetic in GET_SYM() into a separate add and
sub instruction was an attempt to work around an error ("invalid operand
type") that occurred when assembling the file with NASM.  However, this
created a link error on macOS ("ld: illegal text-relocation to
'_jconst_huff_encode_one_block' in
simd/CMakeFiles/simd.dir/i386/jchuff-sse2.asm.o from
'_jsimd_huff_encode_one_block_sse2' in
simd/CMakeFiles/simd.dir/i386/jchuff-sse2.asm.o for architecture i386")
and also changed the alignment of the code in ways that might have
affected the previous benchmark results (which took a great deal of time
to obtain.)  Ultimately, the path of least resistance is just to
require NASM 2.13 or later.
2019-11-05 15:56:28 -06:00
DRC
bbedb4b564 Merge branch 'master' into dev 2019-11-05 15:43:21 -06:00
DRC
087c29e07f Optimize Huffman encoding
This commit improves the C and SSE2 Huffman encoding implementations in
the following ways:

- Avoid using xmm8-xmm15 in the x86-64 SSE2 implementation.  There is no
  actual need to use those registers, and avoiding them produces a
  cleaner WIN64 function entry/exit-- as well as shorter code, since REX
  prefixes can be avoided (this is helpful on certain CPUs, such as
  Intel Atom, for which instruction fetch and decoding can be a
  bottleneck.)
- Optimize register usage so that fewer REX prefixes and
  register-register moves are needed.
- Use the bit counter to store the number of free bits in the bit buffer
  rather than the number of bits in the bit buffer.  This changes the
  method for inserting a code into the bit buffer to:

  (put_buffer |= code << (free_bits -= code_size));

  As a result:
  * Only one bit counter needs to stay in a register (we just keep it in
    cl.)
  * The bit buffer contents are already properly aligned to be written
    out (after a byte swap.)
  * Adjusting the free bits counter and checking if the bit buffer is
    full can be combined into a single operation.
  * We can wait to flush the bit buffer until the buffer is actually
    full and not just in danger of becoming full.  Thus, eight bytes can
    be flushed at a time.

- Speed is quite sensitive to the alignment of branch target labels, so
  insert some padding and remove branches from the flush code.
  (Flushing this way isn't actually faster when compared to using
  branches, but the branchless code doesn't need extra alignment and is
  thus smaller.)
- Speculatively write out the bit buffer as a single 8-byte write,
  falling back to a byte-by-byte write only if there are any 0xFF bytes
  in the bit buffer that need to be encoded as 0xFF 0x00.
- Use MMX registers for the 32-bit implementation (so the bit buffer can
  be 64 bits wide.)
- Slightly reduce overall function code size.
- Eliminate or combine a few SSE instructions.
- Make some minor improvements to instruction scheduling.
- Adjust flush_bits() in jchuff.c to handle cases in which the bit
  buffer has less than 7 free bits (apparently that couldn't happen
  before.)

Based on:
947a09defa
262ebb6b81
6e9a091221

See change log for performance claims.

Closes #292
2019-11-04 19:04:05 -06:00
DRC
d92ae5df0c Merge branch 'master' into dev 2019-11-04 18:50:45 -06:00
DRC
adf9cc942f j*huff.c: Remove crufty ASSIGN_STATE() macro
This macro is a relic of libjpeg's historic need to support a wide
variety of C compilers with varying degrees of compatibility.  Such was
necessary during the open systems era, because C compilers were often
supplied by the system vendor.  Prior to 1989, there was no C standard
per se, and even after ANSI C became a thing, there were still compilers
in use that didn't conform to it (libjpeg was first released in 1991.)

Realistically, only a handful of C compilers are in widespread use these
days, and all modern C compilers should support structure assignment.
2019-10-24 02:13:34 -05:00
DRC
95f4d6ef8b Merge branch 'master' into dev 2019-10-24 02:13:23 -05:00
DRC
2ae2bd66b4 Remove support for Apple's Java implementation
(AKA "Java for OS X systems.")  This implementation of Java 1.6 is long
obsolete and not supported on any version of macOS past High Sierra.
Oracle no longer provides a 32-bit JVM on macOS, so it is no longer
necessary to provide a 32-bit version of the TurboJPEG Java wrapper on
macOS.
2019-10-04 16:31:46 -05:00
DRC
b7523059c1 Merge branch 'master' into dev 2019-10-04 15:53:30 -05:00
DRC
b4110b65fc Merge branch 'master' into dev 2019-09-04 18:58:12 -05:00
DRC
8ef53b102f Merge branch 'master' into dev 2019-08-14 22:08:59 -05:00
DRC
7fbfe29c65 Merge branch 'master' into dev 2019-07-18 15:18:27 -05:00
DRC
051f4862f9 Travis: Fix iOS build
The new libjpeg-turbo 2.1.x official build scripts expect Xcode to be
under /Applications/Xcode83.app.
2019-05-09 20:46:18 -05:00
DRC
c055c88057 Discontinue support for 32-bit iOS builds 2019-05-09 20:36:51 -05:00
DRC
85d96d4478 Merge branch 'master' into dev 2019-05-09 19:13:39 -05:00
DRC
f36d531553 Merge branch 'master' into dev 2019-04-23 14:54:23 -05:00
DRC
8a0e35b212 Merge branch 'master' into dev 2019-04-15 13:41:45 -05:00
DRC
afbe48c290 MMI: Support 32-bit Loongson architectures 2019-02-27 13:36:48 -06:00
DRC
98ff5507d8 MMI: Fix bug in jsimd_h2v1_merged_upsample_mmi()
... that occurred when ((image width) & 1) != 0.
2019-02-27 13:36:48 -06:00
DRC
3ca6dba96e Merge branch 'master' into dev 2019-02-17 09:33:57 -06:00
DRC
aaf58dabb6 Merge branch 'master' into dev 2019-02-13 17:05:26 -06:00
DRC
a9075a17c3 Merge branch 'master' into dev 2019-02-12 13:42:57 -06:00
DRC
bdec995839 MMI: Fix unaligned decomp. perf. for 32-bit PFs
(Oversight from db84125fcb)
2019-02-01 01:16:13 -06:00
DRC
fa905fbf7b MMI: Use unaligned stores w/ merged upsampling
... when necessary.  This was an oversight from
2f9e7c84d1
2019-02-01 01:03:32 -06:00
DRC
9aada25ced Merge branch 'master' into dev 2019-02-01 01:02:55 -06:00
DRC
73fd604161 MMI: Fix formatting issue detected by checkstyle 2019-02-01 00:24:09 -06:00
DRC
2f9e7c84d1 Loongson MMI h2v1 and h2v2 merged upsampling
Based on:
e8f5cee5aa
2019-01-31 23:18:48 -06:00
DRC
3c7199ff06 Loongson MMI h2v1 fancy upsampling
Based on:
e8f5cee5aa
2019-01-31 17:01:01 -06:00
DRC
73b98acd8b Loongson MMI RGB-to-Grayscale conversion
Based on:
e8f5cee5aa
2019-01-31 16:44:55 -06:00
DRC
bb0d170288 Improve readability of Loongson MMI code
We have more than eight registers to work with, as well as three-operand
intrinsics, so there's no need for the implementation to be such a
literal port of the MMX code.
2019-01-31 16:44:48 -06:00
DRC
db84125fcb MMI: Use aligned store instructions when possible
This improves decompression performance by 2-5%.
2019-01-31 15:30:58 -06:00
DRC
ae4221f905 Loongson MMI fast forward/inverse DCT
Based on:
32a9ca222d
2019-01-31 15:30:58 -06:00
DRC
674343ab14 Merge branch 'master' into dev 2019-01-31 15:30:25 -06:00
DRC
6fac90945a wrbmp.c, wrtarga.c: Remove unused variables
(should have been done with the previous commit)
2019-01-23 16:18:41 -06: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
42d62bf114 Merge branch 'master' into dev 2019-01-23 11:20:11 -06:00
DRC
a39c970d27 Merge branch 'master' into dev 2019-01-01 21:53:19 -06:00
DRC
12f3d0be84 Merge branch 'master' into dev 2019-01-01 21:52:21 -06:00
DRC
2cc4f93c88 Merge branch 'master' into dev 2018-11-12 14:40:19 -06:00
DRC
133e4af070 Add x32 ABI support on Linux
The x32 ABI is similar to the x86-64 ABI but uses 32-bit pointers.
(Refer to https://sites.google.com/site/x32abi)

Based on:
8da8fc5213
1e33dfea80
24ffea78da
dedcf76753
d04228a7b5
b4ad38316a

Closes #274
2018-09-05 17:10:06 -05:00
DRC
995eb29dc3 Bump version to 2.1 alpha1
(to prepare for new features)
2018-09-05 09:08:00 -05:00
292 changed files with 22675 additions and 21048 deletions

4
.gitattributes vendored
View File

@@ -1,4 +1,4 @@
/.travis.yml export-ignore
/appveyor.yml export-ignore /appveyor.yml export-ignore
/ci export-ignore
/.gitattributes export-ignore /.gitattributes export-ignore
/.github export-ignore
*.ppm binary

95
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,95 @@
Contributing to libjpeg-turbo
=============================
libjpeg-turbo is a stable and mature product with a worldwide reach, it is an
ISO/ITU-T reference implementation of the JPEG standard, and its maintainer
does not earn a salary for maintaining it. Thus, not every code contribution
can or will be accepted into the libjpeg-turbo code base. In order to maximize
the chances that a code contribution is acceptable, please adhere to the
following guidelines:
1. If the code contribution is a bug fix, then please ensure that enough
information is provided so that the maintainer can readily reproduce and
document the bug. That information should include:
- A clear and concise description of the bug
- The steps and (if applicable) images necessary to reproduce the bug
- The compilers, operating systems, and CPUs with which the bug was
observed
- The versions of libjpeg-turbo with which the bug was observed
- If the bug is a regression, the specific commit that introduced the bug
(use `git bisect` to determine this)
2. If the code contribution will implement a major new feature, then please
contact the project maintainer (through a
[GitHub issue](https://github.com/libjpeg-turbo/libjpeg-turbo/issues/new),
[direct e-mail](https://libjpeg-turbo.org/About/Contact), or the
[libjpeg-turbo-devel mailing list](https://libjpeg-turbo.org/About/MailingLists))
prior to implementing the feature. In general, major new features that are
potentially disruptive to the quality of libjpeg-turbo are unlikely to be
accepted unless:
- The new feature is within the existing scope of libjpeg-turbo.
- The new feature has been thoroughly regression tested and benchmarked on
all of the supported platforms that are potentially affected by it.
- The new feature has been documented clearly and concisely in the change
log and (if applicable) the libjpeg and TurboJPEG API documentation and
man pages.
- The code implementing the new feature is formatted consistently with the
rest of the libjpeg-turbo code base (use
[checkstyle](https://github.com/libjpeg-turbo/checkstyle) to validate
this.)
- The new feature does not introduce new members into the exposed libjpeg
API structures (doing so would break backward ABI compatibility.)
- The new feature does not alter existing libjpeg-turbo usage or
development workflows.
- The code implementing the new feature is elegant, easily maintainable,
and causes the least possible amount of disruption to the libjpeg-turbo
code base.
- The new feature is based on the dev branch of the libjpeg-turbo
repository.
... OR ...
- Your organization is prepared to pay for the labor necessary to ensure
all of the above. Even the most well-written patches can still require
a significant amount of labor to clean up, test, and integrate. (See
above RE: the maintainer not earning a salary.)
Specific types of features that *will not* be accepted:
- Features that extend the scope of libjpeg-turbo to support image formats
other than DCT-based JPEG and JFIF
- Features that extend the scope of libjpeg-turbo to support image
processing algorithms that are not necessary for JPEG compression or
decompression
- Extensions to the JPEG format that have not been approved by the
appropriate standards bodies
- Non-trivial performance enhancements that have less than a 5% overall
impact on performance
3. If the code contribution is a build system enhancement, then please be
prepared to justify the enhancement. In general, build system enhancements
are unlikely to be accepted unless:
- The enhancement is potentially beneficial to a significant number of
upstream libjpeg-turbo users/developers. (If the enhancement is only
beneficial to a downstream project, then it does not belong here.)
- The enhancement has been tested with the following CMake versions:
- The earliest version of CMake that libjpeg-turbo currently supports
(refer to CMakeLists.txt)
- The most recent major version of CMake
- (if applicable) The earliest version of CMake with which the
enhancement can be used
- The enhancement has been tested on all of the major platforms (Mac,
Linux, Windows/Visual C++, Windows/MinGW) that are potentially affected
by it.
- The enhancement does not introduce new build system requirements or CMake
variables unless absolutely necessary.
- The enhancement does not alter existing libjpeg-turbo development
workflows.
Specific types of build system enhancements that *will not* be accepted:
- Enhancements that allow libjpeg-turbo to be built from a subdirectory
of a downstream repository. These enhancements are not maintainable in
the upstream libjpeg-turbo build system. Use the CMake
`ExternalProject_Add()` function instead.
- Enhancements that introduce new (non-CMake-based) build systems

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: libjpeg-turbo

40
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
name: Bug Report
about: Inform the libjpeg-turbo maintainer about unexpected, reproducible behavior
title: ''
labels: bug
assignees: dcommander
---
**Have you searched the existing issues (both open and closed) in the libjpeg-turbo issue tracker to ensure that this bug report is not a duplicate?**
**Does this bug report describe one of the [two known and unsolvable issues with the JPEG format](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf)?**
**Clear and concise description of the bug:**
**Steps to reproduce the bug (using *only* libjpeg-turbo):**
**Image(s) needed in order to reproduce the bug (if applicable):**
**Expected behavior:**
**Observed behavior:**
**Platform(s) (compiler version, operating system version, CPU) on which the bug was observed:**
**libjpeg-turbo release(s), commit(s), or branch(es) in which the bug was observed (always test the tip of the main branch or the latest [stable pre-release](https://libjpeg-turbo.org/DeveloperInfo/PreReleases) to verify that the bug hasn't already been fixed):**
**If the bug is a regression, the specific commit that introduced the regression (use `git bisect` to determine this):**
**Additional information:**

View File

@@ -0,0 +1,8 @@
---
name: Feature Request
about: Suggest new libjpeg-turbo functionality
title: ''
labels: enhancement
assignees: dcommander
---

193
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,193 @@
name: Build
on:
push:
branches:
- '**'
tags-ignore:
- '**'
pull_request:
workflow_dispatch:
jobs:
linux:
runs-on: ubuntu-latest
steps:
- name: Set global environment variables
run: |
echo "BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}" >$GITHUB_ENV
- name: Check out code
uses: actions/checkout@v2
- name: Set up build
run: |
mkdir -p $HOME/src/ljt.nightly
docker pull dcommander/buildljt:$BRANCH
git clone --depth=1 https://github.com/libjpeg-turbo/buildscripts.git -b $BRANCH $HOME/src/buildscripts
mkdir $HOME/rpmkeys
wget --no-check-certificate "http://www.libjpeg-turbo.org/key/LJTPR-GPG-KEY" -O $HOME/rpmkeys/LJTPR-GPG-KEY
- name: Configure GPG signing
if: ${{github.event_name != 'pull_request'}}
run: |
sudo apt install -y gnupg1
printf "${{secrets.GPG_KEY}}" | base64 --decode | gpg1 --batch --import -
chmod 600 $HOME/.gnupg/gpg.conf
echo "GPG_KEY_NAME=\"${{secrets.GPG_KEY_NAME}}\"" >$HOME/src/buildscripts/gpgsign
echo "GPG_KEY_ID=${{secrets.GPG_KEY_ID}}" >>$HOME/src/buildscripts/gpgsign
echo "GPG_KEY_PASS=${{secrets.GPG_KEY_PASS}}" >>$HOME/src/buildscripts/gpgsign
- name: Build
run: |
docker run -v $HOME/src/ljt.nightly:/root/src/ljt.nightly -v $HOME/src/buildscripts:/root/src/buildscripts -v $GITHUB_WORKSPACE:/root/src/libjpeg-turbo -v $HOME/.gnupg:/root/.gnupg -v $HOME/rpmkeys:/rpmkeys -t dcommander/buildljt:$BRANCH bash -c "rpm --import /rpmkeys/LJTPR-GPG-KEY && ~/src/buildscripts/buildljt -d /root/src/libjpeg-turbo -v"
sudo chown -R runner:runner $HOME/src/ljt.nightly
mv $HOME/src/ljt.nightly/latest/log-${{github.job}}.txt $HOME/src/ljt.nightly/latest/files/
- name: Configure AWS
if: ${{github.event_name != 'pull_request'}}
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{secrets.AWS_ACCESS_KEY_ID}}
aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: ${{secrets.AWS_REGION}}
- name: Deploy
if: ${{github.event_name != 'pull_request'}}
run: |
aws s3 sync --acl public-read --delete $HOME/src/ljt.nightly/latest/files/ s3://libjpeg-turbo-pr/${{env.BRANCH}}/${{github.job}}/
macos:
runs-on: macos-10.15
steps:
- name: Set global environment variables
run: |
echo "BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}" >$GITHUB_ENV
- name: Check out code
uses: actions/checkout@v2
- name: Set up build
run: |
brew install yasm md5sha1sum
mkdir -p $HOME/src/ljt.nightly
git clone --depth=1 https://github.com/libjpeg-turbo/buildscripts.git -b $BRANCH $HOME/src/buildscripts
- name: Configure GPG signing
if: ${{github.event_name != 'pull_request'}}
run: |
printf "${{secrets.GPG_KEY}}" | base64 --decode | gpg --batch --import -
echo "GPG_KEY_NAME=\"${{secrets.GPG_KEY_NAME}}\"" >$HOME/src/buildscripts/gpgsign
echo "GPG_KEY_ID=${{secrets.GPG_KEY_ID}}" >>$HOME/src/buildscripts/gpgsign
echo "GPG_KEY_PASS=${{secrets.GPG_KEY_PASS}}" >>$HOME/src/buildscripts/gpgsign
- name: Build
run: |
$HOME/src/buildscripts/buildljt -d $GITHUB_WORKSPACE -v
mv $HOME/src/ljt.nightly/latest/log-${{github.job}}.txt $HOME/src/ljt.nightly/latest/files/
- name: Configure AWS
if: ${{github.event_name != 'pull_request'}}
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{secrets.AWS_ACCESS_KEY_ID}}
aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: ${{secrets.AWS_REGION}}
- name: Deploy
if: ${{github.event_name != 'pull_request'}}
run: |
aws s3 sync --acl public-read --delete $HOME/src/ljt.nightly/latest/files/ s3://libjpeg-turbo-pr/${{env.BRANCH}}/${{github.job}}/
linux-asan-ubsan:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up build
run: |
sudo apt install -y nasm
- name: Build
env:
ASAN_OPTIONS: "detect_leaks=1 symbolize=1"
CTEST_OUTPUT_ON_FAILURE: 1
run: |
mkdir build
pushd build
cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_C_FLAGS_RELWITHDEBINFO="-O1 -g -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" -DENABLE_SHARED=0 ..
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
make -j$NUMCPUS --load-average=$NUMCPUS
make test
JSIMD_FORCESSE2=1 make test
cmake -DFLOATTEST=no-fp-contract ..
JSIMD_FORCENONE=1 make test
popd
linux-12bit:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: |
mkdir build
pushd build
cmake -G"Unix Makefiles" -DWITH_12BIT=1 \
-DCMAKE_C_FLAGS='--std=gnu90 -Wall -Werror -Wextra -Wpedantic -pedantic-errors -Wdouble-promotion -Wformat-overflow=2 -Wformat-security -Wformat-signedness -Wformat-truncation=2 -Wformat-y2k -Wmissing-include-dirs -Wshift-overflow=2 -Wswitch-bool -Wno-unused-parameter -Wuninitialized -Wstrict-overflow=2 -Wstringop-overflow=4 -Wstringop-truncation -Wduplicated-branches -Wduplicated-cond -Wdeclaration-after-statement -Wshadow -Wunsafe-loop-optimizations -Wundef -Wcast-align -Wno-clobbered -Wjump-misses-init -Wno-sign-compare -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wdisabled-optimization -Wno-overlength-strings' \
..
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
make -j$NUMCPUS --load-average=$NUMCPUS
make test
popd
linux-jpeg7-x32:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up build
run: |
sudo apt update
sudo apt -y --install-recommends install libc6-dev-x32 nasm
- name: Build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: |
mkdir build
pushd build
cmake -G"Unix Makefiles" -DWITH_JPEG7=1 -DCMAKE_C_FLAGS=-mx32 \
-DCMAKE_C_FLAGS='--std=gnu90 -Wall -Werror -Wextra -Wpedantic -pedantic-errors -Wdouble-promotion -Wformat-overflow=2 -Wformat-security -Wformat-signedness -Wformat-truncation=2 -Wformat-y2k -Wmissing-include-dirs -Wshift-overflow=2 -Wswitch-bool -Wno-unused-parameter -Wuninitialized -Wstrict-overflow=2 -Wstringop-overflow=4 -Wstringop-truncation -Wduplicated-branches -Wduplicated-cond -Wdeclaration-after-statement -Wshadow -Wunsafe-loop-optimizations -Wundef -Wcast-align -Wno-clobbered -Wjump-misses-init -Wno-sign-compare -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wdisabled-optimization -Wno-overlength-strings' \
..
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
make -j$NUMCPUS --load-average=$NUMCPUS
make test
JSIMD_FORCESSE2=1 make test
cmake -DFLOATTEST=no-fp-contract ..
JSIMD_FORCENONE=1 make test
popd
linux-jpeg8:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up build
run: |
sudo apt -y install nasm
- name: Build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: |
mkdir build
pushd build
cmake -G"Unix Makefiles" -DWITH_JPEG8=1 \
-DCMAKE_C_FLAGS='--std=gnu90 -Wall -Werror -Wextra -Wpedantic -pedantic-errors -Wdouble-promotion -Wformat-overflow=2 -Wformat-security -Wformat-signedness -Wformat-truncation=2 -Wformat-y2k -Wmissing-include-dirs -Wshift-overflow=2 -Wswitch-bool -Wno-unused-parameter -Wuninitialized -Wstrict-overflow=2 -Wstringop-overflow=4 -Wstringop-truncation -Wduplicated-branches -Wduplicated-cond -Wdeclaration-after-statement -Wshadow -Wunsafe-loop-optimizations -Wundef -Wcast-align -Wno-clobbered -Wjump-misses-init -Wno-sign-compare -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wdisabled-optimization -Wno-overlength-strings' \
..
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
make -j$NUMCPUS --load-average=$NUMCPUS
make test
JSIMD_FORCESSE2=1 make test
cmake -DFLOATTEST=no-fp-contract ..
JSIMD_FORCENONE=1 make test
popd
linux-msan:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: |
mkdir build
pushd build
cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_C_FLAGS_RELWITHDEBINFO="-O3 -g -fsanitize=memory -fno-sanitize-recover=all -fPIE" -DWITH_SIMD=0 ..
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
make -j$NUMCPUS --load-average=$NUMCPUS
make test
popd

48
.gitignore vendored
View File

@@ -1,48 +0,0 @@
.DS_Store
Makefile.in
Makefile
/CMakeFiles
/autom4te.cache
/aclocal.m4
/compile
/configure
/depcomp
/install-sh
/libtool
/missing
/stamp-h*
/java/classnoinst.stamp
/pkgscripts/
/jconfig.h
/jconfigint.h
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/ltmain.sh
/ar-lib
/libjpeg.map
/.libs/
/simd/.libs/
/simd/jsimdcfg.inc
*.o
*.lo
*.la
/cjpeg
/djpeg
/jcstest
/jpegtran
/jpegyuv
/md5/md5cmp
/rdjpgcom
/test_enc_*
/tjbench
/tjbenchtest
/tjunittest
/wrjpgcom
/yuvjpeg
test_yuv*.jpg
CMakeCache.txt
CTestTestfile.cmake

View File

@@ -10,38 +10,24 @@ Build Requirements
- [CMake](http://www.cmake.org) v2.8.12 or later - [CMake](http://www.cmake.org) v2.8.12 or later
- [NASM](http://www.nasm.us) or [YASM](http://yasm.tortall.net) - [NASM](http://www.nasm.us) or [Yasm](http://yasm.tortall.net)
(if building x86 or x86-64 SIMD extensions) (if building x86 or x86-64 SIMD extensions)
* If using NASM, 2.10 or later is required. * If using NASM, 2.13 or later is required.
* If using NASM, 2.10 or later (except 2.11.08) is required for an x86-64 Mac * If using Yasm, 1.2.0 or later is required.
build (2.11.08 does not work properly with libjpeg-turbo's x86-64 SIMD code * If building on macOS, NASM or Yasm can be obtained from
when building macho64 objects.)
* If using YASM, 1.2.0 or later is required.
* If building on macOS, NASM or YASM can be obtained from
[MacPorts](http://www.macports.org/) or [Homebrew](http://brew.sh/). [MacPorts](http://www.macports.org/) or [Homebrew](http://brew.sh/).
- NOTE: Currently, if it is desirable to hide the SIMD function symbols in - NOTE: Currently, if it is desirable to hide the SIMD function symbols in
Mac executables or shared libraries that statically link with Mac executables or shared libraries that statically link with
libjpeg-turbo, then NASM 2.14 or later or YASM must be used when libjpeg-turbo, then NASM 2.14 or later or Yasm must be used when
building libjpeg-turbo. building libjpeg-turbo.
* If building on Windows, **nasm.exe**/**yasm.exe** should be in your `PATH`. * If NASM or Yasm is not in your `PATH`, then you can specify the full path
* NASM and YASM are located in the CRB (Code Ready Builder) repository on to the assembler by using either the `CMAKE_ASM_NASM_COMPILER` CMake
Red Hat Enterprise Linux 8 and in the PowerTools repository on CentOS 8, variable or the `ASM_NASM` environment variable. On Windows, use forward
which is not enabled by default. slashes rather than backslashes in the path (for example,
**c:/nasm/nasm.exe**).
The binary RPMs released by the NASM project do not work on older Linux * NASM and Yasm are located in the CRB (Code Ready Builder) repository on
systems, such as Red Hat Enterprise Linux 5. On such systems, you can easily Red Hat Enterprise Linux 8 and in the PowerTools repository on RHEL
build and install NASM from a source RPM by downloading one of the SRPMs from derivatives, which is not enabled by default.
<http://www.nasm.us/pub/nasm/releasebuilds>
and executing the following as root:
ARCH=`uname -m`
rpmbuild --rebuild nasm-{version}.src.rpm
rpm -Uvh /usr/src/redhat/RPMS/$ARCH/nasm-{version}.$ARCH.rpm
NOTE: the NASM build will fail if texinfo is not installed.
### Un*x Platforms (including Linux, Mac, FreeBSD, Solaris, and Cygwin) ### Un*x Platforms (including Linux, Mac, FreeBSD, Solaris, and Cygwin)
@@ -49,10 +35,8 @@ Build Requirements
- If building the TurboJPEG Java wrapper, JDK or OpenJDK 1.5 or later is - If building the TurboJPEG Java wrapper, JDK or OpenJDK 1.5 or later is
required. Most modern Linux distributions, as well as Solaris 10 and later, required. Most modern Linux distributions, as well as Solaris 10 and later,
include JDK or OpenJDK. On OS X 10.5 and 10.6, it will be necessary to include JDK or OpenJDK. For other systems, you can obtain the Oracle Java
install the Java Developer Package, which can be downloaded from Development Kit from
<http://developer.apple.com/downloads> (Apple ID required.) For other
systems, you can obtain the Oracle Java Development Kit from
<http://www.oracle.com/technetwork/java/javase/downloads>. <http://www.oracle.com/technetwork/java/javase/downloads>.
* If using JDK 11 or later, CMake 3.10.x or later must also be used. * If using JDK 11 or later, CMake 3.10.x or later must also be used.
@@ -62,22 +46,22 @@ Build Requirements
- Microsoft Visual C++ 2005 or later - Microsoft Visual C++ 2005 or later
If you don't already have Visual C++, then the easiest way to get it is by If you don't already have Visual C++, then the easiest way to get it is by
installing the installing
[Windows SDK](http://msdn.microsoft.com/en-us/windows/bb980924.aspx). [Visual Studio Community Edition](https://visualstudio.microsoft.com),
The Windows SDK includes both 32-bit and 64-bit Visual C++ compilers and which includes everything necessary to build libjpeg-turbo.
everything necessary to build libjpeg-turbo.
* You can also use Microsoft Visual Studio Express/Community Edition, which * You can also download and install the standalone Windows SDK (for Windows 7
is a free download. (NOTE: versions prior to 2012 can only be used to or later), which includes command-line versions of the 32-bit and 64-bit
build 32-bit code.) Visual C++ compilers.
* If you intend to build libjpeg-turbo from the command line, then add the * If you intend to build libjpeg-turbo from the command line, then add the
appropriate compiler and SDK directories to the `INCLUDE`, `LIB`, and appropriate compiler and SDK directories to the `INCLUDE`, `LIB`, and
`PATH` environment variables. This is generally accomplished by `PATH` environment variables. This is generally accomplished by
executing `vcvars32.bat` or `vcvars64.bat` and `SetEnv.cmd`. executing `vcvars32.bat` or `vcvars64.bat`, which are located in the same
`vcvars32.bat` and `vcvars64.bat` are part of Visual C++ and are located in directory as the compiler.
the same directory as the compiler. `SetEnv.cmd` is part of the Windows * If built with Visual C++ 2015 or later, the libjpeg-turbo static libraries
SDK. You can pass optional arguments to `SetEnv.cmd` to specify a 32-bit cannot be used with earlier versions of Visual C++, and vice versa.
or 64-bit build environment. * The libjpeg API DLL (**jpeg{version}.dll**) will depend on the C run-time
DLLs corresponding to the version of Visual C++ that was used to build it.
... OR ... ... OR ...
@@ -94,17 +78,13 @@ Build Requirements
* If using JDK 11 or later, CMake 3.10.x or later must also be used. * If using JDK 11 or later, CMake 3.10.x or later must also be used.
- Vcpkg
You can download and install mozjpeg using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git Sub-Project Builds
cd vcpkg ------------------
./bootstrap-vcpkg.sh
./vcpkg integrate install The libjpeg-turbo build system does not support being included as a sub-project
vcpkg install mozjpeg using the CMake `add_subdirectory()` function. Use the CMake
`ExternalProject_Add()` function instead.
The mozjpeg port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Out-of-Tree Builds Out-of-Tree Builds
@@ -120,6 +100,14 @@ directory, whereas *{source_directory}* refers to the libjpeg-turbo source
directory. For in-tree builds, these directories are the same. directory. For in-tree builds, these directories are the same.
Ninja
-----
If using Ninja, then replace `make` or `nmake` with `ninja`, and replace the
CMake generator (specified with the `-G` option) with `Ninja`, in all of the
procedures and recipes below.
Build Procedure Build Procedure
--------------- ---------------
@@ -345,7 +333,7 @@ Build Recipes
------------- -------------
### 32-bit Build on 64-bit Linux/Unix/Mac ### 32-bit Build on 64-bit Linux/Unix
Use export/setenv to set the following environment variables before running Use export/setenv to set the following environment variables before running
CMake: CMake:
@@ -417,103 +405,9 @@ compression/decompression. This section describes how to build libjpeg-turbo
for these platforms. for these platforms.
### Additional build requirements
- For configurations that require [gas-preprocessor.pl]
(https://raw.githubusercontent.com/libjpeg-turbo/gas-preprocessor/master/gas-preprocessor.pl),
it should be installed in your `PATH`.
### Armv7 (32-bit)
**gas-preprocessor.pl required**
The following scripts demonstrate how to build libjpeg-turbo to run on the
iPhone 3GS-4S/iPad 1st-3rd Generation and newer:
#### Xcode 4.2 and earlier (LLVM-GCC)
IOS_PLATFORMDIR=/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
export CFLAGS="-mfloat-abi=softfp -march=armv7 -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -miphoneos-version-min=3.0"
cd {build_directory}
cat <<EOF >toolchain.cmake
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER ${IOS_PLATFORMDIR}/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2)
EOF
cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
[additional CMake flags] {source_directory}
make
#### Xcode 4.3-4.6 (LLVM-GCC)
Same as above, but replace the first line with:
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
#### Xcode 5 and later (Clang)
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
export CFLAGS="-mfloat-abi=softfp -arch armv7 -miphoneos-version-min=3.0"
export ASMFLAGS="-no-integrated-as"
cd {build_directory}
cat <<EOF >toolchain.cmake
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
EOF
cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
[additional CMake flags] {source_directory}
make
### Armv7s (32-bit)
**gas-preprocessor.pl required**
The following scripts demonstrate how to build libjpeg-turbo to run on the
iPhone 5/iPad 4th Generation and newer:
#### Xcode 4.5-4.6 (LLVM-GCC)
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
export CFLAGS="-Wall -mfloat-abi=softfp -march=armv7s -mcpu=swift -mtune=swift -mfpu=neon -miphoneos-version-min=6.0"
cd {build_directory}
cat <<EOF >toolchain.cmake
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER ${IOS_PLATFORMDIR}/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2)
EOF
cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
[additional CMake flags] {source_directory}
make
#### Xcode 5 and later (Clang)
Same as the Armv7 build procedure for Xcode 5 and later, except replace the
compiler flags as follows:
export CFLAGS="-Wall -mfloat-abi=softfp -arch armv7s -miphoneos-version-min=6.0"
### Armv8 (64-bit) ### Armv8 (64-bit)
**gas-preprocessor.pl required if using Xcode < 6** **Xcode 5 or later required, Xcode 6.3.x or later recommended**
The following script demonstrates how to build libjpeg-turbo to run on the The following script demonstrates how to build libjpeg-turbo to run on the
iPhone 5S/iPad Mini 2/iPad Air and newer. iPhone 5S/iPad Mini 2/iPad Air and newer.
@@ -535,9 +429,6 @@ iPhone 5S/iPad Mini 2/iPad Air and newer.
[additional CMake flags] {source_directory} [additional CMake flags] {source_directory}
make make
Once built, lipo can be used to combine the Armv7, v7s, and/or v8 variants into
a universal library.
Building libjpeg-turbo for Android Building libjpeg-turbo for Android
---------------------------------- ----------------------------------
@@ -548,6 +439,8 @@ Building libjpeg-turbo for Android platforms requires v13b or later of the
### Armv7 (32-bit) ### Armv7 (32-bit)
**NDK r19 or later with Clang recommended**
The following is a general recipe script that can be modified for your specific The following is a general recipe script that can be modified for your specific
needs. needs.
@@ -573,6 +466,8 @@ needs.
### Armv8 (64-bit) ### Armv8 (64-bit)
**Clang recommended**
The following is a general recipe script that can be modified for your specific The following is a general recipe script that can be modified for your specific
needs. needs.
@@ -747,44 +642,23 @@ Mac
make dmg make dmg
Create Mac package/disk image. This requires pkgbuild and productbuild, which Create Mac package/disk image. This requires pkgbuild and productbuild, which
are installed by default on OS X 10.7 and later and which can be obtained by are installed by default on OS X/macOS 10.7 and later.
installing Xcode 3.2.6 (with the "Unix Development" option) on OS X 10.6.
Packages built in this manner can be installed on OS X 10.5 and later, but they
must be built on OS X 10.6 or later.
make udmg In order to create a Mac package/disk image that contains universal
x86-64/Arm binaries, set the following CMake variable:
This creates a Mac package/disk image that contains universal x86-64/i386/Arm * `ARMV8_BUILD`: Directory containing an Armv8 (64-bit) iOS or macOS build of
binaries. The following CMake variables control which architectures are libjpeg-turbo to include in the universal binaries
included in the universal binaries. Setting any of these variables to an empty
string excludes that architecture from the package.
* `OSX_32BIT_BUILD`: Directory containing an i386 (32-bit) Mac build of You should first use CMake to configure an Armv8 sub-build of libjpeg-turbo
libjpeg-turbo (default: *{source_directory}*/osxx86) (see "Building libjpeg-turbo for iOS" above, if applicable) in a build
* `IOS_ARMV7_BUILD`: Directory containing an Armv7 (32-bit) iOS build of directory that matches the one specified in the aforementioned CMake variable.
libjpeg-turbo (default: *{source_directory}*/iosarmv7) Next, configure the primary (x86-64) build of libjpeg-turbo as an out-of-tree
* `IOS_ARMV7S_BUILD`: Directory containing an Armv7s (32-bit) iOS build of build, specifying the aforementioned CMake variable, and build it. Once the
libjpeg-turbo (default: *{source_directory}*/iosarmv7s) primary build has been built, run `make dmg` from the build directory. The
* `IOS_ARMV8_BUILD`: Directory containing an Armv8 (64-bit) iOS build of packaging system will build the sub-build, use lipo to combine it with the
libjpeg-turbo (default: *{source_directory}*/iosarmv8) primary build into a single set of universal binaries, then package the
universal binaries.
You should first use CMake to configure i386, Armv7, Armv7s, and/or Armv8
sub-builds of libjpeg-turbo (see "Build Recipes" and "Building libjpeg-turbo
for iOS" above) in build directories that match those specified in the
aforementioned CMake variables. Next, configure the primary build of
libjpeg-turbo as an out-of-tree build, and build it. Once the primary build
has been built, run `make udmg` from the build directory. The packaging system
will build the sub-builds, use lipo to combine them into a single set of
universal binaries, then package the universal binaries in the same manner as
`make dmg`.
Cygwin
------
make cygwinpkg
Build a Cygwin binary package.
Windows Windows

View File

@@ -1,902 +0,0 @@
*******************************************************************************
** Building on Un*x Platforms (including Cygwin and OS X)
*******************************************************************************
==================
Build Requirements
==================
-- pkg-config
-- autoconf 2.56 or later
-- automake 1.7 or later
-- libtool 1.4 or later
* If using Xcode 4.3 or later on OS X, autoconf and automake are no longer
provided. The easiest way to obtain them is from MacPorts
(http://www.macports.org/).
-- NASM or YASM (if building x86 or x86-64 SIMD extensions)
* NASM 0.98, or 2.01 or later is required for an x86 build (0.99 and 2.00 do
not work properly with libjpeg-turbo's x86 SIMD code.)
* NASM 2.00 or later is required for an x86-64 build.
* NASM 2.07, or 2.11.09 or later is required for an x86-64 Mac build
(2.11.08 does not work properly with libjpeg-turbo's x86-64 SIMD code when
building macho64 objects.) NASM or YASM can be obtained from MacPorts
(http://www.macports.org/).
The binary RPMs released by the NASM project do not work on older Linux
systems, such as Red Hat Enterprise Linux 4. On such systems, you can
easily build and install NASM from a source RPM by downloading one of the
SRPMs from
http://www.nasm.us/pub/nasm/releasebuilds
and executing the following as root:
ARCH=`uname -m`
rpmbuild --rebuild nasm-{version}.src.rpm
rpm -Uvh /usr/src/redhat/RPMS/$ARCH/nasm-{version}.$ARCH.rpm
NOTE: the NASM build will fail if texinfo is not installed.
-- GCC v4.1 or later recommended for best performance
* Beginning with Xcode 4, Apple stopped distributing GCC and switched to
the LLVM compiler. Xcode v4.0 through v4.6 provides a GCC front end
called LLVM-GCC. Unfortunately, as of this writing, neither LLVM-GCC nor
the LLVM (clang) compiler produces optimal performance with libjpeg-turbo.
Building mozjpeg with LLVM-GCC v4.2 results in a 10% performance
degradation when compressing using 64-bit code, relative to building
libjpeg-turbo with GCC v4.2. Building libjpeg-turbo with LLVM (clang)
results in a 20% performance degradation when compressing using 64-bit
code, relative to building libjpeg-turbo with GCC v4.2. If you are
running Snow Leopard or earlier, it is suggested that you continue to use
Xcode v3.2.6, which provides GCC v4.2. If you are using Lion or later, it
is suggested that you install Apple GCC v4.2 or GCC v5 through MacPorts.
-- If building the TurboJPEG Java wrapper, JDK or OpenJDK 1.5 or later is
required. Some systems, such as Solaris 10 and later and Red Hat Enterprise
Linux 5 and later, have this pre-installed. On OS X 10.5 and later, it will
be necessary to install the Java Developer Package, which can be downloaded
from http://developer.apple.com/downloads (Apple ID required.) For systems
that do not have a JDK installed, you can obtain the Oracle Java Development
Kit from http://www.java.com.
==================
Out-of-Tree Builds
==================
Binary objects, libraries, and executables are generated in the same directory
from which configure was executed (the "binary directory"), and this directory
need not necessarily be the same as the mozjpeg source directory. You
can create multiple independent binary directories, in which different versions
of mozjpeg can be built from the same source tree using different
compilers or settings. In the sections below, {build_directory} refers to the
binary directory, whereas {source_directory} refers to the mozjpeg source
directory. For in-tree builds, these directories are the same.
================
Building mozjpeg
================
The following procedure will build mozjpeg on Linux, FreeBSD, Cygwin, and
Solaris/x86 systems (on Solaris, this generates a 32-bit library. See below
for 64-bit build instructions.)
Simple Release tar.gz Source Build
----------------------------------
cd {source_directory}
./configure [additional configure flags]
make
Non-Release Source Build (e.g. GitHub clone)
--------------------------------------------
cd {source_directory}
autoreconf -fiv
cd {build_directory}
sh {source_directory}/configure [additional configure flags]
make
NOTE: Running autoreconf in the source directory is not necessary if building
mozjpeg from one of the official release tarballs.
This will generate the following files under .libs/
libjpeg.a
Static link library for the libjpeg API
libjpeg.so.{version} (Linux, Unix)
libjpeg.{version}.dylib (OS X)
cygjpeg-{version}.dll (Cygwin)
Shared library for the libjpeg API
By default, {version} is 62.2.0, 7.2.0, or 8.1.2, depending on whether
libjpeg v6b (default), v7, or v8 emulation is enabled. If using Cygwin,
{version} is 62, 7, or 8.
libjpeg.so (Linux, Unix)
libjpeg.dylib (OS X)
Development symlink for the libjpeg API
libjpeg.dll.a (Cygwin)
Import library for the libjpeg API
libturbojpeg.a
Static link library for the TurboJPEG API
libturbojpeg.so.0.1.0 (Linux, Unix)
libturbojpeg.0.1.0.dylib (OS X)
cygturbojpeg-0.dll (Cygwin)
Shared library for the TurboJPEG API
libturbojpeg.so (Linux, Unix)
libturbojpeg.dylib (OS X)
Development symlink for the TurboJPEG API
libturbojpeg.dll.a (Cygwin)
Import library for the TurboJPEG API
libjpeg v7 or v8 API/ABI Emulation
----------------------------------
Add --with-jpeg7 to the configure command line to build a version of
mozjpeg that is API/ABI-compatible with libjpeg v7. Add --with-jpeg8 to
the configure command to build a version of mozjpeg that is
API/ABI-compatible with libjpeg v8. See README-turbo.txt for more information
on libjpeg v7 and v8 emulation.
In-Memory Source/Destination Managers
-------------------------------------
When using libjpeg v6b or v7 API/ABI emulation, add --without-mem-srcdst to the
configure command line to build a version of mozjpeg that lacks the
jpeg_mem_src() and jpeg_mem_dest() functions. These functions were not part of
the original libjpeg v6b and v7 APIs, so removing them ensures strict
conformance with those APIs. See README-turbo.txt for more information.
Arithmetic Coding Support
-------------------------
Since the patent on arithmetic coding has expired, this functionality has been
included in this release of mozjpeg. mozjpeg's implementation is
based on the implementation in libjpeg v8, but it works when emulating libjpeg
v7 or v6b as well. The default is to enable both arithmetic encoding and
decoding, but those who have philosophical objections to arithmetic coding can
add --without-arith-enc or --without-arith-dec to the configure command line to
disable encoding or decoding (respectively.)
TurboJPEG Java Wrapper
----------------------
Add --with-java to the configure command line to incorporate an optional Java
Native Interface wrapper into the TurboJPEG shared library and build the Java
front-end classes to support it. This allows the TurboJPEG shared library to
be used directly from Java applications. See java/README for more details.
You can set the JAVAC, JAR, and JAVA configure variables to specify
alternate commands for javac, jar, and java (respectively.) You can also
set the JAVACFLAGS configure variable to specify arguments that should be
passed to the Java compiler when building the front-end classes, and JNI_CFLAGS
to specify arguments that should be passed to the C compiler when building the
JNI wrapper. Run 'configure --help' for more details.
==================
Installing mozjpeg
==================
If you intend to install these libraries and the associated header files, then
replace 'make' in the instructions above with
make install prefix={base dir} libdir={library directory}
For example,
make install prefix=/usr/local libdir=/usr/local/lib64
will install the header files in /usr/local/include and the library files in
/usr/local/lib64. If 'prefix' and 'libdir' are not specified, then the default
is to install the header files in /opt/mozjpeg/include and the library
files in /opt/mozjpeg/lib32 (32-bit) or /opt/mozjpeg/lib64
(64-bit.)
NOTE: You can specify a prefix of /usr and a libdir of, for instance,
/usr/lib64 to overwrite the system's version of libjpeg. If you do this,
however, then be sure to BACK UP YOUR SYSTEM'S INSTALLATION OF LIBJPEG before
overwriting it. It is recommended that you instead install mozjpeg into
a non-system directory and manipulate the LD_LIBRARY_PATH or create symlinks
to force applications to use mozjpeg instead of libjpeg. See
README-turbo.txt for more information.
=============
Build Recipes
=============
32-bit Build on 64-bit Linux
----------------------------
Add
--host i686-pc-linux-gnu CFLAGS='-O3 -m32' LDFLAGS=-m32
to the configure command line.
64-bit Build on 64-bit OS X
---------------------------
Add
--host x86_64-apple-darwin NASM=/opt/local/bin/nasm
to the configure command line. NASM 2.07 or later from MacPorts must be
installed.
32-bit Build on 64-bit OS X
---------------------------
Add
--host i686-apple-darwin CFLAGS='-O3 -m32' LDFLAGS=-m32
to the configure command line.
64-bit Backward-Compatible Build on 64-bit OS X
-----------------------------------------------
Add
--host x86_64-apple-darwin NASM=/opt/local/bin/nasm \
CFLAGS='-isysroot /Developer/SDKs/MacOSX10.5.sdk \
-mmacosx-version-min=10.5 -O3' \
LDFLAGS='-isysroot /Developer/SDKs/MacOSX10.5.sdk \
-mmacosx-version-min=10.5'
to the configure command line. The OS X 10.5 SDK, and NASM 2.07 or later from
MacPorts, must be installed.
32-bit Backward-Compatible Build on OS X
----------------------------------------
Add
--host i686-apple-darwin \
CFLAGS='-isysroot /Developer/SDKs/MacOSX10.5.sdk \
-mmacosx-version-min=10.5 -O3 -m32' \
LDFLAGS='-isysroot /Developer/SDKs/MacOSX10.5.sdk \
-mmacosx-version-min=10.5 -m32'
to the configure command line. The OS X 10.5 SDK must be installed.
64-bit Library Build on 64-bit Solaris
--------------------------------------
Add
--host x86_64-pc-solaris CFLAGS='-O3 -m64' LDFLAGS=-m64
to the configure command line.
32-bit Build on 64-bit FreeBSD
------------------------------
Add
--host i386-unknown-freebsd CC='gcc -B /usr/lib32' CFLAGS='-O3 -m32' \
LDFLAGS='-B/usr/lib32'
to the configure command line. NASM 2.07 or later from FreeBSD ports must be
installed.
Oracle Solaris Studio
---------------------
Add
CC=cc
to the configure command line. mozjpeg will automatically be built with
the maximum optimization level (-xO5) unless you override CFLAGS.
To build a 64-bit version of mozjpeg using Oracle Solaris Studio, add
--host x86_64-pc-solaris CC=cc CFLAGS='-xO5 -m64' LDFLAGS=-m64
to the configure command line.
MinGW Build on Cygwin
---------------------
Use CMake (see recipes below)
===========
ARM Support
===========
This release of mozjpeg can use ARM NEON SIMD instructions to accelerate
JPEG compression/decompression by approximately 2-4x on ARMv7 and later
platforms. If mozjpeg is configured on an ARM Linux platform, then the
build system will automatically include the NEON SIMD routines, if they are
supported. Build instructions for other ARM-based platforms follow.
Building mozjpeg for iOS
------------------------
iOS platforms, such as the iPhone and iPad, use ARM processors, some of which
support NEON instructions. Additional steps are required in order to build
mozjpeg for these platforms.
Additional build requirements:
gas-preprocessor.pl
(https://raw.githubusercontent.com/libjpeg-turbo/gas-preprocessor/master/gas-preprocessor.pl)
should be installed in your PATH.
ARM 32-bit Build (Xcode 4.6.x and earlier, LLVM-GCC):
Set the following shell variables for simplicity:
Xcode 4.2 and earlier:
IOS_PLATFORMDIR=/Developer/Platforms/iPhoneOS.platform
Xcode 4.3 and later:
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=$IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk
IOS_GCC=$IOS_PLATFORMDIR/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2
ARMv6 (code will run on all iOS devices, not SIMD-accelerated):
[NOTE: Requires Xcode 4.4.x or earlier]
IOS_CFLAGS="-march=armv6 -mcpu=arm1176jzf-s -mfpu=vfp"
ARMv7 (code will run on iPhone 3GS-4S/iPad 1st-3rd Generation and newer):
IOS_CFLAGS="-march=armv7 -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon"
ARMv7s (code will run on iPhone 5/iPad 4th Generation and newer):
[NOTE: Requires Xcode 4.5 or later]
IOS_CFLAGS="-march=armv7s -mcpu=swift -mtune=swift -mfpu=neon"
Follow the procedure under "Building mozjpeg" above, adding
--host arm-apple-darwin10 \
CC="$IOS_GCC" LD="$IOS_GCC" \
CFLAGS="-mfloat-abi=softfp -isysroot $IOS_SYSROOT -O3 $IOS_CFLAGS" \
LDFLAGS="-mfloat-abi=softfp -isysroot $IOS_SYSROOT $IOS_CFLAGS"
to the configure command line.
ARM 32-bit Build (Xcode 5.0.x and later, Clang):
Set the following shell variables for simplicity:
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=$IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk
IOS_GCC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
ARMv7 (code will run on iPhone 3GS-4S/iPad 1st-3rd Generation and newer):
IOS_CFLAGS="-arch armv7"
ARMv7s (code will run on iPhone 5/iPad 4th Generation and newer):
IOS_CFLAGS="-arch armv7s"
Follow the procedure under "Building libjpeg-turbo" above, adding
--host arm-apple-darwin10 \
CC="$IOS_GCC" LD="$IOS_GCC" \
CFLAGS="-mfloat-abi=softfp -isysroot $IOS_SYSROOT -O3 $IOS_CFLAGS" \
LDFLAGS="-mfloat-abi=softfp -isysroot $IOS_SYSROOT $IOS_CFLAGS" \
CCASFLAGS="-no-integrated-as $IOS_CFLAGS"
to the configure command line.
ARMv8 64-bit Build (Xcode 5.0.x and later, Clang):
Code will run on iPhone 5S/iPad Mini 2/iPad Air and newer.
Set the following shell variables for simplicity:
IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
IOS_SYSROOT=$IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk
IOS_GCC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
IOS_CFLAGS="-arch arm64"
Follow the procedure under "Building libjpeg-turbo" above, adding
--host aarch64-apple-darwin \
CC="$IOS_GCC" LD="$IOS_GCC" \
CFLAGS="-isysroot $IOS_SYSROOT -O3 $IOS_CFLAGS" \
LDFLAGS="-isysroot $IOS_SYSROOT $IOS_CFLAGS"
to the configure command line.
NOTE: You can also add -miphoneos-version-min={version} to $IOS_CFLAGS above
in order to support older versions of iOS than the default version supported by
the SDK.
Once built, lipo can be used to combine the ARMv6, v7, v7s, and/or v8 variants
into a universal library.
Building libjpeg-turbo for Android
----------------------------------
Building libjpeg-turbo for Android platforms requires the Android NDK
(https://developer.android.com/tools/sdk/ndk) and autotools. The following is
a general recipe script that can be modified for your specific needs.
# Set these variables to suit your needs
NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/ndk}
BUILD_PLATFORM={the platform name for the NDK package you installed--
for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"}
TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc. This corresponds to a
toolchain directory under ${NDK_PATH}/toolchains/.}
ANDROID_VERSION={The minimum version of Android to support-- for example,
"16", "19", etc. "21" or later is required for a 64-bit build.}
# 32-bit ARMv7 build
HOST=arm-linux-androideabi
SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-arm
ANDROID_CFLAGS="-march=armv7-a -mfloat-abi=softfp -fprefetch-loop-arrays \
--sysroot=${SYSROOT}"
# 64-bit ARMv8 build
HOST=aarch64-linux-android
SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-arm64
ANDROID_CFLAGS="--sysroot=${SYSROOT}"
TOOLCHAIN=${NDK_PATH}/toolchains/${HOST}-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM}
ANDROID_INCLUDES="-I${SYSROOT}/usr/include -I${TOOLCHAIN}/include"
export CPP=${TOOLCHAIN}/bin/${HOST}-cpp
export AR=${TOOLCHAIN}/bin/${HOST}-ar
export AS=${TOOLCHAIN}/bin/${HOST}-as
export NM=${TOOLCHAIN}/bin/${HOST}-nm
export CC=${TOOLCHAIN}/bin/${HOST}-gcc
export LD=${TOOLCHAIN}/bin/${HOST}-ld
export RANLIB=${TOOLCHAIN}/bin/${HOST}-ranlib
export OBJDUMP=${TOOLCHAIN}/bin/${HOST}-objdump
export STRIP=${TOOLCHAIN}/bin/${HOST}-strip
cd {build_directory}
sh {source_directory}/configure --host=${HOST} \
CFLAGS="${ANDROID_INCLUDES} ${ANDROID_CFLAGS} -O3 -fPIE" \
CPPFLAGS="${ANDROID_INCLUDES} ${ANDROID_CFLAGS}" \
LDFLAGS="${ANDROID_CFLAGS} -pie" --with-simd ${1+"$@"}
make
If building for Android 4.0.x (API level < 16) or earlier, remove -fPIE from
CFLAGS and -pie from LDFLAGS.
*******************************************************************************
** Building on Windows (Visual C++ or MinGW)
*******************************************************************************
==================
Build Requirements
==================
-- CMake (http://www.cmake.org) v2.8.8 or later
-- Microsoft Visual C++ 2005 or later
If you don't already have Visual C++, then the easiest way to get it is by
installing the Windows SDK:
http://msdn.microsoft.com/en-us/windows/bb980924.aspx
The Windows SDK includes both 32-bit and 64-bit Visual C++ compilers and
everything necessary to build mozjpeg.
* You can also use Microsoft Visual Studio Express Edition, which is a free
download. (NOTE: versions prior to 2012 can only be used to build 32-bit
code.)
* If you intend to build mozjpeg from the command line, then add the
appropriate compiler and SDK directories to the INCLUDE, LIB, and PATH
environment variables. This is generally accomplished by executing
vcvars32.bat or vcvars64.bat and SetEnv.cmd. vcvars32.bat and
vcvars64.bat are part of Visual C++ and are located in the same directory
as the compiler. SetEnv.cmd is part of the Windows SDK. You can pass
optional arguments to SetEnv.cmd to specify a 32-bit or 64-bit build
environment.
... OR ...
-- MinGW
MinGW-builds (http://sourceforge.net/projects/mingwbuilds/) or
tdm-gcc (http://tdm-gcc.tdragon.net/) recommended if building on a Windows
machine. Both distributions install a Start Menu link that can be used to
launch a command prompt with the appropriate compiler paths automatically
set.
-- NASM (http://www.nasm.us/) 0.98 or later (NASM 2.05 or later is required for
a 64-bit build)
-- If building the TurboJPEG Java wrapper, JDK 1.5 or later is required. This
can be downloaded from http://www.java.com.
==================
Out-of-Tree Builds
==================
Binary objects, libraries, and executables are generated in the same directory
from which cmake was executed (the "binary directory"), and this directory need
not necessarily be the same as the mozjpeg source directory. You can
create multiple independent binary directories, in which different versions of
mozjpeg can be built from the same source tree using different compilers
or settings. In the sections below, {build_directory} refers to the binary
directory, whereas {source_directory} refers to the mozjpeg source
directory. For in-tree builds, these directories are the same.
================
Building mozjpeg
================
Visual C++ (Command Line)
-------------------------
cd {build_directory}
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release {source_directory}
nmake
This will build either a 32-bit or a 64-bit version of mozjpeg, depending
on which version of cl.exe is in the PATH.
The following files will be generated under {build_directory}:
jpeg-static.lib
Static link library for the libjpeg API
sharedlib/jpeg{version}.dll
DLL for the libjpeg API
sharedlib/jpeg.lib
Import library for the libjpeg API
turbojpeg-static.lib
Static link library for the TurboJPEG API
turbojpeg.dll
DLL for the TurboJPEG API
turbojpeg.lib
Import library for the TurboJPEG API
{version} is 62, 7, or 8, depending on whether libjpeg v6b (default), v7, or
v8 emulation is enabled.
Visual C++ (IDE)
----------------
Choose the appropriate CMake generator option for your version of Visual Studio
(run "cmake" with no arguments for a list of available generators.) For
instance:
cd {build_directory}
cmake -G "Visual Studio 10" {source_directory}
NOTE: Add "Win64" to the generator name (for example, "Visual Studio 10
Win64") to build a 64-bit version of libjpeg-turbo. Recent versions of CMake
no longer document that. A separate build directory must be used for 32-bit
and 64-bit builds.
You can then open ALL_BUILD.vcproj in Visual Studio and build one of the
configurations in that project ("Debug", "Release", etc.) to generate a full
build of mozjpeg.
This will generate the following files under {build_directory}:
{configuration}/jpeg-static.lib
Static link library for the libjpeg API
sharedlib/{configuration}/jpeg{version}.dll
DLL for the libjpeg API
sharedlib/{configuration}/jpeg.lib
Import library for the libjpeg API
{configuration}/turbojpeg-static.lib
Static link library for the TurboJPEG API
{configuration}/turbojpeg.dll
DLL for the TurboJPEG API
{configuration}/turbojpeg.lib
Import library for the TurboJPEG API
{configuration} is Debug, Release, RelWithDebInfo, or MinSizeRel, depending on
the configuration you built in the IDE, and {version} is 62, 7, or 8,
depending on whether libjpeg v6b (default), v7, or v8 emulation is enabled.
MinGW
-----
NOTE: This assumes that you are building on a Windows machine. If you are
cross-compiling on a Linux/Unix machine, then see "Build Recipes" below.
cd {build_directory}
cmake -G "MinGW Makefiles" {source_directory}
mingw32-make
This will generate the following files under {build_directory}
libjpeg.a
Static link library for the libjpeg API
sharedlib/libjpeg-{version}.dll
DLL for the libjpeg API
sharedlib/libjpeg.dll.a
Import library for the libjpeg API
libturbojpeg.a
Static link library for the TurboJPEG API
libturbojpeg.dll
DLL for the TurboJPEG API
libturbojpeg.dll.a
Import library for the TurboJPEG API
{version} is 62, 7, or 8, depending on whether libjpeg v6b (default), v7, or
v8 emulation is enabled.
Debug Build
-----------
Add "-DCMAKE_BUILD_TYPE=Debug" to the cmake command line. Or, if building with
NMake, remove "-DCMAKE_BUILD_TYPE=Release" (Debug builds are the default with
NMake.)
libjpeg v7 or v8 API/ABI Emulation
-----------------------------------
Add "-DWITH_JPEG7=1" to the cmake command line to build a version of
mozjpeg that is API/ABI-compatible with libjpeg v7. Add "-DWITH_JPEG8=1"
to the cmake command to build a version of mozjpeg that is
API/ABI-compatible with libjpeg v8. See README-turbo.txt for more information
on libjpeg v7 and v8 emulation.
In-Memory Source/Destination Managers
-------------------------------------
When using libjpeg v6b or v7 API/ABI emulation, add -DWITH_MEM_SRCDST=0 to the
CMake command line to build a version of mozjpeg that lacks the
jpeg_mem_src() and jpeg_mem_dest() functions. These functions were not part of
the original libjpeg v6b and v7 APIs, so removing them ensures strict
conformance with those APIs. See README-turbo.txt for more information.
Arithmetic Coding Support
-------------------------
Since the patent on arithmetic coding has expired, this functionality has been
included in this release of mozjpeg. mozjpeg's implementation is
based on the implementation in libjpeg v8, but it works when emulating libjpeg
v7 or v6b as well. The default is to enable both arithmetic encoding and
decoding, but those who have philosophical objections to arithmetic coding can
add "-DWITH_ARITH_ENC=0" or "-DWITH_ARITH_DEC=0" to the cmake command line to
disable encoding or decoding (respectively.)
TurboJPEG Java Wrapper
----------------------
Add "-DWITH_JAVA=1" to the cmake command line to incorporate an optional Java
Native Interface wrapper into the TurboJPEG shared library and build the Java
front-end classes to support it. This allows the TurboJPEG shared library to
be used directly from Java applications. See java/README for more details.
If you are using CMake 2.8, you can set the Java_JAVAC_EXECUTABLE,
Java_JAVA_EXECUTABLE, and Java_JAR_EXECUTABLE CMake variables to specify
alternate commands or locations for javac, jar, and java (respectively.) If
you are using CMake 2.6, set JAVA_COMPILE, JAVA_RUNTIME, and JAVA_ARCHIVE
instead. You can also set the JAVACFLAGS CMake variable to specify arguments
that should be passed to the Java compiler when building the front-end classes.
==================
Installing mozjpeg
==================
You can use the build system to install mozjpeg into a directory of your
choosing (as opposed to creating an installer.) To do this, add:
-DCMAKE_INSTALL_PREFIX={install_directory}
to the cmake command line.
For example,
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=c:\mozjpeg {source_directory}
nmake install
will install the header files in c:\mozjpeg\include, the library files
in c:\mozjpeg\lib, the DLL's in c:\mozjpeg\bin, and the
documentation in c:\mozjpeg\doc.
=============
Build Recipes
=============
64-bit MinGW Build on Cygwin
----------------------------
cd {build_directory}
CC=/usr/bin/x86_64-w64-mingw32-gcc \
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_RC_COMPILER=/usr/bin/x86_64-w64-mingw32-windres.exe \
{source_directory}
make
This produces a 64-bit build of mozjpeg that does not depend on
cygwin1.dll or other Cygwin DLL's. The mingw64-x86_64-gcc-core and
mingw64-x86_64-gcc-g++ packages (and their dependencies) must be installed.
32-bit MinGW Build on Cygwin
----------------------------
cd {build_directory}
CC=/usr/bin/i686-w64-mingw32-gcc \
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_RC_COMPILER=/usr/bin/i686-w64-mingw32-windres.exe \
{source_directory}
make
This produces a 32-bit build of mozjpeg that does not depend on
cygwin1.dll or other Cygwin DLL's. The mingw64-i686-gcc-core and
mingw64-i686-gcc-g++ packages (and their dependencies) must be installed.
MinGW Build on Linux
--------------------
cd {build_directory}
CC={mingw_binary_path}/i386-mingw32-gcc \
cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_AR={mingw_binary_path}/i386-mingw32-ar \
-DCMAKE_RANLIB={mingw_binary_path}/i386-mingw32-ranlib \
{source_directory}
make
*******************************************************************************
** Creating Release Packages
*******************************************************************************
The following commands can be used to create various types of release packages:
Unix/Linux
----------
make rpm
Create Red Hat-style binary RPM package. Requires RPM v4 or later.
make srpm
This runs 'make dist' to create a pristine source tarball, then creates a
Red Hat-style source RPM package from the tarball. Requires RPM v4 or later.
make deb
Create Debian-style binary package. Requires dpkg.
make dmg
Create Macintosh package/disk image. This requires pkgbuild and
productbuild, which are installed by default on OS X 10.7 and later and which
can be obtained by installing Xcode 3.2.6 (with the "Unix Development"
option) on OS X 10.6. Packages built in this manner can be installed on OS X
10.5 and later, but they must be built on OS X 10.6 or later.
make udmg [BUILDDIR32={32-bit build directory}]
On 64-bit OS X systems, this creates a Macintosh package and disk image that
contains universal i386/x86-64 binaries. You should first configure a 32-bit
out-of-tree build of mozjpeg, then configure a 64-bit out-of-tree
build, then run 'make udmg' from the 64-bit build directory. The build
system will look for the 32-bit build under {source_directory}/osxx86 by
default, but you can override this by setting the BUILDDIR32 variable on the
make command line as shown above.
make iosdmg [BUILDDIR32={32-bit build directory}] \
[BUILDDIRARMV6={ARMv6 build directory}] \
[BUILDDIRARMV7={ARMv7 build directory}] \
[BUILDDIRARMV7S={ARMv7s build directory}] \
[BUILDDIRARMV8={ARMv8 build directory}]
On OS X systems, this creates a Macintosh package and disk image in which the
mozjpeg static libraries contain ARM architectures necessary to build
iOS applications. If building on an x86-64 system, the binaries will also
contain the i386 architecture, as with 'make udmg' above. You should first
configure ARMv6, ARMv7, ARMv7s, and/or ARMv8 out-of-tree builds of
mozjpeg (see "Building mozjpeg for iOS" above.) If you are
building an x86-64 version of mozjpeg, you should configure a 32-bit
out-of-tree build as well. Next, build mozjpeg as you would normally,
using an out-of-tree build. When it is built, run 'make iosdmg' from the
build directory. The build system will look for the ARMv6 build under
{source_directory}/iosarmv6 by default, the ARMv7 build under
{source_directory}/iosarmv7 by default, the ARMv7s build under
{source_directory}/iosarmv7s by default, the ARMv8 build under
{source_directory}/iosarmv8 by default, and (if applicable) the 32-bit build
under {source_directory}/osxx86 by default, but you can override this by
setting the BUILDDIR32, BUILDDIRARMV6, BUILDDIRARMV7, BUILDDIRARMV7S, and/or
BUILDDIRARMV8 variables on the make command line as shown above.
NOTE: If including an ARMv8 build in the package, then you may need to use
Xcode's version of lipo instead of the operating system's. To do this, pass
an argument of LIPO="xcrun lipo" on the make command line.
make cygwinpkg
Build a Cygwin binary package.
Windows
-------
If using NMake:
cd {build_directory}
nmake installer
If using MinGW:
cd {build_directory}
make installer
If using the Visual Studio IDE, build the "installer" project.
The installer package (mozjpeg[-gcc][64].exe) will be located under
{build_directory}. If building using the Visual Studio IDE, then the installer
package will be located in a subdirectory with the same name as the
configuration you built (such as {build_directory}\Debug\ or
{build_directory}\Release\).
Building a Windows installer requires the Nullsoft Install System
(http://nsis.sourceforge.net/.) makensis.exe should be in your PATH.
*******************************************************************************
** Regression testing
*******************************************************************************
The most common way to test mozjpeg is by invoking 'make test' on
Unix/Linux platforms or 'ctest' on Windows platforms, once the build has
completed. This runs a series of tests to ensure that mathematical
compatibility has been maintained. This also invokes the TurboJPEG unit tests,
which ensure that the colorspace extensions, YUV encoding, decompression
scaling, and other features of the TurboJPEG C and Java APIs are working
properly (and, by extension, that the equivalent features of the underlying
libjpeg API are also working.)
Invoking 'make testclean' or 'nmake testclean' (if using NMake) or building
the 'testclean' target (if using the Visual Studio IDE) will clean up the
output images generated by 'make test'.
On Unix/Linux platforms, more extensive tests of the TurboJPEG C and Java
wrappers can be run by invoking 'make tjtest'. These extended TurboJPEG tests
essentially iterate through all of the available features of the TurboJPEG APIs
that are not covered by the TurboJPEG unit tests (this includes the lossless
transform options) and compare the images generated by each feature to images
generated using the equivalent feature in the libjpeg API. The extended
TurboJPEG tests are meant to test for regressions in the TurboJPEG wrappers,
not in the underlying libjpeg API library.

View File

@@ -1,11 +1,17 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8.12)
# When using CMake 3.4 and later, don't export symbols from executables unless
# the CMAKE_ENABLE_EXPORTS variable is set.
if(POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
if(CMAKE_EXECUTABLE_SUFFIX) if(CMAKE_EXECUTABLE_SUFFIX)
set(CMAKE_EXECUTABLE_SUFFIX_TMP ${CMAKE_EXECUTABLE_SUFFIX}) set(CMAKE_EXECUTABLE_SUFFIX_TMP ${CMAKE_EXECUTABLE_SUFFIX})
endif() endif()
project(mozjpeg C) project(libjpeg-turbo C)
set(VERSION 4.0.2) set(VERSION 2.1.4)
set(COPYRIGHT_YEAR "1991-2022")
string(REPLACE "." ";" VERSION_TRIPLET ${VERSION}) string(REPLACE "." ";" VERSION_TRIPLET ${VERSION})
list(GET VERSION_TRIPLET 0 VERSION_MAJOR) list(GET VERSION_TRIPLET 0 VERSION_MAJOR)
list(GET VERSION_TRIPLET 1 VERSION_MINOR) list(GET VERSION_TRIPLET 1 VERSION_MINOR)
@@ -25,6 +31,15 @@ pad_number(VERSION_MINOR 3)
pad_number(VERSION_REVISION 3) pad_number(VERSION_REVISION 3)
set(LIBJPEG_TURBO_VERSION_NUMBER ${VERSION_MAJOR}${VERSION_MINOR}${VERSION_REVISION}) set(LIBJPEG_TURBO_VERSION_NUMBER ${VERSION_MAJOR}${VERSION_MINOR}${VERSION_REVISION})
# CMake 3.14 and later sets CMAKE_MACOSX_BUNDLE to TRUE by default when
# CMAKE_SYSTEM_NAME is iOS, tvOS, or watchOS, which breaks the libjpeg-turbo
# build. (Specifically, when CMAKE_MACOSX_BUNDLE is TRUE, executables for
# Apple platforms are built as application bundles, which causes CMake to
# complain that our install() directives for executables do not specify a
# BUNDLE DESTINATION. Even if CMake did not complain, building executables as
# application bundles would break our iOS packages.)
set(CMAKE_MACOSX_BUNDLE FALSE)
string(TIMESTAMP DEFAULT_BUILD "%Y%m%d") string(TIMESTAMP DEFAULT_BUILD "%Y%m%d")
set(BUILD ${DEFAULT_BUILD} CACHE STRING "Build string (default: ${DEFAULT_BUILD})") set(BUILD ${DEFAULT_BUILD} CACHE STRING "Build string (default: ${DEFAULT_BUILD})")
@@ -38,15 +53,24 @@ message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
message(STATUS "VERSION = ${VERSION}, BUILD = ${BUILD}") message(STATUS "VERSION = ${VERSION}, BUILD = ${BUILD}")
include(cmakescripts/PackageInfo.cmake)
# Detect CPU type and whether we're building 64-bit or 32-bit code # Detect CPU type and whether we're building 64-bit or 32-bit code
math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8") math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8")
string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR_LC) string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR_LC)
set(COUNT 1)
foreach(ARCH ${CMAKE_OSX_ARCHITECTURES})
if(COUNT GREATER 1)
message(FATAL_ERROR "The libjpeg-turbo build system does not support multiple values in CMAKE_OSX_ARCHITECTURES.")
endif()
math(EXPR COUNT "${COUNT}+1")
endforeach()
if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "amd64" OR CMAKE_SYSTEM_PROCESSOR_LC MATCHES "amd64" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "i[0-9]86" OR CMAKE_SYSTEM_PROCESSOR_LC MATCHES "i[0-9]86" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86" OR CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ia32") CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ia32")
if(BITS EQUAL 64) if(BITS EQUAL 64 OR CMAKE_C_COMPILER_ABI MATCHES "ELF X32")
set(CPU_TYPE x86_64) set(CPU_TYPE x86_64)
else() else()
set(CPU_TYPE i386) set(CPU_TYPE i386)
@@ -55,18 +79,30 @@ if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR
set(CMAKE_SYSTEM_PROCESSOR ${CPU_TYPE}) set(CMAKE_SYSTEM_PROCESSOR ${CPU_TYPE})
endif() endif()
elseif(CMAKE_SYSTEM_PROCESSOR_LC STREQUAL "aarch64" OR elseif(CMAKE_SYSTEM_PROCESSOR_LC STREQUAL "aarch64" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "arm*") CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^arm")
if(BITS EQUAL 64) if(BITS EQUAL 64)
set(CPU_TYPE arm64) set(CPU_TYPE arm64)
else() else()
set(CPU_TYPE arm) set(CPU_TYPE arm)
endif() endif()
elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ppc*" OR elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^ppc" OR
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "powerpc*") CMAKE_SYSTEM_PROCESSOR_LC MATCHES "^powerpc")
set(CPU_TYPE powerpc) set(CPU_TYPE powerpc)
else() else()
set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC}) set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC})
endif() endif()
if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR
CMAKE_OSX_ARCHITECTURES MATCHES "arm64" OR
CMAKE_OSX_ARCHITECTURES MATCHES "i386")
set(CPU_TYPE ${CMAKE_OSX_ARCHITECTURES})
endif()
if(CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
set(CPU_TYPE powerpc)
endif()
if(MSVC_IDE AND CMAKE_GENERATOR_PLATFORM MATCHES "arm64")
set(CPU_TYPE arm64)
endif()
message(STATUS "${BITS}-bit build (${CPU_TYPE})") message(STATUS "${BITS}-bit build (${CPU_TYPE})")
@@ -84,7 +120,9 @@ if(WIN32)
set(CMAKE_INSTALL_DEFAULT_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}64") set(CMAKE_INSTALL_DEFAULT_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}64")
endif() endif()
else() else()
set(CMAKE_INSTALL_DEFAULT_PREFIX /opt/${CMAKE_PROJECT_NAME}) if(NOT CMAKE_INSTALL_DEFAULT_PREFIX)
set(CMAKE_INSTALL_DEFAULT_PREFIX /opt/${CMAKE_PROJECT_NAME})
endif()
endif() endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}" CACHE PATH set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}" CACHE PATH
@@ -103,6 +141,8 @@ if(CMAKE_INSTALL_PREFIX STREQUAL "${CMAKE_INSTALL_DEFAULT_PREFIX}")
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
if(BITS EQUAL 64) if(BITS EQUAL 64)
set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64") set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64")
elseif(CMAKE_C_COMPILER_ABI MATCHES "ELF X32")
set(CMAKE_INSTALL_DEFAULT_LIBDIR "libx32")
else() else()
set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib32") set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib32")
endif() endif()
@@ -135,9 +175,9 @@ endforeach()
macro(boolean_number var) macro(boolean_number var)
if(${var}) if(${var})
set(${var} 1) set(${var} 1 ${ARGN})
else() else()
set(${var} 0) set(${var} 0 ${ARGN})
endif() endif()
endmacro() endmacro()
@@ -147,16 +187,18 @@ option(ENABLE_STATIC "Build static libraries" TRUE)
boolean_number(ENABLE_STATIC) boolean_number(ENABLE_STATIC)
option(REQUIRE_SIMD "Generate a fatal error if SIMD extensions are not available for this platform (default is to fall back to a non-SIMD build)" FALSE) option(REQUIRE_SIMD "Generate a fatal error if SIMD extensions are not available for this platform (default is to fall back to a non-SIMD build)" FALSE)
boolean_number(REQUIRE_SIMD) boolean_number(REQUIRE_SIMD)
option(PNG_SUPPORTED "Enable PNG support (requires libpng)" TRUE)
boolean_number(PNG_SUPPORTED)
option(WITH_12BIT "Encode/decode JPEG images with 12-bit samples (implies WITH_ARITH_DEC=0 WITH_ARITH_ENC=0 WITH_JAVA=0 WITH_SIMD=0 WITH_TURBOJPEG=0 )" FALSE) option(WITH_12BIT "Encode/decode JPEG images with 12-bit samples (implies WITH_ARITH_DEC=0 WITH_ARITH_ENC=0 WITH_JAVA=0 WITH_SIMD=0 WITH_TURBOJPEG=0 )" FALSE)
boolean_number(WITH_12BIT) boolean_number(WITH_12BIT)
option(WITH_ARITH_DEC "Include arithmetic decoding support when emulating the libjpeg v6b API/ABI" FALSE) option(WITH_ARITH_DEC "Include arithmetic decoding support when emulating the libjpeg v6b API/ABI" TRUE)
boolean_number(WITH_ARITH_DEC) boolean_number(WITH_ARITH_DEC)
option(WITH_ARITH_ENC "Include arithmetic encoding support when emulating the libjpeg v6b API/ABI" FALSE) option(WITH_ARITH_ENC "Include arithmetic encoding support when emulating the libjpeg v6b API/ABI" TRUE)
boolean_number(WITH_ARITH_ENC) boolean_number(WITH_ARITH_ENC)
option(WITH_JAVA "Build Java wrapper for the TurboJPEG API library (implies ENABLE_SHARED=1)" FALSE) if(CMAKE_C_COMPILER_ABI MATCHES "ELF X32")
boolean_number(WITH_JAVA) set(WITH_JAVA 0)
else()
option(WITH_JAVA "Build Java wrapper for the TurboJPEG API library (implies ENABLE_SHARED=1)" FALSE)
boolean_number(WITH_JAVA)
endif()
option(WITH_JPEG7 "Emulate libjpeg v7 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE) option(WITH_JPEG7 "Emulate libjpeg v7 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE)
boolean_number(WITH_JPEG7) boolean_number(WITH_JPEG7)
option(WITH_JPEG8 "Emulate libjpeg v8 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE) option(WITH_JPEG8 "Emulate libjpeg v8 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE)
@@ -167,6 +209,7 @@ option(WITH_SIMD "Include SIMD extensions, if available for this platform" TRUE)
boolean_number(WITH_SIMD) boolean_number(WITH_SIMD)
option(WITH_TURBOJPEG "Include the TurboJPEG API library and associated test programs" TRUE) option(WITH_TURBOJPEG "Include the TurboJPEG API library and associated test programs" TRUE)
boolean_number(WITH_TURBOJPEG) boolean_number(WITH_TURBOJPEG)
option(WITH_FUZZ "Build fuzz targets" FALSE)
macro(report_option var desc) macro(report_option var desc)
if(${var}) if(${var})
@@ -296,7 +339,8 @@ message(STATUS "libjpeg API shared library version = ${SO_MAJOR_VERSION}.${SO_AG
# minor SO versions don't change. However, we increase the middle number (the # minor SO versions don't change. However, we increase the middle number (the
# SO "age") whenever functions are added to the API. # SO "age") whenever functions are added to the API.
set(TURBOJPEG_SO_MAJOR_VERSION 0) set(TURBOJPEG_SO_MAJOR_VERSION 0)
set(TURBOJPEG_SO_VERSION 0.2.0) set(TURBOJPEG_SO_AGE 2)
set(TURBOJPEG_SO_VERSION 0.${TURBOJPEG_SO_AGE}.0)
############################################################################### ###############################################################################
@@ -316,7 +360,7 @@ if(MSVC)
endif() endif()
endforeach() endforeach()
endif() endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /wd4996") add_definitions(-D_CRT_NONSTDC_NO_WARNINGS)
endif() endif()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
@@ -366,34 +410,6 @@ if(MSVC)
endif() endif()
if(UNIX) if(UNIX)
# Check for headers
check_include_files(locale.h HAVE_LOCALE_H)
check_include_files(stddef.h HAVE_STDDEF_H)
check_include_files(stdlib.h HAVE_STDLIB_H)
check_include_files(sys/types.h NEED_SYS_TYPES_H)
# Check for functions
include(CheckSymbolExists)
check_symbol_exists(memset string.h HAVE_MEMSET)
check_symbol_exists(memcpy string.h HAVE_MEMCPY)
if(NOT HAVE_MEMSET AND NOT HAVE_MEMCPY)
set(NEED_BSD_STRINGS 1)
endif()
# Check for types
check_type_size("unsigned char" UNSIGNED_CHAR)
check_type_size("unsigned short" UNSIGNED_SHORT)
# Check for compiler features
check_c_source_compiles("int main(void) { typedef struct undefined_structure *undef_struct_ptr; undef_struct_ptr ptr = 0; return ptr != 0; }"
INCOMPLETE_TYPES)
if(INCOMPLETE_TYPES)
message(STATUS "Compiler supports pointers to undefined structures.")
else()
set(INCOMPLETE_TYPES_BROKEN 1)
message(STATUS "Compiler does not support pointers to undefined structures.")
endif()
if(CMAKE_CROSSCOMPILING) if(CMAKE_CROSSCOMPILING)
set(RIGHT_SHIFT_IS_UNSIGNED 0) set(RIGHT_SHIFT_IS_UNSIGNED 0)
else() else()
@@ -418,13 +434,6 @@ if(UNIX)
exit(is_shifting_signed(-0x7F7E80B1L)); exit(is_shifting_signed(-0x7F7E80B1L));
}" RIGHT_SHIFT_IS_UNSIGNED) }" RIGHT_SHIFT_IS_UNSIGNED)
endif() endif()
if(CMAKE_CROSSCOMPILING)
set(__CHAR_UNSIGNED__ 0)
else()
check_c_source_runs("int main(void) { return ((char) -1 < 0); }"
__CHAR_UNSIGNED__)
endif()
endif() endif()
if(MSVC) if(MSVC)
@@ -511,6 +520,7 @@ else()
configure_file(jconfig.h.in jconfig.h) configure_file(jconfig.h.in jconfig.h)
endif() endif()
configure_file(jconfigint.h.in jconfigint.h) configure_file(jconfigint.h.in jconfigint.h)
configure_file(jversion.h.in jversion.h)
if(UNIX) if(UNIX)
configure_file(libjpeg.map.in libjpeg.map) configure_file(libjpeg.map.in libjpeg.map)
endif() endif()
@@ -528,7 +538,7 @@ 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 jcext.c set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c
jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c
jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.c
@@ -550,6 +560,9 @@ endif()
if(WITH_SIMD) if(WITH_SIMD)
add_subdirectory(simd) add_subdirectory(simd)
if(NEON_INTRINSICS)
add_definitions(-DNEON_INTRINSICS)
endif()
elseif(NOT WITH_12BIT) elseif(NOT WITH_12BIT)
message(STATUS "SIMD extensions: None (WITH_SIMD = ${WITH_SIMD})") message(STATUS "SIMD extensions: None (WITH_SIMD = ${WITH_SIMD})")
endif() endif()
@@ -560,6 +573,9 @@ if(WITH_SIMD)
endif() endif()
else() else()
add_library(simd OBJECT jsimd_none.c) add_library(simd OBJECT jsimd_none.c)
if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED))
set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif()
endif() endif()
if(WITH_JAVA) if(WITH_JAVA)
@@ -589,6 +605,12 @@ if(WITH_TURBOJPEG)
include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2}) include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile.jni) set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile.jni)
endif() endif()
if(MSVC)
configure_file(${CMAKE_SOURCE_DIR}/win/turbojpeg.rc.in
${CMAKE_BINARY_DIR}/win/turbojpeg.rc)
set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES}
${CMAKE_BINARY_DIR}/win/turbojpeg.rc)
endif()
add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES}) add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES})
set_property(TARGET turbojpeg PROPERTY COMPILE_FLAGS set_property(TARGET turbojpeg PROPERTY COMPILE_FLAGS
"-DBMP_SUPPORTED -DPPM_SUPPORTED") "-DBMP_SUPPORTED -DPPM_SUPPORTED")
@@ -614,9 +636,6 @@ if(WITH_TURBOJPEG)
add_executable(tjunittest tjunittest.c tjutil.c md5/md5.c md5/md5hl.c) add_executable(tjunittest tjunittest.c tjutil.c md5/md5.c md5/md5hl.c)
target_link_libraries(tjunittest turbojpeg) target_link_libraries(tjunittest turbojpeg)
if(UNIX)
target_link_libraries(tjunittest m)
endif()
add_executable(tjbench tjbench.c tjutil.c) add_executable(tjbench tjbench.c tjutil.c)
target_link_libraries(tjbench turbojpeg) target_link_libraries(tjbench turbojpeg)
@@ -626,9 +645,6 @@ if(WITH_TURBOJPEG)
add_executable(tjexample tjexample.c) add_executable(tjexample tjexample.c)
target_link_libraries(tjexample turbojpeg) target_link_libraries(tjexample turbojpeg)
if(UNIX)
target_link_libraries(tjexample m)
endif()
endif() endif()
if(ENABLE_STATIC) if(ENABLE_STATIC)
@@ -644,9 +660,6 @@ if(WITH_TURBOJPEG)
add_executable(tjunittest-static tjunittest.c tjutil.c md5/md5.c add_executable(tjunittest-static tjunittest.c tjutil.c md5/md5.c
md5/md5hl.c) md5/md5hl.c)
target_link_libraries(tjunittest-static turbojpeg-static) target_link_libraries(tjunittest-static turbojpeg-static)
if(UNIX)
target_link_libraries(tjunittest-static m)
endif()
add_executable(tjbench-static tjbench.c tjutil.c) add_executable(tjbench-static tjbench.c tjutil.c)
target_link_libraries(tjbench-static turbojpeg-static) target_link_libraries(tjbench-static turbojpeg-static)
@@ -665,58 +678,21 @@ else()
set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}") set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
set(CJPEG_BMP_SOURCES rdbmp.c rdtarga.c) set(CJPEG_BMP_SOURCES rdbmp.c rdtarga.c)
set(DJPEG_BMP_SOURCES wrbmp.c wrtarga.c) set(DJPEG_BMP_SOURCES wrbmp.c wrtarga.c)
if(PNG_SUPPORTED)
report_option(PNG_SUPPORTED "PNG reading support")
set(COMPILE_FLAGS "${COMPILE_FLAGS} -DPNG_SUPPORTED")
set(CJPEG_BMP_SOURCES ${CJPEG_BMP_SOURCES} rdpng.c)
endif()
endif() endif()
if(ENABLE_STATIC) if(ENABLE_STATIC)
add_executable(cjpeg-static cjpeg.c cdjpeg.c rdgif.c rdppm.c rdjpeg.c rdswitch.c add_executable(cjpeg-static cjpeg.c cdjpeg.c rdgif.c rdppm.c rdswitch.c
${CJPEG_BMP_SOURCES}) ${CJPEG_BMP_SOURCES})
set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
target_link_libraries(cjpeg-static jpeg-static) target_link_libraries(cjpeg-static jpeg-static)
if(UNIX)
target_link_libraries(cjpeg-static m)
endif()
if(PNG_SUPPORTED)
# to avoid finding shared library from CMake cache
unset(PNG_LIBRARY CACHE)
unset(PNG_LIBRARY_RELEASE CACHE)
unset(PNG_LIBRARY_DEBUG CACHE)
unset(ZLIB_LIBRARY CACHE)
unset(ZLIB_LIBRARY_RELEASE CACHE)
unset(ZLIB_LIBRARY_DEBUG CACHE)
if (APPLE)
find_package(ZLIB REQUIRED) # macos doesn't have static zlib
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
find_package(PNG 1.6 REQUIRED)
if (NOT APPLE)
find_package(ZLIB REQUIRED)
endif()
target_include_directories(cjpeg-static PUBLIC ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
target_link_libraries(cjpeg-static ${PNG_LIBRARY} ${ZLIB_LIBRARY})
endif()
add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrgif.c add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrgif.c
wrppm.c ${DJPEG_BMP_SOURCES}) wrppm.c ${DJPEG_BMP_SOURCES})
set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
target_link_libraries(djpeg-static jpeg-static) target_link_libraries(djpeg-static jpeg-static)
if(UNIX)
target_link_libraries(djpeg-static m)
endif()
add_executable(jpegtran-static jpegtran.c cdjpeg.c rdswitch.c transupp.c) add_executable(jpegtran-static jpegtran.c cdjpeg.c rdswitch.c transupp.c)
target_link_libraries(jpegtran-static jpeg-static) target_link_libraries(jpegtran-static jpeg-static)
if(UNIX)
target_link_libraries(jpegtran-static m)
endif()
set_property(TARGET jpegtran-static PROPERTY COMPILE_FLAGS "${USE_SETMODE}") set_property(TARGET jpegtran-static PROPERTY COMPILE_FLAGS "${USE_SETMODE}")
endif() endif()
@@ -729,6 +705,12 @@ add_executable(wrjpgcom wrjpgcom.c)
# TESTS # TESTS
############################################################################### ###############################################################################
if(WITH_FUZZ)
add_subdirectory(fuzz)
endif()
add_executable(strtest strtest.c)
add_subdirectory(md5) add_subdirectory(md5)
if(MSVC_IDE OR XCODE) if(MSVC_IDE OR XCODE)
@@ -746,8 +728,10 @@ if(WITH_12BIT)
set(MD5_PPM_RGB_ISLOW f3301d2219783b8b3d942b7239fa50c0) set(MD5_PPM_RGB_ISLOW f3301d2219783b8b3d942b7239fa50c0)
set(MD5_JPEG_422_IFAST_OPT 7322e3bd2f127f7de4b40d4480ce60e4) set(MD5_JPEG_422_IFAST_OPT 7322e3bd2f127f7de4b40d4480ce60e4)
set(MD5_PPM_422_IFAST 79807fa552899e66a04708f533e16950) set(MD5_PPM_422_IFAST 79807fa552899e66a04708f533e16950)
set(MD5_JPEG_440_ISLOW e25c1912e38367be505a89c410c1c2d2)
set(MD5_PPM_440_ISLOW e7d2e26288870cfcb30f3114ad01e380)
set(MD5_PPM_422M_IFAST 07737bfe8a7c1c87aaa393a0098d16b0) set(MD5_PPM_422M_IFAST 07737bfe8a7c1c87aaa393a0098d16b0)
set(MD5_JPEG_420_IFAST_Q100_PROG 008ab68d6ddbba04a8f01deee4e0f9f8) set(MD5_JPEG_420_IFAST_Q100_PROG 9447cef4803d9b0f74bcf333cc710a29)
set(MD5_PPM_420_Q100_IFAST 1b3730122709f53d007255e8dfd3305e) set(MD5_PPM_420_Q100_IFAST 1b3730122709f53d007255e8dfd3305e)
set(MD5_PPM_420M_Q100_IFAST 980a1a3c5bf9510022869d30b7d26566) set(MD5_PPM_420M_Q100_IFAST 980a1a3c5bf9510022869d30b7d26566)
set(MD5_JPEG_GRAY_ISLOW 235c90707b16e2e069f37c888b2636d9) set(MD5_JPEG_GRAY_ISLOW 235c90707b16e2e069f37c888b2636d9)
@@ -782,9 +766,9 @@ if(WITH_12BIT)
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_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97) set(MD5_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97)
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 b1fd2e6de6a6db2b3f5447a0b774a117) set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 452a21656115a163029cfba5c04fa76a)
set(MD5_PPM_444_ISLOW_SKIP1_6 4bfeeafcbaeb2ec4b32a71cc72f64fbc) set(MD5_PPM_444_ISLOW_SKIP1_6 ef63901f71ef7a75cd78253fc0914f84)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 e6d8226f43bb30afe927e8b96646b147) set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 15b173fb5872d9575572fbcc1b05956f)
set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c) set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c)
else() else()
set(TESTORIG testorig.jpg) set(TESTORIG testorig.jpg)
@@ -795,10 +779,12 @@ else()
set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4) set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4)
set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8) set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8)
set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa) set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa)
set(MD5_JPEG_440_ISLOW 538bc02bd4b4658fd85de6ece6cbeda6)
set(MD5_PPM_440_ISLOW 11e7eab7ef7ef3276934bb7e7b6bb377)
set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d) set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d)
set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065) set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065)
set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1) set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1)
set(MD5_JPEG_420_IFAST_Q100_PROG e59bb462016a8d9a748c330a3474bb55) set(MD5_JPEG_420_IFAST_Q100_PROG 0ba15f9dab81a703505f835f9dbbac6d)
set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294) set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294)
set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1) set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1)
set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d) set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d)
@@ -824,29 +810,7 @@ else()
set(MD5_PPM_3x2_IFAST fd283664b3b49127984af0a7f118fccd) set(MD5_PPM_3x2_IFAST fd283664b3b49127984af0a7f118fccd)
set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1) set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1)
set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617) set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617)
# Since v1.5.1, libjpeg-turbo uses the separate non-fancy upsampling and set(MD5_PPM_420M_IFAST_ARI 57251da28a35b46eecb7177d82d10e0e)
# YCbCr -> RGB color conversion routines rather than merged upsampling/color
# conversion when fancy upsampling is disabled on platforms that have a SIMD
# implementation of YCbCr -> RGB color conversion but no SIMD implementation
# of merged upsampling/color conversion. This was intended to improve the
# performance of the Arm Neon SIMD extensions, the only SIMD extensions for
# which those circumstances currently apply. The separate non-fancy
# upsampling and color conversion routines usually produce bitwise-identical
# output to the merged upsampling/color conversion routines, but that is not
# the case when skipping scanlines starting at an odd-numbered scanline. In
# libjpeg-turbo 2.0.5 and prior, doing that while using merged h2v2
# upsampling caused a segfault, so this test validates the fix for that
# segfault. Unfortunately, however, the test also produces different bitwise
# output when using the Neon SIMD extensions, because of the aforementioned
# optimization. The easiest workaround is to use the old test from
# libjpeg-turbo 2.0.5 and prior when using the Neon SIMD extensions. The
# aforementioned segfault never would have occurred with the Neon SIMD
# extensions anyhow, since merged upsampling is disabled when using them.
if((CPU_TYPE STREQUAL "arm64" OR CPU_TYPE STREQUAL "arm") AND WITH_SIMD)
set(MD5_PPM_420M_IFAST_ARI 72b59a99bcf1de24c5b27d151bde2437)
else()
set(MD5_PPM_420M_IFAST_ARI 57251da28a35b46eecb7177d82d10e0e)
endif()
set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f) set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f)
set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9) set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9)
set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7) set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7)
@@ -867,10 +831,10 @@ else()
set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b) set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b)
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 f2c1179887f0ff6c5689ed881ea3f32c) set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 26eb36ccc7d1f0cb80cdabb0ac8b5d99)
set(MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4 886c6775af22370257122f8b16207e6d) set(MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4 886c6775af22370257122f8b16207e6d)
set(MD5_PPM_444_ISLOW_SKIP1_6 2f4d84e9832ce741f5f0666a84632a5a) set(MD5_PPM_444_ISLOW_SKIP1_6 5606f86874cf26b8fcee1117a0a436a6)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 d04ed9d1a2a059455b343bf07a2433a3) set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 db87dc7ce26bcdc7a6b56239ce2b9d6c)
set(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 cb57b32bd6d03e35432362f7bf184b6d) set(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 cb57b32bd6d03e35432362f7bf184b6d)
set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d) set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d)
endif() endif()
@@ -945,16 +909,14 @@ if(CPU_TYPE STREQUAL "x86_64" OR CPU_TYPE STREQUAL "i386")
set(DEFAULT_FLOATTEST sse) set(DEFAULT_FLOATTEST sse)
elseif(CPU_TYPE STREQUAL "x86_64") elseif(CPU_TYPE STREQUAL "x86_64")
set(DEFAULT_FLOATTEST no-fp-contract) set(DEFAULT_FLOATTEST no-fp-contract)
elseif(CPU_TYPE STREQUAL "i386" AND MSVC)
set(DEFAULT_FLOATTEST msvc)
# else we can't really set an intelligent default for i386. The appropriate # else we can't really set an intelligent default for i386. The appropriate
# value could be 387, no-fp-contract, or fp-contract, depending on the # value could be no-fp-contract, fp-contract, 387, or msvc, depending on the
# compiler and compiler options. We leave it to the user to set FLOATTEST # compiler and compiler options. We leave it to the user to set FLOATTEST
# manually. # manually.
endif() endif()
else() else()
if((CPU_TYPE STREQUAL "powerpc" OR CPU_TYPE STREQUAL "arm64") AND if((CPU_TYPE STREQUAL "powerpc" OR CPU_TYPE STREQUAL "arm64") AND
NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT MSVC)
set(DEFAULT_FLOATTEST fp-contract) set(DEFAULT_FLOATTEST fp-contract)
else() else()
set(DEFAULT_FLOATTEST no-fp-contract) set(DEFAULT_FLOATTEST no-fp-contract)
@@ -1002,22 +964,22 @@ foreach(libtype ${TEST_LIBTYPES})
add_test(tjunittest-${libtype}-bmp add_test(tjunittest-${libtype}-bmp
${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -bmp) ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -bmp)
set(MD5_PPM_GRAY_TILE b8f5defbd8e76a1d557b860b457bcd05) set(MD5_PPM_GRAY_TILE 89d3ca21213d9d864b50b4e4e7de4ca6)
set(MD5_PPM_420_8x8_TILE cb8bb3f7de153b4cfbf6cc6f36b43bf0) set(MD5_PPM_420_8x8_TILE 847fceab15c5b7b911cb986cf0f71de3)
set(MD5_PPM_420_16x16_TILE a144f52396cba331bb85c6b43d1deedc) set(MD5_PPM_420_16x16_TILE ca45552a93687e078f7137cc4126a7b0)
set(MD5_PPM_420_32x32_TILE 5d6a7c35bb44adc89581466b253ef920) set(MD5_PPM_420_32x32_TILE d8676f1d6b68df358353bba9844f4a00)
set(MD5_PPM_420_64x64_TILE 4e4c1a3d7ea4bace4f868bcbe83b7050) set(MD5_PPM_420_64x64_TILE 4e4c1a3d7ea4bace4f868bcbe83b7050)
set(MD5_PPM_420_128x128_TILE d8b12baac07d24d9705d712359ae2181) set(MD5_PPM_420_128x128_TILE f24c3429c52265832beab9df72a0ceae)
set(MD5_PPM_420M_8x8_TILE bc25320e1f4c31ce2e610e43e9fd173c) set(MD5_PPM_420M_8x8_TILE bc25320e1f4c31ce2e610e43e9fd173c)
set(MD5_PPM_420M_TILE 391df0063a66d7656f18f3a5cb107357) set(MD5_PPM_420M_TILE 75ffdf14602258c5c189522af57fa605)
set(MD5_PPM_422_8x8_TILE d83dacd9fc73b0a6f10c09acad64eb1e) set(MD5_PPM_422_8x8_TILE d83dacd9fc73b0a6f10c09acad64eb1e)
set(MD5_PPM_422_16x16_TILE 35077fb610d72dd743b1eb0cbcfe10fb) set(MD5_PPM_422_16x16_TILE 35077fb610d72dd743b1eb0cbcfe10fb)
set(MD5_PPM_422_32x32_TILE 06a45b730ffa26990af4930140c3233b) set(MD5_PPM_422_32x32_TILE e6902ed8a449ecc0f0d6f2bf945f65f7)
set(MD5_PPM_422_64x64_TILE 007d991538e571e6e56c54b6224b060a) set(MD5_PPM_422_64x64_TILE 2b4502a8f316cedbde1da7bce3d2231e)
set(MD5_PPM_422_128x128_TILE f0b5617d578f5e13c8eee215d64d4877) set(MD5_PPM_422_128x128_TILE f0b5617d578f5e13c8eee215d64d4877)
set(MD5_PPM_422M_8x8_TILE 828941d7f41cd6283abd6beffb7fd51d) set(MD5_PPM_422M_8x8_TILE 828941d7f41cd6283abd6beffb7fd51d)
set(MD5_PPM_422M_TILE df4b4c784feb513d250c2dd76d61fa1a) set(MD5_PPM_422M_TILE e877ae1324c4a280b95376f7f018172f)
set(MD5_PPM_444_TILE c757cfea44ac6439fea03ef57d04b7de) set(MD5_PPM_444_TILE 7964e41e67cfb8d0a587c0aa4798f9c3)
# Test compressing from/decompressing to an arbitrary subregion of a larger # Test compressing from/decompressing to an arbitrary subregion of a larger
# image buffer # image buffer
@@ -1030,6 +992,25 @@ foreach(libtype ${TEST_LIBTYPES})
set_tests_properties(tjbench-${libtype}-tile set_tests_properties(tjbench-${libtype}-tile
PROPERTIES DEPENDS tjbench-${libtype}-tile-cp) PROPERTIES DEPENDS tjbench-${libtype}-tile-cp)
foreach(tile 8 16 32 64 128)
add_test(tjbench-${libtype}-tile-gray-${tile}x${tile}-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_GRAY_TILE}
testout_tile_GRAY_Q95_${tile}x${tile}.ppm)
foreach(subsamp 420 422)
add_test(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP}
${MD5_PPM_${subsamp}_${tile}x${tile}_TILE}
testout_tile_${subsamp}_Q95_${tile}x${tile}.ppm)
endforeach()
add_test(tjbench-${libtype}-tile-444-${tile}x${tile}-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_444_TILE}
testout_tile_444_Q95_${tile}x${tile}.ppm)
foreach(subsamp gray 420 422 444)
set_tests_properties(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp
PROPERTIES DEPENDS tjbench-${libtype}-tile)
endforeach()
endforeach()
add_test(tjbench-${libtype}-tilem-cp add_test(tjbench-${libtype}-tilem-cp
${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm ${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm
testout_tilem.ppm) testout_tilem.ppm)
@@ -1038,6 +1019,27 @@ foreach(libtype ${TEST_LIBTYPES})
-rgb -fastupsample -quiet -tile -benchtime 0.01 -warmup 0) -rgb -fastupsample -quiet -tile -benchtime 0.01 -warmup 0)
set_tests_properties(tjbench-${libtype}-tilem set_tests_properties(tjbench-${libtype}-tilem
PROPERTIES DEPENDS tjbench-${libtype}-tilem-cp) PROPERTIES DEPENDS tjbench-${libtype}-tilem-cp)
add_test(tjbench-${libtype}-tile-420m-8x8-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_420M_8x8_TILE}
testout_tilem_420_Q95_8x8.ppm)
add_test(tjbench-${libtype}-tile-422m-8x8-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_422M_8x8_TILE}
testout_tilem_422_Q95_8x8.ppm)
foreach(tile 16 32 64 128)
foreach(subsamp 420 422)
add_test(tjbench-${libtype}-tile-${subsamp}m-${tile}x${tile}-cmp
${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP}
${MD5_PPM_${subsamp}M_TILE}
testout_tilem_${subsamp}_Q95_${tile}x${tile}.ppm)
endforeach()
endforeach()
foreach(tile 8 16 32 64 128)
foreach(subsamp 420 422)
set_tests_properties(tjbench-${libtype}-tile-${subsamp}m-${tile}x${tile}-cmp
PROPERTIES DEPENDS tjbench-${libtype}-tilem)
endforeach()
endforeach()
endif() endif()
# These tests are carefully crafted to provide full coverage of as many of # These tests are carefully crafted to provide full coverage of as many of
@@ -1060,7 +1062,7 @@ foreach(libtype ${TEST_LIBTYPES})
endmacro() endmacro()
# CC: null SAMP: fullsize FDCT: islow ENT: huff # CC: null SAMP: fullsize FDCT: islow ENT: huff
add_bittest(cjpeg rgb-islow "-revert;-rgb;-dct;int;-icc;${TESTIMAGES}/test1.icc" add_bittest(cjpeg rgb-islow "-rgb;-dct;int;-icc;${TESTIMAGES}/test1.icc"
testout_rgb_islow.jpg ${TESTIMAGES}/testorig.ppm testout_rgb_islow.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_RGB_ISLOW}) ${MD5_JPEG_RGB_ISLOW})
@@ -1075,7 +1077,7 @@ foreach(libtype ${TEST_LIBTYPES})
set_tests_properties(djpeg-${libtype}-rgb-islow-icc-cmp PROPERTIES set_tests_properties(djpeg-${libtype}-rgb-islow-icc-cmp PROPERTIES
DEPENDS djpeg-${libtype}-rgb-islow) DEPENDS djpeg-${libtype}-rgb-islow)
add_bittest(jpegtran icc "-revert;-copy;all;-icc;${TESTIMAGES}/test2.icc" add_bittest(jpegtran icc "-copy;all;-icc;${TESTIMAGES}/test2.icc"
testout_rgb_islow2.jpg testout_rgb_islow.jpg testout_rgb_islow2.jpg testout_rgb_islow.jpg
${MD5_JPEG_RGB_ISLOW2} cjpeg-${libtype}-rgb-islow) ${MD5_JPEG_RGB_ISLOW2} cjpeg-${libtype}-rgb-islow)
@@ -1092,7 +1094,7 @@ foreach(libtype ${TEST_LIBTYPES})
endif() endif()
# CC: RGB->YCC SAMP: fullsize/h2v1 FDCT: ifast ENT: 2-pass huff # CC: RGB->YCC SAMP: fullsize/h2v1 FDCT: ifast ENT: 2-pass huff
add_bittest(cjpeg 422-ifast-opt "-revert;-sample;2x1;-dct;fast;-opt" add_bittest(cjpeg 422-ifast-opt "-sample;2x1;-dct;fast;-opt"
testout_422_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm testout_422_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_422_IFAST_OPT}) ${MD5_JPEG_422_IFAST_OPT})
@@ -1101,6 +1103,16 @@ foreach(libtype ${TEST_LIBTYPES})
testout_422_ifast.ppm testout_422_ifast_opt.jpg testout_422_ifast.ppm testout_422_ifast_opt.jpg
${MD5_PPM_422_IFAST} cjpeg-${libtype}-422-ifast-opt) ${MD5_PPM_422_IFAST} cjpeg-${libtype}-422-ifast-opt)
# CC: RGB->YCC SAMP: fullsize/h1v2 FDCT: islow ENT: huff
add_bittest(cjpeg 440-islow "-sample;1x2;-dct;int"
testout_440_islow.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_440_ISLOW})
# CC: YCC->RGB SAMP: fullsize/h1v2 fancy IDCT: islow ENT: huff
add_bittest(djpeg 440-islow "-dct;int"
testout_440_islow.ppm testout_440_islow.jpg
${MD5_PPM_440_ISLOW} cjpeg-${libtype}-440-islow)
# CC: YCC->RGB SAMP: h2v1 merged IDCT: ifast ENT: huff # CC: YCC->RGB SAMP: h2v1 merged IDCT: ifast ENT: huff
add_bittest(djpeg 422m-ifast "-dct;fast;-nosmooth" add_bittest(djpeg 422m-ifast "-dct;fast;-nosmooth"
testout_422m_ifast.ppm testout_422_ifast_opt.jpg testout_422m_ifast.ppm testout_422_ifast_opt.jpg
@@ -1121,7 +1133,7 @@ foreach(libtype ${TEST_LIBTYPES})
# CC: RGB->YCC SAMP: fullsize/h2v2 FDCT: ifast ENT: prog huff # CC: RGB->YCC SAMP: fullsize/h2v2 FDCT: ifast ENT: prog huff
add_bittest(cjpeg 420-q100-ifast-prog add_bittest(cjpeg 420-q100-ifast-prog
"-revert;-sample;2x2;-quality;100;-dct;fast;-scans;${TESTIMAGES}/test.scan" "-sample;2x2;-quality;100;-dct;fast;-scans;${TESTIMAGES}/test.scan"
testout_420_q100_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm testout_420_q100_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_420_IFAST_Q100_PROG}) ${MD5_JPEG_420_IFAST_Q100_PROG})
@@ -1136,7 +1148,7 @@ foreach(libtype ${TEST_LIBTYPES})
${MD5_PPM_420M_Q100_IFAST} cjpeg-${libtype}-420-q100-ifast-prog) ${MD5_PPM_420M_Q100_IFAST} cjpeg-${libtype}-420-q100-ifast-prog)
# CC: RGB->Gray SAMP: fullsize FDCT: islow ENT: huff # CC: RGB->Gray SAMP: fullsize FDCT: islow ENT: huff
add_bittest(cjpeg gray-islow "-revert;-gray;-dct;int" add_bittest(cjpeg gray-islow "-gray;-dct;int"
testout_gray_islow.jpg ${TESTIMAGES}/testorig.ppm testout_gray_islow.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_GRAY_ISLOW}) ${MD5_JPEG_GRAY_ISLOW})
@@ -1164,13 +1176,13 @@ foreach(libtype ${TEST_LIBTYPES})
# CC: RGB->YCC SAMP: fullsize smooth/h2v2 smooth FDCT: islow # CC: RGB->YCC SAMP: fullsize smooth/h2v2 smooth FDCT: islow
# ENT: 2-pass huff # ENT: 2-pass huff
add_bittest(cjpeg 420s-ifast-opt "-revert;-sample;2x2;-smooth;1;-dct;int;-opt" add_bittest(cjpeg 420s-ifast-opt "-sample;2x2;-smooth;1;-dct;int;-opt"
testout_420s_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm testout_420s_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_420S_IFAST_OPT}) ${MD5_JPEG_420S_IFAST_OPT})
if(FLOATTEST) if(FLOATTEST)
# CC: RGB->YCC SAMP: fullsize/int FDCT: float ENT: prog huff # CC: RGB->YCC SAMP: fullsize/int FDCT: float ENT: prog huff
add_bittest(cjpeg 3x2-float-prog "-revert;-sample;3x2;-dct;float;-prog" add_bittest(cjpeg 3x2-float-prog "-sample;3x2;-dct;float;-prog"
testout_3x2_float_prog.jpg ${TESTIMAGES}/testorig.ppm testout_3x2_float_prog.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_3x2_FLOAT_PROG_${FLOATTEST_UC}}) ${MD5_JPEG_3x2_FLOAT_PROG_${FLOATTEST_UC}})
@@ -1181,7 +1193,7 @@ foreach(libtype ${TEST_LIBTYPES})
endif() endif()
# CC: RGB->YCC SAMP: fullsize/int FDCT: ifast ENT: prog huff # CC: RGB->YCC SAMP: fullsize/int FDCT: ifast ENT: prog huff
add_bittest(cjpeg 3x2-ifast-prog "-revert;-sample;3x2;-dct;fast;-prog" add_bittest(cjpeg 3x2-ifast-prog "-sample;3x2;-dct;fast;-prog"
testout_3x2_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm testout_3x2_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_3x2_IFAST_PROG}) ${MD5_JPEG_3x2_IFAST_PROG})
@@ -1192,36 +1204,28 @@ foreach(libtype ${TEST_LIBTYPES})
if(WITH_ARITH_ENC) if(WITH_ARITH_ENC)
# CC: YCC->RGB SAMP: fullsize/h2v2 FDCT: islow ENT: arith # CC: YCC->RGB SAMP: fullsize/h2v2 FDCT: islow ENT: arith
add_bittest(cjpeg 420-islow-ari "-revert;-dct;int;-arithmetic" add_bittest(cjpeg 420-islow-ari "-dct;int;-arithmetic"
testout_420_islow_ari.jpg ${TESTIMAGES}/testorig.ppm testout_420_islow_ari.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_420_ISLOW_ARI}) ${MD5_JPEG_420_ISLOW_ARI})
add_bittest(jpegtran 420-islow-ari "--revert;arithmetic" add_bittest(jpegtran 420-islow-ari "-arithmetic"
testout_420_islow_ari2.jpg ${TESTIMAGES}/testimgint.jpg testout_420_islow_ari2.jpg ${TESTIMAGES}/testimgint.jpg
${MD5_JPEG_420_ISLOW_ARI}) ${MD5_JPEG_420_ISLOW_ARI})
# CC: YCC->RGB SAMP: fullsize FDCT: islow ENT: prog arith # CC: YCC->RGB SAMP: fullsize FDCT: islow ENT: prog arith
add_bittest(cjpeg 444-islow-progari add_bittest(cjpeg 444-islow-progari
"-revert;-sample;1x1;-dct;int;-prog;-arithmetic" "-sample;1x1;-dct;int;-prog;-arithmetic"
testout_444_islow_progari.jpg ${TESTIMAGES}/testorig.ppm testout_444_islow_progari.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_444_ISLOW_PROGARI}) ${MD5_JPEG_444_ISLOW_PROGARI})
endif() endif()
if(WITH_ARITH_DEC) if(WITH_ARITH_DEC)
# CC: RGB->YCC SAMP: h2v2 merged IDCT: ifast ENT: arith # CC: RGB->YCC SAMP: h2v2 merged IDCT: ifast ENT: arith
if((CPU_TYPE STREQUAL "arm64" OR CPU_TYPE STREQUAL "arm") AND WITH_SIMD) add_bittest(djpeg 420m-ifast-ari "-fast;-skip;1,20;-ppm"
# Refer to the comment above the definition of MD5_PPM_420M_IFAST_ARI for
# an explanation of why this is necessary.
add_bittest(djpeg 420m-ifast-ari "-fast;-ppm"
testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg
${MD5_PPM_420M_IFAST_ARI}) ${MD5_PPM_420M_IFAST_ARI})
else()
add_bittest(djpeg 420m-ifast-ari "-fast;-skip;1,20;-ppm"
testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg
${MD5_PPM_420M_IFAST_ARI})
endif()
add_bittest(jpegtran 420-islow "-revert" add_bittest(jpegtran 420-islow ""
testout_420_islow.jpg ${TESTIMAGES}/testimgari.jpg testout_420_islow.jpg ${TESTIMAGES}/testimgari.jpg
${MD5_JPEG_420_ISLOW}) ${MD5_JPEG_420_ISLOW})
endif() endif()
@@ -1344,7 +1348,7 @@ foreach(libtype ${TEST_LIBTYPES})
endif() endif()
endif() endif()
add_bittest(jpegtran crop "-revert;-crop;120x90+20+50;-transpose;-perfect" add_bittest(jpegtran crop "-crop;120x90+20+50;-transpose;-perfect"
testout_crop.jpg ${TESTIMAGES}/${TESTORIG} testout_crop.jpg ${TESTIMAGES}/${TESTORIG}
${MD5_JPEG_CROP}) ${MD5_JPEG_CROP})
@@ -1425,10 +1429,13 @@ set(EXE ${CMAKE_EXECUTABLE_SUFFIX})
if(WITH_TURBOJPEG) if(WITH_TURBOJPEG)
if(ENABLE_SHARED) if(ENABLE_SHARED)
install(TARGETS turbojpeg tjbench install(TARGETS turbojpeg EXPORT ${CMAKE_PROJECT_NAME}Targets
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS tjbench
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(NOT CMAKE_VERSION VERSION_LESS "3.1" AND MSVC AND if(NOT CMAKE_VERSION VERSION_LESS "3.1" AND MSVC AND
CMAKE_C_LINKER_SUPPORTS_PDB) CMAKE_C_LINKER_SUPPORTS_PDB)
install(FILES "$<TARGET_PDB_FILE:turbojpeg>" install(FILES "$<TARGET_PDB_FILE:turbojpeg>"
@@ -1436,8 +1443,9 @@ if(WITH_TURBOJPEG)
endif() endif()
endif() endif()
if(ENABLE_STATIC) if(ENABLE_STATIC)
install(TARGETS turbojpeg-static ARCHIVE install(TARGETS turbojpeg-static EXPORT ${CMAKE_PROJECT_NAME}Targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT ENABLE_SHARED) if(NOT ENABLE_SHARED)
if(MSVC_IDE OR XCODE) if(MSVC_IDE OR XCODE)
set(DIR "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}") set(DIR "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
@@ -1453,7 +1461,9 @@ if(WITH_TURBOJPEG)
endif() endif()
if(ENABLE_STATIC) if(ENABLE_STATIC)
install(TARGETS jpeg-static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS jpeg-static EXPORT ${CMAKE_PROJECT_NAME}Targets
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT ENABLE_SHARED) if(NOT ENABLE_SHARED)
if(MSVC_IDE OR XCODE) if(MSVC_IDE OR XCODE)
set(DIR "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}") set(DIR "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
@@ -1491,8 +1501,18 @@ if(UNIX OR MINGW)
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif() endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libjpeg.pc install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libjpeg.pc
${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
if(WITH_TURBOJPEG)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/${CMAKE_PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME})
install(EXPORT ${CMAKE_PROJECT_NAME}Targets
NAMESPACE ${CMAKE_PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jconfig.h install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jconfig.h
${CMAKE_CURRENT_SOURCE_DIR}/jerror.h ${CMAKE_CURRENT_SOURCE_DIR}/jmorecfg.h ${CMAKE_CURRENT_SOURCE_DIR}/jerror.h ${CMAKE_CURRENT_SOURCE_DIR}/jmorecfg.h

View File

@@ -1,15 +0,0 @@
# Community Participation Guidelines
This repository is governed by Mozilla's code of conduct and etiquette guidelines.
For more details, please read the
[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/).
## How to Report
For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.
<!--
## Project Specific Etiquette
In some cases, there will be additional project etiquette i.e.: (https://bugzilla.mozilla.org/page.cgi?id=etiquette.html).
Please update for your project.
-->

View File

@@ -1,3 +1,319 @@
2.1.4
=====
### Significant changes relative to 2.1.3
1. Fixed a regression introduced in 2.1.3 that caused build failures with
Visual Studio 2010.
2. The `tjDecompressHeader3()` function in the TurboJPEG C API and the
`TJDecompressor.setSourceImage()` method in the TurboJPEG Java API now accept
"abbreviated table specification" (AKA "tables-only") datastreams, which can be
used to prime the decompressor with quantization and Huffman tables that can be
used when decompressing subsequent "abbreviated image" datastreams.
3. libjpeg-turbo now performs run-time detection of AltiVec instructions on
OS X/PowerPC systems if AltiVec instructions are not enabled at compile time.
This allows both AltiVec-equipped (PowerPC G4 and G5) and non-AltiVec-equipped
(PowerPC G3) CPUs to be supported using the same build of libjpeg-turbo.
4. Fixed an error ("Bogus virtual array access") that occurred when attempting
to decompress a progressive JPEG image with a height less than or equal to one
iMCU (8 * the vertical sampling factor) using buffered-image mode with
interblock smoothing enabled. This was a regression introduced by
2.1 beta1[6(b)].
5. Fixed two issues that prevented partial image decompression from working
properly with buffered-image mode:
- Attempting to call `jpeg_crop_scanline()` after
`jpeg_start_decompress()` but before `jpeg_start_output()` resulted in an error
("Improper call to JPEG library in state 207".)
- Attempting to use `jpeg_skip_scanlines()` resulted in an error ("Bogus
virtual array access") under certain circumstances.
2.1.3
=====
### Significant changes relative to 2.1.2
1. Fixed a regression introduced by 2.0 beta1[7] whereby cjpeg compressed PGM
input files into full-color JPEG images unless the `-grayscale` option was
used.
2. cjpeg now automatically compresses GIF and 8-bit BMP input files into
grayscale JPEG images if the input files contain only shades of gray.
3. The build system now enables the intrinsics implementation of the AArch64
(Arm 64-bit) Neon SIMD extensions by default when using GCC 12 or later.
4. Fixed a segfault that occurred while decompressing a 4:2:0 JPEG image using
the merged (non-fancy) upsampling algorithms (that is, with
`cinfo.do_fancy_upsampling` set to `FALSE`) along with `jpeg_crop_scanline()`.
Specifically, the segfault occurred if the number of bytes remaining in the
output buffer was less than the number of bytes required to represent one
uncropped scanline of the output image. For that reason, the issue could only
be reproduced using the libjpeg API, not using djpeg.
2.1.2
=====
### Significant changes relative to 2.1.1
1. Fixed a regression introduced by 2.1 beta1[13] that caused the remaining
GAS implementations of AArch64 (Arm 64-bit) Neon SIMD functions (which are used
by default with GCC for performance reasons) to be placed in the `.rodata`
section rather than in the `.text` section. This caused the GNU linker to
automatically place the `.rodata` section in an executable segment, which
prevented libjpeg-turbo from working properly with other linkers and also
represented a potential security risk.
2. Fixed an issue whereby the `tjTransform()` function incorrectly computed the
MCU block size for 4:4:4 JPEG images with non-unary sampling factors and thus
unduly rejected some cropping regions, even though those regions aligned with
8x8 MCU block boundaries.
3. Fixed a regression introduced by 2.1 beta1[13] that caused the build system
to enable the Arm Neon SIMD extensions when targetting Armv6 and other legacy
architectures that do not support Neon instructions.
4. libjpeg-turbo now performs run-time detection of AltiVec instructions on
FreeBSD/PowerPC systems if AltiVec instructions are not enabled at compile
time. This allows both AltiVec-equipped and non-AltiVec-equipped CPUs to be
supported using the same build of libjpeg-turbo.
5. cjpeg now accepts a `-strict` argument similar to that of djpeg and
jpegtran, which causes the compressor to abort if an LZW-compressed GIF input
image contains incomplete or corrupt image data.
2.1.1
=====
### Significant changes relative to 2.1.0
1. Fixed a regression introduced in 2.1.0 that caused build failures with
non-GCC-compatible compilers for Un*x/Arm platforms.
2. Fixed a regression introduced by 2.1 beta1[13] that prevented the Arm 32-bit
(AArch32) Neon SIMD extensions from building unless the C compiler flags
included `-mfloat-abi=softfp` or `-mfloat-abi=hard`.
3. Fixed an issue in the AArch32 Neon SIMD Huffman encoder whereby reliance on
undefined C compiler behavior led to crashes ("SIGBUS: illegal alignment") on
Android systems when running AArch32/Thumb builds of libjpeg-turbo built with
recent versions of Clang.
4. Added a command-line argument (`-copy icc`) to jpegtran that causes it to
copy only the ICC profile markers from the source file and discard any other
metadata.
5. libjpeg-turbo should now build and run on CHERI-enabled architectures, which
use capability pointers that are larger than the size of `size_t`.
6. Fixed a regression (CVE-2021-37972) introduced by 2.1 beta1[5] that caused a
segfault in the 64-bit SSE2 Huffman encoder when attempting to losslessly
transform a specially-crafted malformed JPEG image.
2.1.0
=====
### Significant changes relative to 2.1 beta1
1. Fixed a regression introduced by 2.1 beta1[6(b)] whereby attempting to
decompress certain progressive JPEG images with one or more component planes of
width 8 or less caused a buffer overrun.
2. Fixed a regression introduced by 2.1 beta1[6(b)] whereby attempting to
decompress a specially-crafted malformed progressive JPEG image caused the
block smoothing algorithm to read from uninitialized memory.
3. Fixed an issue in the Arm Neon SIMD Huffman encoders that caused the
encoders to generate incorrect results when using the Clang compiler with
Visual Studio.
4. Fixed a floating point exception (CVE-2021-20205) that occurred when
attempting to compress a specially-crafted malformed GIF image with a specified
image width of 0 using cjpeg.
5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to
generate a progressive JPEG image on an SSE2-capable CPU using a scan script
containing one or more scans with lengths divisible by 32 and non-zero
successive approximation low bit positions would, under certain circumstances,
result in an error ("Missing Huffman code table entry") and an invalid JPEG
image.
6. Introduced a new flag (`TJFLAG_LIMITSCANS` in the TurboJPEG C API and
`TJ.FLAG_LIMIT_SCANS` in the TurboJPEG Java API) and a corresponding TJBench
command-line argument (`-limitscans`) that causes the TurboJPEG decompression
and transform functions/operations to return/throw an error if a progressive
JPEG image contains an unreasonably large number of scans. This allows
applications that use the TurboJPEG API to guard against an exploit of the
progressive JPEG format described in the report
["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf).
7. The PPM reader now throws an error, rather than segfaulting (due to a buffer
overrun) or generating incorrect pixels, if an application attempts to use the
`tjLoadImage()` function to load a 16-bit binary PPM file (a binary PPM file
with a maximum value greater than 255) into a grayscale image buffer or to load
a 16-bit binary PGM file into an RGB image buffer.
8. Fixed an issue in the PPM reader that caused incorrect pixels to be
generated when using the `tjLoadImage()` function to load a 16-bit binary PPM
file into an extended RGB image buffer.
9. Fixed an issue whereby, if a JPEG buffer was automatically re-allocated by
one of the TurboJPEG compression or transform functions and an error
subsequently occurred during compression or transformation, the JPEG buffer
pointer passed by the application was not updated when the function returned.
2.0.90 (2.1 beta1)
==================
### Significant changes relative to 2.0.6:
1. The build system, x86-64 SIMD extensions, and accelerated Huffman codec now
support the x32 ABI on Linux, which allows for using x86-64 instructions with
32-bit pointers. The x32 ABI is generally enabled by adding `-mx32` to the
compiler flags.
Caveats:
- CMake 3.9.0 or later is required in order for the build system to
automatically detect an x32 build.
- Java does not support the x32 ABI, and thus the TurboJPEG Java API will
automatically be disabled with x32 builds.
2. Added Loongson MMI SIMD implementations of the RGB-to-grayscale, 4:2:2 fancy
chroma upsampling, 4:2:2 and 4:2:0 merged chroma upsampling/color conversion,
and fast integer DCT/IDCT algorithms. Relative to libjpeg-turbo 2.0.x, this
speeds up:
- the compression of RGB source images into grayscale JPEG images by
approximately 20%
- the decompression of 4:2:2 JPEG images by approximately 40-60% when
using fancy upsampling
- the decompression of 4:2:2 and 4:2:0 JPEG images by approximately
15-20% when using merged upsampling
- the compression of RGB source images by approximately 30-45% when using
the fast integer DCT
- the decompression of JPEG images into RGB destination images by
approximately 2x when using the fast integer IDCT
The overall decompression speedup for RGB images is now approximately
2.3-3.7x (compared to 2-3.5x with libjpeg-turbo 2.0.x.)
3. 32-bit (Armv7 or Armv7s) iOS builds of libjpeg-turbo are no longer
supported, and the libjpeg-turbo build system can no longer be used to package
such builds. 32-bit iOS apps cannot run in iOS 11 and later, and the App Store
no longer allows them.
4. 32-bit (i386) OS X/macOS builds of libjpeg-turbo are no longer supported,
and the libjpeg-turbo build system can no longer be used to package such
builds. 32-bit Mac applications cannot run in macOS 10.15 "Catalina" and
later, and the App Store no longer allows them.
5. The SSE2 (x86 SIMD) and C Huffman encoding algorithms have been
significantly optimized, resulting in a measured average overall compression
speedup of 12-28% for 64-bit code and 22-52% for 32-bit code on various Intel
and AMD CPUs, as well as a measured average overall compression speedup of
0-23% on platforms that do not have a SIMD-accelerated Huffman encoding
implementation.
6. The block smoothing algorithm that is applied by default when decompressing
progressive Huffman-encoded JPEG images has been improved in the following
ways:
- The algorithm is now more fault-tolerant. Previously, if a particular
scan was incomplete, then the smoothing parameters for the incomplete scan
would be applied to the entire output image, including the parts of the image
that were generated by the prior (complete) scan. Visually, this had the
effect of removing block smoothing from lower-frequency scans if they were
followed by an incomplete higher-frequency scan. libjpeg-turbo now applies
block smoothing parameters to each iMCU row based on which scan generated the
pixels in that row, rather than always using the block smoothing parameters for
the most recent scan.
- When applying block smoothing to DC scans, a Gaussian-like kernel with a
5x5 window is used to reduce the "blocky" appearance.
7. Added SIMD acceleration for progressive Huffman encoding on Arm platforms.
This speeds up the compression of full-color progressive JPEGs by about 30-40%
on average (relative to libjpeg-turbo 2.0.x) when using modern Arm CPUs.
8. Added configure-time and run-time auto-detection of Loongson MMI SIMD
instructions, so that the Loongson MMI SIMD extensions can be included in any
MIPS64 libjpeg-turbo build.
9. Added fault tolerance features to djpeg and jpegtran, mainly to demonstrate
methods by which applications can guard against the exploits of the JPEG format
described in the report
["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf).
- Both programs now accept a `-maxscans` argument, which can be used to
limit the number of allowable scans in the input file.
- Both programs now accept a `-strict` argument, which can be used to
treat all warnings as fatal.
10. CMake package config files are now included for both the libjpeg and
TurboJPEG API libraries. This facilitates using libjpeg-turbo with CMake's
`find_package()` function. For example:
find_package(libjpeg-turbo CONFIG REQUIRED)
add_executable(libjpeg_program libjpeg_program.c)
target_link_libraries(libjpeg_program PUBLIC libjpeg-turbo::jpeg)
add_executable(libjpeg_program_static libjpeg_program.c)
target_link_libraries(libjpeg_program_static PUBLIC
libjpeg-turbo::jpeg-static)
add_executable(turbojpeg_program turbojpeg_program.c)
target_link_libraries(turbojpeg_program PUBLIC
libjpeg-turbo::turbojpeg)
add_executable(turbojpeg_program_static turbojpeg_program.c)
target_link_libraries(turbojpeg_program_static PUBLIC
libjpeg-turbo::turbojpeg-static)
11. Since the Unisys LZW patent has long expired, cjpeg and djpeg can now
read/write both LZW-compressed and uncompressed GIF files (feature ported from
jpeg-6a and jpeg-9d.)
12. jpegtran now includes the `-wipe` and `-drop` options from jpeg-9a and
jpeg-9d, as well as the ability to expand the image size using the `-crop`
option. Refer to jpegtran.1 or usage.txt for more details.
13. Added a complete intrinsics implementation of the Arm Neon SIMD extensions,
thus providing SIMD acceleration on Arm platforms for all of the algorithms
that are SIMD-accelerated on x86 platforms. This new implementation is
significantly faster in some cases than the old GAS implementation--
depending on the algorithms used, the type of CPU core, and the compiler. GCC,
as of this writing, does not provide a full or optimal set of Neon intrinsics,
so for performance reasons, the default when building libjpeg-turbo with GCC is
to continue using the GAS implementation of the following algorithms:
- 32-bit RGB-to-YCbCr color conversion
- 32-bit fast and accurate inverse DCT
- 64-bit RGB-to-YCbCr and YCbCr-to-RGB color conversion
- 64-bit accurate forward and inverse DCT
- 64-bit Huffman encoding
A new CMake variable (`NEON_INTRINSICS`) can be used to override this
default.
Since the new intrinsics implementation includes SIMD acceleration
for merged upsampling/color conversion, 1.5.1[5] is no longer necessary and has
been reverted.
14. The Arm Neon SIMD extensions can now be built using Visual Studio.
15. The build system can now be used to generate a universal x86-64 + Armv8
libjpeg-turbo SDK package for both iOS and macOS.
2.0.6 2.0.6
===== =====
@@ -88,15 +404,15 @@ JPEG images. This was known to cause a buffer overflow when attempting to
decompress some such images using `tjDecompressToYUV2()` or decompress some such images using `tjDecompressToYUV2()` or
`tjDecompressToYUVPlanes()`. `tjDecompressToYUVPlanes()`.
5. Fixed an issue, detected by ASan, whereby attempting to losslessly transform 5. Fixed an issue (CVE-2020-17541), detected by ASan, whereby attempting to
a specially-crafted malformed JPEG image containing an extremely-high-frequency losslessly transform a specially-crafted malformed JPEG image containing an
coefficient block (junk image data that could never be generated by a extremely-high-frequency coefficient block (junk image data that could never be
legitimate JPEG compressor) could cause the Huffman encoder's local buffer to generated by a legitimate JPEG compressor) could cause the Huffman encoder's
be overrun. (Refer to 1.4.0[9] and 1.4beta1[15].) Given that the buffer local buffer to be overrun. (Refer to 1.4.0[9] and 1.4beta1[15].) Given that
overrun was fully contained within the stack and did not cause a segfault or the buffer overrun was fully contained within the stack and did not cause a
other user-visible errant behavior, and given that the lossless transformer segfault or other user-visible errant behavior, and given that the lossless
(unlike the decompressor) is not generally exposed to arbitrary data exploits, transformer (unlike the decompressor) is not generally exposed to arbitrary
this issue did not likely pose a security risk. data exploits, this issue did not likely pose a security risk.
6. The Arm 64-bit (Armv8) Neon SIMD assembly code now stores constants in a 6. The Arm 64-bit (Armv8) Neon SIMD assembly code now stores constants in a
separate read-only data section rather than in the text section, to support separate read-only data section rather than in the text section, to support
@@ -384,7 +700,7 @@ algorithm that caused incorrect dithering in the output image. This algorithm
now produces bitwise-identical results to the unmerged algorithms. now produces bitwise-identical results to the unmerged algorithms.
12. The SIMD function symbols for x86[-64]/ELF, MIPS/ELF, macOS/x86[-64] (if 12. The SIMD function symbols for x86[-64]/ELF, MIPS/ELF, macOS/x86[-64] (if
libjpeg-turbo is built with YASM), and iOS/Arm[64] builds are now private. libjpeg-turbo is built with Yasm), and iOS/Arm[64] builds are now private.
This prevents those symbols from being exposed in applications or shared This prevents those symbols from being exposed in applications or shared
libraries that link statically with libjpeg-turbo. libraries that link statically with libjpeg-turbo.
@@ -1269,8 +1585,8 @@ either the fast or the accurate DCT/IDCT algorithms in the underlying codec.
### Significant changes relative to 1.2 beta1: ### Significant changes relative to 1.2 beta1:
1. Fixed build issue with YASM on Unix systems (the libjpeg-turbo build system 1. Fixed build issue with Yasm on Unix systems (the libjpeg-turbo build system
was not adding the current directory to the assembler include path, so YASM was not adding the current directory to the assembler include path, so Yasm
was not able to find jsimdcfg.inc.) was not able to find jsimdcfg.inc.)
2. Fixed out-of-bounds read in SSE2 SIMD code that occurred when decompressing 2. Fixed out-of-bounds read in SSE2 SIMD code that occurred when decompressing
@@ -1338,7 +1654,7 @@ transposed or rotated 90 degrees.
8. All legacy VirtualGL code has been re-factored, and this has allowed 8. All legacy VirtualGL code has been re-factored, and this has allowed
libjpeg-turbo, in its entirety, to be re-licensed under a BSD-style license. libjpeg-turbo, in its entirety, to be re-licensed under a BSD-style license.
9. libjpeg-turbo can now be built with YASM. 9. libjpeg-turbo can now be built with Yasm.
10. Added SIMD acceleration for ARM Linux and iOS platforms that support 10. Added SIMD acceleration for ARM Linux and iOS platforms that support
NEON instructions. NEON instructions.

View File

@@ -91,7 +91,7 @@ best of our understanding.
The Modified (3-clause) BSD License The Modified (3-clause) BSD License
=================================== ===================================
Copyright (C)2009-2020 D. R. Commander. All Rights Reserved. Copyright (C)2009-2022 D. R. Commander. All Rights Reserved.<br>
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. Copyright (C)2015 Viktor Szathmáry. 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

View File

@@ -1,194 +0,0 @@
Mozilla JPEG Encoder Project
============================
mozjpeg is a fork of libjpeg-turbo that aims to speed up load times of web
pages by reducing the size (and, by extension, the transmission time) of JPEG
files. It accomplishes this by enabling optimized Huffman trees and
progressive entropy coding by default in the JPEG compressor, as well as
splitting the spectrum of DCT coefficients into separate scans and using
Trellis quantisation.
Although it is based on libjpeg-turbo, mozjpeg is not intended to be a
general-purpose or high-performance JPEG library. Its performance is highly
"asymmetric". That is, the JPEG files it generates require much more time to
compress than to decompress. When the default settings are used, mozjpeg is
considerably slower than libjpeg-turbo or even libjpeg at compressing images.
Thus, it is not generally suitable for real-time compression. It is best used
as part of a web encoding workflow.
libjpeg API Extensibility Framework
===================================
mozjpeg's implementation of the libjpeg API includes an extensibility framework
that allows new features to be added without modifying the transparent libjpeg
compress/decompress structures (which would break backward ABI compatibility.)
Extension parameters are placed into the opaque jpeg_comp_master structure, and
a set of accessor functions and globally unique tokens allows for
getting/setting those parameters without directly accessing the structure.
Currently, only the accessor functions necessary to support the mozjpeg
extensions are implemented, but the framework can be easily extended in the
future to accommodate additional simple parameter types, complex or
multi-valued parameters, or decompressor extensions.
The currently-implemented accessor functions are as follows:
boolean jpeg_c_bool_param_supported (j_compress_ptr cinfo,
J_BOOLEAN_PARAM param)
Returns TRUE if the given boolean extension parameter is supported by
this implementation of the libjpeg API, or FALSE otherwise.
void jpeg_c_set_bool_param (j_compress_ptr cinfo,
J_BOOLEAN_PARAM param, boolean value);
Set the given boolean extension parameter to the given value (TRUE or
FALSE.)
boolean jpeg_c_get_bool_param (j_compress_ptr cinfo, J_BOOLEAN_PARAM param)
Get the value of the given boolean extension parameter (TRUE or FALSE.)
boolean jpeg_c_float_param_supported (j_compress_ptr cinfo,
J_FLOAT_PARAM param)
Returns TRUE if the given floating point extension parameter is
supported by this implementation of the libjpeg API, or FALSE
otherwise.
void jpeg_c_set_float_param (j_compress_ptr cinfo, J_FLOAT_PARAM param,
float value)
Set the given floating point extension parameter to the given value.
float jpeg_c_get_float_param (j_compress_ptr cinfo, J_FLOAT_PARAM param);
Get the value of the given floating point extension parameter.
boolean jpeg_c_int_param_supported (j_compress_ptr cinfo,
J_INT_PARAM param)
Returns TRUE if the given integer extension parameter is supported by
this implementation of the libjpeg API, or FALSE otherwise.
void jpeg_c_set_int_param (j_compress_ptr cinfo, J_INT_PARAM param,
int value)
Set the given integer extension parameter to the given value.
int jpeg_c_get_int_param (j_compress_ptr cinfo, J_INT_PARAM param)
Get the value of the given integer extension parameter.
Boolean Extension Parameters Supported by mozjpeg
-------------------------------------------------
* JBOOLEAN_OPTIMIZE_SCANS (default: TRUE)
Specifies whether scan parameters should be optimized. Parameter
optimization is done as in jpgcrush. jpeg_simple_progression() should be called
after setting JBOOLEAN_OPTIMIZE_SCANS.
When disabling JBOOLEAN_OPTIMIZE_SCANS, cinfo.scan_info should additionally be
set to NULL to disable use of the progressive coding mode, if so desired.
* JBOOLEAN_TRELLIS_QUANT (default: TRUE)
Specifies whether to apply trellis quantization. For each 8x8 block, trellis
quantization determines the best tradeoff between rate and distortion.
* JBOOLEAN_TRELLIS_QUANT_DC (default: TRUE)
Specifies whether to apply trellis quantization to DC coefficients.
* JBOOLEAN_TRELLIS_EOB_OPT (default: FALSE)
Specifies whether to optimize runs of zero blocks in trellis quantization.
This is applicable only when JBOOLEAN_USE_SCANS_IN_TRELLIS is enabled.
* JBOOLEAN_USE_LAMBDA_WEIGHT_TBL currently has no effect.
* JBOOLEAN_USE_SCANS_IN_TRELLIS (default: FALSE)
Specifies whether multiple scans should be considered during trellis
quantization.
* JBOOLEAN_TRELLIS_Q_OPT (default: FALSE)
Specifies whether to optimize the quantization table after trellis
quantization. If enabled, then a revised quantization table is derived so
as to minimize the reconstruction error of the quantized coefficients.
* JBOOLEAN_OVERSHOOT_DERINGING (default: TRUE)
Specifies whether overshooting is applied to samples with extreme values
(for example, 0 and 255 for 8-bit samples). Overshooting may reduce ringing
artifacts from compression, in particular in areas where black text appears
on a white background.
Floating Point Extension Parameters Supported by mozjpeg
--------------------------------------------------------
* JFLOAT_LAMBDA_LOG_SCALE1 (default: 14.75)
JFLOAT_LAMBDA_LOG_SCALE2 (default: 16.5)
These parameters specify the lambda value used in trellis quantization. The
lambda value (Lagrange multiplier) in the
R + lambda * D
equation is derived from
lambda = 2^s1 / ((2^s2 + n) * q^2),
where s1 and s2 are the values of JFLOAT_LAMBDA_LOG_SCALE1 and
JFLOAT_LAMBDA_LOG_SCALE2, n is the average of the squared unquantized AC
coefficients within the current 8x8 block, and q is the quantization table
entry associated with the current coefficient frequency. If
JFLOAT_LAMBDA_LOG_SCALE2 is 0, then an alternate form is used that does not
rely on n:
lambda = 2^(s1-12) / q^2.
* JFLOAT_TRELLIS_DELTA_DC_WEIGHT (default: 0.0)
This parameter controls how distortion is calculated in DC trellis quantization
(enabled with JBOOLEAN_TRELLIS_QUANT_DC). It defines weighting between distortion
of the DC coefficient and distortion of the vertical gradient of DC coefficients.
The value of the parameter corresponds to the weight applied to the distortion
of the vertical gradient.
Integer Extension Parameters Supported by mozjpeg
-------------------------------------------------
* JINT_COMPRESS_PROFILE (default: JCP_MAX_COMPRESSION)
Select a compression profile, which is a set of default parameters that will
achieve a desired compression goal. This parameter controls the behavior of
the jpeg_set_defaults() function. Thus, setting JINT_COMPRESS_PROFILE does
not cause any other parameters to be modified until jpeg_set_defaults() is
called. The following compression profiles are supported:
- JCP_MAX_COMPRESSION (default)
Increase the compression ratio as much as possible, at the expense of
increased encoding time. This enables progressive entropy coding and all
mozjpeg extensions.
- JCP_FASTEST
Use the libjpeg[-turbo] defaults (baseline entropy coding, no mozjpeg
extensions enabled.)
* JINT_TRELLIS_FREQ_SPLIT (default: 8)
Specifies the position within the zigzag scan at which the split between
scans is positioned in the context of trellis quantization.
JBOOLEAN_USE_SCANS_IN_TRELLIS must be enabled for this parameter to have any
effect.
* JINT_TRELLIS_NUM_LOOPS (default: 1)
Specifies the number of trellis quantization passes. Huffman tables are
updated between passes.
* JINT_BASE_QUANT_TBL_IDX (default: 3)
Specifies which quantization table set to use. The following options are
available:
0 = Tables from JPEG Annex K
1 = Flat table
2 = Table tuned for MSSIM on Kodak image set
3 = Table from http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=20333&p=98008#p98008
4 = Table tuned for PSNR-HVS-M on Kodak image set
5 = Table from: Relevance of Human Vision to JPEG-DCT Compression
(1992) Klein, Silverstein and Carney
6 = Table from: DCTune Perceptual Optimization of Compressed Dental X-Rays
(1997) Watson, Taylor, Borthwick
7 = Table from: A Visual Detection Model for DCT Coefficient Quantization
(12/9/93) Ahumada, Watson, Peterson
8 = Table from: An Improved Detection Model for DCT Coefficient Quantization
(1993) Peterson, Ahumada and Watson
* JINT_DC_SCAN_OPT_MODE (default: 1)
Specifies the DC scan optimization mode. The following options are
available:
0 = One scan for all components
1 = One scan per component
2 = Optimize between one scan for all components and one scan for the first
component plus one scan for the remaining components

View File

@@ -1,346 +0,0 @@
Background
==========
libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2,
AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression
on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG
compression on x86 and x86-64 systems. On such systems, libjpeg-turbo is
generally 2-6x as fast as libjpeg, all else being equal. On other types of
systems, libjpeg-turbo can still outperform libjpeg by a significant amount, by
virtue of its highly-optimized Huffman coding routines. In many cases, the
performance of libjpeg-turbo rivals that of proprietary high-speed JPEG codecs.
libjpeg-turbo implements both the traditional libjpeg API as well as the less
powerful but more straightforward TurboJPEG API. libjpeg-turbo also features
colorspace extensions that allow it to compress from/decompress to 32-bit and
big-endian pixel buffers (RGBX, XBGR, etc.), as well as a full-featured Java
interface.
libjpeg-turbo was originally based on libjpeg/SIMD, an MMX-accelerated
derivative of libjpeg v6b developed by Miyasaka Masaru. The TigerVNC and
VirtualGL projects made numerous enhancements to the codec in 2009, and in
early 2010, libjpeg-turbo spun off into an independent project, with the goal
of making high-speed JPEG compression/decompression technology available to a
broader range of users and developers.
License
=======
libjpeg-turbo is covered by three compatible BSD-style open source licenses.
Refer to [LICENSE.md](LICENSE.md) for a roll-up of license terms.
Building libjpeg-turbo
======================
Refer to [BUILDING.md](BUILDING.md) for complete instructions.
Using libjpeg-turbo
===================
libjpeg-turbo includes two APIs that can be used to compress and decompress
JPEG images:
- **TurboJPEG API**<br>
This API provides an easy-to-use interface for compressing and decompressing
JPEG images in memory. It also provides some functionality that would not be
straightforward to achieve using the underlying libjpeg API, such as
generating planar YUV images and performing multiple simultaneous lossless
transforms on an image. The Java interface for libjpeg-turbo is written on
top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
users of libjpeg-turbo. Refer to [tjexample.c](tjexample.c) and
[TJExample.java](java/TJExample.java) for examples of its usage and to
<http://libjpeg-turbo.org/Documentation/Documentation> for API documentation.
- **libjpeg API**<br>
This is the de facto industry-standard API for compressing and decompressing
JPEG images. It is more difficult to use than the TurboJPEG API but also
more powerful. The libjpeg API implementation in libjpeg-turbo is both
API/ABI-compatible and mathematically compatible with libjpeg v6b. It can
also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
(see below.) Refer to [cjpeg.c](cjpeg.c) and [djpeg.c](djpeg.c) for examples
of its usage and to [libjpeg.txt](libjpeg.txt) for API documentation.
There is no significant performance advantage to either API when both are used
to perform similar operations.
Colorspace Extensions
---------------------
libjpeg-turbo includes extensions that allow JPEG images to be compressed
directly from (and decompressed directly to) buffers that use BGR, BGRX,
RGBX, XBGR, and XRGB pixel ordering. This is implemented with ten new
colorspace constants:
JCS_EXT_RGB /* red/green/blue */
JCS_EXT_RGBX /* red/green/blue/x */
JCS_EXT_BGR /* blue/green/red */
JCS_EXT_BGRX /* blue/green/red/x */
JCS_EXT_XBGR /* x/blue/green/red */
JCS_EXT_XRGB /* x/red/green/blue */
JCS_EXT_RGBA /* red/green/blue/alpha */
JCS_EXT_BGRA /* blue/green/red/alpha */
JCS_EXT_ABGR /* alpha/blue/green/red */
JCS_EXT_ARGB /* alpha/red/green/blue */
Setting `cinfo.in_color_space` (compression) or `cinfo.out_color_space`
(decompression) to one of these values will cause libjpeg-turbo to read the
red, green, and blue values from (or write them to) the appropriate position in
the pixel when compressing from/decompressing to an RGB buffer.
Your application can check for the existence of these extensions at compile
time with:
#ifdef JCS_EXTENSIONS
At run time, attempting to use these extensions with a libjpeg implementation
that does not support them will result in a "Bogus input colorspace" error.
Applications can trap this error in order to test whether run-time support is
available for the colorspace extensions.
When using the RGBX, BGRX, XBGR, and XRGB colorspaces during decompression, the
X byte is undefined, and in order to ensure the best performance, libjpeg-turbo
can set that byte to whatever value it wishes. If an application expects the X
byte to be used as an alpha channel, then it should specify `JCS_EXT_RGBA`,
`JCS_EXT_BGRA`, `JCS_EXT_ABGR`, or `JCS_EXT_ARGB`. When these colorspace
constants are used, the X byte is guaranteed to be 0xFF, which is interpreted
as opaque.
Your application can check for the existence of the alpha channel colorspace
extensions at compile time with:
#ifdef JCS_ALPHA_EXTENSIONS
[jcstest.c](jcstest.c), located in the libjpeg-turbo source tree, demonstrates
how to check for the existence of the colorspace extensions at compile time and
run time.
libjpeg v7 and v8 API/ABI Emulation
-----------------------------------
With libjpeg v7 and v8, new features were added that necessitated extending the
compression and decompression structures. Unfortunately, due to the exposed
nature of those structures, extending them also necessitated breaking backward
ABI compatibility with previous libjpeg releases. Thus, programs that were
built to use libjpeg v7 or v8 did not work with libjpeg-turbo, since it is
based on the libjpeg v6b code base. Although libjpeg v7 and v8 are not
as widely used as v6b, enough programs (including a few Linux distros) made
the switch that there was a demand to emulate the libjpeg v7 and v8 ABIs
in libjpeg-turbo. It should be noted, however, that this feature was added
primarily so that applications that had already been compiled to use libjpeg
v7+ could take advantage of accelerated baseline JPEG encoding/decoding
without recompiling. libjpeg-turbo does not claim to support all of the
libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all
cases (see below.)
By passing an argument of `--with-jpeg7` or `--with-jpeg8` to `configure`, or
an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you can build a
version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so that
programs that are built against libjpeg v7 or v8 can be run with libjpeg-turbo.
The following section describes which libjpeg v7+ features are supported and
which aren't.
### Support for libjpeg v7 and v8 Features
#### Fully supported
- **libjpeg: IDCT scaling extensions in decompressor**<br>
libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8,
1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4
and 1/2 are SIMD-accelerated.)
- **libjpeg: Arithmetic coding**
- **libjpeg: In-memory source and destination managers**<br>
See notes below.
- **cjpeg: Separate quality settings for luminance and chrominance**<br>
Note that the libpjeg v7+ API was extended to accommodate this feature only
for convenience purposes. It has always been possible to implement this
feature with libjpeg v6b (see rdswitch.c for an example.)
- **cjpeg: 32-bit BMP support**
- **cjpeg: `-rgb` option**
- **jpegtran: Lossless cropping**
- **jpegtran: `-perfect` option**
- **jpegtran: Forcing width/height when performing lossless crop**
- **rdjpgcom: `-raw` option**
- **rdjpgcom: Locale awareness**
#### Not supported
NOTE: As of this writing, extensive research has been conducted into the
usefulness of DCT scaling as a means of data reduction and SmartScale as a
means of quality improvement. The reader is invited to peruse the research at
<http://www.libjpeg-turbo.org/About/SmartScale> and draw his/her own conclusions,
but it is the general belief of our project that these features have not
demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
- **libjpeg: DCT scaling in compressor**<br>
`cinfo.scale_num` and `cinfo.scale_denom` are silently ignored.
There is no technical reason why DCT scaling could not be supported when
emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see
below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and
8/9 would be available, which is of limited usefulness.
- **libjpeg: SmartScale**<br>
`cinfo.block_size` is silently ignored.
SmartScale is an extension to the JPEG format that allows for DCT block
sizes other than 8x8. Providing support for this new format would be
feasible (particularly without full acceleration.) However, until/unless
the format becomes either an official industry standard or, at minimum, an
accepted solution in the community, we are hesitant to implement it, as
there is no sense of whether or how it might change in the future. It is
our belief that SmartScale has not demonstrated sufficient usefulness as a
lossless format nor as a means of quality enhancement, and thus our primary
interest in providing this feature would be as a means of supporting
additional DCT scaling factors.
- **libjpeg: Fancy downsampling in compressor**<br>
`cinfo.do_fancy_downsampling` is silently ignored.
This requires the DCT scaling feature, which is not supported.
- **jpegtran: Scaling**<br>
This requires both the DCT scaling and SmartScale features, which are not
supported.
- **Lossless RGB JPEG files**<br>
This requires the SmartScale feature, which is not supported.
### What About libjpeg v9?
libjpeg v9 introduced yet another field to the JPEG compression structure
(`color_transform`), thus making the ABI backward incompatible with that of
libjpeg v8. This new field was introduced solely for the purpose of supporting
lossless SmartScale encoding. Furthermore, there was actually no reason to
extend the API in this manner, as the color transform could have just as easily
been activated by way of a new JPEG colorspace constant, thus preserving
backward ABI compatibility.
Our research (see link above) has shown that lossless SmartScale does not
generally accomplish anything that can't already be accomplished better with
existing, standard lossless formats. Therefore, at this time it is our belief
that there is not sufficient technical justification for software projects to
upgrade from libjpeg v8 to libjpeg v9, and thus there is not sufficient
technical justification for us to emulate the libjpeg v9 ABI.
In-Memory Source/Destination Managers
-------------------------------------
By default, libjpeg-turbo 1.3 and later includes the `jpeg_mem_src()` and
`jpeg_mem_dest()` functions, even when not emulating the libjpeg v8 API/ABI.
Previously, it was necessary to build libjpeg-turbo from source with libjpeg v8
API/ABI emulation in order to use the in-memory source/destination managers,
but several projects requested that those functions be included when emulating
the libjpeg v6b API/ABI as well. This allows the use of those functions by
programs that need them, without breaking ABI compatibility for programs that
don't, and it allows those functions to be provided in the "official"
libjpeg-turbo binaries.
Those who are concerned about maintaining strict conformance with the libjpeg
v6b or v7 API can pass an argument of `--without-mem-srcdst` to `configure` or
an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to building
libjpeg-turbo. This will restore the pre-1.3 behavior, in which
`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the
libjpeg v8 API/ABI.
On Un*x systems, including the in-memory source/destination managers changes
the dynamic library version from 62.1.0 to 62.2.0 if using libjpeg v6b API/ABI
emulation and from 7.1.0 to 7.2.0 if using libjpeg v7 API/ABI emulation.
Note that, on most Un*x systems, the dynamic linker will not look for a
function in a library until that function is actually used. Thus, if a program
is built against libjpeg-turbo 1.3+ and uses `jpeg_mem_src()` or
`jpeg_mem_dest()`, that program will not fail if run against an older version
of libjpeg-turbo or against libjpeg v7- until the program actually tries to
call `jpeg_mem_src()` or `jpeg_mem_dest()`. Such is not the case on Windows.
If a program is built against the libjpeg-turbo 1.3+ DLL and uses
`jpeg_mem_src()` or `jpeg_mem_dest()`, then it must use the libjpeg-turbo 1.3+
DLL at run time.
Both cjpeg and djpeg have been extended to allow testing the in-memory
source/destination manager functions. See their respective man pages for more
details.
Mathematical Compatibility
==========================
For the most part, libjpeg-turbo should produce identical output to libjpeg
v6b. The one exception to this is when using the floating point DCT/IDCT, in
which case the outputs of libjpeg v6b and libjpeg-turbo can differ for the
following reasons:
- The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever so
slightly more accurate than the implementation in libjpeg v6b, but not by
any amount perceptible to human vision (generally in the range of 0.01 to
0.08 dB gain in PNSR.)
- When not using the SIMD extensions, libjpeg-turbo uses the more accurate
(and slightly faster) floating point IDCT algorithm introduced in libjpeg
v8a as opposed to the algorithm used in libjpeg v6b. It should be noted,
however, that this algorithm basically brings the accuracy of the floating
point IDCT in line with the accuracy of the slow integer IDCT. The floating
point DCT/IDCT algorithms are mainly a legacy feature, and they do not
produce significantly more accuracy than the slow integer algorithms (to put
numbers on this, the typical difference in PNSR between the two algorithms
is less than 0.10 dB, whereas changing the quality level by 1 in the upper
range of the quality scale is typically more like a 1.0 dB difference.)
- If the floating point algorithms in libjpeg-turbo are not implemented using
SIMD instructions on a particular platform, then the accuracy of the
floating point DCT/IDCT can depend on the compiler settings.
While libjpeg-turbo does emulate the libjpeg v8 API/ABI, under the hood it is
still using the same algorithms as libjpeg v6b, so there are several specific
cases in which libjpeg-turbo cannot be expected to produce the same output as
libjpeg v8:
- When decompressing using scaling factors of 1/2 and 1/4, because libjpeg v8
implements those scaling algorithms differently than libjpeg v6b does, and
libjpeg-turbo's SIMD extensions are based on the libjpeg v6b behavior.
- When using chrominance subsampling, because libjpeg v8 implements this
with its DCT/IDCT scaling algorithms rather than with a separate
downsampling/upsampling algorithm. In our testing, the subsampled/upsampled
output of libjpeg v8 is less accurate than that of libjpeg v6b for this
reason.
- When decompressing using a scaling factor > 1 and merged (AKA "non-fancy" or
"non-smooth") chrominance upsampling, because libjpeg v8 does not support
merged upsampling with scaling factors > 1.
Performance Pitfalls
====================
Restart Markers
---------------
The optimized Huffman decoder in libjpeg-turbo does not handle restart markers
in a way that makes the rest of the libjpeg infrastructure happy, so it is
necessary to use the slow Huffman decoder when decompressing a JPEG image that
has restart markers. This can cause the decompression performance to drop by
as much as 20%, but the performance will still be much greater than that of
libjpeg. Many consumer packages, such as PhotoShop, use restart markers when
generating JPEG images, so images generated by those programs will experience
this issue.
Fast Integer Forward DCT at High Quality Levels
-----------------------------------------------
The algorithm used by the SIMD-accelerated quantization function cannot produce
correct results whenever the fast integer forward DCT is used along with a JPEG
quality of 98-100. Thus, libjpeg-turbo must use the non-SIMD quantization
function in those cases. This causes performance to drop by as much as 40%.
It is therefore strongly advised that you use the slow integer forward DCT
whenever encoding images with a JPEG quality of 98 or higher.

View File

@@ -128,7 +128,7 @@ with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you, fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy. its user, assume the entire risk as to its quality and accuracy.
This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding. This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
All Rights Reserved except as specified below. All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this Permission is hereby granted to use, copy, modify, and distribute this
@@ -159,19 +159,6 @@ commercial products, provided that all warranty or liability claims are
assumed by the product vendor. assumed by the product vendor.
The IJG distribution formerly included code to read and write GIF files.
To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
support has been removed altogether, and the GIF writer has been simplified
to produce "uncompressed GIFs". This technique does not use the LZW
algorithm; the resulting GIF files are larger than usual, but are readable
by all standard GIF decoders.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."
REFERENCES REFERENCES
========== ==========

366
README.md
View File

@@ -1,29 +1,357 @@
Mozilla JPEG Encoder Project [![Build Status](https://ci.appveyor.com/api/projects/status/github/mozilla/mozjpeg?branch=master&svg=true)](https://ci.appveyor.com/project/kornel/mozjpeg-4ekrx) Background
============================ ==========
MozJPEG improves JPEG compression efficiency achieving higher visual quality and smaller file sizes at the same time. It is compatible the JPEG standard, and the vast majority of the world's deployed JPEG decoders. libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate
baseline JPEG compression and decompression on x86, x86-64, Arm, PowerPC, and
MIPS systems, as well as progressive JPEG compression on x86, x86-64, and Arm
systems. On such systems, libjpeg-turbo is generally 2-6x as fast as libjpeg,
all else being equal. On other types of systems, libjpeg-turbo can still
outperform libjpeg by a significant amount, by virtue of its highly-optimized
Huffman coding routines. In many cases, the performance of libjpeg-turbo
rivals that of proprietary high-speed JPEG codecs.
MozJPEG is a patch for [libjpeg-turbo](https://github.com/libjpeg-turbo/libjpeg-turbo). **Please send pull requests to libjpeg-turbo** if the changes aren't specific to newly-added MozJPEG-only compression code. This project aims to keep differences with libjpeg-turbo minimal, so whenever possible, improvements and bug fixes should go there first. libjpeg-turbo implements both the traditional libjpeg API as well as the less
powerful but more straightforward TurboJPEG API. libjpeg-turbo also features
colorspace extensions that allow it to compress from/decompress to 32-bit and
big-endian pixel buffers (RGBX, XBGR, etc.), as well as a full-featured Java
interface.
MozJPEG is compatible with the libjpeg API and ABI. It is intended to be a drop-in replacement for libjpeg. MozJPEG is a strict superset of libjpeg-turbo's functionality. All MozJPEG's improvements can be disabled at run time, and in that case it behaves exactly like libjpeg-turbo. libjpeg-turbo was originally based on libjpeg/SIMD, an MMX-accelerated
derivative of libjpeg v6b developed by Miyasaka Masaru. The TigerVNC and
VirtualGL projects made numerous enhancements to the codec in 2009, and in
early 2010, libjpeg-turbo spun off into an independent project, with the goal
of making high-speed JPEG compression/decompression technology available to a
broader range of users and developers.
MozJPEG is meant to be used as a library in graphics programs and image processing tools. We include a demo `cjpeg` command-line tool, but it's not intended for serious use. We encourage authors of graphics programs to use libjpeg's [C API](libjpeg.txt) and link with MozJPEG library instead.
## Features License
=======
* Progressive encoding with "jpegrescan" optimization. It can be applied to any JPEG file (with `jpegtran`) to losslessly reduce file size. libjpeg-turbo is covered by three compatible BSD-style open source licenses.
* Trellis quantization. When converting other formats to JPEG it maximizes quality/filesize ratio. Refer to [LICENSE.md](LICENSE.md) for a roll-up of license terms.
* Comes with new quantization table presets, e.g. tuned for high-resolution displays.
* Fully compatible with all web browsers.
* Can be seamlessly integrated into any program that uses the industry-standard libjpeg API. There's no need to write any MozJPEG-specific integration code.
## Releases
* [Latest release](https://github.com/mozilla/mozjpeg/releases/latest) Building libjpeg-turbo
* [Overview of 3.0 features](https://calendar.perfplanet.com/2014/mozjpeg-3-0/) ======================
* [Version 2.0 Announcement](https://blog.mozilla.org/research/2014/07/15/mozilla-advances-jpeg-encoding-with-mozjpeg-2-0/)
* [Version 1.0 Announcement](https://blog.mozilla.org/research/2014/03/05/introducing-the-mozjpeg-project/)
## Compiling Refer to [BUILDING.md](BUILDING.md) for complete instructions.
See [BUILDING](BUILDING.md). MozJPEG is built exactly the same way as libjpeg-turbo, so if you need additional help please consult [libjpeg-turbo documentation](https://libjpeg-turbo.org/).
Using libjpeg-turbo
===================
libjpeg-turbo includes two APIs that can be used to compress and decompress
JPEG images:
- **TurboJPEG API**<br>
This API provides an easy-to-use interface for compressing and decompressing
JPEG images in memory. It also provides some functionality that would not be
straightforward to achieve using the underlying libjpeg API, such as
generating planar YUV images and performing multiple simultaneous lossless
transforms on an image. The Java interface for libjpeg-turbo is written on
top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
users of libjpeg-turbo. Refer to [tjexample.c](tjexample.c) and
[TJExample.java](java/TJExample.java) for examples of its usage and to
<http://libjpeg-turbo.org/Documentation/Documentation> for API documentation.
- **libjpeg API**<br>
This is the de facto industry-standard API for compressing and decompressing
JPEG images. It is more difficult to use than the TurboJPEG API but also
more powerful. The libjpeg API implementation in libjpeg-turbo is both
API/ABI-compatible and mathematically compatible with libjpeg v6b. It can
also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
(see below.) Refer to [cjpeg.c](cjpeg.c) and [djpeg.c](djpeg.c) for examples
of its usage and to [libjpeg.txt](libjpeg.txt) for API documentation.
There is no significant performance advantage to either API when both are used
to perform similar operations.
Colorspace Extensions
---------------------
libjpeg-turbo includes extensions that allow JPEG images to be compressed
directly from (and decompressed directly to) buffers that use BGR, BGRX,
RGBX, XBGR, and XRGB pixel ordering. This is implemented with ten new
colorspace constants:
JCS_EXT_RGB /* red/green/blue */
JCS_EXT_RGBX /* red/green/blue/x */
JCS_EXT_BGR /* blue/green/red */
JCS_EXT_BGRX /* blue/green/red/x */
JCS_EXT_XBGR /* x/blue/green/red */
JCS_EXT_XRGB /* x/red/green/blue */
JCS_EXT_RGBA /* red/green/blue/alpha */
JCS_EXT_BGRA /* blue/green/red/alpha */
JCS_EXT_ABGR /* alpha/blue/green/red */
JCS_EXT_ARGB /* alpha/red/green/blue */
Setting `cinfo.in_color_space` (compression) or `cinfo.out_color_space`
(decompression) to one of these values will cause libjpeg-turbo to read the
red, green, and blue values from (or write them to) the appropriate position in
the pixel when compressing from/decompressing to an RGB buffer.
Your application can check for the existence of these extensions at compile
time with:
#ifdef JCS_EXTENSIONS
At run time, attempting to use these extensions with a libjpeg implementation
that does not support them will result in a "Bogus input colorspace" error.
Applications can trap this error in order to test whether run-time support is
available for the colorspace extensions.
When using the RGBX, BGRX, XBGR, and XRGB colorspaces during decompression, the
X byte is undefined, and in order to ensure the best performance, libjpeg-turbo
can set that byte to whatever value it wishes. If an application expects the X
byte to be used as an alpha channel, then it should specify `JCS_EXT_RGBA`,
`JCS_EXT_BGRA`, `JCS_EXT_ABGR`, or `JCS_EXT_ARGB`. When these colorspace
constants are used, the X byte is guaranteed to be 0xFF, which is interpreted
as opaque.
Your application can check for the existence of the alpha channel colorspace
extensions at compile time with:
#ifdef JCS_ALPHA_EXTENSIONS
[jcstest.c](jcstest.c), located in the libjpeg-turbo source tree, demonstrates
how to check for the existence of the colorspace extensions at compile time and
run time.
libjpeg v7 and v8 API/ABI Emulation
-----------------------------------
With libjpeg v7 and v8, new features were added that necessitated extending the
compression and decompression structures. Unfortunately, due to the exposed
nature of those structures, extending them also necessitated breaking backward
ABI compatibility with previous libjpeg releases. Thus, programs that were
built to use libjpeg v7 or v8 did not work with libjpeg-turbo, since it is
based on the libjpeg v6b code base. Although libjpeg v7 and v8 are not
as widely used as v6b, enough programs (including a few Linux distros) made
the switch that there was a demand to emulate the libjpeg v7 and v8 ABIs
in libjpeg-turbo. It should be noted, however, that this feature was added
primarily so that applications that had already been compiled to use libjpeg
v7+ could take advantage of accelerated baseline JPEG encoding/decoding
without recompiling. libjpeg-turbo does not claim to support all of the
libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all
cases (see below.)
By passing an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you
can build a version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so
that programs that are built against libjpeg v7 or v8 can be run with
libjpeg-turbo. The following section describes which libjpeg v7+ features are
supported and which aren't.
### Support for libjpeg v7 and v8 Features
#### Fully supported
- **libjpeg API: IDCT scaling extensions in decompressor**<br>
libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8,
1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4
and 1/2 are SIMD-accelerated.)
- **libjpeg API: Arithmetic coding**
- **libjpeg API: In-memory source and destination managers**<br>
See notes below.
- **cjpeg: Separate quality settings for luminance and chrominance**<br>
Note that the libpjeg v7+ API was extended to accommodate this feature only
for convenience purposes. It has always been possible to implement this
feature with libjpeg v6b (see rdswitch.c for an example.)
- **cjpeg: 32-bit BMP support**
- **cjpeg: `-rgb` option**
- **jpegtran: Lossless cropping**
- **jpegtran: `-perfect` option**
- **jpegtran: Forcing width/height when performing lossless crop**
- **rdjpgcom: `-raw` option**
- **rdjpgcom: Locale awareness**
#### Not supported
NOTE: As of this writing, extensive research has been conducted into the
usefulness of DCT scaling as a means of data reduction and SmartScale as a
means of quality improvement. Readers are invited to peruse the research at
<http://www.libjpeg-turbo.org/About/SmartScale> and draw their own conclusions,
but it is the general belief of our project that these features have not
demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
- **libjpeg API: DCT scaling in compressor**<br>
`cinfo.scale_num` and `cinfo.scale_denom` are silently ignored.
There is no technical reason why DCT scaling could not be supported when
emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see
below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and
8/9 would be available, which is of limited usefulness.
- **libjpeg API: SmartScale**<br>
`cinfo.block_size` is silently ignored.
SmartScale is an extension to the JPEG format that allows for DCT block
sizes other than 8x8. Providing support for this new format would be
feasible (particularly without full acceleration.) However, until/unless
the format becomes either an official industry standard or, at minimum, an
accepted solution in the community, we are hesitant to implement it, as
there is no sense of whether or how it might change in the future. It is
our belief that SmartScale has not demonstrated sufficient usefulness as a
lossless format nor as a means of quality enhancement, and thus our primary
interest in providing this feature would be as a means of supporting
additional DCT scaling factors.
- **libjpeg API: Fancy downsampling in compressor**<br>
`cinfo.do_fancy_downsampling` is silently ignored.
This requires the DCT scaling feature, which is not supported.
- **jpegtran: Scaling**<br>
This requires both the DCT scaling and SmartScale features, which are not
supported.
- **Lossless RGB JPEG files**<br>
This requires the SmartScale feature, which is not supported.
### What About libjpeg v9?
libjpeg v9 introduced yet another field to the JPEG compression structure
(`color_transform`), thus making the ABI backward incompatible with that of
libjpeg v8. This new field was introduced solely for the purpose of supporting
lossless SmartScale encoding. Furthermore, there was actually no reason to
extend the API in this manner, as the color transform could have just as easily
been activated by way of a new JPEG colorspace constant, thus preserving
backward ABI compatibility.
Our research (see link above) has shown that lossless SmartScale does not
generally accomplish anything that can't already be accomplished better with
existing, standard lossless formats. Therefore, at this time it is our belief
that there is not sufficient technical justification for software projects to
upgrade from libjpeg v8 to libjpeg v9, and thus there is not sufficient
technical justification for us to emulate the libjpeg v9 ABI.
In-Memory Source/Destination Managers
-------------------------------------
By default, libjpeg-turbo 1.3 and later includes the `jpeg_mem_src()` and
`jpeg_mem_dest()` functions, even when not emulating the libjpeg v8 API/ABI.
Previously, it was necessary to build libjpeg-turbo from source with libjpeg v8
API/ABI emulation in order to use the in-memory source/destination managers,
but several projects requested that those functions be included when emulating
the libjpeg v6b API/ABI as well. This allows the use of those functions by
programs that need them, without breaking ABI compatibility for programs that
don't, and it allows those functions to be provided in the "official"
libjpeg-turbo binaries.
Those who are concerned about maintaining strict conformance with the libjpeg
v6b or v7 API can pass an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to
building libjpeg-turbo. This will restore the pre-1.3 behavior, in which
`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the
libjpeg v8 API/ABI.
On Un*x systems, including the in-memory source/destination managers changes
the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI
emulation and from 7.2.0 to 7.3.0 if using libjpeg v7 API/ABI emulation.
Note that, on most Un*x systems, the dynamic linker will not look for a
function in a library until that function is actually used. Thus, if a program
is built against libjpeg-turbo 1.3+ and uses `jpeg_mem_src()` or
`jpeg_mem_dest()`, that program will not fail if run against an older version
of libjpeg-turbo or against libjpeg v7- until the program actually tries to
call `jpeg_mem_src()` or `jpeg_mem_dest()`. Such is not the case on Windows.
If a program is built against the libjpeg-turbo 1.3+ DLL and uses
`jpeg_mem_src()` or `jpeg_mem_dest()`, then it must use the libjpeg-turbo 1.3+
DLL at run time.
Both cjpeg and djpeg have been extended to allow testing the in-memory
source/destination manager functions. See their respective man pages for more
details.
Mathematical Compatibility
==========================
For the most part, libjpeg-turbo should produce identical output to libjpeg
v6b. The one exception to this is when using the floating point DCT/IDCT, in
which case the outputs of libjpeg v6b and libjpeg-turbo can differ for the
following reasons:
- The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever so
slightly more accurate than the implementation in libjpeg v6b, but not by
any amount perceptible to human vision (generally in the range of 0.01 to
0.08 dB gain in PNSR.)
- When not using the SIMD extensions, libjpeg-turbo uses the more accurate
(and slightly faster) floating point IDCT algorithm introduced in libjpeg
v8a as opposed to the algorithm used in libjpeg v6b. It should be noted,
however, that this algorithm basically brings the accuracy of the floating
point IDCT in line with the accuracy of the accurate integer IDCT. The
floating point DCT/IDCT algorithms are mainly a legacy feature, and they do
not produce significantly more accuracy than the accurate integer algorithms
(to put numbers on this, the typical difference in PNSR between the two
algorithms is less than 0.10 dB, whereas changing the quality level by 1 in
the upper range of the quality scale is typically more like a 1.0 dB
difference.)
- If the floating point algorithms in libjpeg-turbo are not implemented using
SIMD instructions on a particular platform, then the accuracy of the
floating point DCT/IDCT can depend on the compiler settings.
While libjpeg-turbo does emulate the libjpeg v8 API/ABI, under the hood it is
still using the same algorithms as libjpeg v6b, so there are several specific
cases in which libjpeg-turbo cannot be expected to produce the same output as
libjpeg v8:
- When decompressing using scaling factors of 1/2 and 1/4, because libjpeg v8
implements those scaling algorithms differently than libjpeg v6b does, and
libjpeg-turbo's SIMD extensions are based on the libjpeg v6b behavior.
- When using chrominance subsampling, because libjpeg v8 implements this
with its DCT/IDCT scaling algorithms rather than with a separate
downsampling/upsampling algorithm. In our testing, the subsampled/upsampled
output of libjpeg v8 is less accurate than that of libjpeg v6b for this
reason.
- When decompressing using a scaling factor > 1 and merged (AKA "non-fancy" or
"non-smooth") chrominance upsampling, because libjpeg v8 does not support
merged upsampling with scaling factors > 1.
Performance Pitfalls
====================
Restart Markers
---------------
The optimized Huffman decoder in libjpeg-turbo does not handle restart markers
in a way that makes the rest of the libjpeg infrastructure happy, so it is
necessary to use the slow Huffman decoder when decompressing a JPEG image that
has restart markers. This can cause the decompression performance to drop by
as much as 20%, but the performance will still be much greater than that of
libjpeg. Many consumer packages, such as Photoshop, use restart markers when
generating JPEG images, so images generated by those programs will experience
this issue.
Fast Integer Forward DCT at High Quality Levels
-----------------------------------------------
The algorithm used by the SIMD-accelerated quantization function cannot produce
correct results whenever the fast integer forward DCT is used along with a JPEG
quality of 98-100. Thus, libjpeg-turbo must use the non-SIMD quantization
function in those cases. This causes performance to drop by as much as 40%.
It is therefore strongly advised that you use the accurate integer forward DCT
whenever encoding images with a JPEG quality of 98 or higher.
Memory Debugger Pitfalls
========================
Valgrind and Memory Sanitizer (MSan) can generate false positives
(specifically, incorrect reports of uninitialized memory accesses) when used
with libjpeg-turbo's SIMD extensions. It is generally recommended that the
SIMD extensions be disabled, either by passing an argument of `-DWITH_SIMD=0`
to `cmake` when configuring the build or by setting the environment variable
`JSIMD_FORCENONE` to `1` at run time, when testing libjpeg-turbo with Valgrind,
MSan, or other memory debuggers.

View File

@@ -1,62 +1,99 @@
image: Visual Studio 2017
configuration: Release
platform:
- Win32
- x64
install: install:
- if %PLATFORM% == Win32 (set ARCH=x86) - cmd: >-
- if %PLATFORM% == x64 (set ARCH=x64) if not exist c:\installers mkdir c:\installers
## Set up nasm
- choco install nasm
- set PATH=%PATH%;C:\Program Files\NASM
## Set up libpng
- cd C:\Tools\vcpkg
- vcpkg install libpng:%ARCH%-windows
- vcpkg install libpng:%ARCH%-windows-static
before_build: mkdir c:\temp
- cd %APPVEYOR_BUILD_FOLDER%
- nasm -v
- cmake --version
- git describe --always --tags --dirty
- FOR /F %%a in ('git describe --always --tags --dirty') do set GIT_VERSION=%%a
build_script: if not exist c:\installers\nasm-2.10.01-win32.zip curl -fSL -o c:\installers\nasm-2.10.01-win32.zip http://www.nasm.us/pub/nasm/releasebuilds/2.10.01/win32/nasm-2.10.01-win32.zip
## Build shared
- cmake -B shared -A %PLATFORM%
-DENABLE_SHARED=1 -DENABLE_STATIC=0
-DREQUIRE_SIMD=1
-DCMAKE_TOOLCHAIN_FILE=C:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake
- cmake --build shared --config Release 7z x c:\installers\nasm-2.10.01-win32.zip -oc:\ > c:\installers\nasm.install.log
## Build static if not exist c:\installers\i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z curl -fSL -o c:\installers\i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z "https://sourceforge.net/projects/mingw-w64/files/Toolchains targetting Win32/Personal Builds/mingw-builds/6.4.0/threads-posix/dwarf/i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z"
- cmake -B static -A %PLATFORM%
-DENABLE_SHARED=0 -DENABLE_STATIC=1
-DREQUIRE_SIMD=1
-DCMAKE_TOOLCHAIN_FILE=C:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake
-DVCPKG_TARGET_TRIPLET=%ARCH%-windows-static
- cmake --build static --config Release md "c:\Program Files (x86)\mingw-w64\i686-6.4.0-posix-dwarf-rt_v5-rev0"
after_build: 7z x c:\installers\i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z -o"c:\Program Files (x86)\mingw-w64\i686-6.4.0-posix-dwarf-rt_v5-rev0" > c:\installers\mingw32.install.log
- 7z a mozjpeg-%GIT_VERSION%-win-%ARCH%.zip shared/Release static/Release
artifacts: if not exist c:\installers\x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z curl -fSL -o c:\installers\x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z "https://sourceforge.net/projects/mingw-w64/files/Toolchains targetting Win64/Personal Builds/mingw-builds/6.4.0/threads-posix/seh/x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z"
- path: '*.zip'
md "c:\Program Files\mingw-w64\x86_64-6.4.0-posix-seh-rt_v5-rev0"
7z x c:\installers\x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z -o"c:\Program Files\mingw-w64\x86_64-6.4.0-posix-seh-rt_v5-rev0" > c:\installers\mingw64.install.log
set PATH=c:\nasm-2.10.01;c:\Program Files (x86)\NSIS;c:\msys64\usr\bin;%PATH%
"c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
set INCLUDE
set LIB
set PATH
set MSYSTEM=MINGW32
mklink /d "%ProgramData%\Oracle\Java32" "c:\Program Files (x86)\Java\jdk1.6.0"
git clone --depth=1 https://github.com/libjpeg-turbo/buildscripts.git -b %APPVEYOR_REPO_BRANCH% c:/buildscripts
cache: cache:
- C:\ProgramData\chocolatey\bin - c:\installers\nasm-2.10.01-win32.zip -> appveyor.yml
- C:\ProgramData\chocolatey\lib - c:\installers\i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z -> appveyor.yml
- C:\Program Files\NASM - c:\installers\x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z -> appveyor.yml
- C:\tools\vcpkg\installed
build_script:
- cmd: >-
for /f %%i in ('"cygpath %CD%"') do set MINGWPATH=%%i
bash c:/buildscripts/buildljt -d %MINGWPATH% -b /c/ljt.nightly -v
cmake --build . --target clean
md win64
cd win64
bash c:/buildscripts/setupscripts/win64 -DCMAKE_C_FLAGS='-DWIN32 -D_WINDOWS -W4 -wd4100 -wd4127 -wd4245 -wd4324 -wd4701 -wd4702 -wd4706 -WX'
cd ..
ninja
move c:\ljt.nightly\files\*.tar.gz .
move c:\ljt.nightly\files\*.exe .
move c:\ljt.nightly\files\*.html .
move c:\ljt.nightly\log-windows.txt .
artifacts:
- path: '*.tar.gz'
name: Source tarball
- path: '*-gcc*.exe'
name: SDK for MinGW
- path: '*-vc*.exe'
name: SDK for Visual C++
- path: 'log-windows.txt'
name: Build log
- path: 'index.html'
name: MD5 checksums
test: off
deploy: deploy:
description: 'Automated build using Appveyor' provider: S3
provider: GitHub access_key_id:
auth_token: secure: Z74OYogQ6bNV/I+6b5ZEXig74+6MW2WLER0v/bPM/uk=
secure: 2Jj47Q5HnaPob9U4yX2t4q4TYTw4JWU6cS56mM12aoRLgfYkZ4gRZPySIzfmTPqC secret_access_key:
artifact: /.*\.zip/ secure: cyGZhHVCFwZ9jgf5lXoW69mVtECmqwx3eLo61ha8ueWbMYlHho7lwDXwVvxOFiCa
on: bucket: libjpeg-turbo-pr
APPVEYOR_REPO_TAG: true # deploy on tag push only region:
secure: qSElYBgBRcEUf88M6Osthw==
folder: $(APPVEYOR_REPO_BRANCH)/windows
set_public: true
remove_files: true

View File

@@ -1,9 +1,11 @@
/* /*
* cderror.h * cderror.h
* *
* 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 2009-2017 by Guido Vollbeding. * Modified 2009-2017 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software. * libjpeg-turbo Modifications:
* Copyright (C) 2021, 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
* file. * file.
* *
@@ -42,7 +44,7 @@ JMESSAGE(JMSG_FIRSTADDONCODE = 1000, NULL) /* Must be first entry! */
#ifdef BMP_SUPPORTED #ifdef BMP_SUPPORTED
JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") JMESSAGE(JERR_BMP_BADDEPTH, "Only 8-, 24-, and 32-bit BMP files are supported")
JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
@@ -50,9 +52,9 @@ JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image")
JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
JMESSAGE(JERR_BMP_OUTOFRANGE, "Numeric value out of range in BMP file") JMESSAGE(JERR_BMP_OUTOFRANGE, "Numeric value out of range in BMP file")
JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP, "%ux%u %d-bit BMP image")
JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") JMESSAGE(JTRC_BMP_OS2, "%ux%u %d-bit OS2 BMP image")
JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
#endif /* BMP_SUPPORTED */ #endif /* BMP_SUPPORTED */
@@ -60,6 +62,7 @@ JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
JMESSAGE(JERR_GIF_BUG, "GIF output got confused") JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
JMESSAGE(JERR_GIF_EMPTY, "Empty GIF image")
JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
JMESSAGE(JERR_GIF_NOT, "Not a GIF file") JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
@@ -84,23 +87,6 @@ JMESSAGE(JTRC_PPM, "%ux%u PPM image")
JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
#endif /* PPM_SUPPORTED */ #endif /* PPM_SUPPORTED */
#ifdef RLE_SUPPORTED
JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
#endif /* RLE_SUPPORTED */
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
@@ -117,19 +103,14 @@ JMESSAGE(JERR_BAD_CMAP_FILE,
JMESSAGE(JERR_TOO_MANY_COLORS, JMESSAGE(JERR_TOO_MANY_COLORS,
"Output file format cannot handle %d colormap entries") "Output file format cannot handle %d colormap entries")
JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
#ifdef PNG_SUPPORTED #ifdef TARGA_SUPPORTED
JMESSAGE(JERR_UNKNOWN_FORMAT, JMESSAGE(JERR_UNKNOWN_FORMAT,
"MozJPEG can't read the image (JPEG, PNG and old BMP and Targa are supported)") "Unrecognized input file format --- perhaps you need -targa")
#else #else
JMESSAGE(JERR_UNKNOWN_FORMAT, "MozJPEG can't read the image (PNG support is disabled in this build)") JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
#endif #endif
JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
#ifdef PNG_SUPPORTED
JMESSAGE(JERR_PNG_ERROR, "Unable to read PNG file: %s")
JMESSAGE(JERR_PNG_PROFILETOOLARGE, "Embedded profile was too large for this tool - dropped.")
#endif
#ifdef JMAKE_ENUM_LIST #ifdef JMAKE_ENUM_LIST
JMSG_LASTADDONCODE JMSG_LASTADDONCODE

View File

@@ -3,8 +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.
* It was modified by The libjpeg-turbo Project to include only code relevant * libjpeg-turbo Modifications:
* to libjpeg-turbo. * Copyright (C) 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
* file. * file.
* *
@@ -25,26 +25,37 @@
* Optional progress monitor: display a percent-done figure on stderr. * Optional progress monitor: display a percent-done figure on stderr.
*/ */
#ifdef PROGRESS_REPORT
METHODDEF(void) METHODDEF(void)
progress_monitor(j_common_ptr cinfo) progress_monitor(j_common_ptr cinfo)
{ {
cd_progress_ptr prog = (cd_progress_ptr)cinfo->progress; cd_progress_ptr prog = (cd_progress_ptr)cinfo->progress;
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
int percent_done =
(int)(prog->pub.pass_counter * 100L / prog->pub.pass_limit);
if (percent_done != prog->percent_done) { if (prog->max_scans != 0 && cinfo->is_decompressor) {
prog->percent_done = percent_done; int scan_no = ((j_decompress_ptr)cinfo)->input_scan_number;
if (total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ", if (scan_no > (int)prog->max_scans) {
prog->pub.completed_passes + prog->completed_extra_passes + 1, fprintf(stderr, "Scan number %d exceeds maximum scans (%u)\n", scan_no,
total_passes, percent_done); prog->max_scans);
} else { exit(EXIT_FAILURE);
fprintf(stderr, "\r %3d%% ", percent_done); }
}
if (prog->report) {
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
int percent_done =
(int)(prog->pub.pass_counter * 100L / prog->pub.pass_limit);
if (percent_done != prog->percent_done) {
prog->percent_done = percent_done;
if (total_passes > 1) {
fprintf(stderr, "\rPass %d/%d: %3d%% ",
prog->pub.completed_passes + prog->completed_extra_passes + 1,
total_passes, percent_done);
} else {
fprintf(stderr, "\r %3d%% ", percent_done);
}
fflush(stderr);
} }
fflush(stderr);
} }
} }
@@ -57,6 +68,8 @@ start_progress_monitor(j_common_ptr cinfo, cd_progress_ptr progress)
progress->pub.progress_monitor = progress_monitor; progress->pub.progress_monitor = progress_monitor;
progress->completed_extra_passes = 0; progress->completed_extra_passes = 0;
progress->total_extra_passes = 0; progress->total_extra_passes = 0;
progress->max_scans = 0;
progress->report = FALSE;
progress->percent_done = -1; progress->percent_done = -1;
cinfo->progress = &progress->pub; cinfo->progress = &progress->pub;
} }
@@ -73,8 +86,6 @@ end_progress_monitor(j_common_ptr cinfo)
} }
} }
#endif
/* /*
* Case-insensitive matching of possibly-abbreviated keyword switches. * Case-insensitive matching of possibly-abbreviated keyword switches.

View File

@@ -3,11 +3,11 @@
* *
* 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 2019 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2017, D. R. Commander. * Copyright (C) 2017, 2019, 2021, D. R. Commander.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README.ijg file.
* *
* This file contains common declarations for the sample applications * This file contains common declarations for the sample applications
* cjpeg and djpeg. It is NOT used by the core JPEG library. * cjpeg and djpeg. It is NOT used by the core JPEG library.
@@ -20,7 +20,6 @@
#include "jerror.h" /* get library error codes too */ #include "jerror.h" /* get library error codes too */
#include "cderror.h" /* get application-specific error codes */ #include "cderror.h" /* get application-specific error codes */
#define JPEG_RAW_READER 0
/* /*
* Object interface for cjpeg's source file decoding modules * Object interface for cjpeg's source file decoding modules
@@ -37,13 +36,9 @@ struct cjpeg_source_struct {
JSAMPARRAY buffer; JSAMPARRAY buffer;
JDIMENSION buffer_height; JDIMENSION buffer_height;
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#if JPEG_RAW_READER JDIMENSION max_pixels;
// For reading JPEG
JSAMPARRAY plane_pointer[4];
#endif #endif
jpeg_saved_marker_ptr marker_list;
}; };
@@ -65,9 +60,9 @@ struct djpeg_dest_struct {
void (*finish_output) (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo); void (*finish_output) (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo);
/* Re-calculate buffer dimensions based on output dimensions (for use with /* Re-calculate buffer dimensions based on output dimensions (for use with
partial image decompression.) If this is NULL, then the output format partial image decompression.) If this is NULL, then the output format
does not support partial image decompression (BMP and RLE, in particular, does not support partial image decompression (BMP, in particular, cannot
cannot support partial decompression because they use an inversion buffer support partial decompression because it uses an inversion buffer to write
to write the image in bottom-up order.) */ the image in bottom-up order.) */
void (*calc_buffer_dimensions) (j_decompress_ptr cinfo, void (*calc_buffer_dimensions) (j_decompress_ptr cinfo,
djpeg_dest_ptr dinfo); djpeg_dest_ptr dinfo);
@@ -96,6 +91,9 @@ struct cdjpeg_progress_mgr {
struct jpeg_progress_mgr pub; /* fields known to JPEG library */ struct jpeg_progress_mgr pub; /* fields known to JPEG library */
int completed_extra_passes; /* extra passes completed */ int completed_extra_passes; /* extra passes completed */
int total_extra_passes; /* total extra */ int total_extra_passes; /* total extra */
JDIMENSION max_scans; /* abort if the number of scans exceeds this
value and the value is non-zero */
boolean report; /* whether or not to report progress */
/* last printed percentage stored here to avoid multiple printouts */ /* last printed percentage stored here to avoid multiple printouts */
int percent_done; int percent_done;
}; };
@@ -105,28 +103,24 @@ typedef struct cdjpeg_progress_mgr *cd_progress_ptr;
/* Module selection routines for I/O modules. */ /* Module selection routines for I/O modules. */
EXTERN(cjpeg_source_ptr) jinit_read_jpeg (j_compress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_png (j_compress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_bmp(j_compress_ptr cinfo, EXTERN(cjpeg_source_ptr) jinit_read_bmp(j_compress_ptr cinfo,
boolean use_inversion_array); boolean use_inversion_array);
EXTERN(djpeg_dest_ptr) jinit_write_bmp(j_decompress_ptr cinfo, boolean is_os2, EXTERN(djpeg_dest_ptr) jinit_write_bmp(j_decompress_ptr cinfo, boolean is_os2,
boolean use_inversion_array); boolean use_inversion_array);
EXTERN(cjpeg_source_ptr) jinit_read_gif(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_gif(j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo, boolean is_lzw);
EXTERN(cjpeg_source_ptr) jinit_read_ppm(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_ppm(j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_ppm(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_ppm(j_decompress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_rle(j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_rle(j_decompress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_targa(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_targa(j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_targa(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_targa(j_decompress_ptr cinfo);
/* cjpeg support routines (in rdswitch.c) */ /* cjpeg support routines (in rdswitch.c) */
EXTERN(boolean) read_quant_tables(j_compress_ptr cinfo, char *filename, EXTERN(boolean) read_quant_tables(j_compress_ptr cinfo, char *filename,
boolean force_baseline); boolean force_baseline);
EXTERN(boolean) read_scan_script(j_compress_ptr cinfo, char *filename); EXTERN(boolean) read_scan_script(j_compress_ptr cinfo, char *filename);
EXTERN(boolean) set_quality_ratings(j_compress_ptr cinfo, char *arg, EXTERN(boolean) set_quality_ratings(j_compress_ptr cinfo, char *arg,
boolean force_baseline); boolean force_baseline);
EXTERN(boolean) set_quant_slots(j_compress_ptr cinfo, char *arg); EXTERN(boolean) set_quant_slots(j_compress_ptr cinfo, char *arg);
EXTERN(boolean) set_sample_factors(j_compress_ptr cinfo, char *arg); EXTERN(boolean) set_sample_factors(j_compress_ptr cinfo, char *arg);
@@ -137,7 +131,7 @@ EXTERN(void) read_color_map(j_decompress_ptr cinfo, FILE *infile);
/* common support routines (in cdjpeg.c) */ /* common support routines (in cdjpeg.c) */
EXTERN(void) start_progress_monitor(j_common_ptr cinfo, EXTERN(void) start_progress_monitor(j_common_ptr cinfo,
cd_progress_ptr progress); cd_progress_ptr progress);
EXTERN(void) end_progress_monitor(j_common_ptr cinfo); EXTERN(void) end_progress_monitor(j_common_ptr cinfo);
EXTERN(boolean) keymatch(char *arg, const char *keyword, int minchars); EXTERN(boolean) keymatch(char *arg, const char *keyword, int minchars);
EXTERN(FILE *) read_stdin(void); EXTERN(FILE *) read_stdin(void);

View File

@@ -6,6 +6,25 @@ reference. Please see ChangeLog.md for information specific to libjpeg-turbo.
CHANGE LOG for Independent JPEG Group's JPEG software CHANGE LOG for Independent JPEG Group's JPEG software
Version 9d 12-Jan-2020
-----------------------
Restore GIF read and write support from libjpeg version 6a.
Thank to Wolfgang Werner (W.W.) Heinz for suggestion.
Add jpegtran -drop option; add options to the crop extension and wipe
to fill the extra area with content from the source image region,
instead of gray out.
Version 9c 14-Jan-2018
-----------------------
jpegtran: add an option to the -wipe switch to fill the region
with the average of adjacent blocks, instead of gray out.
Thank to Caitlyn Feddock and Maddie Ziegler for inspiration.
Version 9b 17-Jan-2016 Version 9b 17-Jan-2016
----------------------- -----------------------
@@ -13,6 +32,13 @@ Document 'f' specifier for jpegtran -crop specification.
Thank to Michele Martone for suggestion. Thank to Michele Martone for suggestion.
Version 9a 19-Jan-2014
-----------------------
Add jpegtran -wipe option and extension for -crop.
Thank to Andrew Senior, David Clunie, and Josef Schmid for suggestion.
Version 9 13-Jan-2013 Version 9 13-Jan-2013
---------------------- ----------------------
@@ -138,11 +164,6 @@ Huffman tables being used.
Huffman tables are checked for validity much more carefully than before. Huffman tables are checked for validity much more carefully than before.
To avoid the Unisys LZW patent, djpeg's GIF output capability has been
changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
has been removed altogether. We're not happy about it either, but there
seems to be no good alternative.
The configure script now supports building libjpeg as a shared library The configure script now supports building libjpeg as a shared library
on many flavors of Unix (all the ones that GNU libtool knows how to on many flavors of Unix (all the ones that GNU libtool knows how to
build shared libraries for). Use "./configure --enable-shared" to build shared libraries for). Use "./configure --enable-shared" to

24
cjpeg.1
View File

@@ -1,4 +1,4 @@
.TH CJPEG 1 "4 November 2020" .TH CJPEG 1 "30 November 2021"
.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
@@ -16,8 +16,7 @@ cjpeg \- compress an image file to a JPEG file
compresses the named image file, or the standard input if no file is compresses the named image file, or the standard input if no file is
named, and produces a JPEG/JFIF file on the standard output. named, and produces a JPEG/JFIF file on the standard output.
The currently supported input file formats are: PPM (PBMPLUS color The currently supported input file formats are: PPM (PBMPLUS color
format), PGM (PBMPLUS grayscale format), BMP, Targa, and RLE (Utah Raster format), PGM (PBMPLUS grayscale format), BMP, GIF, and Targa.
Toolkit format). (RLE is supported only if the URT library is available.)
.SH OPTIONS .SH OPTIONS
All switch names may be abbreviated; for example, All switch names may be abbreviated; for example,
.B \-grayscale .B \-grayscale
@@ -41,11 +40,7 @@ Scale quantization tables to adjust image quality. Quality is 0 (worst) to
100 (best); default is 75. (See below for more info.) 100 (best); default is 75. (See below for more info.)
.TP .TP
.B \-grayscale .B \-grayscale
Create monochrome JPEG file from color input. Be sure to use this switch when Create monochrome JPEG file from color input. By saying
compressing a grayscale BMP file, because
.B cjpeg
isn't bright enough to notice whether a BMP file uses only shades of gray.
By saying
.BR \-grayscale, .BR \-grayscale,
you'll get a smaller JPEG file that takes less time to process. you'll get a smaller JPEG file that takes less time to process.
.TP .TP
@@ -224,6 +219,14 @@ Compress to memory instead of a file. This feature was implemented mainly as a
way of testing the in-memory destination manager (jpeg_mem_dest()), but it is way of testing the in-memory destination manager (jpeg_mem_dest()), but it is
also useful for benchmarking, since it reduces the I/O overhead. also useful for benchmarking, since it reduces the I/O overhead.
.TP .TP
.BI \-report
Report compression progress.
.TP
.BI \-strict
Treat all warnings as fatal. Enabling this option will cause the compressor to
abort if an LZW-compressed GIF input image contains incomplete or corrupt image
data.
.TP
.B \-verbose .B \-verbose
Enable debug printout. More Enable debug printout. More
.BR \-v 's .BR \-v 's
@@ -350,11 +353,6 @@ This file was modified by The libjpeg-turbo Project to include only information
relevant to libjpeg-turbo, to wordsmith certain sections, and to describe relevant to libjpeg-turbo, to wordsmith certain sections, and to describe
features not present in libjpeg. features not present in libjpeg.
.SH ISSUES .SH ISSUES
Support for GIF input files was removed in cjpeg v6b due to concerns over
the Unisys LZW patent. Although this patent expired in 2006, cjpeg still
lacks GIF support, for these historical reasons. (Conversion of GIF files to
JPEG is usually a bad idea anyway, since GIF is a 256-color format.)
.PP
Not all variants of BMP and Targa file formats are supported. Not all variants of BMP and Targa file formats are supported.
.PP .PP
The The

370
cjpeg.c
View File

@@ -5,10 +5,9 @@
* 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.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2010, 2013-2014, 2017, 2020, D. R. Commander. * Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains a command-line user interface for the JPEG compressor. * This file contains a command-line user interface for the JPEG compressor.
* It should work on any system with Unix- or MS-DOS-style command lines. * It should work on any system with Unix- or MS-DOS-style command lines.
@@ -28,25 +27,17 @@
* works regardless of which command line style is used. * works regardless of which command line style is used.
*/ */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef CJPEG_FUZZER
#define JPEG_INTERNALS
#endif
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */ #include "jversion.h" /* for version message */
#include "jconfigint.h" #include "jconfigint.h"
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
extern void *malloc(size_t size);
extern void free(void *ptr);
#endif
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks needs this */
#include <console.h> /* ... and this */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
/* Create the add-on message string table. */ /* Create the add-on message string table. */
@@ -70,9 +61,9 @@ static const char * const cdjpeg_message_table[] = {
* 2) assume we can push back more than one character (works in * 2) assume we can push back more than one character (works in
* some C implementations, but unportable); * some C implementations, but unportable);
* 3) provide our own buffering (breaks input readers that want to use * 3) provide our own buffering (breaks input readers that want to use
* stdio directly, such as the RLE library); * stdio directly);
* or 4) don't put back the data, and modify the input_init methods to assume * or 4) don't put back the data, and modify the input_init methods to assume
* they start reading after the start of file (also breaks RLE library). * they start reading after the start of file.
* #1 is attractive for MS-DOS but is untenable on Unix. * #1 is attractive for MS-DOS but is untenable on Unix.
* *
* The most portable solution for file types that can't be identified by their * The most portable solution for file types that can't be identified by their
@@ -85,8 +76,7 @@ static const char * const cdjpeg_message_table[] = {
*/ */
static boolean is_targa; /* records user -targa switch */ static boolean is_targa; /* records user -targa switch */
static boolean is_jpeg;
static boolean copy_markers;
LOCAL(cjpeg_source_ptr) LOCAL(cjpeg_source_ptr)
select_file_type(j_compress_ptr cinfo, FILE *infile) select_file_type(j_compress_ptr cinfo, FILE *infile)
@@ -119,23 +109,10 @@ select_file_type(j_compress_ptr cinfo, FILE *infile)
case 'P': case 'P':
return jinit_read_ppm(cinfo); return jinit_read_ppm(cinfo);
#endif #endif
#ifdef PNG_SUPPORTED
case 0x89:
copy_markers = TRUE;
return jinit_read_png(cinfo);
#endif
#ifdef RLE_SUPPORTED
case 'R':
return jinit_read_rle(cinfo);
#endif
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
case 0x00: case 0x00:
return jinit_read_targa(cinfo); return jinit_read_targa(cinfo);
#endif #endif
case 0xff:
is_jpeg = TRUE;
copy_markers = TRUE;
return jinit_read_jpeg(cinfo);
default: default:
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
break; break;
@@ -158,6 +135,47 @@ static const char *progname; /* program name for error messages */
static char *icc_filename; /* for -icc switch */ static char *icc_filename; /* for -icc switch */
static char *outfilename; /* for -outfile switch */ static char *outfilename; /* for -outfile switch */
boolean memdst; /* for -memdst switch */ boolean memdst; /* for -memdst switch */
boolean report; /* for -report switch */
boolean strict; /* for -strict switch */
#ifdef CJPEG_FUZZER
#include <setjmp.h>
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
void my_error_exit(j_common_ptr cinfo)
{
struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err;
longjmp(myerr->setjmp_buffer, 1);
}
static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level)
{
if (msg_level < 0)
cinfo->err->num_warnings++;
}
#define HANDLE_ERROR() { \
if (cinfo.global_state > CSTATE_START) { \
if (memdst && outbuffer) \
(*cinfo.dest->term_destination) (&cinfo); \
jpeg_abort_compress(&cinfo); \
} \
jpeg_destroy_compress(&cinfo); \
if (input_file != stdin && input_file != NULL) \
fclose(input_file); \
if (memdst) \
free(outbuffer); \
return EXIT_FAILURE; \
}
#endif
LOCAL(void) LOCAL(void)
@@ -177,32 +195,15 @@ usage(void)
fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
fprintf(stderr, " -rgb Create RGB JPEG file\n"); fprintf(stderr, " -rgb Create RGB JPEG file\n");
#ifdef ENTROPY_OPT_SUPPORTED #ifdef ENTROPY_OPT_SUPPORTED
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression, enabled by default)\n"); fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
#endif #endif
#ifdef C_PROGRESSIVE_SUPPORTED #ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\n"); fprintf(stderr, " -progressive Create progressive JPEG file\n");
#endif #endif
fprintf(stderr, " -baseline Create baseline JPEG file (disable progressive coding)\n");
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#endif #endif
fprintf(stderr, " -revert Revert to standard defaults (instead of mozjpeg defaults)\n");
fprintf(stderr, " -fastcrush Disable progressive scan optimization\n");
fprintf(stderr, " -dc-scan-opt DC scan optimization mode\n");
fprintf(stderr, " - 0 One scan for all components\n");
fprintf(stderr, " - 1 One scan per component (default)\n");
fprintf(stderr, " - 2 Optimize between one scan for all components and one scan for 1st component\n");
fprintf(stderr, " plus one scan for remaining components\n");
fprintf(stderr, " -notrellis Disable trellis optimization\n");
fprintf(stderr, " -trellis-dc Enable trellis optimization of DC coefficients (default)\n");
fprintf(stderr, " -notrellis-dc Disable trellis optimization of DC coefficients\n");
fprintf(stderr, " -tune-psnr Tune trellis optimization for PSNR\n");
fprintf(stderr, " -tune-hvs-psnr Tune trellis optimization for PSNR-HVS (default)\n");
fprintf(stderr, " -tune-ssim Tune trellis optimization for SSIM\n");
fprintf(stderr, " -tune-ms-ssim Tune trellis optimization for MS-SSIM\n");
fprintf(stderr, "Switches for advanced users:\n"); fprintf(stderr, "Switches for advanced users:\n");
fprintf(stderr, " -noovershoot Disable black-on-white deringing via overshoot\n");
fprintf(stderr, " -nojfif Do not write JFIF (reduces size by 18 bytes but breaks standards; no known problems in Web browsers)\n");
#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
@@ -218,14 +219,6 @@ usage(void)
fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n", fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#endif #endif
fprintf(stderr, " -quant-baseline Use 8-bit quantization table entries for baseline JPEG compatibility\n");
fprintf(stderr, " -quant-table N Use predefined quantization table N:\n");
fprintf(stderr, " - 0 JPEG Annex K\n");
fprintf(stderr, " - 1 Flat\n");
fprintf(stderr, " - 2 Custom, tuned for MS-SSIM\n");
fprintf(stderr, " - 3 ImageMagick table by N. Robidoux\n");
fprintf(stderr, " - 4 Custom, tuned for PSNR-HVS\n");
fprintf(stderr, " - 5 Table from paper by Klein, Silverstein and Carney\n");
fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n"); fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n");
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
#ifdef INPUT_SMOOTHING_SUPPORTED #ifdef INPUT_SMOOTHING_SUPPORTED
@@ -236,9 +229,12 @@ usage(void)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
fprintf(stderr, " -memdst Compress to memory instead of file (useful for benchmarking)\n"); fprintf(stderr, " -memdst Compress to memory instead of file (useful for benchmarking)\n");
#endif #endif
fprintf(stderr, " -report Report compression progress\n");
fprintf(stderr, " -strict Treat all warnings as fatal\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, " -version Print version information and exit\n"); fprintf(stderr, " -version Print version information and exit\n");
fprintf(stderr, "Switches for wizards:\n"); fprintf(stderr, "Switches for wizards:\n");
fprintf(stderr, " -baseline Force baseline quantization tables\n");
fprintf(stderr, " -qtables FILE Use quantization tables given in FILE\n"); fprintf(stderr, " -qtables FILE Use quantization tables given in FILE\n");
fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
@@ -274,15 +270,13 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Set up default JPEG parameters. */ /* Set up default JPEG parameters. */
force_baseline = FALSE; /* by default, allow 16-bit quantizers */ force_baseline = FALSE; /* by default, allow 16-bit quantizers */
#ifdef C_PROGRESSIVE_SUPPORTED
simple_progressive = cinfo->num_scans == 0 ? FALSE : TRUE;
#else
simple_progressive = FALSE; simple_progressive = FALSE;
#endif
is_targa = FALSE; is_targa = FALSE;
icc_filename = NULL; icc_filename = NULL;
outfilename = NULL; outfilename = NULL;
memdst = FALSE; memdst = FALSE;
report = FALSE;
strict = FALSE;
cinfo->err->trace_level = 0; cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */ /* Scan command line options, adjust parameters */
@@ -303,9 +297,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Use arithmetic coding. */ /* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED #ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE; cinfo->arith_code = TRUE;
/* No table optimization required for AC */
cinfo->optimize_coding = FALSE;
#else #else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname); progname);
@@ -315,27 +306,19 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "baseline", 1)) { } else if (keymatch(arg, "baseline", 1)) {
/* Force baseline-compatible output (8-bit quantizer values). */ /* Force baseline-compatible output (8-bit quantizer values). */
force_baseline = TRUE; force_baseline = TRUE;
/* Disable multiple scans */
simple_progressive = FALSE;
cinfo->num_scans = 0;
cinfo->scan_info = NULL;
} else if (keymatch(arg, "dct", 2)) { } else if (keymatch(arg, "dct", 2)) {
/* Select DCT algorithm. */ /* Select DCT algorithm. */
if (++argn >= argc) { /* advance to next argument */ if (++argn >= argc) /* advance to next argument */
fprintf(stderr, "%s: missing argument for dct\n", progname);
usage(); usage();
}
if (keymatch(argv[argn], "int", 1)) { if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW; cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) { } else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST; cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) { } else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT; cinfo->dct_method = JDCT_FLOAT;
} else { } else
fprintf(stderr, "%s: invalid argument for dct\n", progname);
usage(); usage();
}
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */ /* Enable debug printouts. */
@@ -357,10 +340,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
PACKAGE_NAME, VERSION, BUILD); PACKAGE_NAME, VERSION, BUILD);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (keymatch(arg, "fastcrush", 4)) { } else if (keymatch(arg, "grayscale", 2) ||
jpeg_c_set_bool_param(cinfo, JBOOLEAN_OPTIMIZE_SCANS, FALSE); keymatch(arg, "greyscale", 2)) {
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */ /* Force a monochrome JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
@@ -368,18 +349,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Force an RGB JPEG file to be generated. */ /* Force an RGB JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_RGB); jpeg_set_colorspace(cinfo, JCS_RGB);
} else if (keymatch(arg, "lambda1", 7)) {
if (++argn >= argc) /* advance to next argument */
usage();
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE1,
atof(argv[argn]));
} else if (keymatch(arg, "lambda2", 7)) {
if (++argn >= argc) /* advance to next argument */
usage();
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE2,
atof(argv[argn]));
} else if (keymatch(arg, "icc", 1)) { } else if (keymatch(arg, "icc", 1)) {
/* Set ICC filename. */ /* Set ICC filename. */
if (++argn >= argc) /* advance to next argument */ if (++argn >= argc) /* advance to next argument */
@@ -399,13 +368,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
lval *= 1000L; lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L; cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "dc-scan-opt", 3)) {
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for dc-scan-opt\n", progname);
usage();
}
jpeg_c_set_int_param(cinfo, JINT_DC_SCAN_OPT_MODE, atoi(argv[argn]));
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
/* Enable entropy parm optimization. */ /* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED #ifdef ENTROPY_OPT_SUPPORTED
@@ -418,10 +380,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "outfile", 4)) { } else if (keymatch(arg, "outfile", 4)) {
/* Set output file name. */ /* Set output file name. */
if (++argn >= argc) { /* advance to next argument */ if (++argn >= argc) /* advance to next argument */
fprintf(stderr, "%s: missing argument for outfile\n", progname);
usage(); usage();
}
outfilename = argv[argn]; /* save it away for later use */ outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "progressive", 1)) { } else if (keymatch(arg, "progressive", 1)) {
@@ -447,10 +407,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "quality", 1)) { } else if (keymatch(arg, "quality", 1)) {
/* Quality ratings (quantization table scaling factors). */ /* Quality ratings (quantization table scaling factors). */
if (++argn >= argc) { /* advance to next argument */ if (++argn >= argc) /* advance to next argument */
fprintf(stderr, "%s: missing argument for quality\n", progname);
usage(); usage();
}
qualityarg = argv[argn]; qualityarg = argv[argn];
} else if (keymatch(arg, "qslots", 2)) { } else if (keymatch(arg, "qslots", 2)) {
@@ -470,22 +428,9 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
qtablefile = argv[argn]; qtablefile = argv[argn];
/* We postpone actually reading the file in case -quality comes later. */ /* We postpone actually reading the file in case -quality comes later. */
} else if (keymatch(arg, "quant-table", 7)) { } else if (keymatch(arg, "report", 3)) {
int val; report = TRUE;
if (++argn >= argc) /* advance to next argument */
usage();
val = atoi(argv[argn]);
jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, val);
if (jpeg_c_get_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX) != val) {
fprintf(stderr, "%s: %d is invalid argument for quant-table\n", progname, val);
usage();
}
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "quant-baseline", 7)) {
/* Force quantization table to meet baseline requirements */
force_baseline = TRUE;
} else if (keymatch(arg, "restart", 1)) { } else if (keymatch(arg, "restart", 1)) {
/* Restart interval in MCU rows (or in MCUs with 'b'). */ /* Restart interval in MCU rows (or in MCUs with 'b'). */
long lval; long lval;
@@ -505,11 +450,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* restart_interval will be computed during startup */ /* restart_interval will be computed during startup */
} }
} else if (keymatch(arg, "revert", 3)) {
/* revert to old JPEG default */
jpeg_c_set_int_param(cinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
jpeg_set_defaults(cinfo);
} else if (keymatch(arg, "sample", 2)) { } else if (keymatch(arg, "sample", 2)) {
/* Set sampling factors. */ /* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */ if (++argn >= argc) /* advance to next argument */
@@ -545,64 +485,14 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
usage(); usage();
cinfo->smoothing_factor = val; cinfo->smoothing_factor = val;
} else if (keymatch(arg, "strict", 2)) {
strict = TRUE;
} else if (keymatch(arg, "targa", 1)) { } else if (keymatch(arg, "targa", 1)) {
/* Input file is Targa format. */ /* Input file is Targa format. */
is_targa = TRUE; is_targa = TRUE;
} else if (keymatch(arg, "notrellis-dc", 11)) {
/* disable trellis quantization */
jpeg_c_set_bool_param(cinfo, JBOOLEAN_TRELLIS_QUANT_DC, FALSE);
} else if (keymatch(arg, "notrellis", 1)) {
/* disable trellis quantization */
jpeg_c_set_bool_param(cinfo, JBOOLEAN_TRELLIS_QUANT, FALSE);
} else if (keymatch(arg, "trellis-dc-ver-weight", 12)) {
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for trellis-dc-ver-weight\n", progname);
usage();
}
jpeg_c_set_float_param(cinfo, JFLOAT_TRELLIS_DELTA_DC_WEIGHT, atof(argv[argn]));
} else if (keymatch(arg, "trellis-dc", 9)) {
/* enable DC trellis quantization */
jpeg_c_set_bool_param(cinfo, JBOOLEAN_TRELLIS_QUANT_DC, TRUE);
} else if (keymatch(arg, "tune-psnr", 6)) {
jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, 1);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE1, 9.0);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE2, 0.0);
jpeg_c_set_bool_param(cinfo, JBOOLEAN_USE_LAMBDA_WEIGHT_TBL, FALSE);
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-ssim", 6)) {
jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, 1);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE1, 11.5);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE2, 12.75);
jpeg_c_set_bool_param(cinfo, JBOOLEAN_USE_LAMBDA_WEIGHT_TBL, FALSE);
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-ms-ssim", 6)) {
jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, 3);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE1, 12.0);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE2, 13.0);
jpeg_c_set_bool_param(cinfo, JBOOLEAN_USE_LAMBDA_WEIGHT_TBL, TRUE);
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-hvs-psnr", 6)) {
jpeg_c_set_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX, 3);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE1, 14.75);
jpeg_c_set_float_param(cinfo, JFLOAT_LAMBDA_LOG_SCALE2, 16.5);
jpeg_c_set_bool_param(cinfo, JBOOLEAN_USE_LAMBDA_WEIGHT_TBL, TRUE);
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "noovershoot", 11)) {
jpeg_c_set_bool_param(cinfo, JBOOLEAN_OVERSHOOT_DERINGING, FALSE);
} else if (keymatch(arg, "nojfif", 6)) {
cinfo->write_JFIF_header = 0;
} else { } else {
fprintf(stderr, "%s: unknown option '%s'\n", progname, arg);
usage(); /* bogus switch */ usage(); /* bogus switch */
} }
} }
@@ -614,28 +504,20 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Set quantization tables for selected quality. */ /* Set quantization tables for selected quality. */
/* Some or all may be overridden if -qtables is present. */ /* Some or all may be overridden if -qtables is present. */
if (qualityarg != NULL) /* process -quality if it was present */ if (qualityarg != NULL) /* process -quality if it was present */
if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) { if (!set_quality_ratings(cinfo, qualityarg, force_baseline))
fprintf(stderr, "%s: can't set quality ratings\n", progname);
usage(); usage();
}
if (qtablefile != NULL) /* process -qtables if it was present */ if (qtablefile != NULL) /* process -qtables if it was present */
if (! read_quant_tables(cinfo, qtablefile, force_baseline)) { if (!read_quant_tables(cinfo, qtablefile, force_baseline))
fprintf(stderr, "%s: can't read qtable file\n", progname);
usage(); usage();
}
if (qslotsarg != NULL) /* process -qslots if it was present */ if (qslotsarg != NULL) /* process -qslots if it was present */
if (!set_quant_slots(cinfo, qslotsarg)) if (!set_quant_slots(cinfo, qslotsarg))
usage(); usage();
/* set_quality_ratings sets default subsampling, so the explicit
subsampling must be set after it */
if (samplearg != NULL) /* process -sample if it was present */ if (samplearg != NULL) /* process -sample if it was present */
if (! set_sample_factors(cinfo, samplearg)) { if (!set_sample_factors(cinfo, samplearg))
fprintf(stderr, "%s: can't set sample factors\n", progname);
usage(); usage();
}
#ifdef C_PROGRESSIVE_SUPPORTED #ifdef C_PROGRESSIVE_SUPPORTED
if (simple_progressive) /* process -progressive; -scans can override */ if (simple_progressive) /* process -progressive; -scans can override */
@@ -653,6 +535,19 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} }
METHODDEF(void)
my_emit_message(j_common_ptr cinfo, int msg_level)
{
if (msg_level < 0) {
/* Treat warning as fatal */
cinfo->err->error_exit(cinfo);
} else {
if (cinfo->err->trace_level >= msg_level)
cinfo->err->output_message(cinfo);
}
}
/* /*
* The main program. * The main program.
*/ */
@@ -661,13 +556,16 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
struct jpeg_compress_struct cinfo; struct jpeg_compress_struct cinfo;
#ifdef CJPEG_FUZZER
struct my_error_mgr myerr;
struct jpeg_error_mgr &jerr = myerr.pub;
#else
struct jpeg_error_mgr jerr; struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress;
#endif #endif
struct cdjpeg_progress_mgr progress;
int file_index; int file_index;
cjpeg_source_ptr src_mgr; cjpeg_source_ptr src_mgr;
FILE *input_file; FILE *input_file = NULL;
FILE *icc_file; FILE *icc_file;
JOCTET *icc_profile = NULL; JOCTET *icc_profile = NULL;
long icc_len = 0; long icc_len = 0;
@@ -676,11 +574,6 @@ main(int argc, char **argv)
unsigned long outsize = 0; unsigned long outsize = 0;
JDIMENSION num_scanlines; JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0]; progname = argv[0];
if (progname == NULL || progname[0] == 0) if (progname == NULL || progname[0] == 0)
progname = "cjpeg"; /* in case C library doesn't provide it */ progname = "cjpeg"; /* in case C library doesn't provide it */
@@ -710,6 +603,9 @@ main(int argc, char **argv)
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
if (strict)
jerr.emit_message = my_emit_message;
#ifdef TWO_FILE_COMMANDLINE #ifdef TWO_FILE_COMMANDLINE
if (!memdst) { if (!memdst) {
/* Must have either -outfile switch or explicit output file name */ /* Must have either -outfile switch or explicit output file name */
@@ -785,21 +681,29 @@ main(int argc, char **argv)
fclose(icc_file); fclose(icc_file);
} }
#ifdef PROGRESS_REPORT #ifdef CJPEG_FUZZER
start_progress_monitor((j_common_ptr)&cinfo, &progress); jerr.error_exit = my_error_exit;
jerr.emit_message = my_emit_message_fuzzer;
if (setjmp(myerr.setjmp_buffer))
HANDLE_ERROR()
#endif #endif
if (report) {
start_progress_monitor((j_common_ptr)&cinfo, &progress);
progress.report = report;
}
/* Figure out the input file format, and set up to read it. */ /* Figure out the input file format, and set up to read it. */
src_mgr = select_file_type(&cinfo, input_file); src_mgr = select_file_type(&cinfo, input_file);
src_mgr->input_file = input_file; src_mgr->input_file = input_file;
#ifdef CJPEG_FUZZER
src_mgr->max_pixels = 1048576;
#endif
/* Read the input file header to obtain file size & colorspace. */ /* Read the input file header to obtain file size & colorspace. */
(*src_mgr->start_input) (&cinfo, src_mgr); (*src_mgr->start_input) (&cinfo, src_mgr);
/* Now that we know input colorspace, fix colorspace-dependent defaults */ /* Now that we know input colorspace, fix colorspace-dependent defaults */
#if JPEG_RAW_READER
if (!is_jpeg)
#endif
jpeg_default_colorspace(&cinfo); jpeg_default_colorspace(&cinfo);
/* Adjust default compression parameters by re-parsing the options */ /* Adjust default compression parameters by re-parsing the options */
@@ -813,53 +717,21 @@ main(int argc, char **argv)
#endif #endif
jpeg_stdio_dest(&cinfo, output_file); jpeg_stdio_dest(&cinfo, output_file);
#ifdef CJPEG_FUZZER
if (setjmp(myerr.setjmp_buffer))
HANDLE_ERROR()
#endif
/* Start compressor */ /* Start compressor */
jpeg_start_compress(&cinfo, TRUE); jpeg_start_compress(&cinfo, TRUE);
/* Copy metadata */
if (copy_markers) {
jpeg_saved_marker_ptr marker;
/* In the current implementation, we don't actually need to examine the
* option flag here; we just copy everything that got saved.
* But to avoid confusion, we do not output JFIF and Adobe APP14 markers
* if the encoder library already wrote one.
*/
for (marker = src_mgr->marker_list; marker != NULL; marker = marker->next) {
if (cinfo.write_JFIF_header &&
marker->marker == JPEG_APP0 &&
marker->data_length >= 5 &&
GETJOCTET(marker->data[0]) == 0x4A &&
GETJOCTET(marker->data[1]) == 0x46 &&
GETJOCTET(marker->data[2]) == 0x49 &&
GETJOCTET(marker->data[3]) == 0x46 &&
GETJOCTET(marker->data[4]) == 0)
continue; /* reject duplicate JFIF */
if (cinfo.write_Adobe_marker &&
marker->marker == JPEG_APP0+14 &&
marker->data_length >= 5 &&
GETJOCTET(marker->data[0]) == 0x41 &&
GETJOCTET(marker->data[1]) == 0x64 &&
GETJOCTET(marker->data[2]) == 0x6F &&
GETJOCTET(marker->data[3]) == 0x62 &&
GETJOCTET(marker->data[4]) == 0x65)
continue; /* reject duplicate Adobe */
jpeg_write_marker(&cinfo, marker->marker, marker->data,
marker->data_length);
}
}
if (icc_profile != NULL) if (icc_profile != NULL)
jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len); jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len);
/* Process data */ /* Process data */
while (cinfo.next_scanline < cinfo.image_height) { while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
#if JPEG_RAW_READER (void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
if (is_jpeg)
(void) jpeg_write_raw_data(&cinfo, src_mgr->plane_pointer, num_scanlines);
else
#endif
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
} }
/* Finish compression and release memory */ /* Finish compression and release memory */
@@ -873,18 +745,18 @@ main(int argc, char **argv)
if (output_file != stdout && output_file != NULL) if (output_file != stdout && output_file != NULL)
fclose(output_file); fclose(output_file);
#ifdef PROGRESS_REPORT if (report)
end_progress_monitor((j_common_ptr)&cinfo); end_progress_monitor((j_common_ptr)&cinfo);
#endif
if (memdst) { if (memdst) {
#ifndef CJPEG_FUZZER
fprintf(stderr, "Compressed size: %lu bytes\n", outsize); fprintf(stderr, "Compressed size: %lu bytes\n", outsize);
#endif
free(outbuffer); free(outbuffer);
} }
free(icc_profile); free(icc_profile);
/* All done. */ /* All done. */
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
return 0; /* suppress no-return-value warnings */
} }

View File

@@ -1,18 +1,6 @@
# This file is included from the top-level CMakeLists.txt. We just store it # This file is included from the top-level CMakeLists.txt. We just store it
# here to avoid cluttering up that file. # here to avoid cluttering up that file.
set(PKGNAME ${CMAKE_PROJECT_NAME} CACHE STRING
"Distribution package name (default: ${CMAKE_PROJECT_NAME})")
set(PKGVENDOR "The ${CMAKE_PROJECT_NAME} Project" CACHE STRING
"Vendor name to be included in distribution package descriptions (default: The ${CMAKE_PROJECT_NAME} Project)")
set(PKGURL "http://www.${CMAKE_PROJECT_NAME}.org" CACHE STRING
"URL of project web site to be included in distribution package descriptions (default: http://www.${CMAKE_PROJECT_NAME}.org)")
set(PKGEMAIL "information@${CMAKE_PROJECT_NAME}.org" CACHE STRING
"E-mail of project maintainer to be included in distribution package descriptions (default: information@${CMAKE_PROJECT_NAME}.org")
set(PKGID "com.${CMAKE_PROJECT_NAME}.${PKGNAME}" CACHE STRING
"Globally unique package identifier (reverse DNS notation) (default: com.${CMAKE_PROJECT_NAME}.${PKGNAME})")
############################################################################### ###############################################################################
# Linux RPM and DEB # Linux RPM and DEB
############################################################################### ###############################################################################
@@ -22,13 +10,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(RPMARCH ${CMAKE_SYSTEM_PROCESSOR}) set(RPMARCH ${CMAKE_SYSTEM_PROCESSOR})
if(CPU_TYPE STREQUAL "x86_64") if(CPU_TYPE STREQUAL "x86_64")
set(DEBARCH amd64) set(DEBARCH amd64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7*")
set(RPMARCH armv7hl)
set(DEBARCH armhf)
elseif(CPU_TYPE STREQUAL "arm64") elseif(CPU_TYPE STREQUAL "arm64")
set(DEBARCH ${CPU_TYPE}) set(DEBARCH ${CPU_TYPE})
elseif(CPU_TYPE STREQUAL "arm") elseif(CPU_TYPE STREQUAL "arm")
if(CMAKE_C_COMPILER MATCHES "gnueabihf") check_c_source_compiles("
#if __ARM_PCS_VFP != 1
#error \"float ABI != hard\"
#endif
int main(void) { return 0; }" HAVE_HARD_FLOAT)
if(HAVE_HARD_FLOAT)
set(RPMARCH armv7hl) set(RPMARCH armv7hl)
set(DEBARCH armhf) set(DEBARCH armhf)
else() else()
@@ -78,12 +68,14 @@ if(WIN32)
if(MSVC) if(MSVC)
set(INST_PLATFORM "Visual C++") set(INST_PLATFORM "Visual C++")
set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-vc) set(INST_ID vc)
set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-${INST_ID})
set(INST_REG_NAME ${CMAKE_PROJECT_NAME}) set(INST_REG_NAME ${CMAKE_PROJECT_NAME})
elseif(MINGW) elseif(MINGW)
set(INST_PLATFORM GCC) set(INST_PLATFORM GCC)
set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-gcc) set(INST_ID gcc)
set(INST_REG_NAME ${CMAKE_PROJECT_NAME}-gcc) set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-${INST_ID})
set(INST_REG_NAME ${CMAKE_PROJECT_NAME}-${INST_ID})
set(INST_DEFS -DGCC) set(INST_DEFS -DGCC)
endif() endif()
@@ -107,66 +99,50 @@ endif()
string(REGEX REPLACE "/" "\\\\" INST_DIR ${CMAKE_INSTALL_PREFIX}) string(REGEX REPLACE "/" "\\\\" INST_DIR ${CMAKE_INSTALL_PREFIX})
configure_file(release/installer.nsi.in installer.nsi @ONLY) configure_file(release/installer.nsi.in installer.nsi @ONLY)
# TODO: It would be nice to eventually switch to CPack and eliminate this mess,
# but not today.
configure_file(win/projectTargets.cmake.in
win/${CMAKE_PROJECT_NAME}Targets.cmake @ONLY)
configure_file(win/${INST_ID}/projectTargets-release.cmake.in
win/${CMAKE_PROJECT_NAME}Targets-release.cmake @ONLY)
if(WITH_JAVA) if(WITH_JAVA)
set(JAVA_DEPEND turbojpeg-java) set(JAVA_DEPEND turbojpeg-java)
endif() endif()
if(WITH_TURBOJPEG)
set(TURBOJPEG_DEPEND turbojpeg turbojpeg-static tjbench)
endif()
add_custom_target(installer add_custom_target(installer
makensis -nocd ${INST_DEFS} installer.nsi makensis -nocd ${INST_DEFS} installer.nsi
DEPENDS jpeg jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom DEPENDS jpeg jpeg-static rdjpgcom wrjpgcom cjpeg djpeg jpegtran
cjpeg djpeg jpegtran tjbench ${JAVA_DEPEND} ${JAVA_DEPEND} ${TURBOJPEG_DEPEND}
SOURCES installer.nsi) SOURCES installer.nsi)
endif() # WIN32 endif() # WIN32
###############################################################################
# Cygwin Package
###############################################################################
if(CYGWIN)
configure_file(release/makecygwinpkg.in pkgscripts/makecygwinpkg)
add_custom_target(cygwinpkg pkgscripts/makecygwinpkg)
endif() # CYGWIN
############################################################################### ###############################################################################
# Mac DMG # Mac DMG
############################################################################### ###############################################################################
if(APPLE) if(APPLE)
set(DEFAULT_OSX_32BIT_BUILD ${CMAKE_SOURCE_DIR}/osxx86) set(ARMV8_BUILD "" CACHE PATH
set(OSX_32BIT_BUILD ${DEFAULT_OSX_32BIT_BUILD} CACHE PATH "Directory containing Armv8 iOS or macOS build to include in universal binaries")
"Directory containing 32-bit (i386) Mac build to include in universal binaries (default: ${DEFAULT_OSX_32BIT_BUILD})")
set(DEFAULT_IOS_ARMV7_BUILD ${CMAKE_SOURCE_DIR}/iosarmv7)
set(IOS_ARMV7_BUILD ${DEFAULT_IOS_ARMV7_BUILD} CACHE PATH
"Directory containing Armv7 iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV7_BUILD})")
set(DEFAULT_IOS_ARMV7S_BUILD ${CMAKE_SOURCE_DIR}/iosarmv7s)
set(IOS_ARMV7S_BUILD ${DEFAULT_IOS_ARMV7S_BUILD} CACHE PATH
"Directory containing Armv7s iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV7S_BUILD})")
set(DEFAULT_IOS_ARMV8_BUILD ${CMAKE_SOURCE_DIR}/iosarmv8)
set(IOS_ARMV8_BUILD ${DEFAULT_IOS_ARMV8_BUILD} CACHE PATH
"Directory containing Armv8 iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV8_BUILD})")
set(OSX_APP_CERT_NAME "" CACHE STRING set(MACOS_APP_CERT_NAME "" CACHE STRING
"Name of the Developer ID Application certificate (in the macOS keychain) that should be used to sign the libjpeg-turbo DMG. Leave this blank to generate an unsigned DMG.") "Name of the Developer ID Application certificate (in the macOS keychain) that should be used to sign the libjpeg-turbo DMG. Leave this blank to generate an unsigned DMG.")
set(OSX_INST_CERT_NAME "" CACHE STRING set(MACOS_INST_CERT_NAME "" CACHE STRING
"Name of the Developer ID Installer certificate (in the macOS keychain) that should be used to sign the libjpeg-turbo installer package. Leave this blank to generate an unsigned package.") "Name of the Developer ID Installer certificate (in the macOS keychain) that should be used to sign the libjpeg-turbo installer package. Leave this blank to generate an unsigned package.")
configure_file(release/makemacpkg.in pkgscripts/makemacpkg) configure_file(release/makemacpkg.in pkgscripts/makemacpkg)
configure_file(release/Distribution.xml.in pkgscripts/Distribution.xml) configure_file(release/Distribution.xml.in pkgscripts/Distribution.xml)
configure_file(release/Welcome.rtf.in pkgscripts/Welcome.rtf)
configure_file(release/uninstall.in pkgscripts/uninstall) configure_file(release/uninstall.in pkgscripts/uninstall)
add_custom_target(dmg pkgscripts/makemacpkg add_custom_target(dmg pkgscripts/makemacpkg
SOURCES pkgscripts/makemacpkg) SOURCES pkgscripts/makemacpkg)
add_custom_target(udmg pkgscripts/makemacpkg universal
SOURCES pkgscripts/makemacpkg)
endif() # APPLE endif() # APPLE
@@ -186,4 +162,15 @@ add_custom_target(tarball pkgscripts/maketarball
configure_file(release/libjpeg.pc.in pkgscripts/libjpeg.pc @ONLY) configure_file(release/libjpeg.pc.in pkgscripts/libjpeg.pc @ONLY)
configure_file(release/libturbojpeg.pc.in pkgscripts/libturbojpeg.pc @ONLY) if(WITH_TURBOJPEG)
configure_file(release/libturbojpeg.pc.in pkgscripts/libturbojpeg.pc @ONLY)
endif()
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
pkgscripts/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
VERSION ${VERSION} COMPATIBILITY AnyNewerVersion)
configure_package_config_file(release/Config.cmake.in
pkgscripts/${CMAKE_PROJECT_NAME}Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME})

View File

@@ -118,6 +118,7 @@
# absolute paths where necessary, using the same logic. # absolute paths where necessary, using the same logic.
#============================================================================= #=============================================================================
# Copyright 2018 Matthias Räncker
# Copyright 2016, 2019 D. R. Commander # Copyright 2016, 2019 D. R. Commander
# Copyright 2016 Dmitry Marakasov # Copyright 2016 Dmitry Marakasov
# Copyright 2016 Roger Leigh # Copyright 2016 Roger Leigh
@@ -259,6 +260,8 @@ if(NOT DEFINED CMAKE_INSTALL_DEFAULT_LIBDIR)
else() else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64") set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64")
elseif(CMAKE_C_COMPILER_ABI MATCHES "ELF X32")
set(CMAKE_INSTALL_DEFAULT_LIBDIR "libx32")
endif() endif()
endif() endif()
endif() endif()

View File

@@ -0,0 +1,13 @@
# This file is included from the top-level CMakeLists.txt. We just store it
# here to avoid cluttering up that file.
set(PKGNAME ${CMAKE_PROJECT_NAME} CACHE STRING
"Distribution package name (default: ${CMAKE_PROJECT_NAME})")
set(PKGVENDOR "The ${CMAKE_PROJECT_NAME} Project" CACHE STRING
"Vendor name to be included in distribution package descriptions (default: The ${CMAKE_PROJECT_NAME} Project)")
set(PKGURL "http://www.${CMAKE_PROJECT_NAME}.org" CACHE STRING
"URL of project web site to be included in distribution package descriptions (default: http://www.${CMAKE_PROJECT_NAME}.org)")
set(PKGEMAIL "information@${CMAKE_PROJECT_NAME}.org" CACHE STRING
"E-mail of project maintainer to be included in distribution package descriptions (default: information@${CMAKE_PROJECT_NAME}.org")
set(PKGID "com.${CMAKE_PROJECT_NAME}.${PKGNAME}" CACHE STRING
"Globally unique package identifier (reverse DNS notation) (default: com.${CMAKE_PROJECT_NAME}.${PKGNAME})")

50
djpeg.1
View File

@@ -15,8 +15,7 @@ djpeg \- decompress a JPEG file to an image file
.B djpeg .B djpeg
decompresses the named JPEG file, or the standard input if no file is named, decompresses the named JPEG file, or the standard input if no file is named,
and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP, and produces an image file on the standard output. PBMPLUS (PPM/PGM), BMP,
GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected. GIF, or Targa output format can be selected.
(RLE is supported only if the URT library is available.)
.SH OPTIONS .SH OPTIONS
All switch names may be abbreviated; for example, All switch names may be abbreviated; for example,
.B \-grayscale .B \-grayscale
@@ -81,9 +80,20 @@ is specified, or if the JPEG file is grayscale; otherwise, 24-bit full-color
format is emitted. format is emitted.
.TP .TP
.B \-gif .B \-gif
Select GIF output format. Since GIF does not support more than 256 colors, Select GIF output format (LZW-compressed). Since GIF does not support more
than 256 colors,
.B \-colors 256 .B \-colors 256
is assumed (unless you specify a smaller number of colors). is assumed (unless you specify a smaller number of colors). If you specify
.BR \-fast,
the default number of colors is 216.
.TP
.B \-gif0
Select GIF output format (uncompressed). Since GIF does not support more than
256 colors,
.B \-colors 256
is assumed (unless you specify a smaller number of colors). If you specify
.BR \-fast,
the default number of colors is 216.
.TP .TP
.B \-os2 .B \-os2
Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is
@@ -100,9 +110,6 @@ PGM is emitted if the JPEG file is grayscale or if
.B \-grayscale .B \-grayscale
is specified; otherwise PPM is emitted. is specified; otherwise PPM is emitted.
.TP .TP
.B \-rle
Select RLE output format. (Requires URT library.)
.TP
.B \-targa .B \-targa
Select Targa output format. Grayscale format is emitted if the JPEG file is Select Targa output format. Grayscale format is emitted if the JPEG file is
grayscale or if grayscale or if
@@ -198,6 +205,19 @@ number. For example,
.B \-max 4m .B \-max 4m
selects 4000000 bytes. If more space is needed, an error will occur. selects 4000000 bytes. If more space is needed, an error will occur.
.TP .TP
.BI \-maxscans " N"
Abort if the JPEG image contains more than
.I N
scans. This feature demonstrates a method by which applications can guard
against denial-of-service attacks instigated by specially-crafted malformed
JPEG images containing numerous scans with missing image data or image data
consisting only of "EOB runs" (a feature of progressive JPEG images that allows
potentially hundreds of thousands of adjoining zero-value pixels to be
represented using only a few bytes.) Attempting to decompress such malformed
JPEG images can cause excessive CPU activity, since the decompressor must fully
process each scan (even if the scan is corrupt) before it can proceed to the
next scan.
.TP
.BI \-outfile " name" .BI \-outfile " name"
Send output image to the named file, not to standard output. Send output image to the named file, not to standard output.
.TP .TP
@@ -205,6 +225,9 @@ Send output image to the named file, not to standard output.
Load input file into memory before decompressing. This feature was implemented Load input file into memory before decompressing. This feature was implemented
mainly as a way of testing the in-memory source manager (jpeg_mem_src().) mainly as a way of testing the in-memory source manager (jpeg_mem_src().)
.TP .TP
.BI \-report
Report decompression progress.
.TP
.BI \-skip " Y0,Y1" .BI \-skip " Y0,Y1"
Decompress all rows of the JPEG image except those between Y0 and Y1 Decompress all rows of the JPEG image except those between Y0 and Y1
(inclusive.) Note that if decompression scaling is being used, then Y0 and Y1 (inclusive.) Note that if decompression scaling is being used, then Y0 and Y1
@@ -218,6 +241,12 @@ decompression scaling is being used, then X, Y, W, and H are relative to the
scaled image dimensions. Currently this option only works with the scaled image dimensions. Currently this option only works with the
PBMPLUS (PPM/PGM), GIF, and Targa output formats. PBMPLUS (PPM/PGM), GIF, and Targa output formats.
.TP .TP
.BI \-strict
Treat all warnings as fatal. This feature also demonstrates a method by which
applications can guard against attacks instigated by specially-crafted
malformed JPEG images. Enabling this option will cause the decompressor to
abort if the JPEG image contains incomplete or corrupt image data.
.TP
.B \-verbose .B \-verbose
Enable debug printout. More Enable debug printout. More
.BR \-v 's .BR \-v 's
@@ -289,10 +318,3 @@ Independent JPEG Group
This file was modified by The libjpeg-turbo Project to include only information This file was modified by The libjpeg-turbo Project to include only information
relevant to libjpeg-turbo, to wordsmith certain sections, and to describe relevant to libjpeg-turbo, to wordsmith certain sections, and to describe
features not present in libjpeg. features not present in libjpeg.
.SH ISSUES
Support for compressed GIF output files was removed in djpeg v6b due to
concerns over the Unisys LZW patent. Although this patent expired in 2006,
djpeg still lacks compressed GIF support, for these historical reasons.
(Conversion of JPEG files to GIF is usually a bad idea anyway, since GIF is a
256-color format.) The uncompressed GIF files that djpeg generates are larger
than they should be, but they are readable by standard GIF decoders.

131
djpeg.c
View File

@@ -3,9 +3,9 @@
* *
* 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 2013 by Guido Vollbeding. * Modified 2013-2019 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2010-2011, 2013-2017, 2020, D. R. Commander. * Copyright (C) 2010-2011, 2013-2017, 2019-2020, 2022, D. R. Commander.
* Copyright (C) 2015, Google, Inc. * Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
@@ -28,26 +28,16 @@
* works regardless of which command line style is used. * works regardless of which command line style is used.
*/ */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */ #include "jversion.h" /* for version message */
#include "jconfigint.h" #include "jconfigint.h"
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare free() */
extern void free(void *ptr);
#endif
#include <ctype.h> /* to declare isprint() */ #include <ctype.h> /* to declare isprint() */
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
#ifdef __MWERKS__
#include <SIOUX.h> /* Metrowerks needs this */
#include <console.h> /* ... and this */
#endif
#ifdef THINK_C
#include <console.h> /* Think declares it here */
#endif
#endif
/* Create the add-on message string table. */ /* Create the add-on message string table. */
@@ -68,10 +58,10 @@ static const char * const cdjpeg_message_table[] = {
typedef enum { typedef enum {
FMT_BMP, /* BMP format (Windows flavor) */ FMT_BMP, /* BMP format (Windows flavor) */
FMT_GIF, /* GIF format */ FMT_GIF, /* GIF format (LZW-compressed) */
FMT_GIF0, /* GIF format (uncompressed) */
FMT_OS2, /* BMP format (OS/2 flavor) */ FMT_OS2, /* BMP format (OS/2 flavor) */
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
FMT_RLE, /* RLE format */
FMT_TARGA, /* Targa format */ FMT_TARGA, /* Targa format */
FMT_TIFF /* TIFF format */ FMT_TIFF /* TIFF format */
} IMAGE_FORMATS; } IMAGE_FORMATS;
@@ -94,11 +84,14 @@ static IMAGE_FORMATS requested_fmt;
static const char *progname; /* program name for error messages */ static const char *progname; /* program name for error messages */
static char *icc_filename; /* for -icc switch */ static char *icc_filename; /* for -icc switch */
JDIMENSION max_scans; /* for -maxscans switch */
static char *outfilename; /* for -outfile switch */ static char *outfilename; /* for -outfile switch */
boolean memsrc; /* for -memsrc switch */ boolean memsrc; /* for -memsrc switch */
boolean report; /* for -report switch */
boolean skip, crop; boolean skip, crop;
JDIMENSION skip_start, skip_end; JDIMENSION skip_start, skip_end;
JDIMENSION crop_x, crop_y, crop_width, crop_height; JDIMENSION crop_x, crop_y, crop_width, crop_height;
boolean strict; /* for -strict switch */
#define INPUT_BUF_SIZE 4096 #define INPUT_BUF_SIZE 4096
@@ -127,8 +120,10 @@ usage(void)
(DEFAULT_FMT == FMT_BMP ? " (default)" : "")); (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
#endif #endif
#ifdef GIF_SUPPORTED #ifdef GIF_SUPPORTED
fprintf(stderr, " -gif Select GIF output format%s\n", fprintf(stderr, " -gif Select GIF output format (LZW-compressed)%s\n",
(DEFAULT_FMT == FMT_GIF ? " (default)" : "")); (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n",
(DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
#endif #endif
#ifdef BMP_SUPPORTED #ifdef BMP_SUPPORTED
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
@@ -138,10 +133,6 @@ usage(void)
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
(DEFAULT_FMT == FMT_PPM ? " (default)" : "")); (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
#endif #endif
#ifdef RLE_SUPPORTED
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
#endif
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Select Targa output format%s\n", fprintf(stderr, " -targa Select Targa output format%s\n",
(DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
@@ -171,14 +162,16 @@ usage(void)
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
#endif #endif
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
fprintf(stderr, " -maxscans N Maximum number of scans to allow in input file\n");
fprintf(stderr, " -outfile name Specify name for output file\n"); fprintf(stderr, " -outfile name Specify name for output file\n");
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
fprintf(stderr, " -memsrc Load input file into memory before decompressing\n"); fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
#endif #endif
fprintf(stderr, " -report Report decompression progress\n");
fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n"); fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n");
fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n"); fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n");
fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n"); fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n");
fprintf(stderr, " -strict Treat all warnings as fatal\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, " -version Print version information and exit\n"); fprintf(stderr, " -version Print version information and exit\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -203,10 +196,13 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
/* Set up default JPEG parameters. */ /* Set up default JPEG parameters. */
requested_fmt = DEFAULT_FMT; /* set default output file format */ requested_fmt = DEFAULT_FMT; /* set default output file format */
icc_filename = NULL; icc_filename = NULL;
max_scans = 0;
outfilename = NULL; outfilename = NULL;
memsrc = FALSE; memsrc = FALSE;
report = FALSE;
skip = FALSE; skip = FALSE;
crop = FALSE; crop = FALSE;
strict = FALSE;
cinfo->err->trace_level = 0; cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */ /* Scan command line options, adjust parameters */
@@ -224,7 +220,7 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
arg++; /* advance past switch marker character */ arg++; /* advance past switch marker character */
if (keymatch(arg, "bmp", 1)) { if (keymatch(arg, "bmp", 1)) {
/* BMP output format. */ /* BMP output format (Windows flavor). */
requested_fmt = FMT_BMP; requested_fmt = FMT_BMP;
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
@@ -295,9 +291,13 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
cinfo->do_fancy_upsampling = FALSE; cinfo->do_fancy_upsampling = FALSE;
} else if (keymatch(arg, "gif", 1)) { } else if (keymatch(arg, "gif", 1)) {
/* GIF output format. */ /* GIF output format (LZW-compressed). */
requested_fmt = FMT_GIF; requested_fmt = FMT_GIF;
} else if (keymatch(arg, "gif0", 4)) {
/* GIF output format (uncompressed). */
requested_fmt = FMT_GIF0;
} else if (keymatch(arg, "grayscale", 2) || } else if (keymatch(arg, "grayscale", 2) ||
keymatch(arg, "greyscale", 2)) { keymatch(arg, "greyscale", 2)) {
/* Force monochrome output. */ /* Force monochrome output. */
@@ -351,6 +351,12 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
lval *= 1000L; lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L; cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "maxscans", 4)) {
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%u", &max_scans) != 1)
usage();
} else if (keymatch(arg, "nosmooth", 3)) { } else if (keymatch(arg, "nosmooth", 3)) {
/* Suppress fancy upsampling */ /* Suppress fancy upsampling */
cinfo->do_fancy_upsampling = FALSE; cinfo->do_fancy_upsampling = FALSE;
@@ -383,9 +389,8 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
/* PPM/PGM output format. */ /* PPM/PGM output format. */
requested_fmt = FMT_PPM; requested_fmt = FMT_PPM;
} else if (keymatch(arg, "rle", 1)) { } else if (keymatch(arg, "report", 2)) {
/* RLE output format. */ report = TRUE;
requested_fmt = FMT_RLE;
} else if (keymatch(arg, "scale", 2)) { } else if (keymatch(arg, "scale", 2)) {
/* Scale the output image by a fraction M/N. */ /* Scale the output image by a fraction M/N. */
@@ -413,6 +418,9 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
usage(); usage();
crop = TRUE; crop = TRUE;
} else if (keymatch(arg, "strict", 2)) {
strict = TRUE;
} else if (keymatch(arg, "targa", 1)) { } else if (keymatch(arg, "targa", 1)) {
/* Targa output format. */ /* Targa output format. */
requested_fmt = FMT_TARGA; requested_fmt = FMT_TARGA;
@@ -444,7 +452,7 @@ jpeg_getc(j_decompress_ptr cinfo)
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
} }
datasrc->bytes_in_buffer--; datasrc->bytes_in_buffer--;
return GETJOCTET(*datasrc->next_input_byte++); return *datasrc->next_input_byte++;
} }
@@ -499,6 +507,19 @@ print_text_marker(j_decompress_ptr cinfo)
} }
METHODDEF(void)
my_emit_message(j_common_ptr cinfo, int msg_level)
{
if (msg_level < 0) {
/* Treat warning as fatal */
cinfo->err->error_exit(cinfo);
} else {
if (cinfo->err->trace_level >= msg_level)
cinfo->err->output_message(cinfo);
}
}
/* /*
* The main program. * The main program.
*/ */
@@ -508,9 +529,7 @@ main(int argc, char **argv)
{ {
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr; struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
struct cdjpeg_progress_mgr progress; struct cdjpeg_progress_mgr progress;
#endif
int file_index; int file_index;
djpeg_dest_ptr dest_mgr = NULL; djpeg_dest_ptr dest_mgr = NULL;
FILE *input_file; FILE *input_file;
@@ -521,11 +540,6 @@ main(int argc, char **argv)
#endif #endif
JDIMENSION num_scanlines; JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0]; progname = argv[0];
if (progname == NULL || progname[0] == 0) if (progname == NULL || progname[0] == 0)
progname = "djpeg"; /* in case C library doesn't provide it */ progname = "djpeg"; /* in case C library doesn't provide it */
@@ -557,6 +571,9 @@ main(int argc, char **argv)
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
if (strict)
jerr.emit_message = my_emit_message;
#ifdef TWO_FILE_COMMANDLINE #ifdef TWO_FILE_COMMANDLINE
/* Must have either -outfile switch or explicit output file name */ /* Must have either -outfile switch or explicit output file name */
if (outfilename == NULL) { if (outfilename == NULL) {
@@ -603,9 +620,11 @@ main(int argc, char **argv)
output_file = write_stdout(); output_file = write_stdout();
} }
#ifdef PROGRESS_REPORT if (report || max_scans != 0) {
start_progress_monitor((j_common_ptr)&cinfo, &progress); start_progress_monitor((j_common_ptr)&cinfo, &progress);
#endif progress.report = report;
progress.max_scans = max_scans;
}
/* Specify data source for decompression */ /* Specify data source for decompression */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
@@ -617,7 +636,7 @@ main(int argc, char **argv)
fprintf(stderr, "%s: memory allocation failure\n", progname); fprintf(stderr, "%s: memory allocation failure\n", progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
nbytes = JFREAD(input_file, &inbuffer[insize], INPUT_BUF_SIZE); nbytes = fread(&inbuffer[insize], 1, INPUT_BUF_SIZE, input_file);
if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) { if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
if (file_index < argc) if (file_index < argc)
fprintf(stderr, "%s: can't read from %s\n", progname, fprintf(stderr, "%s: can't read from %s\n", progname,
@@ -653,7 +672,10 @@ main(int argc, char **argv)
#endif #endif
#ifdef GIF_SUPPORTED #ifdef GIF_SUPPORTED
case FMT_GIF: case FMT_GIF:
dest_mgr = jinit_write_gif(&cinfo); dest_mgr = jinit_write_gif(&cinfo, TRUE);
break;
case FMT_GIF0:
dest_mgr = jinit_write_gif(&cinfo, FALSE);
break; break;
#endif #endif
#ifdef PPM_SUPPORTED #ifdef PPM_SUPPORTED
@@ -661,11 +683,6 @@ main(int argc, char **argv)
dest_mgr = jinit_write_ppm(&cinfo); dest_mgr = jinit_write_ppm(&cinfo);
break; break;
#endif #endif
#ifdef RLE_SUPPORTED
case FMT_RLE:
dest_mgr = jinit_write_rle(&cinfo);
break;
#endif
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
case FMT_TARGA: case FMT_TARGA:
dest_mgr = jinit_write_targa(&cinfo); dest_mgr = jinit_write_targa(&cinfo);
@@ -689,7 +706,7 @@ main(int argc, char **argv)
* that skip_start <= skip_end. * that skip_start <= skip_end.
*/ */
if (skip_end > cinfo.output_height - 1) { if (skip_end > cinfo.output_height - 1) {
fprintf(stderr, "%s: skip region exceeds image height %d\n", progname, fprintf(stderr, "%s: skip region exceeds image height %u\n", progname,
cinfo.output_height); cinfo.output_height);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -710,7 +727,7 @@ main(int argc, char **argv)
} }
if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) != if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
skip_end - skip_start + 1) { skip_end - skip_start + 1) {
fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
progname, tmp, skip_end - skip_start + 1); progname, tmp, skip_end - skip_start + 1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -729,7 +746,7 @@ main(int argc, char **argv)
*/ */
if (crop_x + crop_width > cinfo.output_width || if (crop_x + crop_width > cinfo.output_width ||
crop_y + crop_height > cinfo.output_height) { crop_y + crop_height > cinfo.output_height) {
fprintf(stderr, "%s: crop dimensions exceed image dimensions %d x %d\n", fprintf(stderr, "%s: crop dimensions exceed image dimensions %u x %u\n",
progname, cinfo.output_width, cinfo.output_height); progname, cinfo.output_width, cinfo.output_height);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -750,7 +767,7 @@ main(int argc, char **argv)
/* Process data */ /* Process data */
if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) { if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) {
fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
progname, tmp, crop_y); progname, tmp, crop_y);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -763,7 +780,7 @@ main(int argc, char **argv)
jpeg_skip_scanlines(&cinfo, jpeg_skip_scanlines(&cinfo,
cinfo.output_height - crop_y - crop_height)) != cinfo.output_height - crop_y - crop_height)) !=
cinfo.output_height - crop_y - crop_height) { cinfo.output_height - crop_y - crop_height) {
fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n", fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
progname, tmp, cinfo.output_height - crop_y - crop_height); progname, tmp, cinfo.output_height - crop_y - crop_height);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -781,12 +798,11 @@ main(int argc, char **argv)
} }
} }
#ifdef PROGRESS_REPORT
/* Hack: count final pass as done in case finish_output does an extra pass. /* Hack: count final pass as done in case finish_output does an extra pass.
* The library won't have updated completed_passes. * The library won't have updated completed_passes.
*/ */
progress.pub.completed_passes = progress.pub.total_passes; if (report || max_scans != 0)
#endif progress.pub.completed_passes = progress.pub.total_passes;
if (icc_filename != NULL) { if (icc_filename != NULL) {
FILE *icc_file; FILE *icc_file;
@@ -825,9 +841,8 @@ main(int argc, char **argv)
if (output_file != stdout) if (output_file != stdout)
fclose(output_file); fclose(output_file);
#ifdef PROGRESS_REPORT if (report || max_scans != 0)
end_progress_monitor((j_common_ptr)&cinfo); end_progress_monitor((j_common_ptr)&cinfo);
#endif
if (memsrc) if (memsrc)
free(inbuffer); free(inbuffer);

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>
@@ -122,6 +122,9 @@ Macros</h2></td></tr>
<tr class="memitem:ga43b426750b46190a25d34a67ef76df1b"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b">TJFLAG_PROGRESSIVE</a></td></tr> <tr class="memitem:ga43b426750b46190a25d34a67ef76df1b"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b">TJFLAG_PROGRESSIVE</a></td></tr>
<tr class="memdesc:ga43b426750b46190a25d34a67ef76df1b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use progressive entropy coding in JPEG images generated by the compression and transform functions. <a href="group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b">More...</a><br /></td></tr> <tr class="memdesc:ga43b426750b46190a25d34a67ef76df1b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use progressive entropy coding in JPEG images generated by the compression and transform functions. <a href="group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b">More...</a><br /></td></tr>
<tr class="separator:ga43b426750b46190a25d34a67ef76df1b"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga43b426750b46190a25d34a67ef76df1b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga163e6482dc5096831feef9c79ff3f805"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga163e6482dc5096831feef9c79ff3f805">TJFLAG_LIMITSCANS</a></td></tr>
<tr class="memdesc:ga163e6482dc5096831feef9c79ff3f805"><td class="mdescLeft">&#160;</td><td class="mdescRight">Limit the number of progressive JPEG scans that the decompression and transform functions will process. <a href="group___turbo_j_p_e_g.html#ga163e6482dc5096831feef9c79ff3f805">More...</a><br /></td></tr>
<tr class="separator:ga163e6482dc5096831feef9c79ff3f805"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga79bde1b4a3e2351e00887e47781b966e"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga79bde1b4a3e2351e00887e47781b966e">TJ_NUMERR</a></td></tr> <tr class="memitem:ga79bde1b4a3e2351e00887e47781b966e"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga79bde1b4a3e2351e00887e47781b966e">TJ_NUMERR</a></td></tr>
<tr class="memdesc:ga79bde1b4a3e2351e00887e47781b966e"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of error codes. <a href="group___turbo_j_p_e_g.html#ga79bde1b4a3e2351e00887e47781b966e">More...</a><br /></td></tr> <tr class="memdesc:ga79bde1b4a3e2351e00887e47781b966e"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of error codes. <a href="group___turbo_j_p_e_g.html#ga79bde1b4a3e2351e00887e47781b966e">More...</a><br /></td></tr>
<tr class="separator:ga79bde1b4a3e2351e00887e47781b966e"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga79bde1b4a3e2351e00887e47781b966e"><td class="memSeparator" colspan="2">&#160;</td></tr>
@@ -270,7 +273,7 @@ Functions</h2></td></tr>
<tr class="memdesc:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a TurboJPEG decompressor instance. <a href="group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3">More...</a><br /></td></tr> <tr class="memdesc:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a TurboJPEG decompressor instance. <a href="group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3">More...</a><br /></td></tr>
<tr class="separator:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga0595681096bba7199cc6f3533cb25f77"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77">tjDecompressHeader3</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, int *jpegSubsamp, int *jpegColorspace)</td></tr> <tr class="memitem:ga0595681096bba7199cc6f3533cb25f77"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77">tjDecompressHeader3</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, int *jpegSubsamp, int *jpegColorspace)</td></tr>
<tr class="memdesc:ga0595681096bba7199cc6f3533cb25f77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieve information about a JPEG image without decompressing it. <a href="group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77">More...</a><br /></td></tr> <tr class="memdesc:ga0595681096bba7199cc6f3533cb25f77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieve information about a JPEG image without decompressing it, or prime the decompressor with quantization and Huffman tables. <a href="group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77">More...</a><br /></td></tr>
<tr class="separator:ga0595681096bba7199cc6f3533cb25f77"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga0595681096bba7199cc6f3533cb25f77"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gac3854476006b10787bd128f7ede48057"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="structtjscalingfactor.html">tjscalingfactor</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057">tjGetScalingFactors</a> (int *numscalingfactors)</td></tr> <tr class="memitem:gac3854476006b10787bd128f7ede48057"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="structtjscalingfactor.html">tjscalingfactor</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057">tjGetScalingFactors</a> (int *numscalingfactors)</td></tr>
<tr class="memdesc:gac3854476006b10787bd128f7ede48057"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a list of fractional scaling factors that the JPEG decompressor in this implementation of TurboJPEG supports. <a href="group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057">More...</a><br /></td></tr> <tr class="memdesc:gac3854476006b10787bd128f7ede48057"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a list of fractional scaling factors that the JPEG decompressor in this implementation of TurboJPEG supports. <a href="group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057">More...</a><br /></td></tr>
@@ -497,6 +500,23 @@ YUV Image Format Notes</h2>
<p>When decompressing an image that was compressed using chrominance subsampling, use the fastest chrominance upsampling algorithm available in the underlying codec. </p> <p>When decompressing an image that was compressed using chrominance subsampling, use the fastest chrominance upsampling algorithm available in the underlying codec. </p>
<p>The default is to use smooth upsampling, which creates a smooth transition between neighboring chrominance components in order to reduce upsampling artifacts in the decompressed image. </p> <p>The default is to use smooth upsampling, which creates a smooth transition between neighboring chrominance components in order to reduce upsampling artifacts in the decompressed image. </p>
</div>
</div>
<a id="ga163e6482dc5096831feef9c79ff3f805"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga163e6482dc5096831feef9c79ff3f805">&#9670;&nbsp;</a></span>TJFLAG_LIMITSCANS</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">#define TJFLAG_LIMITSCANS</td>
</tr>
</table>
</div><div class="memdoc">
<p>Limit the number of progressive JPEG scans that the decompression and transform functions will process. </p>
<p>If a progressive JPEG image contains an unreasonably large number of scans, then this flag will cause the decompression and transform functions to return an error. The primary purpose of this is to allow security-critical applications to guard against an exploit of the progressive JPEG format described in <a href="https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf" target="_blank">this report</a>. </p>
</div> </div>
</div> </div>
<a id="ga8808d403c68b62aaa58a4c1e58e98963"></a> <a id="ga8808d403c68b62aaa58a4c1e58e98963"></a>
@@ -1705,16 +1725,16 @@ If you choose option 1, <code>*jpegSize</code> should be set to the size of your
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
<p>Retrieve information about a JPEG image without decompressing it. </p> <p>Retrieve information about a JPEG image without decompressing it, or prime the decompressor with quantization and Huffman tables. </p>
<dl class="params"><dt>Parameters</dt><dd> <dl class="params"><dt>Parameters</dt><dd>
<table class="params"> <table class="params">
<tr><td class="paramname">handle</td><td>a handle to a TurboJPEG decompressor or transformer instance</td></tr> <tr><td class="paramname">handle</td><td>a handle to a TurboJPEG decompressor or transformer instance</td></tr>
<tr><td class="paramname">jpegBuf</td><td>pointer to a buffer containing a JPEG image</td></tr> <tr><td class="paramname">jpegBuf</td><td>pointer to a buffer containing a JPEG image or an "abbreviated table specification" (AKA "tables-only") datastream. Passing a tables-only datastream to this function primes the decompressor with quantization and Huffman tables that can be used when decompressing subsequent "abbreviated image" datastreams. This is useful, for instance, when decompressing video streams in which all frames share the same quantization and Huffman tables.</td></tr>
<tr><td class="paramname">jpegSize</td><td>size of the JPEG image (in bytes)</td></tr> <tr><td class="paramname">jpegSize</td><td>size of the JPEG image or tables-only datastream (in bytes)</td></tr>
<tr><td class="paramname">width</td><td>pointer to an integer variable that will receive the width (in pixels) of the JPEG image</td></tr> <tr><td class="paramname">width</td><td>pointer to an integer variable that will receive the width (in pixels) of the JPEG image. If <code>jpegBuf</code> points to a tables-only datastream, then <code>width</code> is ignored.</td></tr>
<tr><td class="paramname">height</td><td>pointer to an integer variable that will receive the height (in pixels) of the JPEG image</td></tr> <tr><td class="paramname">height</td><td>pointer to an integer variable that will receive the height (in pixels) of the JPEG image. If <code>jpegBuf</code> points to a tables-only datastream, then <code>height</code> is ignored.</td></tr>
<tr><td class="paramname">jpegSubsamp</td><td>pointer to an integer variable that will receive the level of chrominance subsampling used when the JPEG image was compressed (see <a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">Chrominance subsampling options</a>.)</td></tr> <tr><td class="paramname">jpegSubsamp</td><td>pointer to an integer variable that will receive the level of chrominance subsampling used when the JPEG image was compressed (see <a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">Chrominance subsampling options</a>.) If <code>jpegBuf</code> points to a tables-only datastream, then <code>jpegSubsamp</code> is ignored.</td></tr>
<tr><td class="paramname">jpegColorspace</td><td>pointer to an integer variable that will receive one of the JPEG colorspace constants, indicating the colorspace of the JPEG image (see <a class="el" href="group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720">JPEG colorspaces</a>.)</td></tr> <tr><td class="paramname">jpegColorspace</td><td>pointer to an integer variable that will receive one of the JPEG colorspace constants, indicating the colorspace of the JPEG image (see <a class="el" href="group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720">JPEG colorspaces</a>.) If <code>jpegBuf</code> points to a tables-only datastream, then <code>jpegColorspace</code> is ignored.</td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -35,68 +35,69 @@ var searchData=
['tjflag_5fbottomup_40',['TJFLAG_BOTTOMUP',['../group___turbo_j_p_e_g.html#ga72ecf4ebe6eb702d3c6f5ca27455e1ec',1,'turbojpeg.h']]], ['tjflag_5fbottomup_40',['TJFLAG_BOTTOMUP',['../group___turbo_j_p_e_g.html#ga72ecf4ebe6eb702d3c6f5ca27455e1ec',1,'turbojpeg.h']]],
['tjflag_5ffastdct_41',['TJFLAG_FASTDCT',['../group___turbo_j_p_e_g.html#gaabce235db80d3f698b27f36cbd453da2',1,'turbojpeg.h']]], ['tjflag_5ffastdct_41',['TJFLAG_FASTDCT',['../group___turbo_j_p_e_g.html#gaabce235db80d3f698b27f36cbd453da2',1,'turbojpeg.h']]],
['tjflag_5ffastupsample_42',['TJFLAG_FASTUPSAMPLE',['../group___turbo_j_p_e_g.html#ga4ee4506c81177a06f77e2504a22efd2d',1,'turbojpeg.h']]], ['tjflag_5ffastupsample_42',['TJFLAG_FASTUPSAMPLE',['../group___turbo_j_p_e_g.html#ga4ee4506c81177a06f77e2504a22efd2d',1,'turbojpeg.h']]],
['tjflag_5fnorealloc_43',['TJFLAG_NOREALLOC',['../group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963',1,'turbojpeg.h']]], ['tjflag_5flimitscans_43',['TJFLAG_LIMITSCANS',['../group___turbo_j_p_e_g.html#ga163e6482dc5096831feef9c79ff3f805',1,'turbojpeg.h']]],
['tjflag_5fprogressive_44',['TJFLAG_PROGRESSIVE',['../group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b',1,'turbojpeg.h']]], ['tjflag_5fnorealloc_44',['TJFLAG_NOREALLOC',['../group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963',1,'turbojpeg.h']]],
['tjflag_5fstoponwarning_45',['TJFLAG_STOPONWARNING',['../group___turbo_j_p_e_g.html#ga519cfa4ef6c18d9e5b455fdf59306a3a',1,'turbojpeg.h']]], ['tjflag_5fprogressive_45',['TJFLAG_PROGRESSIVE',['../group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b',1,'turbojpeg.h']]],
['tjfree_46',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], ['tjflag_5fstoponwarning_46',['TJFLAG_STOPONWARNING',['../group___turbo_j_p_e_g.html#ga519cfa4ef6c18d9e5b455fdf59306a3a',1,'turbojpeg.h']]],
['tjgeterrorcode_47',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], ['tjfree_47',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]],
['tjgeterrorstr2_48',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], ['tjgeterrorcode_48',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]],
['tjgetscalingfactors_49',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], ['tjgeterrorstr2_49',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]],
['tjgreenoffset_50',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], ['tjgetscalingfactors_50',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]],
['tjhandle_51',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], ['tjgreenoffset_51',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]],
['tjinitcompress_52',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], ['tjhandle_52',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]],
['tjinitdecompress_53',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], ['tjinitcompress_53',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]],
['tjinittransform_54',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], ['tjinitdecompress_54',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]],
['tjloadimage_55',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], ['tjinittransform_55',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]],
['tjmcuheight_56',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], ['tjloadimage_56',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]],
['tjmcuwidth_57',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], ['tjmcuheight_57',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]],
['tjpad_58',['TJPAD',['../group___turbo_j_p_e_g.html#ga0aba955473315e405295d978f0c16511',1,'turbojpeg.h']]], ['tjmcuwidth_58',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]],
['tjpf_59',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], ['tjpad_59',['TJPAD',['../group___turbo_j_p_e_g.html#ga0aba955473315e405295d978f0c16511',1,'turbojpeg.h']]],
['tjpf_5fabgr_60',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], ['tjpf_60',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]],
['tjpf_5fargb_61',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], ['tjpf_5fabgr_61',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]],
['tjpf_5fbgr_62',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], ['tjpf_5fargb_62',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]],
['tjpf_5fbgra_63',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], ['tjpf_5fbgr_63',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]],
['tjpf_5fbgrx_64',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], ['tjpf_5fbgra_64',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]],
['tjpf_5fcmyk_65',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], ['tjpf_5fbgrx_65',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]],
['tjpf_5fgray_66',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], ['tjpf_5fcmyk_66',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]],
['tjpf_5frgb_67',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], ['tjpf_5fgray_67',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]],
['tjpf_5frgba_68',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], ['tjpf_5frgb_68',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]],
['tjpf_5frgbx_69',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], ['tjpf_5frgba_69',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]],
['tjpf_5funknown_70',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], ['tjpf_5frgbx_70',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]],
['tjpf_5fxbgr_71',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], ['tjpf_5funknown_71',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]],
['tjpf_5fxrgb_72',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], ['tjpf_5fxbgr_72',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]],
['tjpixelsize_73',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], ['tjpf_5fxrgb_73',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]],
['tjplaneheight_74',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], ['tjpixelsize_74',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]],
['tjplanesizeyuv_75',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], ['tjplaneheight_75',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]],
['tjplanewidth_76',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], ['tjplanesizeyuv_76',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]],
['tjredoffset_77',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]], ['tjplanewidth_77',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]],
['tjregion_78',['tjregion',['../structtjregion.html',1,'']]], ['tjredoffset_78',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]],
['tjsamp_79',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], ['tjregion_79',['tjregion',['../structtjregion.html',1,'']]],
['tjsamp_5f411_80',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], ['tjsamp_80',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]],
['tjsamp_5f420_81',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], ['tjsamp_5f411_81',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]],
['tjsamp_5f422_82',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], ['tjsamp_5f420_82',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]],
['tjsamp_5f440_83',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], ['tjsamp_5f422_83',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]],
['tjsamp_5f444_84',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], ['tjsamp_5f440_84',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]],
['tjsamp_5fgray_85',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], ['tjsamp_5f444_85',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]],
['tjsaveimage_86',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], ['tjsamp_5fgray_86',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]],
['tjscaled_87',['TJSCALED',['../group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df',1,'turbojpeg.h']]], ['tjsaveimage_87',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]],
['tjscalingfactor_88',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], ['tjscaled_88',['TJSCALED',['../group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df',1,'turbojpeg.h']]],
['tjtransform_89',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'tjtransform():&#160;turbojpeg.h'],['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'tjTransform(tjhandle handle, const unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags):&#160;turbojpeg.h']]], ['tjscalingfactor_89',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]],
['tjxop_90',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]], ['tjtransform_90',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'tjtransform():&#160;turbojpeg.h'],['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'tjTransform(tjhandle handle, const unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags):&#160;turbojpeg.h']]],
['tjxop_5fhflip_91',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], ['tjxop_91',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]],
['tjxop_5fnone_92',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], ['tjxop_5fhflip_92',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]],
['tjxop_5frot180_93',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], ['tjxop_5fnone_93',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]],
['tjxop_5frot270_94',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], ['tjxop_5frot180_94',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]],
['tjxop_5frot90_95',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], ['tjxop_5frot270_95',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]],
['tjxop_5ftranspose_96',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], ['tjxop_5frot90_96',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]],
['tjxop_5ftransverse_97',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], ['tjxop_5ftranspose_97',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]],
['tjxop_5fvflip_98',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]], ['tjxop_5ftransverse_98',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]],
['tjxopt_5fcopynone_99',['TJXOPT_COPYNONE',['../group___turbo_j_p_e_g.html#ga153b468cfb905d0de61706c838986fe8',1,'turbojpeg.h']]], ['tjxop_5fvflip_99',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]],
['tjxopt_5fcrop_100',['TJXOPT_CROP',['../group___turbo_j_p_e_g.html#ga9c771a757fc1294add611906b89ab2d2',1,'turbojpeg.h']]], ['tjxopt_5fcopynone_100',['TJXOPT_COPYNONE',['../group___turbo_j_p_e_g.html#ga153b468cfb905d0de61706c838986fe8',1,'turbojpeg.h']]],
['tjxopt_5fgray_101',['TJXOPT_GRAY',['../group___turbo_j_p_e_g.html#ga3acee7b48ade1b99e5588736007c2589',1,'turbojpeg.h']]], ['tjxopt_5fcrop_101',['TJXOPT_CROP',['../group___turbo_j_p_e_g.html#ga9c771a757fc1294add611906b89ab2d2',1,'turbojpeg.h']]],
['tjxopt_5fnooutput_102',['TJXOPT_NOOUTPUT',['../group___turbo_j_p_e_g.html#gafbf992bbf6e006705886333703ffab31',1,'turbojpeg.h']]], ['tjxopt_5fgray_102',['TJXOPT_GRAY',['../group___turbo_j_p_e_g.html#ga3acee7b48ade1b99e5588736007c2589',1,'turbojpeg.h']]],
['tjxopt_5fperfect_103',['TJXOPT_PERFECT',['../group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00',1,'turbojpeg.h']]], ['tjxopt_5fnooutput_103',['TJXOPT_NOOUTPUT',['../group___turbo_j_p_e_g.html#gafbf992bbf6e006705886333703ffab31',1,'turbojpeg.h']]],
['tjxopt_5fprogressive_104',['TJXOPT_PROGRESSIVE',['../group___turbo_j_p_e_g.html#gad2371c80674584ecc1a7d75e564cf026',1,'turbojpeg.h']]], ['tjxopt_5fperfect_104',['TJXOPT_PERFECT',['../group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00',1,'turbojpeg.h']]],
['tjxopt_5ftrim_105',['TJXOPT_TRIM',['../group___turbo_j_p_e_g.html#ga319826b7eb1583c0595bbe7b95428709',1,'turbojpeg.h']]], ['tjxopt_5fprogressive_105',['TJXOPT_PROGRESSIVE',['../group___turbo_j_p_e_g.html#gad2371c80674584ecc1a7d75e564cf026',1,'turbojpeg.h']]],
['turbojpeg_106',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] ['tjxopt_5ftrim_106',['TJXOPT_TRIM',['../group___turbo_j_p_e_g.html#ga319826b7eb1583c0595bbe7b95428709',1,'turbojpeg.h']]],
['turbojpeg_107',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['w_107',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] ['w_108',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['x_108',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] ['x_109',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['y_109',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] ['y_110',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]]
]; ];

View File

@@ -1,6 +1,6 @@
var searchData= var searchData=
[ [
['tjregion_110',['tjregion',['../structtjregion.html',1,'']]], ['tjregion_111',['tjregion',['../structtjregion.html',1,'']]],
['tjscalingfactor_111',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]], ['tjscalingfactor_112',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]],
['tjtransform_112',['tjtransform',['../structtjtransform.html',1,'']]] ['tjtransform_113',['tjtransform',['../structtjtransform.html',1,'']]]
]; ];

View File

@@ -1,8 +1,8 @@
var searchData= var searchData=
[ [
['tjcs_161',['TJCS',['../group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720',1,'turbojpeg.h']]], ['tjcs_162',['TJCS',['../group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720',1,'turbojpeg.h']]],
['tjerr_162',['TJERR',['../group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe',1,'turbojpeg.h']]], ['tjerr_163',['TJERR',['../group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe',1,'turbojpeg.h']]],
['tjpf_163',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]], ['tjpf_164',['TJPF',['../group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a',1,'turbojpeg.h']]],
['tjsamp_164',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]], ['tjsamp_165',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]],
['tjxop_165',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]] ['tjxop_166',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]]
]; ];

View File

@@ -1,37 +1,37 @@
var searchData= var searchData=
[ [
['tjcs_5fcmyk_166',['TJCS_CMYK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53',1,'turbojpeg.h']]], ['tjcs_5fcmyk_167',['TJCS_CMYK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53',1,'turbojpeg.h']]],
['tjcs_5fgray_167',['TJCS_GRAY',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a',1,'turbojpeg.h']]], ['tjcs_5fgray_168',['TJCS_GRAY',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a',1,'turbojpeg.h']]],
['tjcs_5frgb_168',['TJCS_RGB',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555',1,'turbojpeg.h']]], ['tjcs_5frgb_169',['TJCS_RGB',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555',1,'turbojpeg.h']]],
['tjcs_5fycbcr_169',['TJCS_YCbCr',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75',1,'turbojpeg.h']]], ['tjcs_5fycbcr_170',['TJCS_YCbCr',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75',1,'turbojpeg.h']]],
['tjcs_5fycck_170',['TJCS_YCCK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e',1,'turbojpeg.h']]], ['tjcs_5fycck_171',['TJCS_YCCK',['../group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e',1,'turbojpeg.h']]],
['tjerr_5ffatal_171',['TJERR_FATAL',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a',1,'turbojpeg.h']]], ['tjerr_5ffatal_172',['TJERR_FATAL',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a',1,'turbojpeg.h']]],
['tjerr_5fwarning_172',['TJERR_WARNING',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59',1,'turbojpeg.h']]], ['tjerr_5fwarning_173',['TJERR_WARNING',['../group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59',1,'turbojpeg.h']]],
['tjpf_5fabgr_173',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]], ['tjpf_5fabgr_174',['TJPF_ABGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081',1,'turbojpeg.h']]],
['tjpf_5fargb_174',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]], ['tjpf_5fargb_175',['TJPF_ARGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c',1,'turbojpeg.h']]],
['tjpf_5fbgr_175',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]], ['tjpf_5fbgr_176',['TJPF_BGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839',1,'turbojpeg.h']]],
['tjpf_5fbgra_176',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]], ['tjpf_5fbgra_177',['TJPF_BGRA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4',1,'turbojpeg.h']]],
['tjpf_5fbgrx_177',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]], ['tjpf_5fbgrx_178',['TJPF_BGRX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8',1,'turbojpeg.h']]],
['tjpf_5fcmyk_178',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]], ['tjpf_5fcmyk_179',['TJPF_CMYK',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b',1,'turbojpeg.h']]],
['tjpf_5fgray_179',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]], ['tjpf_5fgray_180',['TJPF_GRAY',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a',1,'turbojpeg.h']]],
['tjpf_5frgb_180',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]], ['tjpf_5frgb_181',['TJPF_RGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c',1,'turbojpeg.h']]],
['tjpf_5frgba_181',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]], ['tjpf_5frgba_182',['TJPF_RGBA',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12',1,'turbojpeg.h']]],
['tjpf_5frgbx_182',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]], ['tjpf_5frgbx_183',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]],
['tjpf_5funknown_183',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]], ['tjpf_5funknown_184',['TJPF_UNKNOWN',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed',1,'turbojpeg.h']]],
['tjpf_5fxbgr_184',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]], ['tjpf_5fxbgr_185',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]],
['tjpf_5fxrgb_185',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]], ['tjpf_5fxrgb_186',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]],
['tjsamp_5f411_186',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]], ['tjsamp_5f411_187',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]],
['tjsamp_5f420_187',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]], ['tjsamp_5f420_188',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]],
['tjsamp_5f422_188',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]], ['tjsamp_5f422_189',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]],
['tjsamp_5f440_189',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]], ['tjsamp_5f440_190',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]],
['tjsamp_5f444_190',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]], ['tjsamp_5f444_191',['TJSAMP_444',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3',1,'turbojpeg.h']]],
['tjsamp_5fgray_191',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]], ['tjsamp_5fgray_192',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]],
['tjxop_5fhflip_192',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]], ['tjxop_5fhflip_193',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]],
['tjxop_5fnone_193',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]], ['tjxop_5fnone_194',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]],
['tjxop_5frot180_194',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]], ['tjxop_5frot180_195',['TJXOP_ROT180',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692',1,'turbojpeg.h']]],
['tjxop_5frot270_195',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]], ['tjxop_5frot270_196',['TJXOP_ROT270',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08',1,'turbojpeg.h']]],
['tjxop_5frot90_196',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]], ['tjxop_5frot90_197',['TJXOP_ROT90',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128',1,'turbojpeg.h']]],
['tjxop_5ftranspose_197',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]], ['tjxop_5ftranspose_198',['TJXOP_TRANSPOSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d',1,'turbojpeg.h']]],
['tjxop_5ftransverse_198',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]], ['tjxop_5ftransverse_199',['TJXOP_TRANSVERSE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4',1,'turbojpeg.h']]],
['tjxop_5fvflip_199',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]] ['tjxop_5fvflip_200',['TJXOP_VFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d',1,'turbojpeg.h']]]
]; ];

View File

@@ -1,31 +1,31 @@
var searchData= var searchData=
[ [
['tjalloc_113',['tjAlloc',['../group___turbo_j_p_e_g.html#gaec627dd4c5f30b7a775a7aea3bec5d83',1,'turbojpeg.h']]], ['tjalloc_114',['tjAlloc',['../group___turbo_j_p_e_g.html#gaec627dd4c5f30b7a775a7aea3bec5d83',1,'turbojpeg.h']]],
['tjbufsize_114',['tjBufSize',['../group___turbo_j_p_e_g.html#ga67ac12fee79073242cb216e07c9f1f90',1,'turbojpeg.h']]], ['tjbufsize_115',['tjBufSize',['../group___turbo_j_p_e_g.html#ga67ac12fee79073242cb216e07c9f1f90',1,'turbojpeg.h']]],
['tjbufsizeyuv2_115',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#ga2be2b9969d4df9ecce9b05deed273194',1,'turbojpeg.h']]], ['tjbufsizeyuv2_116',['tjBufSizeYUV2',['../group___turbo_j_p_e_g.html#ga2be2b9969d4df9ecce9b05deed273194',1,'turbojpeg.h']]],
['tjcompress2_116',['tjCompress2',['../group___turbo_j_p_e_g.html#gafbdce0112fd78fd38efae841443a9bcf',1,'turbojpeg.h']]], ['tjcompress2_117',['tjCompress2',['../group___turbo_j_p_e_g.html#gafbdce0112fd78fd38efae841443a9bcf',1,'turbojpeg.h']]],
['tjcompressfromyuv_117',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga7622a459b79aa1007e005b58783f875b',1,'turbojpeg.h']]], ['tjcompressfromyuv_118',['tjCompressFromYUV',['../group___turbo_j_p_e_g.html#ga7622a459b79aa1007e005b58783f875b',1,'turbojpeg.h']]],
['tjcompressfromyuvplanes_118',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#ga29ec5dfbd2d84b8724e951d6fa0d5d9e',1,'turbojpeg.h']]], ['tjcompressfromyuvplanes_119',['tjCompressFromYUVPlanes',['../group___turbo_j_p_e_g.html#ga29ec5dfbd2d84b8724e951d6fa0d5d9e',1,'turbojpeg.h']]],
['tjdecodeyuv_119',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga70abbf38f77a26fd6da8813bef96f695',1,'turbojpeg.h']]], ['tjdecodeyuv_120',['tjDecodeYUV',['../group___turbo_j_p_e_g.html#ga70abbf38f77a26fd6da8813bef96f695',1,'turbojpeg.h']]],
['tjdecodeyuvplanes_120',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga10e837c07fa9d25770565b237d3898d9',1,'turbojpeg.h']]], ['tjdecodeyuvplanes_121',['tjDecodeYUVPlanes',['../group___turbo_j_p_e_g.html#ga10e837c07fa9d25770565b237d3898d9',1,'turbojpeg.h']]],
['tjdecompress2_121',['tjDecompress2',['../group___turbo_j_p_e_g.html#gae9eccef8b682a48f43a9117c231ed013',1,'turbojpeg.h']]], ['tjdecompress2_122',['tjDecompress2',['../group___turbo_j_p_e_g.html#gae9eccef8b682a48f43a9117c231ed013',1,'turbojpeg.h']]],
['tjdecompressheader3_122',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77',1,'turbojpeg.h']]], ['tjdecompressheader3_123',['tjDecompressHeader3',['../group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77',1,'turbojpeg.h']]],
['tjdecompresstoyuv2_123',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga04d1e839ff9a0860dd1475cff78d3364',1,'turbojpeg.h']]], ['tjdecompresstoyuv2_124',['tjDecompressToYUV2',['../group___turbo_j_p_e_g.html#ga04d1e839ff9a0860dd1475cff78d3364',1,'turbojpeg.h']]],
['tjdecompresstoyuvplanes_124',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#gaa59f901a5258ada5bd0185ad59368540',1,'turbojpeg.h']]], ['tjdecompresstoyuvplanes_125',['tjDecompressToYUVPlanes',['../group___turbo_j_p_e_g.html#gaa59f901a5258ada5bd0185ad59368540',1,'turbojpeg.h']]],
['tjdestroy_125',['tjDestroy',['../group___turbo_j_p_e_g.html#ga75f355fa27225ba1a4ee392c852394d2',1,'turbojpeg.h']]], ['tjdestroy_126',['tjDestroy',['../group___turbo_j_p_e_g.html#ga75f355fa27225ba1a4ee392c852394d2',1,'turbojpeg.h']]],
['tjencodeyuv3_126',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#gac519b922cdf446e97d0cdcba513636bf',1,'turbojpeg.h']]], ['tjencodeyuv3_127',['tjEncodeYUV3',['../group___turbo_j_p_e_g.html#gac519b922cdf446e97d0cdcba513636bf',1,'turbojpeg.h']]],
['tjencodeyuvplanes_127',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gae2d04c72457fe7f4d60cf78ab1b1feb1',1,'turbojpeg.h']]], ['tjencodeyuvplanes_128',['tjEncodeYUVPlanes',['../group___turbo_j_p_e_g.html#gae2d04c72457fe7f4d60cf78ab1b1feb1',1,'turbojpeg.h']]],
['tjfree_128',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]], ['tjfree_129',['tjFree',['../group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b',1,'turbojpeg.h']]],
['tjgeterrorcode_129',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]], ['tjgeterrorcode_130',['tjGetErrorCode',['../group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410',1,'turbojpeg.h']]],
['tjgeterrorstr2_130',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]], ['tjgeterrorstr2_131',['tjGetErrorStr2',['../group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa',1,'turbojpeg.h']]],
['tjgetscalingfactors_131',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]], ['tjgetscalingfactors_132',['tjGetScalingFactors',['../group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057',1,'turbojpeg.h']]],
['tjinitcompress_132',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]], ['tjinitcompress_133',['tjInitCompress',['../group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8',1,'turbojpeg.h']]],
['tjinitdecompress_133',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]], ['tjinitdecompress_134',['tjInitDecompress',['../group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3',1,'turbojpeg.h']]],
['tjinittransform_134',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]], ['tjinittransform_135',['tjInitTransform',['../group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957',1,'turbojpeg.h']]],
['tjloadimage_135',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]], ['tjloadimage_136',['tjLoadImage',['../group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7',1,'turbojpeg.h']]],
['tjplaneheight_136',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]], ['tjplaneheight_137',['tjPlaneHeight',['../group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f',1,'turbojpeg.h']]],
['tjplanesizeyuv_137',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]], ['tjplanesizeyuv_138',['tjPlaneSizeYUV',['../group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d',1,'turbojpeg.h']]],
['tjplanewidth_138',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]], ['tjplanewidth_139',['tjPlaneWidth',['../group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1',1,'turbojpeg.h']]],
['tjsaveimage_139',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]], ['tjsaveimage_140',['tjSaveImage',['../group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879',1,'turbojpeg.h']]],
['tjtransform_140',['tjTransform',['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'turbojpeg.h']]] ['tjtransform_141',['tjTransform',['../group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25',1,'turbojpeg.h']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['turbojpeg_200',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]] ['turbojpeg_201',['TurboJPEG',['../group___turbo_j_p_e_g.html',1,'']]]
]; ];

View File

@@ -1,5 +1,5 @@
var searchData= var searchData=
[ [
['tjhandle_159',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]], ['tjhandle_160',['tjhandle',['../group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763',1,'turbojpeg.h']]],
['tjtransform_160',['tjtransform',['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'turbojpeg.h']]] ['tjtransform_161',['tjtransform',['../group___turbo_j_p_e_g.html#ga504805ec0161f1b505397ca0118bf8fd',1,'turbojpeg.h']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['customfilter_141',['customFilter',['../structtjtransform.html#afd7fc262df33f741e120ef4183202ef5',1,'tjtransform']]] ['customfilter_142',['customFilter',['../structtjtransform.html#afd7fc262df33f741e120ef4183202ef5',1,'tjtransform']]]
]; ];

View File

@@ -1,5 +1,5 @@
var searchData= var searchData=
[ [
['data_142',['data',['../structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3',1,'tjtransform']]], ['data_143',['data',['../structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3',1,'tjtransform']]],
['denom_143',['denom',['../structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3',1,'tjscalingfactor']]] ['denom_144',['denom',['../structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3',1,'tjscalingfactor']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['h_144',['h',['../structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115',1,'tjregion']]] ['h_145',['h',['../structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115',1,'tjregion']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['num_145',['num',['../structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec',1,'tjscalingfactor']]] ['num_146',['num',['../structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec',1,'tjscalingfactor']]]
]; ];

View File

@@ -1,5 +1,5 @@
var searchData= var searchData=
[ [
['op_146',['op',['../structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498',1,'tjtransform']]], ['op_147',['op',['../structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498',1,'tjtransform']]],
['options_147',['options',['../structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6',1,'tjtransform']]] ['options_148',['options',['../structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6',1,'tjtransform']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['r_148',['r',['../structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf',1,'tjtransform']]] ['r_149',['r',['../structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf',1,'tjtransform']]]
]; ];

View File

@@ -1,10 +1,10 @@
var searchData= var searchData=
[ [
['tjalphaoffset_149',['tjAlphaOffset',['../group___turbo_j_p_e_g.html#ga5af0ab065feefd526debf1e20c43e837',1,'turbojpeg.h']]], ['tjalphaoffset_150',['tjAlphaOffset',['../group___turbo_j_p_e_g.html#ga5af0ab065feefd526debf1e20c43e837',1,'turbojpeg.h']]],
['tjblueoffset_150',['tjBlueOffset',['../group___turbo_j_p_e_g.html#ga84e2e35d3f08025f976ec1ec53693dea',1,'turbojpeg.h']]], ['tjblueoffset_151',['tjBlueOffset',['../group___turbo_j_p_e_g.html#ga84e2e35d3f08025f976ec1ec53693dea',1,'turbojpeg.h']]],
['tjgreenoffset_151',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]], ['tjgreenoffset_152',['tjGreenOffset',['../group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f',1,'turbojpeg.h']]],
['tjmcuheight_152',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]], ['tjmcuheight_153',['tjMCUHeight',['../group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf',1,'turbojpeg.h']]],
['tjmcuwidth_153',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]], ['tjmcuwidth_154',['tjMCUWidth',['../group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c',1,'turbojpeg.h']]],
['tjpixelsize_154',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]], ['tjpixelsize_155',['tjPixelSize',['../group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c',1,'turbojpeg.h']]],
['tjredoffset_155',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]] ['tjredoffset_156',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['w_156',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]] ['w_157',['w',['../structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42',1,'tjregion']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['x_157',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]] ['x_158',['x',['../structtjregion.html#a4b6a37a93997091b26a75831fa291ad9',1,'tjregion']]]
]; ];

View File

@@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['y_158',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]] ['y_159',['y',['../structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2',1,'tjregion']]]
]; ];

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;"> <tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG <div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.0</span> &#160;<span id="projectnumber">2.1.4</span>
</div> </div>
</td> </td>
</tr> </tr>

View File

@@ -1,5 +1,5 @@
PROJECT_NAME = TurboJPEG PROJECT_NAME = TurboJPEG
PROJECT_NUMBER = 2.0 PROJECT_NUMBER = 2.1.4
OUTPUT_DIRECTORY = doc/ OUTPUT_DIRECTORY = doc/
USE_WINDOWS_ENCODING = NO USE_WINDOWS_ENCODING = NO
OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_FOR_C = YES

View File

@@ -311,7 +311,7 @@ read_JPEG_file(char *filename)
* We call the libjpeg API from within a separate function, because modifying * We call the libjpeg API from within a separate function, because modifying
* the local non-volatile jpeg_decompress_struct instance below the setjmp() * the local non-volatile jpeg_decompress_struct instance below the setjmp()
* return point and then accessing the instance after setjmp() returns would * return point and then accessing the instance after setjmp() returns would
* return in undefined behavior that may potentially overwrite all or part of * result in undefined behavior that may potentially overwrite all or part of
* the structure. * the structure.
*/ */

55
fuzz/CMakeLists.txt Normal file
View File

@@ -0,0 +1,55 @@
if(NOT ENABLE_STATIC)
message(FATAL_ERROR "Fuzz targets require static libraries.")
endif()
if(NOT WITH_TURBOJPEG)
message(FATAL_ERROR "Fuzz targets require the TurboJPEG API library.")
endif()
set(FUZZ_BINDIR "" CACHE PATH
"Directory into which fuzz targets should be installed")
if(NOT FUZZ_BINDIR)
message(FATAL_ERROR "FUZZ_BINDIR must be specified.")
endif()
message(STATUS "FUZZ_BINDIR = ${FUZZ_BINDIR}")
set(FUZZ_LIBRARY "" CACHE STRING
"Path to fuzzer library or flags necessary to link with it")
if(NOT FUZZ_LIBRARY)
message(FATAL_ERROR "FUZZ_LIBRARY must be specified.")
endif()
message(STATUS "FUZZ_LIBRARY = ${FUZZ_LIBRARY}")
enable_language(CXX)
set(EFFECTIVE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
message(STATUS "C++ Compiler flags = ${EFFECTIVE_CXX_FLAGS}")
add_executable(cjpeg_fuzzer${FUZZER_SUFFIX} cjpeg.cc ../cdjpeg.c ../rdbmp.c
../rdgif.c ../rdppm.c ../rdswitch.c ../rdtarga.c)
set_property(TARGET cjpeg_fuzzer${FUZZER_SUFFIX} PROPERTY COMPILE_FLAGS
${COMPILE_FLAGS})
target_link_libraries(cjpeg_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY} jpeg-static)
install(TARGETS cjpeg_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION
${FUZZ_BINDIR})
macro(add_fuzz_target target source_file)
add_executable(${target}_fuzzer${FUZZER_SUFFIX} ${source_file})
target_link_libraries(${target}_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY}
turbojpeg-static)
install(TARGETS ${target}_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION
${FUZZ_BINDIR})
endmacro()
add_fuzz_target(compress compress.cc)
add_fuzz_target(compress_yuv compress_yuv.cc)
# NOTE: This target is named libjpeg_turbo_fuzzer instead of decompress_fuzzer
# in order to preserve the corpora from Google's OSS-Fuzz target for
# libjpeg-turbo, which this target replaces.
add_fuzz_target(libjpeg_turbo decompress.cc)
add_fuzz_target(decompress_yuv decompress_yuv.cc)
add_fuzz_target(transform transform.cc)

25
fuzz/build.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
set -u
set -e
FUZZER_SUFFIX=
if [ $# -ge 1 ]; then
FUZZER_SUFFIX="$1"
FUZZER_SUFFIX="`echo $1 | sed 's/\./_/g'`"
fi
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_STATIC=1 -DENABLE_SHARED=0 \
-DCMAKE_C_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" -DCMAKE_INSTALL_PREFIX=$WORK \
-DWITH_FUZZ=1 -DFUZZ_BINDIR=$OUT -DFUZZ_LIBRARY=$LIB_FUZZING_ENGINE \
-DFUZZER_SUFFIX="$FUZZER_SUFFIX"
make "-j$(nproc)" "--load-average=$(nproc)"
make install
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/libjpeg_turbo_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/decompress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/transform_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip

89
fuzz/cjpeg.cc Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* This fuzz target wraps cjpeg in order to test esoteric compression options
as well as the GIF and Targa readers. */
#define main cjpeg_main
#define CJPEG_FUZZER
extern "C" {
#include "../cjpeg.c"
}
#undef main
#undef CJPEG_FUZZER
#include <stdint.h>
#include <unistd.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[FILENAME_MAX] = { 0 };
char *argv1[] = {
(char *)"cjpeg", (char *)"-dct", (char *)"float", (char *)"-memdst",
(char *)"-optimize", (char *)"-quality", (char *)"100,99,98",
(char *)"-restart", (char *)"2", (char *)"-sample", (char *)"4x1,2x2,1x2",
(char *)"-targa", NULL
};
char *argv2[] = {
(char *)"cjpeg", (char *)"-arithmetic", (char *)"-dct", (char *)"float",
(char *)"-memdst", (char *)"-quality", (char *)"90,80,70", (char *)"-rgb",
(char *)"-sample", (char *)"2x2", (char *)"-smooth", (char *)"50",
(char *)"-targa", NULL
};
int fd = -1;
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_cjpeg_fuzz.XXXXXX");
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout;
argv1[12] = argv2[13] = filename;
cjpeg_main(13, argv1);
cjpeg_main(14, argv2);
argv1[12] = argv2[13] = NULL;
argv1[11] = argv2[12] = filename;
cjpeg_main(12, argv1);
cjpeg_main(13, argv2);
bailout:
if (fd >= 0) {
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
return 0;
}

133
fuzz/compress.cc Normal file
View File

@@ -0,0 +1,133 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <turbojpeg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define NUMTESTS 7
/* Private flag that triggers different TurboJPEG API behavior when fuzzing */
#define TJFLAG_FUZZING (1 << 30)
struct test {
enum TJPF pf;
enum TJSAMP subsamp;
int quality;
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
tjhandle handle = NULL;
unsigned char *srcBuf = NULL, *dstBuf = NULL;
int width = 0, height = 0, fd = -1, i, ti;
char filename[FILENAME_MAX] = { 0 };
struct test tests[NUMTESTS] = {
{ TJPF_RGB, TJSAMP_444, 100 },
{ TJPF_BGR, TJSAMP_422, 90 },
{ TJPF_RGBX, TJSAMP_420, 80 },
{ TJPF_BGRA, TJSAMP_411, 70 },
{ TJPF_XRGB, TJSAMP_GRAY, 60 },
{ TJPF_GRAY, TJSAMP_GRAY, 50 },
{ TJPF_CMYK, TJSAMP_440, 40 }
};
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX");
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout;
if ((handle = tjInitCompress()) == NULL)
goto bailout;
for (ti = 0; ti < NUMTESTS; ti++) {
int flags = TJFLAG_FUZZING, sum = 0, pf = tests[ti].pf;
unsigned long dstSize = 0, maxBufSize;
/* Test non-default compression options on specific iterations. */
if (ti == 0)
flags |= TJFLAG_BOTTOMUP | TJFLAG_ACCURATEDCT;
else if (ti == 1)
flags |= TJFLAG_PROGRESSIVE;
if (ti != 2)
flags |= TJFLAG_NOREALLOC;
/* tjLoadImage() refuses to load images larger than 1 Megapixel when
FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is defined (yes, that's a dirty
hack), so we don't need to check the width and height here. */
if ((srcBuf = tjLoadImage(filename, &width, 1, &height, &pf,
flags)) == NULL)
continue;
maxBufSize = tjBufSize(width, height, tests[ti].subsamp);
if (flags & TJFLAG_NOREALLOC) {
if ((dstBuf = (unsigned char *)malloc(maxBufSize)) == NULL)
goto bailout;
} else
dstBuf = NULL;
if (tjCompress2(handle, srcBuf, width, 0, height, pf, &dstBuf, &dstSize,
tests[ti].subsamp, tests[ti].quality, flags) == 0) {
/* Touch all of the output pixels in order to catch uninitialized reads
when using MemorySanitizer. */
for (i = 0; i < dstSize; i++)
sum += dstBuf[i];
}
free(dstBuf);
dstBuf = NULL;
tjFree(srcBuf);
srcBuf = NULL;
/* Prevent the code above from being optimized out. This test should never
be true, but the compiler doesn't know that. */
if (sum > 255 * maxBufSize)
goto bailout;
}
bailout:
free(dstBuf);
tjFree(srcBuf);
if (fd >= 0) {
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
if (handle) tjDestroy(handle);
return 0;
}

148
fuzz/compress_yuv.cc Normal file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <turbojpeg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define NUMTESTS 6
/* Private flag that triggers different TurboJPEG API behavior when fuzzing */
#define TJFLAG_FUZZING (1 << 30)
struct test {
enum TJPF pf;
enum TJSAMP subsamp;
int quality;
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
tjhandle handle = NULL;
unsigned char *srcBuf = NULL, *dstBuf = NULL, *yuvBuf = NULL;
int width = 0, height = 0, fd = -1, i, ti;
char filename[FILENAME_MAX] = { 0 };
struct test tests[NUMTESTS] = {
{ TJPF_XBGR, TJSAMP_444, 100 },
{ TJPF_XRGB, TJSAMP_422, 90 },
{ TJPF_BGR, TJSAMP_420, 80 },
{ TJPF_RGB, TJSAMP_411, 70 },
{ TJPF_BGR, TJSAMP_GRAY, 60 },
{ TJPF_GRAY, TJSAMP_GRAY, 50 }
};
char arithEnv[16] = "TJ_ARITHMETIC=0";
char restartEnv[13] = "TJ_RESTART=0";
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char simdEnv[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(simdEnv);
#endif
putenv(arithEnv);
putenv(restartEnv);
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_yuv_fuzz.XXXXXX");
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout;
if ((handle = tjInitCompress()) == NULL)
goto bailout;
for (ti = 0; ti < NUMTESTS; ti++) {
int flags = TJFLAG_FUZZING | TJFLAG_NOREALLOC, sum = 0, pf = tests[ti].pf;
unsigned long dstSize = 0, maxBufSize;
/* Test non-default compression options on specific iterations. */
if (ti == 0)
flags |= TJFLAG_BOTTOMUP | TJFLAG_ACCURATEDCT;
else if (ti == 1 || ti == 3)
flags |= TJFLAG_PROGRESSIVE;
if (ti == 2 || ti == 3)
arithEnv[14] = '1';
else
arithEnv[14] = '0';
if (ti == 1 || ti == 2)
restartEnv[11] = '2';
else
restartEnv[11] = '0';
/* tjLoadImage() refuses to load images larger than 1 Megapixel when
FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is defined (yes, that's a dirty
hack), so we don't need to check the width and height here. */
if ((srcBuf = tjLoadImage(filename, &width, 1, &height, &pf,
flags)) == NULL)
continue;
maxBufSize = tjBufSize(width, height, tests[ti].subsamp);
if ((dstBuf = (unsigned char *)malloc(maxBufSize)) == NULL)
goto bailout;
if ((yuvBuf =
(unsigned char *)malloc(tjBufSizeYUV2(width, 1, height,
tests[ti].subsamp))) == NULL)
goto bailout;
if (tjEncodeYUV3(handle, srcBuf, width, 0, height, pf, yuvBuf, 1,
tests[ti].subsamp, flags) == 0 &&
tjCompressFromYUV(handle, yuvBuf, width, 1, height, tests[ti].subsamp,
&dstBuf, &dstSize, tests[ti].quality, flags) == 0) {
/* Touch all of the output pixels in order to catch uninitialized reads
when using MemorySanitizer. */
for (i = 0; i < dstSize; i++)
sum += dstBuf[i];
}
free(dstBuf);
dstBuf = NULL;
free(yuvBuf);
yuvBuf = NULL;
tjFree(srcBuf);
srcBuf = NULL;
/* Prevent the code above from being optimized out. This test should never
be true, but the compiler doesn't know that. */
if (sum > 255 * maxBufSize)
goto bailout;
}
bailout:
free(dstBuf);
free(yuvBuf);
tjFree(srcBuf);
if (fd >= 0) {
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
if (handle) tjDestroy(handle);
return 0;
}

106
fuzz/decompress.cc Normal file
View File

@@ -0,0 +1,106 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <turbojpeg.h>
#include <stdlib.h>
#include <stdint.h>
#define NUMPF 4
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
tjhandle handle = NULL;
unsigned char *dstBuf = NULL;
int width = 0, height = 0, jpegSubsamp, jpegColorspace, pfi;
/* TJPF_RGB-TJPF_BGR share the same code paths, as do TJPF_RGBX-TJPF_XRGB and
TJPF_RGBA-TJPF_ARGB. Thus, the pixel formats below should be the minimum
necessary to achieve full coverage. */
enum TJPF pixelFormats[NUMPF] =
{ TJPF_RGB, TJPF_BGRX, TJPF_GRAY, TJPF_CMYK };
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
if ((handle = tjInitDecompress()) == NULL)
goto bailout;
/* We ignore the return value of tjDecompressHeader3(), because some JPEG
images may have unusual subsampling configurations that the TurboJPEG API
cannot identify but can still decompress. */
tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp,
&jpegColorspace);
/* Ignore 0-pixel images and images larger than 1 Megapixel, as Google's
OSS-Fuzz target for libjpeg-turbo did. Casting width to (uint64_t)
prevents integer overflow if width * height > INT_MAX. */
if (width < 1 || height < 1 || (uint64_t)width * height > 1048576)
goto bailout;
for (pfi = 0; pfi < NUMPF; pfi++) {
int pf = pixelFormats[pfi], flags = TJFLAG_LIMITSCANS, i, sum = 0;
int w = width, h = height;
/* Test non-default decompression options on the first iteration. */
if (pfi == 0)
flags |= TJFLAG_BOTTOMUP | TJFLAG_FASTUPSAMPLE | TJFLAG_FASTDCT;
/* Test IDCT scaling on the second iteration. */
else if (pfi == 1) {
w = (width + 1) / 2;
h = (height + 1) / 2;
}
if ((dstBuf = (unsigned char *)malloc(w * h * tjPixelSize[pf])) == NULL)
goto bailout;
if (tjDecompress2(handle, data, size, dstBuf, w, 0, h, pf, flags) == 0) {
/* Touch all of the output pixels in order to catch uninitialized reads
when using MemorySanitizer. */
for (i = 0; i < w * h * tjPixelSize[pf]; i++)
sum += dstBuf[i];
}
free(dstBuf);
dstBuf = NULL;
/* Prevent the code above from being optimized out. This test should never
be true, but the compiler doesn't know that. */
if (sum > 255 * 1048576 * tjPixelSize[pf])
goto bailout;
}
bailout:
free(dstBuf);
if (handle) tjDestroy(handle);
return 0;
}

111
fuzz/decompress_yuv.cc Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <turbojpeg.h>
#include <stdlib.h>
#include <stdint.h>
#define NUMPF 3
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
tjhandle handle = NULL;
unsigned char *dstBuf = NULL, *yuvBuf = NULL;
int width = 0, height = 0, jpegSubsamp, jpegColorspace, pfi;
/* TJPF_RGB-TJPF_BGR share the same code paths, as do TJPF_RGBX-TJPF_XRGB and
TJPF_RGBA-TJPF_ARGB. Thus, the pixel formats below should be the minimum
necessary to achieve full coverage. */
enum TJPF pixelFormats[NUMPF] =
{ TJPF_BGR, TJPF_XRGB, TJPF_GRAY };
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
if ((handle = tjInitDecompress()) == NULL)
goto bailout;
if (tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp,
&jpegColorspace) < 0)
goto bailout;
/* Ignore 0-pixel images and images larger than 1 Megapixel. Casting width
to (uint64_t) prevents integer overflow if width * height > INT_MAX. */
if (width < 1 || height < 1 || (uint64_t)width * height > 1048576)
goto bailout;
for (pfi = 0; pfi < NUMPF; pfi++) {
int pf = pixelFormats[pfi], flags = TJFLAG_LIMITSCANS, i, sum = 0;
int w = width, h = height;
/* Test non-default decompression options on the first iteration. */
if (pfi == 0)
flags |= TJFLAG_BOTTOMUP | TJFLAG_FASTUPSAMPLE | TJFLAG_FASTDCT;
/* Test IDCT scaling on the second iteration. */
else if (pfi == 1) {
w = (width + 3) / 4;
h = (height + 3) / 4;
}
if ((dstBuf = (unsigned char *)malloc(w * h * tjPixelSize[pf])) == NULL)
goto bailout;
if ((yuvBuf =
(unsigned char *)malloc(tjBufSizeYUV2(w, 1, h, jpegSubsamp))) == NULL)
goto bailout;
if (tjDecompressToYUV2(handle, data, size, yuvBuf, w, 1, h, flags) == 0 &&
tjDecodeYUV(handle, yuvBuf, 1, jpegSubsamp, dstBuf, w, 0, h, pf,
flags) == 0) {
/* Touch all of the output pixels in order to catch uninitialized reads
when using MemorySanitizer. */
for (i = 0; i < w * h * tjPixelSize[pf]; i++)
sum += dstBuf[i];
}
free(dstBuf);
dstBuf = NULL;
free(yuvBuf);
yuvBuf = NULL;
/* Prevent the code above from being optimized out. This test should never
be true, but the compiler doesn't know that. */
if (sum > 255 * 1048576 * tjPixelSize[pf])
goto bailout;
}
bailout:
free(dstBuf);
free(yuvBuf);
if (handle) tjDestroy(handle);
return 0;
}

135
fuzz/transform.cc Normal file
View File

@@ -0,0 +1,135 @@
/*
* Copyright (C)2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <turbojpeg.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define NUMXFORMS 3
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
tjhandle handle = NULL;
unsigned char *dstBufs[NUMXFORMS] = { NULL, NULL, NULL };
unsigned long dstSizes[NUMXFORMS] = { 0, 0, 0 }, maxBufSize;
int width = 0, height = 0, jpegSubsamp, jpegColorspace, i, t;
tjtransform transforms[NUMXFORMS];
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
if ((handle = tjInitTransform()) == NULL)
goto bailout;
/* We ignore the return value of tjDecompressHeader3(), because some JPEG
images may have unusual subsampling configurations that the TurboJPEG API
cannot identify but can still transform. */
tjDecompressHeader3(handle, data, size, &width, &height, &jpegSubsamp,
&jpegColorspace);
/* Ignore 0-pixel images and images larger than 1 Megapixel. Casting width
to (uint64_t) prevents integer overflow if width * height > INT_MAX. */
if (width < 1 || height < 1 || (uint64_t)width * height > 1048576)
goto bailout;
if (jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP)
jpegSubsamp = TJSAMP_444;
for (t = 0; t < NUMXFORMS; t++)
memset(&transforms[t], 0, sizeof(tjtransform));
transforms[0].op = TJXOP_NONE;
transforms[0].options = TJXOPT_PROGRESSIVE | TJXOPT_COPYNONE;
dstBufs[0] = (unsigned char *)malloc(tjBufSize(width, height, jpegSubsamp));
if (!dstBufs[0])
goto bailout;
transforms[1].r.w = (width + 1) / 2;
transforms[1].r.h = (height + 1) / 2;
transforms[1].op = TJXOP_TRANSPOSE;
transforms[1].options = TJXOPT_GRAY | TJXOPT_CROP | TJXOPT_COPYNONE;
dstBufs[1] =
(unsigned char *)malloc(tjBufSize((width + 1) / 2, (height + 1) / 2,
TJSAMP_GRAY));
if (!dstBufs[1])
goto bailout;
transforms[2].op = TJXOP_ROT90;
transforms[2].options = TJXOPT_TRIM | TJXOPT_COPYNONE;
dstBufs[2] = (unsigned char *)malloc(tjBufSize(height, width, jpegSubsamp));
if (!dstBufs[2])
goto bailout;
maxBufSize = tjBufSize(width, height, jpegSubsamp);
if (tjTransform(handle, data, size, NUMXFORMS, dstBufs, dstSizes, transforms,
TJFLAG_LIMITSCANS | TJFLAG_NOREALLOC) == 0) {
/* Touch all of the output pixels in order to catch uninitialized reads
when using MemorySanitizer. */
for (t = 0; t < NUMXFORMS; t++) {
int sum = 0;
for (i = 0; i < dstSizes[t]; i++)
sum += dstBufs[t][i];
/* Prevent the code above from being optimized out. This test should
never be true, but the compiler doesn't know that. */
if (sum > 255 * maxBufSize)
goto bailout;
}
}
transforms[0].options &= ~TJXOPT_COPYNONE;
free(dstBufs[0]);
dstBufs[0] = NULL;
dstSizes[0] = 0;
if (tjTransform(handle, data, size, 1, dstBufs, dstSizes, transforms,
TJFLAG_LIMITSCANS) == 0) {
int sum = 0;
for (i = 0; i < dstSizes[0]; i++)
sum += dstBufs[0][i];
if (sum > 255 * maxBufSize)
goto bailout;
}
bailout:
for (t = 0; t < NUMXFORMS; t++)
free(dstBufs[t]);
if (handle) tjDestroy(handle);
return 0;
}

View File

@@ -37,7 +37,7 @@ if(WIN32)
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java) ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
else() else()
configure_file(org/libjpegturbo/turbojpeg/TJLoader-unix.java.in configure_file(org/libjpegturbo/turbojpeg/TJLoader-unix.java.in
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java) ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
endif() endif()
set(JAVA_SOURCES ${JAVA_SOURCES} set(JAVA_SOURCES ${JAVA_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java) ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)

View File

@@ -38,7 +38,7 @@ Installation Directory
---------------------- ----------------------
The TurboJPEG Java Wrapper will look for the TurboJPEG JNI library The TurboJPEG Java Wrapper will look for the TurboJPEG JNI library
(libturbojpeg.so, libturbojpeg.jnilib, or turbojpeg.dll) in the system library (libturbojpeg.so, libturbojpeg.dylib, or turbojpeg.dll) in the system library
paths or in any paths specified in LD_LIBRARY_PATH (Un*x), DYLD_LIBRARY_PATH paths or in any paths specified in LD_LIBRARY_PATH (Un*x), DYLD_LIBRARY_PATH
(Mac), or PATH (Windows.) Failing this, on Un*x and Mac systems, the wrapper (Mac), or PATH (Windows.) Failing this, on Un*x and Mac systems, the wrapper
will look for the JNI library under the library directory configured when will look for the JNI library under the library directory configured when

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (C)2009-2014, 2016-2019 D. R. Commander. All Rights Reserved. * Copyright (C)2009-2014, 2016-2019, 2021 D. R. Commander.
* 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
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -648,7 +649,7 @@ final class TJBench {
sigFig((double)(w * h * ps) / sigFig((double)(w * h * ps) /
(double)totalJpegSize, 4), (double)totalJpegSize, 4),
quiet == 2 ? "\n" : " "); quiet == 2 ? "\n" : " ");
} else if (quiet == 0) { } else {
System.out.format("Transform --> Frame rate: %f fps\n", System.out.format("Transform --> Frame rate: %f fps\n",
1.0 / elapsed); 1.0 / elapsed);
System.out.format(" Output image size: %d bytes\n", System.out.format(" Output image size: %d bytes\n",
@@ -752,6 +753,8 @@ final class TJBench {
System.out.println("-componly = Stop after running compression tests. Do not test decompression."); System.out.println("-componly = Stop after running compression tests. Do not test decompression.");
System.out.println("-nowrite = Do not write reference or output images (improves consistency"); System.out.println("-nowrite = Do not write reference or output images (improves consistency");
System.out.println(" of performance measurements.)"); System.out.println(" of performance measurements.)");
System.out.println("-limitscans = Refuse to decompress or transform progressive JPEG images that");
System.out.println(" have an unreasonably large number of scans");
System.out.println("-stoponwarning = Immediately discontinue the current"); System.out.println("-stoponwarning = Immediately discontinue the current");
System.out.println(" compression/decompression/transform operation if the underlying codec"); System.out.println(" compression/decompression/transform operation if the underlying codec");
System.out.println(" throws a warning (non-fatal error)\n"); System.out.println(" throws a warning (non-fatal error)\n");
@@ -929,6 +932,8 @@ final class TJBench {
compOnly = true; compOnly = true;
else if (argv[i].equalsIgnoreCase("-nowrite")) else if (argv[i].equalsIgnoreCase("-nowrite"))
write = false; write = false;
else if (argv[i].equalsIgnoreCase("-limitscans"))
flags |= TJ.FLAG_LIMITSCANS;
else if (argv[i].equalsIgnoreCase("-stoponwarning")) else if (argv[i].equalsIgnoreCase("-stoponwarning"))
flags |= TJ.FLAG_STOPONWARNING; flags |= TJ.FLAG_STOPONWARNING;
else usage(); else usage();

View File

@@ -189,167 +189,174 @@
<td class="colLast"><code>128</code></td> <td class="colLast"><code>128</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_LIMITSCANS">
<!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_LIMITSCANS">FLAG_LIMITSCANS</a></code></td>
<td class="colLast"><code>32768</code></td>
</tr>
<tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></code></td>
<td class="colLast"><code>16384</code></td> <td class="colLast"><code>16384</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_STOPONWARNING"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_STOPONWARNING">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></code></td>
<td class="colLast"><code>8192</code></td> <td class="colLast"><code>8192</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMCS"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMCS">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMCS">NUMCS</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMCS">NUMCS</a></code></td>
<td class="colLast"><code>5</code></td> <td class="colLast"><code>5</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMERR"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMERR">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></code></td>
<td class="colLast"><code>2</code></td> <td class="colLast"><code>2</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMPF"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMPF">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></code></td>
<td class="colLast"><code>12</code></td> <td class="colLast"><code>12</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMSAMP"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMSAMP">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></code></td>
<td class="colLast"><code>6</code></td> <td class="colLast"><code>6</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ABGR"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ABGR">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></code></td>
<td class="colLast"><code>9</code></td> <td class="colLast"><code>9</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ARGB"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ARGB">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></code></td>
<td class="colLast"><code>10</code></td> <td class="colLast"><code>10</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGR"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGR">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></code></td>
<td class="colLast"><code>1</code></td> <td class="colLast"><code>1</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRA"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRA">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></code></td>
<td class="colLast"><code>8</code></td> <td class="colLast"><code>8</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRX"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRX">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></code></td>
<td class="colLast"><code>3</code></td> <td class="colLast"><code>3</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_CMYK"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_CMYK">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></code></td>
<td class="colLast"><code>11</code></td> <td class="colLast"><code>11</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_GRAY"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_GRAY">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></code></td>
<td class="colLast"><code>6</code></td> <td class="colLast"><code>6</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGB"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGB">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></code></td>
<td class="colLast"><code>0</code></td> <td class="colLast"><code>0</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBA"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBA">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></code></td>
<td class="colLast"><code>7</code></td> <td class="colLast"><code>7</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBX"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBX">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></code></td>
<td class="colLast"><code>2</code></td> <td class="colLast"><code>2</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XBGR"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XBGR">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></code></td>
<td class="colLast"><code>4</code></td> <td class="colLast"><code>4</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XRGB"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XRGB">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></code></td>
<td class="colLast"><code>5</code></td> <td class="colLast"><code>5</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_411"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_411">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></code></td>
<td class="colLast"><code>5</code></td> <td class="colLast"><code>5</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_420"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_420">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></code></td>
<td class="colLast"><code>2</code></td> <td class="colLast"><code>2</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_422"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_422">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></code></td>
<td class="colLast"><code>1</code></td> <td class="colLast"><code>1</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_440"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_440">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></code></td>
<td class="colLast"><code>4</code></td> <td class="colLast"><code>4</code></td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_444"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_444">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></code></td> <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></code></td>
<td class="colLast"><code>0</code></td> <td class="colLast"><code>0</code></td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_GRAY"> <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_GRAY">
<!-- --> <!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td> </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>

View File

@@ -337,6 +337,11 @@
<dd> <dd>
<div class="block"><span class="strong">Deprecated.</span></div> <div class="block"><span class="strong">Deprecated.</span></div>
</dd> </dd>
<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_LIMITSCANS">FLAG_LIMITSCANS</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
<dd>
<div class="block">Limit the number of progressive JPEG scans that the decompression and
transform operations will process.</div>
</dd>
<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt> <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
<dd> <dd>
<div class="block">Use progressive entropy coding in JPEG images generated by compression and <div class="block">Use progressive entropy coding in JPEG images generated by compression and
@@ -787,7 +792,8 @@
</dd> </dd>
<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(byte[],%20int)">setSourceImage(byte[], int)</a></span> - Method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</a></dt> <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(byte[],%20int)">setSourceImage(byte[], int)</a></span> - Method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</a></dt>
<dd> <dd>
<div class="block">Associate the JPEG image of length <code>imageSize</code> bytes stored in <div class="block">Associate the JPEG image or "abbreviated table specification" (AKA
"tables-only") datastream of length <code>imageSize</code> bytes stored in
<code>jpegImage</code> with this decompressor instance.</div> <code>jpegImage</code> with this decompressor instance.</div>
</dd> </dd>
<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(org.libjpegturbo.turbojpeg.YUVImage)">setSourceImage(YUVImage)</a></span> - Method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</a></dt> <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(org.libjpegturbo.turbojpeg.YUVImage)">setSourceImage(YUVImage)</a></span> - Method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</a></dt>

View File

@@ -214,145 +214,152 @@ extends java.lang.Object</pre>
</tr> </tr>
<tr class="rowColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_LIMITSCANS">FLAG_LIMITSCANS</a></strong></code>
<div class="block">Limit the number of progressive JPEG scans that the decompression and
transform operations will process.</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></strong></code>
<div class="block">Use progressive entropy coding in JPEG images generated by compression and <div class="block">Use progressive entropy coding in JPEG images generated by compression and
transform operations.</div> transform operations.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></strong></code>
<div class="block">Immediately discontinue the current compression/decompression/transform <div class="block">Immediately discontinue the current compression/decompression/transform
operation if the underlying codec throws a warning (non-fatal error).</div> operation if the underlying codec throws a warning (non-fatal error).</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMCS">NUMCS</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMCS">NUMCS</a></strong></code>
<div class="block">The number of JPEG colorspaces</div> <div class="block">The number of JPEG colorspaces</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></strong></code>
<div class="block">The number of error codes</div> <div class="block">The number of error codes</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></strong></code>
<div class="block">The number of pixel formats</div> <div class="block">The number of pixel formats</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></strong></code>
<div class="block">The number of chrominance subsampling options</div> <div class="block">The number of chrominance subsampling options</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></strong></code>
<div class="block">ABGR pixel format.</div> <div class="block">ABGR pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></strong></code>
<div class="block">ARGB pixel format.</div> <div class="block">ARGB pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></strong></code>
<div class="block">BGR pixel format.</div> <div class="block">BGR pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></strong></code>
<div class="block">BGRA pixel format.</div> <div class="block">BGRA pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></strong></code>
<div class="block">BGRX pixel format.</div> <div class="block">BGRX pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></strong></code>
<div class="block">CMYK pixel format.</div> <div class="block">CMYK pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></strong></code>
<div class="block">Grayscale pixel format.</div> <div class="block">Grayscale pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></strong></code>
<div class="block">RGB pixel format.</div> <div class="block">RGB pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></strong></code>
<div class="block">RGBA pixel format.</div> <div class="block">RGBA pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></strong></code>
<div class="block">RGBX pixel format.</div> <div class="block">RGBX pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></strong></code>
<div class="block">XBGR pixel format.</div> <div class="block">XBGR pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></strong></code>
<div class="block">XRGB pixel format.</div> <div class="block">XRGB pixel format.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></strong></code>
<div class="block">4:1:1 chrominance subsampling.</div> <div class="block">4:1:1 chrominance subsampling.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></strong></code>
<div class="block">4:2:0 chrominance subsampling.</div> <div class="block">4:2:0 chrominance subsampling.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></strong></code>
<div class="block">4:2:2 chrominance subsampling.</div> <div class="block">4:2:2 chrominance subsampling.</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></strong></code>
<div class="block">4:4:0 chrominance subsampling.</div> <div class="block">4:4:0 chrominance subsampling.</div>
</td> </td>
</tr> </tr>
<tr class="rowColor"> <tr class="altColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></strong></code>
<div class="block">4:4:4 chrominance subsampling (no chrominance subsampling).</div> <div class="block">4:4:4 chrominance subsampling (no chrominance subsampling).</div>
</td> </td>
</tr> </tr>
<tr class="altColor"> <tr class="rowColor">
<td class="colFirst"><code>static int</code></td> <td class="colFirst"><code>static int</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY">SAMP_GRAY</a></strong></code> <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY">SAMP_GRAY</a></strong></code>
<div class="block">Grayscale.</div> <div class="block">Grayscale.</div>
@@ -1013,6 +1020,23 @@ public static final&nbsp;int FLAG_FORCESSE3</pre>
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE">Constant Field Values</a></dd></dl> <dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE">Constant Field Values</a></dd></dl>
</li> </li>
</ul> </ul>
<a name="FLAG_LIMITSCANS">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>FLAG_LIMITSCANS</h4>
<pre>public static final&nbsp;int FLAG_LIMITSCANS</pre>
<div class="block">Limit the number of progressive JPEG scans that the decompression and
transform operations will process. If a progressive JPEG image contains
an unreasonably large number of scans, then this flag will cause the
decompression and transform operations to throw an error. The primary
purpose of this is to allow security-critical applications to guard
against an exploit of the progressive JPEG format described in
<a href="https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf" target="_blank">this report</a>.</div>
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_LIMITSCANS">Constant Field Values</a></dd></dl>
</li>
</ul>
<a name="NUMERR"> <a name="NUMERR">
<!-- --> <!-- -->
</a> </a>

View File

@@ -418,7 +418,8 @@ implements java.io.Closeable</pre>
<td class="colFirst"><code>void</code></td> <td class="colFirst"><code>void</code></td>
<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(byte[],%20int)">setSourceImage</a></strong>(byte[]&nbsp;jpegImage, <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#setSourceImage(byte[],%20int)">setSourceImage</a></strong>(byte[]&nbsp;jpegImage,
int&nbsp;imageSize)</code> int&nbsp;imageSize)</code>
<div class="block">Associate the JPEG image of length <code>imageSize</code> bytes stored in <div class="block">Associate the JPEG image or "abbreviated table specification" (AKA
"tables-only") datastream of length <code>imageSize</code> bytes stored in
<code>jpegImage</code> with this decompressor instance.</div> <code>jpegImage</code> with this decompressor instance.</div>
</td> </td>
</tr> </tr>
@@ -611,10 +612,19 @@ implements java.io.Closeable</pre>
<pre>public&nbsp;void&nbsp;setSourceImage(byte[]&nbsp;jpegImage, <pre>public&nbsp;void&nbsp;setSourceImage(byte[]&nbsp;jpegImage,
int&nbsp;imageSize) int&nbsp;imageSize)
throws <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></pre> throws <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></pre>
<div class="block">Associate the JPEG image of length <code>imageSize</code> bytes stored in <div class="block">Associate the JPEG image or "abbreviated table specification" (AKA
<code>jpegImage</code> with this decompressor instance. This image will "tables-only") datastream of length <code>imageSize</code> bytes stored in
be used as the source image for subsequent decompress operations.</div> <code>jpegImage</code> with this decompressor instance. If
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>jpegImage</code> - JPEG image buffer. This buffer is not modified.</dd><dd><code>imageSize</code> - size of the JPEG image (in bytes)</dd> <code>jpegImage</code> contains a JPEG image, then this image will be used
as the source image for subsequent decompress operations. Passing a
tables-only datastream to this method primes the decompressor with
quantization and Huffman tables that can be used when decompressing
subsequent "abbreviated image" datastreams. This is useful, for instance,
when decompressing video streams in which all frames share the same
quantization and Huffman tables.</div>
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>jpegImage</code> - buffer containing a JPEG image or an "abbreviated table
specification" (AKA "tables-only") datastream. This buffer is not
modified.</dd><dd><code>imageSize</code> - size of the JPEG image (in bytes)</dd>
<dt><span class="strong">Throws:</span></dt> <dt><span class="strong">Throws:</span></dt>
<dd><code><a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></code></dd></dl> <dd><code><a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></code></dd></dl>
</li> </li>

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (C)2011-2013, 2017-2018, 2020 D. R. Commander. * Copyright (C)2011-2013, 2017-2018, 2020-2021 D. R. Commander.
* All Rights Reserved. * All Rights Reserved.
* Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. * Copyright (C)2015 Viktor Szathmáry. 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
@@ -438,6 +438,16 @@ public final class TJ {
* reduce compression and decompression performance considerably. * reduce compression and decompression performance considerably.
*/ */
public static final int FLAG_PROGRESSIVE = 16384; public static final int FLAG_PROGRESSIVE = 16384;
/**
* Limit the number of progressive JPEG scans that the decompression and
* transform operations will process. If a progressive JPEG image contains
* an unreasonably large number of scans, then this flag will cause the
* decompression and transform operations to throw an error. The primary
* purpose of this is to allow security-critical applications to guard
* against an exploit of the progressive JPEG format described in
* <a href="https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf" target="_blank">this report</a>.
*/
public static final int FLAG_LIMITSCANS = 32768;
/** /**

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C)2011-2015, 2018 D. R. Commander. All Rights Reserved. * Copyright (C)2011-2015, 2018, 2022 D. R. Commander. All Rights Reserved.
* Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. * Copyright (C)2015 Viktor Szathmáry. 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
@@ -89,11 +89,20 @@ public class TJDecompressor implements Closeable {
} }
/** /**
* Associate the JPEG image of length <code>imageSize</code> bytes stored in * Associate the JPEG image or "abbreviated table specification" (AKA
* <code>jpegImage</code> with this decompressor instance. This image will * "tables-only") datastream of length <code>imageSize</code> bytes stored in
* be used as the source image for subsequent decompress operations. * <code>jpegImage</code> with this decompressor instance. If
* <code>jpegImage</code> contains a JPEG image, then this image will be used
* as the source image for subsequent decompress operations. Passing a
* tables-only datastream to this method primes the decompressor with
* quantization and Huffman tables that can be used when decompressing
* subsequent "abbreviated image" datastreams. This is useful, for instance,
* when decompressing video streams in which all frames share the same
* quantization and Huffman tables.
* *
* @param jpegImage JPEG image buffer. This buffer is not modified. * @param jpegImage buffer containing a JPEG image or an "abbreviated table
* specification" (AKA "tables-only") datastream. This buffer is not
* modified.
* *
* @param imageSize size of the JPEG image (in bytes) * @param imageSize size of the JPEG image (in bytes)
*/ */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C)2011-2013, 2016 D. R. Commander. All Rights Reserved. * Copyright (C)2011-2013, 2016, 2020 D. R. Commander. 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
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -36,9 +36,9 @@ final class TJLoader {
String os = System.getProperty("os.name").toLowerCase(); String os = System.getProperty("os.name").toLowerCase();
if (os.indexOf("mac") >= 0) { if (os.indexOf("mac") >= 0) {
try { try {
System.load("@CMAKE_INSTALL_FULL_LIBDIR@/libturbojpeg.jnilib"); System.load("@CMAKE_INSTALL_FULL_LIBDIR@/libturbojpeg.dylib");
} catch (java.lang.UnsatisfiedLinkError e2) { } catch (java.lang.UnsatisfiedLinkError e2) {
System.load("/usr/lib/libturbojpeg.jnilib"); System.load("/usr/lib/libturbojpeg.dylib");
} }
} else { } else {
try { try {

View File

@@ -61,12 +61,32 @@ extern "C" {
#define org_libjpegturbo_turbojpeg_TJ_CS_YCCK 4L #define org_libjpegturbo_turbojpeg_TJ_CS_YCCK 4L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP #undef org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP
#define org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP 2L #define org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP 2L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX 8L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE 16L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2 32L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3 128L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE #undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE 256L #define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE 256L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT #undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT
#define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT 2048L #define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTDCT 2048L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT #undef org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT
#define org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT 4096L #define org_libjpegturbo_turbojpeg_TJ_FLAG_ACCURATEDCT 4096L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_STOPONWARNING
#define org_libjpegturbo_turbojpeg_TJ_FLAG_STOPONWARNING 8192L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_PROGRESSIVE
#define org_libjpegturbo_turbojpeg_TJ_FLAG_PROGRESSIVE 16384L
#undef org_libjpegturbo_turbojpeg_TJ_FLAG_LIMITSCANS
#define org_libjpegturbo_turbojpeg_TJ_FLAG_LIMITSCANS 32768L
#undef org_libjpegturbo_turbojpeg_TJ_NUMERR
#define org_libjpegturbo_turbojpeg_TJ_NUMERR 2L
#undef org_libjpegturbo_turbojpeg_TJ_ERR_WARNING
#define org_libjpegturbo_turbojpeg_TJ_ERR_WARNING 0L
#undef org_libjpegturbo_turbojpeg_TJ_ERR_FATAL
#define org_libjpegturbo_turbojpeg_TJ_ERR_FATAL 1L
/* /*
* Class: org_libjpegturbo_turbojpeg_TJ * Class: org_libjpegturbo_turbojpeg_TJ
* Method: bufSize * Method: bufSize

View File

@@ -5,8 +5,9 @@
* Copyright (C) 1994-1998, Thomas G. Lane. * Copyright (C) 1994-1998, Thomas G. Lane.
* Modified 2003-2010 by Guido Vollbeding. * Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2014, D. R. Commander. * Copyright (C) 2022, D. R. Commander.
* For conditions of distribution and use, see the accompanying README file. * For conditions of distribution and use, see the accompanying README.ijg
* file.
* *
* This file contains application interface code for the compression half * This file contains application interface code for the compression half
* of the JPEG library. These are the "minimum" API routines that may be * of the JPEG library. These are the "minimum" API routines that may be
@@ -22,8 +23,6 @@
#define JPEG_INTERNALS #define JPEG_INTERNALS
#include "jinclude.h" #include "jinclude.h"
#include "jpeglib.h" #include "jpeglib.h"
#include "jmemsys.h"
#include "jcmaster.h"
/* /*
@@ -53,7 +52,7 @@ jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize)
{ {
struct jpeg_error_mgr *err = cinfo->err; struct jpeg_error_mgr *err = cinfo->err;
void *client_data = cinfo->client_data; /* ignore Purify complaint here */ void *client_data = cinfo->client_data; /* ignore Purify complaint here */
MEMZERO(cinfo, sizeof(struct jpeg_compress_struct)); memset(cinfo, 0, sizeof(struct jpeg_compress_struct));
cinfo->err = err; cinfo->err = err;
cinfo->client_data = client_data; cinfo->client_data = client_data;
} }
@@ -93,16 +92,6 @@ 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. It is later reallocated by jinit_c_master_control().
*/
cinfo->master = (struct jpeg_comp_master *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(my_comp_master));
MEMZERO(cinfo->master, sizeof(my_comp_master));
cinfo->master->compress_profile = JCP_MAX_COMPRESSION;
} }

View File

@@ -3,9 +3,8 @@
* *
* Copyright (C) 1994-1996, Thomas G. Lane. * Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software. * This file is part of the Independent JPEG Group's software.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains application interface code for the compression half * This file contains application interface code for the compression half
* of the JPEG library. These are the "standard" API routines that are * of the JPEG library. These are the "standard" API routines that are
@@ -45,11 +44,6 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables)
if (write_all_tables) if (write_all_tables)
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* setting up scan optimisation pattern failed, disable scan optimisation */
if (cinfo->master->num_scans_luma == 0 || cinfo->scan_info == NULL ||
cinfo->num_scans == 0)
cinfo->master->optimize_scans = FALSE;
/* (Re)initialize error mgr and destination modules */ /* (Re)initialize error mgr and destination modules */
(*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo); (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo); (*cinfo->dest->init_destination) (cinfo);

View File

@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding. * Developed 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2015, 2018, D. R. Commander. * Copyright (C) 2015, 2018, 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
* file. * file.
* *
@@ -22,7 +22,7 @@
#define JPEG_INTERNALS #define JPEG_INTERNALS
#include "jinclude.h" #include "jinclude.h"
#include "jpeglib.h" #include "jpeglib.h"
#include <math.h>
/* Expanded entropy encoder object for arithmetic encoding. */ /* Expanded entropy encoder object for arithmetic encoding. */
@@ -66,8 +66,8 @@ typedef arith_entropy_encoder *arith_entropy_ptr;
* in the lower bits (mask 0x7F). * in the lower bits (mask 0x7F).
*/ */
#define DC_STAT_BINS 64 #define DC_STAT_BINS 64
#define AC_STAT_BINS 256 #define AC_STAT_BINS 256
/* NOTE: Uncomment the following #define if you want to use the /* NOTE: Uncomment the following #define if you want to use the
* given formula for calculating the AC conditioning parameter Kx * given formula for calculating the AC conditioning parameter Kx
@@ -109,9 +109,9 @@ typedef arith_entropy_encoder *arith_entropy_ptr;
#ifdef RIGHT_SHIFT_IS_UNSIGNED #ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp; #define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x, shft) \ #define IRIGHT_SHIFT(x, shft) \
((ishift_temp = (x)) < 0 ? \ ((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
(ishift_temp >> (shft))) (ishift_temp >> (shft)))
#else #else
#define ISHIFT_TEMPS #define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x, shft) ((x) >> (shft)) #define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
@@ -124,11 +124,7 @@ emit_byte(int val, j_compress_ptr cinfo)
{ {
struct jpeg_destination_mgr *dest = cinfo->dest; struct jpeg_destination_mgr *dest = cinfo->dest;
/* Do not emit bytes during trellis passes */ *dest->next_output_byte++ = (JOCTET)val;
if (cinfo->master->trellis_passes)
return;
*dest->next_output_byte++ = (JOCTET) val;
if (--dest->free_in_buffer == 0) if (--dest->free_in_buffer == 0)
if (!(*dest->empty_output_buffer) (cinfo)) if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
@@ -238,8 +234,8 @@ arith_encode(j_compress_ptr cinfo, unsigned char *st, int val)
*/ */
sv = *st; sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Encode & estimation procedures per sections D.1.4 & D.1.5 */ /* Encode & estimation procedures per sections D.1.4 & D.1.5 */
e->a -= qe; e->a -= qe;
@@ -342,14 +338,14 @@ emit_restart(j_compress_ptr cinfo, int restart_num)
compptr = cinfo->cur_comp_info[ci]; compptr = cinfo->cur_comp_info[ci];
/* DC needs no table for refinement scan */ /* DC needs no table for refinement scan */
if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) { if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); memset(entropy->dc_stats[compptr->dc_tbl_no], 0, DC_STAT_BINS);
/* Reset DC predictions to 0 */ /* Reset DC predictions to 0 */
entropy->last_dc_val[ci] = 0; entropy->last_dc_val[ci] = 0;
entropy->dc_context[ci] = 0; entropy->dc_context[ci] = 0;
} }
/* AC needs no table when not present */ /* AC needs no table when not present */
if (cinfo->progressive_mode == 0 || cinfo->Se) { if (cinfo->progressive_mode == 0 || cinfo->Se) {
MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); memset(entropy->ac_stats[compptr->ac_tbl_no], 0, AC_STAT_BINS);
} }
} }
@@ -517,7 +513,7 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
break; break;
} }
} }
arith_encode(cinfo, st + 1, 0); st += 3; k++; arith_encode(cinfo, st + 1, 0); st += 3; k++;
} }
st += 2; st += 2;
/* Figure F.8: Encoding the magnitude category of v */ /* Figure F.8: Encoding the magnitude category of v */
@@ -669,7 +665,7 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
break; break;
} }
} }
arith_encode(cinfo, st + 1, 0); st += 3; k++; arith_encode(cinfo, st + 1, 0); st += 3; k++;
} }
} }
/* Encode EOB decision only if k <= cinfo->Se */ /* Encode EOB decision only if k <= cinfo->Se */
@@ -777,7 +773,7 @@ encode_mcu(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
st = entropy->ac_stats[tbl] + 3 * (k - 1); st = entropy->ac_stats[tbl] + 3 * (k - 1);
arith_encode(cinfo, st, 0); /* EOB decision */ arith_encode(cinfo, st, 0); /* EOB decision */
while ((v = (*block)[jpeg_natural_order[k]]) == 0) { while ((v = (*block)[jpeg_natural_order[k]]) == 0) {
arith_encode(cinfo, st + 1, 0); st += 3; k++; arith_encode(cinfo, st + 1, 0); st += 3; k++;
} }
arith_encode(cinfo, st + 1, 1); arith_encode(cinfo, st + 1, 1);
/* Figure F.6: Encoding nonzero value v */ /* Figure F.6: Encoding nonzero value v */
@@ -834,23 +830,18 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy; arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl; int ci, tbl;
jpeg_component_info *compptr; jpeg_component_info *compptr;
boolean progressive_mode;
if (gather_statistics) if (gather_statistics)
/* Make sure to avoid that in the master control logic! /* Make sure to avoid that in the master control logic!
* We are fully adaptive here and need no extra * We are fully adaptive here and need no extra
* statistics gathering pass! * statistics gathering pass!
*/ */
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOTIMPL);
/* We assume jcmaster.c already validated the progressive scan parameters. */ /* We assume jcmaster.c already validated the progressive scan parameters. */
/* Trellis optimization does DC and AC in same pass and without refinement
* so consider progressive mode to be off in such case */
progressive_mode = (cinfo->master->trellis_passes) ? FALSE : cinfo->progressive_mode;
/* Select execution routines */ /* Select execution routines */
if (progressive_mode) { if (cinfo->progressive_mode) {
if (cinfo->Ah == 0) { if (cinfo->Ah == 0) {
if (cinfo->Ss == 0) if (cinfo->Ss == 0)
entropy->pub.encode_mcu = encode_mcu_DC_first; entropy->pub.encode_mcu = encode_mcu_DC_first;
@@ -869,29 +860,29 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
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];
/* DC needs no table for refinement scan */ /* DC needs no table for refinement scan */
if (progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) { if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
tbl = compptr->dc_tbl_no; tbl = compptr->dc_tbl_no;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->dc_stats[tbl] == NULL) if (entropy->dc_stats[tbl] == NULL)
entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small) entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS); ((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS);
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); memset(entropy->dc_stats[tbl], 0, DC_STAT_BINS);
/* Initialize DC predictions to 0 */ /* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0; entropy->last_dc_val[ci] = 0;
entropy->dc_context[ci] = 0; entropy->dc_context[ci] = 0;
} }
/* AC needs no table when not present */ /* AC needs no table when not present */
if (progressive_mode == 0 || cinfo->Se) { if (cinfo->progressive_mode == 0 || cinfo->Se) {
tbl = compptr->ac_tbl_no; tbl = compptr->ac_tbl_no;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS) if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->ac_stats[tbl] == NULL) if (entropy->ac_stats[tbl] == NULL)
entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small) entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS); ((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); memset(entropy->ac_stats[tbl], 0, AC_STAT_BINS);
#ifdef CALCULATE_SPECTRAL_CONDITIONING #ifdef CALCULATE_SPECTRAL_CONDITIONING
if (progressive_mode) if (cinfo->progressive_mode)
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
cinfo->arith_ac_K[tbl] = cinfo->Ss + cinfo->arith_ac_K[tbl] = cinfo->Ss +
((8 + cinfo->Se - cinfo->Ss) >> 4); ((8 + cinfo->Se - cinfo->Ss) >> 4);
@@ -939,34 +930,3 @@ jinit_arith_encoder(j_compress_ptr cinfo)
/* Initialize index for fixed probability estimation */ /* Initialize index for fixed probability estimation */
entropy->fixed_bin[0] = 113; entropy->fixed_bin[0] = 113;
} }
GLOBAL(void)
jget_arith_rates (j_compress_ptr cinfo, int dc_tbl_no, int ac_tbl_no, arith_rates *r)
{
int i;
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
r->arith_dc_L = cinfo->arith_dc_L[dc_tbl_no];
r->arith_dc_U = cinfo->arith_dc_U[dc_tbl_no];
r->arith_ac_K = cinfo->arith_ac_K[ac_tbl_no];
for (i = 0; i < DC_STAT_BINS; i++) {
int state = entropy->dc_stats[dc_tbl_no][i];
int mps_val = state >> 7;
float prob_lps = (jpeg_aritab[state & 0x7f] >> 16) / 46340.95; /* 32768*sqrt(2) */
float prob_0 = (mps_val) ? prob_lps : 1.0 - prob_lps;
float prob_1 = 1.0 - prob_0;
r->rate_dc[i][0] = -log(prob_0) / log(2.0);
r->rate_dc[i][1] = -log(prob_1) / log(2.0);
}
for (i = 0; i < AC_STAT_BINS; i++) {
int state = entropy->ac_stats[ac_tbl_no][i];
int mps_val = state >> 7;
float prob_lps = (jpeg_aritab[state & 0x7f] >> 16) / 46340.95;
float prob_0 = (mps_val) ? prob_lps : 1.0 - prob_lps;
float prob_1 = 1.0 - prob_0;
r->rate_ac[i][0] = -log(prob_0) / log(2.0);
r->rate_ac[i][1] = -log(prob_1) / log(2.0);
}
}

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1994-1997, Thomas G. Lane. * Copyright (C) 1994-1997, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code and * It was modified by The libjpeg-turbo Project to include only code and
* information relevant to libjpeg-turbo. * information relevant to libjpeg-turbo.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README 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 JPEG compressor proper.
@@ -17,7 +16,7 @@
#define JPEG_INTERNALS #define JPEG_INTERNALS
#include "jinclude.h" #include "jinclude.h"
#include "jpeglib.h" #include "jpeglib.h"
#include "jchuff.h"
/* We use a full-image coefficient buffer when doing Huffman optimization, /* We use a full-image coefficient buffer when doing Huffman optimization,
* and also for writing multiple-scan JPEG files. In all cases, the DCT * and also for writing multiple-scan JPEG files. In all cases, the DCT
@@ -53,10 +52,6 @@ typedef struct {
/* In multi-pass modes, we need a virtual block array for each component. */ /* In multi-pass modes, we need a virtual block array for each component. */
jvirt_barray_ptr whole_image[MAX_COMPONENTS]; jvirt_barray_ptr whole_image[MAX_COMPONENTS];
/* when using trellis quantization, need to keep a copy of all unquantized coefficients */
jvirt_barray_ptr whole_image_uq[MAX_COMPONENTS];
} my_coef_controller; } my_coef_controller;
typedef my_coef_controller *my_coef_ptr; typedef my_coef_controller *my_coef_ptr;
@@ -69,8 +64,6 @@ METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
JSAMPIMAGE input_buf); JSAMPIMAGE input_buf);
METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf); METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#endif #endif
METHODDEF(boolean) compress_trellis_pass
(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
LOCAL(void) LOCAL(void)
@@ -127,12 +120,6 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
coef->pub.compress_data = compress_output; coef->pub.compress_data = compress_output;
break; break;
#endif #endif
case JBUF_REQUANT:
if (coef->whole_image[0] == NULL)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
coef->pub.compress_data = compress_trellis_pass;
break;
default: default:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break; break;
@@ -188,8 +175,7 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
(*cinfo->fdct->forward_DCT) (cinfo, compptr, (*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[compptr->component_index], input_buf[compptr->component_index],
coef->MCU_buffer[blkn], coef->MCU_buffer[blkn],
ypos, xpos, (JDIMENSION) blockcnt, ypos, xpos, (JDIMENSION)blockcnt);
NULL);
if (blockcnt < compptr->MCU_width) { if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */ /* Create some dummy blocks at the right edge of the image. */
jzero_far((void *)coef->MCU_buffer[blkn + blockcnt], jzero_far((void *)coef->MCU_buffer[blkn + blockcnt],
@@ -266,7 +252,6 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
jpeg_component_info *compptr; jpeg_component_info *compptr;
JBLOCKARRAY buffer; JBLOCKARRAY buffer;
JBLOCKROW thisblockrow, lastblockrow; JBLOCKROW thisblockrow, lastblockrow;
JBLOCKARRAY buffer_dst;
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++) {
@@ -274,13 +259,7 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
buffer = (*cinfo->mem->access_virt_barray) buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr)cinfo, coef->whole_image[ci], ((j_common_ptr)cinfo, coef->whole_image[ci],
coef->iMCU_row_num * compptr->v_samp_factor, coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE); (JDIMENSION)compptr->v_samp_factor, TRUE);
buffer_dst = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image_uq[ci],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */ /* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row) if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor; block_rows = compptr->v_samp_factor;
@@ -302,9 +281,8 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
thisblockrow = buffer[block_row]; thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr, (*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow, input_buf[ci], thisblockrow,
(JDIMENSION) (block_row * DCTSIZE), (JDIMENSION)(block_row * DCTSIZE),
(JDIMENSION) 0, blocks_across, (JDIMENSION)0, blocks_across);
buffer_dst[block_row]);
if (ndummy > 0) { if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */ /* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */ thisblockrow += blocks_across; /* => first dummy block */
@@ -348,136 +326,6 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
return compress_output(cinfo, input_buf); return compress_output(cinfo, input_buf);
} }
METHODDEF(boolean)
compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION blocks_across, MCUs_across, MCUindex;
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
JCOEF lastDC;
jpeg_component_info *compptr;
JBLOCKARRAY buffer;
JBLOCKROW thisblockrow, lastblockrow;
JBLOCKARRAY buffer_dst;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
c_derived_tbl dctbl_data;
c_derived_tbl *dctbl = &dctbl_data;
c_derived_tbl actbl_data;
c_derived_tbl *actbl = &actbl_data;
#ifdef C_ARITH_CODING_SUPPORTED
arith_rates arith_r_data;
arith_rates *arith_r = &arith_r_data;
#endif
compptr = cinfo->cur_comp_info[ci];
#ifdef C_ARITH_CODING_SUPPORTED
if (cinfo->arith_code)
jget_arith_rates(cinfo, compptr->dc_tbl_no, compptr->ac_tbl_no, arith_r);
else
#endif
{
jpeg_make_c_derived_tbl(cinfo, TRUE, compptr->dc_tbl_no, &dctbl);
jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl);
}
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
buffer_dst = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image_uq[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here, since may not be set! */
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
blocks_across = compptr->width_in_blocks;
h_samp_factor = compptr->h_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
ndummy = (int) (blocks_across % h_samp_factor);
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
lastDC = 0;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks.
*/
for (block_row = 0; block_row < block_rows; block_row++) {
thisblockrow = buffer[block_row];
lastblockrow = (block_row > 0) ? buffer[block_row-1] : NULL;
#ifdef C_ARITH_CODING_SUPPORTED
if (cinfo->arith_code)
quantize_trellis_arith(cinfo, arith_r, thisblockrow,
buffer_dst[block_row], blocks_across,
cinfo->quant_tbl_ptrs[compptr->quant_tbl_no],
cinfo->master->norm_src[compptr->quant_tbl_no],
cinfo->master->norm_coef[compptr->quant_tbl_no],
&lastDC, lastblockrow, buffer_dst[block_row-1]);
else
#endif
quantize_trellis(cinfo, dctbl, actbl, thisblockrow,
buffer_dst[block_row], blocks_across,
cinfo->quant_tbl_ptrs[compptr->quant_tbl_no],
cinfo->master->norm_src[compptr->quant_tbl_no],
cinfo->master->norm_coef[compptr->quant_tbl_no],
&lastDC, lastblockrow, buffer_dst[block_row-1]);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
jzero_far((void *) thisblockrow, ndummy * sizeof(JBLOCK));
lastDC = thisblockrow[-1][0];
for (bi = 0; bi < ndummy; bi++) {
thisblockrow[bi][0] = lastDC;
}
}
}
/* If at end of image, create dummy block rows as needed.
* The tricky part here is that within each MCU, we want the DC values
* of the dummy blocks to match the last real block's DC value.
* This squeezes a few more bytes out of the resulting file...
*/
if (coef->iMCU_row_num == last_iMCU_row) {
blocks_across += ndummy; /* include lower right corner */
MCUs_across = blocks_across / h_samp_factor;
for (block_row = block_rows; block_row < compptr->v_samp_factor;
block_row++) {
thisblockrow = buffer[block_row];
lastblockrow = buffer[block_row-1];
jzero_far((void *) thisblockrow,
(size_t) (blocks_across * sizeof(JBLOCK)));
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
lastDC = lastblockrow[h_samp_factor-1][0];
for (bi = 0; bi < h_samp_factor; bi++) {
thisblockrow[bi][0] = lastDC;
}
thisblockrow += h_samp_factor; /* advance to next MCU in row */
lastblockrow += h_samp_factor;
}
}
}
}
/* 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 entropy encoder, sharing code with subsequent passes */
return compress_output(cinfo, input_buf);
}
/* /*
* Process some data in subsequent passes of a multi-pass case. * Process some data in subsequent passes of a multi-pass case.
@@ -575,20 +423,12 @@ jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer)
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++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
(JDIMENSION) jround_up((long) compptr->width_in_blocks, (JDIMENSION)jround_up((long)compptr->width_in_blocks,
(long) compptr->h_samp_factor), (long)compptr->h_samp_factor),
(JDIMENSION) jround_up((long) compptr->height_in_blocks, (JDIMENSION)jround_up((long)compptr->height_in_blocks,
(long) compptr->v_samp_factor), (long)compptr->v_samp_factor),
(JDIMENSION) compptr->v_samp_factor); (JDIMENSION)compptr->v_samp_factor);
coef->whole_image_uq[ci] = (*cinfo->mem->request_virt_barray)
((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 #else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);

View File

@@ -48,9 +48,9 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr2 = output_buf[2][output_row]; outptr2 = output_buf[2][output_row];
output_row++; output_row++;
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]); r = inptr[RGB_RED];
g = GETJSAMPLE(inptr[RGB_GREEN]); g = inptr[RGB_GREEN];
b = GETJSAMPLE(inptr[RGB_BLUE]); b = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE; inptr += RGB_PIXELSIZE;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation. * must be too; we do not need an explicit range-limiting operation.
@@ -100,9 +100,9 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr = output_buf[0][output_row]; outptr = output_buf[0][output_row];
output_row++; output_row++;
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]); r = inptr[RGB_RED];
g = GETJSAMPLE(inptr[RGB_GREEN]); g = inptr[RGB_GREEN];
b = GETJSAMPLE(inptr[RGB_BLUE]); b = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE; inptr += RGB_PIXELSIZE;
/* Y */ /* Y */
outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
@@ -135,9 +135,9 @@ rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr2 = output_buf[2][output_row]; outptr2 = output_buf[2][output_row];
output_row++; output_row++;
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
outptr0[col] = GETJSAMPLE(inptr[RGB_RED]); outptr0[col] = inptr[RGB_RED];
outptr1[col] = GETJSAMPLE(inptr[RGB_GREEN]); outptr1[col] = inptr[RGB_GREEN];
outptr2[col] = GETJSAMPLE(inptr[RGB_BLUE]); outptr2[col] = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE; inptr += RGB_PIXELSIZE;
} }
} }

View File

@@ -392,11 +392,11 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr3 = output_buf[3][output_row]; outptr3 = output_buf[3][output_row];
output_row++; output_row++;
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); r = MAXJSAMPLE - inptr[0];
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); g = MAXJSAMPLE - inptr[1];
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); b = MAXJSAMPLE - inptr[2];
/* K passes through as-is */ /* K passes through as-is */
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ outptr3[col] = inptr[3];
inptr += 4; inptr += 4;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation. * must be too; we do not need an explicit range-limiting operation.
@@ -438,7 +438,7 @@ grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr = output_buf[0][output_row]; outptr = output_buf[0][output_row];
output_row++; output_row++;
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ outptr[col] = inptr[0];
inptr += instride; inptr += instride;
} }
} }
@@ -497,7 +497,7 @@ null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
inptr = *input_buf; inptr = *input_buf;
outptr = output_buf[ci][output_row]; outptr = output_buf[ci][output_row];
for (col = 0; col < num_cols; col++) { for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ outptr[col] = inptr[ci];
inptr += nc; inptr += nc;
} }
} }

1209
jcdctmgr.c

File diff suppressed because it is too large Load Diff

219
jcext.c
View File

@@ -1,219 +0,0 @@
/*
* jcext.c
*
* Copyright (C) 2014, D. R. Commander.
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains accessor functions for extension parameters. These
* allow for extending the functionality of the libjpeg API without breaking
* backward ABI compatibility.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
GLOBAL(boolean)
jpeg_c_bool_param_supported (const j_compress_ptr cinfo, J_BOOLEAN_PARAM param)
{
switch (param) {
case JBOOLEAN_OPTIMIZE_SCANS:
case JBOOLEAN_TRELLIS_QUANT:
case JBOOLEAN_TRELLIS_QUANT_DC:
case JBOOLEAN_TRELLIS_EOB_OPT:
case JBOOLEAN_USE_LAMBDA_WEIGHT_TBL:
case JBOOLEAN_USE_SCANS_IN_TRELLIS:
case JBOOLEAN_TRELLIS_Q_OPT:
case JBOOLEAN_OVERSHOOT_DERINGING:
return TRUE;
}
return FALSE;
}
GLOBAL(void)
jpeg_c_set_bool_param (j_compress_ptr cinfo, J_BOOLEAN_PARAM param,
boolean value)
{
switch(param) {
case JBOOLEAN_OPTIMIZE_SCANS:
cinfo->master->optimize_scans = value;
break;
case JBOOLEAN_TRELLIS_QUANT:
cinfo->master->trellis_quant = value;
break;
case JBOOLEAN_TRELLIS_QUANT_DC:
cinfo->master->trellis_quant_dc = value;
break;
case JBOOLEAN_TRELLIS_EOB_OPT:
cinfo->master->trellis_eob_opt = value;
break;
case JBOOLEAN_USE_LAMBDA_WEIGHT_TBL:
cinfo->master->use_lambda_weight_tbl = value;
break;
case JBOOLEAN_USE_SCANS_IN_TRELLIS:
cinfo->master->use_scans_in_trellis = value;
break;
case JBOOLEAN_TRELLIS_Q_OPT:
cinfo->master->trellis_q_opt = value;
break;
case JBOOLEAN_OVERSHOOT_DERINGING:
cinfo->master->overshoot_deringing = value;
break;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
}
GLOBAL(boolean)
jpeg_c_get_bool_param (const j_compress_ptr cinfo, J_BOOLEAN_PARAM param)
{
switch(param) {
case JBOOLEAN_OPTIMIZE_SCANS:
return cinfo->master->optimize_scans;
case JBOOLEAN_TRELLIS_QUANT:
return cinfo->master->trellis_quant;
case JBOOLEAN_TRELLIS_QUANT_DC:
return cinfo->master->trellis_quant_dc;
case JBOOLEAN_TRELLIS_EOB_OPT:
return cinfo->master->trellis_eob_opt;
case JBOOLEAN_USE_LAMBDA_WEIGHT_TBL:
return cinfo->master->use_lambda_weight_tbl;
case JBOOLEAN_USE_SCANS_IN_TRELLIS:
return cinfo->master->use_scans_in_trellis;
case JBOOLEAN_TRELLIS_Q_OPT:
return cinfo->master->trellis_q_opt;
case JBOOLEAN_OVERSHOOT_DERINGING:
return cinfo->master->overshoot_deringing;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
return FALSE;
}
GLOBAL(boolean)
jpeg_c_float_param_supported (const j_compress_ptr cinfo, J_FLOAT_PARAM param)
{
switch (param) {
case JFLOAT_LAMBDA_LOG_SCALE1:
case JFLOAT_LAMBDA_LOG_SCALE2:
case JFLOAT_TRELLIS_DELTA_DC_WEIGHT:
return TRUE;
}
return FALSE;
}
GLOBAL(void)
jpeg_c_set_float_param (j_compress_ptr cinfo, J_FLOAT_PARAM param, float value)
{
switch (param) {
case JFLOAT_LAMBDA_LOG_SCALE1:
cinfo->master->lambda_log_scale1 = value;
break;
case JFLOAT_LAMBDA_LOG_SCALE2:
cinfo->master->lambda_log_scale2 = value;
break;
case JFLOAT_TRELLIS_DELTA_DC_WEIGHT:
cinfo->master->trellis_delta_dc_weight = value;
break;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
}
GLOBAL(float)
jpeg_c_get_float_param (const j_compress_ptr cinfo, J_FLOAT_PARAM param)
{
switch (param) {
case JFLOAT_LAMBDA_LOG_SCALE1:
return cinfo->master->lambda_log_scale1;
case JFLOAT_LAMBDA_LOG_SCALE2:
return cinfo->master->lambda_log_scale2;
case JFLOAT_TRELLIS_DELTA_DC_WEIGHT:
return cinfo->master->trellis_delta_dc_weight;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
return -1;
}
GLOBAL(boolean)
jpeg_c_int_param_supported (const j_compress_ptr cinfo, J_INT_PARAM param)
{
switch (param) {
case JINT_COMPRESS_PROFILE:
case JINT_TRELLIS_FREQ_SPLIT:
case JINT_TRELLIS_NUM_LOOPS:
case JINT_BASE_QUANT_TBL_IDX:
case JINT_DC_SCAN_OPT_MODE:
return TRUE;
}
return FALSE;
}
GLOBAL(void)
jpeg_c_set_int_param (j_compress_ptr cinfo, J_INT_PARAM param, int value)
{
switch (param) {
case JINT_COMPRESS_PROFILE:
switch (value) {
case JCP_MAX_COMPRESSION:
case JCP_FASTEST:
cinfo->master->compress_profile = value;
break;
default:
ERREXIT(cinfo, JERR_BAD_PARAM_VALUE);
}
break;
case JINT_TRELLIS_FREQ_SPLIT:
cinfo->master->trellis_freq_split = value;
break;
case JINT_TRELLIS_NUM_LOOPS:
cinfo->master->trellis_num_loops = value;
break;
case JINT_BASE_QUANT_TBL_IDX:
if (value >= 0 && value <= 8)
cinfo->master->quant_tbl_master_idx = value;
break;
case JINT_DC_SCAN_OPT_MODE:
cinfo->master->dc_scan_opt_mode = value;
break;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
}
GLOBAL(int)
jpeg_c_get_int_param (const j_compress_ptr cinfo, J_INT_PARAM param)
{
switch (param) {
case JINT_COMPRESS_PROFILE:
return cinfo->master->compress_profile;
case JINT_TRELLIS_FREQ_SPLIT:
return cinfo->master->trellis_freq_split;
case JINT_TRELLIS_NUM_LOOPS:
return cinfo->master->trellis_num_loops;
case JINT_BASE_QUANT_TBL_IDX:
return cinfo->master->quant_tbl_master_idx;
case JINT_DC_SCAN_OPT_MODE:
return cinfo->master->dc_scan_opt_mode;
default:
ERREXIT(cinfo, JERR_BAD_PARAM);
}
return -1;
}

417
jchuff.c
View File

@@ -4,8 +4,10 @@
* 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.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2014-2016, 2018-2019, D. R. Commander. * Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois. * Copyright (C) 2015, Matthieu Darbois.
* Copyright (C) 2018, Matthias Räncker.
* Copyright (C) 2020, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -43,14 +45,19 @@
*/ */
/* NOTE: Both GCC and Clang define __GNUC__ */ /* NOTE: Both GCC and Clang define __GNUC__ */
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) #if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \
defined(_M_ARM) || defined(_M_ARM64)
#if !defined(__thumb__) || defined(__thumb2__) #if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC #define USE_CLZ_INTRINSIC
#endif #endif
#endif #endif
#ifdef USE_CLZ_INTRINSIC #ifdef USE_CLZ_INTRINSIC
#if defined(_MSC_VER) && !defined(__clang__)
#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x))
#else
#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x)) #define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
#endif
#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0) #define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else #else
#include "jpeg_nbits_table.h" #include "jpeg_nbits_table.h"
@@ -65,32 +72,43 @@
* but must not be updated permanently until we complete the MCU. * but must not be updated permanently until we complete the MCU.
*/ */
#if defined(__x86_64__) && defined(__ILP32__)
typedef unsigned long long bit_buf_type;
#else
typedef size_t bit_buf_type;
#endif
/* NOTE: The more optimal Huffman encoding algorithm is only used by the
* intrinsics implementation of the Arm Neon SIMD extensions, which is why we
* retain the old Huffman encoder behavior when using the GAS implementation.
*/
#if defined(WITH_SIMD) && !(defined(__arm__) || defined(__aarch64__) || \
defined(_M_ARM) || defined(_M_ARM64))
typedef unsigned long long simd_bit_buf_type;
#else
typedef bit_buf_type simd_bit_buf_type;
#endif
#if (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 8) || defined(_WIN64) || \
(defined(__x86_64__) && defined(__ILP32__))
#define BIT_BUF_SIZE 64
#elif (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 4) || defined(_WIN32)
#define BIT_BUF_SIZE 32
#else
#error Cannot determine word size
#endif
#define SIMD_BIT_BUF_SIZE (sizeof(simd_bit_buf_type) * 8)
typedef struct { typedef struct {
size_t put_buffer; /* current bit-accumulation buffer */ union {
int put_bits; /* # of bits now in it */ bit_buf_type c;
simd_bit_buf_type simd;
} put_buffer; /* current bit accumulation buffer */
int free_bits; /* # of bits available in it */
/* (Neon GAS: # of bits now in it) */
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state; } savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest, src) \
((dest).put_buffer = (src).put_buffer, \
(dest).put_bits = (src).put_bits, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct { typedef struct {
struct jpeg_entropy_encoder pub; /* public fields */ struct jpeg_entropy_encoder pub; /* public fields */
@@ -123,6 +141,7 @@ typedef struct {
size_t free_in_buffer; /* # of byte spaces remaining in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
savable_state cur; /* Current bit buffer & DC state */ savable_state cur; /* Current bit buffer & DC state */
j_compress_ptr cinfo; /* dump_buffer needs access to this */ j_compress_ptr cinfo; /* dump_buffer needs access to this */
int simd;
} working_state; } working_state;
@@ -181,12 +200,12 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
entropy->dc_count_ptrs[dctbl] = (long *) entropy->dc_count_ptrs[dctbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long)); 257 * sizeof(long));
MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * sizeof(long)); memset(entropy->dc_count_ptrs[dctbl], 0, 257 * sizeof(long));
if (entropy->ac_count_ptrs[actbl] == NULL) if (entropy->ac_count_ptrs[actbl] == NULL)
entropy->ac_count_ptrs[actbl] = (long *) entropy->ac_count_ptrs[actbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long)); 257 * sizeof(long));
MEMZERO(entropy->ac_count_ptrs[actbl], 257 * sizeof(long)); memset(entropy->ac_count_ptrs[actbl], 0, 257 * sizeof(long));
#endif #endif
} else { } else {
/* Compute derived values for Huffman tables */ /* Compute derived values for Huffman tables */
@@ -201,8 +220,17 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
} }
/* Initialize bit buffer to empty */ /* Initialize bit buffer to empty */
entropy->saved.put_buffer = 0; if (entropy->simd) {
entropy->saved.put_bits = 0; entropy->saved.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
entropy->saved.free_bits = 0;
#else
entropy->saved.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else {
entropy->saved.put_buffer.c = 0;
entropy->saved.free_bits = BIT_BUF_SIZE;
}
/* Initialize restart stuff */ /* Initialize restart stuff */
entropy->restarts_to_go = cinfo->restart_interval; entropy->restarts_to_go = cinfo->restart_interval;
@@ -287,7 +315,8 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
* this lets us detect duplicate VAL entries here, and later * this lets us detect duplicate VAL entries here, and later
* allows emit_bits to detect any attempt to emit such symbols. * allows emit_bits to detect any attempt to emit such symbols.
*/ */
MEMZERO(dtbl->ehufsi, sizeof(dtbl->ehufsi)); memset(dtbl->ehufco, 0, sizeof(dtbl->ehufco));
memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi));
/* This is also a convenient place to check for out-of-range /* This is also a convenient place to check for out-of-range
* and duplicated VAL entries. We allow 0..255 for AC symbols * and duplicated VAL entries. We allow 0..255 for AC symbols
@@ -334,94 +363,94 @@ dump_buffer(working_state *state)
/* Outputting bits to the file */ /* Outputting bits to the file */
/* These macros perform the same task as the emit_bits() function in the /* Output byte b and, speculatively, an additional 0 byte. 0xFF must be
* original libjpeg code. In addition to reducing overhead by explicitly * encoded as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the
* inlining the code, additional performance is achieved by taking into * byte is 0xFF. Otherwise, the output buffer pointer is advanced by 1, and
* account the size of the bit buffer and waiting until it is almost full * the speculative 0 byte will be overwritten by the next byte.
* before emptying it. This mostly benefits 64-bit platforms, since 6
* bytes can be stored in a 64-bit bit buffer before it has to be emptied.
*/ */
#define EMIT_BYTE(b) { \
#define EMIT_BYTE() { \ buffer[0] = (JOCTET)(b); \
JOCTET c; \ buffer[1] = 0; \
put_bits -= 8; \ buffer -= -2 + ((JOCTET)(b) < 0xFF); \
c = (JOCTET)GETJOCTET(put_buffer >> put_bits); \
*buffer++ = c; \
if (c == 0xFF) /* need to stuff a zero byte? */ \
*buffer++ = 0; \
} }
#define PUT_BITS(code, size) { \ /* Output the entire bit buffer. If there are no 0xFF bytes in it, then write
put_bits += size; \ * directly to the output buffer. Otherwise, use the EMIT_BYTE() macro to
put_buffer = (put_buffer << size) | code; \ * encode 0xFF as 0xFF 0x00.
} */
#if BIT_BUF_SIZE == 64
#if SIZEOF_SIZE_T != 8 && !defined(_WIN64) #define FLUSH() { \
if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
#define CHECKBUF15() { \ EMIT_BYTE(put_buffer >> 56) \
if (put_bits > 15) { \ EMIT_BYTE(put_buffer >> 48) \
EMIT_BYTE() \ EMIT_BYTE(put_buffer >> 40) \
EMIT_BYTE() \ EMIT_BYTE(put_buffer >> 32) \
EMIT_BYTE(put_buffer >> 24) \
EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
EMIT_BYTE(put_buffer ) \
} else { \
buffer[0] = (JOCTET)(put_buffer >> 56); \
buffer[1] = (JOCTET)(put_buffer >> 48); \
buffer[2] = (JOCTET)(put_buffer >> 40); \
buffer[3] = (JOCTET)(put_buffer >> 32); \
buffer[4] = (JOCTET)(put_buffer >> 24); \
buffer[5] = (JOCTET)(put_buffer >> 16); \
buffer[6] = (JOCTET)(put_buffer >> 8); \
buffer[7] = (JOCTET)(put_buffer); \
buffer += 8; \
} \ } \
} }
#endif
#define CHECKBUF31() { \
if (put_bits > 31) { \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
} \
}
#define CHECKBUF47() { \
if (put_bits > 47) { \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
} \
}
#if !defined(_WIN32) && !defined(SIZEOF_SIZE_T)
#error Cannot determine word size
#endif
#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
#define EMIT_BITS(code, size) { \
CHECKBUF47() \
PUT_BITS(code, size) \
}
#define EMIT_CODE(code, size) { \
temp2 &= (((JLONG)1) << nbits) - 1; \
CHECKBUF31() \
PUT_BITS(code, size) \
PUT_BITS(temp2, nbits) \
}
#else #else
#define EMIT_BITS(code, size) { \ #define FLUSH() { \
PUT_BITS(code, size) \ if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
CHECKBUF15() \ EMIT_BYTE(put_buffer >> 24) \
} EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
#define EMIT_CODE(code, size) { \ EMIT_BYTE(put_buffer ) \
temp2 &= (((JLONG)1) << nbits) - 1; \ } else { \
PUT_BITS(code, size) \ buffer[0] = (JOCTET)(put_buffer >> 24); \
CHECKBUF15() \ buffer[1] = (JOCTET)(put_buffer >> 16); \
PUT_BITS(temp2, nbits) \ buffer[2] = (JOCTET)(put_buffer >> 8); \
CHECKBUF15() \ buffer[3] = (JOCTET)(put_buffer); \
buffer += 4; \
} \
} }
#endif #endif
/* Fill the bit buffer to capacity with the leading bits from code, then output
* the bit buffer and put the remaining bits from code into the bit buffer.
*/
#define PUT_AND_FLUSH(code, size) { \
put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
FLUSH() \
free_bits += BIT_BUF_SIZE; \
put_buffer = code; \
}
/* Insert code into the bit buffer and output the bit buffer if needed.
* NOTE: We can't flush with free_bits == 0, since the left shift in
* PUT_AND_FLUSH() would have undefined behavior.
*/
#define PUT_BITS(code, size) { \
free_bits -= size; \
if (free_bits < 0) \
PUT_AND_FLUSH(code, size) \
else \
put_buffer = (put_buffer << size) | code; \
}
#define PUT_CODE(code, size) { \
temp &= (((JLONG)1) << nbits) - 1; \
temp |= code << nbits; \
nbits += size; \
PUT_BITS(temp, nbits) \
}
/* Although it is exceedingly rare, it is possible for a Huffman-encoded /* Although it is exceedingly rare, it is possible for a Huffman-encoded
* coefficient block to be larger than the 128-byte unencoded block. For each * coefficient block to be larger than the 128-byte unencoded block. For each
@@ -444,11 +473,12 @@ dump_buffer(working_state *state)
#define STORE_BUFFER() { \ #define STORE_BUFFER() { \
if (localbuf) { \ if (localbuf) { \
size_t bytes, bytestocopy; \
bytes = buffer - _buffer; \ bytes = buffer - _buffer; \
buffer = _buffer; \ buffer = _buffer; \
while (bytes > 0) { \ while (bytes > 0) { \
bytestocopy = MIN(bytes, state->free_in_buffer); \ bytestocopy = MIN(bytes, state->free_in_buffer); \
MEMCOPY(state->next_output_byte, buffer, bytestocopy); \ memcpy(state->next_output_byte, buffer, bytestocopy); \
state->next_output_byte += bytestocopy; \ state->next_output_byte += bytestocopy; \
buffer += bytestocopy; \ buffer += bytestocopy; \
state->free_in_buffer -= bytestocopy; \ state->free_in_buffer -= bytestocopy; \
@@ -466,20 +496,46 @@ dump_buffer(working_state *state)
LOCAL(boolean) LOCAL(boolean)
flush_bits(working_state *state) flush_bits(working_state *state)
{ {
JOCTET _buffer[BUFSIZE], *buffer; JOCTET _buffer[BUFSIZE], *buffer, temp;
size_t put_buffer; int put_bits; simd_bit_buf_type put_buffer; int put_bits;
size_t bytes, bytestocopy; int localbuf = 0; int localbuf = 0;
if (state->simd) {
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
put_bits = state->cur.free_bits;
#else
put_bits = SIMD_BIT_BUF_SIZE - state->cur.free_bits;
#endif
put_buffer = state->cur.put_buffer.simd;
} else {
put_bits = BIT_BUF_SIZE - state->cur.free_bits;
put_buffer = state->cur.put_buffer.c;
}
put_buffer = state->cur.put_buffer;
put_bits = state->cur.put_bits;
LOAD_BUFFER() LOAD_BUFFER()
/* fill any partial byte with ones */ while (put_bits >= 8) {
PUT_BITS(0x7F, 7) put_bits -= 8;
while (put_bits >= 8) EMIT_BYTE() temp = (JOCTET)(put_buffer >> put_bits);
EMIT_BYTE(temp)
}
if (put_bits) {
/* fill partial byte with ones */
temp = (JOCTET)((put_buffer << (8 - put_bits)) | (0xFF >> put_bits));
EMIT_BYTE(temp)
}
state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ if (state->simd) { /* and reset bit buffer to empty */
state->cur.put_bits = 0; state->cur.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
state->cur.free_bits = 0;
#else
state->cur.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else {
state->cur.put_buffer.c = 0;
state->cur.free_bits = BIT_BUF_SIZE;
}
STORE_BUFFER() STORE_BUFFER()
return TRUE; return TRUE;
@@ -493,7 +549,7 @@ encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl) c_derived_tbl *dctbl, c_derived_tbl *actbl)
{ {
JOCTET _buffer[BUFSIZE], *buffer; JOCTET _buffer[BUFSIZE], *buffer;
size_t bytes, bytestocopy; int localbuf = 0; int localbuf = 0;
LOAD_BUFFER() LOAD_BUFFER()
@@ -509,53 +565,41 @@ LOCAL(boolean)
encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl) c_derived_tbl *dctbl, c_derived_tbl *actbl)
{ {
int temp, temp2, temp3; int temp, nbits, free_bits;
int nbits; bit_buf_type put_buffer;
int r, code, size;
JOCTET _buffer[BUFSIZE], *buffer; JOCTET _buffer[BUFSIZE], *buffer;
size_t put_buffer; int put_bits; int localbuf = 0;
int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0];
size_t bytes, bytestocopy; int localbuf = 0;
put_buffer = state->cur.put_buffer; free_bits = state->cur.free_bits;
put_bits = state->cur.put_bits; put_buffer = state->cur.put_buffer.c;
LOAD_BUFFER() LOAD_BUFFER()
/* Encode the DC coefficient difference per section F.1.2.1 */ /* Encode the DC coefficient difference per section F.1.2.1 */
temp = temp2 = block[0] - last_dc_val; temp = block[0] - last_dc_val;
/* This is a well-known technique for obtaining the absolute value without a /* This is a well-known technique for obtaining the absolute value without a
* branch. It is derived from an assembly language technique presented in * branch. It is derived from an assembly language technique presented in
* "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by * "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by
* Agner Fog. * Agner Fog. This code assumes we are on a two's complement machine.
*/ */
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); nbits = temp >> (CHAR_BIT * sizeof(int) - 1);
temp ^= temp3; temp += nbits;
temp -= temp3; nbits ^= temp;
/* For a negative input, want temp2 = bitwise complement of abs(input) */
/* This code assumes we are on a two's complement machine */
temp2 += temp3;
/* Find the number of bits needed for the magnitude of the coefficient */ /* Find the number of bits needed for the magnitude of the coefficient */
nbits = JPEG_NBITS(temp); nbits = JPEG_NBITS(nbits);
/* Emit the Huffman-coded symbol for the number of bits */ /* Emit the Huffman-coded symbol for the number of bits.
code = dctbl->ehufco[nbits]; * Emit that number of bits of the value, if positive,
size = dctbl->ehufsi[nbits]; * or the complement of its magnitude, if negative.
EMIT_BITS(code, size) */
PUT_CODE(dctbl->ehufco[nbits], dctbl->ehufsi[nbits])
/* Mask off any extra bits in code */
temp2 &= (((JLONG)1) << nbits) - 1;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
EMIT_BITS(temp2, nbits)
/* Encode the AC coefficients per section F.1.2.2 */ /* Encode the AC coefficients per section F.1.2.2 */
r = 0; /* r = run length of zeros */ {
int r = 0; /* r = run length of zeros */
/* Manually unroll the k loop to eliminate the counter variable. This /* Manually unroll the k loop to eliminate the counter variable. This
* improves performance greatly on systems with a limited number of * improves performance greatly on systems with a limited number of
@@ -563,51 +607,46 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
*/ */
#define kloop(jpeg_natural_order_of_k) { \ #define kloop(jpeg_natural_order_of_k) { \
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \ if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
r++; \ r += 16; \
} else { \ } else { \
temp2 = temp; \
/* Branch-less absolute value, bitwise complement, etc., same as above */ \ /* Branch-less absolute value, bitwise complement, etc., same as above */ \
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); \ nbits = temp >> (CHAR_BIT * sizeof(int) - 1); \
temp ^= temp3; \ temp += nbits; \
temp -= temp3; \ nbits ^= temp; \
temp2 += temp3; \ nbits = JPEG_NBITS_NONZERO(nbits); \
nbits = JPEG_NBITS_NONZERO(temp); \
/* if run length > 15, must emit special run-length-16 codes (0xF0) */ \ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
while (r > 15) { \ while (r >= 16 * 16) { \
EMIT_BITS(code_0xf0, size_0xf0) \ r -= 16 * 16; \
r -= 16; \ PUT_BITS(actbl->ehufco[0xf0], actbl->ehufsi[0xf0]) \
} \ } \
/* Emit Huffman symbol for run length / number of bits */ \ /* Emit Huffman symbol for run length / number of bits */ \
temp3 = (r << 4) + nbits; \ r += nbits; \
code = actbl->ehufco[temp3]; \ PUT_CODE(actbl->ehufco[r], actbl->ehufsi[r]) \
size = actbl->ehufsi[temp3]; \
EMIT_CODE(code, size) \
r = 0; \ r = 0; \
} \ } \
} }
/* One iteration for each value in jpeg_natural_order[] */ /* One iteration for each value in jpeg_natural_order[] */
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3); kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18); kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26); kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27); kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21); kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57); kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15); kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58); kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39); kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47); kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
kloop(55); kloop(62); kloop(63); kloop(55); kloop(62); kloop(63);
/* If the last coef(s) were zero, emit an end-of-block code */ /* If the last coef(s) were zero, emit an end-of-block code */
if (r > 0) { if (r > 0) {
code = actbl->ehufco[0]; PUT_BITS(actbl->ehufco[0], actbl->ehufsi[0])
size = actbl->ehufsi[0]; }
EMIT_BITS(code, size)
} }
state->cur.put_buffer = put_buffer; state->cur.put_buffer.c = put_buffer;
state->cur.put_bits = put_bits; state->cur.free_bits = free_bits;
STORE_BUFFER() STORE_BUFFER()
return TRUE; return TRUE;
@@ -654,8 +693,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Load up working state */ /* Load up working state */
state.next_output_byte = cinfo->dest->next_output_byte; state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer; state.free_in_buffer = cinfo->dest->free_in_buffer;
ASSIGN_STATE(state.cur, entropy->saved); state.cur = entropy->saved;
state.cinfo = cinfo; state.cinfo = cinfo;
state.simd = entropy->simd;
/* Emit restart marker if needed */ /* Emit restart marker if needed */
if (cinfo->restart_interval) { if (cinfo->restart_interval) {
@@ -694,7 +734,7 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Completed MCU, so update state */ /* Completed MCU, so update state */
cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer; cinfo->dest->free_in_buffer = state.free_in_buffer;
ASSIGN_STATE(entropy->saved, state.cur); entropy->saved = state.cur;
/* Update restart-interval state too */ /* Update restart-interval state too */
if (cinfo->restart_interval) { if (cinfo->restart_interval) {
@@ -723,8 +763,9 @@ finish_pass_huff(j_compress_ptr cinfo)
/* Load up working state ... flush_bits needs it */ /* Load up working state ... flush_bits needs it */
state.next_output_byte = cinfo->dest->next_output_byte; state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer; state.free_in_buffer = cinfo->dest->free_in_buffer;
ASSIGN_STATE(state.cur, entropy->saved); state.cur = entropy->saved;
state.cinfo = cinfo; state.cinfo = cinfo;
state.simd = entropy->simd;
/* Flush out the last data */ /* Flush out the last data */
if (!flush_bits(&state)) if (!flush_bits(&state))
@@ -733,7 +774,7 @@ finish_pass_huff(j_compress_ptr cinfo)
/* Update state */ /* Update state */
cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer; cinfo->dest->free_in_buffer = state.free_in_buffer;
ASSIGN_STATE(entropy->saved, state.cur); entropy->saved = state.cur;
} }
@@ -900,8 +941,8 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
/* This algorithm is explained in section K.2 of the JPEG standard */ /* This algorithm is explained in section K.2 of the JPEG standard */
MEMZERO(bits, sizeof(bits)); memset(bits, 0, sizeof(bits));
MEMZERO(codesize, sizeof(codesize)); memset(codesize, 0, sizeof(codesize));
for (i = 0; i < 257; i++) for (i = 0; i < 257; i++)
others[i] = -1; /* init links to empty */ others[i] = -1; /* init links to empty */
@@ -1003,7 +1044,7 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
bits[i]--; bits[i]--;
/* Return final symbol counts (only for lengths 0..16) */ /* Return final symbol counts (only for lengths 0..16) */
MEMCOPY(htbl->bits, bits, sizeof(htbl->bits)); memcpy(htbl->bits, bits, sizeof(htbl->bits));
/* Return a list of the symbols sorted by code length */ /* Return a list of the symbols sorted by code length */
/* It's not real clear to me why we don't need to consider the codelength /* It's not real clear to me why we don't need to consider the codelength
@@ -1042,8 +1083,8 @@ finish_pass_gather(j_compress_ptr cinfo)
/* It's important not to apply jpeg_gen_optimal_table more than once /* It's important not to apply jpeg_gen_optimal_table more than once
* per table, because it clobbers the input frequency counts! * per table, because it clobbers the input frequency counts!
*/ */
MEMZERO(did_dc, sizeof(did_dc)); memset(did_dc, 0, sizeof(did_dc));
MEMZERO(did_ac, sizeof(did_ac)); memset(did_ac, 0, sizeof(did_ac));
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];

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1991-1997, Thomas G. Lane. * Copyright (C) 1991-1997, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code relevant * It was modified by The libjpeg-turbo Project to include only code relevant
* to libjpeg-turbo. * to libjpeg-turbo.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains declarations for Huffman entropy encoding routines * This file contains declarations for Huffman entropy encoding routines
* that are shared between the sequential encoder (jchuff.c) and the * that are shared between the sequential encoder (jchuff.c) and the
@@ -21,9 +20,9 @@
*/ */
#if BITS_IN_JSAMPLE == 8 #if BITS_IN_JSAMPLE == 8
#define MAX_COEF_BITS 10 #define MAX_COEF_BITS 10
#else #else
#define MAX_COEF_BITS 14 #define MAX_COEF_BITS 14
#endif #endif
/* Derived data constructed for each Huffman table */ /* Derived data constructed for each Huffman table */
@@ -39,10 +38,5 @@ EXTERN(void) jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC,
int tblno, c_derived_tbl **pdtbl); int tblno, c_derived_tbl **pdtbl);
/* Generate an optimal table definition given the specified counts */ /* Generate an optimal table definition given the specified counts */
EXTERN(void) jpeg_gen_optimal_table EXTERN(void) jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl,
(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]); long freq[]);
EXTERN(void) quantize_trellis
(j_compress_ptr cinfo, c_derived_tbl *dctbl, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef, JCOEF *last_dc_val,
JBLOCKROW coef_blocks_above, JBLOCKROW src_above);

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1991-1997, Thomas G. Lane. * Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2020, D. R. Commander. * Copyright (C) 2020, D. R. Commander.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains initialization logic for the JPEG compressor. * This file contains initialization logic for the JPEG compressor.
* This routine is in charge of selecting the modules to be executed and * This routine is in charge of selecting the modules to be executed and
@@ -32,13 +31,13 @@
*/ */
GLOBAL(void) GLOBAL(void)
jinit_compress_master (j_compress_ptr cinfo) jinit_compress_master(j_compress_ptr cinfo)
{ {
/* Initialize master control (includes parameter checking/processing) */ /* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */); jinit_c_master_control(cinfo, FALSE /* full compression */);
/* Preprocessing */ /* Preprocessing */
if (! cinfo->raw_data_in) { if (!cinfo->raw_data_in) {
jinit_color_converter(cinfo); jinit_color_converter(cinfo);
jinit_downsampler(cinfo); jinit_downsampler(cinfo);
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
@@ -64,15 +63,14 @@ jinit_compress_master (j_compress_ptr cinfo)
} }
/* Need a full-image coefficient buffer in any multi-pass mode. */ /* Need a full-image coefficient buffer in any multi-pass mode. */
jinit_c_coef_controller(cinfo, jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding || cinfo->optimize_coding));
cinfo->master->optimize_scans || cinfo->master->trellis_quant));
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);
/* We can now tell the memory manager to allocate virtual arrays. */ /* We can now tell the memory manager to allocate virtual arrays. */
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Write the datastream header (SOI) immediately. /* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later. * Frame and scan headers are postponed till later.

View File

@@ -184,72 +184,6 @@ emit_dqt(j_compress_ptr cinfo, int index)
return prec; return prec;
} }
LOCAL(int)
emit_multi_dqt (j_compress_ptr cinfo)
/* Emits a DQT marker containing all quantization tables */
/* Returns number of emitted 16-bit tables, or -1 for failed for baseline checking. */
{
int prec[MAX_COMPONENTS];
int seen[MAX_COMPONENTS] = { 0 };
int fin_prec = 0;
int ci;
int size = 0;
if (cinfo->master->compress_profile == JCP_FASTEST)
return -1;
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
int i;
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[tbl_num];
if (qtbl == NULL || qtbl->sent_table == TRUE)
return -1;
prec[ci] = 0;
for (i = 0; i < DCTSIZE2; i++)
prec[ci] = !!(prec[ci] + (qtbl->quantval[i] > 255));
fin_prec += prec[ci];
}
emit_marker(cinfo, M_DQT);
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
if (!seen[tbl_num]) {
size += DCTSIZE2 * (prec[ci] + 1) + 1;
seen[tbl_num] = 1;
}
}
size += 2;
emit_2bytes(cinfo, size);
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
int i;
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[tbl_num];
if (qtbl->sent_table == TRUE)
continue;
emit_byte(cinfo, tbl_num + (prec[ci] << 4));
for (i = 0; i < DCTSIZE2; i++) {
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec[ci])
emit_byte(cinfo, (int) (qval >> 8));
emit_byte(cinfo, (int) (qval & 0xFF));
}
qtbl->sent_table = TRUE;
}
return fin_prec;
}
LOCAL(void) LOCAL(void)
emit_dht(j_compress_ptr cinfo, int index, boolean is_ac) emit_dht(j_compress_ptr cinfo, int index, boolean is_ac)
@@ -288,115 +222,6 @@ emit_dht(j_compress_ptr cinfo, int index, boolean is_ac)
} }
} }
LOCAL(boolean)
emit_multi_dht (j_compress_ptr cinfo)
/* Emit all DHT markers */
/* Returns FALSE on failure, TRUE otherwise. */
{
int i, j;
int length = 2;
int dclens[NUM_HUFF_TBLS] = { 0 };
int aclens[NUM_HUFF_TBLS] = { 0 };
JHUFF_TBL *dcseen[NUM_HUFF_TBLS] = { NULL };
JHUFF_TBL *acseen[NUM_HUFF_TBLS] = { NULL };
if (cinfo->master->compress_profile == JCP_FASTEST)
return 0;
/* Calclate the total length. */
for (i = 0; i < cinfo->comps_in_scan; i++) {
jpeg_component_info *compptr = cinfo->cur_comp_info[i];
int dcidx = compptr->dc_tbl_no;
int acidx = compptr->ac_tbl_no;
JHUFF_TBL *dctbl = cinfo->dc_huff_tbl_ptrs[dcidx];
JHUFF_TBL *actbl = cinfo->ac_huff_tbl_ptrs[acidx];
int seen = 0;
/* Handle DC table lenghts */
if (cinfo->Ss == 0 && cinfo->Ah == 0) {
if (dctbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dcidx);
if (dctbl->sent_table)
continue;
for (j = 0; j < NUM_HUFF_TBLS; j++)
seen += (dctbl == dcseen[j]);
if (seen)
continue;
dcseen[i] = dctbl;
for (j = 1; j <= 16; j++)
dclens[i] += dctbl->bits[j];
length += dclens[i] + 16 + 1;
}
/* Handle AC table lengths */
if (cinfo->Se) {
if (actbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, acidx + 0x10);
if (actbl->sent_table)
continue;
seen = 0;
for (j = 0; j < NUM_HUFF_TBLS; j++)
seen += (actbl == acseen[j]);
if (seen)
continue;
acseen[i] = actbl;
for (j = 1; j <= 16; j++)
aclens[i] += actbl->bits[j];
length += aclens[i] + 16 + 1;
}
}
/* Make sure we can fit it all into one DHT marker */
if (length > (1 << 16) - 1)
return FALSE;
emit_marker(cinfo, M_DHT);
emit_2bytes(cinfo, length);
for (i = 0; i < cinfo->comps_in_scan; i++) {
jpeg_component_info *compptr = cinfo->cur_comp_info[i];
int dcidx = compptr->dc_tbl_no;
int acidx = compptr->ac_tbl_no;
JHUFF_TBL *dctbl = cinfo->dc_huff_tbl_ptrs[dcidx];
JHUFF_TBL *actbl = cinfo->ac_huff_tbl_ptrs[acidx];
acidx += 0x10;
/* DC */
if (cinfo->Ss == 0 && cinfo->Ah == 0 && !dctbl->sent_table) {
emit_byte(cinfo, dcidx);
for (j = 1; j <= 16; j++)
emit_byte(cinfo, dctbl->bits[j]);
for (j = 0; j < dclens[i]; j++)
emit_byte(cinfo, dctbl->huffval[j]);
dctbl->sent_table = TRUE;
}
if (cinfo->Se && !actbl->sent_table) {
emit_byte(cinfo, acidx);
for (j = 1; j <= 16; j++)
emit_byte(cinfo, actbl->bits[j]);
for (j = 0; j < aclens[i]; j++)
emit_byte(cinfo, actbl->huffval[j]);
actbl->sent_table = TRUE;
}
}
return TRUE;
}
LOCAL(void) LOCAL(void)
emit_dac(j_compress_ptr cinfo) emit_dac(j_compress_ptr cinfo)
@@ -679,14 +504,11 @@ write_frame_header(j_compress_ptr cinfo)
/* Emit DQT for each quantization table. /* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables. * Note that emit_dqt() suppresses any duplicate tables.
*/ */
prec = emit_multi_dqt(cinfo);
if (prec == -1) {
prec = 0; 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.
@@ -749,7 +571,6 @@ write_scan_header(j_compress_ptr cinfo)
/* Emit Huffman tables. /* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables. * Note that emit_dht() suppresses any duplicate tables.
*/ */
if (!emit_multi_dht(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 */
@@ -760,7 +581,6 @@ write_scan_header(j_compress_ptr cinfo)
emit_dht(cinfo, compptr->ac_tbl_no, TRUE); emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
} }
} }
}
/* Emit DRI if required --- note that DRI value could change for each scan. /* Emit DRI if required --- note that DRI value could change for each scan.
* We avoid wasting space with unnecessary DRIs, however. * We avoid wasting space with unnecessary DRIs, however.

View File

@@ -6,9 +6,8 @@
* Modified 2003-2010 by Guido Vollbeding. * Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2010, 2016, 2018, D. R. Commander. * Copyright (C) 2010, 2016, 2018, D. R. Commander.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains master control logic for the JPEG compressor. * This file contains master control logic for the JPEG compressor.
* These routines are concerned with parameter validation, initial setup, * These routines are concerned with parameter validation, initial setup,
@@ -21,11 +20,41 @@
#include "jpeglib.h" #include "jpeglib.h"
#include "jpegcomp.h" #include "jpegcomp.h"
#include "jconfigint.h" #include "jconfigint.h"
#include "jmemsys.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;
/*
* Support routines that do various essential calculations. * Support routines that do various essential calculations.
*/ */
@@ -37,7 +66,7 @@
*/ */
GLOBAL(void) 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 */
{ {
/* Hardwire it to "no scaling" */ /* Hardwire it to "no scaling" */
@@ -50,7 +79,7 @@ jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
LOCAL(void) LOCAL(void)
initial_setup (j_compress_ptr cinfo, boolean transcode_only) initial_setup(j_compress_ptr cinfo, boolean transcode_only)
/* Do computations that are needed before master selection phase */ /* Do computations that are needed before master selection phase */
{ {
int ci; int ci;
@@ -71,14 +100,14 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
ERREXIT(cinfo, JERR_EMPTY_IMAGE); ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */ /* Make sure image isn't bigger than I can handle */
if ((long) cinfo->_jpeg_height > (long) JPEG_MAX_DIMENSION || if ((long)cinfo->_jpeg_height > (long)JPEG_MAX_DIMENSION ||
(long) cinfo->_jpeg_width > (long) JPEG_MAX_DIMENSION) (long)cinfo->_jpeg_width > (long)JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */ /* Width of an input scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; samplesperrow = (long)cinfo->image_width * (long)cinfo->input_components;
jd_samplesperrow = (JDIMENSION) samplesperrow; jd_samplesperrow = (JDIMENSION)samplesperrow;
if ((long) jd_samplesperrow != samplesperrow) if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */ /* For now, precision must match compiled-in value... */
@@ -119,18 +148,18 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
#endif #endif
/* Size in DCT blocks */ /* Size in DCT blocks */
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 * DCTSIZE));
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 * DCTSIZE));
/* 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,
(long) cinfo->max_h_samp_factor); (long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION) compptr->downsampled_height = (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); (long)cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */ /* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE; compptr->component_needed = TRUE;
} }
@@ -139,15 +168,15 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
* main controller will call coefficient controller). * main controller will call coefficient 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 * DCTSIZE));
} }
#ifdef C_MULTISCAN_FILES_SUPPORTED #ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL(void) LOCAL(void)
validate_script (j_compress_ptr cinfo) validate_script(j_compress_ptr cinfo)
/* Verify that the scan script in cinfo->scan_info[] is valid; also /* Verify that the scan script in cinfo->scan_info[] is valid; also
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode. * determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
*/ */
@@ -162,14 +191,6 @@ validate_script (j_compress_ptr cinfo)
/* -1 until that coefficient has been seen; then last Al for it */ /* -1 until that coefficient has been seen; then last Al for it */
#endif #endif
if (cinfo->master->optimize_scans) {
cinfo->progressive_mode = TRUE;
/* When we optimize scans, there is redundancy in the scan list
* and this function will fail. Therefore skip all this checking
*/
return;
}
if (cinfo->num_scans <= 0) if (cinfo->num_scans <= 0)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
@@ -177,10 +198,10 @@ validate_script (j_compress_ptr cinfo)
* for progressive JPEG, no scan can have this. * for progressive JPEG, no scan can have this.
*/ */
scanptr = cinfo->scan_info; scanptr = cinfo->scan_info;
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;
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++)
*last_bitpos_ptr++ = -1; *last_bitpos_ptr++ = -1;
@@ -203,7 +224,7 @@ validate_script (j_compress_ptr cinfo)
if (thisi < 0 || thisi >= cinfo->num_components) if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */ /* Components must appear in SOF order within each scan */
if (ci > 0 && thisi <= scanptr->component_index[ci-1]) if (ci > 0 && thisi <= scanptr->component_index[ci - 1])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
} }
/* Validate progression parameters */ /* Validate progression parameters */
@@ -221,9 +242,9 @@ validate_script (j_compress_ptr cinfo)
* which might cause problems for some decoders. * which might cause problems for some decoders.
*/ */
#if BITS_IN_JSAMPLE == 8 #if BITS_IN_JSAMPLE == 8
#define MAX_AH_AL 10 #define MAX_AH_AL 10
#else #else
#define MAX_AH_AL 13 #define MAX_AH_AL 13
#endif #endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
@@ -236,7 +257,7 @@ validate_script (j_compress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} }
for (ci = 0; ci < ncomps; ci++) { for (ci = 0; ci < ncomps; ci++) {
last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; last_bitpos_ptr = &last_bitpos[scanptr->component_index[ci]][0];
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) { for (coefi = Ss; coefi <= Se; coefi++) {
@@ -246,7 +267,7 @@ validate_script (j_compress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else { } else {
/* not first scan */ /* not first scan */
if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) if (Ah != last_bitpos_ptr[coefi] || Al != Ah - 1)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} }
last_bitpos_ptr[coefi] = Al; last_bitpos_ptr[coefi] = Al;
@@ -255,7 +276,7 @@ validate_script (j_compress_ptr cinfo)
#endif #endif
} else { } else {
/* For sequential JPEG, all progression parameters must be these: */ /* For sequential JPEG, all progression parameters must be these: */
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); 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++) {
@@ -282,7 +303,7 @@ validate_script (j_compress_ptr cinfo)
#endif #endif
} else { } else {
for (ci = 0; ci < cinfo->num_components; ci++) { for (ci = 0; ci < cinfo->num_components; ci++) {
if (! component_sent[ci]) if (!component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA); ERREXIT(cinfo, JERR_MISSING_DATA);
} }
} }
@@ -292,33 +313,15 @@ validate_script (j_compress_ptr cinfo)
LOCAL(void) LOCAL(void)
select_scan_parameters (j_compress_ptr cinfo) select_scan_parameters(j_compress_ptr cinfo)
/* Set up the scan parameters for the current scan */ /* Set up the scan parameters for the current scan */
{ {
int ci; int ci;
#ifdef C_MULTISCAN_FILES_SUPPORTED #ifdef C_MULTISCAN_FILES_SUPPORTED
my_master_ptr master = (my_master_ptr) cinfo->master; if (cinfo->scan_info != NULL) {
if (master->pass_number < master->pass_number_scan_opt_base) {
cinfo->comps_in_scan = 1;
if (cinfo->master->use_scans_in_trellis) {
cinfo->cur_comp_info[0] =
&cinfo->comp_info[master->pass_number /
(4 * cinfo->master->trellis_num_loops)];
cinfo->Ss = (master->pass_number % 4 < 2) ?
1 : cinfo->master->trellis_freq_split + 1;
cinfo->Se = (master->pass_number % 4 < 2) ?
cinfo->master->trellis_freq_split : DCTSIZE2 - 1;
} else {
cinfo->cur_comp_info[0] =
&cinfo->comp_info[master->pass_number /
(2 * cinfo->master->trellis_num_loops)];
cinfo->Ss = 1;
cinfo->Se = DCTSIZE2-1;
}
}
else 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;
const jpeg_scan_info *scanptr = cinfo->scan_info + master->scan_number; const jpeg_scan_info *scanptr = cinfo->scan_info + master->scan_number;
cinfo->comps_in_scan = scanptr->comps_in_scan; cinfo->comps_in_scan = scanptr->comps_in_scan;
@@ -330,23 +333,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->Se = scanptr->Se; cinfo->Se = scanptr->Se;
cinfo->Ah = scanptr->Ah; cinfo->Ah = scanptr->Ah;
cinfo->Al = scanptr->Al; cinfo->Al = scanptr->Al;
if (cinfo->master->optimize_scans) { } else
/* luma frequency split passes */
if (master->scan_number >= cinfo->master->num_scans_luma_dc +
3 * cinfo->master->Al_max_luma + 2 &&
master->scan_number < cinfo->master->num_scans_luma)
cinfo->Al = master->best_Al_luma;
/* chroma frequency split passes */
if (master->scan_number >= cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc +
(6 * cinfo->master->Al_max_chroma + 4) &&
master->scan_number < cinfo->num_scans)
cinfo->Al = master->best_Al_chroma;
}
/* save value for later retrieval during printout of scans */
master->actual_Al[master->scan_number] = cinfo->Al;
}
else
#endif #endif
{ {
/* Prepare for single sequential-JPEG scan containing all components */ /* Prepare for single sequential-JPEG scan containing all components */
@@ -358,7 +345,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
} }
cinfo->Ss = 0; cinfo->Ss = 0;
cinfo->Se = DCTSIZE2-1; cinfo->Se = DCTSIZE2 - 1;
cinfo->Ah = 0; cinfo->Ah = 0;
cinfo->Al = 0; cinfo->Al = 0;
} }
@@ -366,7 +353,7 @@ select_scan_parameters (j_compress_ptr cinfo)
LOCAL(void) LOCAL(void)
per_scan_setup (j_compress_ptr cinfo) per_scan_setup(j_compress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */ /* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{ {
@@ -391,7 +378,7 @@ per_scan_setup (j_compress_ptr cinfo)
/* 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.
*/ */
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;
compptr->last_row_height = tmp; compptr->last_row_height = tmp;
@@ -408,11 +395,11 @@ 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 * DCTSIZE));
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 * DCTSIZE));
cinfo->blocks_in_MCU = 0; cinfo->blocks_in_MCU = 0;
@@ -424,10 +411,10 @@ per_scan_setup (j_compress_ptr cinfo)
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 * DCTSIZE;
/* 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;
compptr->last_col_width = tmp; compptr->last_col_width = tmp;
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); tmp = (int)(compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height; if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp; compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */ /* Prepare array describing MCU composition */
@@ -444,8 +431,8 @@ per_scan_setup (j_compress_ptr cinfo)
/* Convert restart specified in rows to actual MCU count. */ /* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */ /* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) { if (cinfo->restart_in_rows > 0) {
long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; long nominal = (long)cinfo->restart_in_rows * (long)cinfo->MCUs_per_row;
cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); cinfo->restart_interval = (unsigned int)MIN(nominal, 65535L);
} }
} }
@@ -459,11 +446,9 @@ per_scan_setup (j_compress_ptr cinfo)
*/ */
METHODDEF(void) METHODDEF(void)
prepare_for_pass (j_compress_ptr cinfo) prepare_for_pass(j_compress_ptr cinfo)
{ {
my_master_ptr master = (my_master_ptr) cinfo->master; my_master_ptr master = (my_master_ptr)cinfo->master;
cinfo->master->trellis_passes =
master->pass_number < master->pass_number_scan_opt_base;
switch (master->pass_type) { switch (master->pass_type) {
case main_pass: case main_pass:
@@ -472,18 +457,18 @@ prepare_for_pass (j_compress_ptr cinfo)
*/ */
select_scan_parameters(cinfo); select_scan_parameters(cinfo);
per_scan_setup(cinfo); per_scan_setup(cinfo);
if (! cinfo->raw_data_in) { if (!cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo); (*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
} }
(*cinfo->fdct->start_pass) (cinfo); (*cinfo->fdct->start_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo, (cinfo->optimize_coding || cinfo->master->trellis_quant) && !cinfo->arith_code); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
(*cinfo->coef->start_pass) (cinfo, (*cinfo->coef->start_pass) (cinfo,
(master->total_passes > 1 ? (master->total_passes > 1 ?
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
if (cinfo->optimize_coding || cinfo->master->trellis_quant) { if (cinfo->optimize_coding) {
/* No immediate data output; postpone writing frame/scan headers */ /* No immediate data output; postpone writing frame/scan headers */
master->pub.call_pass_startup = FALSE; master->pub.call_pass_startup = FALSE;
} else { } else {
@@ -508,21 +493,14 @@ prepare_for_pass (j_compress_ptr cinfo)
master->pass_type = output_pass; master->pass_type = output_pass;
master->pass_number++; master->pass_number++;
#endif #endif
/*FALLTHROUGH*/ FALLTHROUGH /*FALLTHROUGH*/
case output_pass: case output_pass:
/* Do a data-output pass. */ /* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */ /* We need not repeat per-scan setup if prior optimization pass did it. */
if (! cinfo->optimize_coding) { if (!cinfo->optimize_coding) {
select_scan_parameters(cinfo); select_scan_parameters(cinfo);
per_scan_setup(cinfo); per_scan_setup(cinfo);
} }
if (cinfo->master->optimize_scans) {
master->saved_dest = cinfo->dest;
cinfo->dest = NULL;
master->scan_size[master->scan_number] = 0;
jpeg_mem_dest_internal(cinfo, &master->scan_buffer[master->scan_number], &master->scan_size[master->scan_number], JPOOL_IMAGE);
(*cinfo->dest->init_destination)(cinfo);
}
(*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->entropy->start_pass) (cinfo, FALSE);
(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
/* We emit frame/scan headers now */ /* We emit frame/scan headers now */
@@ -531,29 +509,11 @@ prepare_for_pass (j_compress_ptr cinfo)
(*cinfo->marker->write_scan_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo);
master->pub.call_pass_startup = FALSE; master->pub.call_pass_startup = FALSE;
break; break;
case trellis_pass:
if (master->pass_number %
(cinfo->num_components * (cinfo->master->use_scans_in_trellis ? 4 : 2)) == 1 &&
cinfo->master->trellis_q_opt) {
int i, j;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
for (j = 1; j < DCTSIZE2; j++) {
cinfo->master->norm_src[i][j] = 0.0;
cinfo->master->norm_coef[i][j] = 0.0;
}
}
}
(*cinfo->entropy->start_pass) (cinfo, !cinfo->arith_code);
(*cinfo->coef->start_pass) (cinfo, JBUF_REQUANT);
master->pub.call_pass_startup = FALSE;
break;
default: default:
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOT_COMPILED);
} }
master->pub.is_last_pass = (master->pass_number == master->total_passes-1); master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
/* Set up progress monitor's pass info if present */ /* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) { if (cinfo->progress != NULL) {
@@ -574,7 +534,7 @@ prepare_for_pass (j_compress_ptr cinfo)
*/ */
METHODDEF(void) METHODDEF(void)
pass_startup (j_compress_ptr cinfo) pass_startup(j_compress_ptr cinfo)
{ {
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
@@ -583,240 +543,14 @@ pass_startup (j_compress_ptr cinfo)
} }
LOCAL(void)
copy_buffer (j_compress_ptr cinfo, int scan_idx)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
unsigned long size = master->scan_size[scan_idx];
unsigned char * src = master->scan_buffer[scan_idx];
int i;
if (cinfo->err->trace_level > 0) {
fprintf(stderr, "SCAN ");
for (i = 0; i < cinfo->scan_info[scan_idx].comps_in_scan; i++)
fprintf(stderr, "%s%d", (i==0)?"":",", cinfo->scan_info[scan_idx].component_index[i]);
fprintf(stderr, ": %d %d", cinfo->scan_info[scan_idx].Ss, cinfo->scan_info[scan_idx].Se);
fprintf(stderr, " %d %d", cinfo->scan_info[scan_idx].Ah, master->actual_Al[scan_idx]);
fprintf(stderr, "\n");
}
while (size >= cinfo->dest->free_in_buffer)
{
MEMCOPY(cinfo->dest->next_output_byte, src, cinfo->dest->free_in_buffer);
src += cinfo->dest->free_in_buffer;
size -= cinfo->dest->free_in_buffer;
cinfo->dest->next_output_byte += cinfo->dest->free_in_buffer;
cinfo->dest->free_in_buffer = 0;
if (!(*cinfo->dest->empty_output_buffer)(cinfo))
ERREXIT(cinfo, JERR_UNSUPPORTED_SUSPEND);
}
MEMCOPY(cinfo->dest->next_output_byte, src, size);
cinfo->dest->next_output_byte += size;
cinfo->dest->free_in_buffer -= size;
}
LOCAL(void)
select_scans (j_compress_ptr cinfo, int next_scan_number)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
int base_scan_idx = 0;
int luma_freq_split_scan_start = cinfo->master->num_scans_luma_dc +
3 * cinfo->master->Al_max_luma + 2;
int chroma_freq_split_scan_start = cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc +
(6 * cinfo->master->Al_max_chroma + 4);
int passes_per_scan = cinfo->optimize_coding ? 2 : 1;
if (next_scan_number > 1 && next_scan_number <= luma_freq_split_scan_start) {
if ((next_scan_number - 1) % 3 == 2) {
int Al = (next_scan_number - 1) / 3;
int i;
unsigned long cost = 0;
cost += master->scan_size[next_scan_number-2];
cost += master->scan_size[next_scan_number-1];
for (i = 0; i < Al; i++)
cost += master->scan_size[3 + 3*i];
if (Al == 0 || cost < master->best_cost) {
master->best_cost = cost;
master->best_Al_luma = Al;
} else {
master->scan_number = luma_freq_split_scan_start - 1;
master->pass_number = passes_per_scan * (master->scan_number + 1) - 1 + master->pass_number_scan_opt_base;
}
}
} else if (next_scan_number > luma_freq_split_scan_start &&
next_scan_number <= cinfo->master->num_scans_luma) {
if (next_scan_number == luma_freq_split_scan_start + 1) {
master->best_freq_split_idx_luma = 0;
master->best_cost = master->scan_size[next_scan_number-1];
} else if ((next_scan_number - luma_freq_split_scan_start) % 2 == 1) {
int idx = (next_scan_number - luma_freq_split_scan_start) >> 1;
unsigned long cost = 0;
cost += master->scan_size[next_scan_number-2];
cost += master->scan_size[next_scan_number-1];
if (cost < master->best_cost) {
master->best_cost = cost;
master->best_freq_split_idx_luma = idx;
}
/* if after testing first 3, no split is the best, don't search further */
if ((idx == 2 && master->best_freq_split_idx_luma == 0) ||
(idx == 3 && master->best_freq_split_idx_luma != 2) ||
(idx == 4 && master->best_freq_split_idx_luma != 4)) {
master->scan_number = cinfo->master->num_scans_luma - 1;
master->pass_number = passes_per_scan * (master->scan_number + 1) - 1 + master->pass_number_scan_opt_base;
master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
}
}
} else if (cinfo->num_scans > cinfo->master->num_scans_luma) {
if (next_scan_number == cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc) {
base_scan_idx = cinfo->master->num_scans_luma;
master->interleave_chroma_dc = master->scan_size[base_scan_idx] <= master->scan_size[base_scan_idx+1] + master->scan_size[base_scan_idx+2];
} else if (next_scan_number > cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc &&
next_scan_number <= chroma_freq_split_scan_start) {
base_scan_idx = cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc;
if ((next_scan_number - base_scan_idx) % 6 == 4) {
int Al = (next_scan_number - base_scan_idx) / 6;
int i;
unsigned long cost = 0;
cost += master->scan_size[next_scan_number-4];
cost += master->scan_size[next_scan_number-3];
cost += master->scan_size[next_scan_number-2];
cost += master->scan_size[next_scan_number-1];
for (i = 0; i < Al; i++) {
cost += master->scan_size[base_scan_idx + 4 + 6*i];
cost += master->scan_size[base_scan_idx + 5 + 6*i];
}
if (Al == 0 || cost < master->best_cost) {
master->best_cost = cost;
master->best_Al_chroma = Al;
} else {
master->scan_number = chroma_freq_split_scan_start - 1;
master->pass_number = passes_per_scan * (master->scan_number + 1) - 1 + master->pass_number_scan_opt_base;
}
}
} else if (next_scan_number > chroma_freq_split_scan_start && next_scan_number <= cinfo->num_scans) {
if (next_scan_number == chroma_freq_split_scan_start + 2) {
master->best_freq_split_idx_chroma = 0;
master->best_cost = master->scan_size[next_scan_number-2];
master->best_cost += master->scan_size[next_scan_number-1];
} else if ((next_scan_number - chroma_freq_split_scan_start) % 4 == 2) {
int idx = (next_scan_number - chroma_freq_split_scan_start) >> 2;
unsigned long cost = 0;
cost += master->scan_size[next_scan_number-4];
cost += master->scan_size[next_scan_number-3];
cost += master->scan_size[next_scan_number-2];
cost += master->scan_size[next_scan_number-1];
if (cost < master->best_cost) {
master->best_cost = cost;
master->best_freq_split_idx_chroma = idx;
}
/* if after testing first 3, no split is the best, don't search further */
if ((idx == 2 && master->best_freq_split_idx_chroma == 0) ||
(idx == 3 && master->best_freq_split_idx_chroma != 2) ||
(idx == 4 && master->best_freq_split_idx_chroma != 4)) {
master->scan_number = cinfo->num_scans - 1;
master->pass_number = passes_per_scan * (master->scan_number + 1) - 1 + master->pass_number_scan_opt_base;
master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
}
}
}
}
if (master->scan_number == cinfo->num_scans - 1) {
int i, Al;
int min_Al = MIN(master->best_Al_luma, master->best_Al_chroma);
copy_buffer(cinfo, 0);
if (cinfo->num_scans > cinfo->master->num_scans_luma &&
cinfo->master->dc_scan_opt_mode != 0) {
base_scan_idx = cinfo->master->num_scans_luma;
if (master->interleave_chroma_dc && cinfo->master->dc_scan_opt_mode != 1)
copy_buffer(cinfo, base_scan_idx);
else {
copy_buffer(cinfo, base_scan_idx+1);
copy_buffer(cinfo, base_scan_idx+2);
}
}
if (master->best_freq_split_idx_luma == 0)
copy_buffer(cinfo, luma_freq_split_scan_start);
else {
copy_buffer(cinfo, luma_freq_split_scan_start+2*(master->best_freq_split_idx_luma-1)+1);
copy_buffer(cinfo, luma_freq_split_scan_start+2*(master->best_freq_split_idx_luma-1)+2);
}
/* copy the LSB refinements as well */
for (Al = master->best_Al_luma-1; Al >= min_Al; Al--)
copy_buffer(cinfo, 3 + 3*Al);
if (cinfo->num_scans > cinfo->master->num_scans_luma) {
if (master->best_freq_split_idx_chroma == 0) {
copy_buffer(cinfo, chroma_freq_split_scan_start);
copy_buffer(cinfo, chroma_freq_split_scan_start+1);
}
else {
copy_buffer(cinfo, chroma_freq_split_scan_start+4*(master->best_freq_split_idx_chroma-1)+2);
copy_buffer(cinfo, chroma_freq_split_scan_start+4*(master->best_freq_split_idx_chroma-1)+3);
copy_buffer(cinfo, chroma_freq_split_scan_start+4*(master->best_freq_split_idx_chroma-1)+4);
copy_buffer(cinfo, chroma_freq_split_scan_start+4*(master->best_freq_split_idx_chroma-1)+5);
}
base_scan_idx = cinfo->master->num_scans_luma +
cinfo->master->num_scans_chroma_dc;
for (Al = master->best_Al_chroma-1; Al >= min_Al; Al--) {
copy_buffer(cinfo, base_scan_idx + 6*Al + 4);
copy_buffer(cinfo, base_scan_idx + 6*Al + 5);
}
}
for (Al = min_Al-1; Al >= 0; Al--) {
copy_buffer(cinfo, 3 + 3*Al);
if (cinfo->num_scans > cinfo->master->num_scans_luma) {
copy_buffer(cinfo, base_scan_idx + 6*Al + 4);
copy_buffer(cinfo, base_scan_idx + 6*Al + 5);
}
}
/* free the memory allocated for buffers */
for (i = 0; i < cinfo->num_scans; i++)
if (master->scan_buffer[i])
free(master->scan_buffer[i]);
}
}
/* /*
* Finish up at end of pass. * Finish up at end of pass.
*/ */
METHODDEF(void) METHODDEF(void)
finish_pass_master (j_compress_ptr cinfo) finish_pass_master(j_compress_ptr cinfo)
{ {
my_master_ptr master = (my_master_ptr) cinfo->master; my_master_ptr master = (my_master_ptr)cinfo->master;
/* The entropy coder always needs an end-of-pass call, /* The entropy coder always needs an end-of-pass call,
* either to analyze statistics or to flush its output buffer. * either to analyze statistics or to flush its output buffer.
@@ -829,54 +563,20 @@ finish_pass_master (j_compress_ptr cinfo)
/* next pass is either output of scan 0 (after optimization) /* next pass is either output of scan 0 (after optimization)
* or output of scan 1 (if no optimization). * or output of scan 1 (if no optimization).
*/ */
if (cinfo->master->trellis_quant)
master->pass_type = trellis_pass;
else {
master->pass_type = output_pass; master->pass_type = output_pass;
if (! cinfo->optimize_coding) if (!cinfo->optimize_coding)
master->scan_number++; master->scan_number++;
}
break; break;
case huff_opt_pass: case huff_opt_pass:
/* next pass is always output of current scan */ /* next pass is always output of current scan */
master->pass_type = (master->pass_number < master->pass_number_scan_opt_base-1) ? trellis_pass : output_pass; master->pass_type = output_pass;
break; break;
case output_pass: case output_pass:
/* next pass is either optimization or output of next scan */ /* next pass is either optimization or output of next scan */
if (cinfo->optimize_coding) if (cinfo->optimize_coding)
master->pass_type = huff_opt_pass; master->pass_type = huff_opt_pass;
if (cinfo->master->optimize_scans) {
(*cinfo->dest->term_destination)(cinfo);
cinfo->dest = master->saved_dest;
select_scans(cinfo, master->scan_number + 1);
}
master->scan_number++; master->scan_number++;
break; break;
case trellis_pass:
if (cinfo->optimize_coding)
master->pass_type = huff_opt_pass;
else
master->pass_type = (master->pass_number < master->pass_number_scan_opt_base-1) ? trellis_pass : output_pass;
if ((master->pass_number + 1) %
(cinfo->num_components * (cinfo->master->use_scans_in_trellis ? 4 : 2)) == 0 &&
cinfo->master->trellis_q_opt) {
int i, j;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
for (j = 1; j < DCTSIZE2; j++) {
if (cinfo->master->norm_coef[i][j] != 0.0) {
int q = (int)(cinfo->master->norm_src[i][j] /
cinfo->master->norm_coef[i][j] + 0.5);
if (q > 254) q = 254;
if (q < 1) q = 1;
cinfo->quant_tbl_ptrs[i]->quantval[j] = q;
}
}
}
}
break;
} }
master->pass_number++; master->pass_number++;
@@ -888,15 +588,18 @@ 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) cinfo->master; my_master_ptr 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;
master->pub.call_pass_startup = FALSE;
/* Validate parameters, determine derived values */ /* Validate parameters, determine derived values */
initial_setup(cinfo, transcode_only); initial_setup(cinfo, transcode_only);
@@ -934,25 +637,4 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
master->total_passes = cinfo->num_scans; master->total_passes = cinfo->num_scans;
master->jpeg_version = PACKAGE_NAME " version " VERSION " (build " BUILD ")"; master->jpeg_version = PACKAGE_NAME " version " VERSION " (build " BUILD ")";
master->pass_number_scan_opt_base = 0;
if (cinfo->master->trellis_quant) {
if (cinfo->optimize_coding)
master->pass_number_scan_opt_base =
((cinfo->master->use_scans_in_trellis) ? 4 : 2) * cinfo->num_components *
cinfo->master->trellis_num_loops;
else
master->pass_number_scan_opt_base =
((cinfo->master->use_scans_in_trellis) ? 2 : 1) * cinfo->num_components *
cinfo->master->trellis_num_loops + 1;
master->total_passes += master->pass_number_scan_opt_base;
}
if (cinfo->master->optimize_scans) {
int i;
master->best_Al_chroma = 0;
for (i = 0; i < cinfo->num_scans; i++)
master->scan_buffer[i] = NULL;
}
} }

View File

@@ -1,56 +0,0 @@
/*
* jcmaster.h
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the master control structures 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 */
trellis_pass /* trellis quantization 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[] */
/* fields for scan optimisation */
int pass_number_scan_opt_base; /* pass number where scan optimization begins */
unsigned char * scan_buffer[64]; /* buffer for a given scan */
unsigned long scan_size[64]; /* size for a given scan */
int actual_Al[64]; /* actual value of Al used for a scan */
unsigned long best_cost; /* bit count for best frequency split */
int best_freq_split_idx_luma; /* index for best frequency split (luma) */
int best_freq_split_idx_chroma; /* index for best frequency split (chroma) */
int best_Al_luma; /* best value for Al found in scan search (luma) */
int best_Al_chroma; /* best value for Al found in scan search (luma) */
boolean interleave_chroma_dc; /* indicate whether to interleave chroma DC scans */
struct jpeg_destination_mgr * saved_dest; /* saved value of cinfo->dest */
/*
* 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;

View File

@@ -32,42 +32,6 @@
#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */ #define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1
/* Define to 1 if you have the <stddef.h> header file. */
#cmakedefine HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define if you need to include <sys/types.h> to get size_t. */
#cmakedefine NEED_SYS_TYPES_H 1
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
memset/memcpy in <string.h>. */
#cmakedefine NEED_BSD_STRINGS 1
/* Define to 1 if the system has the type `unsigned char'. */
#cmakedefine HAVE_UNSIGNED_CHAR 1
/* Define to 1 if the system has the type `unsigned short'. */
#cmakedefine HAVE_UNSIGNED_SHORT 1
/* Compiler does not support pointers to undefined structures. */
#cmakedefine INCOMPLETE_TYPES_BROKEN 1
/* Define if your (broken) compiler shifts signed values as if they were /* Define if your (broken) compiler shifts signed values as if they were
unsigned. */ unsigned. */
#cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1 #cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
#cmakedefine __CHAR_UNSIGNED__ 1
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

View File

@@ -26,56 +26,6 @@
* #define the symbol if yes, #undef it if no. * #define the symbol if yes, #undef it if no.
*/ */
/* Does your compiler support the declaration "unsigned char" ?
* How about "unsigned short" ?
*/
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define "const" as empty if your compiler doesn't know the "const" keyword.
*/
/* #define const */
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
*/
#undef __CHAR_UNSIGNED__
/* Define this if your system has an ANSI-conforming <stddef.h> file.
*/
#define HAVE_STDDEF_H
/* Define this if your system has an ANSI-conforming <stdlib.h> file.
*/
#define HAVE_STDLIB_H
/* Define this if your system does not have an ANSI/SysV <string.h>,
* but does have a BSD-style <strings.h>.
*/
#undef NEED_BSD_STRINGS
/* Define this if your system does not provide typedef size_t in any of the
* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
* <sys/types.h> instead.
*/
#undef NEED_SYS_TYPES_H
/* Although a real ANSI C compiler can deal perfectly well with pointers to
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
* define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
* actually get "missing structure definition" warnings or errors while
* compiling the JPEG code.
*/
#undef INCOMPLETE_TYPES_BROKEN
/* Define "boolean" as unsigned char, not int, on Windows systems. /* Define "boolean" as unsigned char, not int, on Windows systems.
*/ */
#ifdef _WIN32 #ifdef _WIN32
@@ -115,11 +65,9 @@ typedef unsigned char boolean;
/* These defines indicate which image (non-JPEG) file formats are allowed. */ /* These defines indicate which image (non-JPEG) file formats are allowed. */
#define PNG_SUPPORTED /* PNG image file format */
#define BMP_SUPPORTED /* BMP image file format */ #define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */ #define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */ #define TARGA_SUPPORTED /* Targa image file format */
/* Define this if you want to name both input and output files on the command /* Define this if you want to name both input and output files on the command

View File

@@ -32,3 +32,13 @@
#define HAVE_BITSCANFORWARD #define HAVE_BITSCANFORWARD
#endif #endif
#endif #endif
#if defined(__has_attribute)
#if __has_attribute(fallthrough)
#define FALLTHROUGH __attribute__((fallthrough));
#else
#define FALLTHROUGH
#endif
#else
#define FALLTHROUGH
#endif

554
jcparam.c
View File

@@ -6,9 +6,8 @@
* Modified 2003-2008 by Guido Vollbeding. * Modified 2003-2008 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2018, D. R. Commander. * Copyright (C) 2009-2011, 2018, D. R. Commander.
* mozjpeg Modifications: * For conditions of distribution and use, see the accompanying README.ijg
* Copyright (C) 2014, Mozilla Corporation. * file.
* For conditions of distribution and use, see the accompanying README file.
* *
* This file contains optional default-setting code for the JPEG compressor. * This file contains optional default-setting code for the JPEG compressor.
* Applications do not have to use this file, but those that don't use it * Applications do not have to use this file, but those that don't use it
@@ -26,7 +25,7 @@
*/ */
GLOBAL(void) GLOBAL(void)
jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table, int scale_factor, const unsigned int *basic_table, int scale_factor,
boolean force_baseline) boolean force_baseline)
/* Define a quantization table equal to the basic_table times /* Define a quantization table equal to the basic_table times
@@ -46,19 +45,19 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; qtblptr = &cinfo->quant_tbl_ptrs[which_tbl];
if (*qtblptr == NULL) if (*qtblptr == NULL)
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); *qtblptr = jpeg_alloc_quant_table((j_common_ptr)cinfo);
for (i = 0; i < DCTSIZE2; i++) { for (i = 0; i < DCTSIZE2; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; temp = ((long)basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */ /* limit the values to the valid range */
if (temp <= 0L) temp = 1L; if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L) if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */ temp = 255L; /* limit to baseline range if requested */
(*qtblptr)->quantval[i] = (UINT16) temp; (*qtblptr)->quantval[i] = (UINT16)temp;
} }
/* Initialize sent_table FALSE so table will be written to JPEG file. */ /* Initialize sent_table FALSE so table will be written to JPEG file. */
@@ -71,10 +70,7 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
* The spec says that the values given produce "good" quality, and * The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality. * when divided by 2, "very good" quality.
*/ */
static const unsigned int std_luminance_quant_tbl[9][DCTSIZE2] = { static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
{
/* JPEG Annex K
*/
16, 11, 10, 16, 24, 40, 51, 61, 16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55, 12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56, 14, 13, 16, 24, 40, 57, 69, 56,
@@ -83,105 +79,8 @@ static const unsigned int std_luminance_quant_tbl[9][DCTSIZE2] = {
24, 35, 55, 64, 81, 104, 113, 92, 24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101, 49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99 72, 92, 95, 98, 112, 100, 103, 99
},
{
/* flat
*/
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16
},
{
12, 17, 20, 21, 30, 34, 56, 63,
18, 20, 20, 26, 28, 51, 61, 55,
19, 20, 21, 26, 33, 58, 69, 55,
26, 26, 26, 30, 46, 87, 86, 66,
31, 33, 36, 40, 46, 96, 100, 73,
40, 35, 46, 62, 81, 100, 111, 91,
46, 66, 76, 86, 102, 121, 120, 101,
68, 90, 90, 96, 113, 102, 105, 103
},
{
/* From http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=20333&p=98008#p98008
*/
16, 16, 16, 18, 25, 37, 56, 85,
16, 17, 20, 27, 34, 40, 53, 75,
16, 20, 24, 31, 43, 62, 91, 135,
18, 27, 31, 40, 53, 74, 106, 156,
25, 34, 43, 53, 69, 94, 131, 189,
37, 40, 62, 74, 94, 124, 169, 238,
56, 53, 91, 106, 131, 169, 226, 311,
85, 75, 135, 156, 189, 238, 311, 418
},
{
9, 10, 12, 14, 27, 32, 51, 62,
11, 12, 14, 19, 27, 44, 59, 73,
12, 14, 18, 25, 42, 59, 79, 78,
17, 18, 25, 42, 61, 92, 87, 92,
23, 28, 42, 75, 79, 112, 112, 99,
40, 42, 59, 84, 88, 124, 132, 111,
42, 64, 78, 95, 105, 126, 125, 99,
70, 75, 100, 102, 116, 100, 107, 98
},
{
/* Relevance of human vision to JPEG-DCT compression (1992) Klein, Silverstein and Carney.
*/
10, 12, 14, 19, 26, 38, 57, 86,
12, 18, 21, 28, 35, 41, 54, 76,
14, 21, 25, 32, 44, 63, 92, 136,
19, 28, 32, 41, 54, 75, 107, 157,
26, 35, 44, 54, 70, 95, 132, 190,
38, 41, 63, 75, 95, 125, 170, 239,
57, 54, 92, 107, 132, 170, 227, 312,
86, 76, 136, 157, 190, 239, 312, 419
},
{
/* DCTune perceptual optimization of compressed dental X-Rays (1997) Watson, Taylor, Borthwick
*/
7, 8, 10, 14, 23, 44, 95, 241,
8, 8, 11, 15, 25, 47, 102, 255,
10, 11, 13, 19, 31, 58, 127, 255,
14, 15, 19, 27, 44, 83, 181, 255,
23, 25, 31, 44, 72, 136, 255, 255,
44, 47, 58, 83, 136, 255, 255, 255,
95, 102, 127, 181, 255, 255, 255, 255,
241, 255, 255, 255, 255, 255, 255, 255
},
{
/* A visual detection model for DCT coefficient quantization (12/9/93) Ahumada, Watson, Peterson
*/
15, 11, 11, 12, 15, 19, 25, 32,
11, 13, 10, 10, 12, 15, 19, 24,
11, 10, 14, 14, 16, 18, 22, 27,
12, 10, 14, 18, 21, 24, 28, 33,
15, 12, 16, 21, 26, 31, 36, 42,
19, 15, 18, 24, 31, 38, 45, 53,
25, 19, 22, 28, 36, 45, 55, 65,
32, 24, 27, 33, 42, 53, 65, 77
},
{
/* An improved detection model for DCT coefficient quantization (1993) Peterson, Ahumada and Watson
*/
14, 10, 11, 14, 19, 25, 34, 45,
10, 11, 11, 12, 15, 20, 26, 33,
11, 11, 15, 18, 21, 25, 31, 38,
14, 12, 18, 24, 28, 33, 39, 47,
19, 15, 21, 28, 36, 43, 51, 59,
25, 20, 25, 33, 43, 54, 64, 74,
34, 26, 31, 39, 51, 64, 77, 91,
45, 33, 38, 47, 59, 74, 91, 108
}
}; };
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
static const unsigned int std_chrominance_quant_tbl[9][DCTSIZE2] = {
{
/* JPEG Annex K
*/
17, 18, 24, 47, 99, 99, 99, 99, 17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99,
@@ -190,125 +89,29 @@ static const unsigned int std_chrominance_quant_tbl[9][DCTSIZE2] = {
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99 99, 99, 99, 99, 99, 99, 99, 99
},
{
/* flat
*/
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16
},
{
8, 12, 15, 15, 86, 96, 96, 98,
13, 13, 15, 26, 90, 96, 99, 98,
12, 15, 18, 96, 99, 99, 99, 99,
17, 16, 90, 96, 99, 99, 99, 99,
96, 96, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
},
{
/* From http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=20333&p=98008#p98008
*/
16, 16, 16, 18, 25, 37, 56, 85,
16, 17, 20, 27, 34, 40, 53, 75,
16, 20, 24, 31, 43, 62, 91, 135,
18, 27, 31, 40, 53, 74, 106, 156,
25, 34, 43, 53, 69, 94, 131, 189,
37, 40, 62, 74, 94, 124, 169, 238,
56, 53, 91, 106, 131, 169, 226, 311,
85, 75, 135, 156, 189, 238, 311, 418
},
{
9, 10, 17, 19, 62, 89, 91, 97,
12, 13, 18, 29, 84, 91, 88, 98,
14, 19, 29, 93, 95, 95, 98, 97,
20, 26, 84, 88, 95, 95, 98, 94,
26, 86, 91, 93, 97, 99, 98, 99,
99, 100, 98, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
97, 97, 99, 99, 99, 99, 97, 99
},
{
/* Relevance of human vision to JPEG-DCT compression (1992) Klein, Silverstein and Carney.
* Copied from luma
*/
10, 12, 14, 19, 26, 38, 57, 86,
12, 18, 21, 28, 35, 41, 54, 76,
14, 21, 25, 32, 44, 63, 92, 136,
19, 28, 32, 41, 54, 75, 107, 157,
26, 35, 44, 54, 70, 95, 132, 190,
38, 41, 63, 75, 95, 125, 170, 239,
57, 54, 92, 107, 132, 170, 227, 312,
86, 76, 136, 157, 190, 239, 312, 419
},
{
/* DCTune perceptual optimization of compressed dental X-Rays (1997) Watson, Taylor, Borthwick
* Copied from luma
*/
7, 8, 10, 14, 23, 44, 95, 241,
8, 8, 11, 15, 25, 47, 102, 255,
10, 11, 13, 19, 31, 58, 127, 255,
14, 15, 19, 27, 44, 83, 181, 255,
23, 25, 31, 44, 72, 136, 255, 255,
44, 47, 58, 83, 136, 255, 255, 255,
95, 102, 127, 181, 255, 255, 255, 255,
241, 255, 255, 255, 255, 255, 255, 255
},
{
/* A visual detection model for DCT coefficient quantization (12/9/93) Ahumada, Watson, Peterson
* Copied from luma
*/
15, 11, 11, 12, 15, 19, 25, 32,
11, 13, 10, 10, 12, 15, 19, 24,
11, 10, 14, 14, 16, 18, 22, 27,
12, 10, 14, 18, 21, 24, 28, 33,
15, 12, 16, 21, 26, 31, 36, 42,
19, 15, 18, 24, 31, 38, 45, 53,
25, 19, 22, 28, 36, 45, 55, 65,
32, 24, 27, 33, 42, 53, 65, 77
},
{
/* An improved detection model for DCT coefficient quantization (1993) Peterson, Ahumada and Watson
* Copied from luma
*/
14, 10, 11, 14, 19, 25, 34, 45,
10, 11, 11, 12, 15, 20, 26, 33,
11, 11, 15, 18, 21, 25, 31, 38,
14, 12, 18, 24, 28, 33, 39, 47,
19, 15, 21, 28, 36, 43, 51, 59,
25, 20, 25, 33, 43, 54, 64, 74,
34, 26, 31, 39, 51, 64, 77, 91,
45, 33, 38, 47, 59, 74, 91, 108
}
}; };
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
GLOBAL(void) GLOBAL(void)
jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) jpeg_default_qtables(j_compress_ptr cinfo, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables /* Set or change the 'quality' (quantization) setting, using default tables
* and straight percentage-scaling quality scales. * and straight percentage-scaling quality scales.
* This entry point allows different scalings for luminance and chrominance. * This entry point allows different scalings for luminance and chrominance.
*/ */
{ {
/* Set up two quantization tables using the specified scaling */ /* Set up two quantization tables using the specified scaling */
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl[cinfo->master->quant_tbl_master_idx], jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
cinfo->q_scale_factor[0], force_baseline); cinfo->q_scale_factor[0], force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl[cinfo->master->quant_tbl_master_idx], jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
cinfo->q_scale_factor[1], force_baseline); cinfo->q_scale_factor[1], force_baseline);
} }
#endif #endif
GLOBAL(void) GLOBAL(void)
jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
boolean force_baseline) boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables /* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better * and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for * to use jpeg_set_quality (below); this entry point is provided for
@@ -316,29 +119,23 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
*/ */
{ {
/* Set up two quantization tables using the specified scaling */ /* Set up two quantization tables using the specified scaling */
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl[cinfo->master->quant_tbl_master_idx], jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
scale_factor, force_baseline); scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl[cinfo->master->quant_tbl_master_idx], jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
scale_factor, force_baseline); scale_factor, force_baseline);
} }
GLOBAL(int) GLOBAL(int)
jpeg_quality_scaling (int quality) jpeg_quality_scaling(int quality)
{
return jpeg_float_quality_scaling(quality);
}
GLOBAL(float)
jpeg_float_quality_scaling(float quality)
/* Convert a user-specified quality rating to a percentage scaling factor /* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve. * for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good). * The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/ */
{ {
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if (quality <= 0.f) quality = 1.f; if (quality <= 0) quality = 1;
if (quality > 100.f) quality = 100.f; if (quality > 100) quality = 100;
/* The basic table is used as-is (scaling 100) for a quality of 50. /* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
@@ -346,17 +143,17 @@ jpeg_float_quality_scaling(float quality)
* to make all the table entries 1 (hence, minimum quantization loss). * to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q. * Qualities 1..50 are converted to scaling percentage 5000/Q.
*/ */
if (quality < 50.f) if (quality < 50)
quality = 5000.f / quality; quality = 5000 / quality;
else else
quality = 200.f - quality*2.f; quality = 200 - quality * 2;
return quality; return quality;
} }
GLOBAL(void) GLOBAL(void)
jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) jpeg_set_quality(j_compress_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables. /* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user * This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables * interfaces; only those who want detailed control over quantization tables
@@ -382,7 +179,7 @@ jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
*/ */
GLOBAL(void) GLOBAL(void)
jpeg_set_defaults (j_compress_ptr cinfo) jpeg_set_defaults(j_compress_ptr cinfo)
{ {
int i; int i;
@@ -396,7 +193,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
*/ */
if (cinfo->comp_info == NULL) if (cinfo->comp_info == NULL)
cinfo->comp_info = (jpeg_component_info *) cinfo->comp_info = (jpeg_component_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
MAX_COMPONENTS * sizeof(jpeg_component_info)); MAX_COMPONENTS * sizeof(jpeg_component_info));
/* Initialize everything not dependent on the color space */ /* Initialize everything not dependent on the color space */
@@ -409,7 +206,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
/* Set up two quantization tables using default quality of 75 */ /* Set up two quantization tables using default quality of 75 */
jpeg_set_quality(cinfo, 75, TRUE); jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */ /* Set up two Huffman tables */
std_huff_tables((j_common_ptr) cinfo); std_huff_tables((j_common_ptr)cinfo);
/* Initialize default arithmetic coding conditioning */ /* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) { for (i = 0; i < NUM_ARITH_TBLS; i++) {
@@ -428,18 +225,8 @@ jpeg_set_defaults (j_compress_ptr cinfo)
/* Use Huffman coding, not arithmetic coding, by default */ /* Use Huffman coding, not arithmetic coding, by default */
cinfo->arith_code = FALSE; cinfo->arith_code = FALSE;
#ifdef ENTROPY_OPT_SUPPORTED
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION)
/* By default, do extra passes to optimize entropy coding */
cinfo->optimize_coding = TRUE;
else
/* By default, don't do extra passes to optimize entropy coding */ /* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE; cinfo->optimize_coding = FALSE;
#else
/* By default, don't do extra passes to optimize entropy coding */
cinfo->optimize_coding = FALSE;
#endif
/* The standard Huffman tables are only valid for 8-bit data precision. /* The standard Huffman tables are only valid for 8-bit data precision.
* If the precision is higher, force optimization on so that usable * If the precision is higher, force optimization on so that usable
* tables will be computed. This test can be removed if default tables * tables will be computed. This test can be removed if default tables
@@ -456,9 +243,6 @@ jpeg_set_defaults (j_compress_ptr cinfo)
cinfo->do_fancy_downsampling = TRUE; cinfo->do_fancy_downsampling = TRUE;
#endif #endif
cinfo->master->overshoot_deringing =
cinfo->master->compress_profile == JCP_MAX_COMPRESSION;
/* No input smoothing */ /* No input smoothing */
cinfo->smoothing_factor = 0; cinfo->smoothing_factor = 0;
@@ -487,31 +271,6 @@ jpeg_set_defaults (j_compress_ptr cinfo)
/* Choose JPEG colorspace based on input space, set defaults accordingly */ /* Choose JPEG colorspace based on input space, set defaults accordingly */
jpeg_default_colorspace(cinfo); jpeg_default_colorspace(cinfo);
cinfo->master->dc_scan_opt_mode = 1;
#ifdef C_PROGRESSIVE_SUPPORTED
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
cinfo->master->optimize_scans = TRUE;
jpeg_simple_progression(cinfo);
} else
cinfo->master->optimize_scans = FALSE;
#endif
cinfo->master->trellis_quant =
cinfo->master->compress_profile == JCP_MAX_COMPRESSION;
cinfo->master->lambda_log_scale1 = 14.75;
cinfo->master->lambda_log_scale2 = 16.5;
cinfo->master->quant_tbl_master_idx =
cinfo->master->compress_profile == JCP_MAX_COMPRESSION ? 3 : 0;
cinfo->master->use_lambda_weight_tbl = TRUE;
cinfo->master->use_scans_in_trellis = FALSE;
cinfo->master->trellis_freq_split = 8;
cinfo->master->trellis_num_loops = 1;
cinfo->master->trellis_q_opt = FALSE;
cinfo->master->trellis_quant_dc = TRUE;
cinfo->master->trellis_delta_dc_weight = 0.0;
} }
@@ -520,7 +279,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
*/ */
GLOBAL(void) GLOBAL(void)
jpeg_default_colorspace (j_compress_ptr cinfo) jpeg_default_colorspace(j_compress_ptr cinfo)
{ {
switch (cinfo->in_color_space) { switch (cinfo->in_color_space) {
case JCS_GRAYSCALE: case JCS_GRAYSCALE:
@@ -562,12 +321,12 @@ jpeg_default_colorspace (j_compress_ptr cinfo)
*/ */
GLOBAL(void) GLOBAL(void)
jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) jpeg_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
{ {
jpeg_component_info *compptr; jpeg_component_info *compptr;
int ci; int ci;
#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ #define SET_COMP(index, id, hsamp, vsamp, quant, dctbl, actbl) \
(compptr = &cinfo->comp_info[index], \ (compptr = &cinfo->comp_info[index], \
compptr->component_id = (id), \ compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \ compptr->h_samp_factor = (hsamp), \
@@ -594,39 +353,39 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 1; cinfo->num_components = 1;
/* JFIF specifies component ID 1 */ /* JFIF specifies component ID 1 */
SET_COMP(0, 1, 1,1, 0, 0,0); SET_COMP(0, 1, 1, 1, 0, 0, 0);
break; break;
case JCS_RGB: case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3; cinfo->num_components = 3;
SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); SET_COMP(0, 0x52 /* 'R' */, 1, 1, 0, 0, 0);
SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); SET_COMP(1, 0x47 /* 'G' */, 1, 1, 0, 0, 0);
SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); SET_COMP(2, 0x42 /* 'B' */, 1, 1, 0, 0, 0);
break; break;
case JCS_YCbCr: case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3; cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */ /* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */ /* We default to 2x2 subsamples of chrominance */
SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(0, 1, 2, 2, 0, 0, 0);
SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(1, 2, 1, 1, 1, 1, 1);
SET_COMP(2, 3, 1,1, 1, 1,1); SET_COMP(2, 3, 1, 1, 1, 1, 1);
break; break;
case JCS_CMYK: case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4; cinfo->num_components = 4;
SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); SET_COMP(0, 0x43 /* 'C' */, 1, 1, 0, 0, 0);
SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); SET_COMP(1, 0x4D /* 'M' */, 1, 1, 0, 0, 0);
SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); SET_COMP(2, 0x59 /* 'Y' */, 1, 1, 0, 0, 0);
SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); SET_COMP(3, 0x4B /* 'K' */, 1, 1, 0, 0, 0);
break; break;
case JCS_YCCK: case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4; cinfo->num_components = 4;
SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(0, 1, 2, 2, 0, 0, 0);
SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(1, 2, 1, 1, 1, 1, 1);
SET_COMP(2, 3, 1,1, 1, 1,1); SET_COMP(2, 3, 1, 1, 1, 1, 1);
SET_COMP(3, 4, 2,2, 0, 0,0); SET_COMP(3, 4, 2, 2, 0, 0, 0);
break; break;
case JCS_UNKNOWN: case JCS_UNKNOWN:
cinfo->num_components = cinfo->input_components; cinfo->num_components = cinfo->input_components;
@@ -634,7 +393,7 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS); MAX_COMPONENTS);
for (ci = 0; ci < cinfo->num_components; ci++) { for (ci = 0; ci < cinfo->num_components; ci++) {
SET_COMP(ci, ci, 1,1, 0, 0,0); SET_COMP(ci, ci, 1, 1, 0, 0, 0);
} }
break; break;
default: default:
@@ -660,24 +419,7 @@ fill_a_scan(jpeg_scan_info *scanptr, int ci, int Ss, int Se, int Ah, int Al)
} }
LOCAL(jpeg_scan_info *) LOCAL(jpeg_scan_info *)
fill_a_scan_pair (jpeg_scan_info * scanptr, int ci, fill_scans(jpeg_scan_info *scanptr, int ncomps, int Ss, int Se, int Ah, int Al)
int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for pair of components */
{
scanptr->comps_in_scan = 2;
scanptr->component_index[0] = ci;
scanptr->component_index[1] = ci + 1;
scanptr->Ss = Ss;
scanptr->Se = Se;
scanptr->Ah = Ah;
scanptr->Al = Al;
scanptr++;
return scanptr;
}
LOCAL(jpeg_scan_info *)
fill_scans (jpeg_scan_info *scanptr, int ncomps,
int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for each component */ /* Support routine: generate one scan for each component */
{ {
int ci; int ci;
@@ -695,7 +437,7 @@ fill_scans (jpeg_scan_info *scanptr, int ncomps,
} }
LOCAL(jpeg_scan_info *) LOCAL(jpeg_scan_info *)
fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al) fill_dc_scans(jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
/* Support routine: generate interleaved DC scan if possible, else N scans */ /* Support routine: generate interleaved DC scan if possible, else N scans */
{ {
int ci; int ci;
@@ -717,182 +459,33 @@ fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
} }
/*
* List of scans to be tested
* cinfo->num_components and cinfo->jpeg_color_space must be correct.
*/
LOCAL(boolean)
jpeg_search_progression (j_compress_ptr cinfo)
{
int ncomps = cinfo->num_components;
int nscans;
jpeg_scan_info * scanptr;
int Al;
int frequency_split[] = { 2, 8, 5, 12, 18 };
int i;
/* Safety check to ensure start_compress not called yet. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Figure space needed for script. Calculation must match code below! */
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* Custom script for YCbCr color images. */
nscans = 64;
} else if (ncomps == 1) {
nscans = 23;
} else {
cinfo->master->num_scans_luma = 0;
return FALSE;
}
/* Allocate space for script.
* We need to put it in the permanent pool in case the application performs
* multiple compressions without changing the settings. To avoid a memory
* leak if jpeg_simple_progression is called repeatedly for the same JPEG
* object, we try to re-use previously allocated space, and we allocate
* enough space to handle YCbCr even if initially asked for grayscale.
*/
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 64);
cinfo->script_space = (jpeg_scan_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
cinfo->script_space_size * sizeof(jpeg_scan_info));
}
scanptr = cinfo->script_space;
cinfo->scan_info = scanptr;
cinfo->num_scans = nscans;
cinfo->master->Al_max_luma = 3;
cinfo->master->num_scans_luma_dc = 1;
cinfo->master->num_frequency_splits = 5;
cinfo->master->num_scans_luma =
cinfo->master->num_scans_luma_dc + (3 * cinfo->master->Al_max_luma + 2) +
(2 * cinfo->master->num_frequency_splits + 1);
/* 23 scans for luma */
/* 1 scan for DC */
/* 11 scans to determine successive approximation */
/* 11 scans to determine frequency approximation */
/* after 12 scans need to update following 11 */
/* after 23 scans need to determine which to keep */
/* last 4 done conditionally */
/* luma DC by itself */
if (cinfo->master->dc_scan_opt_mode == 0)
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);
else
scanptr = fill_dc_scans(scanptr, 1, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 9, 63, 0, 0);
for (Al = 0; Al < cinfo->master->Al_max_luma; Al++) {
scanptr = fill_a_scan(scanptr, 0, 1, 63, Al+1, Al);
scanptr = fill_a_scan(scanptr, 0, 1, 8, 0, Al+1);
scanptr = fill_a_scan(scanptr, 0, 9, 63, 0, Al+1);
}
scanptr = fill_a_scan(scanptr, 0, 1, 63, 0, 0);
for (i = 0; i < cinfo->master->num_frequency_splits; i++) {
scanptr = fill_a_scan(scanptr, 0, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 0, frequency_split[i]+1, 63, 0, 0);
}
if (ncomps == 1) {
cinfo->master->Al_max_chroma = 0;
cinfo->master->num_scans_chroma_dc = 0;
} else {
cinfo->master->Al_max_chroma = 2;
cinfo->master->num_scans_chroma_dc = 3;
/* 41 scans for chroma */
/* chroma DC combined */
scanptr = fill_a_scan_pair(scanptr, 1, 0, 0, 0, 0);
/* chroma DC separate */
scanptr = fill_a_scan(scanptr, 1, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 0);
for (Al = 0; Al < cinfo->master->Al_max_chroma; Al++) {
scanptr = fill_a_scan(scanptr, 1, 1, 63, Al+1, Al);
scanptr = fill_a_scan(scanptr, 2, 1, 63, Al+1, Al);
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, Al+1);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, Al+1);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, Al+1);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, Al+1);
}
scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 0);
for (i = 0; i < cinfo->master->num_frequency_splits; i++) {
scanptr = fill_a_scan(scanptr, 1, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 1, frequency_split[i]+1, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 2, frequency_split[i]+1, 63, 0, 0);
}
}
return TRUE;
}
/* /*
* Create a recommended progressive-JPEG script. * Create a recommended progressive-JPEG script.
* cinfo->num_components and cinfo->jpeg_color_space must be correct. * cinfo->num_components and cinfo->jpeg_color_space must be correct.
*/ */
GLOBAL(void) GLOBAL(void)
jpeg_simple_progression (j_compress_ptr cinfo) jpeg_simple_progression(j_compress_ptr cinfo)
{ {
int ncomps; int ncomps = cinfo->num_components;
int nscans; int nscans;
jpeg_scan_info *scanptr; jpeg_scan_info *scanptr;
if (cinfo->master->optimize_scans) {
if (jpeg_search_progression(cinfo) == TRUE)
return;
}
/* Safety check to ensure start_compress not called yet. */ /* Safety check to ensure start_compress not called yet. */
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);
/* Figure space needed for script. Calculation must match code below! */ /* Figure space needed for script. Calculation must match code below! */
ncomps = cinfo->num_components;
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. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) { nscans = 10;
if (cinfo->master->dc_scan_opt_mode == 0) {
nscans = 9; /* 1 DC scan for all components */
} else if (cinfo->master->dc_scan_opt_mode == 1) {
nscans = 11; /* 1 DC scan for each component */
} else {
nscans = 10; /* 1 DC scan for luminance and 1 DC scan for chroma */
}
} else {
nscans = 10; /* 2 DC scans and 8 AC scans */
}
} else { } else {
/* All-purpose script for other color spaces. */ /* All-purpose script for other color spaces. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
if (ncomps > MAX_COMPS_IN_SCAN) if (ncomps > MAX_COMPS_IN_SCAN)
nscans = 5 * ncomps; /* 2 DC + 4 AC scans per component */
else
nscans = 1 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
} else {
if (ncomps > MAX_COMPS_IN_SCAN)
nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
else else
nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
} }
}
/* Allocate space for script. /* Allocate space for script.
* We need to put it in the permanent pool in case the application performs * We need to put it in the permanent pool in case the application performs
@@ -904,7 +497,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 10); cinfo->script_space_size = MAX(nscans, 10);
cinfo->script_space = (jpeg_scan_info *) cinfo->script_space = (jpeg_scan_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
cinfo->script_space_size * sizeof(jpeg_scan_info)); cinfo->script_space_size * sizeof(jpeg_scan_info));
} }
scanptr = cinfo->script_space; scanptr = cinfo->script_space;
@@ -913,35 +506,6 @@ jpeg_simple_progression (j_compress_ptr cinfo)
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. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
/* scan defined in jpeg_scan_rgb.txt in jpgcrush */
/* Initial DC scan */
if (cinfo->master->dc_scan_opt_mode == 0) {
/* 1 DC scan for all components */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);
} else if (cinfo->master->dc_scan_opt_mode == 1) {
/* 1 DC scan for each component */
scanptr = fill_a_scan(scanptr, 0, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 0, 0, 0, 0);
} else {
/* 1 DC scan for luminance and 1 DC scan for chroma */
scanptr = fill_dc_scans(scanptr, 1, 0, 0);
scanptr = fill_a_scan_pair(scanptr, 1, 0, 0, 0, 0);
}
/* Low frequency AC scans */
scanptr = fill_a_scan(scanptr, 0, 1, 8, 0, 2);
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 0);
/* Complete spectral selection for luma AC */
scanptr = fill_a_scan(scanptr, 0, 9, 63, 0, 2);
/* Finish luma AC successive approximation */
scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
/* Complete spectral selection for chroma AC */
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 0);
} else {
/* Initial DC scan */ /* Initial DC scan */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
/* Initial AC scan: get some luma data out in a hurry */ /* Initial AC scan: get some luma data out in a hurry */
@@ -960,22 +524,9 @@ jpeg_simple_progression (j_compress_ptr cinfo)
scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
/* Luma bottom bit comes last since it's usually largest scan */ /* Luma bottom bit comes last since it's usually largest scan */
scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
}
} else { } else {
/* All-purpose script for other color spaces. */ /* All-purpose script for other color spaces. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
/* scan defined in jpeg_scan_bw.txt in jpgcrush */
/* DC component, no successive approximation */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);
/* Successive approximation first pass */ /* Successive approximation first pass */
scanptr = fill_scans(scanptr, ncomps, 1, 8, 0, 2);
scanptr = fill_scans(scanptr, ncomps, 9, 63, 0, 2);
/* Successive approximation second pass */
scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
/* Successive approximation final pass */
scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
} else {
/* Successive approximation first pass */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
@@ -986,6 +537,5 @@ jpeg_simple_progression (j_compress_ptr cinfo)
scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
} }
} }
}
#endif /* C_PROGRESSIVE_SUPPORTED */ #endif /* C_PROGRESSIVE_SUPPORTED */

168
jcphuff.c
View File

@@ -4,9 +4,10 @@
* 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.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2011, 2015, 2018, 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.
* Copyright (C) 2014, Mozilla Corporation. * Copyright (C) 2020, Arm Limited.
* Copyright (C) 2021, Alex Richardson.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -53,14 +54,19 @@
*/ */
/* NOTE: Both GCC and Clang define __GNUC__ */ /* NOTE: Both GCC and Clang define __GNUC__ */
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) #if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \
defined(_M_ARM) || defined(_M_ARM64)
#if !defined(__thumb__) || defined(__thumb2__) #if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC #define USE_CLZ_INTRINSIC
#endif #endif
#endif #endif
#ifdef USE_CLZ_INTRINSIC #ifdef USE_CLZ_INTRINSIC
#if defined(_MSC_VER) && !defined(__clang__)
#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x))
#else
#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x)) #define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
#endif
#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0) #define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else #else
#include "jpeg_nbits_table.h" #include "jpeg_nbits_table.h"
@@ -135,34 +141,34 @@ typedef phuff_entropy_encoder *phuff_entropy_ptr;
#ifdef RIGHT_SHIFT_IS_UNSIGNED #ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp; #define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x,shft) \ #define IRIGHT_SHIFT(x, shft) \
((ishift_temp = (x)) < 0 ? \ ((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
(ishift_temp >> (shft))) (ishift_temp >> (shft)))
#else #else
#define ISHIFT_TEMPS #define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif #endif
#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1))) #define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
/* Forward declarations */ /* Forward declarations */
METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo,
JBLOCKROW *MCU_data); JBLOCKROW *MCU_data);
METHODDEF(void) encode_mcu_AC_first_prepare METHODDEF(void) encode_mcu_AC_first_prepare
(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
JCOEF *values, size_t *zerobits); JCOEF *values, size_t *zerobits);
METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data); JBLOCKROW *MCU_data);
METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
METHODDEF(int) encode_mcu_AC_refine_prepare METHODDEF(int) encode_mcu_AC_refine_prepare
(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
JCOEF *absvalues, size_t *bits); JCOEF *absvalues, size_t *bits);
METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data); JBLOCKROW *MCU_data);
METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo); METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo);
METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo); METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo);
/* Count bit loop zeroes */ /* Count bit loop zeroes */
@@ -170,24 +176,26 @@ INLINE
METHODDEF(int) METHODDEF(int)
count_zeroes(size_t *x) count_zeroes(size_t *x)
{ {
int result;
#if defined(HAVE_BUILTIN_CTZL) #if defined(HAVE_BUILTIN_CTZL)
int result;
result = __builtin_ctzl(*x); result = __builtin_ctzl(*x);
*x >>= result; *x >>= result;
#elif defined(HAVE_BITSCANFORWARD64) #elif defined(HAVE_BITSCANFORWARD64)
unsigned long result;
_BitScanForward64(&result, *x); _BitScanForward64(&result, *x);
*x >>= result; *x >>= result;
#elif defined(HAVE_BITSCANFORWARD) #elif defined(HAVE_BITSCANFORWARD)
unsigned long result;
_BitScanForward(&result, *x); _BitScanForward(&result, *x);
*x >>= result; *x >>= result;
#else #else
result = 0; int result = 0;
while ((*x & 1) == 0) { while ((*x & 1) == 0) {
++result; ++result;
*x >>= 1; *x >>= 1;
} }
#endif #endif
return result; return (int)result;
} }
@@ -196,9 +204,9 @@ count_zeroes(size_t *x)
*/ */
METHODDEF(void) METHODDEF(void)
start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band; boolean is_DC_band;
int ci, tbl; int ci, tbl;
jpeg_component_info *compptr; jpeg_component_info *compptr;
@@ -232,7 +240,7 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* AC refinement needs a correction bit buffer */ /* AC refinement needs a correction bit buffer */
if (entropy->bit_buffer == NULL) if (entropy->bit_buffer == NULL)
entropy->bit_buffer = (char *) entropy->bit_buffer = (char *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
MAX_CORR_BITS * sizeof(char)); MAX_CORR_BITS * sizeof(char));
} }
} }
@@ -265,22 +273,14 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->count_ptrs[tbl] == NULL) if (entropy->count_ptrs[tbl] == NULL)
entropy->count_ptrs[tbl] = (long *) entropy->count_ptrs[tbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long)); 257 * sizeof(long));
MEMZERO(entropy->count_ptrs[tbl], 257 * sizeof(long)); memset(entropy->count_ptrs[tbl], 0, 257 * sizeof(long));
if (cinfo->master->trellis_passes) {
/* When generating tables for trellis passes, make sure that all */
/* codewords have an assigned length */
int i, j;
for (i = 0; i < 16; i++)
for (j = 0; j < 12; j++)
entropy->count_ptrs[tbl][16 * i + j] = 1;
}
} else { } else {
/* Compute derived values for Huffman table */ /* Compute derived values for Huffman table */
/* We may do this more than once for a table, but it's not expensive */ /* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
& entropy->derived_tbls[tbl]); &entropy->derived_tbls[tbl]);
} }
} }
@@ -306,18 +306,18 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* Emit a byte */ /* Emit a byte */
#define emit_byte(entropy, val) { \ #define emit_byte(entropy, val) { \
*(entropy)->next_output_byte++ = (JOCTET)(val); \ *(entropy)->next_output_byte++ = (JOCTET)(val); \
if (--(entropy)->free_in_buffer == 0) \ if (--(entropy)->free_in_buffer == 0) \
dump_buffer(entropy); \ dump_buffer(entropy); \
} }
LOCAL(void) LOCAL(void)
dump_buffer (phuff_entropy_ptr entropy) dump_buffer(phuff_entropy_ptr entropy)
/* Empty the output buffer; we do not support suspension in this module. */ /* Empty the output buffer; we do not support suspension in this module. */
{ {
struct jpeg_destination_mgr *dest = entropy->cinfo->dest; struct jpeg_destination_mgr *dest = entropy->cinfo->dest;
if (! (*dest->empty_output_buffer) (entropy->cinfo)) if (!(*dest->empty_output_buffer) (entropy->cinfo))
ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
/* After a successful buffer dump, must reset buffer pointers */ /* After a successful buffer dump, must reset buffer pointers */
entropy->next_output_byte = dest->next_output_byte; entropy->next_output_byte = dest->next_output_byte;
@@ -334,11 +334,11 @@ dump_buffer (phuff_entropy_ptr entropy)
*/ */
LOCAL(void) LOCAL(void)
emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) emit_bits(phuff_entropy_ptr entropy, unsigned int code, int size)
/* Emit some bits, unless we are in gather mode */ /* Emit some bits, unless we are in gather mode */
{ {
/* This routine is heavily used, so it's worth coding tightly. */ /* This routine is heavily used, so it's worth coding tightly. */
register size_t put_buffer = (size_t) code; register size_t put_buffer = (size_t)code;
register int put_bits = entropy->put_bits; register int put_bits = entropy->put_bits;
/* if size is 0, caller used an invalid Huffman table entry */ /* if size is 0, caller used an invalid Huffman table entry */
@@ -348,7 +348,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
if (entropy->gather_statistics) if (entropy->gather_statistics)
return; /* do nothing if we're only getting stats */ return; /* do nothing if we're only getting stats */
put_buffer &= (((size_t) 1)<<size) - 1; /* mask off any extra bits in code */ put_buffer &= (((size_t)1) << size) - 1; /* mask off any extra bits in code */
put_bits += size; /* new number of bits in buffer */ put_bits += size; /* new number of bits in buffer */
@@ -357,7 +357,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */ put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
while (put_bits >= 8) { while (put_bits >= 8) {
int c = (int) ((put_buffer >> 16) & 0xFF); int c = (int)((put_buffer >> 16) & 0xFF);
emit_byte(entropy, c); emit_byte(entropy, c);
if (c == 0xFF) { /* need to stuff a zero byte? */ if (c == 0xFF) { /* need to stuff a zero byte? */
@@ -373,7 +373,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
LOCAL(void) LOCAL(void)
flush_bits (phuff_entropy_ptr entropy) flush_bits(phuff_entropy_ptr entropy)
{ {
emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
entropy->put_buffer = 0; /* and reset bit-buffer to empty */ entropy->put_buffer = 0; /* and reset bit-buffer to empty */
@@ -386,7 +386,7 @@ flush_bits (phuff_entropy_ptr entropy)
*/ */
LOCAL(void) LOCAL(void)
emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) emit_symbol(phuff_entropy_ptr entropy, int tbl_no, int symbol)
{ {
if (entropy->gather_statistics) if (entropy->gather_statistics)
entropy->count_ptrs[tbl_no][symbol]++; entropy->count_ptrs[tbl_no][symbol]++;
@@ -402,14 +402,14 @@ emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
*/ */
LOCAL(void) LOCAL(void)
emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart, emit_buffered_bits(phuff_entropy_ptr entropy, char *bufstart,
unsigned int nbits) unsigned int nbits)
{ {
if (entropy->gather_statistics) if (entropy->gather_statistics)
return; /* no real work */ return; /* no real work */
while (nbits > 0) { while (nbits > 0) {
emit_bits(entropy, (unsigned int) (*bufstart), 1); emit_bits(entropy, (unsigned int)(*bufstart), 1);
bufstart++; bufstart++;
nbits--; nbits--;
} }
@@ -421,7 +421,7 @@ emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
*/ */
LOCAL(void) LOCAL(void)
emit_eobrun (phuff_entropy_ptr entropy) emit_eobrun(phuff_entropy_ptr entropy)
{ {
register int temp, nbits; register int temp, nbits;
@@ -450,13 +450,13 @@ emit_eobrun (phuff_entropy_ptr entropy)
*/ */
LOCAL(void) LOCAL(void)
emit_restart (phuff_entropy_ptr entropy, int restart_num) emit_restart(phuff_entropy_ptr entropy, int restart_num)
{ {
int ci; int ci;
emit_eobrun(entropy); emit_eobrun(entropy);
if (! entropy->gather_statistics) { if (!entropy->gather_statistics) {
flush_bits(entropy); flush_bits(entropy);
emit_byte(entropy, 0xFF); emit_byte(entropy, 0xFF);
emit_byte(entropy, JPEG_RST0 + restart_num); emit_byte(entropy, JPEG_RST0 + restart_num);
@@ -480,9 +480,9 @@ emit_restart (phuff_entropy_ptr entropy, int restart_num)
*/ */
METHODDEF(boolean) METHODDEF(boolean)
encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, temp2, temp3; register int temp, temp2, temp3;
register int nbits; register int nbits;
int blkn, ci; int blkn, ci;
@@ -508,7 +508,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Compute the DC value after the required point transform by Al. /* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift. * This is simply an arithmetic right shift.
*/ */
temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); temp2 = IRIGHT_SHIFT((int)((*block)[0]), Al);
/* DC differences are figured on the point-transformed values. */ /* DC differences are figured on the point-transformed values. */
temp = temp2 - entropy->last_dc_val[ci]; temp = temp2 - entropy->last_dc_val[ci];
@@ -524,7 +524,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
temp ^= temp3; temp ^= temp3;
temp -= temp3; /* temp is abs value of input */ temp -= temp3; /* temp is abs value of input */
/* For a negative input, want temp2 = bitwise complement of abs(input) */ /* For a negative input, want temp2 = bitwise complement of abs(input) */
temp2 = temp ^ temp3; temp2 = temp ^ temp3;
/* Find the number of bits needed for the magnitude of the coefficient */ /* Find the number of bits needed for the magnitude of the coefficient */
@@ -532,7 +532,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Check for out-of-range coefficient values. /* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much. * Since we're encoding a difference, the range limit is twice as much.
*/ */
if (nbits > MAX_COEF_BITS+1) if (nbits > MAX_COEF_BITS + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF); ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count/emit the Huffman-coded symbol for the number of bits */ /* Count/emit the Huffman-coded symbol for the number of bits */
@@ -541,7 +541,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Emit that number of bits of the value, if positive, */ /* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */ /* or the complement of its magnitude, if negative. */
if (nbits) /* emit_bits rejects calls with size 0 */ if (nbits) /* emit_bits rejects calls with size 0 */
emit_bits(entropy, (unsigned int) temp2, nbits); emit_bits(entropy, (unsigned int)temp2, nbits);
} }
cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -584,8 +584,8 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
continue; \ continue; \
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */ \ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ \
temp2 ^= temp; \ temp2 ^= temp; \
values[k] = temp; \ values[k] = (JCOEF)temp; \
values[k + DCTSIZE2] = temp2; \ values[k + DCTSIZE2] = (JCOEF)temp2; \
zerobits |= ((size_t)1U) << k; \ zerobits |= ((size_t)1U) << k; \
} \ } \
} }
@@ -659,9 +659,9 @@ label \
} }
METHODDEF(boolean) METHODDEF(boolean)
encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, temp2; register int temp, temp2;
register int nbits, r; register int nbits, r;
int Sl = cinfo->Se - cinfo->Ss + 1; int Sl = cinfo->Se - cinfo->Ss + 1;
@@ -681,7 +681,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
emit_restart(entropy, entropy->next_restart_num); emit_restart(entropy, entropy->next_restart_num);
#ifdef WITH_SIMD #ifdef WITH_SIMD
cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16); cvalue = values = (JCOEF *)PAD((JUINTPTR)values_unaligned, 16);
#else #else
/* Not using SIMD, so alignment is not needed */ /* Not using SIMD, so alignment is not needed */
cvalue = values = values_unaligned; cvalue = values = values_unaligned;
@@ -696,9 +696,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
zerobits |= bits[1]; zerobits |= bits[1];
#endif #endif
/* Emit any pending EOBRUN */ /* Emit any pending EOBRUN */
if (zerobits && (entropy->EOBRUN > 0)) if (zerobits && (entropy->EOBRUN > 0))
emit_eobrun(entropy); emit_eobrun(entropy);
#if SIZEOF_SIZE_T == 4 #if SIZEOF_SIZE_T == 4
zerobits = bits[0]; zerobits = bits[0];
@@ -751,9 +751,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/ */
METHODDEF(boolean) METHODDEF(boolean)
encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp; register int temp;
int blkn; int blkn;
int Al = cinfo->Al; int Al = cinfo->Al;
@@ -773,7 +773,7 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* We simply emit the Al'th bit of the DC coefficient value. */ /* We simply emit the Al'th bit of the DC coefficient value. */
temp = (*block)[0]; temp = (*block)[0];
emit_bits(entropy, (unsigned int) (temp >> Al), 1); emit_bits(entropy, (unsigned int)(temp >> Al), 1);
} }
cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -869,7 +869,7 @@ encode_mcu_AC_refine_prepare(const JCOEF *block,
#define ENCODE_COEFS_AC_REFINE(label) { \ #define ENCODE_COEFS_AC_REFINE(label) { \
while (zerobits) { \ while (zerobits) { \
int idx = count_zeroes(&zerobits); \ idx = count_zeroes(&zerobits); \
r += idx; \ r += idx; \
cabsvalue += idx; \ cabsvalue += idx; \
signbits >>= idx; \ signbits >>= idx; \
@@ -923,10 +923,10 @@ label \
} }
METHODDEF(boolean) METHODDEF(boolean)
encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, r; register int temp, r, idx;
char *BR_buffer; char *BR_buffer;
unsigned int BR; unsigned int BR;
int Sl = cinfo->Se - cinfo->Ss + 1; int Sl = cinfo->Se - cinfo->Ss + 1;
@@ -946,7 +946,7 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
emit_restart(entropy, entropy->next_restart_num); emit_restart(entropy, entropy->next_restart_num);
#ifdef WITH_SIMD #ifdef WITH_SIMD
cabsvalue = absvalues = (JCOEF *)PAD((size_t)absvalues_unaligned, 16); cabsvalue = absvalues = (JCOEF *)PAD((JUINTPTR)absvalues_unaligned, 16);
#else #else
/* Not using SIMD, so alignment is not needed */ /* Not using SIMD, so alignment is not needed */
cabsvalue = absvalues = absvalues_unaligned; cabsvalue = absvalues = absvalues_unaligned;
@@ -977,13 +977,13 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
if (zerobits) { if (zerobits) {
int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue); int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue);
int idx = count_zeroes(&zerobits); idx = count_zeroes(&zerobits);
signbits >>= idx; signbits >>= idx;
idx += diff; idx += diff;
r += idx; r += idx;
cabsvalue += idx; cabsvalue += idx;
goto first_iter_ac_refine; goto first_iter_ac_refine;
} }
ENCODE_COEFS_AC_REFINE(first_iter_ac_refine:); ENCODE_COEFS_AC_REFINE(first_iter_ac_refine:);
#endif #endif
@@ -1024,9 +1024,9 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/ */
METHODDEF(void) METHODDEF(void)
finish_pass_phuff (j_compress_ptr cinfo) finish_pass_phuff(j_compress_ptr cinfo)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer; entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -1045,9 +1045,9 @@ finish_pass_phuff (j_compress_ptr cinfo)
*/ */
METHODDEF(void) METHODDEF(void)
finish_pass_gather_phuff (j_compress_ptr cinfo) finish_pass_gather_phuff(j_compress_ptr cinfo)
{ {
phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band; boolean is_DC_band;
int ci, tbl; int ci, tbl;
jpeg_component_info *compptr; jpeg_component_info *compptr;
@@ -1062,7 +1062,7 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
/* It's important not to apply jpeg_gen_optimal_table more than once /* It's important not to apply jpeg_gen_optimal_table more than once
* per table, because it clobbers the input frequency counts! * per table, because it clobbers the input frequency counts!
*/ */
MEMZERO(did, sizeof(did)); memset(did, 0, sizeof(did));
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];
@@ -1073,13 +1073,13 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
} else { } else {
tbl = compptr->ac_tbl_no; tbl = compptr->ac_tbl_no;
} }
if (! did[tbl]) { if (!did[tbl]) {
if (is_DC_band) if (is_DC_band)
htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; htblptr = &cinfo->dc_huff_tbl_ptrs[tbl];
else else
htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; htblptr = &cinfo->ac_huff_tbl_ptrs[tbl];
if (*htblptr == NULL) if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
did[tbl] = TRUE; did[tbl] = TRUE;
} }
@@ -1092,15 +1092,15 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
*/ */
GLOBAL(void) GLOBAL(void)
jinit_phuff_encoder (j_compress_ptr cinfo) jinit_phuff_encoder(j_compress_ptr cinfo)
{ {
phuff_entropy_ptr entropy; phuff_entropy_ptr entropy;
int i; int i;
entropy = (phuff_entropy_ptr) entropy = (phuff_entropy_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(phuff_entropy_encoder)); sizeof(phuff_entropy_encoder));
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_phuff; entropy->pub.start_pass = start_pass_phuff;
/* Mark tables unallocated */ /* Mark tables unallocated */

View File

@@ -3,8 +3,8 @@
* *
* This file is part of the Independent JPEG Group's software: * This file is part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane. * Copyright (C) 1994-1996, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code relevant * libjpeg-turbo Modifications:
* to libjpeg-turbo. * 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
* file. * file.
* *
@@ -289,8 +289,8 @@ create_context_buffer(j_compress_ptr cinfo)
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 */
MEMCOPY(fake_buffer + rgroup_height, true_buffer, memcpy(fake_buffer + rgroup_height, true_buffer,
3 * rgroup_height * sizeof(JSAMPROW)); 3 * rgroup_height * sizeof(JSAMPROW));
/* Fill in the above and below wraparound pointers */ /* Fill in the above and below wraparound pointers */
for (i = 0; i < rgroup_height; i++) { for (i = 0; i < rgroup_height; i++) {
fake_buffer[i] = true_buffer[2 * rgroup_height + i]; fake_buffer[i] = true_buffer[2 * rgroup_height + i];

Some files were not shown because too many files have changed in this diff Show More